时间:2021-07-01 10:21:17 帮助过:30人阅读
天气有点冷,早上竟然出奇般的七点多就起床了,呵呵~~ 6.4 、 Actions 在第五课,我们创建一个 InputHandler ,它调用了 4 个分开的 InputAction : KeyNodeForwardAction , KeyNodeBackwardAction , KeyTurnLeftAction , KeyTurnRightAction 。我们现
天气有点冷,早上竟然出奇般的七点多就起床了,呵呵~~
在第五课,我们创建一个InputHandler,它调用了4个分开的InputAction:KeyNodeForwardAction,KeyNodeBackwardAction,KeyTurnLeftAction,KeyTurnRightAction。我们现在将编写我们自定义的Action去使用新的Vehicle类。
首先,我们想用一个加速vehicle的action替换KeyNodeForwardAction。我决定创建5个新的InputAction(比之前多了一个)。所以,为了替换keyNodeForwardAction,我们将创建AccelerateAction。
我们不再需要关心action的速度,因为这是由vehicle决定的。我们只需要在action执行的时候更新它的速度,然后基于这个新的速度移动vehicle。
publicvoid 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之外。
publicvoid 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正在后退,所以转弯的效果将相反。
publicvoid performAction(InputActionEvent evt) {
//我们想转不同的方向,这取决于我们往哪个方向行驶
if(vehicle.getVelocity() < 0) {
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();
}
和
publicvoid performAction(InputActionEvent evt) {
if (vehicle.getVelocity() < 0) {
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方法并更新位置。
publicvoid 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的时候发生了什么?我将在下一节课修复和讨论这个瑕疵。是的,我现在给出作业了。
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
*
*/
publicclass 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 用于控制的结点
*/
privatevoid 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
*/
privatevoid 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
publicvoid update(float time) {
if(!isEnabled()) return;
super.update(time);
//我们通常想让摩擦力控制漂移
drift.performAction(event);
}
}
import lesson6.Vehicle;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.math.Vector3f;
publicclass AccelerateAction extends InputAction {
private Vehicle node;
private Vector3f tempVa=new Vector3f();
public AccelerateAction(Vehicle node){
this.node = node;
}
@Override
publicvoid 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);
}
}
import lesson6.Vehicle;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.math.Vector3f;
publicclass BrakeAction extends InputAction {
private Vehicle node;
private Vector3f tempVa=new Vector3f();
public BrakeAction(Vehicle node){
this.node = node;
}
@Override
publicvoid 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);
}
}
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;
publicclass VehicleRotateLeftAction extends InputAction {
//处理旋转的临时变量
privatestaticfinal Matrix3f incr = new Matrix3f();
privatestaticfinal Matrix3f tempMa = new Matrix3f();
privatestaticfinal Matrix3f tempMb = new Matrix3f();
//我们使用Y轴作为上
private Vector3f upAxis = new Vector3f(0,1,0);
//操纵的结点
private Vehicle vehicle;
public VehicleRotateLeftAction(Vehicle vehicle){
this.vehicle = vehicle;
}
@Override
publicvoid performAction(InputActionEvent evt) {
//我们想转不同的方向,这取决于我们往哪个方向行驶
if(vehicle.getVelocity() < 0) {
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();
}
}
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;
publicclass VehicleRotateRightAction extends InputAction {
//用于处理旋转的临时变量
privatestaticfinal Matrix3f incr = new Matrix3f();
privatestaticfinal Matrix3f tempMa = new Matrix3f();
privatestaticfinal Matrix3f tempMb = new Matrix3f();
//用于操作的结点
private Vehicle vehicle;
private Vector3f upAxis = new Vector3f(0, 1, 0);
public VehicleRotateRightAction(Vehicle vehicle){
this.vehicle = vehicle;
}
@Override
publicvoid performAction(InputActionEvent evt) {
if (vehicle.getVelocity() < 0) {
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();
}
}
import lesson6.Vehicle;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.math.Vector3f;
publicclass DriftAction extends InputAction {
private Vehicle vehicle;
private Vector3f tempVa = new Vector3f();
public DriftAction(Vehicle vehicle) {
this.vehicle = vehicle;
}
@Override
publicvoid 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);
}
}
就那样,我们现在已经创建自己的action去允许我们的vehicle以一种更真实的方式运行。这将给我们一种控制玩家执行特性的能力,包括后面的敌人。
下一步,我们将看看改善terrain和图形外观。