PageRenderTime 56ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/demos/OneWayPlatforms/Main.hx

http://nape.googlecode.com/
Haxe | 252 lines | 132 code | 52 blank | 68 comment | 22 complexity | 7367b58e5da6a061de40bca1043a2578 MD5 | raw file
  1. /*
  2. * Stage size 800x600
  3. * fps 60
  4. *
  5. * Necessitates that there 'is' a sound Bang in the library.
  6. */
  7. package;
  8. //urgh far too many imports!
  9. import nape.Space;
  10. import nape.PhysObj;
  11. import nape.Tools;
  12. import nape.Geom;
  13. import nape.PhysAux;
  14. import nape.Dynamics;
  15. import nape.Constraint;
  16. import flash.Lib;
  17. import flash.text.TextField;
  18. import flash.events.Event;
  19. import flash.events.MouseEvent;
  20. import flash.display.StageQuality;
  21. import flash.display.Bitmap;
  22. import flash.display.BitmapData;
  23. import flash.display.Sprite;
  24. import flash.filters.ColorMatrixFilter;
  25. import flash.geom.Point;
  26. import flash.geom.Rectangle;
  27. import flash.media.Sound;
  28. import flash.media.SoundTransform;
  29. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  30. class Main {
  31. static var space:Space;
  32. //cbType values for objects.
  33. static var OBJECT :Int = CbType.get();
  34. static var PLATFORM:Int = CbType.get();
  35. static var IN_BIN :Int = CbType.get();
  36. static var OUT_BIN :Int = CbType.get();
  37. static var fps:TextField;
  38. //shiz for the fade-out of removed objects.
  39. static var bit:BitmapData;
  40. static var conv:ColorMatrixFilter;
  41. static var graph:Sprite;
  42. static function main() {
  43. //set up bitmap for fade outs (could be done differently, but i like bitmaps :P)
  44. bit = new BitmapData(800, 600, true, 0);
  45. graph = new Sprite();
  46. Lib.current.addChild(new Bitmap(bit));
  47. conv = new ColorMatrixFilter([1,0,0,0,0, 0,1,0,0,0, 0,0,1,0,0, 0,0,0,0.85,0]);
  48. fps = new TextField();
  49. Lib.current.addChild(fps);
  50. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  51. space = new UniformSleepSpace(0,0,800,600,15, new Vec2(0,250));
  52. var b:Body;
  53. //create platforms
  54. b = Tools.createBox(200, 300, 250, 10, 0, 0, 0, true, Material.Wood);
  55. b.cbType = PLATFORM; space.addObject(b);
  56. Lib.current.addChild(b.graphic);
  57. b = Tools.createBox(600, 300, 250, 10, 0, 0, 0, true, Material.Wood);
  58. b.cbType = PLATFORM; space.addObject(b);
  59. Lib.current.addChild(b.graphic);
  60. b = Tools.createBox(400, 100, 300, 25, 0, 0, 0, true, Material.Wood);
  61. b.cbType = PLATFORM; space.addObject(b);
  62. Lib.current.addChild(b.graphic);
  63. b = Tools.createBox(400, 500, 500, 50, 0, 0, 0, true, Material.Wood);
  64. b.cbType = PLATFORM; space.addObject(b);
  65. Lib.current.addChild(b.graphic);
  66. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  67. //create sensor bins.
  68. // note the values for group layer, and sensor layer.
  69. // 0 collision => can never collide
  70. // 1 sensor => acts in layer 1.
  71. b = Tools.createBox(300, 400, 150, 30, 0, 0, 0, true, Material.Tire, 0, 1);
  72. b.cbType = IN_BIN; space.addObject(b);
  73. Lib.current.addChild(b.graphic); b.graphic.alpha = 0.5;
  74. b = Tools.createBox(500, 400, 150, 30, 0, 0, 0, true, Material.Rubber, 0, 1);
  75. b.cbType = OUT_BIN; space.addObject(b);
  76. Lib.current.addChild(b.graphic); b.graphic.alpha = 0.5;
  77. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  78. //----assign callbacks to the type pairs
  79. //one-way platforms
  80. space.addCbPreBegin (OBJECT, PLATFORM, cbOneWay);
  81. //sounds
  82. //use post-solve to get a sound for every single impact
  83. // rather than 'begin' wherein in the case of a box hitting the ground
  84. // and then rotating down to have a second impact without it seperating not
  85. // generating a second sound. impactImpulse only takes into account
  86. // new contacts, so there's no issues of generating sounds when objects
  87. // are simply in a stack etc.
  88. //can easily use 'begin' anyways for effeciency reasons perhaps.
  89. // the overall result isn't so different.
  90. space.addCbPostSolve(OBJECT, PLATFORM);
  91. space.addCbPostSolve(OBJECT, OBJECT);
  92. //removal of objects for bins.
  93. space.addCbSenseBegin(IN_BIN, OBJECT);
  94. space.addCbSenseEnd (OUT_BIN, OBJECT);
  95. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  96. //set graphical quality to medium
  97. Lib.current.stage.quality = StageQuality.MEDIUM;
  98. //set up events
  99. Lib.current.stage.addEventListener(Event.ENTER_FRAME, enterFrame);
  100. Lib.current.stage.addEventListener(MouseEvent.MOUSE_DOWN, mdown);
  101. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  102. //create a list of Bang's up to flash limit of concurrent sounds
  103. bangs = new Array<Bang>();
  104. for (i in 0...32)
  105. bangs.push(new Bang());
  106. }
  107. static function mdown(ev) {
  108. for(i in 0...10) {
  109. var b:PhysObj;
  110. var mx = ev.stageX +Math.random() * 50 - 25;
  111. var my = ev.stageY +Math.random() * 50 - 25;
  112. var vy = (my > 300) ? -400 : 0;
  113. var m = (my > 300) ? Material.Steel : Material.Tire;
  114. // note collision and sensor layers
  115. // collision = 0xffffffff => collides with everything
  116. // sensor = 1 => senses in the first layer, matching with that of the bins.
  117. b = Tools.createBox(mx, my, 14,14, 0, vy, 0, false, m, 0xffffffff, 1);
  118. b.cbType = OBJECT; space.addObject(b);
  119. Lib.current.addChild(b.graphic);
  120. }
  121. }
  122. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  123. static function cbOneWay(arb:Arbiter):Int {
  124. //grab first contact in arbiter.
  125. var con = arb.contacts.front();
  126. //if contact normal points wrong way, let object move through platform
  127. // here i abuse the fact that platforms are all static, and therefore
  128. // the contact normal MUST be pointing away from the platform.
  129. // without knowledge of this inner working of the engine, you could
  130. // still simply do it as below with the bins and compare cbTypes to know
  131. // which object is which, to know which direction normal will be pointing
  132. return if (con.ny < 0) Callback.ACCEPT else Callback.IGNORE;
  133. }
  134. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  135. //in the following, i've not abused the fact that both bins
  136. //are static: I 'could' have abused this, and therefore assumed that
  137. //p2 will always be the object to be removed.
  138. static inline function cbBin(cb:Callback,type:Int) {
  139. var p1 = cb.obj_arb.p1; var p2 = cb.obj_arb.p2;
  140. var rem = if (p1.cbType == type) p2 else p1;
  141. //rem = p2; is equivalent should you abuse the fact that the bins are static.
  142. // again, this depends however on internal knowledge of the engine workings.
  143. space.removeObject(rem);
  144. if (Lib.current.contains(rem.graphic)) Lib.current.removeChild(rem.graphic);
  145. bit.draw(rem.graphic,rem.graphic.transform.matrix);
  146. }
  147. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  148. //sound shiz.
  149. static var bangs:Array<Bang>;
  150. static var cbang = 0;
  151. static var soundt:SoundTransform = new SoundTransform();
  152. static var psound = 0; static var pvol = 0.0;
  153. static function enterFrame(ev) {
  154. //step 1/60th of a second through time in space.
  155. //not bothered with variable time step here clearly.
  156. space.step(1 / 60, 6, 8);
  157. //apply filter to bitmap.
  158. bit.applyFilter(bit, new Rectangle(0, 0, 800, 600), new Point(0, 0), conv);
  159. //max volume, pan accumulator, impact count.
  160. var vol = 0.;
  161. var pan = 0.;
  162. var cnt = 0;
  163. //iterate the non-immediate callbacks.
  164. while(!space.callbacks.empty()) {
  165. var cb = space.callbacks.pop();
  166. if (cb.type == Callback.SENSE_BEGIN) cbBin(cb,IN_BIN);
  167. else if (cb.type == Callback.SENSE_END) cbBin(cb, OUT_BIN);
  168. else if (cb.type == Callback.POST_SOLVE) {
  169. var oarb = cb.obj_arb;
  170. //iterate associated arbiters.
  171. var ite = oarb.arbiters.begin();
  172. while (ite != oarb.arbiters.end()) {
  173. var arb = ite.elem();
  174. //use first contact position as an aprox. to impact position for sound
  175. //not neccessary to be perfect for sound panning.
  176. var impact = arb.impactImpulse();
  177. pan += -1 + 2 * arb.contacts.front().px / 800;
  178. var cvol = Math.sqrt(impact.px * impact.px + impact.py * impact.py) * 2e-6;
  179. if (cvol > vol) vol = cvol;
  180. cnt++;
  181. ite = ite.next;
  182. }
  183. }
  184. }
  185. //sound is only played if it's volume is not tiny.
  186. // and either it is significantly louder than previously played sound
  187. // or sufficient time has passed since the previous sound was played (5 frames)
  188. //this helps de-clutter the sound and makes it not just sound horrible.
  189. if (vol > 0.01 && (space.stamp - psound > 5 || vol>pvol+0.15)) {
  190. psound = space.stamp;
  191. pvol = vol;
  192. soundt.volume = vol;
  193. soundt.pan = pan / cnt;
  194. bangs[cbang++].play(150, 0, soundt);
  195. }
  196. cbang %= 32;
  197. }
  198. }
  199. //dummy Bang class to link against the Bang sound in library swf.
  200. class Bang extends Sound { public function new() { super(); } }