Android游戏开发框架Libgdx的使用(九)--舞台类的使用

本文使用的libgdx是0.98版本,可能和最新版有一些不同地方。全文内容仅供参考。
 
原文地址:http://blog.sina.com.cn/weyingkj
 
  上一次我们讲解了关于演员类的使用,其实大家都发现了上个程序中我使用了多次的Stage,熟悉libgdx的朋友可能都知道这就是libgdx第二个必须掌握的基本元素------舞台类。舞台类相比于演员类来说,更容易理解,它其实从功能的角度来说就是负责管理演员和Group类的平台,他本身的存在就是为了管理,而不是去负责演出,他就像一个导演一样,只负责管理,具体如何表演,那不是舞台所负责的事情。今天土豆这里就带大家来学习一下舞台类的使用,和上篇博文一样,我们也是通过实现一个游戏中常见的商店系统来学习舞台类。
 
Libgdx游戏引擎(1群):187378034
Libgdx游戏引擎(2群):148848483
Libgdx游戏引擎(3群): 79168470
 
 
1.Stage类
 
API定义:包含拥有层次结构的一个二维场景,场景中有许多演员。期处理视图和分配的输入事件。舞台负责操作视角,和处理分配输入事件。
 
功能作用:一个Stage可以充满整个屏幕。设置视角(一般是浮点型和布尔类型),同时设置阶段内使用的相机,调配 Actor、Group 与 Screen 之间的关系转换(包括坐标)。一个Stage必须负责接收输入事件,同时将它分配给演员。这通常是通过Stage的gdx.input.setinputprocessor来实现。一个inputmultiplexer可用来处理输入事件的不同阶段,即之前或之后。如果一个演员通过返回TRUE从输入的方法中处理一个事件,那么Stage的输入方法也会返回true,导致随后的inputprocessors不接收事件。
 
使用方法:Stage(float width, float height, boolean keepAspectRatio, SpriteBatch batch) ,实例化大家都会,这里我主要讲解下这4个参数。
 
(1)第一个参数:设置舞台的宽度。
 
(2)第二个参数:设置舞台的高度。
 
(3)第三个参数:是负责是否让舞台铺满屏幕,如果这个值是ture的话,舞台的尺寸就是你设置的大        小。如果是false的话,就铺满屏幕。
 
(4)第四个参数:就是传入你所声明的Spirtibatch。
 
方法原理:Stage类中有许多方法,比较常用的有:act()、draw()、addlistener()、clear()、getroot()等方法。由于Stage类是和Actor类一同使用的,所要这些方法都是和演员类有直接的关系。这里我们拿act()方法来举例子,通过看包内的源码,我们可以知道stage调用act方法,实际上是通知这个舞台内所有演员按照一定的规则,有序的调用自身的act()方法,其实stage.act()只是做了一件通知的事情,它通知所有的演员,你们需要调用act()了,有了这个通知所有的演员才去act(),而不是stage去act。这样大家应该更能理解stage其实是负责管理,而不是一个实际的Actor了吧。
 
 
2.功能分析
 
这次我们通过一个游戏中的商店系统来实现多舞台的使用,同时了解舞台是如何切换的。一个简单的游戏商店需要有4个元素:
(1)商店按钮,按钮应该在游戏的画面内部。
(2)商店货架,陈列出售的物品。
(3)商品,出售的商品,点击商品需要有返回效果。
(4)购买结束状态,这里就弹出“购买成功”作为结束状态。
 
使用素材:


3.创建项目
 
我们还是使用上次教程的超级玛丽的例子,这次我们加入一个开始界面,和一个商店系统。
 
(1)首先加入一个开始画面,这里我们使用Image控件,将它铺满屏幕。同时我们再使用一个image控件,作为新游戏按钮,这里土豆只拿了一个图片加入监听的方式,为了节约时间。
 
如图:
 
 
(2)使用一个布尔类型的变量来控制舞台的切换,这里我们就使用GameIsRunning。为了是开始界面的舞台能启动,我们重写button的touchdown方法,将GameIsRunning赋值为true。
 
如图:
 
 
(3)在render()方法中进行判断,然后将openStage画出来。
 
如图:
 


 
(4)通过上面的办法,我们就初步的实现了一个双舞台的切换,首先是在开始舞台上,随后通过点击“新游戏”进入主游戏界面。
 
我们要做的游戏商店,上面也提到了,并不是仅仅有2个舞台,他有3个舞台以上,所以我们需要在主游戏舞台上面,再引入变量,来控制第二、第三个舞台的切换。其实原理是一样的。这里我们引入ShopIsRunning和SuccessIsRunning分别来控制shop舞台和success舞台。
 
如图:
 



(5)切换的原理和上面的一样。
 
如图:
 





(6)加入监听,同时通过重写touchdown方法来修改变量,从而控制舞台切换。
 
如图:
 






(7)游戏初始化和设置图片位置。
 
如图:
 


 
4.完整代码
 
这个例子,只是比较简单的舞台切换,当然了,正常游戏中是不这样设置舞台切换的,这里只是拿最浅显易懂的东西来给大家说明,Stage类的使用和简单的切换,大家千万别以为游戏中就要这么使用。希望大家通过简单的代码能理解Stage类的使用,能明白他的原理就可以了。
 
完整代码:
 
(1)主类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.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
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;
Stage OpenStage;
Mario mario;
Image image;
Image button;
Image OpenImage;
Image shop;
Image rack;//货架
Image coin;
Image heart;
Image buy;
Stage shopMenu;
Stage success;
public static boolean GameIsRunning = false;
public static boolean ShopIsRunning = false;
public static boolean SuccessIsRunning = false;
@Override
public void create() {
//实例化所需元素
show();
//加入监听
setListener();
//设置image坐标
setPosition();
//演员加入舞台
addActor();
}
 
public void show() {
mario = new Mario(100, 190);
Texture tex = new Texture(Gdx.files.internal("data/open.png"));
Texture tex1 = new Texture(Gdx.files.internal("data/shop.png"));
image = new Image(new Texture(Gdx.files.internal("data/13.jpg")));
button = new Image(new TextureRegion(tex,924,0,100,50));
OpenImage = new Image(new TextureRegion(tex, 0, 0, 800, 480));
shop = new Image(new TextureRegion(tex1, 204, 0, 102, 85));
rack = new Image(new TextureRegion(tex1, 0, 85, 510, 350));
heart = new Image(new TextureRegion(tex1, 0, 0, 102, 85));
coin = new Image(new TextureRegion(tex1, 102, 0, 102, 85));
buy = new Image(new TextureRegion(tex1, 510, 0, 255, 255));
stage = new Stage(480, 320, false);
OpenStage = new Stage(480,320,false);
shopMenu = new Stage(480,320,false);
success = new Stage(480,320,false);
}
public void setStage() {
if(GameIsRunning ) {
Gdx.input.setInputProcessor(stage);
if(ShopIsRunning) {
Gdx.input.setInputProcessor(shopMenu);
if(SuccessIsRunning) {
Gdx.input.setInputProcessor(success);
success.addActor(buy);
}
}
}else {
Gdx.input.setInputProcessor(OpenStage);
}
}
 
public void setPosition() {
image.setPosition(0, 170);
button.setPosition(40, 230);
shop.setPosition(290, 60);
OpenImage.setSize(480, 320);
rack.setPosition(0, 0);
rack.setSize(480, 320);
coin.setPosition(50, 50);
heart.setPosition(190, 50);
buy.setPosition(100, 100);
}
public void addActor() {
OpenStage.addActor(OpenImage);
OpenStage.addActor(button);
stage.addActor(image);
stage.addActor(mario);
stage.addActor(mario.buttonL);
stage.addActor(mario.buttonR);
stage.addActor(shop);
shopMenu.addActor(rack);
shopMenu.addActor(coin);
shopMenu.addActor(heart);
}
public void setListener() {
button.addListener(new InputListener() {
 
@Override
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
// TODO Auto-generated method stub
GameIsRunning = true;
return true;
}
});
heart.addListener(new InputListener() {
 
@Override
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
// TODO Auto-generated method stub
SuccessIsRunning = true;
return true;
}
});
coin.addListener(new InputListener() {
 
@Override
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
// TODO Auto-generated method stub
SuccessIsRunning = true;
return true;
}
});
shop.addListener(new InputListener() {
 
@Override
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
// TODO Auto-generated method stub
ShopIsRunning = true;
return super.touchDown(event, x, y, pointer, button);
}
});
}
@Override
public void dispose() {
 
}
public void stageRender() {
if(GameIsRunning) {
stage.act();
stage.draw();
if(ShopIsRunning) {
shopMenu.act();
shopMenu.draw();
if(ShopIsRunning) {
success.act();
success.draw();
}
}
}else {
OpenStage.act();
OpenStage.draw();
}
}
@Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
//创建舞台
setStage();
//渲染舞台
stageRender();
}
 
 
 
@Override
public void resize(int width, int height) {
}
 
@Override
public void pause() {
}
 
@Override
public void resume() {
}
}
 
(2)Mario类中的代码,其实和上个教程一样,并没有修改。
 
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;
}
});
}
}
 
效果图: (同样是视频,方便大家测试)
 
 
 
 
写在最后,关于Stage舞台的使用就介绍到这里了,Stage类是libgdx学习中的基础,其中有许多方法都是非常长重要的,千万记住这不是Stage的全部,土豆这里只是给大家简单的介绍了下,只是给大家引个路,希望大家能自己去多熟悉stage的使用方法。下一篇是是关于libgdx框架中《游戏音乐的使用》的博文,我会介绍下关于游戏音乐libgdx是如何处理的。希望大家理解如果大家有什么问题可以加我QQ:316344618,一起讨论下。
PS: 土豆最近也是做项目,超级忙,博文更新慢了点,
 
                            ------------奋斗小土豆丶
                                                                       
                                   2013 年 4 月 20 日
posted @ 2013-04-20 17:15  奋斗小土豆丶  阅读(712)  评论(0编辑  收藏  举报