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

/src/org/flixel/FlxSprite.as

https://github.com/ctin489/ShooterDemo
ActionScript | 790 lines | 491 code | 57 blank | 242 comment | 128 complexity | 3e1dacf73b5af86d61a006429447412f MD5 | raw file
  1. package org.flixel
  2. {
  3. import flash.display.Bitmap;
  4. import flash.display.BitmapData;
  5. import flash.display.Graphics;
  6. import flash.display.Sprite;
  7. import flash.geom.ColorTransform;
  8. import flash.geom.Matrix;
  9. import flash.geom.Point;
  10. import flash.geom.Rectangle;
  11. import org.flixel.data.FlxAnim;
  12. /**
  13. * The main "game object" class, handles basic physics and animation.
  14. */
  15. public class FlxSprite extends FlxObject
  16. {
  17. /**
  18. * Useful for controlling flipped animations and checking player orientation.
  19. */
  20. static public const LEFT:uint = 0;
  21. /**
  22. * Useful for controlling flipped animations and checking player orientation.
  23. */
  24. static public const RIGHT:uint = 1;
  25. /**
  26. * Useful for checking player orientation.
  27. */
  28. static public const UP:uint = 2;
  29. /**
  30. * Useful for checking player orientation.
  31. */
  32. static public const DOWN:uint = 3;
  33. /**
  34. * If you changed the size of your sprite object to shrink the bounding box,
  35. * you might need to offset the new bounding box from the top-left corner of the sprite.
  36. */
  37. public var offset:FlxPoint;
  38. /**
  39. * Change the size of your sprite's graphic.
  40. * NOTE: Scale doesn't currently affect collisions automatically,
  41. * you will need to adjust the width, height and offset manually.
  42. * WARNING: scaling sprites decreases rendering performance for this sprite by a factor of 10x!
  43. */
  44. public var scale:FlxPoint;
  45. /**
  46. * Blending modes, just like Photoshop!
  47. * E.g. "multiply", "screen", etc.
  48. * @default null
  49. */
  50. public var blend:String;
  51. /**
  52. * Controls whether the object is smoothed when rotated, affects performance.
  53. * @default false
  54. */
  55. public var antialiasing:Boolean;
  56. /**
  57. * Whether the current animation has finished its first (or only) loop.
  58. */
  59. public var finished:Boolean;
  60. /**
  61. * The width of the actual graphic or image being displayed (not necessarily the game object/bounding box).
  62. * NOTE: Edit at your own risk!! This is intended to be read-only.
  63. */
  64. public var frameWidth:uint;
  65. /**
  66. * The height of the actual graphic or image being displayed (not necessarily the game object/bounding box).
  67. * NOTE: Edit at your own risk!! This is intended to be read-only.
  68. */
  69. public var frameHeight:uint;
  70. /**
  71. * The total number of frames in this image (assumes each row is full).
  72. */
  73. public var frames:uint;
  74. //Animation helpers
  75. protected var _animations:Array;
  76. protected var _flipped:uint;
  77. protected var _curAnim:FlxAnim;
  78. protected var _curFrame:uint;
  79. protected var _caf:uint;
  80. protected var _frameTimer:Number;
  81. protected var _callback:Function;
  82. protected var _facing:uint;
  83. protected var _bakedRotation:Number;
  84. //Various rendering helpers
  85. protected var _flashRect:Rectangle;
  86. protected var _flashRect2:Rectangle;
  87. protected var _flashPointZero:Point;
  88. protected var _pixels:BitmapData;
  89. protected var _framePixels:BitmapData;
  90. protected var _alpha:Number;
  91. protected var _color:uint;
  92. protected var _ct:ColorTransform;
  93. protected var _mtx:Matrix;
  94. protected var _bbb:BitmapData;
  95. protected var _boundsVisible:Boolean;
  96. static protected var _gfxSprite:Sprite;
  97. static protected var _gfx:Graphics;
  98. /**
  99. * Creates a white 8x8 square <code>FlxSprite</code> at the specified position.
  100. * Optionally can load a simple, one-frame graphic instead.
  101. *
  102. * @param X The initial X position of the sprite.
  103. * @param Y The initial Y position of the sprite.
  104. * @param SimpleGraphic The graphic you want to display (OPTIONAL - for simple stuff only, do NOT use for animated images!).
  105. */
  106. public function FlxSprite(X:Number=0,Y:Number=0,SimpleGraphic:Class=null)
  107. {
  108. super();
  109. x = X;
  110. y = Y;
  111. _flashRect = new Rectangle();
  112. _flashRect2 = new Rectangle();
  113. _flashPointZero = new Point();
  114. offset = new FlxPoint();
  115. scale = new FlxPoint(1,1);
  116. _alpha = 1;
  117. _color = 0x00ffffff;
  118. blend = null;
  119. antialiasing = false;
  120. finished = false;
  121. _facing = RIGHT;
  122. _animations = new Array();
  123. _flipped = 0;
  124. _curAnim = null;
  125. _curFrame = 0;
  126. _caf = 0;
  127. _frameTimer = 0;
  128. _mtx = new Matrix();
  129. _callback = null;
  130. if(_gfxSprite == null)
  131. {
  132. _gfxSprite = new Sprite();
  133. _gfx = _gfxSprite.graphics;
  134. }
  135. if(SimpleGraphic == null)
  136. createGraphic(8,8);
  137. else
  138. loadGraphic(SimpleGraphic);
  139. }
  140. /**
  141. * Load an image from an embedded graphic file.
  142. *
  143. * @param Graphic The image you want to use.
  144. * @param Animated Whether the Graphic parameter is a single sprite or a row of sprites.
  145. * @param Reverse Whether you need this class to generate horizontally flipped versions of the animation frames.
  146. * @param Width OPTIONAL - Specify the width of your sprite (helps FlxSprite figure out what to do with non-square sprites or sprite sheets).
  147. * @param Height OPTIONAL - Specify the height of your sprite (helps FlxSprite figure out what to do with non-square sprites or sprite sheets).
  148. * @param Unique Whether the graphic should be a unique instance in the graphics cache.
  149. *
  150. * @return This FlxSprite instance (nice for chaining stuff together, if you're into that).
  151. */
  152. public function loadGraphic(Graphic:Class,Animated:Boolean=false,Reverse:Boolean=false,Width:uint=0,Height:uint=0,Unique:Boolean=false):FlxSprite
  153. {
  154. _bakedRotation = 0;
  155. _pixels = FlxG.addBitmap(Graphic,Reverse,Unique);
  156. if(Reverse)
  157. _flipped = _pixels.width>>1;
  158. else
  159. _flipped = 0;
  160. if(Width == 0)
  161. {
  162. if(Animated)
  163. Width = _pixels.height;
  164. else if(_flipped > 0)
  165. Width = _pixels.width*0.5;
  166. else
  167. Width = _pixels.width;
  168. }
  169. width = frameWidth = Width;
  170. if(Height == 0)
  171. {
  172. if(Animated)
  173. Height = width;
  174. else
  175. Height = _pixels.height;
  176. }
  177. height = frameHeight = Height;
  178. resetHelpers();
  179. return this;
  180. }
  181. /**
  182. * Create a pre-rotated sprite sheet from a simple sprite.
  183. * This can make a huge difference in graphical performance!
  184. *
  185. * @param Graphic The image you want to rotate & stamp.
  186. * @param Frames The number of frames you want to use (more == smoother rotations).
  187. * @param Offset Use this to select a specific frame to draw from the graphic.
  188. * @param AntiAliasing Whether to use high quality rotations when creating the graphic.
  189. * @param AutoBuffer Whether to automatically increase the image size to accomodate rotated corners.
  190. *
  191. * @return This FlxSprite instance (nice for chaining stuff together, if you're into that).
  192. */
  193. public function loadRotatedGraphic(Graphic:Class, Rotations:uint=16, Frame:int=-1, AntiAliasing:Boolean=false, AutoBuffer:Boolean=false):FlxSprite
  194. {
  195. //Create the brush and canvas
  196. var rows:uint = Math.sqrt(Rotations);
  197. var brush:BitmapData = FlxG.addBitmap(Graphic);
  198. if(Frame >= 0)
  199. {
  200. //Using just a segment of the graphic - find the right bit here
  201. var full:BitmapData = brush;
  202. brush = new BitmapData(full.height,full.height);
  203. var rx:uint = Frame*brush.width;
  204. var ry:uint = 0;
  205. var fw:uint = full.width;
  206. if(rx >= fw)
  207. {
  208. ry = uint(rx/fw)*brush.height;
  209. rx %= fw;
  210. }
  211. _flashRect.x = rx;
  212. _flashRect.y = ry;
  213. _flashRect.width = brush.width;
  214. _flashRect.height = brush.height;
  215. brush.copyPixels(full,_flashRect,_flashPointZero);
  216. }
  217. var max:uint = brush.width;
  218. if(brush.height > max)
  219. max = brush.height;
  220. if(AutoBuffer)
  221. max *= 1.5;
  222. var cols:uint = FlxU.ceil(Rotations/rows);
  223. width = max*cols;
  224. height = max*rows;
  225. var key:String = String(Graphic) + ":" + Frame + ":" + width + "x" + height;
  226. var skipGen:Boolean = FlxG.checkBitmapCache(key);
  227. _pixels = FlxG.createBitmap(width, height, 0, true, key);
  228. width = frameWidth = _pixels.width;
  229. height = frameHeight = _pixels.height;
  230. _bakedRotation = 360/Rotations;
  231. //Generate a new sheet if necessary, then fix up the width & height
  232. if(!skipGen)
  233. {
  234. var r:uint = 0;
  235. var c:uint;
  236. var ba:Number = 0;
  237. var bw2:uint = brush.width*0.5;
  238. var bh2:uint = brush.height*0.5;
  239. var gxc:uint = max*0.5;
  240. var gyc:uint = max*0.5;
  241. while(r < rows)
  242. {
  243. c = 0;
  244. while(c < cols)
  245. {
  246. _mtx.identity();
  247. _mtx.translate(-bw2,-bh2);
  248. _mtx.rotate(ba*0.017453293);
  249. _mtx.translate(max*c+gxc, gyc);
  250. ba += _bakedRotation;
  251. _pixels.draw(brush,_mtx,null,null,null,AntiAliasing);
  252. c++;
  253. }
  254. gyc += max;
  255. r++;
  256. }
  257. }
  258. frameWidth = frameHeight = width = height = max;
  259. resetHelpers();
  260. return this;
  261. }
  262. /**
  263. * This function creates a flat colored square image dynamically.
  264. *
  265. * @param Width The width of the sprite you want to generate.
  266. * @param Height The height of the sprite you want to generate.
  267. * @param Color Specifies the color of the generated block.
  268. * @param Unique Whether the graphic should be a unique instance in the graphics cache.
  269. * @param Key Optional parameter - specify a string key to identify this graphic in the cache. Trumps Unique flag.
  270. *
  271. * @return This FlxSprite instance (nice for chaining stuff together, if you're into that).
  272. */
  273. public function createGraphic(Width:uint,Height:uint,Color:uint=0xffffffff,Unique:Boolean=false,Key:String=null):FlxSprite
  274. {
  275. _bakedRotation = 0;
  276. _pixels = FlxG.createBitmap(Width,Height,Color,Unique,Key);
  277. width = frameWidth = _pixels.width;
  278. height = frameHeight = _pixels.height;
  279. resetHelpers();
  280. return this;
  281. }
  282. /**
  283. * Set <code>pixels</code> to any <code>BitmapData</code> object.
  284. * Automatically adjust graphic size and render helpers.
  285. */
  286. public function get pixels():BitmapData
  287. {
  288. return _pixels;
  289. }
  290. /**
  291. * @private
  292. */
  293. public function set pixels(Pixels:BitmapData):void
  294. {
  295. _pixels = Pixels;
  296. width = frameWidth = _pixels.width;
  297. height = frameHeight = _pixels.height;
  298. resetHelpers();
  299. }
  300. /**
  301. * Resets some important variables for sprite optimization and rendering.
  302. */
  303. protected function resetHelpers():void
  304. {
  305. _boundsVisible = false;
  306. _flashRect.x = 0;
  307. _flashRect.y = 0;
  308. _flashRect.width = frameWidth;
  309. _flashRect.height = frameHeight;
  310. _flashRect2.x = 0;
  311. _flashRect2.y = 0;
  312. _flashRect2.width = _pixels.width;
  313. _flashRect2.height = _pixels.height;
  314. if((_framePixels == null) || (_framePixels.width != width) || (_framePixels.height != height))
  315. _framePixels = new BitmapData(width,height);
  316. if((_bbb == null) || (_bbb.width != width) || (_bbb.height != height))
  317. _bbb = new BitmapData(width,height);
  318. origin.x = frameWidth*0.5;
  319. origin.y = frameHeight*0.5;
  320. _framePixels.copyPixels(_pixels,_flashRect,_flashPointZero);
  321. frames = (_flashRect2.width / _flashRect.width) * (_flashRect2.height / _flashRect.height);
  322. if(_ct != null) _framePixels.colorTransform(_flashRect,_ct);
  323. if(FlxG.showBounds)
  324. drawBounds();
  325. _caf = 0;
  326. refreshHulls();
  327. }
  328. /**
  329. * @private
  330. */
  331. override public function set solid(Solid:Boolean):void
  332. {
  333. var os:Boolean = _solid;
  334. _solid = Solid;
  335. if((os != _solid) && FlxG.showBounds)
  336. calcFrame();
  337. }
  338. /**
  339. * @private
  340. */
  341. override public function set fixed(Fixed:Boolean):void
  342. {
  343. var of:Boolean = _fixed;
  344. _fixed = Fixed;
  345. if((of != _fixed) && FlxG.showBounds)
  346. calcFrame();
  347. }
  348. /**
  349. * Set <code>facing</code> using <code>FlxSprite.LEFT</code>,<code>RIGHT</code>,
  350. * <code>UP</code>, and <code>DOWN</code> to take advantage of
  351. * flipped sprites and/or just track player orientation more easily.
  352. */
  353. public function get facing():uint
  354. {
  355. return _facing;
  356. }
  357. /**
  358. * @private
  359. */
  360. public function set facing(Direction:uint):void
  361. {
  362. var c:Boolean = _facing != Direction;
  363. _facing = Direction;
  364. if(c) calcFrame();
  365. }
  366. /**
  367. * Set <code>alpha</code> to a number between 0 and 1 to change the opacity of the sprite.
  368. */
  369. public function get alpha():Number
  370. {
  371. return _alpha;
  372. }
  373. /**
  374. * @private
  375. */
  376. public function set alpha(Alpha:Number):void
  377. {
  378. if(Alpha > 1) Alpha = 1;
  379. if(Alpha < 0) Alpha = 0;
  380. if(Alpha == _alpha) return;
  381. _alpha = Alpha;
  382. if((_alpha != 1) || (_color != 0x00ffffff)) _ct = new ColorTransform((_color>>16)*0.00392,(_color>>8&0xff)*0.00392,(_color&0xff)*0.00392,_alpha);
  383. else _ct = null;
  384. calcFrame();
  385. }
  386. /**
  387. * Set <code>color</code> to a number in this format: 0xRRGGBB.
  388. * <code>color</code> IGNORES ALPHA. To change the opacity use <code>alpha</code>.
  389. * Tints the whole sprite to be this color (similar to OpenGL vertex colors).
  390. */
  391. public function get color():uint
  392. {
  393. return _color;
  394. }
  395. /**
  396. * @private
  397. */
  398. public function set color(Color:uint):void
  399. {
  400. Color &= 0x00ffffff;
  401. if(_color == Color) return;
  402. _color = Color;
  403. if((_alpha != 1) || (_color != 0x00ffffff)) _ct = new ColorTransform((_color>>16)*0.00392,(_color>>8&0xff)*0.00392,(_color&0xff)*0.00392,_alpha);
  404. else _ct = null;
  405. calcFrame();
  406. }
  407. /**
  408. * This function draws or stamps one <code>FlxSprite</code> onto another.
  409. * This function is NOT intended to replace <code>render()</code>!
  410. *
  411. * @param Brush The image you want to use as a brush or stamp or pen or whatever.
  412. * @param X The X coordinate of the brush's top left corner on this sprite.
  413. * @param Y They Y coordinate of the brush's top left corner on this sprite.
  414. */
  415. public function draw(Brush:FlxSprite,X:int=0,Y:int=0):void
  416. {
  417. var b:BitmapData = Brush._framePixels;
  418. //Simple draw
  419. if(((Brush.angle == 0) || (Brush._bakedRotation > 0)) && (Brush.scale.x == 1) && (Brush.scale.y == 1) && (Brush.blend == null))
  420. {
  421. _flashPoint.x = X;
  422. _flashPoint.y = Y;
  423. _flashRect2.width = b.width;
  424. _flashRect2.height = b.height;
  425. _pixels.copyPixels(b,_flashRect2,_flashPoint,null,null,true);
  426. _flashRect2.width = _pixels.width;
  427. _flashRect2.height = _pixels.height;
  428. calcFrame();
  429. return;
  430. }
  431. //Advanced draw
  432. _mtx.identity();
  433. _mtx.translate(-Brush.origin.x,-Brush.origin.y);
  434. _mtx.scale(Brush.scale.x,Brush.scale.y);
  435. if(Brush.angle != 0)
  436. _mtx.rotate(Brush.angle * 0.017453293);
  437. _mtx.translate(X+Brush.origin.x,Y+Brush.origin.y);
  438. _pixels.draw(b,_mtx,null,Brush.blend,null,Brush.antialiasing);
  439. calcFrame();
  440. }
  441. /**
  442. * This function draws a line on this sprite from position X1,Y1
  443. * to position X2,Y2 with the specified color.
  444. *
  445. * @param StartX X coordinate of the line's start point.
  446. * @param StartY Y coordinate of the line's start point.
  447. * @param EndX X coordinate of the line's end point.
  448. * @param EndY Y coordinate of the line's end point.
  449. * @param Color The line's color.
  450. * @param Thickness How thick the line is in pixels (default value is 1).
  451. */
  452. public function drawLine(StartX:Number,StartY:Number,EndX:Number,EndY:Number,Color:uint,Thickness:uint=1):void
  453. {
  454. //Draw line
  455. _gfx.clear();
  456. _gfx.moveTo(StartX,StartY);
  457. _gfx.lineStyle(Thickness,Color);
  458. _gfx.lineTo(EndX,EndY);
  459. //Cache line to bitmap
  460. _pixels.draw(_gfxSprite);
  461. calcFrame();
  462. }
  463. /**
  464. * Fills this sprite's graphic with a specific color.
  465. *
  466. * @param Color The color with which to fill the graphic, format 0xAARRGGBB.
  467. */
  468. public function fill(Color:uint):void
  469. {
  470. _pixels.fillRect(_flashRect2,Color);
  471. if(_pixels != _framePixels)
  472. calcFrame();
  473. }
  474. /**
  475. * Internal function for updating the sprite's animation.
  476. * Useful for cases when you need to update this but are buried down in too many supers.
  477. * This function is called automatically by <code>FlxSprite.update()</code>.
  478. */
  479. protected function updateAnimation():void
  480. {
  481. if(_bakedRotation)
  482. {
  483. var oc:uint = _caf;
  484. var ta:int = angle%360;
  485. if(ta < 0)
  486. ta += 360;
  487. _caf = ta/_bakedRotation;
  488. if(oc != _caf)
  489. calcFrame();
  490. return;
  491. }
  492. if((_curAnim != null) && (_curAnim.delay > 0) && (_curAnim.looped || !finished))
  493. {
  494. _frameTimer += FlxG.elapsed;
  495. while(_frameTimer > _curAnim.delay)
  496. {
  497. _frameTimer = _frameTimer - _curAnim.delay;
  498. if(_curFrame == _curAnim.frames.length-1)
  499. {
  500. if(_curAnim.looped) _curFrame = 0;
  501. finished = true;
  502. }
  503. else
  504. _curFrame++;
  505. _caf = _curAnim.frames[_curFrame];
  506. calcFrame();
  507. }
  508. }
  509. }
  510. /**
  511. * Main game loop update function. Override this to create your own sprite logic!
  512. * Just don't forget to call super.update() or any of the helper functions.
  513. */
  514. override public function update():void
  515. {
  516. updateMotion();
  517. updateAnimation();
  518. updateFlickering();
  519. }
  520. /**
  521. * Internal function that performs the actual sprite rendering, called by render().
  522. */
  523. protected function renderSprite():void
  524. {
  525. if(FlxG.showBounds != _boundsVisible)
  526. calcFrame();
  527. getScreenXY(_point);
  528. _flashPoint.x = _point.x;
  529. _flashPoint.y = _point.y;
  530. //Simple render
  531. if(((angle == 0) || (_bakedRotation > 0)) && (scale.x == 1) && (scale.y == 1) && (blend == null))
  532. {
  533. FlxG.buffer.copyPixels(_framePixels,_flashRect,_flashPoint,null,null,true);
  534. return;
  535. }
  536. //Advanced render
  537. _mtx.identity();
  538. _mtx.translate(-origin.x,-origin.y);
  539. _mtx.scale(scale.x,scale.y);
  540. if(angle != 0)
  541. _mtx.rotate(angle * 0.017453293);
  542. _mtx.translate(_point.x+origin.x,_point.y+origin.y);
  543. FlxG.buffer.draw(_framePixels,_mtx,null,blend,null,antialiasing);
  544. }
  545. /**
  546. * Called by game loop, updates then blits or renders current frame of animation to the screen
  547. */
  548. override public function render():void
  549. {
  550. renderSprite();
  551. }
  552. /**
  553. * Checks to see if a point in 2D space overlaps this FlxCore object.
  554. *
  555. * @param X The X coordinate of the point.
  556. * @param Y The Y coordinate of the point.
  557. * @param PerPixel Whether or not to use per pixel collision checking.
  558. *
  559. * @return Whether or not the point overlaps this object.
  560. */
  561. override public function overlapsPoint(X:Number,Y:Number,PerPixel:Boolean = false):Boolean
  562. {
  563. X = X + FlxU.floor(FlxG.scroll.x);
  564. Y = Y + FlxU.floor(FlxG.scroll.y);
  565. getScreenXY(_point);
  566. if(PerPixel)
  567. return _framePixels.hitTest(new Point(0,0),0xFF,new Point(X-_point.x,Y-_point.y));
  568. else if((X <= _point.x) || (X >= _point.x+frameWidth) || (Y <= _point.y) || (Y >= _point.y+frameHeight))
  569. return false;
  570. return true;
  571. }
  572. /**
  573. * Triggered whenever this sprite is launched by a <code>FlxEmitter</code>.
  574. */
  575. virtual public function onEmit():void { }
  576. /**
  577. * Adds a new animation to the sprite.
  578. *
  579. * @param Name What this animation should be called (e.g. "run").
  580. * @param Frames An array of numbers indicating what frames to play in what order (e.g. 1, 2, 3).
  581. * @param FrameRate The speed in frames per second that the animation should play at (e.g. 40 fps).
  582. * @param Looped Whether or not the animation is looped or just plays once.
  583. */
  584. public function addAnimation(Name:String, Frames:Array, FrameRate:Number=0, Looped:Boolean=true):void
  585. {
  586. _animations.push(new FlxAnim(Name,Frames,FrameRate,Looped));
  587. }
  588. /**
  589. * Pass in a function to be called whenever this sprite's animation changes.
  590. *
  591. * @param AnimationCallback A function that has 3 parameters: a string name, a uint frame number, and a uint frame index.
  592. */
  593. public function addAnimationCallback(AnimationCallback:Function):void
  594. {
  595. _callback = AnimationCallback;
  596. }
  597. /**
  598. * Plays an existing animation (e.g. "run").
  599. * If you call an animation that is already playing it will be ignored.
  600. *
  601. * @param AnimName The string name of the animation you want to play.
  602. * @param Force Whether to force the animation to restart.
  603. */
  604. public function play(AnimName:String,Force:Boolean=false):void
  605. {
  606. if(!Force && (_curAnim != null) && (AnimName == _curAnim.name) && (_curAnim.looped || !finished)) return;
  607. _curFrame = 0;
  608. _caf = 0;
  609. _frameTimer = 0;
  610. var i:uint = 0;
  611. var al:uint = _animations.length;
  612. while(i < al)
  613. {
  614. if(_animations[i].name == AnimName)
  615. {
  616. _curAnim = _animations[i];
  617. if(_curAnim.delay <= 0)
  618. finished = true;
  619. else
  620. finished = false;
  621. _caf = _curAnim.frames[_curFrame];
  622. calcFrame();
  623. return;
  624. }
  625. i++;
  626. }
  627. }
  628. /**
  629. * Tell the sprite to change to a random frame of animation
  630. * Useful for instantiating particles or other weird things.
  631. */
  632. public function randomFrame():void
  633. {
  634. _curAnim = null;
  635. _caf = int(FlxU.random()*(_pixels.width/frameWidth));
  636. calcFrame();
  637. }
  638. /**
  639. * Tell the sprite to change to a specific frame of animation.
  640. *
  641. * @param Frame The frame you want to display.
  642. */
  643. public function get frame():uint
  644. {
  645. return _caf;
  646. }
  647. /**
  648. * @private
  649. */
  650. public function set frame(Frame:uint):void
  651. {
  652. _curAnim = null;
  653. _caf = Frame;
  654. calcFrame();
  655. }
  656. /**
  657. * Call this function to figure out the on-screen position of the object.
  658. *
  659. * @param P Takes a <code>Point</code> object and assigns the post-scrolled X and Y values of this object to it.
  660. *
  661. * @return The <code>Point</code> you passed in, or a new <code>Point</code> if you didn't pass one, containing the screen X and Y position of this object.
  662. */
  663. override public function getScreenXY(Point:FlxPoint=null):FlxPoint
  664. {
  665. if(Point == null) Point = new FlxPoint();
  666. Point.x = FlxU.floor(x + FlxU.roundingError)+FlxU.floor(FlxG.scroll.x*scrollFactor.x) - offset.x;
  667. Point.y = FlxU.floor(y + FlxU.roundingError)+FlxU.floor(FlxG.scroll.y*scrollFactor.y) - offset.y;
  668. return Point;
  669. }
  670. /**
  671. * Internal function to update the current animation frame.
  672. */
  673. protected function calcFrame():void
  674. {
  675. _boundsVisible = false;
  676. var rx:uint = _caf*frameWidth;
  677. var ry:uint = 0;
  678. //Handle sprite sheets
  679. var w:uint = _flipped?_flipped:_pixels.width;
  680. if(rx >= w)
  681. {
  682. ry = uint(rx/w)*frameHeight;
  683. rx %= w;
  684. }
  685. //handle reversed sprites
  686. if(_flipped && (_facing == LEFT))
  687. rx = (_flipped<<1)-rx-frameWidth;
  688. //Update display bitmap
  689. _flashRect.x = rx;
  690. _flashRect.y = ry;
  691. _framePixels.copyPixels(_pixels,_flashRect,_flashPointZero);
  692. _flashRect.x = _flashRect.y = 0;
  693. if(_ct != null) _framePixels.colorTransform(_flashRect,_ct);
  694. if(FlxG.showBounds)
  695. drawBounds();
  696. if(_callback != null) _callback(_curAnim.name,_curFrame,_caf);
  697. }
  698. protected function drawBounds():void
  699. {
  700. _boundsVisible = true;
  701. if((_bbb == null) || (_bbb.width != width) || (_bbb.height != height))
  702. _bbb = new BitmapData(width,height);
  703. var bbbc:uint = getBoundingColor();
  704. _bbb.fillRect(_flashRect,0);
  705. var ofrw:uint = _flashRect.width;
  706. var ofrh:uint = _flashRect.height;
  707. _flashRect.width = int(width);
  708. _flashRect.height = int(height);
  709. _bbb.fillRect(_flashRect,bbbc);
  710. _flashRect.width = _flashRect.width - 2;
  711. _flashRect.height = _flashRect.height - 2;
  712. _flashRect.x = 1;
  713. _flashRect.y = 1;
  714. _bbb.fillRect(_flashRect,0);
  715. _flashRect.width = ofrw;
  716. _flashRect.height = ofrh;
  717. _flashRect.x = _flashRect.y = 0;
  718. _flashPoint.x = int(offset.x);
  719. _flashPoint.y = int(offset.y);
  720. _framePixels.copyPixels(_bbb,_flashRect,_flashPoint,null,null,true);
  721. }
  722. /**
  723. * Internal function, currently only used to quickly update FlxState.screen for post-processing.
  724. * Potentially super-unsafe, since it doesn't call <code>resetHelpers()</code>!
  725. *
  726. * @param Pixels The <code>BitmapData</code> object you want to point at.
  727. */
  728. internal function unsafeBind(Pixels:BitmapData):void
  729. {
  730. _pixels = _framePixels = Pixels;
  731. }
  732. }
  733. }