A sidescroller action fighting MMO game with 3-D features and modern graphics engine.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Rabi-bounce-bounce-rabi/src/mygame/control/PlayableCharacter.java

275 lines
11 KiB

package mygame.control;
import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.collision.CollisionResults;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.Savable;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.network.Message;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.control.Control;
import java.io.IOException;
import static mygame.Main.level;
import static mygame.Main.main;
import mygame.server.ServerMain.PlayerActionMessage;
import mygame.server.ServerMain.PlayerPositionMessage;
import mygame.server.ServerMain.ServerMessage;
public class PlayableCharacter extends AbstractControl implements Savable, Cloneable, ActionListener, AnalogListener, AnimEventListener {
float speed = 10.0f;
float rotation_time = 3f;
float current_time = 0.0f;
Quaternion prevRot;
boolean walkingForward = false;
boolean walkingBackward = false;
boolean strafingLeft = false;
boolean strafingRight = false;
boolean moving = false;
AnimChannel channel;
//AnimChannel channel_lowerbody;
AnimControl control;
PhysicsControl physics;
Vector3f walkDirection;
// empty serialization constructor
/** This method is called when the control is added to the spatial,
* and when the control is removed from the spatial (setting a null value).
* It can be used for both initialization and cleanup.
*/
@Override
public void setSpatial(Spatial spatial) {
super.setSpatial(spatial);
if (spatial!=null) {
//control = spatial.getControl(BetterCharacterControl.class);
Node myNode = (Node)spatial;
physics = new PhysicsControl(
0.1f,
-0.25f,
5f
);
myNode.addControl(physics);
control = (((Node)spatial).getChild(0)).getControl(AnimControl.class);
//System.out.println(control.getAnimationNames());
control.addListener(this);
channel = control.createChannel();
channel.setAnim("stand");
channel.setLoopMode(LoopMode.Cycle);
/*channel_lowerbody = control.createChannel();
channel_lowerbody.addBone("hip.right");
channel_lowerbody.addBone("hip.left");*/ //There is no strafing animation
main.getInputManager().addMapping("WalkForward", new KeyTrigger(KeyInput.KEY_W));
main.getInputManager().addMapping("WalkBackward", new KeyTrigger(KeyInput.KEY_S));
main.getInputManager().addMapping("StrafeLeft", new KeyTrigger(KeyInput.KEY_A));
main.getInputManager().addMapping("StrafeRight", new KeyTrigger(KeyInput.KEY_D));
main.getInputManager().addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
main.getInputManager().addListener(this, "WalkForward");
main.getInputManager().addListener(this, "WalkBackward");
main.getInputManager().addListener(this, "StrafeRight");
main.getInputManager().addListener(this, "StrafeLeft");
main.getInputManager().addListener(this, "Jump");
} else {
main.getInputManager().removeListener(this);
}
}
/** Implement your spatial's behaviour here.
* From here you can modify the scene graph and the spatial
* (transform them, get and set userdata, etc).
* This loop controls the spatial while the Control is enabled.
*/
@Override
protected void controlUpdate(float tpf){
//System.out.println(((Geometry)(((Node)((Node)spatial).getChild(0)).getChild(0))).getName()); //Possibility of using geometry node names.
/*if (this instanceof NetworkPlayableCharacter) {
System.out.println("1:"+getWalkDirection()+"Moving:"+moving+"/"+strafingLeft+"/"+strafingRight+"/"+walkingBackward+"/"+walkingForward);
}*/
if (moving) {
if (!channel.getAnimationName().equalsIgnoreCase("Walk")) {
channel.setAnim("Walk");
channel.setLoopMode(LoopMode.Loop);
}
moving=false;
if (this instanceof NetworkPlayableCharacter) {
walkDirection = getWalkDirection((Vector3f)spatial.getUserData("lastCamDir"),(Vector3f)spatial.getUserData("lastCamLeftDir"));
} else {
walkDirection = getWalkDirection(main.getCamera().getDirection(),main.getCamera().getLeft());
}
/*if (this instanceof NetworkPlayableCharacter) {
System.out.println(" 2:"+getWalkDirection()+"Moving:"+moving+"/"+strafingLeft+"/"+strafingRight+"/"+walkingBackward+"/"+walkingForward);
}*/
if (moving) {
SmoothMoveWalk(walkDirection, tpf);
//Message msg = new PlayerPositionMessage(spatial.getLocalTranslation());
//main.client.send(msg);
} else {
channel.setAnim("stand");
channel.setLoopMode(LoopMode.DontLoop);
}
}
//isOnGround();
}
private void SmoothMoveWalk(Vector3f walkDirection, float tpf) {
walkDirection.multLocal(speed).multLocal(tpf);
spatial.move(walkDirection);
/*if (this instanceof NetworkPlayableCharacter) {
System.out.println("Moving. My speed is "+speed+" walkDir is "+walkDirection);
}*/
Quaternion q = new Quaternion().fromAngleAxis((float)FastMath.atan2(walkDirection.x,walkDirection.z),Vector3f.UNIT_Y);
Quaternion q2 = spatial.getLocalRotation();
q2.slerp(q,Math.min(current_time/rotation_time,1));
spatial.setLocalRotation(q2);
current_time+=tpf;
}
@Override
public Control cloneForSpatial(Spatial spatial){
final PlayableCharacter control = new PlayableCharacter();
/* Optional: use setters to copy userdata into the cloned control */
// control.setIndex(i); // example
control.setSpatial(spatial);
return control;
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp){
}
@Override
public void read(JmeImporter im) throws IOException {
super.read(im);
}
@Override
public void write(JmeExporter ex) throws IOException {
super.write(ex);
}
@Override
public void onAction(String name, boolean isPressed, float tpf) {
switch (name) {
case "StrafeLeft":{
current_time = 0.0f;
prevRot = spatial.getLocalRotation();
strafingLeft = isPressed;
moving = true;
if (!(this instanceof NetworkPlayableCharacter)) { //Only send if this is the source client.
PlayerActionMessage action = new PlayerActionMessage(name,Boolean.toString(isPressed),main.client.getId(),spatial.getLocalTranslation(),spatial.getLocalRotation(),main.getCamera().getDirection(),main.getCamera().getLeft());
main.client.send(action);
}
}break;
case "StrafeRight":{
current_time = 0.0f;
prevRot = spatial.getLocalRotation();
strafingRight = isPressed;
moving = true;
if (!(this instanceof NetworkPlayableCharacter)) { //Only send if this is the source client.
PlayerActionMessage action = new PlayerActionMessage(name,Boolean.toString(isPressed),main.client.getId(),spatial.getLocalTranslation(),spatial.getLocalRotation(),main.getCamera().getDirection(),main.getCamera().getLeft());
main.client.send(action);
}
}break;
case "WalkBackward":{
current_time = 0.0f;
prevRot = spatial.getLocalRotation();
walkingBackward = isPressed;
moving = true;
if (!(this instanceof NetworkPlayableCharacter)) { //Only send if this is the source client.
PlayerActionMessage action = new PlayerActionMessage(name,Boolean.toString(isPressed),main.client.getId(),spatial.getLocalTranslation(),spatial.getLocalRotation(),main.getCamera().getDirection(),main.getCamera().getLeft());
main.client.send(action);
}
}break;
case "WalkForward":{
current_time = 0.0f;
prevRot = spatial.getLocalRotation();
walkingForward = isPressed;
moving = true;
if (!(this instanceof NetworkPlayableCharacter)) { //Only send if this is the source client.
PlayerActionMessage action = new PlayerActionMessage(name,Boolean.toString(isPressed),main.client.getId(),spatial.getLocalTranslation(),spatial.getLocalRotation(),main.getCamera().getDirection(),main.getCamera().getLeft());
main.client.send(action);
}
}break;
}
}
@Override
public void onAnalog(String name, float value, float tpf) {
switch (name) {
case "Jump":{
if (isOnGround() || physics.airTime<=physics.walkOffTime) {
//System.out.println("Jump");
physics.jump();
if (!(this instanceof NetworkPlayableCharacter)) { //Only send if this is the source client.
PlayerActionMessage action = new PlayerActionMessage(name,"",main.client.getId(),spatial.getLocalTranslation(),spatial.getLocalRotation(),main.getCamera().getDirection(),main.getCamera().getLeft());
main.client.send(action);
}
}
}break;
}
}
public boolean isOnGround() {
return physics.isOnGround();
}
@Override
public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
}
@Override
public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
}
public Vector3f getWalkDirection(Vector3f camDir, Vector3f camLeftDir) {
camDir.y=0; camDir.normalizeLocal();
camLeftDir.y=0; camLeftDir.normalizeLocal();
Vector3f walkDirection = new Vector3f(0,0,0);
if (strafingLeft) {
walkDirection.addLocal(camLeftDir);
moving=true;
}
if (strafingRight) {
walkDirection.addLocal(camLeftDir.negate());
moving=true;
}
if (walkingForward) {
walkDirection.addLocal(camDir);
moving=true;
}
if (walkingBackward) {
walkDirection.addLocal(camDir.negate());
moving=true;
}
return walkDirection;
}
}