-
Notifications
You must be signed in to change notification settings - Fork 0
Making your First Game
This guide will first walk you through the basics of RSauce, and then apply those basics to making a simple game.
RSauce uses a game design pattern known as an Entity Component System. An Entity Component System is an easy way to create complicated systems of entities without keeping track of complicated class "trees." Why is this so useful? Say you are designing an entity that represents a normal platform block, a-la Super Mario Brothers. You can walk on it, and if the player collides with it from underneath, it shatters, but you cannot pass through it from the sides; let's call this behavior. Most people who are familiar with Java and Object Oriented Programming will jump to making a Class
for this, called Block
which encapsulates this behavior. Let's say you also have enemies that perish if the player collides with them from above, but will kill the player if he collides from either side or underneath, also an example of behavior, and you make a class for that as well, called Enemy
. This is straightforward enough, but what happens if you want to make an entity that seems like a block but is an enemy in disguise? You can't subclass both Block
and Enemy
, and each of those classes require common code that represents their respective behavior, so you cant make them interfaces. Any other solution to this would needlessly complicate your class tree.
So this is what the Entity Component System is for.
In the Entity Component System, an Entity
is just nothing more than a "box" of Component
s. A Component
is nothing more than a completely abstract type that just represents some kind of property of the Entity, like position or velocity.
Engine
is a singleton class, to get the current instance of Engine
:
Engine engine = Engine.getEngine();
To add an Entity
to the Engine
:
Entity ent = new Entity;
engine.add(ent);
To give the Entity
a sprite and position, use DrawComponent
. DrawComponent
is a Component
built right into RSauce. Like other components, DrawComponent
implements the Component
interface. It has a constructor:
new DrawComponent(Graphic graphic, int x, int y, int z);
graphic
represents the graphical asset (See the "Assets" section) that will be displayed at position x
and y
in the Scene
. Let's use a Sprite
for this. Let's call this already created Sprite
entSprite
for now:
DrawComponent drawComp = new DrawComponent(entSprite, 100, 100, 0);
ent.addComponent(drawComp);
The last argument, z
represents the depth at where the Entity will be drawn. Entities with DrawComponent
with a greater z
will be drawn on top, and vice versa. Each Entity
can only have one of any type of Component
. If you try to add another DrawComponent
to ent
, it will replace the old one.
If you want to remove a Component
from an Entity
, use the respective class type:
ent.removeComponent(DrawComponent.class);
to remove an Entity
from the Engine
however, you'll need the actual Entity
itself:
engine.removeEntity(ent);
Like DrawComponent
, you can create your very own components by implementing the Component
interface. Components don't usually do anything by themselves however, They are meant to be acted on by a System
, but to understand Systems, we first have to understand the game loop.
The game loop has 4 steps, "step", "pre-draw", "draw", and "post-draw", which are executed in that order. Most of the time, you'll only be concerned with two of those steps, "step" and "draw" (pre- and post- draw are just the steps that draw the background and foreground layers respectively, which will be discussed later in this guide).
A System
is an Object that can be added to the Engine
, just like entities, and are used to define the logic of your game as it's executed each frame. Subclasses of System
have 3 methods to implement. addedToEngine()
and removedFromEngine()
are executed when the System
is added or removed from the Engine
, and update()
is called by the Engine
once per frame.
Unlike Entity
, you cannot subclass System
directly, but must instead subclass StepSystem
or DrawSystem
. The only difference between the two is exactly when their update()
methods are called in the game loop. You'll be using StepSystem
for most logic in the game, but keep in mind the "step" event occurs before all the "-draw" events, so if you try to draw anything in a StepSystem
, it will probably get overwritten by the draw event. Use DrawSystem
to draw things.
Here is an example of a vague StepSystem
, note the superclass constructor:
public class MyStepSystem extends StepSystem{
public MyStepSystem() {
super(0); // Superclass constructor required. It takes an int which sets the priority value
}
@Override
public void addedToEngine(Engine engine) {
// This method is executed when this system is added to the Engine,
// Use this time to set up and/or load your resources needed in update()
}
@Override
public void update(double delta) {
// Because this is a StepSystem, this method is executed during the step event.
// "delta" is a value that represents the time, in seconds, since the last frame.
}
@Override
public void removedFromEngine(Engine engine) {
// This method is executed when this system is removed from the Engine,
// Use this time to dispose of resources to avoid memory leaks.
}
}
To add this System
to the Engine
:
StepSystem sys = new MyStepSystem();
engine.add(sys);
Like Component
types in an Entity
, there can only be one of any type of System
in the Engine. If I try to add another MyStepSystem
to the Engine
it will replace the old one. Also like component, you remove System
s with their class reference:
engine.removeStepSystem(MyStepSystem.class);
So to summarize the game loop:
-
STEP - Executes all
StepSystem
s active in the engine, in order of their priority value. -
PREDRAW - Draws all the backgrounds in the current
Scene
sBackgroundAttribute
, if it has one. -
DRAW - Executes all
DrawSystem
s active in the engine, in order of their priority value, includingRenderSystem
, which renders all entities with aDrawComponent
. -
POSTDRAW - Draws all the foregrounds in the current
Scene
sBackgroundAttribute
, if it has one.