Android游戏开发框架Libgdx的使用(八)--演员类的使用

本文使用的libgdx是0.98版本,可能和最新版有一些不同地方。全文内容仅供参考。

 
什么是演员的呢?做为LibGdx的开发者来说,这个大家可能都是很熟悉,但是确实很难解释,就像让你解释什么是水平面一样。但是,虽然解释起来很难,但是这并不代表着我们不能理解,比如说,平静的湖水就给人一种水平面的感觉,这样我们就能理解水平面了,同样的,我们可以通过实例是理解什么是演员。所以,为了让大家理解什么是演员,今天土豆这里给大家写一个小例子,来阐述下Actor类的使用。
 
Libgdx游戏引擎(1群):187378034
Libgdx游戏引擎(2群):148848483
Libgdx游戏引擎(3群): 79168470
 
1.Actor类
 
API定义二维场景图中,一个演员拥有的位置,矩形的大小,起点,规模,旋转,和颜色等属性。位置对应且不成比例。演员的位置是相对于演员的父母,它的起点是相对位置,同时可用于缩放和旋转。一个演员也有一个行动,可以操纵的演员在时间段内活动,同时可以加入监听来实现演员接收事件通知
 
功能用法:详情见今天例子
 
演员类是一个项目中的基本元素,就像高楼大厦的砖头一样,都是最基本的元素。比如,超级玛丽这个游戏中,主角Mario就是一个演员,区分其实很简单,一个游戏里面,能进行一定活动同时有一定效果的东西,就是演员。libgdx中演员封装了许多有用的方法,比较常用的有draw、addlistrener、fire、addaction等等,这些方法都是比较常用的,但是这些方法在我们实际的使用中,有许多都是需要重写的,毕竟这只是libgdx给我们的刚,至于具体的使用,就必须由我们去实现。我们通过一个实例来理解一下libgdx中演员类是如何使用的,今天我们就使用一个超级玛丽的简单游戏,来学习一下演员类。
 
使用素材:(1)马里奥图片。(2)场景图片
          
2.功能分析
 
开发一个游戏,首先应该做的就是功能分析。虽然咱们今天做的是一个简单的实例,但是也应该有功能分析。
功能分析如下:
 
(1)实现一个可以移动的人物。
(2)人物在不同时间段是播放不同的动画。
(3)人物分3中状态:左走、右走、空闲
(4)通过2个按钮来实现状态的切换
(5)添加游戏背景。
 
基本今天做的例子,有这些功能就可以了,一个人物移动,有这些基本就够了。
 
3.新建Mario的类
 
(1)在核心代码项目中,新建一个Mario的类,使Mario继承Actor类,然后重写其中的draw方法。
 
如图:
 
(2)声明变量,将坐标、时间、imagebutton、texture、动画、以及枚举类型等变量声明。
 
如图:
 


(3)设置成员变量。
 
如图:
 
(4)动画设置。
 
我将动画设置,都写在了show方法里面,这样其实不太好,很乱思路不清晰,但是一个测试的例子,也就不讲究那么多了,希望同学们还是不要学我这样。
 
如图:

这里重点讲解一下show方法中2个难点:
 
(1)TextureRegion中有一个flip(boolean x, boolean y) 方法,他有2个参数。第一个参数是负责确定是否沿X轴方向翻转,第二个参数是负责确定是否沿Y轴方向翻转
(2)所使用的遍历,因为遍历的是一个二维数组,所以需要先取出来一位数组,然后再遍历取出的一维数组,然后将遍历到的每一个mirror,都进行翻转。


(5)设置按钮同时加入监听。
 
监听的加入方法有很多,土豆这里选择一个比较简单的输入监听同时重写他的touchdown方法,用去判断状态。在touchup方法中,又将Mario的状态赋会Idile,这样比较简单,当然了如果做比较复杂的游戏,还是不推荐这么来使用,这样其实不是太好。
 
如图:
 



PS:这里的touchdown()方法重写的时候一定要将后面的super返回值,一定要修改为return true。因为只有按下方法返回true的情况下,touchup方法才执行,这个需要大家注意,同时还touchup执行的时候要将状态赋会idle。 
 
(6)状态判断与动画选择
 
由于我们将人物动画分为左走的动画、右走的动画、和空闲的动画,这样我们就要在不同的状态下,使用不同的动画,这样才能符合游戏逻辑,我们创建一个check()方法来实现动画和状态的关联。这里我们用currentFrame来给不同的状态赋值,最后将currentFrame画出来,这样可以节省许多代码。
 
如图:
 
 
(7)人物移动。

其实人物移动的原理很简单,但是由于人类思考的误区,总是理解的不很清楚。为了构造人物移动的效果,我们只是在不断变化的坐标的上,绘画出我们做好的动画。这个坐标,我们需要和人物的状态联系起来,人物的状态又是按钮改变的,通过这几种联系,最后就实现了,通过按钮来控制动画的效果了。所以,我们通过update()方法来实现状态和坐标的联系,顺便设置一下“空气墙”,其实就是不让人物超过屏幕。
 
如图:
 
 
(8)draw()方法
 
演员类的draw方法中,默认提供给我们一个SpriteBatch和parentAlpha (透明度的意思),然后我们需要在这里调用判断状态和负责移动的方法,即check()和update()方法。特别注意的是,重写draw方法的时候SpriteBatch中已经给我们写好了 batch.begion 和batch.end方法,所以我们只需要写batch.draw()就可以了。这样我们就可以将我们做好的动画,在绘画出来。
 
如图:
 
 

4.修改MyGdxGame类
 
演员类必须需要使用到舞台,这是大家都知道的,所以我们在主类MyGdxGame里面,添加一个Image控件作为背景,然后将Marion和Mario中的button控件加入到stage中
 
如图:
 


5.完整代码
 
(1)Actor类中的代码:
 
package com.me.mygdxgame;
 
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
 
public class Mario extends Actor{
public static float x ;
public static float y ;
public float statetime;
Texture texture;
TextureRegion currentFrame;
ImageButton buttonL;
ImageButton buttonR;
Animation aniRight;
Animation aniLeft;
Animation aniIdle;
STATE state;
 
enum STATE {
Left,Right,Idel
};
public Mario(float x,float y) {
 
this.x = x;
this.y = y;
this.statetime = 0;
this.show();
state = STATE.Idel;
}
@Override
public void draw(SpriteBatch batch, float parentAlpha) {
// TODO Auto-generated method stub
 
statetime += Gdx.graphics.getDeltaTime();
this.update();
this.check();
batch.draw(currentFrame, x, y);
 
 
}
 
public void update() {
if(state == STATE.Left){
this.x -= 1.5f;
if(this.x < 20) this.x = 20;
}else if (state == STATE.Right) {
this.x +=1.5f;
if(this.x > 400) this.x = 400;
}
this.x = x;
}
public void check() {
if(state == STATE.Left) {
currentFrame = aniLeft.getKeyFrame(statetime, true);
}else if (state == STATE.Right) {
currentFrame = aniRight.getKeyFrame(statetime, true);
}else if (state == STATE.Idel) {
currentFrame = aniIdle.getKeyFrame(statetime, true);
}
}
public void show() {
texture = new Texture(Gdx.files.internal("data/Mario.png"));
TextureRegion[][] spilt = TextureRegion.split(texture, 64, 64);
TextureRegion[][] miror = TextureRegion.split(texture, 64, 64);
for(TextureRegion[] region1 : miror){
for(TextureRegion region2 : region1){
region2.flip(true, false);
}
}
//右
TextureRegion[] regionR = new TextureRegion[3];
regionR[0] = spilt[0][1];
regionR[1] = spilt[0][2];
regionR[2] = spilt[0][0];
aniRight = new Animation(0.1f, regionR);
//左
TextureRegion[] regionL = new TextureRegion[3];
regionL[0] = miror[0][1];
regionL[1] = miror[0][2];
regionL[2] = miror[0][0];
aniLeft = new Animation(0.1f, regionL);
//空闲
TextureRegion[] regionI = new TextureRegion[1];
regionI[0] = spilt[0][0];
 
aniIdle = new Animation(0.1f, regionI);
buttonL = new ImageButton(new TextureRegionDrawable(spilt[1][0]), new TextureRegionDrawable(spilt[1][1]));
buttonR = new ImageButton(new TextureRegionDrawable(miror[1][0]), new TextureRegionDrawable(miror[1][1]));
buttonL.setPosition(20, 20);
buttonR.setPosition(100, 20);
buttonL.addListener(new InputListener(){
 
@Override
public void touchUp(InputEvent event, float x, float y,
int pointer, int button) {
// TODO Auto-generated method stub
state = STATE.Idel;
super.touchUp(event, x, y, pointer, button);
}
 
@Override
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
// TODO Auto-generated method stub
state = STATE.Left;
return true;
}
});
buttonR.addListener(new InputListener(){
@Override
public void touchUp(InputEvent event, float x, float y,
int pointer, int button) {
// TODO Auto-generated method stub
state = STATE.Idel;
super.touchUp(event, x, y, pointer, button);
}
@Override
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
// TODO Auto-generated method stub
state = STATE.Right;
return true;
}
});
}
}
 
(2)MygdxGame类中的代码
 
package com.me.mygdxgame;
 
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
 
public class MyGdxGame implements ApplicationListener {
 
Stage stage;
Mario mario;
Image image;
@Override
public void create() {
 
image = new Image(new Texture(Gdx.files.internal("data/13.jpg")));
image.setPosition(0, 170);
 
stage = new Stage(480, 320, false);
mario = new Mario(100, 190);
Gdx.input.setInputProcessor(stage);
 
stage.addActor(image);
stage.addActor(mario);
stage.addActor(mario.buttonL);
stage.addActor(mario.buttonR);
}
 
@Override
public void dispose() {
 
}
 
@Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
 
}
 
@Override
public void resize(int width, int height) {
}
 
@Override
public void pause() {
}
 
@Override
public void resume() {
}
}
 
效果图:(为了方便大家观看效果,土豆这里就用视频了)
 
 
写在最后,关于演员类》的使用土豆这里就介绍到这里了,希望能为大家理解演员类做到一点启发的作用,其实演员类中还有许多重要的使用方法,希望大家可以去一一探索。下一篇是是关于libgdx框架中《舞台类的使用》的博文,我会介绍下Stage的使用。如果大家有什么问题可以加我QQ:316344618,一起讨论下。PS:土豆最近也是在做项目,不过还是会尽量抽出时间来写教程的。如果太忙的话可能就2天更新一次了,希望大家能谅解。
                            ------------奋斗小土豆丶
                                                                                                          2013 年 4 月 18 日
posted @ 2013-04-18 16:18  奋斗小土豆丶  阅读(597)  评论(0编辑  收藏  举报