[added] TextureRegion.split() methods that will generate a 2D array of texture regions, each referencing an equally sized area of the originl TextureRegion/Texture. See AnimationTest.
[added] Animation class for stateless sprite animation via TextureRegions.
--- /dev/null
+package com.badlogic.gdx.graphics;\r
+\r
+import com.badlogic.gdx.Gdx;\r
+\r
+/**\r
+ * A simple helper class to log the frames per seconds\r
+ * achieved. Just invoke the {@link #log()} method in\r
+ * your rendering method. The output will be logged\r
+ * once per second.\r
+ * \r
+ * @author mzechner\r
+ *\r
+ */\r
+public class FPSLogger {\r
+ long startTime;\r
+ \r
+ public FPSLogger() {\r
+ startTime = System.nanoTime();\r
+ }\r
+ \r
+ /**\r
+ * Logs the current frames per second to the console.\r
+ */\r
+ public void log() {\r
+ if(System.nanoTime()-startTime>1000000000) {\r
+ Gdx.app.log("FPSLogger", "fps: " + Gdx.graphics.getFramesPerSecond());\r
+ startTime = System.nanoTime();\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package com.badlogic.gdx.graphics.g2d;\r
+\r
+/**\r
+ * <p>An Animation stores a list of {@link TextureRegion}s representing an\r
+ * animated sequence, e.g. for running or jumping. Each region of an\r
+ * Animation is called a key frame, multiple key frames make up the\r
+ * animation.<p> \r
+ * \r
+ * @author mzechner\r
+ *\r
+ */\r
+public class Animation { \r
+ final TextureRegion[] keyFrames;\r
+ final float frameDuration;\r
+ \r
+ /**\r
+ * Constructor, storing the frame duration and key frames. \r
+ * \r
+ * @param frameDuration the time between frames in seconds.\r
+ * @param keyFrames the {@link TextureRegion}s representing the frames.\r
+ */\r
+ public Animation(float frameDuration, TextureRegion ... keyFrames) {\r
+ this.frameDuration = frameDuration;\r
+ this.keyFrames = keyFrames;\r
+ }\r
+ \r
+ /**\r
+ * Returns a {@link TextureRegion} based on the so called state time. \r
+ * This is the amount of seconds an object has spent in the state this\r
+ * Animation instance represents, e.g. running, jumping and so on. The\r
+ * mode specifies whether the animation is looping or not. \r
+ * @param stateTime the time spent in the state represented by this animation.\r
+ * @param looping whether the animation is looping or not.\r
+ * @return the TextureRegion representing the frame of animation for the given state time.\r
+ */\r
+ public TextureRegion getKeyFrame(float stateTime, boolean looping) {\r
+ int frameNumber = (int)(stateTime / frameDuration);\r
+ \r
+ if(!looping) {\r
+ frameNumber = Math.min(keyFrames.length-1, frameNumber); \r
+ } else {\r
+ frameNumber = frameNumber % keyFrames.length;\r
+ } \r
+ return keyFrames[frameNumber];\r
+ }\r
+}\r
* Draws a rectangle with the top left corner at x,y having the width and height of the region.\r
*/\r
public void draw (TextureRegion region, float x, float y) {\r
- draw(region, x, y, region.getRegionWidth(), region.getRegionHeight());\r
+ draw(region, x, y, Math.abs(region.getRegionWidth()), Math.abs(region.getRegionHeight()));\r
}\r
\r
/**\r
v2 = v + height / texture.getHeight();\r
}\r
}\r
+ \r
+ /**\r
+ * Helper function to create tiles out of this TextureRegion\r
+ * starting from the top left corner going to the left and\r
+ * ending at the bottom right corner. Only complete tiles will\r
+ * be returned so if the region's width or height are not a \r
+ * multiple of the tile width and height not all of the\r
+ * region will be used.\r
+ * \r
+ * @param tileWidth a tile's width in pixels\r
+ * @param tileHeight a tile's height in pixels\r
+ * @return a 2D array of TextureRegions indexed by [row][column].\r
+ */\r
+ public TextureRegion[][] split(int tileWidth, int tileHeight) {\r
+ int x = getRegionX();\r
+ int y = getRegionY();\r
+ int width = getRegionWidth();\r
+ int height = getRegionHeight();\r
+ \r
+ if(width < 0) {\r
+ x = x - width;\r
+ width = -width;\r
+ }\r
+ \r
+ if(height < 0) {\r
+ y = y - height;\r
+ height = -height;\r
+ }\r
+ \r
+ int rows = height / tileHeight;\r
+ int cols = width / tileWidth; \r
+ \r
+ TextureRegion[][] tiles = new TextureRegion[rows][cols]; \r
+ for(int row = 0; row < rows; row++, y += tileHeight) {\r
+ for(int col = 0; col < cols; col++, x += tileWidth) {\r
+ tiles[row][col] = new TextureRegion(texture, x, y, tileWidth, tileHeight);\r
+ }\r
+ }\r
+ \r
+ return tiles;\r
+ }\r
+ \r
+ /**\r
+ * Helper function to create tiles out of the given {@link Texture}\r
+ * starting from the top left corner going to the left and\r
+ * ending at the bottom right corner. Only complete tiles will\r
+ * be returned so if the texture's width or height are not a \r
+ * multiple of the tile width and height not all of the\r
+ * texture will be used.\r
+ * \r
+ * @param texture the Texture\r
+ * @param tileWidth a tile's width in pixels\r
+ * @param tileHeight a tile's height in pixels\r
+ * @return a 2D array of TextureRegions indexed by [row][column].\r
+ */\r
+ public static TextureRegion[][] split(Texture texture, int tileWidth, int tileHeight) {\r
+ TextureRegion region = new TextureRegion(texture);\r
+ return region.split(tileWidth, tileHeight);\r
+ }\r
}\r
public class JoglDebugStarter {\r
\r
public static void main (String[] argv) {\r
- new JoglApplication(new com.badlogic.gdx.tests.TextureDataTest(), "Debug Test", 480, 320, false);\r
+ new JoglApplication(new com.badlogic.gdx.tests.AnimationTest(), "Debug Test", 480, 320, false);\r
}\r
}\r
--- /dev/null
+\r
+package com.badlogic.gdx.tests;\r
+\r
+import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.graphics.FPSLogger;\r
+import com.badlogic.gdx.graphics.GL10;\r
+import com.badlogic.gdx.graphics.Texture;\r
+import com.badlogic.gdx.graphics.g2d.Animation;\r
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;\r
+import com.badlogic.gdx.graphics.g2d.TextureRegion;\r
+import com.badlogic.gdx.math.Vector2;\r
+import com.badlogic.gdx.tests.utils.GdxTest;\r
+\r
+public class AnimationTest extends GdxTest {\r
+\r
+ @Override public boolean needsGL20 () {\r
+ return false;\r
+ }\r
+ \r
+ class Caveman {\r
+ static final float VELOCITY = 20;\r
+ public final Vector2 pos;\r
+ public final boolean headsLeft;\r
+ public float stateTime;\r
+ \r
+ public Caveman(float x, float y, boolean headsLeft) {\r
+ pos = new Vector2().set(x, y);\r
+ this.headsLeft = headsLeft;\r
+ this.stateTime = (float)Math.random();\r
+ } \r
+ \r
+ public void update(float deltaTime) {\r
+ stateTime += deltaTime;\r
+ pos.x = pos.x + (headsLeft?-VELOCITY*deltaTime:VELOCITY*deltaTime);\r
+ if(pos.x < -64) pos.x = Gdx.graphics.getWidth();\r
+ if(pos.x > Gdx.graphics.getWidth() + 64) pos.x = -64;\r
+ }\r
+ }\r
+ \r
+ Animation leftWalk;\r
+ Animation rightWalk;\r
+ Caveman[] cavemen;\r
+ SpriteBatch batch;\r
+ FPSLogger fpsLog;\r
+\r
+ @Override public void create () {\r
+ Texture texture = new Texture(Gdx.files.internal("data/walkanim.png"));\r
+ TextureRegion[] leftWalkFrames = TextureRegion.split(texture, 64, 64)[0];\r
+ TextureRegion[] rightWalkFrames = new TextureRegion[leftWalkFrames.length];\r
+ for(int i = 0; i < rightWalkFrames.length; i++) {\r
+ TextureRegion frame = new TextureRegion(leftWalkFrames[i]);\r
+ frame.flip(true, false);\r
+ rightWalkFrames[i] = frame;\r
+ }\r
+ leftWalk = new Animation(0.25f, leftWalkFrames);\r
+ rightWalk = new Animation(0.25f, rightWalkFrames);\r
+ \r
+ cavemen = new Caveman[100];\r
+ for(int i = 0; i < 100; i++) {\r
+ cavemen[i] = new Caveman((float)Math.random() * Gdx.graphics.getWidth(),\r
+ (float)Math.random() * Gdx.graphics.getHeight(), \r
+ Math.random() > 0.5?true:false);\r
+ }\r
+ batch = new SpriteBatch();\r
+ fpsLog = new FPSLogger();\r
+ }\r
+\r
+ @Override public void render () {\r
+ Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);\r
+ batch.begin();\r
+ for(int i = 0; i < cavemen.length; i++) {\r
+ Caveman caveman = cavemen[i];\r
+ TextureRegion frame = caveman.headsLeft?\r
+ leftWalk.getKeyFrame(caveman.stateTime, true):\r
+ rightWalk.getKeyFrame(caveman.stateTime, true);\r
+ batch.draw(frame, caveman.pos.x, caveman.pos.y);\r
+ }\r
+ batch.end();\r
+ \r
+ for(int i = 0; i < cavemen.length; i++) {\r
+ cavemen[i].update(Gdx.graphics.getDeltaTime());\r
+ }\r
+ \r
+ fpsLog.log();\r
+ }\r
+}\r
\r
import com.badlogic.gdx.tests.ActionTest;\r
import com.badlogic.gdx.tests.AlphaTest;\r
+import com.badlogic.gdx.tests.AnimationTest;\r
import com.badlogic.gdx.tests.AtlasIssueTest;\r
import com.badlogic.gdx.tests.AudioDeviceTest;\r
import com.badlogic.gdx.tests.AudioRecorderTest;\r
public static final Class[] tests = { \r
PixmapTest.class,\r
RotationTest.class,\r
- Gdx2DTest.class, \r
+ Gdx2DTest.class,\r
+ AnimationTest.class,\r
ActionTest.class,\r
AlphaTest.class, \r
AtlasIssueTest.class, \r