GameCore: An exercise in design

As a kind of mental exercise I have started working out a design for a 2D game engine. I have choosen three primary goals for the design:

1> The system must be able to have the rendering code layer completely replaced without any code changes. For instance I would like to be able to have LWJGL, JOGL and Java2D versions of the rendering layer.

2> The code (related to the library) for a game should be very easy to read and understand.

3> A java programmer just starting to get into game programming should be able to get something on screen in under an hour.

The current class diagram, such as it is, can be viewed here.

I’m interested in hearing opinions/advice on the design. A little background should help (an example program provided below):

GameCore - This abstract class is the center of the world for the library. Each rendering layer will have to implement a version of this class. Some methods common to every rendering layer are provided. The factory methods for creating different kinds of game objects will be filled in by each implementation. This object hides the specifics for any given type of rendering, OGL, Java2D.

GameCoreProgram - This interface must be implemented by the game.

DisplayObject - All classes that place something on the screen must subclass this class.

RenderList - A list of DisplayObject objects. Can use Z sorting to order the items drawn to the screen.

RenderSet - A list of RenderList objects. RenderSets are the only objects allowed to be passed into the GameCore rendering method.

org.gamecore.event.* - The classes in this package are used to avoid the AWT/Rendering thread issues. The rendering layer GameCore implementation must handle all events and place them into the GameCoreEventQueue. The programmer then deals with the events inside of the rendering thread.

Currently I’m having trouble trying to figure out how to abstract out the canvas that will be drawn to. Any help here would greatly appretiated.

An evolving example of a game for GameCore.

The code is too hard to read with this forum software so here it is all pretty, thanks Dennis.

http://showsrc.com/$http://www.scottshaver2000.com/temp/MyGame.java

Not very helpful, but…this is a worthwhile exercise :). There was some interest a while back in trying something like this collaboritvely, and several aborted early attempts (personally I ran out of time). I think it would have helped if something had happened from the GTG about publishing developer articles (on JGO), because there was a lot of interest in developing it as an example throughout articles.

If/when you get around to the networking side, I’ll help there (just too busy at the moment to do anything myself).

PS this kind of architectural design is very hard to get right (hence I ran out of time trying to make a good one before). I suggest implementing two dissimilar simple games ASAP, and that will tell you pretty quickly where your design is iffy.

I had a scan over the class diagram, and it looked OK, although I think you’d need to modularise some more - e.g. your classes look a bit too monolithic at the moment.

Okay thanks for the notes, there is an updated class diagram up. I have taken your advice and I’m writing a couple programs to see how things would work. The first one is a simple Tic-Tac-Toe game. The code is here.

http://showsrc.com/$http://www.scottshaver2000.com/temp/GCTicTacToe.java

I’m finding I like this process, write the program how you want it to be and then see how that affects the library design.

Bravo for the effort + good intentions but I think 2) would be lost on a “new” game programmer and 3) is irrelavent; the real difficulty/complexity in gamedev is not gfx (imho).

But when/if you get to scripting/networking I will be very interested in your ideas.

I think I kind of see what you’re getting at, but…these are things that entirely control (prevent):

  • RAD: trying out new game ideas; giving people like me who are v.busy a chance to write new games in their v. limited free time; etc
  • Tutorials: basis for teaching people how to program java games, assuming they are naive java programmers (a lot of people who come here have done v. little java programming before…)

And, of course, given how many games people start but never finish, anything that reduces the hurdles and saves time is a massive boon.

Okay a few questions:

1> The DisplayObject class is the root for all things that can go on the screen. I’m thinking that I’ll create a set of objects such as ImageSprite, AnimImageSprite, TextSprite, etc. These would simply be data containers with concrete implementations having a render() method that accepts an Interface type of GameCoreRenderer. The render layer has to implement the GameCoreRenderer interface so that it knows how to render the different types of sprites. The other option is to make the sprite classes abstract and the render layer would have to implement the render() method for each sprite type. What do you think?

2> For networking would it make since to have a thread that handles ripping the data from the network card and turns that into a set of events that end up in the GameCoreEventQueue?

Suggestion off the top of my head.

The last java 2D game I did I found that having an object for every thing in the game was a PITA.

Instead I sliced it aspect-ly, and I got a lot of mileage out of having:

  • "Object positioner"s
  • "Object mover"s
  • "Object collider"s
  • "object renderer"s
  • …etc
    where one instance of each of those was responsible for a class (not the keyword!) of objects. E.g. one positioner for all “alien_type_1” that are on the screen, a separate positioner for all “alien_type_2” that are on the screen, etc.

One advantage was that getting classes (not java) of objects to behave as a group was a doddle. Which especially applies to getting aliens to collaborate, etc.

The main advantage was that it was easy to “share” different aspects of game-entities - like their movement, their solidity, whether they were lethal, etc. e.g. I had a collider implementation that ignored collisions, another that caused things to bounce away, and another that caused things to be removed from the game.

So I could easily experiment with making different objects destructible/indestructible/etc. RAD was easy.

It’s just a pity that I screwed up the mouse input layer, which was so ugh! that it wasn’t worth continuing with :(.

[quote]Okay a few questions:

1> The DisplayObject class is the root for all things that can go on the screen. I’m thinking that I’ll create a set of objects such as ImageSprite, AnimImageSprite, TextSprite, etc. These would simply be data containers with concrete implementations having a render() method that accepts an Interface type of GameCoreRenderer. The render layer has to implement the GameCoreRenderer interface so that it knows how to render the different types of sprites. The other option is to make the sprite classes abstract and the render layer would have to implement the render() method for each sprite type. What do you think?
[/quote]
Not entirely sure what you’re asking, but…AFAICS you’re asking whether to have each of your XXXSprite classes implement a method that either:
a. renders to a surface
b. provides an image of known format (RGBA etc)
?

In which case, it doesn’t really matter, it’s the same amount of code either way - with a) you have all the sprites extend a base class that contains basic rendering capability, with b) you have them extend a base class that negotiates with the GCR to get the img format. a) seems slightly cleaner?

Well, with NIO that’s unnecessary…you can just allocate X ms to the networking at a point of your chosing. Although:

…so you might prefer just to poll periodically. Either way, it’ll be non-blocking, so there’s no need for an extra thread.

You are going to only use NIO, aren’t you? :). Not worth the effort of old I/O, IMHO.

As for the rendering of different sprite types I was trying to figure if it would be better to have the rendering layers have to implement a single interface, GameCoreRenderer such as:


public interface GameCoreRenderer
{
   public renderImageSprite(ImageSprite);
   public renderAnimImageSprite(AnimImageSprite);
   etc...
}

This would mean that I could write all of the looping through the GameCoreRenderSets and the layer only has to know about the rendering specifics. I would have a method in the GameCore class that returns an instance of the GCR provided by the rendering layer and then call it on each object in the GCRenderSets based on the object types with instanceof. This means you can create the sprite objects using new ImageSprite() instead of a factory method. This is how I’m thinking of going.

or they have to implement a different class for each of the different types of sprites. This would mean then that the GameCore object would become a factory for all of the different sprite types and the render layer would have to provide an method implmentation for each of the type like:


public ImageSprite newImageSprite();
etc...

On the networking side basically what I’m asking is should ALL things in the engine be driven by the event queue?

I would use NIO, of course. So when data arrived from a client it would be packaged into a GameCoreNetworkEvent and added to the event queue for handling in the the handleEvent() method. I see that I wouldn’t need another thread for this it would simply happen behind the scenes automatically in the render loop.

[quote]On the networking side basically what I’m asking is should ALL things in the engine be driven by the event queue?
[/quote]
Well, you’d need to add several more event types AFAICS if you did that. So long as you had one for “game-logic-event” that should handle them all I think.

I mean, how do you handle network-sourced commands that are nothing to do with player-inserted commands, such as:

  • “change_level_to 3” (e.g. quake servers that rotate the level every X minutes)
  • “new_player_appears_at 405,340”
  • “chat_message_from_player wibble Hello there!”

etc.

Okay there is a new class diagram up (check the link above). The way it is right now only one class has to be created to completely replace the rendering layer. The GameCoreRenerer interface has to have an implementation.

I’m still not quite sure how to abstract out the drawing canvas so there might be an additional class to implement as well.

Question: Currently I have the handleEvents method in the GameCoreProgram interface. You have to implement it and the system assumes you will handle the events in that method. I was thinking about calling it automatically. Would it be better to have the system call it or let the programmer place it were they want it. For instance at the beginning of a frame render or after.

I’ve pretty much sorted out this framework design in Alien Flux hehe :slight_smile: I’m not so sure that it’s a particularly worthwhile gesture trying to allow the “rendering layer” to get abstracted out as you end up with bloat, complexity, and satisfying no-one. Technically my sprite engine can be replaced by a drop in Java2D renderer but then its performance characteristics would be radically different. Likewise the realtime GUI interface could be done in Java2D but it would run at 5fps. Just my 2p.

The sprite engine in SPGL might well be worth you taking a look at as it does, well, everything pretty much that you need it to, and you can replace the rendering part with something else if you really really want. What it doesn’t have is nice IDE tools to make it easier to actually get sprite resources into it.

Cas :slight_smile:

Another new class diagram up (check the link in the first post).

The way it is right now:

Two classes have to be created to completely replace the rendering layer.

1> GameCoreRenderer interface has to have an implementation.
2> CanavsPeer interface has to have an implementation.

Two classes have to be created to completely replace the audio layer.

1> GameCoreSoundStore abstract class has to have an implementation.
2> GameCoreSound interface has to have at least one implementation.

WTF is a “MeterSprite” ??? :slight_smile:

The idea was to give a class that could display a health meter like sheild strength or something. Just throwing out ideas :P.

Typo: you have in GameCoreRenderer:
renderAnimeImageSprite

But the argument is:
GameCoreAnimImageSprite

Also, could you possibly do a slightly larger (+20% ?) version of the image? It’s really hard to read at 1400x1050 :frowning:

What do you plan to do about the game-logic network-sourced events? Will they be part of the gameCoreEventQ, or handled separately? (I suspectly separately is easier to keep clean, because it will likely evolve separately from the others, BUT it makes lock-step games and replays much harder because you can’t simply “record every event in the GameCoreEventQ and play them back in order at correct times”).

[quote]The idea was to give a class that could display a health meter like sheild strength or something. Just throwing out ideas :P.
[/quote]
I can’t see the animSprite API in the diagram, but your anim sprite should handle that OK. A meter is just an anim sprite that uses a different algorithm to decide which frame to display next :).

Shouldn’t require ANY extra code - assuming your anim sprites have their frame updated independently of the render call? (i.e. internally they keep track of whether they need to advance the frame; they do -of course- need the renderer to tell them the delta since the last render call).

[quote]Typo: you have in GameCoreRenderer:
[/quote]
Fixed the typo, thanks.

[quote]Also, could you possibly do a slightly larger (+20% ?) version of the image? It’s really hard to read at 1400x1050
[/quote]
Poseidon doesn’t let me set the image size, unfortunately. It just creates one that everything will fit in apparently at a hard coded zoom level.

If you have a UML tool that will import XMI I can export the diagram in that format and put it on the web. Also I could post up the code that is getting generated. I have filled in a number of the methods and have been trying to make sure the javadocs are there as well.

[quote]What do you plan to do about the game-logic network-sourced events? Will they be part of the gameCoreEventQ, or handled separately?
[/quote]
I’m still thinking I want to have the network events in some sort of queue. It might not be in the same queue as the other events though. For scripting demos it would be really nice to place them in the same queue.

[quote]A meter is just an anim sprite
[/quote]
Good thinking on the meter sprite I’ll kill it.

[quote]assuming your anim sprites have their frame updated independently of the render call
[/quote]
I’m thinking of adding a specific interface to the sprite types that need frame updates. Something like:

public interface Updatable
{
public void setUpdateInterval(long interval);
public long getUpdateInterval(long interval);
public void shouldUpdate(long interval);
public void update();
}