每个游戏中都有一些只有程序员自己才知道的控制功能,比如增加金钱,满血复活,无视防御,不死等等。

都是为了方便自己调试而在测试阶段使用的功能。

正如上一章提到的:我们也需要加些只有程序员才知道的控制功能。以方便调试。

在WorldController里加入:

public void update(float deltaTime) {
handleDebugInput(deltaTime);
updateTestObjects(deltaTime);
} private void handleDebugInput(float deltaTime) {
if (Gdx.app.getType() != ApplicationType.Desktop)
return;
// Selected Sprite Controls
float sprMoveSpeed = 5 * deltaTime;
if (Gdx.input.isKeyPressed(Keys.A))
moveSelectedSprite(-sprMoveSpeed, 0);
if (Gdx.input.isKeyPressed(Keys.D))
moveSelectedSprite(sprMoveSpeed, 0);
if (Gdx.input.isKeyPressed(Keys.W))
moveSelectedSprite(0, sprMoveSpeed);
if (Gdx.input.isKeyPressed(Keys.S))
moveSelectedSprite(0, -sprMoveSpeed);
} private void moveSelectedSprite(float x, float y) {
testSprites[selectedSprite].translate(x, y);
}

我们为什么要闲得在update里做判断呢,为什么不用监听器?(用监听器照样可以实现,这里略了,有兴趣可以自己试试)
因为我们需要知道按键是不是一直按着isKeyPressed()。监听器是事件触发的,直接这样做更省事。你可以按A, D, W, S看看现在效果。

当然了,现在我们要实现Reset功能,按R键。因为不用一直判断,所以我们可以直接用监听器了。

public class WorldController extends InputAdapter {
// ...
}

注册监听

private void init () {
Gdx.input.setInputProcessor(this);
initTestObjects();
}

这时候,Libgdx会把所有的input事件都发给注册了的监听器,你接到了input事件,该干嘛干嘛去。比如现在我们要处理R键和空格键。

    @Override
public boolean keyUp(int keycode) {
// Reset game world
if (keycode == Keys.R) {
init();
Gdx.app.debug(TAG, "Game world resetted");
}
// Select next sprite
else if (keycode == Keys.SPACE) {
selectedSprite = (selectedSprite + 1) % testSprites.length;
Gdx.app.debug(TAG, "Sprite #" + selectedSprite + " selected");
}
return false;
}

跑起来,试试这些实现的功能吧。
接下来,我们来玩摄像机:

增加一个类:CameraHelper

package com.packtpub.libgdx.canyonbunny.util;

import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2; public class CameraHelper {
private static final String TAG = CameraHelper.class.getName();
private final float MAX_ZOOM_IN = 0.25f;
private final float MAX_ZOOM_OUT = 10.0f;
private Vector2 position;
private float zoom;
private Sprite target; public CameraHelper() {
position = new Vector2();
zoom = 1.0f;
} public void update(float deltaTime) {
if (!hasTarget())
return;
position.x = target.getX() + target.getOriginX();
position.y = target.getY() + target.getOriginY();
} public void setPosition(float x, float y) {
this.position.set(x, y);
} public Vector2 getPosition() {
return position;
} public void addZoom(float amount) {
setZoom(zoom + amount);
} public void setZoom(float zoom) {
this.zoom = MathUtils.clamp(zoom, MAX_ZOOM_IN, MAX_ZOOM_OUT);
} public float getZoom() {
return zoom;
} public void setTarget(Sprite target) {
this.target = target;
} public Sprite getTarget() {
return target;
} public boolean hasTarget() {
return target != null;
} public boolean hasTarget(Sprite target) {
return hasTarget() && this.target.equals(target);
} public void applyTo(OrthographicCamera camera) {
camera.position.x = position.x;
camera.position.y = position.y;
camera.zoom = zoom;
camera.update();
}
}

可以控制摄像机上下左右移动,拉近放远,跟随目标。
ok,加入到control:

首先申明一个:public CameraHelper cameraHelper;

然后在init里初始化:cameraHelper = new CameraHelper();

接着在update里加上:cameraHelper.update(deltaTime);

最后修改keyup里的控制:

public CameraHelper cameraHelper;

    private void init() {
Gdx.input.setInputProcessor(this);
cameraHelper = new CameraHelper();
initTestObjects();
} public void update(float deltaTime) {
handleDebugInput(deltaTime);
updateTestObjects(deltaTime);
cameraHelper.update(deltaTime);
} @Override
public boolean keyUp(int keycode) {
// Reset game world
if (keycode == Keys.R) {
init();
Gdx.app.debug(TAG, "Game world resetted");
}
// Select next sprite
else if (keycode == Keys.SPACE) {
selectedSprite = (selectedSprite + 1) % testSprites.length;
// Update camera's target to follow the currently
// selected sprite
if (cameraHelper.hasTarget()) {
cameraHelper.setTarget(testSprites[selectedSprite]);
}
Gdx.app.debug(TAG, "Sprite #" + selectedSprite + "selected");
}
// Toggle camera follow
else if (keycode == Keys.ENTER) {
cameraHelper.setTarget(cameraHelper.hasTarget() ? null
: testSprites[selectedSprite]);
Gdx.app.debug(TAG,
"Camera follow enabled: " + cameraHelper.hasTarget());
}
return false;
}

把对摄像机的上下左右控制加上:

private void handleDebugInput(float deltaTime) {
if (Gdx.app.getType() != ApplicationType.Desktop)
return;
// Selected Sprite Controls
float sprMoveSpeed = 5 * deltaTime;
if (Gdx.input.isKeyPressed(Keys.A))
moveSelectedSprite(-sprMoveSpeed, 0);
if (Gdx.input.isKeyPressed(Keys.D))
moveSelectedSprite(sprMoveSpeed, 0);
if (Gdx.input.isKeyPressed(Keys.W))
moveSelectedSprite(0, sprMoveSpeed);
if (Gdx.input.isKeyPressed(Keys.S))
moveSelectedSprite(0, -sprMoveSpeed);
// Camera Controls (move)
float camMoveSpeed = 5 * deltaTime;
float camMoveSpeedAccelerationFactor = 5;
if (Gdx.input.isKeyPressed(Keys.SHIFT_LEFT))
camMoveSpeed *= camMoveSpeedAccelerationFactor;
if (Gdx.input.isKeyPressed(Keys.LEFT))
moveCamera(-camMoveSpeed, 0);
if (Gdx.input.isKeyPressed(Keys.RIGHT))
moveCamera(camMoveSpeed, 0);
if (Gdx.input.isKeyPressed(Keys.UP))
moveCamera(0, camMoveSpeed);
if (Gdx.input.isKeyPressed(Keys.DOWN))
moveCamera(0, -camMoveSpeed);
if (Gdx.input.isKeyPressed(Keys.BACKSPACE))
cameraHelper.setPosition(0, 0);
// Camera Controls (zoom)
float camZoomSpeed = 1 * deltaTime;
float camZoomSpeedAccelerationFactor = 5;
if (Gdx.input.isKeyPressed(Keys.SHIFT_LEFT))
camZoomSpeed *= camZoomSpeedAccelerationFactor;
if (Gdx.input.isKeyPressed(Keys.COMMA))
cameraHelper.addZoom(camZoomSpeed);
if (Gdx.input.isKeyPressed(Keys.PERIOD))
cameraHelper.addZoom(-camZoomSpeed);
if (Gdx.input.isKeyPressed(Keys.SLASH))
cameraHelper.setZoom(1);
} private void moveCamera(float x, float y) {
x += cameraHelper.getPosition().x;
y += cameraHelper.getPosition().y;
cameraHelper.setPosition(x, y);
}

让摄像机跟随,还需要修改render:这样才能保证移动之后的摄像机,更新到了新的位置。

public void renderTestObjects() {
worldController.cameraHelper.applyTo(camera);
batch.setProjectionMatrix(camera.combined);
batch.begin();
for (Sprite sprite : worldController.testSprites) {
sprite.draw(batch);
}
batch.end();
}

按键总结说明:

AWSD控制箱子,空格键选择下一个箱子,R键重置游戏。

上下左右控制摄像机,逗号句号键放大缩小,破折号恢复正常大小。backspace键恢复原点位置,enter键让摄像机跟随控制的箱子。

开心的跑起来耍吧,骚年!

[libgdx游戏开发教程]使用Libgdx进行游戏开发(3)-给游戏添加一些控制功能的更多相关文章

  1. [libGDX游戏开发教程]使用libGDX进行游戏开发(12)-Action动画

    前文章节列表:  使用libGDX进行游戏开发(11)-高级编程技巧   使用libGDX进行游戏开发(10)-音乐音效不求人,程序员也可以DIY   使用libGDX进行游戏开发(9)-场景过渡   ...

  2. [libGDX游戏开发教程]使用libGDX进行游戏开发(1)-游戏设计

    声明:<使用Libgdx进行游戏开发>是一个系列,文章的原文是<Learning Libgdx Game Development>,大家请周知.后续的文章连接在这里 使用Lib ...

  3. 使用Html5+C#+微信 开发移动端游戏详细教程 :(三)使用html5引擎搭建游戏框架

    教程里的案例我们是通过H5游戏引擎开发,目前H5的游戏引擎比较好用的是白鹭,不过对于新手来说白鹭的开发环境和工具使用过于复杂,这里推荐一个国内大神编写的游戏引擎:lufylegend. 直接在页面引入 ...

  4. 微信小程序开发教程 #043 - 在小程序开发中使用 npm

    本文介绍了如何在微信小程序开发中使用 npm 中包的功能,大大提高微信小程序的开发效率,同时也是微信小程序系列教程的视频版更新. 微信小程序在发布之初没有对 npm 的支持功能,这也是目前很多前端开发 ...

  5. PythonWeb开发教程(一),开发之前需要准备什么

    什么是web开发呢,其实就是开发一个网站了.那开发网站需要用到哪些知识呢 1.python基础,因为用python开发的,所以python指定要会,最起码你也得会条件判断,循环,函数,类这些知识: 2 ...

  6. [libgdx游戏开发教程]使用Libgdx进行游戏开发(11)-高级编程技巧 Box2d和Shader

    高级编程技巧只是相对的,其实主要是讲物理模拟和着色器程序的使用. 本章主要讲解利用Box2D并用它来实现萝卜雨,然后是使用单色着色器shader让画面呈现单色状态:http://files.cnblo ...

  7. [libgdx游戏开发教程]使用Libgdx进行游戏开发(10)-音乐和音效

    本章音效文件都来自于公共许可: http://files.cnblogs.com/mignet/sounds.zip 在游戏中,播放背景音乐和音效是基本的功能. Libgdx提供了跨平台的声音播放功能 ...

  8. [libgdx游戏开发教程]使用Libgdx进行游戏开发(2)-游戏框架搭建

    让我们抛开理论开始code吧. 入口类CanyonBunnyMain的代码: package com.packtpub.libgdx.canyonbunny; import com.badlogic. ...

  9. [libgdx游戏开发教程]使用Libgdx进行游戏开发(9)-场景过渡

    本章主要讲解场景过渡效果的使用.这里将用到Render to Texture(RTT)技术. Libgdx提供了一个类,实现了各种常见的插值算法,不仅适合过渡效果,也适合任意特定行为. 在本游戏里面, ...

  10. [libgdx游戏开发教程]使用Libgdx进行游戏开发(7)-屏幕布局的最佳实践

    管理多个屏幕 我们的菜单屏有2个按钮,一个play一个option.option里就是一些开关的设置,比如音乐音效等.这些设置将会保存到Preferences中. 多屏幕切换是游戏的基本机制,Libg ...

随机推荐

  1. 一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。求总共有 多少总跳法?

    首先我们考虑最简单的情况:如果只有1 级台阶,那显然只有一种跳法,如果有2 级台阶,那就有两种跳的方法了:一种是分两次跳,每次跳1 级:另外一种就是一次跳2 级.现在我们再来讨论一般情况:我们把n 级 ...

  2. AGC017D Game on Tree(树型博弈)

    题目大意: 给出一棵n个结点的树,以1为根,每次可以切掉除1外的任意一棵子树,最后不能切的话就为负,问是先手必胜还是后手必胜. 题解: 首先我们考虑利用SG函数解决这个问题 如果1结点有多个子节点,那 ...

  3. [洛谷P4390][BOI2007]Mokia 摩基亚

    题目大意: 维护一个W*W的矩阵,每次操作可以增加某格子的权值,或询问某子矩阵的总权值. 题解:CDQ分治,把询问拆成四个小矩形 卡点:无 C++ Code: #include <cstdio& ...

  4. BZOJ3211 花神游历各国 【树状数组 + 并查集】

    题目 输入格式 输出格式 每次x=1时,每行一个整数,表示这次旅行的开心度 输入样例 4 1 100 5 5 5 1 1 2 2 1 2 1 1 2 2 2 3 1 1 4 输出样例 101 11 1 ...

  5. oracle设置自动清理归档日志脚本

    设置定时自动清理归档日志脚本 root用户下 [root@localhost ~]# mkdir /nstg [root@localhost ~]# cd /nstg/ [root@localhost ...

  6. innodb log file与binlog的区别在哪里?

    Q: innodb log file与binlog的区别在哪里?有人说1.mysql的innodb引擎实际上是包装了inno base存储引擎.而innodb log file是由 inno base ...

  7. 我自己的python开发环境

    1.开发工具 eclipse 所有的版本下载: https://www.eclipse.org/downloads/index-packages.php , 我下载的是比较低的版本:https://w ...

  8. Hibernate 懒加载 错误----no session

    错误: unable to evaluate the expression Method threw 'org.hibernate.LazyInitializa org.hibernate.LazyI ...

  9. mybatis 关系映射

    一:订单商品数据模型 1.数据库执行脚本 创建数据库表代码: 1 CREATE TABLE items ( 2 id INT NOT NULL AUTO_INCREMENT, 3 itemsname ...

  10. org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported解决!

    org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported解决 ...