Permalink
Browse files

Added Conway's Game of Life example

Updated the particle engine to have effects
Added the explosion, spray, and spark example
Updated jQuery UI to latest stable
Doing some work on the level editor
  • Loading branch information...
bfattori committed Mar 15, 2013
1 parent c124026 commit e9ef3c9340b3edd6bfab74ff4be5b7eb72f3b8ec
Showing with 918 additions and 521 deletions.
  1. +1 −0 demos/index.html
  2. +192 −0 demos/life/game.js
  3. +18 −0 demos/life/index.html
  4. +2 −2 demos/tilemap/game.js
  5. +11 −1 demos/vector/game.js
  6. +10 −50 demos/vector/particle.js
  7. +10 −8 demos/vector/rock.js
  8. +1 −0 engine/build/engine.intro.js
  9. +9 −1 engine/build/engine.main.js
  10. +1 −0 engine/build/namespaces.js
  11. +8 −0 engine/game.js
  12. +1 −1 engine/math/point2d.js
  13. +1 −0 engine/particles/accumulatorparticleengine.js
  14. +103 −0 engine/particles/effect.js
  15. +115 −0 engine/particles/effects/explosion.js
  16. +49 −0 engine/particles/effects/spark.js
  17. +108 −0 engine/particles/effects/spray.js
  18. +42 −3 engine/particles/particleengine.js
  19. +76 −20 engine/resources/types/tilemap.js
  20. +10 −1 engine/runtime/engine.js
  21. BIN tools/level_editor/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
  22. BIN tools/level_editor/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
  23. BIN tools/level_editor/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
  24. BIN tools/level_editor/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
  25. BIN tools/level_editor/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png
  26. BIN tools/level_editor/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
  27. BIN tools/level_editor/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
  28. BIN tools/level_editor/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
  29. BIN tools/level_editor/css/smoothness/images/ui-icons_222222_256x240.png
  30. BIN tools/level_editor/css/smoothness/images/ui-icons_2e83ff_256x240.png
  31. BIN tools/level_editor/css/smoothness/images/ui-icons_454545_256x240.png
  32. BIN tools/level_editor/css/smoothness/images/ui-icons_888888_256x240.png
  33. BIN tools/level_editor/css/smoothness/images/ui-icons_cd0a0a_256x240.png
  34. +0 −349 tools/level_editor/css/smoothness/jquery-ui-1.8.8.custom.css
  35. +1 −0 tools/level_editor/edit_tilemaps.js
  36. +124 −60 tools/level_editor/level_editor.js
  37. +25 −25 tutorials/tutorial13/particle.js
View
@@ -37,6 +37,7 @@
<em>The Render Engine</em> Demos
<ul>
<li loc="empty/empty.html">Start the Engine</li>
+ <li loc="life/index.html">Conway's Game of Life</li>
<li loc="htmlcontext/index.html">HTMLContext Demo</li>
<li loc="vector/index.html">Vector Graphics Demo</li>
<li loc="tilemap/index.html">2d Tile Demo</li>
View
@@ -0,0 +1,192 @@
+// Load all required engine components
+R.Engine.define({
+ "class": "GameOfLife",
+ "requires": [
+ "R.engine.Game"
+ ]
+});
+
+/**
+ * @class Game of Life
+ */
+var GameOfLife = function () {
+ return R.engine.Game.extend({
+
+ world: null,
+
+ LIVE_CELL: 1,
+ DEAD_CELL: 2,
+ CELL_DIED: 3,
+ CELL_BORN: 4,
+
+ cellWidth: 0,
+ cellHeight: 0,
+
+ playWidth: 500,
+ playHeight: 500,
+
+ xDivisions: 0,
+ yDivisions: 0,
+
+ surroundingCells: [],
+
+ TOP_LEFT: R.math.Point2D.create(-1, -1),
+ TOP_CENTER: R.math.Point2D.create(0, -1),
+ TOP_RIGHT: R.math.Point2D.create(1, -1),
+ LEFT: R.math.Point2D.create(-1, 0),
+ RIGHT: R.math.Point2D.create(1, 0),
+ BOTTOM_LEFT: R.math.Point2D.create(-1, 1),
+ BOTTOM_CENTER: R.math.Point2D.create(0, 1),
+ BOTTOM_RIGHT: R.math.Point2D.create(1, 1),
+
+ /**
+ * Called to set up the game, download any resources, and initialize
+ * the game to its running state.
+ */
+ setup: function () {
+ GameOfLife.seedWorld(R.engine.Support.getNumericParam('width', 30),
+ R.engine.Support.getNumericParam('height', 30),
+ R.engine.Support.getNumericParam('seed', R.lang.Math2.randomInt()));
+ },
+
+ seedWorld: function(worldWidth, worldHeight, seed) {
+ R.lang.Math2.seed(seed);
+
+ GameOfLife.cellWidth = Math.floor(GameOfLife.playWidth / worldWidth);
+ GameOfLife.cellHeight = Math.floor(GameOfLife.playHeight / worldHeight);
+
+ // Drop a few dynamic styles
+ var cellStyle = 'div.cell { width: ' + GameOfLife.cellWidth + 'px; height: ' + GameOfLife.cellHeight + 'px; ' +
+ 'float: left; position: relative; padding: 0; margin: 0; line-height: 7px; } ' +
+ 'div.cell.alive { background-color: black; } ' +
+ 'div.cell.dead { background-color: none; } ';
+
+ var worldStyle = 'div.world { width: ' + (GameOfLife.playWidth + 1) + 'px; height: ' +
+ (GameOfLife.playHeight + 1) + 'px; ' +
+ 'border: 1px solid black; }';
+
+ var styles = "<style type='text/css'>" + cellStyle + worldStyle + "</style>";
+ $("head").append(styles);
+
+ GameOfLife.world = [];
+ for (var cell = 0; cell < worldWidth * worldHeight; cell++) {
+ var cellState = R.lang.Math2.randomRange(GameOfLife.LIVE_CELL, GameOfLife.DEAD_CELL, true);
+ GameOfLife.world[cell] = {
+ state: cellState,
+ element: $("<div>").addClass("cell").addClass(cellState === GameOfLife.LIVE_CELL ? 'alive' : 'dead')
+ };
+ }
+
+ GameOfLife.xDivisions = worldWidth;
+ GameOfLife.yDivisions = worldHeight;
+
+ // Draw out the cells
+ var world = $("<div class='world'>");
+ for (cell = 0; cell < GameOfLife.world.length; cell++) {
+ world.append(GameOfLife.world[cell].element);
+ }
+
+ $("body", document).append(world).append($("<div>").html("seed: " + seed));
+
+ for (var x = 0; x < 8; x++) {
+ GameOfLife.surroundingCells[x] = R.math.Point2D.create(0,0);
+ }
+
+
+ },
+
+ applyRules: function(cell) {
+ var surroundingCells = [];
+
+ // Get the cell
+ var theCell = GameOfLife.world[cell];
+ var isAlive = (theCell.state == GameOfLife.LIVE_CELL);
+
+ // Cell loc
+ var cellPoint = GameOfLife.getCoordinates(cell);
+
+ // Surrounding cells
+ GameOfLife.surroundingCells[0].set(cellPoint).add(GameOfLife.TOP_LEFT);
+ GameOfLife.surroundingCells[1].set(cellPoint).add(GameOfLife.TOP_CENTER);
+ GameOfLife.surroundingCells[2].set(cellPoint).add(GameOfLife.TOP_RIGHT);
+ GameOfLife.surroundingCells[3].set(cellPoint).add(GameOfLife.LEFT);
+ GameOfLife.surroundingCells[4].set(cellPoint).add(GameOfLife.RIGHT);
+ GameOfLife.surroundingCells[5].set(cellPoint).add(GameOfLife.BOTTOM_LEFT);
+ GameOfLife.surroundingCells[6].set(cellPoint).add(GameOfLife.BOTTOM_CENTER);
+ GameOfLife.surroundingCells[7].set(cellPoint).add(GameOfLife.BOTTOM_RIGHT);
+
+ // Determine which neighbors are alive
+ var liveNeighbors = 0;
+ for (var sCell = 0; sCell < GameOfLife.surroundingCells.length; sCell++) {
+ if (GameOfLife.surroundingCells[sCell].x == -1) {
+ GameOfLife.surroundingCells[sCell].x = GameOfLife.xDivisions - 1;
+ }
+
+ if (GameOfLife.surroundingCells[sCell].x > GameOfLife.xDivisions - 1) {
+ GameOfLife.surroundingCells[sCell].x = 0;
+ }
+
+ if (GameOfLife.surroundingCells[sCell].y < 0) {
+ GameOfLife.surroundingCells[sCell].y = GameOfLife.yDivisions - 1;
+ }
+
+ if (GameOfLife.surroundingCells[sCell].y > GameOfLife.yDivisions - 1) {
+ GameOfLife.surroundingCells[sCell].y = 0;
+ }
+
+ var neighborCell = GameOfLife.getCell(GameOfLife.surroundingCells[sCell]);
+
+ if (GameOfLife.world[neighborCell].state == GameOfLife.LIVE_CELL) {
+ liveNeighbors++;
+ }
+ }
+
+ // Run the rules
+ if (isAlive && liveNeighbors < 2) {
+ theCell.state = GameOfLife.CELL_DIED;
+ } else if (isAlive && (liveNeighbors == 2 || liveNeighbors == 3)) {
+ // Lives on
+ } else if (isAlive && liveNeighbors > 3) {
+ theCell.state = GameOfLife.CELL_DIED;
+ } else if (!isAlive && liveNeighbors == 3) {
+ theCell.state = GameOfLife.CELL_BORN;
+ }
+
+ // Clean up
+ cellPoint.destroy();
+ },
+
+ getCell: function(point) {
+ return (point.y * GameOfLife.yDivisions + point.x);
+ },
+
+ getCoordinates: function(cell) {
+ var y = Math.floor(cell / GameOfLife.xDivisions);
+ var x = (cell % GameOfLife.xDivisions);
+ return R.math.Point2D.create(x, y);
+ },
+
+ tick: function(time, dt) {
+ var cell;
+
+ // Process rules
+ for (cell = 0; cell < GameOfLife.world.length; cell++) {
+ GameOfLife.applyRules(cell);
+ }
+
+ // End cycle
+ for (cell = 0; cell < GameOfLife.world.length; cell++) {
+ if (GameOfLife.world[cell].state == GameOfLife.CELL_DIED) {
+ GameOfLife.world[cell].element.removeClass("alive").addClass("dead");
+ GameOfLife.world[cell].state = GameOfLife.DEAD_CELL;
+ }
+
+ if (GameOfLife.world[cell].state == GameOfLife.CELL_BORN) {
+ GameOfLife.world[cell].element.addClass("alive").removeClass("dead");
+ GameOfLife.world[cell].state = GameOfLife.LIVE_CELL;
+ }
+ }
+ }
+
+ });
+};
View
@@ -0,0 +1,18 @@
+<!doctype html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>The Render Engine - Conway's Game of Life</title>
+
+ <!-- Load the main engine script -->
+ <script type="text/javascript" src="../../engine/runtime/engine.js"></script>
+
+ </head>
+ <body>
+ <script type="text/javascript">
+ // Load the game script
+ $(document).ready(function() {
+ R.loadGame('game.js', 'GameOfLife', 'Conway\'s Game of Life');
+ });
+ </script>
+ </body>
+</html>
View
@@ -111,8 +111,8 @@ var TilemapDemo = function() {
run: function() {
// Create the 2D context
-// this.renderContext = R.rendercontexts.VirtualCanvasContext.create("playfield", 800, 600, 3200, 3200);
- this.renderContext = R.rendercontexts.VirtualHTMLDivContext.create("playfield", 800, 600, 3200, 3200);
+ this.renderContext = R.rendercontexts.VirtualCanvasContext.create("playfield", 800, 600, 3200, 3200);
+// this.renderContext = R.rendercontexts.VirtualHTMLDivContext.create("playfield", 800, 600, 3200, 3200);
this.renderContext.setWorldScale(this.areaScale);
R.Engine.getDefaultContext().add(this.renderContext);
this.renderContext.setBackgroundColor("#0a0a0a");
View
@@ -50,7 +50,8 @@ R.Engine.define({
"R.engine.Events",
"R.math.Math2D",
//"R.particles.ParticleEngine"
- "R.particles.AccumulatorParticleEngine"
+ "R.particles.AccumulatorParticleEngine",
+ "R.particles.effects.Spark"
],
// Game class dependencies
@@ -174,6 +175,15 @@ var Spaceroids = function() {
this.pEngine.setFadeRate(0.5);
+ this.pEngine.addEffect(R.particles.effects.Spark.create(titlePos).
+ quantity(10).
+ lifespan(Infinity).
+ particle(R.particles.effects.SprayParticle).
+ particleLife(1000).
+ width(10).
+ delay(10000, 2000)
+ );
+
var pWidth = this.fieldWidth;
var pHeight = this.fieldHeight;
View
@@ -34,7 +34,7 @@
R.Engine.define({
"class": "SimpleParticle",
"requires": [
- "R.particles.AbstractParticle",
+ "R.particles.effects.Explosion",
"R.math.Math2D"
]
});
@@ -46,40 +46,8 @@ R.Engine.define({
* velocity vector will be derived from this position.
*/
var SimpleParticle = function() {
- return R.particles.AbstractParticle.extend(/** @scope SimpleParticle.prototype */{
-
- vec: null,
- decel: 0,
- invVel: null,
-
- constructor: function(pos, ttl, decel) {
- this.base(ttl || 2000);
- this.setPosition(pos.x, pos.y);
+ return R.particles.effects.ExplosionParticle.extend(/** @scope SimpleParticle.prototype */{
- var a = Math.floor(R.lang.Math2.random() * 360);
-
- if (this.invVel == null) {
- // Another situation where it's better to keep this value, rather than destroying
- // it after use. Since particles are short-lived, it's better to do this than
- // create/destroy over and over.
- this.invVel = R.math.Vector2D.create(0, 0);
- }
-
- if (this.vec == null) {
- // Same as above to save cycles...
- this.vec = R.math.Vector2D.create(0, 0);
- }
-
- R.math.Math2D.getDirectionVector(R.math.Point2D.ZERO, R.math.Vector2D.UP, a, this.vec);
- var vel = 1 + (R.lang.Math2.random() * 5);
- this.vec.mul(vel);
- this.decel = decel;
- },
-
- release: function() {
- this.base();
- this.decel = 0;
- },
/**
* Called by the particle engine to draw the particle to the rendering
@@ -90,15 +58,7 @@ var SimpleParticle = function() {
* @param dt {Number} The delta between the world time and the last time the world was updated
* in milliseconds.
*/
- draw: function(renderContext, time, dt) {
- if (this.decel > 0 && this.vec.len() > 0) {
- this.invVel.set(this.vec).neg();
- this.invVel.mul(this.decel);
- this.vec.add(this.invVel);
- }
-
- this.getPosition().add(this.vec);
-
+ renderParticle: function(renderContext, time, dt) {
var colr,rgba;
if (!Spaceroids.isAttractMode) {
var s = time - this.getBirth();
@@ -148,7 +108,7 @@ R.Engine.define({
var TrailParticle = function() {
return R.particles.AbstractParticle.extend(/** @scope TrailParticle.prototype */{
- vec: null,
+ velocityVector: null,
clr: null,
constructor: function(pos, rot, spread, color, ttl) {
@@ -157,14 +117,14 @@ var TrailParticle = function() {
this.setPosition(pos.x, pos.y);
var a = rot + Math.floor((180 - (spread / 2)) + (R.lang.Math2.random() * (spread * 2)));
- if (this.vec == null) {
+ if (this.velocityVector == null) {
// Same as SimpleParticle to save cycles...
- this.vec = R.math.Vector2D.create(0, 0);
+ this.velocityVector = R.math.Vector2D.create(0, 0);
}
- R.math.Math2D.getDirectionVector(R.math.Point2D.ZERO, R.math.Vector2D.UP, a, this.vec);
+ R.math.Math2D.getDirectionVector(R.math.Point2D.ZERO, R.math.Vector2D.UP, a, this.velocityVector);
var vel = 1 + (R.lang.Math2.random() * 2);
- this.vec.mul(vel);
+ this.velocityVector.mul(vel);
},
release: function() {
@@ -186,7 +146,7 @@ var TrailParticle = function() {
* in milliseconds.
*/
draw: function(renderContext, time, dt) {
- this.getPosition().add(this.vec);
+ this.getPosition().add(this.velocityVector);
renderContext.setFillStyle(this.clr);
renderContext.drawPoint(this.getPosition());
}
@@ -219,7 +179,7 @@ var RockTrailParticle = function() {
release: function() {
this.base();
- this.decel = 0;
+ this.decay = 0;
},
/**
Oops, something went wrong.

0 comments on commit e9ef3c9

Please sign in to comment.