Object Orinentated Programing In Bge Tutorial

Abstract

Its possible that virtually every major video game in the history of ever was object orientated. This tutorial will teach you how to implement object orientated programing specifically in the Bge.

Prerequisites

Familiarity with oop in python.
Child By Name
Json Coder

Subclassing

Subclassing game object is not difficult but it is a little weird.

import bge
own = bge.logic.getCurrentController().owner
 
# https://upbge-docs.readthedocs.io/en/latest/api/bge.types.html
# Pass the base class for the object that is being subclassed
class SomeSubclassOfGameObject(bge.types.KX_GameObject):
 
  # Self is the new object while DNU is the old object.
  # DNU stands for Do Not Use.  You will probably never use it, but it has to be there.
  def __init__(self, DNU):
    pass
 
SomeSubclassOfGameObject(own)

If you get the following error then you probably forgot to pass either self or DNU.

TypeError: __init__() takes 1 positional argument but 2 were given

When ever possible I'd recommend subclassing a hitbox or empty and having all relevant objects be children of the empty or hitbox.

Running a Method

In order to sublcass from a controller, place a sub function in the same script as the subclass. To run methods you need some method controllers. In our case we need a run and message function.

# We define the these global variables here so that we don't have to modify the code that follows them. 
 
# This should the base class defined above.
BASE_CLASS = SomeSubclassOfGameObject
 
# http://upbge.wikidot.com/json-coder-tutorial
JSON_CODER = bge.logic.globalDict['jsonCoder']
 
# This is the name of the message sensor.
SEN_MESSAGE = 'Message'
 
# The rest of this code is boilerplate.
 
def sub(cont):
  self = cont.owner
 
  # Check to see own has already been subclassed with base class.
  # Sometimes you will want to subclass an object imedetly insted of with the controler.
  # This prevents the controler from subclassing it a second time in such cases.
  if isinstance(self, BASE_CLASS):  return self
 
  # Subclass with the new class.
  else:  return baseClass(self)
 
def run(cont):  cont.owner.run()
 
def message(cont):
  sen = cont.sensors[SEN_MESSAGE]
  for i in range(sen.frameMessageCount):
    subject = sen.subjects[i]
    body = sen.bodies[i]
 
    # http://upbge.wikidot.com/json-coder-tutorial
    body = JSON_CODER.dumps(body)
 
    # Run the message method.
    cont.owner.message(subject, body)

Final Code

This is an abbreviated example of what an actual object might look like.

Logic Bricks

Make an Empty and give it the following logic bricks and properties. The code should be placed in a script called player.py located in the same directory as the .blend.

oop_in_bge_img_0.png

Code

import bge
 
class Player(bge.types.KX_GameObject):
  # We can import a method into the global of a class.  Python is awesome.
  # http://upbge.wikidot.com/child-by-name-tutorial
  from somewhere import child
 
  def __init__(self, DNU):
    self.arma = self.child('Arma')
    self.maxHp = self['maxHp']
    self.hp = self.maxHp
    bge.logic.sendMessage( 'currentPlayer', JSON_CODER.loads(self) )
 
  def run(self):
    from random import random
    if random() < 0.5:
    print('I stubith my toe!')      
    self.hp -= 1
 
  def message(self, subject, body):
    if subject == 'currentPlayerPosition':
      # We already converted the body from a string to objects.
      self.worldPosition = body
 
  @property
  def hp(self):
    return self._hp
  @hp.setter
  def hp(self, value):
    if value > self.maxHp:  value = self.maxHp
    elif value < 0:  value = 0
    if value == 0:  self.die()
 
  def die(self):
    print('I dieith!')
    self.endObject()
 
# This should the base class defined above.
BASE_CLASS = Player
# http://upbge.wikidot.com/json-coder-tutorial
JSON_CODER = bge.logic.globalDict['jsonCoder']
# This is the name of the message sensor.
SEN_MESSAGE = 'Message'
 
# The rest of this code is boilerplate.
 
def sub(cont):
  self = cont.owner
  if isinstance(self, BASE_CLASS):  return self
  else:  return BASE_CLASS(self)
 
def run(cont):  cont.owner.run()
 
def message(cont):
  sen = cont.sensors[SEN_MESSAGE]
  for i in range(sen.frameMessageCount):
    subject = sen.subjects[i]
    body = sen.bodies[i]
    body = JSON_CODER.dumps(body)
    cont.owner.message(subject, body)

Questions

Create an account and edit this page to ask or answer any questions.

Further Reading

Object Oriented Programing
Oop Tutorial
@property
Boilerplate Code

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License