Detalles del juego de la moto en jMonekyEngine.

Detalles del juego de la moto creado en jMonkeyEngine, donde se definen movimientos y chaserCameras

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.

Comentarios

Un comentario

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

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

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

  • Responsable: IZERTIS S.A.
  • Finalidad: Envío información de carácter administrativa, técnica, organizativa y/o comercial sobre los productos y servicios sobre los que se nos consulta.
  • Legitimación: Consentimiento del interesado
  • Destinatarios: Otras empresas del Grupo IZERTIS. Encargados del tratamiento.
  • Derechos: Acceso, rectificación, supresión, cancelación, limitación y portabilidad de los datos.
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad

Consultor tecnológico de desarrollo de proyectos informáticos. Ingeniero en Informática por la Universidad de Alcalá de Henares.

¿Quieres publicar en Adictos al trabajo?

Te puede interesar

Tutoriales
La segmentación predictiva en tiempo real optimiza la publicidad digital con IA y datos masivos, mejorando conversión y eficiencia en la inversión publicitaria.
Tutoriales
Desarrollo de apps en Android Automotive OS: configuración, interacción con el Host, UI con Car App Library, navegación y pruebas en emulador
Tutoriales
Aprende a implementar un Outbox Transaccional con AsyncAPI, SpringModulith y ZenWaveSDK, garantizando la consistencia y externalización eficiente de eventos en arquitecturas distribuidas.