Libgdx专题系列:实例篇 打飞机
Posted 吴佳峻
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Libgdx专题系列:实例篇 打飞机相关的知识,希望对你有一定的参考价值。
声明:
本系列文章使用的Libgdx版本均为0.99版本
Libgdx游戏开发交流群 323876830
最近打飞机游戏比较火, 但是这个游戏本身的确没啥好说的, 比较简单, 火的原因可能跟微信平台有关吧,也许还有他本身的意思。 哈哈。
但是对于使用Libgdx练手,算是个好的例子了,四五天时间基本上可以搞定了,这里帖出来自己制作的过程 , 对于新手来说也算是个帮助。
先上截图看看效果吧
声明:以上游戏中用到的图片资源来自于网络,如果冒犯,请告诉我,我会替换掉, 不会用于商用
现在来说说这个游戏有哪些需要说明的地方吧。 也是实际Libgdx开发中,注意的。 如果不合适的, 望指正, 再改进。
图片资源规格
这里使用的图片来自于网络,基本上不是2的幂次方的宽和高,所以使用了opengl2.0,使用手机在2.2以上
菜单界面
包含了背景按钮什么的, 这里使用UI组件就好了,自定义了一个敌机的actor,用于他的动画展示
private Image bg;
private Image logo;
private ImageButton start;
private Image player;
private EnemyPlane enemy1;
private EnemyPlane enemy2;
这里用到了Action的组合,用户敌机和我机的规定路径动作,例如敌机2
enemy2.setPosition(-enemy2.getWidth(),
Gdx.graphics.getHeight() / 4f * 2);// 2/4
MoveByAction enemy2MoveByAction = Actions.moveBy(
Gdx.graphics.getWidth() + enemy2.getWidth(), 0, 4);// 向右走动
MoveToAction enemy2MoveToAction = Actions.moveTo(
-enemy1.getWidth(),
Gdx.graphics.getHeight() / 4f * 2, 0);// 返回
SequenceAction enemy2SequenceAction = Actions.sequence(
enemy2MoveByAction, enemy2MoveToAction);//序列化这两个动作
DelayAction enemy2DelayAction = Actions.delay(2, enemy2SequenceAction);//延迟2s
enemy2.addAction(Actions.forever(enemy2DelayAction));// 循环动作
enemy2.setOrigin(enemy2.getWidth()/2f, enemy2.getHeight()/2f);//设置中心点
enemy2.setRotation(90);//逆时针旋转90°
游戏界面
游戏界面包含了我机、敌机、我机炮弹、敌机炮弹、爆炸、分数显示等
这里的对象没有继承actor,也没有使用stage,其实刚开始是使用这个的,但是由于对象的管理和碰撞检测方便,自己实现了这些绘制逻辑。
GameObject
这是所有游戏对象的超类, 主要保存一些坐标,碰撞区域,状态等信息
private float x;
private float y;
private float width;
private float height;
protected float stateTime;
protected int state;
protected CollisionGeometry geometry;// 碰撞区域集合,相对坐标
敌机,我机,爆炸,子弹
这里都是继承GameObject,实现自己的逻辑和绘制部分,对于碰撞后的处理等操作
例如敌机
private GameScreen screen;
private Texture texture;
private Animation animation;
private float stateTime;
private Vector2 speed;
private int fireNum;
在update和draw中实现自己的逻辑和绘制部分
public void update()
public void draw(SpriteBatch batch)
背景的移动
这里刚开始是使用uv变换, 滚动图片的方式实现,但是没有实现成功, uv超过1就出现拉伸现象,没有循环展示,
Texture设置成repeat也不行, 有谁可以实现的可以告诉我下。谢谢啦 。所以我就换了种方式,基本原理是绘制纹理两次,
有一个y来动态改变绘制的位置,也很简单。
private float deltaY;
spriteBatch.draw(bgTexture, 0, deltaY % Config.HEIGHT, Config.WIDTH,
Config.HEIGHT, 0, 1, 1, 0);// u v u2 v2
spriteBatch.draw(bgTexture, 0, Config.HEIGHT + deltaY % Config.HEIGHT,
Config.WIDTH, Config.HEIGHT, 0, 1, 1, 0);// u v u2 v2
对象的管理
这里使用了Libgdx的Array和Pool,基本原理是 把用到的放到array里面,把不用的放到pool里,这样可以节省频繁释放的开销,
有点数据库连接池的味道。
private final Pool<PlayerBullet> playerBulletPool;// 主角子弹池
private final Pool<Enemy> enemyPool;// 敌人池
private final Pool<EnemyBullet> enemyBulletPool;// 敌人子弹池
private final Pool<Explode> explodePool;// 爆炸池
private Array<PlayerBullet> playerBulletList;
private Array<Enemy> enemyList;
private Array<EnemyBullet> enemyBulletList;
private Array<Explode> explodeList;
对象的碰撞
这里使用了Colliders和CollisionGeometry两个类,来处理碰撞,配合array使用,非常方便,碰撞后,
会回调,我们可以在里面进行逻辑处理。
例如
Colliders.collide(player, enemyList, playerEnemyCollisionHandler);
Colliders.removeOutOfBounds(playerBulletPool, playerBulletList,
roomBounds);
Colliders.removeMarkedCollisions(enemyPool, enemyList,
enemyRemovalHandler);
Handler的处理
private RemovalHandler<Enemy> enemyRemovalHandler = new RemovalHandler<Enemy>()
@Override
public void onRemove(Enemy t)
notifier.onEnemyDestroyed(t);
;
分数
分数的显示这里使用了ttf字库,具体的使用方法是
加入gdx-freetype.jar包,和libgdx-freetype.so文件
使用
private FreeTypeFontGenerator generator;
private FreeTypeBitmapFontData fontData;
private BitmapFont mScoreFont;
generator = new FreeTypeFontGenerator(
Gdx.files.internal("font/font.ttf"));
fontData = generator.generateData(40,
FreeTypeFontGenerator.DEFAULT_CHARS, false);
mScoreFont = new BitmapFont(fontData, fontData.getTextureRegion(),
false);
绘制
mScoreFont.setColor(Color.BLACK);
mScoreFont.draw(spriteBatch, "score:" + score, 100, 100);
mScoreFont.setColor(Color.WHITE);
mScoreFont.draw(spriteBatch, "score:" + score, 100 - 5, 100 + 5);
这里为什么绘制两遍呢,目的是想让他有个不同颜色重叠的效果。
Screen切换
当我们跳到暂停界面,而又想看到我们的游戏界面需要怎么做呢?
这里可以让PauseScreen界面保留一个GameScreen的引用 , 绘制的时候,绘制就行了, 不要执行逻辑就行了。
gameScreen.draw(delta);
stage.act(delta);
stage.draw();
这里就牵涉到个问题, 事件触摸的问题, 有两个界面接受事件, 这里我们可以设置事件为我们的界面处理
//舞台响应事件
Gdx.input.setInputProcessor(stage);
当我们回到游戏界面的时候, 在设置回去就ok了。
监听事件
这里有个WorldListener和WorldNotifier来监听我机碰撞、敌机销毁等事件,可以播放音乐,添加爆炸等等。
public interface WorldListener
public void onPlayerFired (Player player);
public void onPlayerHit (Player player);
public void onEnemyFired (Enemy enemy);
public void onEnemyDestroyed (Enemy enemy);
可以注册多个, 实现不同的目的,这样逻辑也分的很清楚。
好了, 基本上就这样了, 有什么问题,可以留言反馈。
PS:
1.这里有人对碰撞的那个Colliders和CollisionGeometry感兴趣, 这里我上传了一个官网的机器人游戏项目,可以参考下
下载地址 http://download.csdn.net/detail/wu928320442/6771707
2.Pool的概念,可以参考Api解释,不难理解的
应广大同学的对于源码的关注,代码我已经上传了, 希望对你有所帮助 下载地址
http://download.csdn.net/detail/wu928320442/6777211
转载请链接原文链接地址:http://blog.csdn.net/wu928320442/article/details/17578125
以上是关于Libgdx专题系列:实例篇 打飞机的主要内容,如果未能解决你的问题,请参考以下文章