First pass at particle system
This commit is contained in:
parent
7dbeda0dc9
commit
8735e06619
10
examples/particles/index.html
Normal file
10
examples/particles/index.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Particles - MomentumEngine</title>
|
||||
<script type="application/javascript" src="./dist/particles.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
</body>
|
||||
</html>
|
45
examples/particles/particles.js
Normal file
45
examples/particles/particles.js
Normal file
@ -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();
|
||||
|
||||
};
|
15
gulpfile.js
15
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,
|
||||
|
16
package.json
16
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": {}
|
||||
}
|
||||
|
56
src/classes/emitter.js
Normal file
56
src/classes/emitter.js
Normal file
@ -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;
|
@ -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")) {
|
||||
|
||||
|
@ -123,7 +123,7 @@ class Game extends Entity {
|
||||
|
||||
self._wantPause = false;
|
||||
|
||||
var requestFrame = (() => {
|
||||
let requestFrame = (() => {
|
||||
|
||||
return (window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
|
@ -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(
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user