Un des gros avantages de APE, c’est sa logique de fonctionnement !
Toute personne connaissant la programmation objet sera en terrain connu, d’où une relative facilité d’apprentissage, pas de perte de temps !
Il sera parfait pour toutes les utilisations ou le nombre d’objets a tester pour collision sera dans une fourchette relativement basse, une 50aine d’objets sera certainement un grand maximum.

Vous pouvez tester les possibilités de APE dans cette animation.
Attention, les objets qui sortent de la scène continuent a exister, faut donc appuyer de temps en temps sur le bouton d’effacement.
Le clique de la souris + déplacement place un objet cercle sur la scène, le type de ce objet peut être modifié en appuyant sur une touche du clavier :
- CTRL = un tricycle avec liaison souple entre chaque roue (a placer un par un pour éviter de les imbriquer)
- SHIFT = une roue
Si vous ne voyez pas de différence entre un cercle et une roue, c’est normal, la seule différence entre les 2, c’est la possibilité de définir un coefficient de traction (ici a 0) pour la roue afin qu’elle ce comporte comme une roue de voiture.
code utilisé dans le SWF :
/* ---------------------------------------------------------------------------- * * classe Main v1.0 * ------------------------------------------------------------------------------- */ package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import org.cove.ape.*; import lol.controle.Bouton; /** * * @author Lorenzo */ public class Main extends Sprite { // ----------------------------------------------------------------------------------- // DECLARATIONS // ----------------------------------------------------------------------------------- // le groupe des objets a tester pour collision. // un objet peut faire partie de plusieurs groupe private var _apeGroupDyn:Group = new Group(true); // le groupe des objets statiques -> ne bouge pas et pas de test // de collision entre eux ! private var _apeGroupStatiq:Group = new Group(); // definition du vecteur de gravité du monde private var _apeVectorGravite:Vector = new Vector(0, 10); // ----------------------------------------------------------------------------------- // CONSTRUCTEUR // ----------------------------------------------------------------------------------- /** * Constructeur de Main */ public function Main():void { if (stage){ init(); }else{ addEventListener(Event.ADDED_TO_STAGE, init); } } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // entry point stage.scaleMode = "noScale"; //stage.align = "LB"; var bt:Bouton = new Bouton(); bt.texte = "Effacer objets utilisateur"; bt.x = 798; bt.y = 2; bt.aligne = "droite"; this.addChild(bt); bt.addEventListener(MouseEvent.MOUSE_DOWN, evtBtEffacerDynamiqueMouseDown); // Initialisation du moteur physique APEngine.init(1/6); APEngine.container = this; APEngine.addMasslessForce(this._apeVectorGravite); APEngine.damping = 0.99; APEngine.constraintCollisionCycles = 1; APEngine.constraintCycles = 1; this._apeGroupStatiq = new Group(); this._apeGroupDyn = new Group(true); // definition des rectangles statiques var floor:RectangleParticle; floor = new RectangleParticle(250,200,500,20,Math.PI/16,true,1,0,0); floor.setStyle(0,0,0,0x006699); this._apeGroupStatiq.addParticle(floor); floor = new RectangleParticle(8,120,10,100,0,true,1,0,0); floor.setStyle(0,0,0,0x006699); this._apeGroupStatiq.addParticle(floor); floor = new RectangleParticle(550,400,500,20,-Math.PI/16,true,1,0,0); floor.setStyle(0,0,0,0x006699); this._apeGroupStatiq.addParticle(floor); floor = new RectangleParticle(792,320,10,100,0,true,1,0,0); floor.setStyle(0,0,0,0x006699); this._apeGroupStatiq.addParticle(floor); APEngine.addGroup(this._apeGroupStatiq); APEngine.addGroup(this._apeGroupDyn); // on indique au moteur que les membres du groupe "this._apeGroupDyn" seront testé pour collision // avec "this._apeGroupStatiq" this._apeGroupDyn.addCollidable(this._apeGroupStatiq); this.addEventListener(Event.ENTER_FRAME, evtThisEnterFrame); this.stage.addEventListener(MouseEvent.MOUSE_DOWN, evtStageMouseDown); this.stage.addEventListener(MouseEvent.MOUSE_UP, evtStageMouseUp); } // ----------------------------------------------------------------------------------- // EVENEMENTS // ----------------------------------------------------------------------------------- /** */ private function evtStageMouseDown(ev:MouseEvent):void { stage.addEventListener(MouseEvent.MOUSE_MOVE, evtThisMouseMove); } /** */ private function evtStageMouseUp(ev:MouseEvent):void { stage.removeEventListener(MouseEvent.MOUSE_MOVE, evtThisMouseMove); } /** */ private function evtThisMouseMove(ev:MouseEvent):void { if ( ev.target != this.stage ) { return; } var masseRayon:Number; if ( ev.ctrlKey ) { // Ajouter un espece de tricycle avec liaison souple entre les roues masseRayon = Math.random() * 10 + 5; var wa:WheelParticle = new WheelParticle(ev.stageX, ev.stageY, masseRayon, false, masseRayon, 0.3, 0, 1); this._apeGroupDyn.addParticle(wa); var wb:WheelParticle = new WheelParticle(ev.stageX + masseRayon * 4, ev.stageY - masseRayon * 4, masseRayon, false, masseRayon, 0.3, 0, 1); this._apeGroupDyn.addParticle(wb); var wc:WheelParticle = new WheelParticle(ev.stageX + masseRayon * 8, ev.stageY, masseRayon, false, masseRayon, 0.3, 0, 1); this._apeGroupDyn.addParticle(wc); var sca:SpringConstraint = new SpringConstraint(wa, wb, 0.1, true, masseRayon >> 1); this._apeGroupDyn.addConstraint(sca); var scb:SpringConstraint = new SpringConstraint(wb, wc, 0.1, true, masseRayon >> 1); this._apeGroupDyn.addConstraint(scb); var scc:SpringConstraint = new SpringConstraint(wa, wc, 0.1, true, masseRayon >> 1); this._apeGroupDyn.addConstraint(scc); }else if ( ev.shiftKey ) { // Ajouter une roue masseRayon = Math.random() * 15 + 5; var cercle:WheelParticle = new WheelParticle(ev.stageX, ev.stageY, masseRayon, false, masseRayon, 0.3, 0); cercle.setStyle(0, 0, 1, Math.random() * 0xFFFFFF); this._apeGroupDyn.addParticle(cercle); }else { // Ajouter un cercle masseRayon = Math.random() * 15 + 5; var cercle2:CircleParticle = new CircleParticle(ev.stageX, ev.stageY, masseRayon, false, masseRayon); cercle2.setStyle(0, 0, 1, Math.random() * 0xFFFFFF); this._apeGroupDyn.addParticle(cercle2); } } private function evtThisEnterFrame(evt:Event):void { // moteur du moteur physique : calcul position/collision APEngine.step(); // affichage APEngine.paint(); } /** * @param ev */ private function evtBtEffacerDynamiqueMouseDown(ev:MouseEvent):void { while ( this._apeGroupDyn.constraints.length > 0 ) { this._apeGroupDyn.removeConstraint(this._apeGroupDyn.constraints[0]); } while ( this._apeGroupDyn.particles.length > 0 ) { this._apeGroupDyn.removeParticle(this._apeGroupDyn.particles[0]); } } } }