Object Oriented

Objectives

a In this part you learn how to write a little game for the game engine which is splitted in many scripts, which are executed every frame.

Instructions

Tasks:
  1. Download the .blend file from here
  2. Add functions

Preparations

  1. Open the the .blend file in Blender
  2. Change the Scene layout to »Game Logic«
../../_images/change_scene_layout.png

Running scripts for an object

If you want to run a script for a Blender-Object, you can use the logic bricks to do that. First you have to add an »Always« sensor. Click to the left ‘’‘, for executing the script every frame.

../../_images/add_sensor.png

Then add an »Python« controller and set the Script Property to your script.

../../_images/add_controller.png

Then connect them.

../../_images/connect_logic_bricks.png

The scripts

The script for our Player (The monkey named »Player«).

#! bpy
import bge
import timeit
import aud
import os


def main():
    """Contains all changes"""
    # get scene
    scene = bge.logic.getCurrentScene()
    # get contoller
    con = bge.logic.getCurrentController()
    # get player
    player = con.owner
    # get keyboard
    keyboard = bge.logic.keyboard
    # get the text object
    text = scene.objects["Text"]
    # check if start has already been run
    if "lives" not in player:
        start(player)
    # check for collisions
    for object in scene.objects:
        # does object collide
        # the distance is from origin to origin, so we subtract a bit
        if player.getDistanceTo(object) - 2 <= 0:
            # Is object an enemy ...
            if object.name.startswith("Enemy"):
                if player["can_collide"]:
                    player["lives"] -= 1
                    # play enemy hit sound
                    aud.device().play(player["enemy_sound"])
                    # Set that player can't collide
                    player["can_collide"] = False
                    # register time of collision
                    player["last_col"] = timeit.default_timer()
            # ... or is object a coin?
            elif object.name.startswith("Coin"):
                player["coins"] += 1
                # play collecting sound with the aud module
                aud.device().play(player["coin_sound"])
                # remove the coin from the scene
                object.endObject()

    # player hasn't got lives?
    if player["lives"] <= 0:
        print("lost")
        # remove player from scene
        player.endObject()
        # stop game
        bge.logic.endGame()
    # player got all coins?
    if player["coins"] >= 10:
        print("Win")
        bge.logic.endGame()
    # player can collide again?
    if not player["can_collide"]:
        if (timeit.default_timer() - player["last_col"]) >= 1:
            player["can_collide"] = True

    # move player
    # keyboard events
    k_events = bge.logic.KX_INPUT_ACTIVE
    # up arrow pressed?
    if keyboard.events[bge.events.UPARROWKEY] == k_events:
        # move player forwards on its local y axis
        player.applyMovement((0, 0, .2), True)
    # down arrow pressed
    if keyboard.events[bge.events.DOWNARROWKEY] == k_events:
        # move player backwards on its local y axis
        player.applyMovement((0, 0, -.2), True)
    # left arrow pressed
    if keyboard.events[bge.events.LEFTARROWKEY] == k_events:
        # rotate to the left
        player.applyRotation((0, 0, .05))
    # right arrow pressed
    if keyboard.events[bge.events.RIGHTARROWKEY] == k_events:
        # rotate to the right
        player.applyRotation((0, 0, -.05))
    # Set the text
    text.text = "Lives: {}; Coins: {}".format(player["lives"], player["coins"])


def start(player):
    """Setup the player"""
    player["lives"] = 3
    player["coins"] = 0
    player["can_collide"] = True
    # sound with the aud module
    # coin collect sound
    path = bge.logic.expandPath("//snd/coin.wav")
    player["coin_sound"] = aud.Factory.file(path)
    # enemy hit sound
    path = bge.logic.expandPath("//snd/enemy.wav")
    player["enemy_sound"] = aud.Factory.file(path)


main()

And the Script for our Enemys:

#! bpy
import bge
from random import randint


def main():
    """Contains all changes"""
    # get scene
    scene = bge.logic.getCurrentScene()
    # get contoller
    con = bge.logic.getCurrentController()
    # get player
    enemy = con.owner

    # check, if enemy is outside the field
    if abs(enemy.position[0]) >= 20 or abs(enemy.position[1]) >= 20:
        # reverse direction
        enemy.applyRotation((0, 0, 180))
    # change direction in ca. 1% of the calls
    if randint(1, 100) == 1:
        # change direction
        enemy.applyRotation((0, 0, randint(1, 360)))
    # check for collisions
    for object in scene.objects:
        # does object collide
        # the distance is from origin to origin, so we subtract a bit
        if enemy.getDistanceTo(object) - 2 <= 0 and object != enemy:
            # Is object an enemy ...
            if object.name.startswith("Enemy"):
                # reverse direction
                enemy.applyRotation((0, 0, 180))
    # move
    enemy.applyMovement((0, 0, .15), True)


main()

The camera

Connecting the camera to the player: 1. Deselect all (»A« toggles selection) 2. Select the camera (with a right click) 3. Press shift while selecting the player, so you selected both and the player is active 4. Press »Ctrl« + »P« and click on »Object«

../../_images/set_parent.png
  1. Select the camera again and enable »Slow Parent« in the Relations Extras
  2. Set the Offset to »11.5«
../../_images/set_slow_parent.png

More about Blender and the Game Enigne under Blender Game Engine – API