Android游戏引擎libgdx使用教程4:舞台和演员的游戏实例

移动开发 Android
演员是游戏设计中常用的一个对象,它接受舞台的统一管理,拥有一些公共的事件,比如触摸,点击,但是同时还有自身的响应和属性;而舞台就是容纳演员的场所。它统一管理所有演员,接受输入,同时提供一个方便的框架操作演员的时间变化。

大家先要有舞台和演员的概念,下面通过一个游戏截图来说明:

Android游戏引擎libgdx使用教程4:舞台和演员的游戏实例

请仔细观察图片中的元素,有些东西是不能动,有些可以动,有些有特效,有些没有,有各种图片,但是其实它们都可以统一称为演员(Actor)。图中用框标出的就是演员。而整个游戏界面就是我们的舞台。

演员是游戏设计中常用的一个对象,它接受舞台的统一管理,拥有一些公共的事件,比如触摸,点击,但是同时还有自身的响应和属性;而舞台就是容纳演员的场所。它统一管理所有演员,接受输入,同时提供一个方便的框架操作演员的时间变化。

Stage类

我们来看一下Stage类:

       protected final Group root;

       protected final SpriteBatch batch;

       protected Camera camera;

它拥有一个Group,一个SpriteBatch,还有一个相机。

SpriteBatch我们在前几篇说过,这里就不再重复了。

Group是一个类,用于容纳和控制演员。但是这里要注意Group本身其实也是继承自Actor。

相机我们这里跳过,以后再说,可以暂时理解成一个控制观察视角和指标转化的工具。

当我们拥有一个演员后就可以调用addActor方法加入舞台。

舞台可以获取输入,但是需要设置。

       Gdx.input.setInputProcessor(stage);

舞台和演员实例分享

下面来个列子,控制一个人物前进。

Android游戏引擎libgdx使用教程4:舞台和演员的游戏实例

控制人物的按钮:

Android游戏引擎libgdx使用教程4:舞台和演员的游戏实例

将所需的图片放到assert中:

Android游戏引擎libgdx使用教程4:舞台和演员的游戏实例

新建三个类:

FirstGame,实现接口ApplicationListener

FirstActor,继承Actor

NarrowButton,继承Actor

先看一下FirstGame

声明一个Stage,然后实例化FirstActor和NarrowButton,将二者加入舞台中,最后设置输入响应为Stage。

  1. package com.cnblogs.htynkn.listener;     
  2. import java.util.Date;     
  3. import java.util.Random;     
  4. import javax.microedition.khronos.opengles.GL;     
  5. import android.util.Log;     
  6. import com.badlogic.gdx.ApplicationListener;     
  7. import com.badlogic.gdx.Gdx;     
  8. import com.badlogic.gdx.graphics.GL10;     
  9. import com.badlogic.gdx.graphics.g2d.BitmapFont;     
  10. import com.badlogic.gdx.scenes.scene2d.Stage;     
  11. import com.cnblogs.htynkn.domain.FirstActor;     
  12. import com.cnblogs.htynkn.domain.NarrowButton;     
  13. public class FirstGame implements ApplicationListener {     
  14. private Stage stage;     
  15. private FirstActor firstActor;     
  16. private NarrowButton button;     
  17. @Override     
  18. public void create() {     
  19. stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),     
  20. true);     
  21. firstActor = new FirstActor("renwu");     
  22. button = new NarrowButton("narrow");     
  23. stage.addActor(firstActor);     
  24. stage.addActor(button);     
  25. Gdx.input.setInputProcessor(stage);     
  26. }     
  27. @Override     
  28. public void dispose() {     
  29. stage.dispose();     
  30. }     
  31. @Override     
  32. public void pause() {     
  33. // TODO Auto-generated method stub     
  34. }     
  35. @Override     
  36. public void render() {     
  37. Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);     
  38. stage.act(Gdx.graphics.getDeltaTime());     
  39. stage.draw();     
  40. }     
  41. @Override     
  42. public void resize(int width, int height) {     
  43. // TODO Auto-generated method stub     
  44. }     
  45. @Override     
  46. public void resume() {     
  47. // TODO Auto-generated method stub     
  48. }     
  49. }   

再看一下FirstActor。

声明一个Texture用于绘制。在构造方法中获取到高度和宽度,以便于后期的hit时间判断。

  1. package com.cnblogs.htynkn.domain;     
  2. import com.badlogic.gdx.Gdx;     
  3. import com.badlogic.gdx.graphics.Texture;     
  4. import com.badlogic.gdx.graphics.g2d.SpriteBatch;     
  5. import com.badlogic.gdx.scenes.scene2d.Actor;     
  6. public class FirstActor extends Actor {     
  7. Texture texture;     
  8. @Override     
  9. public void draw(SpriteBatch batch, float parentAlpha) {     
  10. batch.draw(texture, this.x, this.y);     
  11. }     
  12. @Override     
  13. public Actor hit(float x, float y) {     
  14. if (x > 0 && y > 0 && this.height > y && this.width > x) {     
  15. return this;     
  16. else {     
  17. return null;     
  18. }     
  19. }     
  20. @Override     
  21. public boolean touchDown(float x, float y, int pointer) {     
  22. // TODO Auto-generated method stub     
  23. return false;     
  24. }     
  25. @Override     
  26. public void touchDragged(float x, float y, int pointer) {     
  27. // TODO Auto-generated method stub     
  28. }     
  29. @Override     
  30. public void touchUp(float x, float y, int pointer) {     
  31. // TODO Auto-generated method stub     
  32. }     
  33. public FirstActor(String name) {     
  34. super(name);     
  35. texture = new Texture(Gdx.files.internal("actor1.gif"));     
  36. this.height = texture.getHeight();     
  37. this.width = texture.getWidth();     
  38. }     
  39. }   

NarrowButton中代码绘制部分和上面的以下,主要是有个点击后控制人物行动的问题。

修改touchDown事件:

通过Group获取到FirstActor,控制x值。

  1. public boolean touchDown(float x, float y, int pointer) {     
  2. Actor actor = this.parent.findActor("renwu");     
  3. actor.x += 10;     
  4. return false;     
  5. }   

效果:

Android游戏引擎libgdx使用教程4:舞台和演员的游戏实例

到此为止一个最简单的人物控制我们已经实现了。但是这个有实例还有很多可以改进的地方,比如方向按钮没有点击效果,人物没有移动效果。

我们可以使用Animation来实现。添加一张图片:

Android游戏引擎libgdx使用教程4:舞台和演员的游戏实例

具体的原理我们看一下Animation类:

  1. public class Animation {     
  2. final TextureRegion[] keyFrames;     
  3. public float frameDuration;     
  4. /** Constructor, storing the frame duration and key frames.    
  5. *    
  6. * @param frameDuration the time between frames in seconds.    
  7. * @param keyFrames the {@link TextureRegion}s representing the frames. */     
  8. public Animation (float frameDuration, List keyFrames) {     
  9. this.frameDuration = frameDuration;     
  10. this.keyFrames = new TextureRegion[keyFrames.size()];     
  11. for(int i = 0, n = keyFrames.size(); i < n; i++) {     
  12. this.keyFrames[i] = (TextureRegion)keyFrames.get(i);     
  13. }     
  14. }     
  15. /** Constructor, storing the frame duration and key frames.    
  16. *    
  17. * @param frameDuration the time between frames in seconds.    
  18. * @param keyFrames the {@link TextureRegion}s representing the frames. */     
  19. public Animation (float frameDuration, TextureRegion... keyFrames) {     
  20. this.frameDuration = frameDuration;     
  21. this.keyFrames = keyFrames;     
  22. }     
  23. /** Returns a {@link TextureRegion} based on the so called state time. This is the amount of seconds an object has spent in the    
  24. * state this Animation instance represents, e.g. running, jumping and so on. The mode specifies whether the animation is    
  25. * looping or not.    
  26. * @param stateTime the time spent in the state represented by this animation.    
  27. * @param looping whether the animation is looping or not.    
  28. * @return the TextureRegion representing the frame of animation for the given state time. */     
  29. public TextureRegion getKeyFrame (float stateTime, boolean looping) {     
  30. int frameNumber = (int)(stateTime / frameDuration);     
  31. if (!looping) {     
  32. frameNumber = Math.min(keyFrames.length - 1, frameNumber);     
  33. else {     
  34. frameNumber = frameNumber % keyFrames.length;     
  35. }     
  36. return keyFrames[frameNumber];     
  37. }     
  38. }   

可以看出所谓的动画其实是一张一张的图片不断切换(其实所有的动画都是这个样子的)。

我们构造一个图片列表然后根据事件变动不停取出,重新绘制就形成动画了。

注意一下传入的时间和图片列表大小的问题,修改FirstActor代码如下:

  1. package com.cnblogs.htynkn.domain;     
  2. import com.badlogic.gdx.Gdx;     
  3. import com.badlogic.gdx.graphics.Texture;     
  4. import com.badlogic.gdx.graphics.g2d.Animation;     
  5. import com.badlogic.gdx.graphics.g2d.SpriteBatch;     
  6. import com.badlogic.gdx.graphics.g2d.TextureRegion;     
  7. import com.badlogic.gdx.scenes.scene2d.Actor;     
  8. public class FirstActor extends Actor {     
  9. Texture texture1;     
  10. Texture texture2;     
  11. Animation animation;     
  12. TextureRegion[] walksFrame;     
  13. float stateTime;     
  14. @Override   
  15. public void draw(SpriteBatch batch, float parentAlpha) {     
  16. stateTime += Gdx.graphics.getDeltaTime();     
  17. TextureRegion currentFrame = animation.getKeyFrame(stateTime, true);     
  18. batch.draw(currentFrame, this.x, this.y);     
  19. }     
  20. @Override   
  21. public Actor hit(float x, float y) {     
  22. Gdx.app.log("INFO", x + " " + this.width);     
  23. if (x > 0 && y > 0 && this.height > y && this.width > x) {     
  24. return this;     
  25. else {     
  26. return null;     
  27. }     
  28. }     
  29. @Override   
  30. public boolean touchDown(float x, float y, int pointer) {     
  31. // TODO Auto-generated method stub     
  32. return false;     
  33. }     
  34. @Override   
  35. public void touchDragged(float x, float y, int pointer) {     
  36. // TODO Auto-generated method stub     
  37. }     
  38. @Override   
  39. public void touchUp(float x, float y, int pointer) {     
  40. // TODO Auto-generated method stub     
  41. }     
  42. public FirstActor(String name) {     
  43. super(name);     
  44. texture1 = new Texture(Gdx.files.internal("actor1.gif"));     
  45. texture2 = new Texture(Gdx.files.internal("actor2.gif"));     
  46. this.height = texture1.getHeight();     
  47. this.width = texture1.getWidth();     
  48. TextureRegion region1;     
  49. TextureRegion region2;     
  50. region1 = new TextureRegion(texture1);     
  51. region2 = new TextureRegion(texture2);     
  52. walksFrame = new TextureRegion[30];     
  53. for (int i = 0; i < 30; i++) {     
  54. if (i % 2 == 0) {     
  55. walksFrame[i] = region1;     
  56. else {     
  57. walksFrame[i] = region2;     
  58. }     
  59. }     
  60. animation = new Animation(0.25f, walksFrame);     
  61. }     
  62. }   

效果:

Android游戏引擎libgdx使用教程4:舞台和演员的游戏实例

这里注意一下,为什么我们要Texture转为TextureRegion。这是因为在实际开发中的图片是集成在一起的,比如所有角色要用的图片都是放在一张图里,然后分割截取的,对应的辅助方法TextureRegion.split。

另外我们可以发现NarrowButton和FirstActor中有大量代码重复了,可能有朋友觉得应该提取一下,其实libgdx已经帮我们做了,可以参考

Android游戏引擎libgdx使用教程4:舞台和演员的游戏实例

图片分享:

这里有一些常用的UI控件,估计下一篇可以讲到。

责任编辑:闫佳明 来源: jizhuomi
相关推荐

2013-12-06 10:31:14

Android游戏引擎libgdx教程

2013-12-04 17:27:10

Android游戏引擎libgdx教程

2013-12-04 17:14:57

Android游戏引擎libgdx教程

2013-12-04 13:30:45

Android游戏引擎libgdx教程

2013-12-06 10:12:49

Android游戏引擎libgdx教程

2013-12-06 09:59:53

Android游戏引擎libgdx教程

2013-12-06 10:22:42

Android游戏引擎libgdx教程

2013-12-06 10:35:28

Android游戏引擎libgdx教程

2013-12-04 16:07:27

Android游戏引擎libgdx教程

2013-12-04 16:21:02

Android游戏引擎libgdx教程

2011-07-18 11:39:58

iPhone 游戏 引擎

2011-07-18 12:29:10

2011-07-18 11:23:29

iPhone 游戏 动画

2011-07-18 11:07:12

iPhone 游戏 引擎

2011-07-18 10:53:09

2011-12-12 13:58:11

TinyCoiOSAndroid

2013-04-19 01:42:02

2014-07-15 10:34:14

Android游戏引擎

2013-05-20 15:42:22

2013-06-07 13:20:16

Android开发开源游戏引擎游戏开发
点赞
收藏

51CTO技术栈公众号