簡體   English   中英

LibGDX-創建動畫

[英]LibGDX - Create Animation

您好StackOverflow社區!

我一直在從事游戲項目,最近在Spritesheet類中遇到錯誤。

問題:游戲是使用LibGDX開發的,它具有內置功能,可讓您將圖像拆分為2D數組,其中第一維為行,第二維為列。

例如:spriteSheet [0] [1]將為您提供第一行的第二列。

因此,我想出了一種使用該行生成動畫的小方法,但是當我運行游戲時,由於玩家始終保持靜止,因此動畫似乎不起作用!

此過程涉及4個類:

播放器類:

package com.darkbyte.games.tfa.game.entity.entities;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.darkbyte.games.tfa.game.entity.Entity;
import com.darkbyte.games.tfa.game.entity.SpriteSheet;
import com.darkbyte.games.tfa.render.RenderManager;

public class Player extends Entity {

    //The constructor for the player class
    public Player(String name, SpriteSheet spriteSheet) {
        super(name, spriteSheet);
        direction = Direction.DOWN;
    }

    //A flag to see if the player is moving
    private boolean isMoving;
    //The player's walking animations
    private Animation[] walkAnimations = {
            spriteSheet.getAnimation(4, 1/16f),
            spriteSheet.getAnimation(5, 1/16f),
            spriteSheet.getAnimation(6, 1/16f),
            spriteSheet.getAnimation(7, 1/16f)
    };
    //The player's static frames
    private TextureRegion[] staticFrames = {
            spriteSheet.getTexture(4, 0),
            spriteSheet.getTexture(5, 0),
            spriteSheet.getTexture(6, 0),
            spriteSheet.getTexture(7, 0)
    };

    //The render code for the player
    @Override
    public void render() {
        //Gets the player's direction, if the player's moving, it sets the current frame to the frame that would be played at the current moment based on the state time
        //If the player isn't moving, it sets the current frame to the static frame associated to the direction
        switch(direction) {
        case UP:
            if(isMoving)
                currentFrame = walkAnimations[0].getKeyFrame(RenderManager.getStateTime(), true);
            else
                currentFrame = staticFrames[0];
            break;
        case LEFT:
            if(isMoving)
                currentFrame = walkAnimations[1].getKeyFrame(RenderManager.getStateTime(), true);
            else
                currentFrame = staticFrames[1];
            break;
        case DOWN:
            if(isMoving)
                currentFrame = walkAnimations[2].getKeyFrame(RenderManager.getStateTime(), true);
            else
                currentFrame = staticFrames[2];
            break;
        case RIGHT:
            if(isMoving)
                currentFrame = walkAnimations[3].getKeyFrame(RenderManager.getStateTime(), true);
            else
                currentFrame = staticFrames[3];
            break;
        }
    }

    //The tick code for the player
    @Override
    public void tick() {
        if(Gdx.input.isKeyPressed(Keys.W) || Gdx.input.isKeyPressed(Keys.UP)) {
            direction = Direction.UP;
            y += 2;
        } else if(Gdx.input.isKeyPressed(Keys.A) || Gdx.input.isKeyPressed(Keys.LEFT)) {
            direction = Direction.LEFT;
            x -= 2;
        } else if(Gdx.input.isKeyPressed(Keys.S) || Gdx.input.isKeyPressed(Keys.DOWN)) {
            direction = Direction.DOWN;
            y -= 2;
        } else if(Gdx.input.isKeyPressed(Keys.D) || Gdx.input.isKeyPressed(Keys.RIGHT)) {
            direction = Direction.RIGHT;
            x += 2;
        } else {

        }
    }

    //Returns if the player is moving
    public boolean isMoving() {
        return isMoving;
    }
}

RenderManager類:

package com.darkbyte.games.tfa.render;

import javax.swing.JOptionPane;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.darkbyte.ammarlib.files.DataWriter;
import com.darkbyte.games.tfa.Core;
import com.darkbyte.games.tfa.music.MusicManager;
import com.darkbyte.games.tfa.screens.ScreenManager;
import com.darkbyte.games.tfa.screens.UnidentifiedScreenStateException;

public class RenderManager {

    //timeSinceLastFramesPerSecondCheck is used to store the clock time since the last frames per second check was done
    private static long timeSinceLastFramesPerSecondCheck;
    //framesPassed is used to store the number of frames passed in a second
    private static int framesPassed, framesPerSecond;
    //The variable that stores the current state time of the render, used for animations
    private static float stateTime;

    //Initialisation for everything render related
    public static void init() {
        Camera.init();
        Batch.init();
        Button.init();
    }

    //Disposal for everything render related
    public static void dispose() {
        Batch.dispose();
        Button.dispose();
    }

    //The main render method
    public static void render() {
        //Gets the current clock time in milliseconds
        long now = System.currentTimeMillis();
        //Increments the frames passed
        framesPassed++;

        //Updates the state time variable
        stateTime += Gdx.graphics.getDeltaTime();

        //Checks if 1 second has passed since the last frames per second check
        if(now >= timeSinceLastFramesPerSecondCheck + 1000) {
            //The frames per second is set to the frames passed that second
            framesPerSecond = framesPassed;
            //The frames passed is reset
            framesPassed = 0;
            //Sets the time since the last frames per second check to now
            timeSinceLastFramesPerSecondCheck = now;
        }

        //Clears the screen from the previous render call
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        //Renders the correct screen from the screen manager and plays the music for that screen
        try {
            ScreenManager.renderScreen();
            MusicManager.playMusic();
        } catch (UnidentifiedScreenStateException e) { //If the screen state runs into an error
            //Prints the error log to a time-stamped file
            DataWriter writer = new DataWriter(); //Creates a new data writer to write to the file
            writer.openFile(Core.getTime(true) + ".txt"); //Opens a the file
            writer.write("Tetros: First Age - An error has occurred!\nType: UnidentifiedScreenStateException in RenderManager!"); //Writes some basic data about the error
            writer.write(e.getMessage()); //Prints a detailed error log from the exception
            writer.closeFile(); //Closes the file, housekeeping reasons

            e.printStackTrace(); //Prints the error log to the console
            //Shows the client an error message in a dialog box
            JOptionPane.showMessageDialog(null, "An unexpected error occured: UnidentifiedScreenStateException in RenderManager!", "Error", JOptionPane.ERROR_MESSAGE);
            //Closes the game
            System.exit(0);
        }
    }

    //Returns the ticks per second rate
    public static int getFPS() {
        return framesPerSecond;
    }

    //Returns the frames passed
    public static int getFramesPassed() {
        return framesPassed;
    }

    //Returns the current state time
    public static float getStateTime() {
        return stateTime;
    }
}

SpriteSheet類:

package com.darkbyte.games.tfa.game.entity;

import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.*;

public class SpriteSheet {

    //All the frames from the entity
    private TextureRegion[][] textureSheet;

    //Gets the sprite sheet for the entity and splits it into frames
    public SpriteSheet(Texture spriteSheet, int tileWidth, int tileHeight) {
        //Splits the textures into a two dimensional array
        /*
         * Dimension 1: Row
         * Dimension 2: Column
         * Example:
         * ********
         * ****0***
         * ********
         * ********
         * 0 = textureSheet[1][4] to access the second row and the fifth column
         * Some of the columns may be blank, check the sprite sheet to reference
         */
        textureSheet = TextureRegion.split(spriteSheet, tileWidth, tileHeight);
    }

    //Disposes of the textures by looping through the rows then the individual columns and disposing of all the textures
    public void dispose() {
        for(TextureRegion[] textureRow : textureSheet) for(TextureRegion texture : textureRow) texture.getTexture().dispose();
    }

    //Returns the texture at a certain row or column (starting at 1,1 being textureSheet[0][0])
    public TextureRegion getTexture(int row, int column) {
        return textureSheet[row][column];
    }

    //Returns an animation using pieces of the sprite sheet
    public Animation getAnimation(int row, float animationFPS) {

        //Returns the animation generated using the frames from the row specified and the FPS from the parameters
        return new Animation(animationFPS, textureSheet[row]);
    }
}

TestRoom類:

package com.darkbyte.games.tfa.game.world.room.rooms;

import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.darkbyte.games.tfa.game.entity.Entity;
import com.darkbyte.games.tfa.game.entity.EntityManager;
import com.darkbyte.games.tfa.game.world.room.Room;
import com.darkbyte.games.tfa.render.Batch;
import com.darkbyte.games.tfa.render.Camera;

public class TestRoom extends Room {

    //Initialises the room's tiled map and map renderer
    @Override
    public void init() {
        this.tileMap = Room.generateMap("assets/world/rooms/test.tmx");
        this.mapRenderer = new OrthogonalTiledMapRenderer(this.tileMap);

        entitiesInRoom.add(EntityManager.getPlayer(0, 0, 0));
    }

    //Disposes of the room
    @Override
    public void dispose() {
        this.tileMap.dispose();
    }

    //Runs the render code for the room
    @Override
    public void render() {
        //Sets the map renderer's viewpoint to the viewpoint of the camera
        mapRenderer.setView(Camera.getCamera());
        //Renders the map
        mapRenderer.render();

        //Begins the drawing batch
        Batch.getGameBatch().begin();
        //Loops through the entities in the room and renders them
        for(Entity entityToRender : entitiesInRoom) {
            entityToRender.render();
            Batch.getGameBatch().draw(entityToRender.getCurrentFrame(), entityToRender.getX(), entityToRender.getY());
        }
        //Ends the drawing batch
        Batch.getGameBatch().end();
    }

    //Runs the tick code for the room
    @Override
    public void tick() {
        //Loops through the entities in the room and runs their tick code
        for(Entity entityToRender : entitiesInRoom) entityToRender.tick();
    }
}

與其自己構建所有動畫機制,不如使用Libgdx的Animation,它更易於使用。 閱讀維基

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM