Artenus 2D Framework
Artenus Getting Started

Creating the First Scene

Each screen in a game is a scene. The game flow is controlled by switching between different scenes. For example, a game can contain a "main menu" scene, an "options" scene, and a "game play" scene. Our example has only two scenes: the main menu, and the game. This helps you understand the process of switching scenes while keeping things simple. The menu scene only contains a title, and a play button, which switches to the game scene. Create a new class called MenuScene and extend it from Scene. The following is the starting point of this class.

public class MenuScene extends Scene {
    public MenuScene(Stage parentStage) {
        super(parentStage);
        setBackColor(new RGB("44aaff"));
    }

    /**
     * This method is called by the framework when all textures are in place and it is safe
     * to build the scene. Create all sprites here.
     */
    @Override
    public void onLoaded() {
        // TODO: Create entities
        super.onLoaded();
    }
}

Note that we set the background color in the constructor. It is completely safe in the framework to set the background color there. But entities MUST be created in onLoaded, as resources required to create them (textures, etc) are guaranteed to be present when this method is called. As the scene we just created is the first scene in the game, we should also return it in our stage manager (which is also our main activity).

@Override
public Scene createInitialScene(Stage stage) {
    // Let the game begin!
    return new MenuScene(stage);
}

Setting up the scene

We start by adding entities to the scene in the onLoaded method. The first thing we add to the scene is a title text. Note how we call the superclass method at the end of the method. This instructs the framework that the scene is ready for rendering. It is recommended to always make this call at the very end.

@Override
public void onLoaded() {
    TextSprite welcomeText = new TextSprite(
        TextureManager.getFont(R.raw.font_letters), // Font texture
        40, // Font size
        "Welcome to Artenus!" // Initial text
    );

    welcomeText.centerAt(stage.getLogicalWidth() / 2, 50);
    add(new DropShadow(welcomeText).setOffset(2, 2));

    super.onLoaded();
}

A text sprite takes a font, a font size, and an initial text in its constructor. The text and the font size can be changed later on. The method getLogicalWidth of stage is an important method. In Artenus, the smallest dimension always has the logical size 600, that is, the width in portrait, and the height in landscape mode. The other dimension has a size according to the ratio of the device's native screen resolution. This makes it easier to create resolution-independent games. getLogicalWidth and getLogicalHeight simply return these logical dimensions. Finally, the last line wraps the text in a drop shadow entity, which causes it to, well, drop shadow!

Next step is to add a play button. In order to do this, we need to create an image sprite with the play texture we loaded globally, and the wrap it in a touch button. First, add the following field to the scene:

/**
* Play button
*/
private TouchButton playButton;

We will need to access this field later. Then add this code to the onLoaded method:

ImageSprite playSprite = new ImageSprite(R.raw.play, new ImageSprite.Cutout(160, 160, 1));
playSprite.setPosition(stage.getLogicalWidth() / 2, stage.getLogicalHeight() / 2);

playButton = new TouchButton(
        new DropShadow(playSprite).setShadowAlpha(0.3f).setOffset(4, 5)
);
playButton.setScale(0.9f);
add(playButton);

The cutout instructs the framework to extract a single frame out of the texture which is 160x160. The interesting point with above code is that we wrap the image sprite twice. First we wrap it in a drop shadow entity, and then we wrap that in a touch button entity. The touch button is the final entity that we add to the scene. Many entities in Artenus are created using similar patterns.

Animating the touch button

Our menu scene doesn't have much animation. The only animation we add here is to make the button larger when it's pressed, and back to normal when it is released. All animation in a scene is handled in the advance method. It is very important to call the superclass method when you override this method, as if you don't, animation handlers will stop working.

/**
 * Called by the framework for each frame, to advance the animation.
 *
 * @param elapsedTime The time elapsed since last frame
 */
@Override
public void advance(float elapsedTime) {
    super.advance(elapsedTime);

    if (playButton.isPressed()) {
        // Zoom the button in when pressed
        playButton.setScale(Math.min(1, playButton.getScale().x + elapsedTime));
    } else {
        // Zoom the button out when not pressed
        playButton.setScale(Math.max(0.9f, playButton.getScale().x - elapsedTime));
    }
}

What the code does is self-explanatory. The elapsedTime is in seconds, and it has a floating point type to be able to represent fractions of a second.

Managing the game flow

Up to now we have a button that does nothing, and if the user presses the back button, nothing happens either. This is not exactly what a game is like, and this is what we are going to change. We start by handling the back button.

    @Override
    public boolean onBackButton() {
        Artenus.getInstance().exit();
        return true;
    }

This was pretty straightforward Handling the play button click is not as simple. First, we need to assign a button listener to the touch button. For the sake of this example, it is enough to just implement the listener into the scene itself. So, we add the implements directive to the class.

public class MenuScene extends Scene implements ButtonListener {

This interface has two methods: onPressed, and onReleased. We only need to take action when the button is released.

@Override
public void onPress(Button button) {

}

@Override
public void onRelease(Button button, boolean cancel) {
    if (!cancel) {
        if (button == playButton) {
            stage.setScene(new GameScene(stage));
        }
    }
}

The cancel argument specifies whether the release action for this button is canceled. This happens when the user presses the button, and releases the touch stroke (or mouse button) outside the button area. On a successful click, we set the stage's scene to the game scene (which we will create next). The last thing we need to do here is to assign the listener to the button. So, add the following after the creation of the play button in onLoaded:

playButton.setListener(this);
Previous: Adding Graphics and Sound Next: Creating the Game Scene