LibGDX_4.7: 场景(Screen)
2015-12-07 00:07
316 查看
本文链接: http://blog.csdn.net/xietansheng/article/details/50187415
LibGDX 基础教程(总目录)
LibGDX API 中提供的 Screen 仅仅是一个接口,我们需要自定义场景类实现 Screen 接口,并结合 com.badlogic.gdx.Game 类进行使用,Game 是一个抽象类,直接继承自 Object,并实现了 ApplicationListener 接口(即属于游戏主程序的入口类),Game 可以看做是 Screen 的父节点或游戏框架的最顶层节点,可以将 Screen 添加到 Game 中,Game 负责管理 Screen 和其生命周期方法的调用。
Game,Screen,Stage,Actor 之间的关系如下图所示:
![](https://img-blog.csdn.net/20151205170644774)
Screen 接口中共有下面 7 个方法:
Game 类的实现其实非常简单,为了更好的理解 Game 对 Screen 的处理,下面展示一下 com.badlogic.gdx.Game 类中的源码:
文件名:logo.png (300*50):
![](https://img-blog.csdn.net/20151205170630744)
先引用前面章节自定义的演员类:
开始场景(欢迎界面):
主游戏场景(游戏主界面):
游戏主程序的启动入口类:
温馨提示:对于 Desktop 平台,窗口(屏幕)的大小可以自己手动设置,而程序中使用的是伸展视口(StretchViewport),为了最终显示的内容不会被压扁或拉长,可以将窗口的宽高比设置成和视口世界的宽高比一致。Desktop 平台启动器配置参考如下:
运行结果:
![](https://img-blog.csdn.net/20151205170656360)
LibGDX 基础教程(总目录)
1. 概述
场景(Screen)是游戏框架中舞台(Stage)的父节点,一个场景可以理解为一个游戏界面,类似 Android 中的 Activity,一个游戏由多个场景(界面)组成,通常包括开始界面、游戏/关卡界面、帮助界面等。一个场景中可以包含一个或多个舞台。LibGDX API 中提供的 Screen 仅仅是一个接口,我们需要自定义场景类实现 Screen 接口,并结合 com.badlogic.gdx.Game 类进行使用,Game 是一个抽象类,直接继承自 Object,并实现了 ApplicationListener 接口(即属于游戏主程序的入口类),Game 可以看做是 Screen 的父节点或游戏框架的最顶层节点,可以将 Screen 添加到 Game 中,Game 负责管理 Screen 和其生命周期方法的调用。
Game,Screen,Stage,Actor 之间的关系如下图所示:
2. Screen 的生命周期方法
Screen 的生命周期方法和 ApplicationListener 生命周期方法的调用相似,实际是将 ApplicationListener 委派给了 Screen。查看 Game 类的源码可以很容易看出 Game 对 Screen 的处理。Screen 接口中共有下面 7 个方法:
/** * 当该场景被设置到 Game 中成为 Game 的当前场景时被调用 */ public void show(); public void resize(int width, int height); /** * 当该场景需要被渲染时被调用 */ public void render(float delta); public void pause(); public void resume(); /** * 当有另一个场景被设置为 Game 的当前场景时(即该场景被覆盖/移出当前场景)被调用 */ public void hide(); /** * 当场景需要被释放所有资源时调用, * 注意: 该方法不会自动被调用, 在需要释放场景的所有资源时手动进行调用 */ public void dispose();
Game 类的实现其实非常简单,为了更好的理解 Game 对 Screen 的处理,下面展示一下 com.badlogic.gdx.Game 类中的源码:
package com.badlogic.gdx; import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Screen; /** * Game 实现了 ApplicationListener 接口, 是游戏主程序的启动入口类 */ public abstract class Game implements ApplicationListener { // Game 中的当前需要被渲染的场景 protected Screen screen; @Override public void dispose () { if (screen != null) { // 当应用被销毁时调用一次当前 Screen 的 hide() 方法 screen.hide(); // 注意: 这里没有调用 Screen 的 dispose() 方法, 所以需要在适当时机自己手动调用 } } @Override public void pause () { if (screen != null) { screen.pause(); } } @Override public void resume () { if (screen != null) { screen.resume(); } } @Override public void render () { if (screen != null) { // 游戏被渲染时调用当前 Screen 的 render() 方法, 并将渲染时间步(delta)传递给 screen screen.render(Gdx.graphics.getDeltaTime()); } } @Override public void resize (int width, int height) { if (screen != null) { screen.resize(width, height); } } /** * 设置 Game 的当前需要渲染的场景时; * 先调用之前 Game 中旧的当前场景的 hide() 方法; * 然后调用新设置到 Game 中的当前场景的 show() 方法, 并接着调用一次 resize() 方法; */ public void setScreen (Screen screen) { if (this.screen != null) { this.screen.hide(); } this.screen = screen; if (this.screen != null) { this.screen.show(); this.screen.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); } } public Screen getScreen () { return screen; } }
3. 代码示例
这个示例中除了使用到 badlogic.jpg 图片外,还需要使用到下面这张图片(LibGDX 的官方 logo),保存图片到本地 -> 重命名为 “logo.png” -> 然后复制到 “assets” 资源文件夹中。文件名:logo.png (300*50):
先引用前面章节自定义的演员类:
package com.libgdx.test; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.Actor; /** * 自定义演员 */ public class MyActor extends Actor { private TextureRegion region; public MyActor(TextureRegion region) { super(); this.region = region; setSize(this.region.getRegionWidth(), this.region.getRegionHeight()); } public TextureRegion getRegion() { return region; } public void setRegion(TextureRegion region) { this.region = region; setSize(this.region.getRegionWidth(), this.region.getRegionHeight()); } @Override public void act(float delta) { super.act(delta); } @Override public void draw(Batch batch, float parentAlpha) { super.draw(batch, parentAlpha); if (region == null || !isVisible()) { return; } batch.draw( region, getX(), getY(), getOriginX(), getOriginY(), getWidth(), getHeight(), getScaleX(), getScaleY(), getRotation() ); } }
开始场景(欢迎界面):
package com.libgdx.test; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Screen; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.utils.viewport.StretchViewport; /** * 开始场景(欢迎界面), 实现 Screen 接口 或者 继承 ScreenAdapter 类, ScreenAdapter 类空实现了 Screen 接口的所有方法。<br/> * 这个场景使用 LibGDX 的官方 logo 居中显示 3 秒钟当做是游戏的欢迎界面。 <br/><br/> * * PS: 类似 Screen 这样的有许多方法的接口, 更多时候只需要实现其中一两个方法, 往往会有一个对应的便捷的空实现所有接口方法的 XXAdapter 类, * 例如 ApplicationListener >> ApplicationAdapter, InputProcessor >> InputAdapter */ public class StartScreen implements Screen { // 为了方便与 MainGame 进行交互, 创建 Screen 时将 MainGame 作为参数传进来 private MainGame mainGame; private Texture logoTexture; private Stage stage; private MyActor logoActor; // 渲染时间步累计变量(当前场景被展示的时间总和) private float deltaSum; public StartScreen(MainGame mainGame) { this.mainGame = mainGame; // 在 Screen 中没有 create() 方法, show() 方法有可能被调用多次, 所有一般在构造方法中做一些初始化操作较好 // 创建 logo 的纹理, 图片 logo.png 的宽高为 300 * 50 logoTexture = new Texture(Gdx.files.internal("logo.png")); // 使用伸展视口创建舞台 stage = new Stage(new StretchViewport(MainGame.WORLD_WIDTH, MainGame.WORLD_HEIGHT)); // 创建 logo 演员 logoActor = new MyActor(new TextureRegion(logoTexture)); // 将演员设置到舞台中心 logoActor.setPosition( stage.getWidth() / 2 - logoActor.getWidth() / 2, stage.getHeight() / 2 - logoActor.getHeight() / 2 ); // 添加演员到舞台 stage.addActor(logoActor); } @Override public void show() { deltaSum = 0; } @Override public void render(float delta) { // 累计渲染时间步 deltaSum += delta; if (deltaSum >= 3.0F) { // 开始场景展示时间超过 3 秒, 通知 MainGame 切换场景(启动主游戏界面) if (mainGame != null) { mainGame.showGameScreen(); return; } } // 使用淡蓝色清屏 Gdx.gl.glClearColor(0.75F, 1, 0.98F, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // 更新舞台逻辑 stage.act(); // 绘制舞台 stage.draw(); } @Override public void resize(int width, int height) { } @Override public void pause() { } @Override public void resume() { } @Override public void hide() { } @Override public void dispose() { // 场景被销毁时释放资源 if (stage != null) { stage.dispose(); } if (logoTexture != null) { logoTexture.dispose(); } } }
主游戏场景(游戏主界面):
package com.libgdx.test; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.ScreenAdapter; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.utils.viewport.StretchViewport; /** * 主游戏场景(游戏主界面), 实现 Screen 接口 或者 继承 ScreenAdapter 类 <br/> * 这里就展示一张图片代表游戏主界面 */ public class GameScreen extends ScreenAdapter { private Texture manTexture; private Stage stage; private MyActor manActor; public GameScreen() { // 创游戏人物的纹理, 图片 badlogic.jpg 的宽高为 256 * 256 manTexture = new Texture(Gdx.files.internal("badlogic.jpg")); // 使用伸展视口创建舞台 stage = new Stage(new StretchViewport(MainGame.WORLD_WIDTH, MainGame.WORLD_HEIGHT)); // 创建游戏人物演员 manActor = new MyActor(new TextureRegion(manTexture)); // 添加演员到舞台 stage.addActor(manActor); } @Override public void render(float delta) { // 红色清屏 Gdx.gl.glClearColor(1, 0, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // 更新舞台逻辑 stage.act(); // 绘制舞台 stage.draw(); } @Override public void dispose() { super.dispose(); // 场景被销毁时释放资源 if (stage != null) { stage.dispose(); } if (manTexture != null) { manTexture.dispose(); } } }
游戏主程序的启动入口类:
package com.libgdx.test; import com.badlogic.gdx.Game; /** * 游戏主程序的启动入口类, 要使用场景需要将 MainGame 改为继承 Game 抽象类 */ public class MainGame extends Game { // 视口世界的宽高统使用 480 * 800, 并统一使用伸展视口(StretchViewport) public static final float WORLD_WIDTH = 480; public static final float WORLD_HEIGHT = 800; // 开始场景 private StartScreen startScreen; // 主游戏场景 private GameScreen gameScreen; @Override public void create() { // 创建开始场景 startScreen = new StartScreen(this); // 创建主游戏场景 gameScreen = new GameScreen(); // 设置当前场景为开始场景 setScreen(startScreen); } /** * 开始场景展示完毕后调用该方法切换到主游戏场景 */ public void showGameScreen() { // 设置当前场景为主游戏场景 setScreen(gameScreen); if (startScreen != null) { // 由于 StartScreen 只有在游戏启动时展示一下, 之后都不需要展示, // 所以启动完 GameScreen 后手动调用 StartScreen 的 dispose() 方法销毁开始场景。 startScreen.dispose(); // 场景销毁后, 场景变量值空, 防止二次调用 dispose() 方法 startScreen = null; } } @Override public void dispose() { super.dispose(); // super.dispose() 不能删除, 在父类中还有其他操作(调用当前场景的 hide 方法) // 游戏程序退出时, 手动销毁还没有被销毁的场景 if (startScreen != null) { startScreen.dispose(); startScreen = null; } if (gameScreen != null) { gameScreen.dispose(); gameScreen = null; } } }
温馨提示:对于 Desktop 平台,窗口(屏幕)的大小可以自己手动设置,而程序中使用的是伸展视口(StretchViewport),为了最终显示的内容不会被压扁或拉长,可以将窗口的宽高比设置成和视口世界的宽高比一致。Desktop 平台启动器配置参考如下:
package com.libgdx.test; import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; import com.libgdx.test.MainGame; /** * Desktop 平台启动器 */ public class DesktopLauncher { public static void main(String[] args) { LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); float scale = 0.6F; // 适当改变窗口缩放比以适应自己的电脑屏幕 /* * 窗口(实际屏幕)宽高比设置为 480:800, 与视口世界的宽高比相同, 所以最终显示到屏幕上的内容将不会被压扁或拉长 */ config.width = (int) (480 * scale); // 窗口宽度 config.height = (int) (800 * scale); // 窗口高度 config.resizable = false; // 窗口设置为大小不可改变 new LwjglApplication(new MainGame(), config); } }
运行结果:
相关文章推荐
- javascript制作游戏开发碰撞检测的封装代码
- 跨平台移动WEB应用开发框架iMAG入门教程
- Android游戏开发实践之人物移动地图的平滑滚动处理
- PHP跨平台获取服务器IP地址自定义函数分享
- 跨平台python异步回调机制实现和使用方法
- Libgdx之封装简单的脚本机制
- Libgdx学习笔记:UI之技能冷却按钮
- 游戏服务器端开发要点
- 跨平台音频项目
- tvOS游戏开发系列(SpriteKit)之准备工作(一)
- tvOS游戏开发系列(SpriteKit)之新建tvOS游戏项目(二)
- 开源游戏 “打飞机”
- 开源游戏 “Elvish Bird”
- 开源游戏“2048”IOS移植版
- 游戏开发如何成功
- 【v2.x OGE教程 15】布局相关
- 【v2.x OGE-example 第二节】 实体参数
- HTML5简介
- [转]C++强大背后
- [游戏资讯][转]《反恐精英:全球攻势》要实现跨平台对战