diff --git a/examples/particles/index.html b/examples/particles/index.html new file mode 100644 index 0000000..ccba0ee --- /dev/null +++ b/examples/particles/index.html @@ -0,0 +1,10 @@ + + + + Particles - MomentumEngine + + + + + + \ No newline at end of file diff --git a/examples/particles/particles.js b/examples/particles/particles.js new file mode 100644 index 0000000..fcc3592 --- /dev/null +++ b/examples/particles/particles.js @@ -0,0 +1,45 @@ +"use strict"; + +import MomentumEngine from "../../src/es6"; + +let white = new MomentumEngine.Classes.Color(255, 255, 255); + +class BlueParticle extends MomentumEngine.Classes.Rect { + + constructor (x, y) { + super(x, y, 1, 1, white); + } + +} + + +window.onload = function () { + + var width = 640, + height = 360, + baseSize = width / 64; + + var particles = new MomentumEngine.Classes.Game({ + canvas: document.getElementById("canvas"), + width: width, + height: height, + fixRatio: true, + desiredFps: 60 + }); + + var black = new MomentumEngine.Classes.Color(0, 0, 0), + red = new MomentumEngine.Classes.Color(255, 0, 0); + + var mainScene = new MomentumEngine.Classes.Rect(0, 0, width, height, black); + particles.addChildEntity(mainScene); + + var rect = new MomentumEngine.Classes.Rect(width / 2 - baseSize, height / 2 - baseSize, baseSize * 2, baseSize * 2, red), + emitter = new MomentumEngine.Classes.Emitter(0, 0, new MomentumEngine.Classes.Vector2D(1, 1), BlueParticle); + + mainScene.addChildEntity(rect); + rect.addChildEntity(emitter); + + emitter.emitting = true; + particles.start(); + +}; \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index e42da1b..57067f6 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -26,7 +26,8 @@ var build = function (options, callback) { webpack({ entry: { - "es5": path.join(__dirname, "src", "es5.js") + "es5": path.join(__dirname, "src", "es5.js"), + "particles": path.join(__dirname, "examples/particles", "particles.js") }, bail: !options.watch, watch: options.watch, @@ -41,7 +42,8 @@ var build = function (options, callback) { loader: "babel-loader", test: /\.js$/, include: [ - path.join(__dirname, "src") + path.join(__dirname, "src"), + path.join(__dirname, "examples") ], query: { plugins: ["transform-runtime"], @@ -76,6 +78,15 @@ var build = function (options, callback) { }; +gulp.task("move", () => { + gulp.src([ + "./dist/particles.*" + ], { + base: "./dist" + }).pipe(gulp.dest("examples/particles/dist")); +}); + + gulp.task("build-dev", (callback) => { build({ watch: false, diff --git a/package.json b/package.json index cc7c0b7..bebcb7d 100644 --- a/package.json +++ b/package.json @@ -12,15 +12,15 @@ "node": "^4.2.3" }, "devDependencies": { - "babel-core": "6.3.17", - "babel-loader": "6.2.0", - "babel-plugin-transform-runtime": "6.3.13", - "babel-preset-es2015": "6.3.13", - "babel-preset-stage-0": "6.3.13", - "babel-runtime": "6.3.19", - "gulp": "3.9.0", + "babel-core": "6.5.2", + "babel-loader": "6.2.2", + "babel-plugin-transform-runtime": "6.5.2", + "babel-preset-es2015": "6.5.0", + "babel-preset-stage-0": "6.5.0", + "babel-runtime": "6.5.0", + "gulp": "3.9.1", "gulp-util": "3.0.7", - "webpack": "1.12.9" + "webpack": "1.12.13" }, "dependencies": {} } diff --git a/src/classes/emitter.js b/src/classes/emitter.js new file mode 100644 index 0000000..1755403 --- /dev/null +++ b/src/classes/emitter.js @@ -0,0 +1,56 @@ +"use strict"; + +import Entity from "./entity.js"; +import Vector2D from "./vector2d.js"; + + +class Emitter extends Entity { + + + constructor (x, y, velocity, particle) { + + super(x, y); + + this.particleVelocity = velocity; + this.particleClass = particle; + this.emitting = false; + + this.particles = []; + + this.spread = function () { + return Math.PI / 32; + } + + } + + + _emit () { + + if (this.emitting) { + + let ParticleClass = this.particleClass; + + let angle = this.particleVelocity.angle() + this.spread() - (Math.random() * this.spread() * 2), + magnitude = this.particleVelocity.length(), + velocity = Vector2D.fromAngle(angle, magnitude); + + let particle = new ParticleClass(this.pos.x, this.pos.y); + particle.velocity = velocity; + + this.particles.push(particle); + this._parent.addChildEntity(particle); + + } + + } + + + update () { + this._emit(); + } + + +} + + +export default Emitter; \ No newline at end of file diff --git a/src/classes/entity.js b/src/classes/entity.js index 629cb15..705b028 100644 --- a/src/classes/entity.js +++ b/src/classes/entity.js @@ -8,6 +8,8 @@ class Entity { constructor (x, y) { this.pos = new Vector2D(x || 0, y || 0); + this.velocity = new Vector2D(0, 0); + this.acceleration = new Vector2D(0, 0); this.state = {}; this.children = []; @@ -20,6 +22,30 @@ class Entity { } + setVelocity (x, y) { + + if (x instanceof Vector2D) { + this.velocity = x; + } else { + this.velocity.x = x; + this.velocity.y = y; + } + + } + + + setAcceleration (x, y) { + + if (x instanceof Vector2D) { + this.acceleration = x; + } else { + this.acceleration.x = x; + this.acceleration.y = y; + } + + } + + createChildEntity () { let child = new Entity(); @@ -46,7 +72,7 @@ class Entity { detachChildEntity (child) { - for (var i = 0; i < this.children.length; i++) { + for (let i = 0; i < this.children.length; i++) { if (this.children[i] == child) { this.children.splice(i, 1); @@ -104,7 +130,19 @@ class Entity { _updateEntity (delta) { - var updated = this.update && this.update(delta); + // Calculate new position based on velocity and acceleration if there's one set + if (this.velocity) { + + if (this.acceleration) { + this.velocity.add(this.acceleration); + } + + this.pos.add(this.velocity); + + } + + // If there's an update method, call it + let updated = this.update && this.update(delta); if (updated || (typeof updated == "undefined") || (typeof this.update === "undefined")) { @@ -121,7 +159,7 @@ class Entity { this._preprocess(); - var rendered = this.render && this.render(); + let rendered = this.render && this.render(); if (rendered || (typeof rendered == "undefined") || (typeof this.render === "undefined")) { diff --git a/src/classes/game.js b/src/classes/game.js index 501dc2f..283a47d 100644 --- a/src/classes/game.js +++ b/src/classes/game.js @@ -123,7 +123,7 @@ class Game extends Entity { self._wantPause = false; - var requestFrame = (() => { + let requestFrame = (() => { return (window.requestAnimationFrame || window.webkitRequestAnimationFrame || diff --git a/src/classes/sprite.js b/src/classes/sprite.js index 4a83ca9..3aa0048 100644 --- a/src/classes/sprite.js +++ b/src/classes/sprite.js @@ -46,9 +46,9 @@ class Sprite extends Entity { if (this.isReady() && this._game) { - var imageObj = this._image.getImageObj(); + let imageObj = this._image.getImageObj(); - var subWidth = imageObj.width - this._imagePos.x, + let subWidth = imageObj.width - this._imagePos.x, subHeight = imageObj.height - this._imagePos.y; this._game.context.drawImage( diff --git a/src/classes/vector2d.js b/src/classes/vector2d.js index 507e22e..32309d8 100644 --- a/src/classes/vector2d.js +++ b/src/classes/vector2d.js @@ -101,6 +101,11 @@ class Vector2D { } + angle () { + return Math.atan2(this.x, this.y); + } + + toArray () { return [this.x, this.y]; } @@ -116,6 +121,11 @@ class Vector2D { } + static fromAngle (angle, length) { + return new Vector2D(length * Math.cos(angle), length * Math.sin(angle)); + } + + } diff --git a/src/es5.js b/src/es5.js index d81b8ec..f2bcf63 100644 --- a/src/es5.js +++ b/src/es5.js @@ -1,6 +1,7 @@ "use strict"; import Game from "./classes/game.js"; +import Emitter from "./classes/emitter.js"; import Entity from "./classes/entity.js"; import Vector2D from "./classes/vector2d.js"; import Sprite from "./classes/sprite.js"; @@ -13,6 +14,7 @@ import {KeyConsts} from "./classes/keyboardinput.js"; const Classes = { Game: Game, + Emitter: Emitter, Entity: Entity, Sprite: Sprite, Rect: Rect, diff --git a/src/es6.js b/src/es6.js index 60008dd..5dafa0c 100644 --- a/src/es6.js +++ b/src/es6.js @@ -1,6 +1,7 @@ "use strict"; import Game from "./classes/game.js"; +import Emitter from "./classes/emitter.js"; import Entity from "./classes/entity.js"; import Vector2D from "./classes/vector2d.js"; import Sprite from "./classes/sprite.js"; @@ -13,6 +14,7 @@ import {KeyConsts} from "./classes/keyboardinput.js"; const Classes = { Game: Game, + Emitter: Emitter, Entity: Entity, Sprite: Sprite, Rect: Rect, @@ -29,7 +31,7 @@ const Consts = { }; -export { +export default { Classes, Consts }; \ No newline at end of file