Implémentation RK4 en Java pour de la 2D
Bonjour :)
Je m'intéresse à la programmation de jeux 2D en réseau avec Java, j'utilise la librairie Slick2D. N'ayant pas d'expérience dans la programmation de jeux en réseaux je me suis lancé dans la lecture de ce tutoriel:
http://gafferongames.com/game-physic...ration-basics/
D'après ce que j'ai compris (mon niveau en maths/anglais est plutôt moyen :oops:) la physique semble obligatoire pour la réalisation d'un jeux en réseau. J'ai donc commencé l'implémentation du RK4 en Java conformément au tutoriel de gafferongames. J'ai construit une petite démo basé dessus ou on peut déplacer un tank (Windows/Java SE6).
http://www.vin789.fr/wordpress/games/gogi.rar
Mon problème est le suivant, je n'arrive pas à intégrer la notion de rotation et diminution de la vitesse en fonction de la rotation. Le tutoriel 3 de gafferongame le fait mais dans un univers 3D avec des Quaternions. Hors je veux rester dans la 2D.
J'ai "bidouillé" le code de la méthode accélération pour faire ralentir mon tank mais on dirait surtout que ce dernier se déplace sur une patinoire :mrgreen:. Il me manque surement la notion de masse ou de frottement de l'air.
Si quelqu'un peut m'aider à intégrer la rotation pour la 2D dans le R4K, je le remercie d'avance ;)
Voici le code utilisé dans la partie physique de la démo (tout le code source est disponible dans le .rar):
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
|
public class PhysicMath {
private static Derivative evaluate(State initial, float t, float dt, Derivative d) {
State state = new State();
state.position.set(initial.position.x + d.dx.x * dt, initial.position.y + d.dx.y * dt);
state.velocity.set(initial.velocity.x + d.dv.x * dt, initial.velocity.y + d.dv.y * dt);
Derivative output = new Derivative();
output.dx.set(state.velocity);
output.dv.set(acceleration(state, t + dt));
return output;
}
private static Derivative evaluate(State initial, float t) {
Derivative output = new Derivative();
output.dx.set(initial.velocity);
output.dv.set(acceleration(initial, t));
return output;
}
public static void integrate(State state, float t, float dt) {
Derivative a = evaluate(state, t);
Derivative b = evaluate(state, t + dt * 0.5f, dt * 0.5f, a);
Derivative c = evaluate(state, t + dt * 0.5f, dt * 0.5f, b);
Derivative d = evaluate(state, t + dt, dt, c);
final float dxdt = 1.0f / 6.0f * (a.dx.x + 2.0f * (b.dx.x + c.dx.x) + d.dx.x);
final float dydt = 1.0f / 6.0f * (a.dx.y + 2.0f * (b.dx.y + c.dx.y) + d.dx.y);
final float dvxdt = 1.0f / 6.0f * (a.dv.x + 2.0f * (b.dv.x + c.dv.x) + d.dv.x);
final float dvydt = 1.0f / 6.0f * (a.dv.y + 2.0f * (b.dv.y + c.dv.y) + d.dv.y);
state.position.set(state.position.x + dxdt * dt, state.position.y + dydt * dt);
float nvx = state.velocity.x + dvxdt * dt;
float nvy = state.velocity.y + dvydt * dt;
// Driven too fast is bad for health...
if (Math.abs(nvx) < 80)
state.velocity.x = nvx;
if (Math.abs(nvy) < 80)
state.velocity.y = nvy;
}
private static Vector2f acceleration(State state, float t) {
float force = 0;
if (state.input.left) {
state.ang -= 2;
}
if (state.input.right) {
state.ang += 2;
}
float dirX = (float) Math.sin(Math.toRadians(state.ang));
float dirY = (float) -Math.cos(Math.toRadians(state.ang));
if (state.input.down) {
force -= 800;
} else if (state.input.up) {
force += 800;
} else {
if (!(state.velocity.x > -0.01f && state.velocity.x < 0.01f)) {
state.velocity.x += -(state.velocity.x * 0.01f);
}
if (!(state.velocity.y > -0.01f && state.velocity.y < 0.01f)) {
state.velocity.y += -(state.velocity.y * 0.01f);
}
}
return new Vector2f(dirX * force, dirY * force);
}
private static class Derivative {
public Vector2f dx; // derivative of position: velocity
public Vector2f dv; // derivative of velocity: acceleration/force
public Derivative() {
this.dx = new Vector2f();
this.dv = new Vector2f();
}
} |