11

Background

I do game development as a hobby, and am looking for a better way to design them. Currently, I am using a standard OOP approach (I have been doing enterprise development for 8 years so it comes nartually). Take for example a "baddie"

public class Baddie:AnimatedSprite //(or StaticSprite if needed, which inherit Sprite)
{
    //sprite base will have things like what texture to use, 
    //what the current position is, the base Update/Draw/GetInput methods, etc..
    //an AnimatedSprite contains helpers to animated the player while 
    //a StaticSprite is just one that will draw whatever texture is there
}

The problem

Lets say I am making a 2d platformer, and need the baddie to be able to Jump. Usually what I do is add the appropriate code in the Update/GetInput methods. Then if I need to make the player crawl, duck, climb, etc... the code will go there.

If I'm not careful, those methods get cluttered, so I end up creating methods pairs like this

CheckForJumpAction(Input input) and DoJump()

CheckforDuckAction(Input input) and DoDuck()

so GetInput looks like

public void DoInput(Input input)
{
    CheckForJumpAction(input);
    CheckForDuckAction(input);
}

and Update looks like

public void Update()
{
    DoJump();
    DoDuck();
}

If I go and create another game where the player needs to jump and duck, I usually go into a game that has the functionality and copy it over. Messy, I know. Thats I why I'm looking for something better.

Solution?

I really like how Blend has behaviors I can attach to an element. I have been thinking about using the same concept in my games. So lets look at the same examples.

I would create a base Behavior object

public class Behavior
{
    public void Update()
    Public void GetInput()
}

And I can create behaviors using that. JumpBehavior:Behavior and DuckBehavior:Behavior

I can then add a collection of behaviors to the Sprite base and add what I need to each entity.

public class Baddie:AnimatedSprite
{
    public Baddie()
    {
        this.behaviors = new Behavior[2];
        this.behaviors[0] = new JumpBehavior();
        //etc...
    }

    public void Update()
    {
        //behaviors.update
    }

    public GetInput()
    {
        //behaviors.getinput
    }
}

So now If I wanted to use Jump and Duck in many games, I can just bring the behaviors over. I could even make a library for the common ones.

Does it work?

What I can't figure out is how to share state between them. Looking at Jump and Duck, both affect not only the current portion of the texture being drawn, but also the state of the player. (Jump is going to apply a decrementing amount of upward force over time, while duck is just going to stop movement, change the texture and the collision size of the baddie.

How can I tie this together so it works? Should I create dependency properties between the behaviors? Should I have each behavior know about the parent and directly modify it? One thing I thought was being able to pass a delegate into each behavior to get executed when it is triggered.

I'm sure there are more issues I am looking over, but the entire purpose is for me to be able to easily reuse these behaviors between games, and entities in the same game.

So I turn it over to you. Care to explain how/if this can be done? Do you have a better idea? I'm all ears.

5
  • This might be better asked at gamedev.stackexchange.com?
    – rcapote
    Jul 4, 2011 at 4:24
  • I do like where you're going but I'm not sure how to address the issues you bring up. Very interesting and has implications beyond game development. Jul 4, 2011 at 4:30
  • @rcapote isnt this site for whiteboarding/discussions?
    – user81
    Jul 4, 2011 at 4:50
  • 2
    @Joe - no, no. Don't even mention "discussion" here or you'll be modded out of existence. This site is only for Question->Answer->Done type of interaction. Jul 4, 2011 at 5:08
  • Well, component-based entity systems is something that has started trending in the game dev community lately so I figured you might get better attention there, but you'll probably get good answers here anyway. Here is an interesting discussion on gamedev.net about this problem that you might find interesting: gamedev.net/topic/…
    – rcapote
    Jul 4, 2011 at 5:09

4 Answers 4

1

Take a look at this presentation. Sounds pretty close to the kind of pattern you're looking for. This pattern supports behaviours and attachable properties. I don't think the presentation mentions it, but you can also create attachable events. This idea is similar the dependency properties used in WPF.

9
+100

To me this sounds like an almost textbook case for using the Strategy Pattern. In this pattern, your generic behaviors can be defined in interfaces which will allow you to swap out different implementations of behaviors at runtime (think about how a power-up may affect the jumping or running ability of your character).

For (a contrived) example:

// The basic definition of the jump behavior
public interface IJumpBehavior {
    void Jump();
}

Now you can implement various types of jumps that your character can use, without necessarily knowing the details about each specific jump:

// This is the jump the character may have when first starting
public class NormalJump : IJumpBehavior {

     public void Jump() {
         Console.WriteLine("I am jumping, and being pretty boring about it!");
     }

}

// This is the jump of a character who has consumed a power-up
public class SuperJump : IJumpBehavior {
    public void Jump() { 
         Console.WriteLine("I am all hopped up on star power, now my jumps can do damage!");
     }
}

Any characters you want to have the ability to jump can just now contain a reference to an IJumpable and can start consuming your various implementations

public class HeroCharacter {

    // By default this hero can perform normal jump.
    private IJumpBehavior _jumpBehavior = new NormalJump();

    public void Jump() {
        _jumpBehvaior.Jump();
    }

    // If you want to change the hero's IJumpable at runtime
    public void SetJump(IJumpBehavior jumpBehavior) {
      _jumpBehavior = jumpBehavior;
    }

}

Then your code can look something like:

HeroCharacter myHero = new HeroCharacer();

// Outputs: "I am jumping, and being pretty boring about it!"
myHero.Jump()

// After consuming a power-up
myHero.SetJump(new SuperJump());

// Outputs: "I am all hopped up on star power, now my jumps can do damage!"
myHero.Jump();

Now you can easily re-use these behaviors, or even extend them later as you want to add more types of jumps, or create more games built on a single Side-scrolling platform.

1
  • while not exactly what I'm looking for, this is very close and like it. I'm going to play around with it to make sure. thanks!
    – user81
    Jul 12, 2011 at 20:48
1

Take a look at DCI architecture an interesting take on OO programming that may help.

Implementing a DCI style architecture in C# requires using simple domain classes, and using Context objects (behaviours) with Extension Methods and Interfaces to allow the domain classes to collaborate under different roles. The Interfaces are used to mark out the roles required for a scenario. Domain classes implement the interfaces (roles) that apply to their intended behaviour. The collaboration between the roles takes place in the context (behaviour) objects.

You could create a library of common behaviours and roles that can be shared amongst domain objects from separate projects.

See DCI in C# for code examples in C#.

0

What about passing in a context object into a behavior which provides methods to change the state of the sprites/objects affected by a behavior? Now if an object has several behaviors they are each called in a loop giving them the chance to change the context. If a certain modification of a property rules out / constrains the modification of other properties the context object can provide methods to set some kind of flags to indicate this fact, or it can simply deny unwanted modifications.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy