Detalles del juego de la moto en jMonekyEngine.

1
9813

Detalles del juego de la moto.

En este tutorial veremos algunos puntos interesantes sobre el tutorial
 JMonkeyEngine,
Creación de nuestro primer juego
.

Nos centraremos en el seguimiento de cámara, los movimientos
de la moto y os mencionare algún bug que tiene.

Empecemos por la cámara de seguimiento,todo los cambios para
la cámara se harán en el fichero juego.java, para
implementar una cámara de seguimiento, tenemos que declarar
2 variables: la primera es la cámara y la siguiente el
seguidor.

	private Camera cam;
	private ChaseCamera chaser;

Ya que se necesita una cámara para poder estar viendo los
objetos, luego esta cámara se englobara dentro del seguidor
que sera luego quien realmente vaya detrás de la moto.

Luego tendremos que modificar nuestro método update, ya que
hay que ir refrescando la posición de la cámara
para poder ver la moto en su posición actual. Como hacemos
en todos las aplicaciones.

	skybox.setLocalTranslation(cam.getLocation());

	 if(cam.getLocation().y < (tb.getHeight(cam.getLocation())+2)) {
            cam.getLocation().y = tb.getHeight(cam.getLocation()) + 2;
            cam.update();
        }

Despúes en el método initSystem() tambien
tendremos que añadir codigo, ya que es el
método de inicio y tendremos que iniciar la
cámara que usara el seguidor.

	try {
            display = DisplaySystem.getDisplaySystem	(settings.getRenderer());
            display.setMinStencilBits(8);
            display.createWindow(width, height, depth, freq fullscreen);

            cam = display.getRenderer().createCamera(width, height);
        } catch (JmeException e) {
            logger.log(Level.SEVERE, "Could not create displaySystem", e);
            System.exit(1);
        }

        display.getRenderer().setBackgroundColor(ColorRGBA.black.clone());

        cam.setFrustumPerspective(45.0f, (float) width / (float) height, 1,
                5000);
        cam.setLocation(new Vector3f(200,1000,200));

        cam.update();

       timer = Timer.getTimer();

        display.getRenderer().setCamera(cam);

Y por ultimo añadimos un método que llamaremos en
InitGame(), a este método le llamaremos buildChaseCamera()
en el que definimos las propiedades del seguidor y le asociamos la
cámara y el objeto a seguir.

  private void buildPassManager() {
        passManager = new BasicPassManager();

        // Add skybox first to make sure it is in the background
        RenderPass rPass = new RenderPass();
        rPass.add(skybox);
        passManager.add(rPass);

        shadowPass.add(scene);
        shadowPass.addOccluder(player);
        shadowPass.setRenderShadows(true);
        shadowPass.setLightingMethod(ShadowedRenderPass.LightingMethod.Modulative);
        passManager.add(shadowPass);
    }

Ahora os hablare de como hacer los movimientos de la moto, empezare por el movimiento de las ruedas, esto lo haremos dentro del archivo
moto.java. Lo que tenemos que hacer son los cálculos
matemáticos para calcular el angulo de movimiento,
según la velocidad y luego  aplicárselo
a las ruedas( para hallar los nombres de los nodos de las ruedas y lo
que hay que hacer para usarlas  mirar el tutorial Scene
Monitor, jMonkeyEngine).

La variable wheelAxis es una constante que es del tipo Vector3f cuyo
valor es (0,1,0).

 private void rotateWheels(float time) {

        if (vehicleIsMoving()) {
            if(velocity > FastMath.FLT_EPSILON) {
                angle = angle - ((time) * velocity * 0.5f);
                if (angle < -360) {
                    angle = 0;
                }
            } else {
                angle = angle + ((time) * velocity * 0.5f);
                if (angle > 360) {
                    angle = 0;
                }
            }
            rotQuat.fromAngleAxis(angle, wheelAxis);
            frontwheel.getLocalRotation().multLocal(rotQuat);
            backwheel.setLocalRotation(frontwheel.getLocalRotation());
        }
    }

Para hacer que la moto se tumbe añadimos el
método processLean que es el que nos permite hacer que la
moto se tumbe cuando gire, entonces para ello tenemos que hacer un
calculo del angulo que necesita y lo hacemos en función del
tiempo ya que la moto se encuentra en movimiento y según
como vaya de rápido inclinara mas o menos.

La variable q es de tipo Quaternion y se usa de variable auxiliar.


 private void processLean(float time) {
        //check if we are leaning at all
        if(lean != 0) {
            if(lean == -1 && leanAngle < 0) {
                leanAngle += -lean * 4 * time;
            } else if(lean == 1 && leanAngle > 0) {
                leanAngle += -lean * 4 * time;
            } else {
                leanAngle += -lean * 2 * time;
            }
            //max lean is 1 and -1
            if(leanAngle > 1) {
                leanAngle = 1;
            } else if(leanAngle < -1) {
                leanAngle = -1;
            }
        } else { //we are not leaning, so right ourself back up.
            if(leanAngle < LEAN_BUFFER && leanAngle > -LEAN_BUFFER) {
                leanAngle = 0;
            }
            else if(leanAngle < -FastMath.FLT_EPSILON) {
                leanAngle += time * 4;
            } else if(leanAngle > FastMath.FLT_EPSILON) {
                leanAngle -= time * 4;
            } else {
                leanAngle = 0;
            }
        }

        q.fromAngleAxis(leanAngle, leanAxis);
        model.setLocalRotation(q);

        lean = 0;
    }

Para hacer el efecto de freno sin mas con que disminuyamos el valor de la velocidad  en función del tiempo se consigue.


public void brake(float time) {
        velocity -= time * braking;
        if(velocity < -minSpeed) {
            velocity = -minSpeed;
        }
    }

El efecto de acelerar es el mismo que el de frenar solo que en vez de restar sumamos.


  public void accelerate(float time) {
        velocity += time * acceleration;
        if(velocity > maxSpeed) {
            velocity = maxSpeed;
        }
    }

Para hacer que las ruedas patinen usaremos el método drift

public void drift(float time) {
        if(velocity < -FastMath.FLT_EPSILON) {
            velocity += ((weight/5) * time);            
            if(velocity > 0) {
                velocity = 0;
            }
        } else if(velocity > FastMath.FLT_EPSILON){
            velocity -= ((weight/5) * time);
            if(velocity < 0) {
                velocity = 0;
            }
        }
    }

Para que la moto gire hemos implementado una nueva clase que es una
extension de KeyInputAction ya que luego lo usaremos para que cuando
pulsemos unas teclas especificas ocurran los giros, ha este fichero lo
hemos denominado RotacionMoto.java.

package Intento1;

import com.jme.input.action.InputActionEvent;
import com.jme.input.action.KeyInputAction;
import com.jme.math.FastMath;
import com.jme.math.Matrix3f;
import com.jme.math.Vector3f;


public class RotacionMoto extends KeyInputAction {
    public static final int RIGHT = 0;
    public static final int LEFT = 1;
    private static final Matrix3f incr = new Matrix3f();
    private static final Matrix3f tempMa = new Matrix3f();
    private static final Matrix3f tempMb = new Matrix3f();

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

    private moto vehicle;
    private int direction;
    private int modifier = 1;

    
    public RotacionMoto(moto vehicle, int direction) {
        this.vehicle = vehicle;
        this.direction = direction;
    }


    public void performAction(InputActionEvent evt) {
        if(vehicle.getVelocity() > -FastMath.FLT_EPSILON && vehicle.getVelocity() < FastMath.FLT_EPSILON) {
            return;
        }

        if(direction == LEFT) {
            modifier = 1;
        } else if(direction == RIGHT) {
            modifier = -1;
        }

        if(vehicle.getVelocity() < 0) {
            incr.fromAngleNormalAxis(-modifier * vehicle.getTurnSpeed() * evt.getTime(), upAxis);
        } else {
            incr.fromAngleNormalAxis(modifier * vehicle.getTurnSpeed() * evt.getTime(), upAxis);
        }
        vehicle.getLocalRotation().fromRotationMatrix(
                incr.mult(vehicle.getLocalRotation().toRotationMatrix(tempMa),
                        tempMb));
        vehicle.getLocalRotation().normalize();
        vehicle.setRotateOn(modifier);
    }
}

Para hacer que vaya hacia delante y hacia atrás
también tenemos que denominar una nueva clase para esto
suceda con una teclas definidas, también la definiremos como
una clase extendida de KeyInputAction como la clase anterior y la
llamaremos AvanzarRetroceder.java

package Intento1;

import com.jme.input.action.InputActionEvent;
import com.jme.input.action.KeyInputAction;

public class AvanzarRetroceder extends KeyInputAction {
    public static final int FORWARD = 0;
    public static final int BACKWARD = 1;
    
    private moto node;
    private int direction;

    
    public AvanzarRetroceder(moto node, int direction) {
        this.node = node;
        this.direction = direction;
    }

    public void performAction(InputActionEvent evt) {
        if(direction == FORWARD) {
            node.accelerate(evt.getTime());
        } else if(direction == BACKWARD){
            node.brake(evt.getTime());
        }
    }
}

Para hacer que derrape hay que hacer exactamente lo mismo que en las
dos clases anteriores, definirla como clase extendida de KeyInputAction
 en este caso la llamaremos  AccionDerrape.java

package Intento1;


import com.jme.input.action.InputActionEvent;
import com.jme.input.action.KeyInputAction;


public class AccionDerrape extends KeyInputAction {
  
    private moto vehicle;

    public AccionDerrape(moto vehicle) {
        this.vehicle = vehicle;
    }

    public void performAction(InputActionEvent evt) {
        vehicle.drift(evt.getTime());
    }
}

Como bugs que tiene el juego, podríamos decir que es uno que
la moto se puede salir del escenario y parece que va volando, eso es
porque no están implementadas las colisiones

Para cualquier duda de los métodos y las clases de JMonkey
Engine se puede consultar http://wiki.jmonkeyengine.org/doku.php/
):

Espero que les haya sido útil para poder profundizar algo
más en el juego, seguiremos
haciendo más tutoriales sobre esta tecnología
analizando más ejemplos algo más complicados,
todo el que quiera hacer una aportación será bien
recibida.

Para comunicarme cualquier problema o sugerencia de mejora
podéis utilizar la zona de comentarios, de este modo todo el
mundo se podrá aprovechar de las respuestas.

Saludos.

1 COMENTARIO

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad