PageRenderTime 68ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/src/net/flashpunk/FP.as

https://github.com/olex/FlashPunk-JRPG-Engine
ActionScript | 712 lines | 393 code | 59 blank | 260 comment | 82 complexity | bfe176d856c935a464d0b238718fcf4b MD5 | raw file
  1. package net.flashpunk
  2. {
  3. import flash.display.BitmapData;
  4. import flash.display.Sprite;
  5. import flash.display.Stage;
  6. import flash.geom.Matrix;
  7. import flash.geom.Point;
  8. import flash.geom.Rectangle;
  9. import flash.media.SoundMixer;
  10. import flash.media.SoundTransform;
  11. import flash.system.System;
  12. import flash.utils.getTimer;
  13. import net.flashpunk.*;
  14. import net.flashpunk.debug.Console;
  15. /**
  16. * Static catch-all class used to access global properties and functions.
  17. */
  18. public class FP
  19. {
  20. /**
  21. * The FlashPunk major version.
  22. */
  23. public static const VERSION:String = "1.3";
  24. /**
  25. * Width of the game.
  26. */
  27. public static var width:uint;
  28. /**
  29. * Height of the game.
  30. */
  31. public static var height:uint;
  32. /**
  33. * If the game is running at a fixed framerate.
  34. */
  35. public static var fixed:Boolean;
  36. /**
  37. * The framerate assigned to the stage.
  38. */
  39. public static var frameRate:Number;
  40. /**
  41. * The framerate assigned to the stage.
  42. */
  43. public static var assignedFrameRate:Number;
  44. /**
  45. * Time elapsed since the last frame (non-fixed framerate only).
  46. */
  47. public static var elapsed:Number;
  48. /**
  49. * Timescale applied to FP.elapsed (non-fixed framerate only).
  50. */
  51. public static var rate:Number = 1;
  52. /**
  53. * The Screen object, use to transform or offset the Screen.
  54. */
  55. public static var screen:Screen;
  56. /**
  57. * The current screen buffer, drawn to in the render loop.
  58. */
  59. public static var buffer:BitmapData;
  60. /**
  61. * A rectangle representing the size of the screen.
  62. */
  63. public static var bounds:Rectangle;
  64. /**
  65. * Point used to determine drawing offset in the render loop.
  66. */
  67. public static var camera:Point = new Point;
  68. /**
  69. * The currently active World object. When you set this, the World is flagged
  70. * to switch, but won't actually do so until the end of the current frame.
  71. */
  72. public static function get world():World { return _world; }
  73. public static function set world(value:World):void
  74. {
  75. if (_world == value) return;
  76. _goto = value;
  77. }
  78. /**
  79. * Global volume factor for all sounds, a value from 0 to 1.
  80. */
  81. public static function get volume():Number { return _volume; }
  82. public static function set volume(value:Number):void
  83. {
  84. if (value < 0) value = 0;
  85. if (_volume == value) return;
  86. _soundTransform.volume = _volume = value;
  87. SoundMixer.soundTransform = _soundTransform;
  88. }
  89. /**
  90. * Global panning factor for all sounds, a value from -1 to 1.
  91. */
  92. public static function get pan():Number { return _pan; }
  93. public static function set pan(value:Number):void
  94. {
  95. if (value < -1) value = -1;
  96. if (value > 1) value = 1;
  97. if (_pan == value) return;
  98. _soundTransform.pan = _pan = value;
  99. SoundMixer.soundTransform = _soundTransform;
  100. }
  101. /**
  102. * Randomly chooses and returns one of the provided values.
  103. * @param ...objs The Objects you want to randomly choose from. Can be ints, Numbers, Points, etc.
  104. * @return A randomly chosen one of the provided parameters.
  105. */
  106. public static function choose(...objs):*
  107. {
  108. if (objs.length == 1 && (objs[0] is Array || objs[0] is Vector.<*>)) objs = objs[0];
  109. return objs[rand(objs.length)];
  110. }
  111. /**
  112. * Finds the sign of the provided value.
  113. * @param value The Number to evaluate.
  114. * @return 1 if value > 0, -1 if value < 0, and 0 when value == 0.
  115. */
  116. public static function sign(value:Number):int
  117. {
  118. return value < 0 ? -1 : (value > 0 ? 1 : 0);
  119. }
  120. /**
  121. * Approaches the value towards the target, by the specified amount, without overshooting the target.
  122. * @param value The starting value.
  123. * @param target The target that you want value to approach.
  124. * @param amount How much you want the value to approach target by.
  125. * @return The new value.
  126. */
  127. public static function approach(value:Number, target:Number, amount:Number):Number
  128. {
  129. return value < target ? (target < value + amount ? target : value + amount) : (target > value - amount ? target : value - amount);
  130. }
  131. /**
  132. * Linear interpolation between two values.
  133. * @param a First value.
  134. * @param b Second value.
  135. * @param t Interpolation factor.
  136. * @return When t=0, returns a. When t=1, returns b. When t=0.5, will return halfway between a and b. Etc.
  137. */
  138. public static function lerp(a:Number, b:Number, t:Number = 1):Number
  139. {
  140. return a + (b - a) * t;
  141. }
  142. /**
  143. * Linear interpolation between two colors.
  144. * @param fromColor First color.
  145. * @param toColor Second color.
  146. * @param t Interpolation value. Clamped to the range [0, 1].
  147. * return RGB component-interpolated color value.
  148. */
  149. public static function colorLerp(fromColor:uint, toColor:uint, t:Number = 1):uint
  150. {
  151. if (t <= 0) { return fromColor; }
  152. if (t >= 1) { return toColor; }
  153. var a:uint = fromColor >> 24 & 0xFF,
  154. r:uint = fromColor >> 16 & 0xFF,
  155. g:uint = fromColor >> 8 & 0xFF,
  156. b:uint = fromColor & 0xFF,
  157. dA: int = (toColor >> 24 & 0xFF) - a,
  158. dR: int = (toColor >> 16 & 0xFF) - r,
  159. dG: int = (toColor >> 8 & 0xFF) - g,
  160. dB: int = (toColor & 0xFF) - b;
  161. a += dA * t;
  162. r += dR * t;
  163. g += dG * t;
  164. b += dB * t;
  165. return a << 24 | r << 16 | g << 8 | b;
  166. }
  167. /**
  168. * Steps the object towards a point.
  169. * @param object Object to move (must have an x and y property).
  170. * @param x X position to step towards.
  171. * @param y Y position to step towards.
  172. * @param distance The distance to step (will not overshoot target).
  173. */
  174. public static function stepTowards(object:Object, x:Number, y:Number, distance:Number = 1):void
  175. {
  176. point.x = x - object.x;
  177. point.y = y - object.y;
  178. if (point.length > distance)
  179. {
  180. object.x = x;
  181. object.y = y;
  182. return;
  183. }
  184. point.normalize(distance);
  185. object.x += point.x;
  186. object.y += point.y;
  187. }
  188. /**
  189. * Finds the angle (in degrees) from point 1 to point 2.
  190. * @param x1 The first x-position.
  191. * @param y1 The first y-position.
  192. * @param x2 The second x-position.
  193. * @param y2 The second y-position.
  194. * @return The angle from (x1, y1) to (x2, y2).
  195. */
  196. public static function angle(x1:Number, y1:Number, x2:Number, y2:Number):Number
  197. {
  198. var a:Number = Math.atan2(y2 - y1, x2 - x1) * DEG;
  199. return a < 0 ? a + 360 : a;
  200. }
  201. /**
  202. * Sets the x/y values of the provided point to a vector of the specified angle and length.
  203. * @param point The point object to return.
  204. * @param angle The angle of the vector, in degrees.
  205. * @param length The distance to the vector from (0, 0).
  206. * @return The point object with x/y set to the length and angle from (0, 0).
  207. */
  208. public static function angleXY(point:Point, angle:Number, length:Number = 1):Point
  209. {
  210. angle *= RAD;
  211. point.x = Math.cos(angle) * length;
  212. point.y = Math.sin(angle) * length;
  213. return point;
  214. }
  215. /**
  216. * Find the distance between two points.
  217. * @param x1 The first x-position.
  218. * @param y1 The first y-position.
  219. * @param x2 The second x-position.
  220. * @param y2 The second y-position.
  221. * @return The distance.
  222. */
  223. public static function distance(x1:Number, y1:Number, x2:Number = 0, y2:Number = 0):Number
  224. {
  225. return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
  226. }
  227. /**
  228. * Find the distance between two rectangles. Will return 0 if the rectangles overlap.
  229. * @param x1 The x-position of the first rect.
  230. * @param y1 The y-position of the first rect.
  231. * @param w1 The width of the first rect.
  232. * @param h1 The height of the first rect.
  233. * @param x2 The x-position of the second rect.
  234. * @param y2 The y-position of the second rect.
  235. * @param w2 The width of the second rect.
  236. * @param h2 The height of the second rect.
  237. * @return The distance.
  238. */
  239. public static function distanceRects(x1:Number, y1:Number, w1:Number, h1:Number, x2:Number, y2:Number, w2:Number, h2:Number):Number
  240. {
  241. if (x1 < x2 + w2 && x2 < x1 + w1)
  242. {
  243. if (y1 < y2 + h2 && y2 < y1 + h1) return 0;
  244. if (y1 > y2) return y1 - (y2 + h2);
  245. return y2 - (y1 + h1);
  246. }
  247. if (y1 < y2 + h2 && y2 < y1 + h1)
  248. {
  249. if (x1 > x2) return x1 - (x2 + w2);
  250. return x2 - (x1 + w1)
  251. }
  252. if (x1 > x2)
  253. {
  254. if (y1 > y2) return distance(x1, y1, (x2 + w2), (y2 + h2));
  255. return distance(x1, y1 + h1, x2 + w2, y2);
  256. }
  257. if (y1 > y2) return distance(x1 + w1, y1, x2, y2 + h2)
  258. return distance(x1 + w1, y1 + h1, x2, y2);
  259. }
  260. /**
  261. * Find the distance between a point and a rectangle. Returns 0 if the point is within the rectangle.
  262. * @param px The x-position of the point.
  263. * @param py The y-position of the point.
  264. * @param rx The x-position of the rect.
  265. * @param ry The y-position of the rect.
  266. * @param rw The width of the rect.
  267. * @param rh The height of the rect.
  268. * @return The distance.
  269. */
  270. public static function distanceRectPoint(px:Number, py:Number, rx:Number, ry:Number, rw:Number, rh:Number):Number
  271. {
  272. if (px >= rx && px <= rx + rw)
  273. {
  274. if (py >= ry && py <= ry + rh) return 0;
  275. if (py > ry) return py - (ry + rh);
  276. return ry - py;
  277. }
  278. if (py >= ry && py <= ry + rh)
  279. {
  280. if (px > rx) return px - (rx + rw);
  281. return rx - px;
  282. }
  283. if (px > rx)
  284. {
  285. if (py > ry) return distance(px, py, rx + rw, ry + rh);
  286. return distance(px, py, rx + rw, ry);
  287. }
  288. if (py > ry) return distance(px, py, rx, ry + rh)
  289. return distance(px, py, rx, ry);
  290. }
  291. /**
  292. * Clamps the value within the minimum and maximum values.
  293. * @param value The Number to evaluate.
  294. * @param min The minimum range.
  295. * @param max The maximum range.
  296. * @return The clamped value.
  297. */
  298. public static function clamp(value:Number, min:Number, max:Number):Number
  299. {
  300. if (max > min)
  301. {
  302. value = value < max ? value : max;
  303. return value > min ? value : min;
  304. }
  305. value = value < min ? value : min;
  306. return value > max ? value : max;
  307. }
  308. /**
  309. * 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.
  310. * @param value The value on the first scale.
  311. * @param min The minimum range of the first scale.
  312. * @param max The maximum range of the first scale.
  313. * @param min2 The minimum range of the second scale.
  314. * @param max2 The maximum range of the second scale.
  315. * @return The scaled value.
  316. */
  317. public static function scale(value:Number, min:Number, max:Number, min2:Number, max2:Number):Number
  318. {
  319. return min2 + ((value - min) / (max - min)) * (max2 - min2);
  320. }
  321. /**
  322. * Transfers a value from one scale to another scale, but clamps the return value within the second scale.
  323. * @param value The value on the first scale.
  324. * @param min The minimum range of the first scale.
  325. * @param max The maximum range of the first scale.
  326. * @param min2 The minimum range of the second scale.
  327. * @param max2 The maximum range of the second scale.
  328. * @return The scaled and clamped value.
  329. */
  330. public static function scaleClamp(value:Number, min:Number, max:Number, min2:Number, max2:Number):Number
  331. {
  332. value = min2 + ((value - min) / (max - min)) * (max2 - min2);
  333. if (max2 > min2)
  334. {
  335. value = value < max2 ? value : max2;
  336. return value > min2 ? value : min2;
  337. }
  338. value = value < min2 ? value : min2;
  339. return value > max2 ? value : max2;
  340. }
  341. /**
  342. * The random seed used by FP's random functions.
  343. */
  344. public static function get randomSeed():uint { return _getSeed; }
  345. public static function set randomSeed(value:uint):void
  346. {
  347. _seed = clamp(value, 1, 2147483646);
  348. _getSeed = _seed;
  349. }
  350. /**
  351. * Randomizes the random seed using Flash's Math.random() function.
  352. */
  353. public static function randomizeSeed():void
  354. {
  355. randomSeed = 2147483647 * Math.random();
  356. }
  357. /**
  358. * A pseudo-random Number produced using FP's random seed, where 0 <= Number < 1.
  359. */
  360. public static function get random():Number
  361. {
  362. _seed = (_seed * 16807) % 2147483647;
  363. return _seed / 2147483647;
  364. }
  365. /**
  366. * Returns a pseudo-random uint.
  367. * @param amount The returned uint will always be 0 <= uint < amount.
  368. * @return The uint.
  369. */
  370. public static function rand(amount:uint):uint
  371. {
  372. _seed = (_seed * 16807) % 2147483647;
  373. return (_seed / 2147483647) * amount;
  374. }
  375. /**
  376. * Returns the next item after current in the list of options.
  377. * @param current The currently selected item (must be one of the options).
  378. * @param options An array of all the items to cycle through.
  379. * @param loop If true, will jump to the first item after the last item is reached.
  380. * @return The next item in the list.
  381. */
  382. public static function next(current:*, options:Array, loop:Boolean = true):*
  383. {
  384. if (loop) return options[(options.indexOf(current) + 1) % options.length];
  385. return options[Math.max(options.indexOf(current) + 1, options.length - 1)];
  386. }
  387. /**
  388. * Returns the item previous to the current in the list of options.
  389. * @param current The currently selected item (must be one of the options).
  390. * @param options An array of all the items to cycle through.
  391. * @param loop If true, will jump to the last item after the first is reached.
  392. * @return The previous item in the list.
  393. */
  394. public static function prev(current:*, options:Array, loop:Boolean = true):*
  395. {
  396. if (loop) return options[((options.indexOf(current) - 1) + options.length) % options.length];
  397. return options[Math.max(options.indexOf(current) - 1, 0)];
  398. }
  399. /**
  400. * Swaps the current item between a and b. Useful for quick state/string/value swapping.
  401. * @param current The currently selected item.
  402. * @param a Item a.
  403. * @param b Item b.
  404. * @return Returns a if current is b, and b if current is a.
  405. */
  406. public static function swap(current:*, a:*, b:*):*
  407. {
  408. return current == a ? b : a;
  409. }
  410. /**
  411. * Creates a color value by combining the chosen RGB values.
  412. * @param R The red value of the color, from 0 to 255.
  413. * @param G The green value of the color, from 0 to 255.
  414. * @param B The blue value of the color, from 0 to 255.
  415. * @return The color uint.
  416. */
  417. public static function getColorRGB(R:uint = 0, G:uint = 0, B:uint = 0):uint
  418. {
  419. return R << 16 | G << 8 | B;
  420. }
  421. /**
  422. * Finds the red factor of a color.
  423. * @param color The color to evaluate.
  424. * @return A uint from 0 to 255.
  425. */
  426. public static function getRed(color:uint):uint
  427. {
  428. return color >> 16 & 0xFF;
  429. }
  430. /**
  431. * Finds the green factor of a color.
  432. * @param color The color to evaluate.
  433. * @return A uint from 0 to 255.
  434. */
  435. public static function getGreen(color:uint):uint
  436. {
  437. return color >> 8 & 0xFF;
  438. }
  439. /**
  440. * Finds the blue factor of a color.
  441. * @param color The color to evaluate.
  442. * @return A uint from 0 to 255.
  443. */
  444. public static function getBlue(color:uint):uint
  445. {
  446. return color & 0xFF;
  447. }
  448. /**
  449. * Fetches a stored BitmapData object represented by the source.
  450. * @param source Embedded Bitmap class.
  451. * @return The stored BitmapData object.
  452. */
  453. public static function getBitmap(source:Class):BitmapData
  454. {
  455. if (_bitmap[String(source)]) return _bitmap[String(source)];
  456. return (_bitmap[String(source)] = (new source).bitmapData);
  457. }
  458. /**
  459. * Sets a time flag.
  460. * @return Time elapsed (in milliseconds) since the last time flag was set.
  461. */
  462. public static function timeFlag():uint
  463. {
  464. var t:uint = getTimer(),
  465. e:uint = t - _time;
  466. _time = t;
  467. return e;
  468. }
  469. /**
  470. * The global Console object.
  471. */
  472. public static function get console():Console
  473. {
  474. if (!_console) _console = new Console;
  475. return _console;
  476. }
  477. /**
  478. * Logs data to the console.
  479. * @param ...data The data parameters to log, can be variables, objects, etc. Parameters will be separated by a space (" ").
  480. */
  481. public static function log(...data):void
  482. {
  483. if (_console)
  484. {
  485. if (data.length > 1)
  486. {
  487. var i:int = 0, s:String = "";
  488. while (i < data.length)
  489. {
  490. if (i > 0) s += " ";
  491. s += data[i ++].toString();
  492. }
  493. _console.log(s);
  494. }
  495. else _console.log(data[0]);
  496. }
  497. }
  498. /**
  499. * Adds properties to watch in the console's debug panel.
  500. * @param ...properties The properties (strings) to watch.
  501. */
  502. public static function watch(...properties):void
  503. {
  504. if (_console)
  505. {
  506. if (properties.length > 1) _console.watch(properties);
  507. else _console.watch(properties[0]);
  508. }
  509. }
  510. /**
  511. * Shuffles the elements in the array.
  512. * @param a The Object to shuffle (an Array or Vector).
  513. */
  514. public static function shuffle(a:Object):void
  515. {
  516. if (a is Array || a is Vector.<*>)
  517. {
  518. var i:int = a.length, j:int, t:*;
  519. while (-- i)
  520. {
  521. t = a[i];
  522. a[i] = a[j = FP.rand(i + 1)];
  523. a[j] = t;
  524. }
  525. }
  526. }
  527. /**
  528. * Sorts the elements in the array.
  529. * @param object The Object to sort (an Array or Vector).
  530. * @param ascending If it should be sorted ascending (true) or descending (false).
  531. */
  532. public static function sort(object:Object, ascending:Boolean = true):void
  533. {
  534. if (object is Array || object is Vector.<*>) quicksort(object, 0, object.length - 1, ascending);
  535. }
  536. /**
  537. * Sorts the elements in the array by a property of the element.
  538. * @param object The Object to sort (an Array or Vector).
  539. * @param property The numeric property of object's elements to sort by.
  540. * @param ascending If it should be sorted ascending (true) or descending (false).
  541. */
  542. public static function sortBy(object:Object, property:String, ascending:Boolean = true):void
  543. {
  544. if (object is Array || object is Vector.<*>) quicksortBy(object, 0, object.length - 1, ascending, property);
  545. }
  546. /** @private Quicksorts the array. */
  547. private static function quicksort(a:Object, left:int, right:int, ascending:Boolean):void
  548. {
  549. var i:int = left, j:int = right, t:Number,
  550. p:* = a[Math.round((left + right) * .5)];
  551. if (ascending)
  552. {
  553. while (i <= j)
  554. {
  555. while (a[i] < p) i ++;
  556. while (a[j] > p) j --;
  557. if (i <= j)
  558. {
  559. t = a[i];
  560. a[i ++] = a[j];
  561. a[j --] = t;
  562. }
  563. }
  564. }
  565. else
  566. {
  567. while (i <= j)
  568. {
  569. while (a[i] > p) i ++;
  570. while (a[j] < p) j --;
  571. if (i <= j)
  572. {
  573. t = a[i];
  574. a[i ++] = a[j];
  575. a[j --] = t;
  576. }
  577. }
  578. }
  579. if (left < j) quicksort(a, left, j, ascending);
  580. if (i < right) quicksort(a, i, right, ascending);
  581. }
  582. /** @private Quicksorts the array by the property. */
  583. private static function quicksortBy(a:Object, left:int, right:int, ascending:Boolean, property:String):void
  584. {
  585. var i:int = left, j:int = right, t:Object,
  586. p:* = a[Math.round((left + right) * .5)][property];
  587. if (ascending)
  588. {
  589. while (i <= j)
  590. {
  591. while (a[i][property] < p) i ++;
  592. while (a[j][property] > p) j --;
  593. if (i <= j)
  594. {
  595. t = a[i];
  596. a[i ++] = a[j];
  597. a[j --] = t;
  598. }
  599. }
  600. }
  601. else
  602. {
  603. while (i <= j)
  604. {
  605. while (a[i][property] > p) i ++;
  606. while (a[j][property] < p) j --;
  607. if (i <= j)
  608. {
  609. t = a[i];
  610. a[i ++] = a[j];
  611. a[j --] = t;
  612. }
  613. }
  614. }
  615. if (left < j) quicksortBy(a, left, j, ascending, property);
  616. if (i < right) quicksortBy(a, i, right, ascending, property);
  617. }
  618. // World information.
  619. /** @private */ internal static var _world:World;
  620. /** @private */ internal static var _goto:World;
  621. // Console information.
  622. /** @private */ internal static var _console:Console;
  623. // Time information.
  624. /** @private */ internal static var _time:uint;
  625. /** @private */ public static var _updateTime:uint;
  626. /** @private */ public static var _renderTime:uint;
  627. /** @private */ public static var _gameTime:uint;
  628. /** @private */ public static var _flashTime:uint;
  629. // Bitmap storage.
  630. /** @private */ private static var _bitmap:Object = { };
  631. // Pseudo-random number generation (the seed is set in Engine's contructor).
  632. /** @private */ private static var _seed:uint = 0;
  633. /** @private */ private static var _getSeed:uint;
  634. // Volume control.
  635. /** @private */ private static var _volume:Number = 1;
  636. /** @private */ private static var _pan:Number = 0;
  637. /** @private */ private static var _soundTransform:SoundTransform = new SoundTransform;
  638. // Used for rad-to-deg and deg-to-rad conversion.
  639. /** @private */ public static const DEG:Number = -180 / Math.PI;
  640. /** @private */ public static const RAD:Number = Math.PI / -180;
  641. // Global Flash objects.
  642. /** @private */ public static var stage:Stage;
  643. /** @private */ public static var engine:Engine;
  644. // Global objects used for rendering, collision, etc.
  645. /** @private */ public static var point:Point = new Point;
  646. /** @private */ public static var point2:Point = new Point;
  647. /** @private */ public static var zero:Point = new Point;
  648. /** @private */ public static var rect:Rectangle = new Rectangle;
  649. /** @private */ public static var matrix:Matrix = new Matrix;
  650. /** @private */ public static var sprite:Sprite = new Sprite;
  651. /** @private */ public static var entity:Entity;
  652. }
  653. }