LibGDX game jam first weekend

This weekend have I set up the project, I have started to use Artemis. This is my first time so I’m little lost how big every component should be and how big every system should be. You can find all the code on my GitHub page, and you can find all my planing on trello. I don’t have any direkt graphics yet. But it is the next thing for me.

Main core class

I like to be able to change screen very easy so in my main class I add all my screens as public and then in the constractor on every screen I add my main core class. I also have some objects that all the screens need. I have the viewport/camera and batch public also for easy access.

/LibGDXJamSpace/blob/master/core/src/net/corpwar/game/libgdxjam/LibGDXJamSpace.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// One batch
public SpriteBatch batch;
 
// One camera, orthographic to handle 2d, and a viewport
public Camera camera;
public Viewport viewport;
 
// Arthemis gameworld
public World arthWorld;
 
// Screens
public SplashScreen splashScreen;
public GameScreen gameScreen;
 
// Handle all assets
public AssetManager assetManager;

All the creation of objects are stright forward. I create all my screens, easy to add more. I add my camera and move it so 0,0 are in the bottom left corner and not center screen. I haven’t decided what viewport I should use yet so I use a streatched viewport to start with.
In the config for artemis I’m adding my own invocation strategy class. This is so I can keep a steady update on all my logic systems and run as fast as I can on my other systems (render for example). The number in my systems (should be a private final value) are the FPS I want to simulate everything in, in my case 20 FPS. I’m thinking if I have time to make it a network game and then I don’t want the logic to be to fast but Still have the render look smooth.

/LibGDXJamSpace/blob/master/core/src/net/corpwar/game/libgdxjam/LibGDXJamSpace.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Override
public void create () {
	assetManager = new AssetManager();
 
	// create all screens
	splashScreen = new SplashScreen(this);
	gameScreen = new GameScreen(this);
 
	// Create camera
	camera = new OrthographicCamera();
	((OrthographicCamera)camera).setToOrtho(false);
	viewport = new StretchViewport(width, height, camera);
	camera.position.set(viewport.getWorldWidth() / 2f, viewport.getWorldHeight() / 2f, 0);
 
	batch = new SpriteBatch();
 
	WorldConfiguration config = new WorldConfigurationBuilder()
			.with(new SortedRenderSystem(this), new PhysicsSystem(20), new InputSystem(this, 20))
			//.with(new RenderSys(), new EditingSys(), new ScriptSys())
			.register(new GameLoopSystemInvocationStrategy(20))
			.build();
	arthWorld = new World(config);
	setScreen(splashScreen);
 
	testData();
}

System classes

In my class GameLoopSystemInvocationStrategy is the strategy to handle a constant FPS on all the logic system and how to handle all the system that isn’t time critical, like rendering. I did find this on GitHub and I have been modifing it to work better for me. This is constructed from the idé from Gaffersons blog.

/LibGDXJamSpace/blob/master/core/src/net/corpwar/game/libgdxjam/systems/GameLoopSystemInvocationStrategy.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public class GameLoopSystemInvocationStrategy extends SystemInvocationStrategy {
 
 
    private float timeToProgress;
    private float accumulator  = 0;
    private float simAccumulator = 0;
 
    private final Array logicMarkedSystems;
    private final Array otherSystems;
 
    private boolean systemsSorted = false;
 
    public GameLoopSystemInvocationStrategy(float logicFPS) {
        timeToProgress = 1 / logicFPS;
        logicMarkedSystems = new Array();
        otherSystems = new Array();
    }
 
    @Override
    protected void process(Bag systems) {
        if (!systemsSorted) {
            sortSystems(systems);
        }
        accumulator += world.delta;
        while (accumulator >= timeToProgress) {
            for (int i = 0; i < logicMarkedSystems.size; i++) {
                /**
                 * Make sure your systems keep the current state before calculating the new state
                 * else you cannot interpolate later on when rendering
                 */
                logicMarkedSystems.get(i).process();
                updateEntityStates();
            }
            accumulator -= timeToProgress;
            simAccumulator = 0;
        }
        for (int i = 0; i < otherSystems.size; i++) {
            /**
             * Use the kept state from the logic above and interpolate with the current state within your render systems.
             */
            otherSystems.get(i).process();
            updateEntityStates();
        }
    }
 
    private void sortSystems(Bag systems) {
        if (!systemsSorted) {
            Object[] systemsData = systems.getData();
            for (int i = 0, s = systems.size(); s > i; i++) {
                BaseSystem system = (BaseSystem) systemsData[i];
                if (system instanceof LogicRenderMarker) {
                    logicMarkedSystems.add(system);
                } else {
                    otherSystems.add(system);
                }
            }
            systemsSorted = true;
        }
    }
}

For my render system I did a general sorting system that make it able to sort all my assets on the Z value. This make it easyer to display things in the correct order. I wanted to send a Comparable argument into the constructor but I couldn’t get that to work. So I had to make a setComparator method. It’s not as elegant but it works.

/LibGDXJamSpace/blob/master/core/src/net/corpwar/game/libgdxjam/systems/SortedIteratingSystem.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public abstract class SortedIteratingSystem extends BaseEntitySystem {
 
    private final Array sortedEntities = new Array();
    private Comparator comparator;
 
    public SortedIteratingSystem(Aspect.Builder aspect) {
        super(aspect);
    }
 
    public void setComparator(Comparator comparator) {
        this.comparator = comparator;
    }
 
    protected abstract void process(Entity entity);
 
    @Override
    protected final void processSystem() {
        for (int i = sortedEntities.size - 1; i >= 0; i--) {
            process(sortedEntities.get(i));
        }
    }
 
    @Override
    protected void inserted(int entityId) {
        sortedEntities.add(world.getEntity(entityId));
        sortedEntities.sort(comparator);
    }
 
    @Override
    protected void removed(int entityId) {
        sortedEntities.removeValue(world.getEntity(entityId), false);
        sortedEntities.sort(comparator);
    }
}

Then my render class just use this sorting class to display everything on the screen.

/LibGDXJamSpace/blob/master/core/src/net/corpwar/game/libgdxjam/systems/SortedRenderSystem.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class SortedRenderSystem extends SortedIteratingSystem {
 
    private LibGDXJamSpace jamSpace;
    private ComponentMapper transform2d;
    private ComponentMapper texture;
 
    public SortedRenderSystem(LibGDXJamSpace jamSpace) {
        super(Aspect.all(Transform2DComp.class, TextureComp.class));
        setComparator(new ZComparator());
        this.jamSpace = jamSpace;
    }
 
    @Override
    protected void begin() {
        if (jamSpace.batch != null) {
            jamSpace.camera.update();
            jamSpace.batch.setProjectionMatrix(jamSpace.camera.combined);
            jamSpace.batch.begin();
        }
    }
 
    @Override
    protected void process(Entity entity) {
        if (jamSpace.batch != null) {
            TextureComp textureComp = texture.get(entity);
            Transform2DComp transformComp = transform2d.get(entity);
            if (textureComp.sprite != null) {
                textureComp.sprite.setPosition(transformComp.position.x, transformComp.position.y);
                textureComp.sprite.setScale(transformComp.scale.x, transformComp.scale.y);
                textureComp.sprite.setRotation(transformComp.rotation);
                textureComp.sprite.draw(jamSpace.batch);
            }
        }
    }
 
    @Override
    protected void end() {
        if (jamSpace.batch != null) {
            jamSpace.batch.end();
        }
    }
 
    private class ZComparator implements Comparator {
        @Override
        public int compare(Entity e1, Entity e2) {
            return (int)Math.signum(transform2d.get(e1).zValue - transform2d.get(e2).zValue);
        }
    }
}

Nothing strange with the other systems. They have a small task on there hand. At the moment I’m thinking how I should get the input system to work in a good way. I’m little confused how I should do it. I have a kinda working solution. It’s easy to change othervise.

That’s it for this blog, Happy Coding everyone.

Bookmark the permalink.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *

Denna webbplats använder Akismet för att minska skräppost. Lär dig hur din kommentardata bearbetas.