天气有点冷,早上竟然出奇般的七点多就起床了,呵呵~~ 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)控制交通工具的详细内容...