5.4、让我们增加玩家

对于这个向导,我们将只是使用一个占位符代替交通工具。我们将在之后载入模型,但那只是没价值的工作,我们想要先让游戏的核心能运作。一个Box是一个好的占位符,因为它是我们交通工具的基础模型。

所以,让我们先增加一个buildPlayer的方法并在initGame中调用它。我们将接着创建一个box做为玩家的几何体并把这个Box  attach到node。这个玩家Node将会是一个类变量,以便我们能在update期间访问它。我将创建一个中心为(0,0,0)和大小为(0.35,0.25,0.5),让它看起来长和宽。Node接着被移到坐标(100,0,100)。我还没设置它的高度,我将在之后才那么做。

private void buildPlayer() {

//box 代替

Box b = new Box("box", new Vector3f(), 0.35f,0.25f,0.5f);

b.setModelBound(new BoundingBox());

b.updateModelBound();

player = new Node("Player Node");

player.setLocalTranslation(new Vector3f(100,0, 100));

scene.attachChild(player);

player.attachChild(b);

player.updateWorldBound();

}

如果你现在运行这个,实际上不会看到player,因为它深陷在terrain下面。我们在update里面设置height,这是因为我们将很快让交通工具在平面上移动,并需要让它保持在terrain上。所以,为了保持box在地面的顶部行驶,增加:

//确保当玩家离开平面时我们不会坠落。

//当我们增加冲突时,fence将做它自己的工作并保持玩家在里面。

float characterMinHeight =

tb.getHeight(player.getLocalTranslation()) +

((BoundingBox)player.getWorldBound()).yExtent;

if(

!Float.isInfinite(characterMinHeight) &&

!Float.isNaN(characterMinHeight)

)

player.getLocalTranslation().y = characterMinHeight;

首先,我们获取玩家当前位置对应的terrain的高度。接着加上BoundingBix的偏移,我们这么做是因为Box位置的点是Box的中心。如果我们没加上偏移,box将有一半沉入地下。我们使用包围对象的BoundingBox去获取对象的高度(yExtent)(但实际上如果你对模型了解得很好,你可以使用值代替)。最后,我们检查获取的高度去确认没有得到一些糟糕的值(非数字、无穷大等)。我们这么做是因为目前我们没做任何事去阻止玩家驾驶出terrain。

我们现在已经在terrain上拥有了玩家!

(现在你可能还看不到这个画面,别急,后面会看到的)

5.5、跟随摄像机(ChaseCamera)

好了,现在我们有了玩家,我们应该有能力移动它。这将是一个第三人称游戏,意味我们在玩游戏的时候能看到自己的玩家(而不是以player的眼睛去看)。所以我们想要摄像头一直指向玩家并跟随他。为了这么做,我们将使用ChaseCamera。ChaseCamera将通过定义它跟随距离的参数一直追踪一个给出的对象。ChaseCamera也定义一些值让它平滑跟随。那就是它不能突然转向玩家。这种突然性的效果当然也是可以定义的。

所以,当我们使用ChaseCamera,视图将一直对着玩家。鼠标将允许camera在玩家四周旋转并一直面向它。鼠标滚轮将允许camera缩放(尽管在这个例子中缩放值很小)。

因此,创建一个buildChaseCamera方法并从initGame中调用它。我们在这里设置ChaseCamera的参数并创建它。ChaseCamera对象将成为一个类变量以致我们能update它(所以把它加到类的顶部)。

我们相对ChaseCamera设置的参数有一些。首先,我们将设置Camera的目标偏移玩家。我们通常想让camera看起来在玩家上一点。所以我们设置偏移(offset)值为(0,玩家的Y*1.5,0).这将让camera指向指向一个在玩家原始高度上面多一半的一个点。下一步,我们将设置滚动(rollout)值。这些值决定了我们能拉近或推远摄像机多少。我这里不想给太多自由,因此这个级别实际上很小。所以我们设置最大为6个单元,而最小为3个单元。下一步我们将设置camera能向上转动多高,在这个例子中为45度,注意是弧度。最后,我们将为camera设置开始起点的球形坐标,roll out为5并升高30度。因为camera在一个“弹簧”系统中,如果交通工具行驶太快时,它能延迟落后一定距离。因此,我们将增加camera能落后的最小和最大值。8和2应该是可以的。

我们在一个hash map中设置这些参数。

private void buildChaseCamera() {

Vector3f targetOffset = new Vector3f();

targetOffset.y =

((BoundingBox)player.getWorldBound()).yExtent*1.5f;

HashMap<String, Object> props = new HashMap<String, Object>();

props.put(ThirdPersonMouseLook.PROP_MAXROLLOUT, "6");

props.put(ThirdPersonMouseLook.PROP_MINROLLOUT, "3");

props.put(

ThirdPersonMouseLook.PROP_MAXASCENT,

""+45*FastMath.DEG_TO_RAD

);

props.put(

ChaseCamera.PROP_INITIALSPHERECOORDS,

new Vector3f(5,0,30*FastMath.DEG_TO_RAD)

);

props.put(ChaseCamera.PROP_TARGETOFFSET, targetOffset);

chaser = new ChaseCamera(cam, player, props);

chaser.setMaxDistance(8);

chaser.setMinDistance(2);

}

我们现在已经设置好了自己的ChaseCamera,但它在调用update方法之前不会产生任何作用。因此在update中加入:

chaser.update(interpolation);

现在,当应用程序运行时,你能看到camera在它初始化的位置并光滑地把镜头拉近直到最大的6个单元。你能接着移动鼠标去围绕box旋转camera,也能滚动鼠标滑轮去将camera拉近或推远一点。那就是所激动的,但没有什么东西可以追踪,因为box只是停在那里。让我们纠正那个。

这里补充一点是作者漏掉的,我们还需要在game的update方面里面加入下面代码以保证camera的位置一直在terrain上面:

//我们不想chase camera走到世界下面,因此让它一直在水平面上2个单元。

if(cam.getLocation().y < (tb.getHeight(cam.getLocation())+2)) {

cam.getLocation().y = tb.getHeight(cam.getLocation()) + 2;

cam.update();

}

5.6、我们自定义的输入处理

我们将创建自己的输入处理器(InputHandler)从而允许我们驾驶交通工具。这个handler的目标是允许我们行驶向前、向后和转向。我想这些控制的键被设置为:WASD。幸运的是,为了做到这个,我们将能使用在jME中构建的action。名字是,KeyNodeForwardAction,KeyNodeBackwardAction,KeyNodeRotateRightAction和KeyNodeRotateLeftAction。这些action处理一个node的旋转和移动,这些都基于速度和传入的时间。

InputAction很直观。你简单将触发器(trigger)赋给action,并把键(key)赋给这些触发器。然后在每次update期间它将检查是否有任何键被按下,如果它们是trigger赋予的按键,那么则让trigger去调用相应的action。

创建一个新的叫做FlagRushInputHandler的类,它继承自InputHandler。这个类将只有2个方法,setKeyBindings和setActions。setKeyBindings将创建KeyBindingManager并赋予W,A,S,D到相应的trigger名字,而setActions将为每个trigger创建InputAction。

FlagRushInputHandler.java

 

import com.jme.input.InputHandler;

import com.jme.input.KeyBindingManager;

import com.jme.input.KeyInput;

import com.jme.input.action.KeyNodeBackwardAction;

import com.jme.input.action.KeyNodeForwardAction;

import com.jme.input.action.KeyNodeRotateLeftAction;

import com.jme.scene.Spatial;

/**

* 游戏的InputHnadler。这控制了一个给出的Spatial

* 允许我们去把它往前移、往后移和左右旋转。

* @author John

*

*/

public class FlagRushInputHandler extends InputHandler {

/**

* 提供用于控制的node。api将处理input的创建

* @param node 我们想移动的那个node

* @param api library将处理input的创建

*/

public FlagRushInputHandler(Spatial node, String api){

setKeyBindings(api);

setActions(node);

}

/**

* 将action类赋给trigger。这些action处理结点前移、后移和旋转

* @param node 用于控制的结点

*/

private void setActions(Spatial node) {

KeyNodeForwardAction forward =

new KeyNodeForwardAction(node,30f);

addAction(forward,"forward",true);

KeyNodeBackwardAction backward =

new KeyNodeBackwardAction(node,15f);

addAction(backward,"backward",true);

KeyNodeRotateLeftAction rotateLeft =

new KeyNodeRotateLeftAction(node,5f);

rotateLeft.setLockAxis(

node.getLocalRotation().getRotationColumn(1)

);

addAction(rotateLeft,"turnLeft",true);

KeyNodeRotateRightAction rotateRight =

new KeyNodeRotateRightAction(node,5f);

rotateRight.setLockAxis(

node.getLocalRotation().getRotationColumn(1)

);

addAction(rotateRight,"turnRight",true);

}

/**

* 创建keyboard对象,当键被按下时允许我们获取键盘的值。

* 它接着设置action作为触发器的基础,如果确认了键被按下(WASD)

* @param api

*/

private void setKeyBindings(String api) {

KeyBindingManager keyboard =

KeyBindingManager.getKeyBindingManager();

keyboard.set("forward", KeyInput.KEY_W);

keyboard.set("backward", KeyInput.KEY_S);

keyboard.set("turnLeft", KeyInput.KEY_A);

keyboard.set("turnRight", KeyInput.KEY_D);

}

}

当这个类真的写完后,我们在自己的游戏中使用。创建一个buildInput方法,由initGame方法调用。这个方法将只有一行:

input = new FlagRushInputHandler(

player,

settings.getRenderer()

);

正如你所猜的,这里input也是类变量。为什么要在类里面呢?因为你将在游戏的update期间调用它的update。

就是那样!不管相信与否,我们现在具有做游戏的条件。Box能被驾驶。现在试试看。注意ChaseCamera将会落后于box一点然后尝试赶上,带来更平滑和真实的感觉。

接下来,我们将改进box的移动以便它能加速和减速。我们也将让它和环境交互得更好。继续收看!

jMonkeyEngine译文 FlagRush5(2)——跟随的摄像机(ChaseCamera)相关推荐

  1. jMonkeyEngine译文 FlagRush1——通过SimpleGame创建你的第一个应用程序

    今天在实验室忙了一下,趁着有空整理了jME的第一篇翻译,献给想在Java3D方面发展的人. 注:本系列教程全部翻译完之后可能会以PDF的形式发布. 如果有什么错误可以留言或EMAIL:kakashi9 ...

  2. jMonkeyEngine译文 FlagRush7(1)——拥抱大地让我们驾驶的不再是Box

    注:本系列教程全部翻译完之后可能会以PDF的形式发布. 如果有什么错误可以到http://blog.csdn.net/kakashi8841留言或EMAIL:kakashi9bi@gmail.com给 ...

  3. 第十章 DirectX 绘制简单场景,地形,天空盒和跟随摄像机(下)

    上个文章里面,我们分别控制胶囊体和摄像机确实比较麻烦,接下来,我将创建一个可以自由移动的模型对象,然后让摄像机跟随其移动和旋转.我们使用VS2019来新建一个项目"D3D_10_Follow ...

  4. Unity 3D系列 摄像机围绕主角进行旋转、缩放

    一.开发环境 Unity版本: 2020.1.0f1 二.建立摄像机结构 1.结构如下图 2.将CameraZoomContainer的Position X坐标设置为12,如图 3.将CameraUp ...

  5. Unity 第三人称 摄像机

    今天主要是简单的模拟下吃鸡游戏的第三人称摄像机的实现. 观察 我们玩过吃鸡手游的都知道,吃鸡的人物跟随的摄像机有两种状态 1. 滑动屏幕的时候,摄像机左右上下移动,人物也会跟随着左右移动,上下抬头低头 ...

  6. Unity Standard Assets 简介之 Cameras

    这篇介绍Cameras资源包. 文件夹下有名为"CameraGuidelines.txt"的说明文档,简要介绍了各个预设的作用和用法. Prefabs文件夹: CctvCamera ...

  7. 历代显卡精彩演示DEMO赏析点评之NV篇

    1 无论ATI还是NVIDIA,每次有新显卡发布都会同时公布一个或者多个美轮美奂的演示DEMO.这些演示DEMO的设计初衷就是通过完美的3D效果征服每一位观众,让大家对新显卡的性能及技术充满憧憬和期待 ...

  8. 毕业时制作的游戏demo

    利用Unity制作的毕业设计 游戏设计整体构思 游戏主体 追逐挑战 炫舞挑战 问答挑战 挑战结束 游戏详细设计 logo的淡出淡入 游戏环境设计 游戏主界面UI设置 道具卡UI 游戏设置界面UI 游戏 ...

  9. U2D愤怒的小鸟学习笔记

    # 官方文档:https://docs.unity3d.com/ScriptReference/index.html Part 1 基本操作 1.左下角Project面板中Assets下创建Image ...

最新文章

  1. change python是什么意思_回溯是什么意思?
  2. datatables ajax刷新数据
  3. bios文件查看工具_何必花钱升级显卡!AMD鸡血BIOS杀到
  4. ASP.NET基础代码备忘
  5. WebClient UI忽略所有增强的开关
  6. php强制对齐,[强迫症福利] 使用 PHPStorm 对齐数组的键值对
  7. node:爬虫爬取网页图片
  8. 【数字图像处理】C++读取、旋转和保存bmp图像文件编程实现
  9. kettle时间维度_MySQL快速生成时间维度表
  10. 插入u盘被计算机限制怎么回事,电脑不读u盘怎么处理,显示本次操作由于计算机的限制而被取消 请您与系统管理员联系,怎门回事?...
  11. 《ParaView Tutorial》
  12. 【高等数学笔记】拉格朗日乘数法(Lagrange Multiplier Method):其实也没那么难嘛
  13. Rate Limiting Algorithms (限流算法)
  14. 0667-6.2.0-什么是Cloudera虚拟私有集群和SDX
  15. 苹果新款笔记本_苹果自研CPU最快下月杀到 搭配史上最便宜Mac笔记本(全文)_苹果 新款MacBook Pro 13英寸_笔记本新闻...
  16. 化工专业和计算机专业哪个好就业前景,2019化学工程与工艺专业就业前景和就业方向分析...
  17. Swift 编程语言入门教程
  18. 解决VS编译中文报错 error C2001:常量中有换行符
  19. UIPATH 收发Outlook邮件
  20. python编程练习-正常血压

热门文章

  1. 解决dataTable在element下的tab切换时表头与内容错位问题
  2. 简单实用,聊聊我常用的 4 款 Pandas 自动数据分析神器
  3. 人工功能计算机,语音人工计算器
  4. 【工具】GIT简单使用
  5. 拼多多校招----最大乘积(python)
  6. windows安装sk-video模块
  7. python找最长的单词,Python 找出英文单词列表(list)中最长单词链
  8. 笔记本蓝牙模块转USB接口方法
  9. the Contextual Loss论文理解
  10. Oracle 12cR1 RAC 在VMware Workstation上安装(上)—OS环境配置