Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411517 Posts in 69380 Topics- by 58436 Members - Latest Member: GlitchyPSI

May 01, 2024, 11:32:58 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Game Architecture
Pages: [1] 2
Print
Author Topic: Game Architecture  (Read 5408 times)
NandoSoft
Level 1
*



View Profile
« on: July 12, 2010, 07:33:28 AM »

So Im making a game once again and Im facing some troubles designing the engine


So I have my main class where the game loop runs, the level class which renders the level and can also tell you if a section of it is collidable or not.

And finally I have the Character class which draws the character

so my problem is that I dont know how to hook up the level class to the character list

since the level class is instantiated in the main class the character class does not have access to the level class unless (I make the level class static, a bad idea, or I send an instance of the level class to the constructor of the character class)

so basically my problem is when in a object oriented design I dont know how to make 2 different classes make notice of each other.

Its is a pain to me because I tend to implement my programs in a waterfall-method like fashion

Hope Im making myself clear

thanks for reading Big Laff
Logged
Matt Thorson
Level 7
**

c'est la vie


View Profile WWW
« Reply #1 on: July 12, 2010, 09:37:44 AM »

I think the usual method is:

Main has a Level has a GameObject

Then Main.render() calls Level.render() calls GameObject.render()
and Main.update() calls Level.update() calls GameObject.update()
Logged

NandoSoft
Level 1
*



View Profile
« Reply #2 on: July 12, 2010, 09:40:50 AM »

ah okay sounds simple enough Smiley

so I either pass my objects list to the level class at load time or just at the draw/update calls
Logged
Matt Thorson
Level 7
**

c'est la vie


View Profile WWW
« Reply #3 on: July 12, 2010, 09:54:59 AM »

In Flash things have to be added to the stage, then the stage keeps references to all the display objects until they are removed. That's usually how I handle it in my engines too - Level.add(GameObject) and Level.remove(GameObject).

If GameObjects need a reference to the Level, your GameObject constructor could take a Level argument, or your GameObject.update()/.render() could take a Level argument.
Logged

BadgerManufactureInc
Guest
« Reply #4 on: July 12, 2010, 03:30:51 PM »

Yes as Matt says you should add objects to your main class in your required order of depth.

Generally inter-class communicaiton is not necessary if you make your Character classes variables public and modify or set those properties from you main class.

If you however require to access Level variables from within a Character object for example then you do need to pass it to Character when you instantiate the character.

Say your character classes constructor looks like this at the moment:

Code:
public var x:int;
public var y:int;

public function Character(XPOS:int,YPOS:int):void
{
 ..
 x=XPOS;
 y=YPOS;
 ..
}

and you create a character in your main class like this:

Code:
var myChar:Character=new Character(200,200);

Then you need to expand on the constructor like this, also creating a new tiles array class var in Character:

Code:
public var x:int;
public var y:int;
public var tiles:Array=[];

public function Character(XPOS:int,YPOS:int,TILES:Array):void
{
 ..
 x=XPOS;
 y=YPOS;
 tiles=TILES;
 ..
}

And now instantiate this way:

Code:
var myChar:Character=new Character(200,200,tilemap);

You can now acces your tilemap in the character class.
If you need to see it the other way around (to access Player data in your Level class) then dont hesitate to ask.

My advice would be don't make inter class communicate unless you need to, ie don't do it for the sake of future proofing but instead only when you need to.  Others may tell you different, which I can accept.

Smiley
« Last Edit: July 12, 2010, 03:34:29 PM by BadgerManufactureInc » Logged
muku
Level 10
*****


View Profile
« Reply #5 on: July 12, 2010, 11:33:52 PM »

What I generally do is make the main game class a global or singleton. Via that, all game objects can access the level, the timer and whatever else they may have a need for.

Yeah, sue me. Tongue

But in all honesty, there will only ever be one game running at a time, so I don't want to go to the hassle of passing what is logically a global around to all game objects. Just not worth it.
Logged
oahda
Level 10
*****



View Profile
« Reply #6 on: July 13, 2010, 02:31:49 AM »

Another possibility is to have a static Level *const getCurrentLevel() or something like that in the class that handles the game, so that you can access it from the character class.
Logged

NandoSoft
Level 1
*



View Profile
« Reply #7 on: July 13, 2010, 07:54:45 AM »

thank you for so many replys u guys rock!
Logged
Matt Thorson
Level 7
**

c'est la vie


View Profile WWW
« Reply #8 on: July 13, 2010, 09:22:24 AM »

Yeah in practice I'll make Main a singleton and have a static reference to it, available to all other classes.

Then everything can access Main.currentLevel, etc.
Logged

Jonathan Whiting
Level 2
**



View Profile WWW
« Reply #9 on: July 15, 2010, 05:35:30 AM »

What I generally do is make the main game class a global or singleton. Via that, all game objects can access the level, the timer and whatever else they may have a need for.

This has always been the most practical method for me.  It's arguably a bit weak as an OOP practice, but it gets stuff done, which is far more important imho.
Logged

InfiniteStateMachine
Level 10
*****



View Profile
« Reply #10 on: July 15, 2010, 08:42:43 AM »

so far I've been doing a singleton type global reference too. I'm pretty new to coding so I was a little worried about doing it that way, glad to see that others are doing it too Smiley
Logged

Triplefox
Level 9
****



View Profile WWW
« Reply #11 on: July 15, 2010, 09:14:59 AM »

I've gravitated towards keeping the hierarchy like so:

App
Game
Level
<components>

It's mainly a matter of how much state I want to preserve. Leaving it in an object means that I can reset easily by instancing a new one on top of the old one and letting the GC do everything else. So the bulk of the gameplay data is running somewhere within Level, while App stores global user settings and basic resource management, and Game stores cross-level information.

The main loop, including all the titles and menus, ends up getting sliced between Game and Level(though I'll tend to factor a lot of the menu code into another file). Those two have the most interdependency of any of the classes, with the components running a close second. The only way I can see to reduce that is to bloat up the code with a lot of unnecessary indirection(e.g. an event system; events can be useful once you have a rich set of behaviors to attach piecemeal to different AIs, but I've struggled to find a purpose for them on a core architecture level).

The entity data layout is optimized to simplify batch updates of each component, hence the entity itself only has an id reference and destructors - you have to use each component's access methods to learn the state in more detail. AI is just another kind of component, aware of the others.

Components have a backreference to the level instance, but that and a backreference from the level to the game are basically the only cases where I do it two-way; it's an architectural optimization specific to Flash, since Flash makes local and instance lookups cheap and static ones expensive. (yes, even static methods.)

I also use object pools for each component and for entity instances. Flash doesn't have generational collection so this strategy pays off for optimization, plus it gives you an easy(albeit imperfect) check for memory-leaking code - cap the pool and throw an exception if it overflows.
Logged

B_ill
Level 0
***


View Profile WWW
« Reply #12 on: July 15, 2010, 09:33:59 AM »

Where do you guys tend to stick your menus in the hierarchy of things? I usually use a structure similar to the one championed here, and it's usually a part of "game" parallel to "level"
Logged

Game Programmer and Designer
Latest Release: Chemical Cubes for Android and Kindle Fire (iOS coming soon)
muku
Level 10
*****


View Profile
« Reply #13 on: July 15, 2010, 10:01:53 AM »

Where do you guys tend to stick your menus in the hierarchy of things? I usually use a structure similar to the one championed here, and it's usually a part of "game" parallel to "level"

I tend to have a stack of "screens", which have update and render methods. For instance, you'd have a TitleScreen, MainMenuScreen, OptionsScreen, and so on. Every screen can choose to push a child screen onto the stack or replace itself with a successor screen. You can also implement a system of "transparent" screens such that you can, for instance, render a PauseScreen on top of your main Game screen.
Logged
Jonathan Whiting
Level 2
**



View Profile WWW
« Reply #14 on: July 15, 2010, 10:35:03 AM »

I tend to have a stack of "screens", which have update and render methods. For instance, you'd have a TitleScreen, MainMenuScreen, OptionsScreen, and so on. Every screen can choose to push a child screen onto the stack or replace itself with a successor screen.

I do exactly this too, it's simple but powerful, and importantly makes adding new screens very simple.

If I have screens that share common functionality I'll dump that functionality into 'component' style classes, so my Main Menu screen might contain a List Menu component with it's own update and render methods.  I'll generally favour keeping such components very lightweight, and do any screen specific behaviour in the screen classes.
Logged

Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #15 on: July 15, 2010, 12:30:57 PM »

I've always modeled a state machine.  I have an abstract Logic type with a Process operation that conducts one frame of action, and returns the next state.  The main loop checks to see if the state has changed, and if it has it releases the old state.  It looks something like this:

Code:
package Logics is
    pragma Elaborate_Body;

    type Logic is abstract new Limited_Controlled with private;
    type Logic_Access is access all Logic'Class;

    --Snip

    -- New operations.
    -- Logic driving procedure.  Passes the next logic state in the
    -- out parameter.  If the parameter comes back null, a quit has
    -- been requested.
    not overriding
    procedure Process(This: in out Logic; Next: out Logic_Access) is abstract;

    -- Snip
end Logics;

The individual states look like this:

Code:
package Logics.Title_Screen is
    type State is new Logic with private;

    -- Logic overrides.
    overriding
    procedure Initialize(This: in out State);
    overriding
    procedure Finalize(This: in out State);
    overriding
    procedure Process(This: in out State; Next: out Logic_Access);

    -- Snip
end Logic.Title_Screen;

The main loop looks like this:

Code:
    function Main_Loop return Integer is
    begin
        -- Calculate the new delta.
        Tickables.Calculate_Delta;

        -- Draw the screen.
        Renderer.Draw;

        declare
            Next_State: Logic_Access;
        begin
            -- Process the logic, obtaining the next logic.
            Current_State.Process(Next_State);

            -- If the logic has changed...
            if Next_State /= Current_State then
                -- Release the old logic.
                Free(Current_State);
                -- Store the new one.
                Current_State := Next_State;

                -- A state of null is a request to die.
                if Current_State = null then
                    return 0;
                end if;
            end if;
        end;

        return 1;

    exception
        when Error: others =>
            Error_Out(Error);

            return 0;
    end Main_Loop;

This has always worked the best for me, it keeps things nicely isolated, since each state can be worked on completely independantly of the others.
Logged



What would John Carmack do?
increpare
Guest
« Reply #16 on: July 15, 2010, 02:51:41 PM »

I tend to just use global variables instead of singleton stuff.
Logged
oahda
Level 10
*****



View Profile
« Reply #17 on: July 16, 2010, 12:28:35 AM »

I tend to just use global variables instead of singleton stuff.

Nasty.
Logged

muku
Level 10
*****


View Profile
« Reply #18 on: July 16, 2010, 12:29:42 AM »

I tend to just use global variables instead of singleton stuff.

Nasty.

Oh, come on. You're kidding yourself if you think that a singleton is anything other than a global variable in disguise.
Logged
Jonathan Whiting
Level 2
**



View Profile WWW
« Reply #19 on: July 16, 2010, 12:54:05 AM »

I tend to just use global variables instead of singleton stuff.

When I'm using something that lets me do this comfortably I do, actionscript isn't particularly "global friendly" in my experience.  As muku said, singleton's are globals in disguise.. Were I a better artist I'd do some sort of transformers/code mash-up thing.
Logged

Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic