上一讲,我们已经实现了点击play进入游戏界面但仅仅是个黑屏
今天,我们就试着编写代码让它出现游戏的一些简单场景。还是在上一讲的代码基础上,我们创建两个类:World 和 WorldRenderer
1.Word类:
package com.zhf.mylibgdx; /** * 统一管理世界中各个部分 * @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 World(WorldListener listener) { this.listener = listener; } }
2.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(); } /**渲染背景**/ 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(); } }
接下来,就是在GameScreen中调用这两个类,完成框架的连接搭建。
声明:
//游戏场景 World world; WorldRenderer renderer; WorldListener worldListener;
实例化:
//实例化场景 worldListener = new WorldListener() { @Override public void jump () { // Assets.playSound(Assets.jumpSound); } @Override public void highJump () { // Assets.playSound(Assets.highJumpSound); } @Override public void hit () { // Assets.playSound(Assets.hitSound); } @Override public void coin () { // Assets.playSound(Assets.coinSound); } }; world = new World(worldListener); renderer = new WorldRenderer(batcher, world);
调用:在GameScreen的draw()方法中调用
//绘制游戏主场景 renderer.render();
运行一下代码,发现我们的黑屏没有了!
这里我需要再��嗦几句,相机的掌握是比较抽象的,WorldRenderer 中 OrthographicCamera的定义就的得先说说游戏是怎么进行的:为什么要把 WorldRender中的OrthographicCamera 定义10 *15,实际上就是把屏幕320*480 映射成每个单位为32像素。这是因为游戏中的素材基本都是基于32像素为单位构建,同时屏幕的分辨率也可以被分解成以32像素为单位。
游戏中,我们的主角Bob会不断进行跳跃,但是他的最高点始终不会超过屏幕的中点,他停留在最高点的过程中会通过移动所有的物体来造成他看上去好像在往上跳,实际上他一直停留在屏幕中点的高度。同时,我们需要为每一关定义一个长度,也就是,需要‘跳’多高才能到达城堡,顺利通关。并且要准备好整一关的过程中,哪里应该出现什么物体,然后根据Bob到达的高度不停的切换这些物体。
想象一下有一段被垂直放置的胶卷,这就是我们的一个关卡,也就是一个World,它准备好了一个关卡的长度,并且设置好了所有的物体。而我们的Bob和WorldRender中的OrthographicCamera 一开始被放置在胶卷的底部,Bob开始不断的跳跃,当超过屏幕中点的高度时则OrthographicCamera 会被往上移动,并且所有进入OrthographicCamera 的物体都会被绘制。直到到达最高点,或Bob死亡。
所以 WorldRender中的OrthographicCamera 被设置成 10 *15 。
并且而在World类中,定义了两个变量:
public static final float WORLD_WIDTH = 10;
public static final float WORLD_HEIGHT = 15 * 20;
同样的关卡的宽带也被定义为10个单位,与WorldRender中的一致(因为我们不需要在X方向进行移动);而高度定义成15*20 这就是一关的长度,也就是Bob要'跳'的高度。
从上面的分析可以得出,分别设置两个不同 OrthographicCamera ,就是因为不同场景的需求。并且 在WorldRender中的OrthographicCamera 其实也可以被设置成 320*480 只是为了简便,才把单位设为32像素变成 10*15。 所以不管是哪个OrthographicCamera它提供的只是一个映射信息,而这个映射的信息真正的使用者是SpriteBatch,它会根据映射信息的不同来决定究竟要把图片绘制在什么位置上,以及该不该绘制这些元素。
即使GameScreen和WorldRender使用的是同一个SpriteBatch,只要在恰当的时候绑定相应的投影矩阵,两者是互不影响的。
后面说了好多,全是文字,大家先理解着,在下一讲中我们将加入各种对象:Bob、跳板,弹簧、松鼠、金币、城堡,以及源码是如何定义他们的。
源码下载:http://down.51cto.com/data/895165