PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/src/bipede/membres/Squelette.as

http://himemm.googlecode.com/
ActionScript | 645 lines | 428 code | 94 blank | 123 comment | 39 complexity | 155ebca2e39e9041395d8e7c8c2c8616 MD5 | raw file
  1. /*
  2. *
  3. * Sprite possédant :
  4. *
  5. * une Armature
  6. * une pose par défaut
  7. * ( des poignées ? des joints physiques ? des contraintes ? )
  8. *
  9. * les IKBone nécessaires sont :
  10. *
  11. * bone_mainD
  12. * bone_piedD
  13. * bone_mainG
  14. * bone_piedG
  15. * epine
  16. *
  17. * Le MovieClip Tete contenant les Yeux
  18. *
  19. * Gestion des armatures :
  20. *
  21. * Il ne peut pas exister 2 instances avec la męme armature : la derničre écrase les précédentes.
  22. * ŕ cause du IKManager.getArmatureByName( "name" );
  23. *
  24. * */
  25. package bipede.membres
  26. {
  27. import drawer.events.DrawEvent;
  28. import fab.geom.Drawer;
  29. import fab.geom.Circle;
  30. import fab.geom.Line;
  31. import fab.geom.Segment;
  32. import fab.Utils;
  33. import events.MarcheEvent;
  34. import events.MoveEvent;
  35. import events.PersonEvent;
  36. import events.PhysicEvent;
  37. import bipede.controleurs.Animateur;
  38. import bipede.animation.Pose;
  39. import physic.Liaison;
  40. import physic.Contrainte;
  41. import physic.Engine;
  42. import physic.SoftBody;
  43. import physic.Obstacle;
  44. import clips.Poignee_mc;
  45. import clips.Poignee;
  46. import fl.ik.*;
  47. import flash.display.Sprite;
  48. import flash.events.Event;
  49. import flash.events.MouseEvent;
  50. import flash.events.TimerEvent;
  51. import flash.geom.Point;
  52. import flash.geom.Matrix;
  53. import flash.geom.Rectangle;
  54. import flash.utils.getQualifiedClassName;
  55. import flash.utils.Timer;
  56. import flash.utils.Dictionary;
  57. public class Squelette extends Sprite
  58. {
  59. public var tree:IKArmature;
  60. public var testIKjoints:Vector.<PhysicJoint> = new Vector.<PhysicJoint>();
  61. public var pieds:Vector.<Pied> = new Vector.<Pied>();
  62. public var lesBras:Vector.<Bras> = new Vector.<Bras>();
  63. //public var contraintes:Vector.<Contrainte> = new Vector.<Contrainte>();
  64. public var contraintes:Object = new Object();
  65. public var physic_bones:Object = new Object();
  66. //private var poignees:Vector.<Poignee> = new Vector.<Poignee>();
  67. public var data:Dictionary = new Dictionary();
  68. private var _pose:Pose;
  69. private var _target_pose:Pose;
  70. public var default_pose:Pose;
  71. public var initStatus:Object;
  72. private var clipBone:Sprite;
  73. private var ikMover:IKMover;
  74. private var bones_names:Array;
  75. private var ikMovers:Vector.<IKMover> = new Vector.<IKMover>();
  76. //public var animateurs:Vector.<Animateur> = new Vector.<Animateur>();
  77. public var animateurs:Dictionary = new Dictionary();
  78. public var main_gauche:Bras;
  79. public var main_droite:Bras;
  80. public var pied_gauche:Pied;
  81. public var pied_droit:Pied;
  82. public var current_pied:Pied;
  83. public var autre_pied:Pied;
  84. private var _start_pose:Pose;
  85. private var marche_compteur:Timer;
  86. private var anim_compteur:Timer;
  87. private var anim_increment:Number;
  88. public var physics:SoftBody;
  89. public var _rectangle_pied_gauche:Rectangle;
  90. public function init():void
  91. {
  92. main_gauche = create_main( "bone_mainG" );
  93. main_droite = create_main( "bone_mainD" );
  94. pied_gauche = create_pied( "bone_piedG" );
  95. pied_droit = create_pied( "bone_piedD" );
  96. current_pied = pied_gauche;
  97. autre_pied = pied_droit;
  98. anim_compteur = new Timer( 40, 10 );
  99. anim_compteur.addEventListener( TimerEvent.TIMER, _tick );
  100. anim_compteur.addEventListener( TimerEvent.TIMER_COMPLETE, _fin_tick );
  101. //IKManager.trackIKObject( dummy_mainD, true );
  102. //create_poignee_mc( "dummy_mainD" );
  103. parse_IKJoint_tree( register_physic_bone, tree.rootJoint );
  104. //addEventListener( MoveEvent.MOVING, moving );// passage dans physics
  105. };
  106. public function Squelette()
  107. {
  108. addEventListener(Event.FRAME_CONSTRUCTED, frameConstructedHandler);
  109. }
  110. private function frameConstructedHandler(event:Event):void
  111. {
  112. removeEventListener(Event.FRAME_CONSTRUCTED, frameConstructedHandler);
  113. tree = IKManager.getArmatureByName( "Armature_" + getQualifiedClassName( this ) );
  114. tree.registerElements( this );
  115. default_pose = pose;
  116. // trace de armature
  117. parse_IKJoint_tree( traceArmature, tree.rootJoint );
  118. initStatus = { scaleX:scaleX, scaleY:scaleY };
  119. init();// to override
  120. dispatchEvent( new PersonEvent( PersonEvent.ARMATURE_READY ) );
  121. dispatchEvent( new PersonEvent( PersonEvent.ANIMATIONS_READY ) );
  122. }
  123. public function create_contrainte( p:Point, mobileBoneNom:String, attachBoneNom:String ):Contrainte
  124. {
  125. // TODO
  126. release_joint_constraint( mobileBoneNom, 4 );
  127. var mobileBone:IKBone = tree.getBoneByName( mobileBoneNom );
  128. //var tailJoint:IKJoint = mobileBone.tailJoint;
  129. var attachBone:IKBone = tree.getBoneByName( attachBoneNom );
  130. //var attachTailJoint:IKJoint = attachBone.tailJoint;
  131. var c:Contrainte = new Contrainte( this, p, mobileBone, attachBone );
  132. contraintes[ mobileBone.tailJoint.name ] = c;
  133. return c;
  134. }
  135. public function create_physic_joint( nom:String ):void
  136. {
  137. var bone:IKBone = tree.getBoneByName( nom );
  138. var tailJoint:IKJoint = bone.tailJoint;
  139. testIKjoints.push( new PhysicJoint( tailJoint ) );
  140. }
  141. public function create_pied( nom:String ):Pied
  142. {
  143. var bone:IKBone = tree.getBoneByName( nom );
  144. //var tailJoint:IKJoint = bone.tailJoint;
  145. var pied:Pied = new Pied( this, bone );
  146. pieds.push( pied );
  147. return pied;
  148. }
  149. public function get tete():*
  150. {
  151. var bone:IKBone = tree.getBoneByName( "epine" );
  152. //trace(bone);
  153. var tailJoint:IKJoint = bone.tailJoint;
  154. //trace(tailJoint);
  155. trace(tailJoint.name);
  156. return ( tailJoint );
  157. }
  158. public function create_main( nom:String ):Bras
  159. {
  160. var bone:IKBone = tree.getBoneByName( nom );
  161. //var tailJoint:IKJoint = bone.tailJoint;
  162. var bras:Bras = new Bras( this, bone );
  163. lesBras.push( bras );
  164. trace("create_main", nom, this.name, bras, bone);
  165. return bras;
  166. }
  167. public function create_poignee_bone( nom:String, x:int=0, y:int=0 ):Poignee
  168. {
  169. var bone:IKBone = tree.getBoneByName( nom );
  170. var tailJoint:IKJoint = bone.tailJoint;
  171. var position:Point = tailJoint.position;
  172. var ikMover:IKMover = new IKMover( tailJoint, tailJoint.position );
  173. var j:Poignee = new Poignee( ikMover, tailJoint );
  174. //stage.
  175. addChild( j );
  176. j.x = position.x;
  177. j.y = position.y;
  178. return j;
  179. }
  180. public function create_poignee_mc( nom:String, x:int=0, y:int=0 ):void
  181. {
  182. var j:Poignee_mc = new Poignee_mc( this[ nom ] );
  183. addChild( j );
  184. j.x = this[ nom ].x;
  185. j.y = this[ nom ].y;
  186. }
  187. public function set orientation( vers_la_droite:Boolean ):void
  188. {
  189. scaleX = vers_la_droite?initStatus.scaleX: - initStatus.scaleX;
  190. }
  191. /*
  192. * renvoie true si vers la droite
  193. * */
  194. public function get orientation():Boolean
  195. {
  196. return scaleX > 0;
  197. }
  198. public function get pose():Pose
  199. {
  200. _pose = new Pose();//<pose></pose>;
  201. parse_IKJoint_tree( getPoseJoint, tree.rootJoint );
  202. return _pose;
  203. }
  204. public function set pose(p:Pose):void
  205. {
  206. _target_pose = p;
  207. parse_IKJoint_tree( setPoseJoint, tree.rootJoint );
  208. }
  209. public function set place(p:Point):void
  210. {
  211. //x = int( p.x );// foire les petites anim comme bras_ballants
  212. //y = int( p.y );
  213. x = ( p.x );
  214. y = ( p.y );
  215. }
  216. public function get place():Point
  217. {
  218. return new Point( x, y );
  219. }
  220. // mapping functions
  221. public function getPoseJoint( nextJoint:* ):void
  222. {
  223. _pose.append( nextJoint.name, nextJoint.position );
  224. }
  225. /*
  226. public function setPoseJoint( nextJoint:* ):void
  227. {
  228. var position:Point = nextJoint.position;
  229. var target:Point = _target_pose.getPosition( nextJoint.name );
  230. var ikMover:IKMover = new IKMover( nextJoint, position );
  231. ikMover.limitByIteration = true;
  232. ikMover.iterationLimit = 6;
  233. ikMover.moveTo( target );
  234. }
  235. */
  236. public function traceArmature( obj:* ):void
  237. {
  238. trace( "\tJoint " + obj.name + "\t\t\tsur Bone " + obj.bone.name + "\t\t\t yTranslationMin " + obj.yTranslationMin + "\t\t\t yTranslation " + obj.yTranslation );
  239. }
  240. public function register_physic_bone( obj:* ):void
  241. {
  242. physic_bones[ obj.bone.name ] = new PhysicBone( obj.bone );
  243. }
  244. // pose de l'armature :
  245. // 2 méthodes : tous les joints, ou les joints ŕ poignee ? ou les bones ?
  246. public function parse_IKJoint_tree( recursiveFunc:Function, joint:IKJoint ):void
  247. {
  248. recursiveFunc( joint );
  249. for ( var i:int = 0; i < joint.numChildren; i++ )
  250. {
  251. var childJoint = joint.getChildAt( i );
  252. //if ( childJoint.numChildren > 0 )
  253. parse_IKJoint_tree( recursiveFunc, childJoint );
  254. }
  255. }
  256. public function distance_au_support( support:Obstacle ):int
  257. {
  258. return support.plateforme.distance( place );
  259. }
  260. public function release_joint_constraint( nom:String, steps:int=2 ):void
  261. {
  262. var step:int = 0;
  263. var bone:IKBone = tree.getBoneByName( nom );
  264. var currentJoint:IKJoint = bone.tailJoint;
  265. while( currentJoint != tree.rootJoint || step < steps )
  266. {
  267. currentJoint.rotationConstrained = false;
  268. step++;
  269. currentJoint = currentJoint.parent;
  270. }
  271. }
  272. public function joint2root_distance_px( nom:String ):int
  273. {
  274. var bone:IKBone = tree.getBoneByName( nom );
  275. var d:int = physic_bones[ bone.name ].longueur;
  276. var currentJoint:IKJoint = bone.tailJoint;
  277. while( currentJoint != tree.rootJoint )
  278. {
  279. currentJoint = currentJoint.parent;
  280. d += physic_bones[ currentJoint.bone.name ].longueur;
  281. }
  282. return d;
  283. }
  284. // ------------------------ from Person :
  285. public function record():Pose
  286. {
  287. return pose;
  288. }
  289. public function set_default_pose( event:MouseEvent=null ):void
  290. {
  291. pose = default_pose;
  292. }
  293. public function register_animateur( anim:Animateur ):void
  294. {
  295. trace("register_animateur " + anim.type);
  296. animateurs[ anim.type ] = anim;
  297. }
  298. public function unregister_animateur( anim:Animateur ):void
  299. {
  300. trace("UNregister_animateur " + anim.type);
  301. delete animateurs[ anim.type ];
  302. //animateurs[ anim.type ] = null;
  303. trace("animateurs length " + animateurs.length);
  304. }
  305. public function applique():void
  306. {
  307. }
  308. public function startmoving( event:MoveEvent ):void
  309. {
  310. //Engine.stop();
  311. //default_pose = pose;
  312. set_default_pose();
  313. //trace("startmoving\r" + default_pose);
  314. for each ( var anim:Animateur in animateurs )
  315. {
  316. anim.stop();
  317. //anim = null;
  318. //unregister_animateur( anim );
  319. }
  320. }
  321. public function endmoving( event:MoveEvent ):void
  322. {
  323. //physics.vitesse = vitesse;
  324. trace(physics.vitesse);
  325. //Engine.start();
  326. //pose = default_pose;// tweener !
  327. //trace("endmoving " + default_pose);
  328. //positionne( default_pose, 4 );
  329. }
  330. public function _physic_update( event:PhysicEvent ):void
  331. {
  332. //positionne( pose );// .translation( new Point( - physics.vitesse.x, - physics.vitesse.y ) ) );
  333. }
  334. /*
  335. * MOVING est subie
  336. * */
  337. public function moving(event:MoveEvent = null):void
  338. {
  339. var cible:Point = event.point;
  340. for each ( var contrainte:Contrainte in contraintes ) cible = contrainte.correction( cible );
  341. /*
  342. for each ( var pied:Pied in pieds )
  343. {
  344. if ( pied.support != null )//pied_droit ?
  345. {
  346. if ( pied.support.plateforme.distance( cible ) < distance_support )
  347. {
  348. var p:Point = pied.support.plateforme.projection( cible );
  349. Drawer.drawPoint( Main.drawings.graphics, p );
  350. var cercle:Circle = new Circle( p, distance_support );
  351. cible = cercle.projection( cible, false );
  352. }
  353. else {
  354. pied.remove_support();
  355. }
  356. }
  357. }
  358. */
  359. var vitesse:Point = cible.subtract( place );
  360. place = cible;
  361. if ( vitesse.length > 4 )
  362. positionne( default_pose );// pose.translation( new Point( vitesse.x, vitesse.y ) ) );
  363. if ( physics != null ) physics.vitesse = vitesse;
  364. }
  365. /*
  366. * renvoie un rectangle de test pour la pose du pied dans le systeme de Engine.espace
  367. * */
  368. public function get rectangle_pied_gauche():Rectangle
  369. {
  370. if ( !orientation ) data.rectangle_pied_gauche.x = 170;
  371. else data.rectangle_pied_gauche.x = 20;
  372. var origine:Point = Utils.PointLocalTransformation( data.rectangle_pied_gauche.topLeft, this, Engine.espace );
  373. // ( int ) pour les tests d'instersectRectangle
  374. return new Rectangle( int(origine.x), int(origine.y), data.rectangle_pied_gauche.width, data.rectangle_pied_gauche.height );
  375. }
  376. public function get rectangle_pied_droit():Rectangle
  377. {
  378. if ( !orientation ) data.rectangle_pied_gauche.x = 170;
  379. else data.rectangle_pied_gauche.x = 20;
  380. var rect:Rectangle = data.rectangle_pied_gauche.clone();
  381. rect.offset( -45, 0 );
  382. var origine:Point = Utils.PointLocalTransformation( rect.topLeft, this, Engine.espace );
  383. // ( int ) pour les tests d'instersectRectangle
  384. return new Rectangle( int(origine.x), int(origine.y), data.rectangle_pied_gauche.width, data.rectangle_pied_gauche.height );
  385. }
  386. // ŕ placer côté Person ??? :
  387. public function findSupport(event:MarcheEvent):void
  388. {
  389. var rectangle:Rectangle = event.dynamic_pied_gauche?rectangle_pied_gauche:rectangle_pied_droit;
  390. var intersect_array:Array = new Array();
  391. var intersect:Segment;
  392. dispatchEvent( new DrawEvent( DrawEvent.DRAWRECTANGLE, rectangle, 0xFF0000 ) );
  393. // recherche des Segments de plateformes d'obstacle inclus dans un rectangle
  394. for each ( var obstacle:Obstacle in Engine.obstacles )
  395. {
  396. //if ( obstacle.display.hitTestPoint( p.x, p.y, true ) )
  397. //{
  398. //Drawer.drawRectangle( Main.drawings.graphics, rectangle );
  399. var plateforme:Segment = obstacle.plateforme;
  400. //trace("findSupport ? "+obstacle);
  401. //Drawer.drawSegment( Main.drawings.graphics, plateforme.debut, plateforme.fin );
  402. intersect = plateforme.instersectRectangle( rectangle );
  403. if ( intersect != null )
  404. {
  405. intersect_array.push( { intersect:intersect, obstacle:obstacle, xmax:orientation?intersect.rectangle.right:intersect.rectangle.left, ymin:intersect.rectangle.top } );
  406. }
  407. //}
  408. }
  409. // classement des segments par leur xmax et envoie du premier
  410. if ( intersect_array.length > 0 )
  411. {
  412. intersect_array.sortOn( "xmax", (orientation?Array.DESCENDING:Array.NUMERIC) | Array.NUMERIC );
  413. //intersect_array.sortOn( "ymin", Array.DESCENDING | Array.NUMERIC );
  414. //Main.drawings.graphics.lineStyle( 0, 0x00FF00 );
  415. //Drawer.drawSegment( Main.drawings.graphics, intersect.debut, intersect.fin );
  416. dispatchEvent( new MarcheEvent( MarcheEvent.LOCALISE_SUPPORT, intersect_array[ 0 ].intersect, intersect_array[ 0 ].obstacle ) );
  417. }
  418. else {
  419. dispatchEvent( new MarcheEvent( MarcheEvent.NO_SUPPORT ) );
  420. trace(" pas de support" );
  421. }
  422. }
  423. public function repose(event:MoveEvent):void
  424. {
  425. stand(event);
  426. support = event.support;
  427. }
  428. public function get support():Obstacle
  429. {
  430. if ( pied_droit.support != null ) return pied_droit.support;
  431. if ( pied_gauche.support != null ) return pied_gauche.support;
  432. return null;
  433. }
  434. public function set support(o:Obstacle):void
  435. {
  436. pied_droit.support = o;
  437. pied_gauche.support = o;
  438. }
  439. public function stand(event:MoveEvent):void
  440. {
  441. //trace("stand " + event );
  442. if ( event.support == null )
  443. {
  444. trace( "il faut un support pour se stand." );
  445. return;
  446. }
  447. if ( event.point != null ) place = event.point;
  448. stayOnSupport( event.support, true, true );
  449. }
  450. public function stayOnSupport(obstacle:Obstacle, attract:Boolean = true, toujours:Boolean = false ):void
  451. {
  452. place = new Circle( support.plateforme.projection( place ), data.distance_support ).projection( place, attract, toujours );
  453. }
  454. public function move(event:MoveEvent):void
  455. {
  456. var cible:Point = (event.point as Point).clone();
  457. var vitesse:Point;
  458. if ( event.increment )
  459. {
  460. vitesse = cible;
  461. place = place.add( cible );
  462. }
  463. else {
  464. vitesse = cible.subtract( place );
  465. place = cible;
  466. }
  467. if ( event.support != null ) stayOnSupport( event.support );
  468. //positionne( pose.translation( new Point( -vitesse.x, -vitesse.y ) ) );
  469. if ( physics != null ) physics.vitesse = vitesse;
  470. }
  471. public function atterrit(event:MoveEvent):void
  472. {
  473. if ( animateurs.saut.running ) return;
  474. // event.point contient un tableau d'object { intersect:Point intersection, obstacle:Obstacle touché }
  475. var hitted_obstacles:Array = event.point;
  476. var hitted_obstacle:Obstacle = hitted_obstacles[ 0 ].obstacle;
  477. support = hitted_obstacle;
  478. // point sur la plateforme, que croise le vecteur deplacement de Person augmenté de data.distance_support_max
  479. var hitted_point:Point = hitted_obstacles[ 0 ].intersect;
  480. // calcul du point bas du Person p/r au support _bloc
  481. var cercle:Circle = new Circle( hitted_point, data.distance_support );
  482. var cible:Point = cercle.projection( place, true, true );
  483. pied_droit.support = support;
  484. pied_gauche.support = support;
  485. //Engine.unRegisterSoftBody( this );// fait, du côté de Engine
  486. var atterrissage:Animateur = new Animateur( this );
  487. atterrissage.action( "atterrissage" );
  488. atterrissage.configure( {
  489. support:support,
  490. sujet:this,
  491. place:place,
  492. cible:cible,
  493. vitesse:.2
  494. } );
  495. atterrissage.start();
  496. }
  497. public function decolle(event:MoveEvent):void
  498. {
  499. trace("decolle");
  500. support = null;
  501. physics = Engine.registerSoftBody( this );
  502. physics.vitesse = event.point.vitesse_sujet;
  503. if ( !Engine.started ) Engine.getInstance().start();
  504. }
  505. // mapping functions
  506. //override
  507. public function setPoseJoint( nextJoint:* ):void
  508. {
  509. var position:Point = nextJoint.position;
  510. var target:Point = _target_pose.getPosition( nextJoint.name );
  511. var startposition:Point = _start_pose.getPosition( nextJoint.name );
  512. var ikMover:IKMover = new IKMover( nextJoint, position );
  513. ikMover.limitByIteration = true;
  514. ikMover.iterationLimit = 6;
  515. var cible:Point = Point.interpolate( target, startposition, anim_increment );
  516. // contraintes
  517. var contrainte:Contrainte = contraintes[ nextJoint.name ]
  518. if ( contrainte != null ) cible = globalToLocal( contrainte );
  519. ikMover.moveTo( cible );
  520. }
  521. public function positionne( newpose:Pose, steps:int=0 ):void
  522. {
  523. //trace( "\t///////////////////////// positionne " + name );
  524. _start_pose = pose;
  525. _target_pose = newpose;
  526. anim_compteur.reset();
  527. if ( steps == 0 )
  528. {
  529. anim_increment = 1;
  530. parse_IKJoint_tree( setPoseJoint, tree.rootJoint );
  531. }
  532. else {
  533. anim_compteur.repeatCount = steps;
  534. anim_compteur.start();
  535. }
  536. //trace( "\t///////////////////////// ------------" );
  537. }
  538. // pour temporiser avant nouveau frame :
  539. private function _fin_tick( event:TimerEvent ):void
  540. {
  541. dispatchEvent( new MoveEvent( MoveEvent.FINFRAME ) );
  542. }
  543. private function _tick( event:TimerEvent ):void
  544. {
  545. anim_increment = anim_compteur.currentCount / anim_compteur.repeatCount;
  546. trace( ">increment> " + anim_increment );
  547. parse_IKJoint_tree( setPoseJoint, tree.rootJoint );
  548. }
  549. }
  550. }