There's only a little bit of changes to the code this time around in the tutorial series. Let's see what the differences are.
from bge import logic
from bge import events
def Sign(value):
if value > 0:
return 1
elif value < 0:
return -1
else:
return 0
def AxisCheck(mx, my, size = 1.0):
cont = logic.getCurrentController()
obj = cont.owner
pos = obj.position # Get the Player's current position
topos = pos.copy() # Make a copy of the Player's current position
topos.x += (Sign(mx) * size) + mx # Offset the copy by the movement value for the X-axis
topos.y += (Sign(my) * size) + my # And offset the copy by the movement value for the Y-axis
return obj.rayCast(topos, pos, 0, 'wall', 1, 1) # We may have just collided with something on the line specified
def Player():
cont = logic.getCurrentController()
obj = cont.owner
motion = cont.actuators['Motion']
key = logic.keyboard.events
kbleft = key[events.LEFTARROWKEY]
kbright = key[events.RIGHTARROWKEY]
kbup = key[events.UPARROWKEY]
kbdown = key[events.DOWNARROWKEY]
def Init():
if not 'init' in obj:
obj['init'] = 1
def Update():
movespd = 0.2
mx = 0.0
my = 0.0
if kbleft > 0:
mx = -movespd
elif kbright > 0:
mx = movespd
if kbup > 0:
my = movespd
elif kbdown > 0:
my = -movespd
if AxisCheck(mx, 0, 1.0)[0] != None: # We just collided with something on the X-axis
mx = 0 # So stop movement on the X-axis
if AxisCheck(0, my, 1.0)[0] != None: # We just collided with something on the Y-axis
my = 0 # So stop movement on the Y-axis
motion.dLoc = [mx, my, 0.0]
cont.activate(motion)
Init()
Update()
Okay, so maybe it's not just a few changes... Anyway, as you can see, there is a major difference in code between the previous part in the series and this one, but the actual amount of tasks finished by the code is the same. What we have done in the source code here is define a new function called AxisCheck that checks for a collision on the given X and Y axes and a distance value (wrongly called size in the example, LOL). This check is initiated by calling the new AxisCheck function with the X, Y, and distance arguments, as can be seen above.
You can also see that the new AxisCheck function uses another new function, the Sign function. The Sign function returns the sign of the inputted number - if the number is greater than 0, it returns 1. If the number is less than 0, it returns -1, and if the number is 0, then 0 is returned. This simply converts the motion amount into a uniform value that we use in collision checking.
That's the only difference in code for this part - there's another difference actually in the source .blend file. Before this part in the tutorial series, the Player cube was a Sensor-type collision object. Sensor-type objects are basically ghost-type Static objects, except that they can test for collisions against Static-type objects. However, Sensors can't detect collision against other Static sensors, and Static-type objects can't detect collisions for Sensors (the collision event is only generated one way). So, how do we navigate this?
Well, it's actually quite simple. We set the Player cube to be Dynamic. Since we control its movement with Python, we won't need the Bullet physics engine to compute collisions on the cube itself, so we make it Ghost-type. Also, we'll control gravity (or lack thereof in this maze-type game), so we also turn the global gravity to 0. Why do all of this?
As you can see, the Dynamic Ghost is highly versatile. |
Here is the source code for Part 4 of the Maze Crawl Source Code, made in the Blender Game Engine. Have fun!
Note: I'm trying out a new download host (MediaFire), so if the download goes down, E-Mail me at solarlune@gmail.com and I'll sort things out.
Thanks for these tutorials! They are easy to follow and quite helpful. I'm currently mentoring a high school about Game Design. I don't really know what I'm doing, but I'm trying to stay one step ahead of him and these tutorials have been great for that.
ReplyDeleteOne question about the code above; I can't figure out why you need these lines of code in the Player function;
pos = obj.position # Get the Player's current position
topos = pos.copy() # Make a copy of the Player's current position
topos.y += Sign(my) + my # And offset the copy by the movement value for the Y-axis
I feel like those could be deleted now that you have the AxisCheck function. I went ahead and deleted them and collision detection seems to work fine without them, but maybe I'm breaking something further down the road. Any thoughts?
Oh, sorry. You're right - that part of code is unnecessary. I'll fix it. Thanks.
ReplyDeletewhen i download your's it works, but when i change the python controller from module to script, and then load in the same scripit, it and use that in the script box it dosn't work. why does it do that
ReplyDeletehow about using pasteall.org for the .blend files! :D
ReplyDelete@Oirod - Can't do that. There's more to the source code files than just the blend files.
ReplyDelete@Anonymous - It won't work straight out because it needs to run a function, not just run through the code. You'll have to delete the function definition if you want to execute the code straight out of the script file.
This comment has been removed by the author.
ReplyDeleteHello!
ReplyDeleteFirst thank you so much for this beginner's guide. I know some coding but havent been able to find something to start properly with Blender, and this tutorial is perfect.
I followed it until this part, and i can notice on blender 2.61 a regular and small freeze in its movement, almost every second, if you keep moving the cube.
First i tried to change framerate to see any change, and.... none.
I also changed logic steps, but it makes things worse, and i cant figure out why it behaves like that.
Would you have an idea?
@Sythu - It seems like it stutters like this to me, as well, sometimes. Try setting VSync to be enabled in your graphics card settings - it seems to help some. If that is not satisfactory, perhaps you should post a thread on the BlenderArtists forum - they can be quite expedient about getting questions answered.
ReplyDelete@SolarLune : Sync to Vblank was already enabled... and it felt a bit better disabling it...
ReplyDeleteI'll give try in blenderartist, thanks for the tip.
Hi,
ReplyDeletethis part still blows my mind. Are you just trying to get a minute directional value (e.g. +/- x or y) to help point the ray? Thanks.
pos = obj.position #get the Player's current position
topos = pos.copy() # Make a copy of the Player's current position
topos.x += (Sign(mx) * size) + mx #offset the copy by the movement value of the x-axis
topos.y += (Sign(my) * size) + my #same for the y axis
return obj.rayCast(topos, pos, 0, 'wall', 1, 1) #collided with something on the specified axis
Hi,
ReplyDeletethis part still blows my mind. Are you just trying to get a minute directional value (e.g. +/- x or y) to help point the ray? Thanks.
pos = obj.position #get the Player's current position
topos = pos.copy() # Make a copy of the Player's current position
topos.x += (Sign(mx) * size) + mx #offset the copy by the movement value of the x-axis
topos.y += (Sign(my) * size) + my #same for the y axis
return obj.rayCast(topos, pos, 0, 'wall', 1, 1) #collided with something on the specified axis