Permalink
Browse files

FlashPunk snapshot from 2010-11-20: https://github.com/Draknek/FlashP…

  • Loading branch information...
1 parent d09848e commit 5814cdaac0a155e5f7c5fb5f3d034122feb1b872 @Draknek committed Nov 20, 2010
Showing with 10,675 additions and 1 deletion.
  1. +0 −1 net
  2. +292 −0 net/flashpunk/Engine.as
  3. +765 −0 net/flashpunk/Entity.as
  4. +901 −0 net/flashpunk/FP.as
  5. +85 −0 net/flashpunk/Graphic.as
  6. +78 −0 net/flashpunk/Mask.as
  7. +41 −0 net/flashpunk/README.markdown
  8. +223 −0 net/flashpunk/Screen.as
  9. +144 −0 net/flashpunk/Sfx.as
  10. +190 −0 net/flashpunk/Tween.as
  11. +119 −0 net/flashpunk/Tweener.as
  12. +1,128 −0 net/flashpunk/World.as
  13. +898 −0 net/flashpunk/debug/Console.as
  14. BIN net/flashpunk/debug/console_debug.png
  15. BIN net/flashpunk/debug/console_logo.png
  16. BIN net/flashpunk/debug/console_output.png
  17. BIN net/flashpunk/debug/console_pause.png
  18. BIN net/flashpunk/debug/console_play.png
  19. BIN net/flashpunk/debug/console_step.png
  20. BIN net/flashpunk/graphics/04B_03__.TTF
  21. +66 −0 net/flashpunk/graphics/Anim.as
  22. +69 −0 net/flashpunk/graphics/Backdrop.as
  23. +342 −0 net/flashpunk/graphics/Canvas.as
  24. +260 −0 net/flashpunk/graphics/Emitter.as
  25. +142 −0 net/flashpunk/graphics/Graphiclist.as
  26. +314 −0 net/flashpunk/graphics/Image.as
  27. +35 −0 net/flashpunk/graphics/Particle.as
  28. +157 −0 net/flashpunk/graphics/ParticleType.as
  29. +106 −0 net/flashpunk/graphics/PreRotation.as
  30. +252 −0 net/flashpunk/graphics/Spritemap.as
  31. +56 −0 net/flashpunk/graphics/Stamp.as
  32. +277 −0 net/flashpunk/graphics/Text.as
  33. +102 −0 net/flashpunk/graphics/TiledImage.as
  34. +109 −0 net/flashpunk/graphics/TiledSpritemap.as
  35. +362 −0 net/flashpunk/graphics/Tilemap.as
  36. +22 −0 net/flashpunk/license.txt
  37. +268 −0 net/flashpunk/masks/Grid.as
  38. +114 −0 net/flashpunk/masks/Hitbox.as
  39. +159 −0 net/flashpunk/masks/Masklist.as
  40. +97 −0 net/flashpunk/masks/Pixelmask.as
  41. +44 −0 net/flashpunk/tweens/TweenInfo.as
  42. +46 −0 net/flashpunk/tweens/misc/Alarm.as
  43. +58 −0 net/flashpunk/tweens/misc/AngleTween.as
  44. +100 −0 net/flashpunk/tweens/misc/ColorTween.as
  45. +61 −0 net/flashpunk/tweens/misc/MultiVarTween.as
  46. +52 −0 net/flashpunk/tweens/misc/NumTween.as
  47. +56 −0 net/flashpunk/tweens/misc/VarTween.as
  48. +94 −0 net/flashpunk/tweens/motion/CircularMotion.as
  49. +69 −0 net/flashpunk/tweens/motion/CubicMotion.as
  50. +86 −0 net/flashpunk/tweens/motion/LinearMotion.as
  51. +133 −0 net/flashpunk/tweens/motion/LinearPath.as
  52. +32 −0 net/flashpunk/tweens/motion/Motion.as
  53. +112 −0 net/flashpunk/tweens/motion/QuadMotion.as
  54. +192 −0 net/flashpunk/tweens/motion/QuadPath.as
  55. +48 −0 net/flashpunk/tweens/sound/Fader.as
  56. +94 −0 net/flashpunk/tweens/sound/SfxFader.as
  57. +146 −0 net/flashpunk/utils/Data.as
  58. +376 −0 net/flashpunk/utils/Draw.as
  59. +214 −0 net/flashpunk/utils/Ease.as
  60. +296 −0 net/flashpunk/utils/Input.as
  61. +193 −0 net/flashpunk/utils/Key.as
View
1 net
View
292 net/flashpunk/Engine.as
@@ -0,0 +1,292 @@
+package net.flashpunk
+{
+ import flash.display.Bitmap;
+ import flash.display.BitmapData;
+ import flash.display.MovieClip;
+ import flash.display.StageAlign;
+ import flash.display.StageDisplayState;
+ import flash.display.StageQuality;
+ import flash.display.StageScaleMode;
+ import flash.events.Event;
+ import flash.events.TimerEvent;
+ import flash.geom.Rectangle;
+ import flash.utils.getTimer;
+ import flash.utils.Timer;
+ import net.flashpunk.utils.Draw;
+ import net.flashpunk.utils.Input;
+
+ /**
+ * Main game Sprite class, added to the Flash Stage. Manages the game loop.
+ */
+ public class Engine extends MovieClip
+ {
+ /**
+ * If the game should stop updating/rendering.
+ */
+ public var paused:Boolean = false;
+
+ /**
+ * Cap on the elapsed time (default at 30 FPS). Raise this to allow for lower framerates (eg. 1 / 10).
+ */
+ public var maxElapsed:Number = 0.0333;
+
+ /**
+ * The max amount of frames that can be skipped in fixed framerate mode.
+ */
+ public var maxFrameSkip:uint = 5;
+
+ /**
+ * The amount of milliseconds between ticks in fixed framerate mode.
+ */
+ public var tickRate:uint = 4;
+
+ /**
+ * Constructor. Defines startup information about your game.
+ * @param width The width of your game.
+ * @param height The height of your game.
+ * @param frameRate The game framerate, in frames per second.
+ * @param fixed If a fixed-framerate should be used.
+ */
+ public function Engine(width:uint, height:uint, frameRate:Number = 60, fixed:Boolean = false)
+ {
+ // global game properties
+ FP.width = width;
+ FP.height = height;
+ FP.assignedFrameRate = frameRate;
+ FP.fixed = fixed;
+
+ // global game objects
+ FP.engine = this;
+ FP.screen = new Screen;
+ FP.bounds = new Rectangle(0, 0, width, height);
+ FP._world = new World;
+
+ // miscellanious startup stuff
+ if (FP.randomSeed == 0) FP.randomizeSeed();
+ FP.entity = new Entity;
+ FP._time = getTimer();
+
+ // on-stage event listener
+ addEventListener(Event.ADDED_TO_STAGE, onStage);
+ }
+
+ /**
+ * Override this, called after Engine has been added to the stage.
+ */
+ public function init():void
+ {
+
+ }
+
+ /**
+ * Updates the game, updating the World and Entities.
+ */
+ public function update():void
+ {
+ if (FP._world.active)
+ {
+ Tween.update();
+ if (FP._world._tween) FP._world.updateTweens();
+ FP._world.update();
+ }
+ FP._world.updateLists();
+ if (FP._goto) checkWorld();
+ }
+
+ /**
+ * Renders the game, rendering the World and Entities.
+ */
+ public function render():void
+ {
+ // timing stuff
+ var t:Number = getTimer();
+ if (!_frameLast) _frameLast = t;
+
+ // render loop
+ FP.screen.swap();
+ Draw.resetTarget();
+ FP.screen.refresh();
+ if (FP._world.visible) FP._world.render();
+ FP.screen.redraw();
+
+ // more timing stuff
+ t = getTimer();
+ _frameListSum += (_frameList[_frameList.length] = t - _frameLast);
+ if (_frameList.length > 10) _frameListSum -= _frameList.shift();
+ FP.frameRate = 1000 / (_frameListSum / _frameList.length);
+ _frameLast = t;
+ }
+
+ /**
+ * Sets the game's stage properties. Override this to set them differently.
+ */
+ public function setStageProperties():void
+ {
+ stage.frameRate = FP.assignedFrameRate;
+ stage.align = StageAlign.TOP_LEFT;
+ stage.quality = StageQuality.HIGH;
+ stage.scaleMode = StageScaleMode.NO_SCALE;
+ stage.displayState = StageDisplayState.NORMAL;
+ }
+
+ /** @private Event handler for stage entry. */
+ private function onStage(e:Event = null):void
+ {
+ // remove event listener
+ removeEventListener(Event.ADDED_TO_STAGE, onStage);
+
+ // set stage properties
+ FP.stage = stage;
+ setStageProperties();
+
+ // enable input
+ Input.enable();
+
+ // switch worlds
+ if (FP._goto) checkWorld();
+
+ // game start
+ init();
+
+ // start game loop
+ _rate = 1000 / FP.assignedFrameRate;
+ if (FP.fixed)
+ {
+ // fixed framerate
+ _skip = _rate * maxFrameSkip;
+ _last = _prev = getTimer();
+ _timer = new Timer(tickRate);
+ _timer.addEventListener(TimerEvent.TIMER, onTimer);
+ _timer.start();
+ }
+ else
+ {
+ // nonfixed framerate
+ _last = getTimer();
+ addEventListener(Event.ENTER_FRAME, onEnterFrame);
+ }
+ }
+
+ /** @private Framerate independent game loop. */
+ private function onEnterFrame(e:Event):void
+ {
+ // update timer
+ _time = _gameTime = getTimer();
+ FP._flashTime = _time - _flashTime;
+ _updateTime = _time;
+ FP.elapsed = (_time - _last) / 1000;
+ if (FP.elapsed > maxElapsed) FP.elapsed = maxElapsed;
+ FP.elapsed *= FP.rate;
+ _last = _time;
+
+ // update console
+ if (FP._console) FP._console.update();
+
+ // update loop
+ if (!paused) update();
+
+ // update input
+ Input.update();
+
+ // update timer
+ _time = _renderTime = getTimer();
+ FP._updateTime = _time - _updateTime;
+
+ // render loop
+ if (!paused) render();
+
+ // update timer
+ _time = _flashTime = getTimer();
+ FP._renderTime = _time - _renderTime;
+ FP._gameTime = _time - _gameTime;
+ }
+
+ /** @private Fixed framerate game loop. */
+ private function onTimer(e:TimerEvent):void
+ {
+ // update timer
+ _time = getTimer();
+ _delta += (_time - _last);
+ _last = _time;
+
+ // quit if a frame hasn't passed
+ if (_delta < _rate) return;
+
+ // update timer
+ _gameTime = _time;
+ FP._flashTime = _time - _flashTime;
+
+ // update console
+ if (FP._console) FP._console.update();
+
+ // update loop
+ if (_delta > _skip) _delta = _skip;
+ while (_delta > _rate)
+ {
+ // update timer
+ _updateTime = _time;
+ _delta -= _rate;
+ FP.elapsed = (_time - _prev) / 1000;
+ if (FP.elapsed > maxElapsed) FP.elapsed = maxElapsed;
+ FP.elapsed *= FP.rate;
+ _prev = _time;
+
+ // update loop
+ if (!paused) update();
+
+ // update input
+ Input.update();
+
+ // update timer
+ _time = getTimer();
+ FP._updateTime = _time - _updateTime;
+ }
+
+ // update timer
+ _renderTime = _time;
+
+ // render loop
+ if (!paused) render();
+
+ // update timer
+ _time = _flashTime = getTimer();
+ FP._renderTime = _time - _renderTime;
+ FP._gameTime = _time - _gameTime;
+ }
+
+ /** @private Switch Worlds if they've changed. */
+ private function checkWorld():void
+ {
+ if (!FP._goto) return;
+ FP._world.end();
+ FP._world.updateLists();
+ if (FP._world && FP._world.autoClear && FP._world._tween) FP._world.clearTweens();
+ FP._world = FP._goto;
+ FP._goto = null;
+ FP.camera = FP._world.camera;
+ FP._world.updateLists();
+ FP._world.begin();
+ FP._world.updateLists();
+ }
+
+ // Timing information.
+ /** @private */ private var _delta:Number = 0;
+ /** @private */ private var _time:Number;
+ /** @private */ private var _last:Number;
+ /** @private */ private var _timer:Timer;
+ /** @private */ private var _rate:Number;
+ /** @private */ private var _skip:Number;
+ /** @private */ private var _prev:Number;
+
+ // Debug timing information.
+ /** @private */ private var _updateTime:uint;
+ /** @private */ private var _renderTime:uint;
+ /** @private */ private var _gameTime:uint;
+ /** @private */ private var _flashTime:uint;
+
+ // FrameRate tracking.
+ /** @private */ private var _frameLast:uint = 0;
+ /** @private */ private var _frameListSum:uint = 0;
+ /** @private */ private var _frameList:Vector.<uint> = new Vector.<uint>;
+ }
+}
View
765 net/flashpunk/Entity.as
@@ -0,0 +1,765 @@
+package net.flashpunk
+{
+ import flash.display.BitmapData;
+ import flash.geom.Point;
+ import flash.geom.Rectangle;
+ import flash.utils.getQualifiedClassName;
+ import flash.utils.getDefinitionByName;
+ import net.flashpunk.masks.*;
+ import net.flashpunk.graphics.*;
+
+ /**
+ * Main game Entity class updated by World.
+ */
+ public class Entity extends Tweener
+ {
+ /**
+ * If the Entity should render.
+ */
+ public var visible:Boolean = true;
+
+ /**
+ * If the Entity should respond to collision checks.
+ */
+ public var collidable:Boolean = true;
+
+ /**
+ * X position of the Entity in the World.
+ */
+ public var x:Number = 0;
+
+ /**
+ * Y position of the Entity in the World.
+ */
+ public var y:Number = 0;
+
+ /**
+ * Width of the Entity's hitbox.
+ */
+ public var width:int;
+
+ /**
+ * Height of the Entity's hitbox.
+ */
+ public var height:int;
+
+ /**
+ * X origin of the Entity's hitbox.
+ */
+ public var originX:int;
+
+ /**
+ * Y origin of the Entity's hitbox.
+ */
+ public var originY:int;
+
+ /**
+ * The BitmapData target to draw the Entity to. Leave as null to render to the current screen buffer (default).
+ */
+ public var renderTarget:BitmapData;
+
+ /**
+ * Constructor. Can be usd to place the Entity and assign a graphic and mask.
+ * @param x X position to place the Entity.
+ * @param y Y position to place the Entity.
+ * @param graphic Graphic to assign to the Entity.
+ * @param mask Mask to assign to the Entity.
+ */
+ public function Entity(x:Number = 0, y:Number = 0, graphic:Graphic = null, mask:Mask = null)
+ {
+ this.x = x;
+ this.y = y;
+ if (graphic) this.graphic = graphic;
+ if (mask) this.mask = mask;
+ HITBOX.assignTo(this);
+ _class = Class(getDefinitionByName(getQualifiedClassName(this)));
+ }
+
+ /**
+ * Override this, called when the Entity is added to a World.
+ */
+ public function added():void
+ {
+
+ }
+
+ /**
+ * Override this, called when the Entity is removed from a World.
+ */
+ public function removed():void
+ {
+
+ }
+
+ /**
+ * Updates the Entity.
+ */
+ override public function update():void
+ {
+
+ }
+
+ /**
+ * Renders the Entity. If you override this for special behaviour,
+ * remember to call super.render() to render the Entity's graphic.
+ */
+ public function render():void
+ {
+ if (_graphic && _graphic.visible)
+ {
+ if (_graphic.relative)
+ {
+ _point.x = x;
+ _point.y = y;
+ }
+ else _point.x = _point.y = 0;
+ _camera.x = FP.camera.x;
+ _camera.y = FP.camera.y;
+ _graphic.render(renderTarget ? renderTarget : FP.buffer, _point, _camera);
+ }
+ }
+
+ /**
+ * Checks for a collision against an Entity type.
+ * @param type The Entity type to check for.
+ * @param x Virtual x position to place this Entity.
+ * @param y Virtual y position to place this Entity.
+ * @return The first Entity collided with, or null if none were collided.
+ */
+ public function collide(type:String, x:Number, y:Number):Entity
+ {
+ if (!_world) return null;
+
+ var e:Entity = _world._typeFirst[type];
+ if (!collidable || !e) return null;
+
+ _x = this.x; _y = this.y;
+ this.x = x; this.y = y;
+
+ if (!_mask)
+ {
+ while (e)
+ {
+ if (x - originX + width > e.x - e.originX
+ && y - originY + height > e.y - e.originY
+ && x - originX < e.x - e.originX + e.width
+ && y - originY < e.y - e.originY + e.height
+ && e.collidable && e !== this)
+ {
+ if (!e._mask || e._mask.collide(HITBOX))
+ {
+ this.x = _x; this.y = _y;
+ return e;
+ }
+ }
+ e = e._typeNext;
+ }
+ this.x = _x; this.y = _y;
+ return null;
+ }
+
+ while (e)
+ {
+ if (x - originX + width > e.x - e.originX
+ && y - originY + height > e.y - e.originY
+ && x - originX < e.x - e.originX + e.width
+ && y - originY < e.y - e.originY + e.height
+ && e.collidable && e !== this)
+ {
+ if (_mask.collide(e._mask ? e._mask : e.HITBOX))
+ {
+ this.x = _x; this.y = _y;
+ return e;
+ }
+ }
+ e = e._typeNext;
+ }
+ this.x = _x; this.y = _y;
+ return null;
+ }
+
+ /**
+ * Checks for collision against multiple Entity types.
+ * @param types An Array or Vector of Entity types to check for.
+ * @param x Virtual x position to place this Entity.
+ * @param y Virtual y position to place this Entity.
+ * @return The first Entity collided with, or null if none were collided.
+ */
+ public function collideTypes(types:Object, x:Number, y:Number):Entity
+ {
+ if (!_world) return null;
+ var e:Entity;
+ for each (var type:String in types)
+ {
+ if ((e = collide(type, x, y))) return e;
+ }
+ return null;
+ }
+
+ /**
+ * Checks if this Entity collides with a specific Entity.
+ * @param e The Entity to collide against.
+ * @param x Virtual x position to place this Entity.
+ * @param y Virtual y position to place this Entity.
+ * @return The Entity if they overlap, or null if they don't.
+ */
+ public function collideWith(e:Entity, x:Number, y:Number):Entity
+ {
+ _x = this.x; _y = this.y;
+ this.x = x; this.y = y;
+
+ if (x - originX + width > e.x - e.originX
+ && y - originY + height > e.y - e.originY
+ && x - originX < e.x - e.originX + e.width
+ && y - originY < e.y - e.originY + e.height
+ && collidable && e.collidable)
+ {
+ if (!_mask)
+ {
+ if (!e._mask || e._mask.collide(HITBOX))
+ {
+ this.x = _x; this.y = _y;
+ return e;
+ }
+ this.x = _x; this.y = _y;
+ return null;
+ }
+ if (_mask.collide(e._mask ? e._mask : e.HITBOX))
+ {
+ this.x = _x; this.y = _y;
+ return e;
+ }
+ }
+ this.x = _x; this.y = _y;
+ return null;
+ }
+
+ /**
+ * Checks if this Entity overlaps the specified rectangle.
+ * @param x Virtual x position to place this Entity.
+ * @param y Virtual y position to place this Entity.
+ * @param rX X position of the rectangle.
+ * @param rY Y position of the rectangle.
+ * @param rWidth Width of the rectangle.
+ * @param rHeight Height of the rectangle.
+ * @return If they overlap.
+ */
+ public function collideRect(x:Number, y:Number, rX:Number, rY:Number, rWidth:Number, rHeight:Number):Boolean
+ {
+ if (x - originX + width >= rX && y - originY + height >= rY
+ && x - originX <= rX + rWidth && y - originY <= rY + rHeight)
+ {
+ if (!_mask) return true;
+ _x = this.x; _y = this.y;
+ this.x = x; this.y = y;
+ FP.entity.x = rX;
+ FP.entity.y = rY;
+ FP.entity.width = rWidth;
+ FP.entity.height = rHeight;
+ if (_mask.collide(FP.entity.HITBOX))
+ {
+ this.x = _x; this.y = _y;
+ return true;
+ }
+ this.x = _x; this.y = _y;
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if this Entity overlaps the specified position.
+ * @param x Virtual x position to place this Entity.
+ * @param y Virtual y position to place this Entity.
+ * @param pX X position.
+ * @param pY Y position.
+ * @return If the Entity intersects with the position.
+ */
+ public function collidePoint(x:Number, y:Number, pX:Number, pY:Number):Boolean
+ {
+ if (pX >= x - originX && pY >= y - originY
+ && pX < x - originX + width && pY < y - originY + height)
+ {
+ if (!_mask) return true;
+ _x = this.x; _y = this.y;
+ this.x = x; this.y = y;
+ FP.entity.x = pX;
+ FP.entity.y = pY;
+ FP.entity.width = 1;
+ FP.entity.height = 1;
+ if (_mask.collide(FP.entity.HITBOX))
+ {
+ this.x = _x; this.y = _y;
+ return true;
+ }
+ this.x = _x; this.y = _y;
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Populates an array with all collided Entities of a type.
+ * @param type The Entity type to check for.
+ * @param x Virtual x position to place this Entity.
+ * @param y Virtual y position to place this Entity.
+ * @param array The Array or Vector object to populate.
+ * @return The array, populated with all collided Entities.
+ */
+ public function collideInto(type:String, x:Number, y:Number, array:Object):void
+ {
+ if (!_world) return;
+
+ var e:Entity = _world._typeFirst[type];
+ if (!collidable || !e) return;
+
+ _x = this.x; _y = this.y;
+ this.x = x; this.y = y;
+ var n:uint = array.length;
+
+ if (!_mask)
+ {
+ while (e)
+ {
+ if (x - originX + width > e.x - e.originX
+ && y - originY + height > e.y - e.originY
+ && x - originX < e.x - e.originX + e.width
+ && y - originY < e.y - e.originY + e.height
+ && e.collidable && e !== this)
+ {
+ if (!e._mask || e._mask.collide(HITBOX)) array[n ++] = e;
+ }
+ e = e._typeNext;
+ }
+ this.x = _x; this.y = _y;
+ return;
+ }
+
+ while (e)
+ {
+ if (x - originX + width > e.x - e.originX
+ && y - originY + height > e.y - e.originY
+ && x - originX < e.x - e.originX + e.width
+ && y - originY < e.y - e.originY + e.height
+ && e.collidable && e !== this)
+ {
+ if (_mask.collide(e._mask ? e._mask : e.HITBOX)) array[n ++] = e;
+ }
+ e = e._typeNext;
+ }
+ this.x = _x; this.y = _y;
+ return;
+ }
+
+ /**
+ * Populates an array with all collided Entities of multiple types.
+ * @param types An array of Entity types to check for.
+ * @param x Virtual x position to place this Entity.
+ * @param y Virtual y position to place this Entity.
+ * @param array The Array or Vector object to populate.
+ * @return The array, populated with all collided Entities.
+ */
+ public function collideTypesInto(types:Object, x:Number, y:Number, array:Object):void
+ {
+ if (!_world) return;
+ for each (var type:String in types) collideInto(type, x, y, array);
+ }
+
+ /**
+ * If the Entity collides with the camera rectangle.
+ */
+ public function get onCamera():Boolean
+ {
+ return collideRect(x, y, FP.camera.x, FP.camera.y, FP.width, FP.height);
+ }
+
+ /**
+ * The World object this Entity has been added to.
+ */
+ public function get world():World
+ {
+ return _world;
+ }
+
+ /**
+ * Half the Entity's width.
+ */
+ public function get halfWidth():Number { return width / 2; }
+
+ /**
+ * Half the Entity's height.
+ */
+ public function get halfHeight():Number { return height / 2; }
+
+ /**
+ * The center x position of the Entity's hitbox.
+ */
+ public function get centerX():Number { return x - originX + width / 2; }
+
+ /**
+ * The center y position of the Entity's hitbox.
+ */
+ public function get centerY():Number { return y - originY + height / 2; }
+
+ /**
+ * The leftmost position of the Entity's hitbox.
+ */
+ public function get left():Number { return x - originX; }
+
+ /**
+ * The rightmost position of the Entity's hitbox.
+ */
+ public function get right():Number { return x - originX + width; }
+
+ /**
+ * The topmost position of the Entity's hitbox.
+ */
+ public function get top():Number { return y - originY; }
+
+ /**
+ * The bottommost position of the Entity's hitbox.
+ */
+ public function get bottom():Number { return y - originY + height; }
+
+ /**
+ * The rendering layer of this Entity. Higher layers are rendered first.
+ */
+ public function get layer():int { return _layer; }
+ public function set layer(value:int):void
+ {
+ if (_layer == value) return;
+ if (!_added)
+ {
+ _layer = value;
+ return;
+ }
+ _world.removeRender(this);
+ _layer = value;
+ _world.addRender(this);
+ }
+
+ /**
+ * The collision type, used for collision checking.
+ */
+ public function get type():String { return _type; }
+ public function set type(value:String):void
+ {
+ if (_type == value) return;
+ if (!_added)
+ {
+ _type = value;
+ return;
+ }
+ if (_type) _world.removeType(this);
+ _type = value;
+ if (value) _world.addType(this);
+ }
+
+ /**
+ * An optional Mask component, used for specialized collision. If this is
+ * not assigned, collision checks will use the Entity's hitbox by default.
+ */
+ public function get mask():Mask { return _mask; }
+ public function set mask(value:Mask):void
+ {
+ if (_mask == value) return;
+ if (_mask) _mask.assignTo(null);
+ _mask = value;
+ if (value) _mask.assignTo(this);
+ }
+
+ /**
+ * Graphical component to render to the screen.
+ */
+ public function get graphic():Graphic { return _graphic; }
+ public function set graphic(value:Graphic):void
+ {
+ if (_graphic == value) return;
+ _graphic = value;
+ if (value && value._assign != null) value._assign();
+ }
+
+ /**
+ * Adds the graphic to the Entity via a Graphiclist.
+ * @param g Graphic to add.
+ */
+ public function addGraphic(g:Graphic):Graphic
+ {
+ if (graphic is Graphiclist) (graphic as Graphiclist).add(g);
+ else
+ {
+ var list:Graphiclist = new Graphiclist;
+ if (graphic) list.add(graphic);
+ list.add(g);
+ graphic = list;
+ }
+ return g;
+ }
+
+ /**
+ * Sets the Entity's hitbox properties.
+ * @param width Width of the hitbox.
+ * @param height Height of the hitbox.
+ * @param originX X origin of the hitbox.
+ * @param originY Y origin of the hitbox.
+ */
+ public function setHitbox(width:int = 0, height:int = 0, originX:int = 0, originY:int = 0):void
+ {
+ this.width = width;
+ this.height = height;
+ this.originX = originX;
+ this.originY = originY;
+ }
+
+ /**
+ * Sets the Entity's hitbox to match that of the provided object.
+ * @param o The object defining the hitbox (eg. an Image or Rectangle).
+ */
+ public function setHitboxTo(o:Object):void
+ {
+ if (o is Image || o is Rectangle) setHitbox(o.width, o.height, -o.x, -o.y);
+ else
+ {
+ if (o.hasOwnProperty("width")) width = o.width;
+ if (o.hasOwnProperty("height")) height = o.height;
+ if (o.hasOwnProperty("originX") && !(o is Graphic)) originX = o.originX;
+ else if (o.hasOwnProperty("x")) originX = -o.x;
+ if (o.hasOwnProperty("originY") && !(o is Graphic)) originX = o.originY;
+ else if (o.hasOwnProperty("y")) originX = -o.y;
+ }
+ }
+
+ /**
+ * Sets the origin of the Entity.
+ * @param x X origin.
+ * @param y Y origin.
+ */
+ public function setOrigin(x:int = 0, y:int = 0):void
+ {
+ originX = x;
+ originY = y;
+ }
+
+ /**
+ * Center's the Entity's origin (half width & height).
+ */
+ public function centerOrigin():void
+ {
+ originX = width / 2;
+ originY = height / 2;
+ }
+
+ /**
+ * Calculates the distance from another Entity.
+ * @param e The other Entity.
+ * @param useHitboxes If hitboxes should be used to determine the distance. If not, the Entities' x/y positions are used.
+ * @return The distance.
+ */
+ public function distanceFrom(e:Entity, useHitboxes:Boolean = false):Number
+ {
+ if (!useHitboxes) return Math.sqrt((x - e.x) * (x - e.x) + (y - e.y) * (y - e.y));
+ return FP.distanceRects(x - originX, y - originY, width, height, e.x - e.originX, e.y - e.originY, e.width, e.height);
+ }
+
+ /**
+ * Calculates the distance from this Entity to the point.
+ * @param px X position.
+ * @param py Y position.
+ * @param useHitboxes If hitboxes should be used to determine the distance. If not, the Entities' x/y positions are used.
+ * @return The distance.
+ */
+ public function distanceToPoint(px:Number, py:Number, useHitbox:Boolean = false):Number
+ {
+ if (!useHitbox) return Math.sqrt((x - px) * (x - px) + (y - py) * (y - py));
+ return FP.distanceRectPoint(px, py, x - originX, y - originY, width, height);
+ }
+
+ /**
+ * Calculates the distance from this Entity to the rectangle.
+ * @param rx X position of the rectangle.
+ * @param ry Y position of the rectangle.
+ * @param rwidth Width of the rectangle.
+ * @param rheight Height of the rectangle.
+ * @return The distance.
+ */
+ public function distanceToRect(rx:Number, ry:Number, rwidth:Number, rheight:Number):Number
+ {
+ return FP.distanceRects(rx, ry, rwidth, rheight, x - originX, y - originY, width, height);
+ }
+
+ /**
+ * Gets the class name as a string.
+ * @return A string representing the class name.
+ */
+ public function toString():String
+ {
+ var s:String = String(_class);
+ return s.substring(7, s.length - 1);
+ }
+
+ /**
+ * Moves the Entity by the amount, retaining integer values for its x and y.
+ * @param x Horizontal offset.
+ * @param y Vertical offset.
+ * @param solidType An optional collision type to stop flush against upon collision.
+ * @param sweep If sweeping should be used (prevents fast-moving objects from going through solidType).
+ */
+ public function moveBy(x:Number, y:Number, solidType:String = null, sweep:Boolean = false):void
+ {
+ _moveX += x;
+ _moveY += y;
+ x = Math.round(_moveX);
+ y = Math.round(_moveY);
+ _moveX -= x;
+ _moveY -= y;
+ if (solidType)
+ {
+ var sign:int, e:Entity;
+ if (x != 0)
+ {
+ if (collidable && (sweep || collide(solidType, this.x + x, this.y)))
+ {
+ sign = x > 0 ? 1 : -1;
+ while (x != 0)
+ {
+ if ((e = collide(solidType, this.x + sign, this.y)))
+ {
+ moveCollideX(e);
+ break;
+ }
+ else
+ {
+ this.x += sign;
+ x -= sign;
+ }
+ }
+ }
+ else this.x += x;
+ }
+ if (y != 0)
+ {
+ if (collidable && (sweep || collide(solidType, this.x, this.y + y)))
+ {
+ sign = y > 0 ? 1 : -1;
+ while (y != 0)
+ {
+ if ((e = collide(solidType, this.x, this.y + sign)))
+ {
+ moveCollideY(e);
+ break;
+ }
+ else
+ {
+ this.y += sign;
+ y -= sign;
+ }
+ }
+ }
+ else this.y += y;
+ }
+ }
+ else
+ {
+ this.x += x;
+ this.y += y;
+ }
+ }
+
+ /**
+ * Moves the Entity to the position, retaining integer values for its x and y.
+ * @param x X position.
+ * @param y Y position.
+ * @param solidType An optional collision type to stop flush against upon collision.
+ * @param sweep If sweeping should be used (prevents fast-moving objects from going through solidType).
+ */
+ public function moveTo(x:Number, y:Number, solidType:String = null, sweep:Boolean = false):void
+ {
+ moveBy(x - this.x, y - this.y, solidType, sweep);
+ }
+
+ /**
+ * Moves towards the target position, retaining integer values for its x and y.
+ * @param x X target.
+ * @param y Y target.
+ * @param amount Amount to move.
+ * @param solidType An optional collision type to stop flush against upon collision.
+ * @param sweep If sweeping should be used (prevents fast-moving objects from going through solidType).
+ */
+ public function moveTowards(x:Number, y:Number, amount:Number, solidType:String = null, sweep:Boolean = false):void
+ {
+ _point.x = x - this.x;
+ _point.y = y - this.y;
+ _point.normalize(amount);
+ moveBy(_point.x, _point.y, solidType, sweep);
+ }
+
+ /**
+ * When you collide with an Entity on the x-axis with moveTo() or moveBy().
+ * @param e The Entity you collided with.
+ */
+ public function moveCollideX(e:Entity):void
+ {
+
+ }
+
+ /**
+ * When you collide with an Entity on the y-axis with moveTo() or moveBy().
+ * @param e The Entity you collided with.
+ */
+ public function moveCollideY(e:Entity):void
+ {
+
+ }
+
+ /**
+ * Clamps the Entity's hitbox on the x-axis.
+ * @param left Left bounds.
+ * @param right Right bounds.
+ * @param padding Optional padding on the clamp.
+ */
+ public function clampHorizontal(left:Number, right:Number, padding:Number = 0):void
+ {
+ if (x - originX < left + padding) x = left + originX + padding;
+ if (x - originX + width > right - padding) x = right - width + originX - padding;
+ }
+
+ /**
+ * Clamps the Entity's hitbox on the y axis.
+ * @param top Min bounds.
+ * @param bottom Max bounds.
+ * @param padding Optional padding on the clamp.
+ */
+ public function clampVertical(top:Number, bottom:Number, padding:Number = 0):void
+ {
+ if (y - originY < top + padding) y = top + originY + padding;
+ if (y - originY + height > bottom - padding) y = bottom - height + originY - padding;
+ }
+
+ // Entity information.
+ /** @private */ internal var _class:Class;
+ /** @private */ internal var _world:World;
+ /** @private */ internal var _added:Boolean;
+ /** @private */ internal var _type:String = "";
+ /** @private */ internal var _layer:int;
+ /** @private */ internal var _updatePrev:Entity;
+ /** @private */ internal var _updateNext:Entity;
+ /** @private */ internal var _renderPrev:Entity;
+ /** @private */ internal var _renderNext:Entity;
+ /** @private */ internal var _typePrev:Entity;
+ /** @private */ internal var _typeNext:Entity;
+ /** @private */ internal var _recycleNext:Entity;
+
+ // Collision information.
+ /** @private */ private const HITBOX:Mask = new Mask;
+ /** @private */ private var _mask:Mask;
+ /** @private */ private var _x:Number;
+ /** @private */ private var _y:Number;
+ /** @private */ private var _moveX:Number = 0;
+ /** @private */ private var _moveY:Number = 0;
+
+ // Rendering information.
+ /** @private */ internal var _graphic:Graphic;
+ /** @private */ private var _point:Point = FP.point;
+ /** @private */ private var _camera:Point = FP.point2;
+ }
+}
View
901 net/flashpunk/FP.as
@@ -0,0 +1,901 @@
+package net.flashpunk
+{
+ import flash.display.BitmapData;
+ import flash.display.Sprite;
+ import flash.display.Stage;
+ import flash.geom.Matrix;
+ import flash.geom.Point;
+ import flash.geom.Rectangle;
+ import flash.media.SoundMixer;
+ import flash.media.SoundTransform;
+ import flash.system.System;
+ import flash.utils.ByteArray;
+ import flash.utils.getTimer;
+ import net.flashpunk.*;
+ import net.flashpunk.debug.Console;
+ import net.flashpunk.tweens.misc.MultiVarTween;
+
+ /**
+ * Static catch-all class used to access global properties and functions.
+ */
+ public class FP
+ {
+ /**
+ * The FlashPunk major version.
+ */
+ public static const VERSION:String = "1.4";
+
+ /**
+ * Width of the game.
+ */
+ public static var width:uint;
+
+ /**
+ * Height of the game.
+ */
+ public static var height:uint;
+
+ /**
+ * If the game is running at a fixed framerate.
+ */
+ public static var fixed:Boolean;
+
+ /**
+ * The framerate assigned to the stage.
+ */
+ public static var frameRate:Number;
+
+ /**
+ * The framerate assigned to the stage.
+ */
+ public static var assignedFrameRate:Number;
+
+ /**
+ * Time elapsed since the last frame (non-fixed framerate only).
+ */
+ public static var elapsed:Number;
+
+ /**
+ * Timescale applied to FP.elapsed (non-fixed framerate only).
+ */
+ public static var rate:Number = 1;
+
+ /**
+ * The Screen object, use to transform or offset the Screen.
+ */
+ public static var screen:Screen;
+
+ /**
+ * The current screen buffer, drawn to in the render loop.
+ */
+ public static var buffer:BitmapData;
+
+ /**
+ * A rectangle representing the size of the screen.
+ */
+ public static var bounds:Rectangle;
+
+ /**
+ * Point used to determine drawing offset in the render loop.
+ */
+ public static var camera:Point = new Point;
+
+ /**
+ * Half the screen width.
+ */
+ public static function get halfWidth():Number { return width / 2; }
+
+ /**
+ * Half the screen height.
+ */
+ public static function get halfHeight():Number { return height / 2; }
+
+ /**
+ * The currently active World object. When you set this, the World is flagged
+ * to switch, but won't actually do so until the end of the current frame.
+ */
+ public static function get world():World { return _world; }
+ public static function set world(value:World):void
+ {
+ if (_world == value) return;
+ _goto = value;
+ }
+
+ /**
+ * Sets the camera position.
+ * @param x X position.
+ * @param y Y position.
+ */
+ public static function setCamera(x:Number = 0, y:Number = 0):void
+ {
+ camera.x = x;
+ camera.y = y;
+ }
+
+ /**
+ * Resets the camera position.
+ */
+ public static function resetCamera():void
+ {
+ camera.x = camera.y = 0;
+ }
+
+ /**
+ * Global volume factor for all sounds, a value from 0 to 1.
+ */
+ public static function get volume():Number { return _volume; }
+ public static function set volume(value:Number):void
+ {
+ if (value < 0) value = 0;
+ if (_volume == value) return;
+ _soundTransform.volume = _volume = value;
+ SoundMixer.soundTransform = _soundTransform;
+ }
+
+ /**
+ * Global panning factor for all sounds, a value from -1 to 1.
+ */
+ public static function get pan():Number { return _pan; }
+ public static function set pan(value:Number):void
+ {
+ if (value < -1) value = -1;
+ if (value > 1) value = 1;
+ if (_pan == value) return;
+ _soundTransform.pan = _pan = value;
+ SoundMixer.soundTransform = _soundTransform;
+ }
+
+ /**
+ * Randomly chooses and returns one of the provided values.
+ * @param ...objs The Objects you want to randomly choose from. Can be ints, Numbers, Points, etc.
+ * @return A randomly chosen one of the provided parameters.
+ */
+ public static function choose(...objs):*
+ {
+ var c:* = (objs.length == 1 && (objs[0] is Array || objs[0] is Vector.<*>)) ? objs[0] : objs;
+ return c[rand(c.length)];
+ }
+
+ /**
+ * Finds the sign of the provided value.
+ * @param value The Number to evaluate.
+ * @return 1 if value > 0, -1 if value < 0, and 0 when value == 0.
+ */
+ public static function sign(value:Number):int
+ {
+ return value < 0 ? -1 : (value > 0 ? 1 : 0);
+ }
+
+ /**
+ * Approaches the value towards the target, by the specified amount, without overshooting the target.
+ * @param value The starting value.
+ * @param target The target that you want value to approach.
+ * @param amount How much you want the value to approach target by.
+ * @return The new value.
+ */
+ public static function approach(value:Number, target:Number, amount:Number):Number
+ {
+ return value < target ? (target < value + amount ? target : value + amount) : (target > value - amount ? target : value - amount);
+ }
+
+ /**
+ * Linear interpolation between two values.
+ * @param a First value.
+ * @param b Second value.
+ * @param t Interpolation factor.
+ * @return When t=0, returns a. When t=1, returns b. When t=0.5, will return halfway between a and b. Etc.
+ */
+ public static function lerp(a:Number, b:Number, t:Number = 1):Number
+ {
+ return a + (b - a) * t;
+ }
+
+ /**
+ * Linear interpolation between two colors.
+ * @param fromColor First color.
+ * @param toColor Second color.
+ * @param t Interpolation value. Clamped to the range [0, 1].
+ * return RGB component-interpolated color value.
+ */
+ public static function colorLerp(fromColor:uint, toColor:uint, t:Number = 1):uint
+ {
+ if (t <= 0) { return fromColor; }
+ if (t >= 1) { return toColor; }
+ var a:uint = fromColor >> 24 & 0xFF,
+ r:uint = fromColor >> 16 & 0xFF,
+ g:uint = fromColor >> 8 & 0xFF,
+ b:uint = fromColor & 0xFF,
+ dA: int = (toColor >> 24 & 0xFF) - a,
+ dR: int = (toColor >> 16 & 0xFF) - r,
+ dG: int = (toColor >> 8 & 0xFF) - g,
+ dB: int = (toColor & 0xFF) - b;
+ a += dA * t;
+ r += dR * t;
+ g += dG * t;
+ b += dB * t;
+ return a << 24 | r << 16 | g << 8 | b;
+ }
+
+ /**
+ * Steps the object towards a point.
+ * @param object Object to move (must have an x and y property).
+ * @param x X position to step towards.
+ * @param y Y position to step towards.
+ * @param distance The distance to step (will not overshoot target).
+ */
+ public static function stepTowards(object:Object, x:Number, y:Number, distance:Number = 1):void
+ {
+ point.x = x - object.x;
+ point.y = y - object.y;
+ if (point.length <= distance)
+ {
+ object.x = x;
+ object.y = y;
+ return;
+ }
+ point.normalize(distance);
+ object.x += point.x;
+ object.y += point.y;
+ }
+
+ /**
+ * Anchors the object to a position.
+ * @param object The object to anchor.
+ * @param anchor The anchor object.
+ * @param distance The max distance object can be anchored to the anchor.
+ */
+ public static function anchorTo(object:Object, anchor:Object, distance:Number = 0):void
+ {
+ point.x = object.x - anchor.x;
+ point.y = object.y - anchor.y;
+ if (point.length > distance) point.normalize(distance);
+ object.x = anchor.x + point.x;
+ object.y = anchor.y + point.y;
+ }
+
+ /**
+ * Finds the angle (in degrees) from point 1 to point 2.
+ * @param x1 The first x-position.
+ * @param y1 The first y-position.
+ * @param x2 The second x-position.
+ * @param y2 The second y-position.
+ * @return The angle from (x1, y1) to (x2, y2).
+ */
+ public static function angle(x1:Number, y1:Number, x2:Number, y2:Number):Number
+ {
+ var a:Number = Math.atan2(y2 - y1, x2 - x1) * DEG;
+ return a < 0 ? a + 360 : a;
+ }
+
+ /**
+ * Sets the x/y values of the provided object to a vector of the specified angle and length.
+ * @param object The object whose x/y properties should be set.
+ * @param angle The angle of the vector, in degrees.
+ * @param length The distance to the vector from (0, 0).
+ * @param x X offset.
+ * @param y Y offset.
+ */
+ public static function angleXY(object:Object, angle:Number, length:Number = 1, x:Number = 0, y:Number = 0):void
+ {
+ angle *= RAD;
+ object.x = Math.cos(angle) * length + x;
+ object.y = Math.sin(angle) * length + y;
+ }
+
+ /**
+ * Rotates the object around the anchor by the specified amount.
+ * @param object Object to rotate around the anchor.
+ * @param anchor Anchor to rotate around.
+ * @param angle The amount of degrees to rotate by.
+ */
+ public static function rotateAround(object:Object, anchor:Object, angle:Number = 0, relative:Boolean = true):void
+ {
+ if (relative) angle += FP.angle(anchor.x, anchor.y, object.x, object.y);
+ FP.angleXY(object, angle, FP.distance(anchor.x, anchor.y, object.x, object.y), anchor.x, anchor.y);
+ }
+
+ /**
+ * Gets the difference of two angles, wrapped around to the range -180 to 180.
+ * @param a First angle in degrees.
+ * @param b Second angle in degrees.
+ * @return Difference in angles, wrapped around to the range -180 to 180.
+ */
+ public static function angleDiff(a:Number, b:Number):Number
+ {
+ var diff:Number = b - a;
+
+ while (diff > 180) { diff -= 360; }
+ while (diff <= -180) { diff += 360; }
+
+ return diff;
+ }
+ /**
+ * Find the distance between two points.
+ * @param x1 The first x-position.
+ * @param y1 The first y-position.
+ * @param x2 The second x-position.
+ * @param y2 The second y-position.
+ * @return The distance.
+ */
+ public static function distance(x1:Number, y1:Number, x2:Number = 0, y2:Number = 0):Number
+ {
+ return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
+ }
+
+ /**
+ * Find the distance between two rectangles. Will return 0 if the rectangles overlap.
+ * @param x1 The x-position of the first rect.
+ * @param y1 The y-position of the first rect.
+ * @param w1 The width of the first rect.
+ * @param h1 The height of the first rect.
+ * @param x2 The x-position of the second rect.
+ * @param y2 The y-position of the second rect.
+ * @param w2 The width of the second rect.
+ * @param h2 The height of the second rect.
+ * @return The distance.
+ */
+ public static function distanceRects(x1:Number, y1:Number, w1:Number, h1:Number, x2:Number, y2:Number, w2:Number, h2:Number):Number
+ {
+ if (x1 < x2 + w2 && x2 < x1 + w1)
+ {
+ if (y1 < y2 + h2 && y2 < y1 + h1) return 0;
+ if (y1 > y2) return y1 - (y2 + h2);
+ return y2 - (y1 + h1);
+ }
+ if (y1 < y2 + h2 && y2 < y1 + h1)
+ {
+ if (x1 > x2) return x1 - (x2 + w2);
+ return x2 - (x1 + w1)
+ }
+ if (x1 > x2)
+ {
+ if (y1 > y2) return distance(x1, y1, (x2 + w2), (y2 + h2));
+ return distance(x1, y1 + h1, x2 + w2, y2);
+ }
+ if (y1 > y2) return distance(x1 + w1, y1, x2, y2 + h2)
+ return distance(x1 + w1, y1 + h1, x2, y2);
+ }
+
+ /**
+ * Find the distance between a point and a rectangle. Returns 0 if the point is within the rectangle.
+ * @param px The x-position of the point.
+ * @param py The y-position of the point.
+ * @param rx The x-position of the rect.
+ * @param ry The y-position of the rect.
+ * @param rw The width of the rect.
+ * @param rh The height of the rect.
+ * @return The distance.
+ */
+ public static function distanceRectPoint(px:Number, py:Number, rx:Number, ry:Number, rw:Number, rh:Number):Number
+ {
+ if (px >= rx && px <= rx + rw)
+ {
+ if (py >= ry && py <= ry + rh) return 0;
+ if (py > ry) return py - (ry + rh);
+ return ry - py;
+ }
+ if (py >= ry && py <= ry + rh)
+ {
+ if (px > rx) return px - (rx + rw);
+ return rx - px;
+ }
+ if (px > rx)
+ {
+ if (py > ry) return distance(px, py, rx + rw, ry + rh);
+ return distance(px, py, rx + rw, ry);
+ }
+ if (py > ry) return distance(px, py, rx, ry + rh)
+ return distance(px, py, rx, ry);
+ }
+
+ /**
+ * Clamps the value within the minimum and maximum values.
+ * @param value The Number to evaluate.
+ * @param min The minimum range.
+ * @param max The maximum range.
+ * @return The clamped value.
+ */
+ public static function clamp(value:Number, min:Number, max:Number):Number
+ {
+ if (max > min)
+ {
+ value = value < max ? value : max;
+ return value > min ? value : min;
+ }
+ value = value < min ? value : min;
+ return value > max ? value : max;
+ }
+
+ /**
+ * Clamps the object inside the rectangle.
+ * @param object The object to clamp (must have an x and y property).
+ * @param x Rectangle's x.
+ * @param y Rectangle's y.
+ * @param width Rectangle's width.
+ * @param height Rectangle's height.
+ */
+ public static function clampInRect(object:Object, x:Number, y:Number, width:Number, height:Number, padding:Number = 0):void
+ {
+ object.x = clamp(object.x, x + padding, x + width - padding);
+ object.y = clamp(object.y, y + padding, y + height - padding);
+ }
+
+ /**
+ * Transfers a value from one scale to another scale. For example, scale(.5, 0, 1, 10, 20) == 15, and scale(3, 0, 5, 100, 0) == 40.
+ * @param value The value on the first scale.
+ * @param min The minimum range of the first scale.
+ * @param max The maximum range of the first scale.
+ * @param min2 The minimum range of the second scale.
+ * @param max2 The maximum range of the second scale.
+ * @return The scaled value.
+ */
+ public static function scale(value:Number, min:Number, max:Number, min2:Number, max2:Number):Number
+ {
+ return min2 + ((value - min) / (max - min)) * (max2 - min2);
+ }
+
+ /**
+ * Transfers a value from one scale to another scale, but clamps the return value within the second scale.
+ * @param value The value on the first scale.
+ * @param min The minimum range of the first scale.
+ * @param max The maximum range of the first scale.
+ * @param min2 The minimum range of the second scale.
+ * @param max2 The maximum range of the second scale.
+ * @return The scaled and clamped value.
+ */
+ public static function scaleClamp(value:Number, min:Number, max:Number, min2:Number, max2:Number):Number
+ {
+ value = min2 + ((value - min) / (max - min)) * (max2 - min2);
+ if (max2 > min2)
+ {
+ value = value < max2 ? value : max2;
+ return value > min2 ? value : min2;
+ }
+ value = value < min2 ? value : min2;
+ return value > max2 ? value : max2;
+ }
+
+ /**
+ * The random seed used by FP's random functions.
+ */
+ public static function get randomSeed():uint { return _getSeed; }
+ public static function set randomSeed(value:uint):void
+ {
+ _seed = clamp(value, 1, 2147483646);
+ _getSeed = _seed;
+ }
+
+ /**
+ * Randomizes the random seed using Flash's Math.random() function.
+ */
+ public static function randomizeSeed():void
+ {
+ randomSeed = 2147483647 * Math.random();
+ }
+
+ /**
+ * A pseudo-random Number produced using FP's random seed, where 0 <= Number < 1.
+ */
+ public static function get random():Number
+ {
+ _seed = (_seed * 16807) % 2147483647;
+ return _seed / 2147483647;
+ }
+
+ /**
+ * Returns a pseudo-random uint.
+ * @param amount The returned uint will always be 0 <= uint < amount.
+ * @return The uint.
+ */
+ public static function rand(amount:uint):uint
+ {
+ _seed = (_seed * 16807) % 2147483647;
+ return (_seed / 2147483647) * amount;
+ }
+
+ /**
+ * Returns the next item after current in the list of options.
+ * @param current The currently selected item (must be one of the options).
+ * @param options An array of all the items to cycle through.
+ * @param loop If true, will jump to the first item after the last item is reached.
+ * @return The next item in the list.
+ */
+ public static function next(current:*, options:Array, loop:Boolean = true):*
+ {
+ if (loop) return options[(options.indexOf(current) + 1) % options.length];
+ return options[Math.max(options.indexOf(current) + 1, options.length - 1)];
+ }
+
+ /**
+ * Returns the item previous to the current in the list of options.
+ * @param current The currently selected item (must be one of the options).
+ * @param options An array of all the items to cycle through.
+ * @param loop If true, will jump to the last item after the first is reached.
+ * @return The previous item in the list.
+ */
+ public static function prev(current:*, options:Array, loop:Boolean = true):*
+ {
+ if (loop) return options[((options.indexOf(current) - 1) + options.length) % options.length];
+ return options[Math.max(options.indexOf(current) - 1, 0)];
+ }
+
+ /**
+ * Swaps the current item between a and b. Useful for quick state/string/value swapping.
+ * @param current The currently selected item.
+ * @param a Item a.
+ * @param b Item b.
+ * @return Returns a if current is b, and b if current is a.
+ */
+ public static function swap(current:*, a:*, b:*):*
+ {
+ return current == a ? b : a;
+ }
+
+ /**
+ * Creates a color value by combining the chosen RGB values.
+ * @param R The red value of the color, from 0 to 255.
+ * @param G The green value of the color, from 0 to 255.
+ * @param B The blue value of the color, from 0 to 255.
+ * @return The color uint.
+ */
+ public static function getColorRGB(R:uint = 0, G:uint = 0, B:uint = 0):uint
+ {
+ return R << 16 | G << 8 | B;
+ }
+
+ /**
+ * Creates a color value with the chosen HSV values.
+ * @param h The hue of the color (from 0 to 1).
+ * @param s The saturation of the color (from 0 to 1).
+ * @param v The value of the color (from 0 to 1).
+ * @return The color uint.
+ */
+ public static function getColorHSV(h:Number, s:Number, v:Number):uint
+ {
+ h = int(h * 360);
+ var hi:int = Math.floor(h / 60) % 6,
+ f:Number = h / 60 - Math.floor(h / 60),
+ p:Number = (v * (1 - s)),
+ q:Number = (v * (1 - f * s)),
+ t:Number = (v * (1 - (1 - f) * s));
+ switch (hi)
+ {
+ case 0: return int(v * 255) << 16 | int(t * 255) << 8 | int(p * 255);
+ case 1: return int(q * 255) << 16 | int(v * 255) << 8 | int(p * 255);
+ case 2: return int(p * 255) << 16 | int(v * 255) << 8 | int(t * 255);
+ case 3: return int(p * 255) << 16 | int(q * 255) << 8 | int(v * 255);
+ case 4: return int(t * 255) << 16 | int(p * 255) << 8 | int(v * 255);
+ case 5: return int(v * 255) << 16 | int(p * 255) << 8 | int(q * 255);
+ default: return 0;
+ }
+ return 0;
+ }
+
+ /**
+ * Finds the red factor of a color.
+ * @param color The color to evaluate.
+ * @return A uint from 0 to 255.
+ */
+ public static function getRed(color:uint):uint
+ {
+ return color >> 16 & 0xFF;
+ }
+
+ /**
+ * Finds the green factor of a color.
+ * @param color The color to evaluate.
+ * @return A uint from 0 to 255.
+ */
+ public static function getGreen(color:uint):uint
+ {
+ return color >> 8 & 0xFF;
+ }
+
+ /**
+ * Finds the blue factor of a color.
+ * @param color The color to evaluate.
+ * @return A uint from 0 to 255.
+ */
+ public static function getBlue(color:uint):uint
+ {
+ return color & 0xFF;
+ }
+
+ /**
+ * Fetches a stored BitmapData object represented by the source.
+ * @param source Embedded Bitmap class.
+ * @return The stored BitmapData object.
+ */
+ public static function getBitmap(source:Class):BitmapData
+ {
+ if (_bitmap[String(source)]) return _bitmap[String(source)];
+ return (_bitmap[String(source)] = (new source).bitmapData);
+ }
+
+ /**
+ * Sets a time flag.
+ * @return Time elapsed (in milliseconds) since the last time flag was set.
+ */
+ public static function timeFlag():uint
+ {
+ var t:uint = getTimer(),
+ e:uint = t - _time;
+ _time = t;
+ return e;
+ }
+
+ /**
+ * The global Console object.
+ */
+ public static function get console():Console
+ {
+ if (!_console) _console = new Console;
+ return _console;
+ }
+
+ /**
+ * Logs data to the console.
+ * @param ...data The data parameters to log, can be variables, objects, etc. Parameters will be separated by a space (" ").
+ */
+ public static function log(...data):void
+ {
+ if (_console)
+ {
+ if (data.length > 1)
+ {
+ var i:int = 0, s:String = "";
+ while (i < data.length)
+ {
+ if (i > 0) s += " ";
+ s += data[i ++].toString();
+ }
+ _console.log(s);
+ }
+ else _console.log(data[0]);
+ }
+ }
+
+ /**
+ * Adds properties to watch in the console's debug panel.
+ * @param ...properties The properties (strings) to watch.
+ */
+ public static function watch(...properties):void
+ {
+ if (_console)
+ {
+ if (properties.length > 1) _console.watch(properties);
+ else _console.watch(properties[0]);
+ }
+ }
+
+ /**
+ * Loads the file as an XML object.
+ * @param file The embedded file to load.
+ * @return An XML object representing the file.
+ */
+ public static function getXML(file:Class):XML
+ {
+ var bytes:ByteArray = new file;
+ return XML(bytes.readUTFBytes(bytes.length));
+ }
+
+ /**
+ * Tweens numeric public properties of an Object. Shorthand for creating a MultiVarTween tween, starting it and adding it to a Tweener.
+ * @param object The object containing the properties to tween.
+ * @param values An object containing key/value pairs of properties and target values.
+ * @param duration Duration of the tween.
+ * @param options An object containing key/value pairs of the following optional parameters:
+ * type Tween type.
+ * complete Optional completion callback function.
+ * ease Optional easer function.
+ * tweener The Tweener to add this Tween to.
+ * @return The added MultiVarTween object.
+ *
+ * Example: FP.tween(object, { x: 500, y: 350 }, 2.0, { ease: easeFunction, complete: onComplete } );
+ */
+ public static function tween(object:Object, values:Object, duration:Number, options:Object = null):MultiVarTween
+ {
+ var type:uint = Tween.ONESHOT,
+ complete:Function = null,
+ ease:Function = null,
+ tweener:Tweener = FP.world;
+ if (object is Tweener) tweener = object as Tweener;
+ if (options)
+ {
+ if (options.hasOwnProperty("type")) type = options.type;
+ if (options.hasOwnProperty("complete")) complete = options.complete;
+ if (options.hasOwnProperty("ease")) ease = options.ease;
+ if (options.hasOwnProperty("tweener")) tweener = options.tweener;
+ }
+ var tween:MultiVarTween = new MultiVarTween(complete, type);
+ tween.tween(object, values, duration, ease);
+ tweener.addTween(tween);
+ return tween;
+ }
+
+ /**
+ * Gets an array of frame indices.
+ * @param from Starting frame.
+ * @param to Ending frame.
+ * @param skip Skip amount every frame (eg. use 1 for every 2nd frame).
+ */
+ public static function frames(from:int, to:int, skip:int = 0):Array
+ {
+ var a:Array = [];
+ skip ++;
+ if (from < to)
+ {
+ while (from <= to)
+ {
+ a.push(from);
+ from += skip;
+ }
+ }
+ else
+ {
+ while (from >= to)
+ {
+ a.push(from);
+ from -= skip;
+ }
+ }
+ return a;
+ }
+
+ /**
+ * Shuffles the elements in the array.
+ * @param a The Object to shuffle (an Array or Vector).
+ */
+ public static function shuffle(a:Object):void
+ {
+ if (a is Array || a is Vector.<*>)
+ {
+ var i:int = a.length, j:int, t:*;
+ while (-- i)
+ {
+ t = a[i];
+ a[i] = a[j = FP.rand(i + 1)];
+ a[j] = t;
+ }
+ }
+ }
+
+ /**
+ * Sorts the elements in the array.
+ * @param object The Object to sort (an Array or Vector).
+ * @param ascending If it should be sorted ascending (true) or descending (false).
+ */
+ public static function sort(object:Object, ascending:Boolean = true):void
+ {
+ if (object is Array || object is Vector.<*>) quicksort(object, 0, object.length - 1, ascending);
+ }
+
+ /**
+ * Sorts the elements in the array by a property of the element.
+ * @param object The Object to sort (an Array or Vector).
+ * @param property The numeric property of object's elements to sort by.
+ * @param ascending If it should be sorted ascending (true) or descending (false).
+ */
+ public static function sortBy(object:Object, property:String, ascending:Boolean = true):void
+ {
+ if (object is Array || object is Vector.<*>) quicksortBy(object, 0, object.length - 1, ascending, property);
+ }
+
+ /** @private Quicksorts the array. */
+ private static function quicksort(a:Object, left:int, right:int, ascending:Boolean):void
+ {
+ var i:int = left, j:int = right, t:Number,
+ p:* = a[Math.round((left + right) * .5)];
+ if (ascending)
+ {
+ while (i <= j)
+ {
+ while (a[i] < p) i ++;
+ while (a[j] > p) j --;
+ if (i <= j)
+ {
+ t = a[i];
+ a[i ++] = a[j];
+ a[j --] = t;
+ }
+ }
+ }
+ else
+ {
+ while (i <= j)
+ {
+ while (a[i] > p) i ++;
+ while (a[j] < p) j --;
+ if (i <= j)
+ {
+ t = a[i];
+ a[i ++] = a[j];
+ a[j --] = t;
+ }
+ }
+ }
+ if (left < j) quicksort(a, left, j, ascending);
+ if (i < right) quicksort(a, i, right, ascending);
+ }
+
+ /** @private Quicksorts the array by the property. */
+ private static function quicksortBy(a:Object, left:int, right:int, ascending:Boolean, property:String):void
+ {
+ var i:int = left, j:int = right, t:Object,
+ p:* = a[Math.round((left + right) * .5)][property];
+ if (ascending)
+ {
+ while (i <= j)
+ {
+ while (a[i][property] < p) i ++;
+ while (a[j][property] > p) j --;
+ if (i <= j)
+ {
+ t = a[i];
+ a[i ++] = a[j];
+ a[j --] = t;
+ }
+ }
+ }
+ else
+ {
+ while (i <= j)
+ {
+ while (a[i][property] > p) i ++;
+ while (a[j][property] < p) j --;
+ if (i <= j)
+ {
+ t = a[i];
+ a[i ++] = a[j];
+ a[j --] = t;
+ }
+ }
+ }
+ if (left < j) quicksortBy(a, left, j, ascending, property);
+ if (i < right) quicksortBy(a, i, right, ascending, property);
+ }
+
+ // World information.
+ /** @private */ internal static var _world:World;
+ /** @private */ internal static var _goto:World;
+
+ // Console information.
+ /** @private */ internal static var _console:Console;
+
+ // Time information.
+ /** @private */ internal static var _time:uint;
+ /** @private */ public static var _updateTime:uint;
+ /** @private */ public static var _renderTime:uint;
+ /** @private */ public static var _gameTime:uint;
+ /** @private */ public static var _flashTime:uint;
+
+ // Bitmap storage.
+ /** @private */ private static var _bitmap:Object = { };
+
+ // Pseudo-random number generation (the seed is set in Engine's contructor).
+ /** @private */ private static var _seed:uint = 0;
+ /** @private */ private static var _getSeed:uint;
+
+ // Volume control.
+ /** @private */ private static var _volume:Number = 1;
+ /** @private */ private static var _pan:Number = 0;
+ /** @private */ private static var _soundTransform:SoundTransform = new SoundTransform;
+
+ // Used for rad-to-deg and deg-to-rad conversion.
+ /** @private */ public static const DEG:Number = -180 / Math.PI;
+ /** @private */ public static const RAD:Number = Math.PI / -180;
+
+ // Global Flash objects.
+ /** @private */ public static var stage:Stage;
+ /** @private */ public static var engine:Engine;
+
+ // Global objects used for rendering, collision, etc.
+ /** @private */ public static var point:Point = new Point;
+ /** @private */ public static var point2:Point = new Point;
+ /** @private */ public static var zero:Point = new Point;
+ /** @private */ public static var rect:Rectangle = new Rectangle;
+ /** @private */ public static var matrix:Matrix = new Matrix;
+ /** @private */ public static var sprite:Sprite = new Sprite;
+ /** @private */ public static var entity:Entity;
+ }
+}
View
85 net/flashpunk/Graphic.as
@@ -0,0 +1,85 @@
+package net.flashpunk
+{
+ import flash.display.BitmapData;
+ import flash.geom.Point;
+
+ /**
+ * Base class for all graphical types that can be drawn by Entity.
+ */
+ public class Graphic
+ {
+ /**
+ * If the graphic should update.
+ */
+ public var active:Boolean = false;
+
+ /**
+ * If the graphic should render.
+ */
+ public var visible:Boolean = true;
+
+ /**
+ * X offset.
+ */
+ public var x:Number = 0;
+
+ /**
+ * Y offset.
+ */
+ public var y:Number = 0;
+
+ /**
+ * X scrollfactor, effects how much the camera offsets the drawn graphic.
+ * Can be used for parallax effect, eg. Set to 0 to follow the camera,
+ * 0.5 to move at half-speed of the camera, or 1 (default) to stay still.
+ */
+ public var scrollX:Number = 1;
+
+ /**
+ * Y scrollfactor, effects how much the camera offsets the drawn graphic.
+ * Can be used for parallax effect, eg. Set to 0 to follow the camera,
+ * 0.5 to move at half-speed of the camera, or 1 (default) to stay still.
+ */
+ public var scrollY:Number = 1;
+
+ /**
+ * If the graphic should render at its position relative to its parent Entity's position.
+ */
+ public var relative:Boolean = true;
+
+ /**
+ * Constructor.
+ */
+ public function Graphic()
+ {
+
+ }
+
+ /**
+ * Updates the graphic.
+ */
+ public function update():void
+ {
+
+ }
+
+ /**
+ * Renders the graphic to the screen buffer.
+ * @param point The position to draw the graphic.
+ * @param camera The camera offset.
+ */
+ public function render(target:BitmapData, point:Point, camera:Point):void
+ {
+
+ }
+
+ /** @private Callback for when the graphic is assigned to an Entity. */
+ protected function get assign():Function { return _assign; }
+ protected function set assign(value:Function):void { _assign = value; }
+
+ // Graphic information.
+ /** @private */ internal var _assign:Function;
+ /** @private */ internal var _scroll:Boolean = true;
+ /** @private */ protected var _point:Point = new Point;
+ }
+}
View
78 net/flashpunk/Mask.as
@@ -0,0 +1,78 @@
+package net.flashpunk
+{
+ import flash.utils.Dictionary;
+ import flash.utils.getDefinitionByName;
+ import flash.utils.getQualifiedClassName;
+ import net.flashpunk.masks.Hitbox;
+ import net.flashpunk.masks.Masklist;
+
+ /**
+ * Base class for Entity collision masks.
+ */
+ public class Mask
+ {
+ /**
+ * The parent Entity of this mask.
+ */
+ public var parent:Entity;
+
+ /**
+ * The parent Masklist of the mask.
+ */
+ public var list:Masklist;
+
+ /**
+ * Constructor.
+ */
+ public function Mask()
+ {
+ _class = Class(getDefinitionByName(getQualifiedClassName(this)));
+ _check[Mask] = collideMask;
+ _check[Masklist] = collideMasklist;
+ }
+
+ /**
+ * Checks for collision with another Mask.
+ * @param mask The other Mask to check against.
+ * @return If the Masks overlap.
+ */
+ public function collide(mask:Mask):Boolean
+ {
+ if (_check[mask._class] != null) return _check[mask._class](mask);
+ if (mask._check[_class] != null) return mask._check[_class](this);
+ return false;
+ }
+
+ /** @private Collide against an Entity. */
+ private function collideMask(other:Mask):Boolean
+ {
+ return parent.x - parent.originX + parent.width > other.parent.x - other.parent.originX
+ && parent.y - parent.originY + parent.height > other.parent.y - other.parent.originY
+ && parent.x - parent.originX < other.parent.x - other.parent.originX + other.parent.width
+ && parent.y - parent.originY < other.parent.y - other.parent.originY + other.parent.height;
+ }
+
+ /** @private Collide against a Masklist. */
+ protected function collideMasklist(other:Masklist):Boolean
+ {
+ return other.collide(this);
+ }
+
+ /** @private Assigns the mask to the parent. */
+ internal function assignTo(parent:Entity):void
+ {
+ this.parent = parent;
+ if (parent) update();
+ }
+
+ /** @private Updates the parent's bounds for this mask. */
+ protected function update():void
+ {
+
+ }
+
+ // Mask information.
+ /** @private */ private var _class:Class;
+ /** @private */ protected var _check:Dictionary = new Dictionary;
+ }
+}
View
41 net/flashpunk/README.markdown
@@ -0,0 +1,41 @@
+ABOUT
+=====
+
+FlashPunk is a free ActionScript 3 library designed for developing 2D Flash games. It provides you with a fast, clean framework to prototype and develop your games in. This means that most of the dirty work (timestep, animation, input, and collision to name a few) is already coded for you and ready to go, giving you more time and energy to concentrate on the design and testing of your game.
+
+FEATURES
+========
+
+* Framerate-independent and fixed-framerate timestep support.
+* Fast & manageable rectangle, pixel, and grid collision system.
+* Helper classes for animations, tilemaps, text, backdrops, and more.