This next section will be about your sprites and creating SpriteSheets. To work with sprites in LibGDX you need a LibGDX tool called ‘TexturePacker’
Download it here: https://github.com/crashinvaders/gdx-texture-packer-gui/releases
java -version
in your Terminal (Terminal can be opened using Spotlight Search)java version "1.8.0_231"
, then you’re set.export JAVA_HOME=/usr/libexec/java_home -v 1.8
to switch your Java version.The TexturePacker will take multiple sprite images and combine them together into one full image. It will also generate a reference file called an Atlas. The atlas has a title for each sprite’s images sectioned off with different coordinates in order to make it easier for your code to reference.
Before starting, find all the sprites you need using https://www.spriters-resource.com/, or any other site you want. When downloading the sprites, it is advisable to have the sprites appear on a transparent background. Download the sprites into a new folder, like so:
To start packing textures, nzip your TexturePacker and open the .jar file with ‘Jar Launcher.app’. Then you should see the screen below.
To create a new pack, click the top left button and name the pack something along the line of ‘Sprites’ or ‘game_sprites’.
Then select add input files and choose your folder of sprites.
Add an output directory (where you want the generated files to be stored) and change the file name if you want.
Then click pack all.
This should then generate an image with all the sprites together and also an Atlas in your selected output directory.
Finally, to add them to your game, copy and paste them into your ‘assets’ folder under ‘android’.
In your Constants class, you should add the name of your atlas as well as the name of each sprite in your atlas. For this example, I’ve only added one of the sprites but you may want to just add them all now for convenience later on.
Additionally, you should make sure your Game class has the variable private SpriteBatch batch;
and to create the getter method for this variable.
public SpriteBatch getBatch() { return batch; }
In your Screen class (which might be called LevelOne or something else), create a private TextureAtlas atlas;
and initialize it: atlas = new TextureAtlas(Constants.ATLAS_FILENAME);
. For a TextureAtlas we have to pass in a String which is the name of the atlas that you packed earlier, however since you should have added it to constants, you can simply call the constant’s variable.
You should also make a getter method for your atlas:
public TextureAtlas getAtlas(){
return atlas;
}
The last thing to do for now in your Screen class is to change the Player variable’s initialization by passing in your Screen in addition to the World. Because Player is initialized within a Screen, you can simply pass in ‘this’.
player = new Player(world, this);
In your Player class, you need to initialize a TextureRegion and some variables to handle the ‘STATE’ your player is in. ‘STATE’ is an enum which is a special data type that enables for a variable to be a set of predefined constants. For now, the only State you need is ‘STANDING’ or ‘IDLE’ where your player isn’t moving. Also, create a currentState variable to track what state the player is currently in and a boolean to track if the player is facing a certain direction (this boolean is only if you want to flip your image when the player is moving to the left).
//texture regions private TextureRegion playerIdleTexture; //states public enum State {STANDING}; public State currentState; private boolean runningToRight;
Then call super(screen.getAtlas().findRegion(Constants.PLAYER_STRING);
where PLAYER_STRING is the name of your player sprite from your Atlas. Because Player extends Sprite, you can set a region of your atlas to your Player’s sprite.
Next, set these as well in the constructor. ‘TextureRegion’ will take in a string of the player’s sprite name and also the (x, y, width, height) of your player sprite. In my case, the player starts at (0, 0) and his sprite is 16 by 16 pixels.
currentState = State.STANDING; runningToRight = true; //player idle texture region playerIdleTexture = new TextureRegion(screen.getAtlas().findRegion(Constants.PLAYER_STRING), 0, 0, 16, 16);
Then it’s time to set the bounds and region for your sprites to show up. ‘setBounds()’ confines the image of your sprite to a specific area, while ‘setRegion()’ sets the TextureRegion to whatever you specify.
//add these setBounds(0, 0, 16, 16); setRegion(playerIdleTexture);
Next, to prepare for animating the sprites, you should create a ‘getFrame()’ method. This method will return the frame, namely a TextureRegion, needed for display depending on the state your Player is in. ‘getState()’ is a method we will make later, it simply returns the State the player is currently in. As of now, we only have one State so there is only one case in the switch case.
Switch Case: For those who might not know, a ‘switch’ case is basically an ‘if’ statement. It takes an argument (in this case the currentState) and checks what it is. Then depending on what it is, the switch case will execute some code. If the switch case doesn’t have a matching condition, it will execute the default code (this is basically the ‘else’ part of the switch statement). Another thing that is special to ‘switch’ statements is that it needs ‘breaks;’ after each case. This might sound annoying but it lets you do something like what’s seen below, where you can have multiple cases end up with the same executed code.
The switch case will return the particular frame you want at that moment for your player. The next thing is to check if your player is facing the left or right so you can flip the texture to match. Essentially, if your player’s velocity is negative in the ‘x’ direction, it’s moving to the left. Additionally, ‘!runningToRight’ will return true if the player is moving to the left. After checking these 2 conditions, if the region texture is not already flipped, then flip the sprite. This idea is the opposite when the player is facing right. After all this is done, this method will return the manipulated texture.
//returns appropriate frame needed to display as sprite's texture region private TextureRegion getFrame(float deltaT) { currentState = getState(); TextureRegion region; switch(currentState) { //no breaks for next 2 cases because the following code applies to all 3 cases case STANDING: //no break needed here because STANDING and 'default' will do the same thing. default: region = playerIdleTexture; break; } //region.isFlipX() = true if texture is flipped i.e. Player running to left //if Player is standing facing right, flip them and run to left if((box2Body.getLinearVelocity().x < 0 || !runningToRight) && !region.isFlipX()) { region.flip(true, false); runningToRight = false; } //if Player is standing facing left, flip them and run to right else if((box2Body.getLinearVelocity().x > 0 || runningToRight) && region.isFlipX()) { region.flip(true, false); runningToRight = true; } return region; }
Now to create ‘getState()’. For now, it’s simple because we only have one state but it’s needed later on for animation.
public State getState() { return State.STANDING; }
Lastly, an update method to continually move the sprite every frame.
public void update(float deltaTime) { //set to position of bottom left corner of box2dbody setPosition(box2Body.getPosition().x - getWidth() / 2, box2Body.getPosition().y - getHeight() / 2); setRegion(getFrame(deltaTime)); }
Then call the Player class’s update() method in your Screen’s update method like so: player.update(deltaTime);
also, remember to pass in the deltaTime from your Screen class’s update method.
Lastly, add the line below to your render() method in your Screen class.
player.draw(myGame.getBatch());
Then you should be able to see your character’s sprite! (even though he won’t be animated quite yet)