Skip to content

player_scene

Night Rider edited this page Nov 26, 2024 · 19 revisions

Creating the player scene

With the project settings in place, we can start working on the player-controlled character.

The first thing is to create a parent state for the scenes.

State

In package e.g.dodgethecreeps.screen create a class 'AbstractScreen' that inherits from BaseAppState (implement all abstract methods).

package e.g.dodgethecreeps.screen;
...
public abstract class AbstractScreen extends BaseAppState {
...
}

Now that you have your main class, create a new class GameSceneAppState for the player scene state.

package e.g.dodgethecreeps.screen;
...
public class GameSceneAppState extends AbstractScreen {
    private Node rootNode;

    @Override
    protected void initialize(Application app) {
        super.initialize(app);
        Dodgethecreeps application = (Dodgethecreeps) app;

        rootNode = new Node("MyRootNode");
        application.getRootNode().attachChild(rootNode);
    }

    @Override
    protected void onDisable() {
        super.onDisable();
        rootNode.detachAllChildren();
    }
}

Add the following states to the manager, open class Dodgethecreeps and find method public void simpleInitApp().

@Override
public void simpleInitApp() {
    ...
    // scene states; where the game is managed
    GameSceneAppState gameAppState  = new GameSceneAppState();
    stateManager.attach(gameAppState);
    ....
}

Node structure

To start, in the e.g.dodgethecreeps.game package, create a new Player class for the player character's body and control.

package e.g.dodgethecreeps.game;
...
public final class Player extends KinematicBody2D {

    public Player(Dodgethecreeps app) {}

    protected void ready() {

    }

    protected void physicsProcess(float delta) {

    }
}

Model

In the Player class, generate a static method where the character models are configured.

public static Player getNewInstancePlayer(Dodgethecreeps app) {
    AssetManager assetManager = app.getAssetManager();
        
    Material mat = MaterialUtilities.getUnshadedMaterialFromClassPath(assetManager, "Textures/playerGrey_walk1.png");
    mat.setFloat("AlphaDiscardThreshold", 0.0F);
        
    Sprite sprite = new Sprite(1.5F, 1.5F);        
    Geometry geom = new Geometry("Player", sprite);
    geom.setMaterial(mat);
    geom.setQueueBucket(RenderQueue.Bucket.Transparent);

    Player player = new Player(app);
    geom.addControl(player);
    return player;
}

Sprite animation

Add 2 animations for the player character.

...
// Add the following animations.
AnimatedSprite2D animatedSprite = new AnimatedSprite2D();
animatedSprite.addAnimation("walk", new Texture[] {
    TextureUtilities.getTextureFromClassPath(assetManager, "Textures/playerGrey_walk1.png"),
    TextureUtilities.getTextureFromClassPath(assetManager, "Textures/playerGrey_walk2.png")
});
animatedSprite.addAnimation("up", new Texture[] {
    TextureUtilities.getTextureFromClassPath(assetManager, "Textures/playerGrey_up1.png"),
     TextureUtilities.getTextureFromClassPath(assetManager, "Textures/playerGrey_up2.png")
});
        
animatedSprite.setAnimationSpeed(0.60F);
geom.addControl(animatedSprite);
...

Filter - Dyn4j

Dyn4j uses a filter system to apply physical body collisions.

Create a new class in package e.g.dodgethecreeps.game as follows.

package e.g.dodgethecreeps.game;
...
public final class LayerFilter implements Filter {
    private final int layer;

    public LayerFilter(int layer) {
        this.layer = layer;
    }

    @Override
    public boolean isAllowed(Filter filter) {
        if (filter instanceof LayerFilter) {
            if (this.layer == ((LayerFilter) filter).layer) {
                return false;
            }
        }
        return true;
    }
}

This filter applies collisions if the layers are equal, otherwise the physical bodies do not collide.

Shape

Finally add a physical shape (Capsule).

....
BodyFixture fixture = new BodyFixture(GeometryUtilities.dyn4jCreateCapsule(0.8, 1.1));
fixture.setFilter(new LayerFilter(0));

player.addFixture(fixture);
player.setMass(MassType.NORMAL);
....

Player Class

Your player class must have the following.

package e.g.dodgethecreeps.game;
...
public final class Player extends KinematicBody2D {

    public Player(Dodgethecreeps app) {
    }

    protected void ready() {

    }

    protected void physicsProcess(float delta) {

    }

    public static Player getNewInstancePlayer(Dodgethecreeps app) {
        AssetManager assetManager = app.getAssetManager();

        Material mat = MaterialUtilities.getUnshadedMaterialFromClassPath(assetManager, "Textures/playerGrey_walk1.png");
        mat.setFloat("AlphaDiscardThreshold", 0.0F);

        Sprite sprite = new Sprite(1.5F, 1.5F);
        Geometry geom = new Geometry("Player", sprite);
        geom.setMaterial(mat);
        geom.setQueueBucket(RenderQueue.Bucket.Transparent);

        // Add the following animations.
        AnimatedSprite2D animatedSprite = new AnimatedSprite2D();
        animatedSprite.addAnimation("walk", new Texture[] {
                TextureUtilities.getTextureFromClassPath(assetManager, "Textures/playerGrey_walk1.png"),
                TextureUtilities.getTextureFromClassPath(assetManager, "Textures/playerGrey_walk2.png")
        });
        animatedSprite.addAnimation("up", new Texture[] {
                TextureUtilities.getTextureFromClassPath(assetManager, "Textures/playerGrey_up1.png"),
                TextureUtilities.getTextureFromClassPath(assetManager, "Textures/playerGrey_up2.png")
        });

        animatedSprite.setAnimationSpeed(0.60F);

        BodyFixture fixture = new BodyFixture(GeometryUtilities.dyn4jCreateCapsule(0.8, 1.1));
        fixture.setFilter(new LayerFilter(0));

        Player player = new Player(app);
        player.addFixture(fixture);
        player.setMass(MassType.NORMAL);

        geom.addControl(player);
        geom.addControl(animatedSprite);
        return player;
    }
}

Show player on scene

Setting GameSceneAppState status

  • Create the following properties in this state:
private Dyn4jAppState<PhysicsBody2D> dyn4jAppState;
private TimerAppState timerAppState;
private Player player;
  • Initialize the following properties:
@Override
protected void initialize(Application app) {
    ....        
    dyn4jAppState = getState(Dyn4jAppState.class);
    timerAppState = getState(TimerAppState.class);
    ...
}
  • Show the player
@Override
protected void onEnable() {
    super.onEnable();
    player = Player.getNewInstancePlayer((Dodgethecreeps) getApplication());
    player.translate(0, -1.5);

    dyn4jAppState.getPhysicsSpace().addBody(player);
    rootNode.attachChild(player.getJmeObject());
}
  • Disabling this state releases all physical bodies of the dyn4j engine.
@Override
protected void onDisable() {
    ...
    World<PhysicsBody2D> world = dyn4jAppState.getPhysicsSpace();
    if (world != null) {
        world.removeAllBodies();
    }
    ...
}

Code

At the moment your code should look similar to the following:

package e.g.dodgethecreeps.screen;
...
public class GameSceneAppState extends AbstractScreen {
    private Node rootNode;

    private Dyn4jAppState<PhysicsBody2D> dyn4jAppState;
    private TimerAppState timerAppState;
    private Player player;

    @Override
    protected void initialize(Application app) {
        super.initialize(app);
        Dodgethecreeps application = (Dodgethecreeps) app;

        rootNode = new Node("MyRootNode");
        application.getRootNode().attachChild(rootNode);

        dyn4jAppState = getState(Dyn4jAppState.class);
        timerAppState = getState(TimerAppState.class);
    }

    @Override
    protected void onEnable() {
        super.onEnable();
        player = Player.getNewInstancePlayer((Dodgethecreeps) getApplication());
        player.translate(0, -1.5);

        dyn4jAppState.getPhysicsSpace().addBody(player);
        rootNode.attachChild(player.getJmeObject());
    }

    @Override
    protected void onDisable() {
        super.onDisable();
        World<PhysicsBody2D> world = dyn4jAppState.getPhysicsSpace();
        if (world != null) {
            world.removeAllBodies();
        }
        rootNode.detachAllChildren();
    }
}

Previous - Next