好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

jMonkeyEngine译文FlagRush6(2)控制交通工具

天气有点冷,早上竟然出奇般的七点多就起床了,呵呵~~ 6.4 、 Actions 在第五课,我们创建一个 InputHandler ,它调用了 4 个分开的 InputAction : KeyNodeForwardAction , KeyNodeBackwardAction , KeyTurnLeftAction , KeyTurnRightAction 。我们现

天气有点冷,早上竟然出奇般的七点多就起床了,呵呵~~

6.4 、 Actions

在第五课,我们创建一个 InputHandler ,它调用了 4 个分开的 InputAction : KeyNodeForwardAction , KeyNodeBackwardAction , KeyTurnLeftAction , KeyTurnRightAction 。我们现在将编写我们自定义的 Action 去使用新的 Vehicle 类。

首先,我们想用一个加速 vehicle 的 action 替换 KeyNodeForwardAction 。我决定创建 5 个新的 InputAction( 比之前多了一个 ) 。所以,为了替换 keyNodeForwardAction ,我们将创建 AccelerateAction 。

我们不再需要关心 action 的速度,因为这是由 vehicle 决定的。我们只需要在 action 执行的时候更新它的速度,然后基于这个新的速度移动 vehicle 。

public void performAction(InputActionEvent e) {

node .accerate(e.getTime());

Vector3f loc = node .getLocalTranslation();

loc.addLocal(

node .getLocalRotation().getRotationColumn(2, tempVa )

. multLocal ( node .getVelocity()*e.getTime())

);

node .setLocalTranslation(loc);

}

正如你看到的,我们仅仅调用 Vehicle 的 accelerate 方法( AccelerateAction 也在构造期间接收一个 Vehicle 对象,而不是 Node ),然后改变它的移动。

BrakeAction 也一样,除了我们叫它 brake 之外。

public void performAction(InputActionEvent e) {

node .brake(e.getTime());

Vector3f loc = node .getLocalTranslation();

loc.addLocal(

node .getLocalRotation().getRotationColumn(2, tempVa )

.multLocal( node .getVelocity()*e.getTime())

);

node .setLocalTranslation(loc);

}

这些 action 现在将允许我们加速和停止 vehicle 。现在我们需要允许它转弯。正如你可能猜到它和 KeyNodeTurn*Action 类是一样的,除了我们使用 Vehicle 的转弯速度代替 action 的速度。一点不同的是我加入了判断我们的速度是正的还是负的。如果它是正的,那么我们正常工作,但如果它是负的, Vehicle 正在后退,所以转弯的效果将相反。

public void performAction(InputActionEvent evt) {

// 我们想转不同的方向,这取决于我们往哪个方向行驶

if ( vehicle .getVelocity()

incr .fromAngleNormalAxis(

- vehicle .getTurnSpeed() * evt.getTime()

, upAxis

);

} else {

incr . fromAngleNormalAxis (

vehicle .getTurnSpeed() * evt.getTime(),

upAxis

);

}

vehicle .getLocalRotation().fromRotationMatrix(

incr .mult(

vehicle .getLocalRotation()

.toRotationMatrix( tempMa ),

tempMb

)

);

vehicle .getLocalRotation().normalize();

}

public void performAction(InputActionEvent evt) {

if ( vehicle .getVelocity()

incr .fromAngleNormalAxis(

vehicle .getTurnSpeed() * evt.getTime(),

upAxis

);

} else {

incr .fromAngleNormalAxis(

- vehicle .getTurnSpeed() * evt.getTime(),

upAxis

);

}

vehicle . getLocalRotation ().fromRotationMatrix(

incr .mult(

vehicle .getLocalRotation()

.toRotationMatrix( tempMa ),

tempMb

)

);

vehicle .getLocalRotation().normalize();

}

我们最后的 InputAction 将处理 vehicle 的漂移。这个 action 是不同的,因为它不会由 key 触发,但在每次 update 都发生。这将在下一节讲到。现在,我们调用 Vehicle 的 drift 方法并更新位置。

public void performAction(InputActionEvent evt) {

vehicle .drift(evt.getTime());

Vector3f loc = vehicle .getLocalTranslation();

loc.addLocal(

vehicle .getLocalRotation()

. getRotationColumn (2, tempVa )

.multLocal(

vehicle .getVelocity() * evt.getTime()

)

);

vehicle .setLocalTranslation(loc);

}

你可能注意到一堆重复的代码。相当于大多类都做相同的事情,只是调用 vehicle 不同的方法。下一节,我们将清理并优化。

既然我们现在已经有了我们 5 个新的 aciton ,我们需要在 FlagRushHandler 中调用它们。我们将赋予相同的键( WASD )。

所以在 setActions 方法中我们只是创建 4 个移动 action ,传入 vehicle 对象作为参数。

Drift 也被实例化而并没有赋给一个触发器。这是因为我们现在覆盖了 update 方法。 update 调用 super 去检查其他常规 action ,然后调用 drift action 。这确保了当没有键被按下时 drift 漂移。然而,这个逻辑有点瑕疵,这就给读者作为练习去弄清那是什么。一点暗示,当玩家按下 W 或 S 的时候发生了什么?我将在下一节课修复和讨论这个瑕疵。是的,我现在给出作业了。

6.5 、 FlagRushHandler.java

import lesson6.actions.AccelerateAction;

import lesson6.actions.DriftAction;

import lesson6.actions.VehicleRotateLeftAction;

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.KeyNodeRotateRightAction;

/**

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

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

* @author John

*

*/

public class FlagRushInputHandler extends InputHandler {

private DriftAction drift ;

/**

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

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

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

*/

public FlagRushInputHandler(Vehicle node, String api){

setKeyBindings(api);

setActions(node);

}

/**

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

* @param node 用于控制的结点

*/

private void setActions(Vehicle node) {

AccelerateAction forward =

new AccelerateAction(node);

addAction(forward, "forward" , true );

KeyNodeBackwardAction backward =

new KeyNodeBackwardAction(node,15f);

addAction(backward, "backward" , true );

VehicleRotateLeftAction rotateLeft =

new VehicleRotateLeftAction(node);

addAction(rotateLeft, "turnLeft" , true );

KeyNodeRotateRightAction rotateRight =

new KeyNodeRotateRightAction(node,5f);

rotateRight.setLockAxis(

node.getLocalRotation().getRotationColumn(1)

);

addAction(rotateRight, "turnRight" , true );

// 不由 key 触发

drift = new DriftAction(node);

}

/**

* 创建 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 );

}

@Override

public void update( float time) {

if (!isEnabled()) return ;

super .update(time);

// 我们通常想让摩擦力控制漂移

drift .performAction( event );

}

}

6.6 、 AccelerateAction.java

import lesson6.Vehicle;

import com.jme.input.action.InputAction;

import com.jme.input.action.InputActionEvent;

import com.jme.math.Vector3f;

public class AccelerateAction extends InputAction {

private Vehicle node ;

private Vector3f tempVa = new Vector3f();

public AccelerateAction(Vehicle node){

this . node = node;

}

@Override

public void performAction(InputActionEvent e) {

node .accerate(e.getTime());

Vector3f loc = node .getLocalTranslation();

loc.addLocal(

node .getLocalRotation().getRotationColumn(2, tempVa )

.multLocal( node .getVelocity()*e.getTime())

);

node .setLocalTranslation(loc);

}

}

6.7 、 BrakeAction.java

import lesson6.Vehicle;

import com.jme.input.action.InputAction;

import com.jme.input.action.InputActionEvent;

import com.jme.math.Vector3f;

public class BrakeAction extends InputAction {

private Vehicle node ;

private Vector3f tempVa = new Vector3f();

public BrakeAction(Vehicle node){

this . node = node;

}

@Override

public void performAction(InputActionEvent e) {

node .brake(e.getTime());

Vector3f loc = node .getLocalTranslation();

loc.addLocal(

node .getLocalRotation().getRotationColumn(2, tempVa )

.multLocal( node .getVelocity()*e.getTime())

);

node .setLocalTranslation(loc);

}

}

6.8 、 VehicleRotateLeftAction.java

import lesson6.Vehicle;

import com.jme.input.action.InputAction;

import com.jme.input.action.InputActionEvent;

import com.jme.math.Matrix3f;

import com.jme.math.Vector3f;

public class VehicleRotateLeftAction extends InputAction {

// 处理旋转的临时变量

private static final Matrix3f incr = new Matrix3f();

private static final Matrix3f tempMa = new Matrix3f();

private static final Matrix3f tempMb = new Matrix3f();

// 我们使用 Y 轴作为上

private Vector3f upAxis = new Vector3f(0,1,0);

// 操纵的结点

private Vehicle vehicle ;

public VehicleRotateLeftAction(Vehicle vehicle){

this . vehicle = vehicle;

}

@Override

public void performAction(InputActionEvent evt) {

// 我们想转不同的方向,这取决于我们往哪个方向行驶

if ( vehicle .getVelocity()

incr .fromAngleNormalAxis(

- vehicle .getTurnSpeed() * evt.getTime()

, upAxis

);

} else {

incr .fromAngleNormalAxis(

vehicle .getTurnSpeed() * evt.getTime(),

upAxis

);

}

vehicle .getLocalRotation().fromRotationMatrix(

incr .mult(

vehicle .getLocalRotation()

.toRotationMatrix( tempMa ),

tempMb

)

);

vehicle .getLocalRotation().normalize();

}

}

6.9 、 VehicleRotateRightAction.java

import lesson6.Vehicle;

import com.jme.input.action.InputAction;

import com.jme.input.action.InputActionEvent;

import com.jme.math.Matrix3f;

import com.jme.math.Vector3f;

public class VehicleRotateRightAction extends InputAction {

// 用于处理旋转的临时变量

private static final Matrix3f incr = new Matrix3f();

private static final Matrix3f tempMa = new Matrix3f();

private static final Matrix3f tempMb = new Matrix3f();

// 用于操作的结点

private Vehicle vehicle ;

private Vector3f upAxis = new Vector3f(0, 1, 0);

public VehicleRotateRightAction(Vehicle vehicle){

this . vehicle = vehicle;

}

@Override

public void performAction (InputActionEvent evt) {

if ( vehicle .getVelocity()

incr .fromAngleNormalAxis(

vehicle .getTurnSpeed() * evt.getTime(),

upAxis

);

} else {

incr .fromAngleNormalAxis(

- vehicle .getTurnSpeed() * evt.getTime(),

upAxis

);

}

vehicle .getLocalRotation().fromRotationMatrix(

incr .mult(

vehicle .getLocalRotation()

.toRotationMatrix( tempMa ),

tempMb

)

);

vehicle .getLocalRotation().normalize();

}

}

6.10 、 DriftAction.java

import lesson6.Vehicle;

import com.jme.input.action.InputAction;

import com.jme.input.action.InputActionEvent;

import com.jme.math.Vector3f;

public class DriftAction extends InputAction {

private Vehicle vehicle ;

private Vector3f tempVa = new Vector3f();

public DriftAction(Vehicle vehicle) {

this . vehicle = vehicle;

}

@Override

public void performAction(InputActionEvent evt) {

vehicle .drift(evt.getTime());

Vector3f loc = vehicle .getLocalTranslation();

loc.addLocal(

vehicle .getLocalRotation()

.getRotationColumn(2, tempVa )

.multLocal(

vehicle .getVelocity() * evt.getTime()

)

);

vehicle .setLocalTranslation(loc);

}

}

6.11 、总结

就那样,我们现在已经创建自己的 action 去允许我们的 vehicle 以一种更真实的方式运行。这将给我们一种控制玩家执行特性的能力,包括后面的敌人。

下一步,我们将看看改善 terrain 和图形外观。

查看更多关于jMonkeyEngine译文FlagRush6(2)控制交通工具的详细内容...

  阅读:42次