HeaderBlog
 
Geekerie The Incredible Machine bientôt sous DS??

Warning: preg_replace() [function.preg-replace]: Compilation failed: unmatched parentheses at offset 9 in /home/.mima/valeuf/blog.valeuf.org/ecrire/tools/syntaxhl/functions.php on line 33

C'est après une petite après-midi de coding avec mon ami Seeme que je viens poster ce billet, encore un peu émoustillé de cette toute petite avancée de notre après-midi. Tous les deux possesseurs d'une Nintendo DS nous avons décidé de coder des applications dessus ! (Oui, oui nous sommes un peu fou). Notre projet final étant de re-coder un DSorganizer suite à l'abandon par Dragoon du projet (sans qu'il libère les sources le vilain !!). Mais avant de ce lancer dans cet énorme projet on (je?) voulait essayer qu'on se fasse la main sur une application plus petite. Je cherchais donc un truc à coder. Finalement ce n'est pas un petit projet qui m'est venus à l'esprit. J'ai eu une sorte de flashback de moi, petit, jouant à The Incredible Machine (merci Seeme d'avoir retrouvé le titre). Jeu très amusant, bien compliqué et dans l'idée adaptable à la DS !!

Aujourd'hui nous avions donc décidé de faire des essais pour voir comment faire de la mécanique du point en C. Vu que pour le moment on a beaucoup de mal avec nos compilations DS, et que Seeme connait pas trop mal la libSDL (il à de bon vieux souvenir le bougre) on a fait des essais avec celle-ci. Et bon sang qu'elle est long, on verras par la suite. L'idée étant de nous entraîner à gérer un objet sur un axe Oy. Et bien moi qui pensais que cela allait être tout con j'ai été surpris. (Et j'ai eu un bon mal de tête !!). Je pense que les problèmes rencontrés sont assez intéressant, je vais donc regarder un peu plus prés certains problèmes rencontrés.

Première approche

Avec l'ordinateur on pénètre dans un nouveau système d'unité ! Il nous fallait résoudre deux petits problèmes : redéfinir le temps et la longueur. Il aurait bien sur était disponible d'utiliser la seconde et le mètre mais cela pose certain problème. Tout d'abord pour le mètre il faut connaître la taille d'un pixel, faire des conversions à chaque fois (donc vu que la SDL est longue à réagir vaut mieux éviter). Ensuite les secondes, dans un premier temps nous voulions garder le temps. (Il est possible de lancer un "chrono" au début et donc d'avoir une durée). Mais cela était compliqué et ne donnait pas vraiment des résultats satisfaisants. L'idée fut donc de définir un temps. Il faut comprendre que notre programme est une boucle infinie. Il est donc composé de cycle qui à chaque fois calcul la position de notre objet et l'actualise. Nous avons définit que chaque cycle vaut 0,3 unités de temps. (Pourquoi pas 1 ? tout simplement car le mouvement est alors bien trop rapide, mais cela peut se régler à 0,5 pour accélérer un peu la vitesse ou 0,1 pour avoir un ralenti).

Le rebond !!

Là on commence à rire. Bon après avoir fait la chute sans rebond assez simplement nous sommes passé aux rebonds ! Bon d'abord il nous fallait détecter quand notre objet touche le sol, rappelons qu'avec SDL le repère est orienté vers le bas, on commence à bien rigoler avec les signes. Ensuite l'idée c'est de changer le sens de notre trajectoire (passé une variable à -1 dans notre cas). Calculer la vitesse et la définir en vitesse initiale de notre seconde équation ! Pour calculer notre vitesse de rebond, on a fait dans l'a peu prés. On à pris un coefficient de rebond (entre 0 et 1) et on a multiplié la vitesse à la quelle arrive notre objet au sol.

L'invention du mouvement perpétuel

Quand la balle remonte, si nos équations sont justes, la vitesse diminue jusqu'à être nulle et à ce moment l'objet redescend. On doit donc détecter cette vitesse nulle et changer le sens (repasser notre variable sens à 1). Et normalement l'objet retombe jusqu'au rebond ! Et si on n'a pas fait d'erreur l'objet remonte à une position plus faible que sa positions de départ !! Sinon on a un beau mouvement perpétuel !

Le mouvement perpétuel II : Le retour

Après une grosse séance d'arrachage de cheveux en grosse partie due à ce repère orienté vers le bas, nous arrivons enfin à un rebond convenable grâce à une astuce que je détaillerais plus bas. Mais horreur et stupéfaction, notre objet bloque sur un rebond de 1px !! (C'est pas beau, on dirait qu'il a la tremblote !). On doit trouver une solution pour le stabiliser. Déjà il faut comprendre que nous faisons des calculs sur des nombres à virgules (flottants), alors que les coordonnées sont des entiers ! Donc c'est ce petit jeu (d'arrondis) qui provoque cette derniére oscillation. On pense d'abord à détecter une variation entre deux positions y assez petite pour penser que l'objet à fini de rebondir mais malheureusement au début de la chute les variations de y sont plus petites que celle qu'on pouvait avoir à la fin ! Nous avons pensé aussi regarder les variations de vitesse, mais ce n'était pas beaucoup mieux. Il faut alors voir une chose, il y'a une position ymax de notre objet. Il suffit alors de forcer cette position ymax au-delà d'un y définis. Par exemple ymax-1 ce qui fait que si le rebond ne renvois pas l'objet au-dessus de ymax-1 alors il reste bloqué !! (Astucieux ?? ou peut-être y'a-t-il une autre solution ??).

Petit problèmes et notre solution : le code source

[cpp]

tps+=0.3; //Horloge de notre programme : 1 cycle égale 0,1 temps
vitesse = sens*G * tps + V0; //Calcul de la vitesse de l'objet à chaque cycle

if(y>(screen->h-bmp->h)){    //Test pour quand l'objet touche le sol
sens=-1;                //Changement du sens de la trajectoire
V0 =BOUND*vitesse;    //Définition de la vitesse de rebond
tps=0.1;             //Remise à zéro de notre horloge
}

if (sens==1){
y = +0.5 * G * pow(tps,2) + V0 * tps + y0; //Équation pour la descente
}
else {
y = screen->h-bmp->h-(-0.5 * G * pow(tps,2) + V0 * tps ); 
}

if(vitesse<=0){  //Changement de sens quand la vitesse est nulle
sens=1;     //Changement de sens
y0=y;      //Redéfinition de notre y0
V0=0;     //Remise à zéro de notre vitesse initiale
tps=0.1;  //Remise à zéro de notre horloge
}

if(y>=screen->h-bmp->h-1){
y = screen->h-bmp->h + 1; //Permet d'éviter un rebond infini de 1px
}

dstrect.y = y; //Mise à jour des coordonnées de l'objet

C'est une partie du code source qui est mis dans la boucle infinie, il est suffisant je pense pour comprendre certaines subtilités !

Petit problèmes et notre solution : le code source

Le choix de la variable sens pouvant prendre -1 et 1 permet de gérer des problèmes de signes assez facilement dans les équations. Ensuite il faut penser à certaine chose. Par exemple dans le passage de la descente à la montée, (au moment du rebond), il faut bien penser à remettre notre horloge à zéro et on peut alors considérer notre mouvement comme si on jetait un objet en l'air ! Bon ensuite selon le sens on calcul notre position avec des équation trouvée grâce l'ami Isaac Newton ! Attention il y'a une petite subtilité dans l'équation de la remonté, qui de soustraire l'équation a la position du point le plus bas de l'objet dans notre fenêtre, je ne saurais précisément expliquer pourquoi il faut le faire, mais les calculs montre que c'est important !! Ensuite deux trois petits truc : bien tester une vitesse nulle ou négative (le deuxième cas étant plus que fréquent !). Et enfin on peut voir ma vision de l'arrondi quand les rebonds sont trop petit !

Tester notre malheureux programme

Je vous propose de télécharger une petite archive avec les sources et un binaire compilé pour linux. Si cela vous amuse ... Si vous avez des idées pour améliorer je suis preneur, car nous en aurons besoin pour la suite, et surtout pour passer outre certains problèmes que va nous poser la DS !

 
retour à l'accueil
Pub
 
retour à l'accueil
Notez l'article
Note : 10.0/10 pour 1 vote
 
retour à l'accueil
Commentaires
1.   Valeuf    vendredi 1 décembre 2006 à 02:14

Lors de test avec le petit programme, à l'occasion de l'écriture du précédent billet je viens de mettre en défaut mon système anti-rebond infini de la fin. En effet, il ne marche plus à partir d'un BOUND = 0,7 car la boucle de rebond finale est trop grande (supérieure à 1px). Il faut donc calculer une valeur en fonction du rebond j'ai pris une variable max = 3*BOUND, cela marche jusqu'à un bound de 0,85 après j'ai pas eu le courage ce soir d'attendre !

Je vais continuer a faire mumuse avec mon prog en attendant ! Je ferrais la mise à jour des sources demain sans doute.

 
retour à l'accueil
Trackbacks

Aucun trackback.

Pour faire un trackback sur ce billet : http://blog.valeuf.org/tb.php?id=42

 
Ajouter un commentaire