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

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

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

在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. asp.net中的cookie

    一.cookie导读,理解什么是cookie 1.什么是cookie:cookie是一种能够让网站服务器把少量数据(4kb左右)存储到客户端的硬盘或内存.并且读可以取出来的一种技术. 2.当你浏览某网 ...

  2. [fzu 2282]置换不动点大于等于k的排列数

    题目链接:http://acm.fzu.edu.cn/problem.php?pid=2282 编号1~n的置换,不动点个数大于等于k的方案数. 参考百度百科错排公式,可以知道长度为n,每个数都不在自 ...

  3. Codeforces Round #524 (Div. 2) A. Petya and Origami

    A. Petya and Origami 题目链接:https://codeforc.es/contest/1080/problem/A 题意: 给出n,k,k表示每个礼品里面sheet的数量(礼品种 ...

  4. c++ STL(2)

    Vector: #include "stdafx.h" #include<iostream> #include<vector> #include<al ...

  5. 问题总结——window平台下grunt\bower安装后无法运行的问题

    一.问题: 安装grunt或者bower后,在cmd控制台运行grunt -version 或者 bower -v会出现:“xxx不是内部或外部命令,也不是可运行的程序或批处理文件”,

  6. python最简单发送邮件

    #!/usr/bin/env python #coding:utf8 #Author:lsp #Date:下午5:51:13 #Version:0.1 #Function: #导入smtplib和MI ...

  7. 【BZOJ】1708: [Usaco2007 Oct]Money奶牛的硬币

    [算法]DP [题解] 如果每个排列算一种,则令f[i]表示凑成面值为i的方案数,容易推出f[i]+=f[i-a[j]]. 现在是每个组合才算一种,令f[i][j]第二维表示只使用前j种面值,f[i] ...

  8. NYOJ 284 坦克大战 (广搜)

    题目链接 描述 Many of us had played the game "Battle city" in our childhood, and some people (li ...

  9. bzoj 1066 最大流

    将每个石柱拆成两个点,分别是进入的和出去的,两个点之间连石柱的高度 然后每个出去的点连别的石柱的进去的点, 源点连所有蜥蜴所在柱子,每个能跳出去的连汇点,然后最大流就行了 /************* ...

  10. 【Python实例一】使用minidom读取xml文件

    前言:最近刚在廖雪峰老师的网站里学习了Python的基础内容,想着循序渐进地找点实例练练手,网上看到有很多相关资料,决定针对感兴趣的内容实际编码实践一下,昨天刚好看到有关使用Python来读取XML文 ...