Search Results

Sunday, May 1, 2011

Using Python in the Blender Game Engine - Part 7

Hey. So here's part 7 of using Python in the BGE. In this one, we've created an enemy!
So, I went ahead and made an enemy from the base 'template' of our character - our enemy's a bit fatter, and has fangs hanging from his mouth. We give the enemy an 'enemy' property that will tell us when our Player runs into an enemy, so that we can deal with that. We also added a property, bullet, to our Bullet, so that we can tell when a bullet collides with an enemy. Finally, we've added a bullet collision sensor to our Enemy object, and an Enemy collision sensor to our player.


Okay, so now that we've done the necessary Blender property changes, we change our source code to do some extra things. We've added a new Python source file - the Enemy.py file. Let's take a look at our new module.

------------------------------------------------------

from bge import logic
from bge import events

import math       

def Enemy():

    cont = logic.getCurrentController()
    sce = logic.getCurrentScene()
    obj = cont.owner
   
    bulletcol = cont.sensors['BulletCol']
   
    def Init():
        if not 'init' in obj:
            obj['init'] = 1
            obj['hp'] = 3                    # Set your HP at the beginning
   
    def Update():
   
        if bulletcol.positive:
            obj['hp'] -= 1                    # Decrement your HP one
            bullet = bulletcol.hitObject    # Get the bullet you collided with
            bullet.endObject()                # And destroy it
       
        if obj['hp'] <= 0:                    # If you have 0 HP
            obj.endObject()                    # Then destroy yourself
           
    Init()
    Update()

    
------------------------------------------------------

Okay, so we see our Enemy's source code here. There's actually not too much here - we initialize the enemy object's health variable, and in the Update function, check the status of the Bullet Collision sensor. If the sensor returns true, then we decrement the enemy's health variable. When the health variable is equal to (or less than) 0, then the Enemy's been killed.

Next, we'll take a look at just the changed portion of our Player code. This portion of our Player code tests for the Player to collide with the Enemy, and when he does, what should happen...

------------------------------------------------------

enemycol = cont.sensors['EnemyCol']
if enemycol.positive:
            print ("You've died. Great.")
            logic.restartGame()


------------------------------------------------------

That's... Pretty much it. If the player collides with the enemy, then we print a simple debug line saying that we've been killed and restart the game. Nooooo! Heheh - so that's it for now, though in the future we can easily expand it to, say, display a screen that says, "You've died. Press Enter to restart", or something more complex than that, obviously.

I noticed that the code restarts the entire game, which works alright, but in the future, it should be changed to restart just the current scene, or better yet, restart from a checkpoint.

Note that in this whole tutorial series, we've been executing logic every game frame. While this may be necessary for certain games, some elements don't need to execute every frame, like the bullet - a collision sensor for the enemy checking for the bullet would be fine. Of course, we'll need to execute the bullet's movement code every frame, but for an example, the idea is the same.

So, that's about it. Download the Part 7 source code here:

Mirror 1: MediaFire
Mirror 2: Box.net

9 comments:

  1. Download the source code where?

    ReplyDelete
  2. @Anonymous - Oops - my mistake. Thanks, I corrected the link.

    ReplyDelete
  3. Thanks a bunch! And keep up the good work. It's really easy to find Blender guides and tutorials for art and animation, but there aren't enough scripting guides out there. Especially with the new Python API.

    ReplyDelete
  4. Hey I've been thinking about your approach to Python scripting and I wonder if you can't make a bit of a speed boost by not having to redefine your subfunctions each frame. Take the Update function, for example. Why not define it inside of the Init function, and save the function itself as one of the object's properties. So in the case of your enemy here, you would define the Init function like this:

    def Enemy():
    def Init():
    if not 'init' in obj:
    def Update(): ...
    obj['init'] = 1
    obj['hp'] = 3
    obj['update'] = Update
    Init()
    obj['update']()

    This way you don't have to re-define your controller functions in each frame, which should give at least a slight performance boost. What do you think?

    ReplyDelete
  5. Grr... lost all the indents in my code when I posted. This should be more legible (just pretend the underscores are spaces):

    def Enemy():
    __def Init():
    ____if not 'init' in obj:
    ______def Update(): ...
    ______obj['init'] = 1
    ______obj['hp'] = 3
    ______obj['update'] = Update
    __Init()
    __obj['update']()

    ReplyDelete
  6. That's actually a really good point. I don't pay a lot of attention to performance, except on performance-intensive processes (like the X-Emitter), but this is a really good idea. That would be a bit more of a performance boost. If I remember, I'll build it into the next part. Thanks for the advice.

    ReplyDelete
  7. Yeah, it's not a big deal now, but it will definitely speed things up when you make bigger games with lots of characters, especially if you have all of your bad guys and NPCs redefining their A.I. scripts every frame.

    ReplyDelete
  8. what is the difference between the regular blender game mode view and your created view game big/small?

    ReplyDelete
  9. @Oirad - Nothing besides the aspect ratio - my custom view is just proportioned to display everything that you would see in the camera and in the BlenderPlayer.

    ReplyDelete