游戏中物体比较多,这里源码里用了两个类封装了游戏中物体的主要属性,方便游戏中物体的封装。
1.GameObject类:
package com.zhf.mylibgdx; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; /** * 所有的游戏物体都会在一个平面内绘制(或者说在屏幕大小内绘制),那么所有的物体都应该包含一个位置(position) 和一个作用范围(bounds) * @author ZHF * */ public class GameObject { public final Vector2 position; //位置 public final Rectangle bounds; //作用范围 /**postion在这里是指游戏物体的中心点,而bounds中的x ,y 坐标是指这个游戏原素在屏幕坐标系中的作用起点,也就是矩形的左下角顶点**/ public GameObject(float x, float y, float width, float height) { this.position = new Vector2(x, y); this.bounds = new Rectangle(x - width / 2, y - height / 2, width, height); } }
2.DynamicGameObject类
package com.zhf.mylibgdx; import com.badlogic.gdx.math.Vector2; /** * 会移动的游戏物体 * @author ZHF * */ public class DynamicGameObject extends GameObject { //包含了 x, y 轴方向相关的运动信息。 public final Vector2 velocity; //速度 public final Vector2 accel; //加速度 public DynamicGameObject (float x, float y, float width, float height) { super(x, y, width, height); velocity = new Vector2(); accel = new Vector2(); } }
接下来就是让游戏中的物体来分别根据自己的情况去继承它们:
Bob ------> 主角
Castle -----> 城堡
Coin -----> 金币
Platform ------> 平台
Spring -------> 弹簧
Squirrel -------> 空中飞行的松鼠
这里我们先将这六个类写出来,待会实现一下跳板是如何显示出来,我们就大体知道了整个游戏的逻辑了。ok! 上代码!
1.Bob类:
package com.zhf.mylibgdx; /** * 主角 * @author ZHF * */ public class Bob extends DynamicGameObject { //主角状态 public static final int BOB_STATE_JUMP = 0; //跳跃 public static final int BOB_STATE_FALL = 1; //下落 public static final int BOB_STATE_HIT = 2; //碰撞 //速度 public static final float BOB_JUMP_VELOCITY = 11; //跳跃的速度 public static final float BOB_MOVE_VELOCITY = 20; //移动的速度 //宽和高 public static final float BOB_WIDTH = 0.8f; public static final float BOB_HEIGHT = 0.8f; int state; //状态 float stateTime; //状态持时间 public Bob(float x, float y) { super(x, y, BOB_WIDTH, BOB_HEIGHT); //初始化状态 state = BOB_STATE_FALL; stateTime = 0; } /**刷新**/ public void update (float deltaTime) { //x,y轴速度的大小 velocity.add(World.gravity.x * deltaTime, World.gravity.y * deltaTime); //主角当前移动的位置 position.add(velocity.x * deltaTime, velocity.y * deltaTime); bounds.x = position.x - bounds.width / 2; bounds.y = position.y - bounds.height / 2; //跳跃状态 if (velocity.y > 0 && state != BOB_STATE_HIT) { if (state != BOB_STATE_JUMP) { state = BOB_STATE_JUMP; stateTime = 0; } } //下落状态 if (velocity.y < 0 && state != BOB_STATE_HIT) { if (state != BOB_STATE_FALL) { state = BOB_STATE_FALL; stateTime = 0; } } //边界限制 if (position.x < 0) position.x = World.WORLD_WIDTH; if (position.x > World.WORLD_WIDTH) position.x = 0; //状态持续时间 stateTime += deltaTime; } /**撞到松鼠**/ public void hitSquirrel () { velocity.set(0, 0); state = BOB_STATE_HIT; stateTime = 0; } /**撞到跳板**/ public void hitPlatform () { velocity.y = BOB_JUMP_VELOCITY; state = BOB_STATE_JUMP; stateTime = 0; } /**撞到弹簧**/ public void hitSpring () { velocity.y = BOB_JUMP_VELOCITY * 1.5f; state = BOB_STATE_JUMP; stateTime = 0; } }
2.Castle类:
package com.zhf.mylibgdx; /** * 城堡 * @author ZHF * */ public class Castle extends GameObject { //宽和高 public static float CASTLE_WIDTH = 1.7f; public static float CASTLE_HEIGHT = 1.7f; public Castle(float x, float y) { super(x, y, CASTLE_WIDTH, CASTLE_HEIGHT); } }
3.Coin类:
package com.zhf.mylibgdx; /** * 金币 * @author ZHF * */ public class Coin extends GameObject { // 宽和高 public static final float COIN_WIDTH = 0.5f; public static final float COIN_HEIGHT = 0.8f; // 金币的分值 public static final int COIN_SCORE = 10; float stateTime; // 状态持续时间 public Coin(float x, float y) { super(x, y, COIN_WIDTH, COIN_HEIGHT); stateTime = 0; } /**刷新**/ public void update(float deltaTime) { stateTime += deltaTime; } }
4.Platform类:
package com.zhf.mylibgdx; /** * 跳板 * @author ZHF * */ public class Platform extends DynamicGameObject { //宽和高 public static final float PLATFORM_WIDTH = 2; public static final float PLATFORM_HEIGHT = 0.5f; //跳板的类型 public static final int PLATFORM_TYPE_STATIC = 0; //静止 public static final int PLATFORM_TYPE_MOVING = 1; //运动 //跳板的状态 public static final int PLATFORM_STATE_NORMAL = 0; //正常 public static final int PLATFORM_STATE_PULVERIZING = 1; //破碎 public static final float PLATFORM_PULVERIZE_TIME = 0.2f * 4; //破碎所需时间 public static final float PLATFORM_VELOCITY = 2; //跳板移动速度 int type; //类型 :静止、移动 int state; //状态:正常、破碎 float stateTime; //状态持续时间 public Platform (int type, float x, float y) { super(x, y, PLATFORM_WIDTH, PLATFORM_HEIGHT); this.type = type; this.state = PLATFORM_STATE_NORMAL; //正常状态 this.stateTime = 0; //若为移动类型,赋值移动速度 if (type == PLATFORM_TYPE_MOVING) { velocity.x = PLATFORM_VELOCITY; } } /**刷新**/ public void update (float deltaTime) { //移动跳板 if (type == PLATFORM_TYPE_MOVING) { //跳板移动位置 position.add(velocity.x * deltaTime, 0); bounds.x = position.x - PLATFORM_WIDTH / 2; bounds.y = position.y - PLATFORM_HEIGHT / 2; //左边界限制 if (position.x < PLATFORM_WIDTH / 2) { velocity.x = -velocity.x; position.x = PLATFORM_WIDTH / 2; } //右边界限制 if (position.x > World.WORLD_WIDTH - PLATFORM_WIDTH / 2) { velocity.x = -velocity.x; position.x = World.WORLD_WIDTH - PLATFORM_WIDTH / 2; } } //状态持续时间 stateTime += deltaTime; } /**破碎**/ public void pulverize () { state = PLATFORM_STATE_PULVERIZING; stateTime = 0; velocity.x = 0; } }
5.Spring类:
package com.zhf.mylibgdx; /** * 弹簧 * @author ZHF * */ public class Spring extends GameObject { //宽和高 public static float SPRING_WIDTH = 0.3f; public static float SPRING_HEIGHT = 0.3f; public Spring(float x, float y) { super(x, y, SPRING_WIDTH, SPRING_HEIGHT); } }
6.Squirrel类:
package com.zhf.mylibgdx; /** * 松鼠 * @author ZHF * */ public class Squirrel extends DynamicGameObject { //宽和高 public static final float SQUIRREL_WIDTH = 1; public static final float SQUIRREL_HEIGHT = 0.6f; //速度 public static final float SQUIRREL_VELOCITY = 3f; float stateTime = 0; //状态持续时间 public Squirrel (float x, float y) { super(x, y, SQUIRREL_WIDTH, SQUIRREL_HEIGHT); //为松鼠x轴方向赋值 velocity.set(SQUIRREL_VELOCITY, 0); } /**刷新**/ public void update (float deltaTime) { //松鼠移动位置 position.add(velocity.x * deltaTime, velocity.y * deltaTime); bounds.x = position.x - SQUIRREL_WIDTH / 2; bounds.y = position.y - SQUIRREL_HEIGHT / 2; //左边界限制 if (position.x < SQUIRREL_WIDTH / 2) { position.x = SQUIRREL_WIDTH / 2; velocity.x = SQUIRREL_VELOCITY; } //右边界限制 if (position.x > World.WORLD_WIDTH - SQUIRREL_WIDTH / 2) { position.x = World.WORLD_WIDTH - SQUIRREL_WIDTH / 2; velocity.x = -SQUIRREL_VELOCITY; } //状态持续时间 stateTime += deltaTime; } }
以上就是游戏中六个物体类的代码,都十分的相似,代码里都注释了,这里不再一一讲解,可能有些变量没有完全写出,大家还是以源码为主,接下来我们要干的工作就是如何在游戏界面里显示出跳板?
首先,在World类中:
package com.zhf.mylibgdx; import java.util.ArrayList; import java.util.List; import java.util.Random; import com.badlogic.gdx.math.Vector2; /** * 统一管理世界中各个部分 * @author ZHF * */ public class World { /**世界监听器接口**/ public interface WorldListener { //跳跃 public void jump (); //高跳 public void highJump (); //碰撞 public void hit (); //收集金币 public void coin (); } //宽和高 public static final float WORLD_WIDTH = 10; public static final float WORLD_HEIGHT = 15 * 20; //状态 public static final int WORLD_STATE_RUNNING = 0; //运行 public static final int WORLD_STATE_NEXT_LEVEL = 1; //下一关 public static final int WORLD_STATE_GAME_OVER = 2; //游戏结束 //世界监听器 public WorldListener listener; //重力 public static final Vector2 gravity = new Vector2(0, -12); //随机数 public Random rand; //游戏中物体 public final List<Platform> platforms; //跳板 public World(WorldListener listener) { this.listener = listener; this.platforms = new ArrayList<Platform>(); rand = new Random(); generateLevel(); } /**生成关卡中除了Bob外所有的物体**/ private void generateLevel() { float y = Platform.PLATFORM_HEIGHT / 2; float maxJumpHeight = Bob.BOB_JUMP_VELOCITY * Bob.BOB_JUMP_VELOCITY / (2 * -gravity.y); while (y < WORLD_HEIGHT - WORLD_WIDTH / 2) { int type = rand.nextFloat() > 0.8f ? Platform.PLATFORM_TYPE_MOVING : Platform.PLATFORM_TYPE_STATIC; float x = rand.nextFloat() * (WORLD_WIDTH - Platform.PLATFORM_WIDTH) + Platform.PLATFORM_WIDTH / 2; Platform platform = new Platform(type, x, y); platforms.add(platform); y += (maxJumpHeight - 0.5f); y -= rand.nextFloat() * (maxJumpHeight / 3); } } /**刷新界面**/ public void update(float deltaTime, float accelX) { updatePlatforms(deltaTime); } /**刷新跳板**/ private void updatePlatforms(float deltaTime) { int len = platforms.size(); for (int i = 0; i < len; i++) { Platform platform = platforms.get(i); //取出集合中的跳板对象,调用其自身的刷新方法 platform.update(deltaTime); //若状态为破碎状态,将该跳板对象移除出去 if (platform.state == Platform.PLATFORM_STATE_PULVERIZING && platform.stateTime > Platform.PLATFORM_PULVERIZE_TIME) { platforms.remove(platform); len = platforms.size(); } } } }
分析:这里我们还是在上一讲的代码的基础上,增加了platform对象及其实例化,还有与其相关的刷新方法。最重要的是在World的构造方法中,初始化跳板集合,并且调用了 generateLevel()方法来生成关卡中除了Bob外所有的物体。
游戏中物体的创建主要是围绕Platform来生成的。在While循环内,通过不断增加y坐标的值,使用随机数rand 和 物体的内置属性来生成不同的游戏物体。比如,对于Playform 有移动和不移动两种,同时它内置的宽度为2(每单位为32个像素),高度为0.5,结合rand就能达到随机生成Playform的效果。
其次就是WorldRenderer类:
package com.zhf.mylibgdx; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; /** * 用来把每个对象关联相应的图片资源,同时控制相机,实现动画。 * @author ZHF * */ public class WorldRenderer { //宽和高 static final float FRUSTUM_WIDTH = 10; static final float FRUSTUM_HEIGHT = 15; World world; //世界 OrthographicCamera cam; //相机 SpriteBatch batch; //用于绘画 TextureRegion background; //背景图片 public WorldRenderer(SpriteBatch batch, World world) { this.world = world; //OrthographicCamera 被定义成 宽度为10,高度为15,同样的也把相机对准中心点。 this.cam = new OrthographicCamera(FRUSTUM_WIDTH, FRUSTUM_HEIGHT); //它指定了和屏幕一样大小的 OrthographicCamera ,并把相机对准屏幕的中心。 this.cam.position.set(FRUSTUM_WIDTH / 2, FRUSTUM_HEIGHT / 2, 0); this.batch = batch; } /**渲染**/ public void render () { cam.update(); //它的作用都是通过把映射矩阵绑定给SpritBatch,告诉SpritBatch怎么去绘制图形 batch.setProjectionMatrix(cam.combined); //渲染背景 renderBackground(); //渲染游戏中各种元素(Bob,跳板,松鼠,弹簧。。)下一讲中会具体讲到 renderObjects(); } /**渲染游戏中各种物体(Bob,跳板,松鼠,弹簧,城堡,金币)**/ private void renderObjects() { batch.enableBlending(); batch.begin(); //绘制跳板 renderPlatforms(); batch.end(); } /**渲染背景**/ public void renderBackground () { batch.disableBlending(); batch.begin(); batch.draw(Assets.backgroundRegion, cam.position.x - FRUSTUM_WIDTH / 2, cam.position.y - FRUSTUM_HEIGHT / 2, FRUSTUM_WIDTH, FRUSTUM_HEIGHT); batch.end(); } /**渲染跳板**/ private void renderPlatforms () { int len = world.platforms.size(); for (int i = 0; i < len; i++) { Platform platform = world.platforms.get(i); TextureRegion keyFrame = Assets.platform; // if (platform.state == Platform.PLATFORM_STATE_PULVERIZING) { // keyFrame = Assets.brakingPlatform.getKeyFrame(platform.stateTime, Animation.ANIMATION_NONLOOPING); // } batch.draw(keyFrame, platform.position.x - 1, platform.position.y - 0.25f, 2, 0.5f); } } }
分析:
1.在该类中,我们写了一个方法renderObjects()用于渲染游戏中各种物体(Bob,跳板,松鼠,弹簧,城堡,金币)
2.渲染跳板renderPlatforms ()方法里我们取出集合中的跳板对象,对应加载资源,并将其绘制出来。
最后,就是在Asset类中加载跳板资源
声明:
//游戏中各种物体 public static TextureRegion platform; //跳板
实例化:
//游戏中各个物体 platform = new TextureRegion(items, 64, 160, 64, 16); //跳板
运行一下,效果图:(每次运行起来跳板的位置都是随机的)
目前游戏还是没有主人公哦,在下一讲中,我们会加上主人公,同时显示出其他游戏物体,当然还有最重要的游戏碰撞检测,以及场景的移动。
源码下载:http://down.51cto.com/data/896982