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

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

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

在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. powerdesigner 外键生成sql语句设置在创建表里面

    根据情况需要将创建外键表的sql语句生成在创建表的sql语句中,如下设置:

  2. [C/C++] “箭头(->)”和“点号(.)”的区别

    转自:http://blog.csdn.net/gyymen/article/details/4962873 首先介绍一下C++中的结构.对于一个结构: struct MyStruct { int m ...

  3. 【bzoj5070】危险的迷宫 费用流

    题目描述 JudgeOnline/upload/201710/55.doc 输入 第一行是两个整数A与B(1≤A,B≤10),中间用空格分隔,表示该迷宫是A行B列的. 第2行至第A+1行,每行有B个1 ...

  4. Android:Google出品的序列化神器Protocol Buffer使用攻略

    习惯用 Json.XML 数据存储格式的你们,相信大多都没听过Protocol Buffer Protocol Buffer 其实 是 Google出品的一种轻量 & 高效的结构化数据存储格式 ...

  5. BZOJ 1040: [ZJOI2008]骑士 | 在基环外向树上DP

    题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1040 题解: 我AC了 是自己写的 超开心 的 考虑断一条边 这样如果根节点不选答案一定正确 ...

  6. 【BZOJ 2753 滑雪与时间胶囊】

    Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 2843  Solved: 993[Submit][Status][Discuss] Descripti ...

  7. 使用setTimeout延时10ms执行onunloadcancel

    在做Web开发时,我们经常用到页面关闭事件onbeforeunload,可以给用户一个选择放弃关闭的机会,就比如这个博客编辑器.如果用户选择了离开,那么onunload事件自然会触发:但若用户选择了取 ...

  8. Codeforces Round #515 (Div. 3) E. Binary Numbers AND Sum

    E. Binary Numbers AND Sum 题目链接:https://codeforces.com/contest/1066/problem/E 题意: 给出两个用二进制表示的数,然后将第二个 ...

  9. C++开源库,欢迎补充。

    转载自:http://blog.csdn.net/kobejayandy/article/details/8681741 C++在"商业应用"方面,曾经是天下第一的开发语言,但这一 ...

  10. Java Web转发和重定向问题

    0x01:转发情况.转发过程中,只请求一次,request对象设置了之后会一直存在,直到下一次请求. 0x02:重定向情况.会发生两次请求,如果设置了request对象,那么重定向之后,request ...