Third work done
This commit is contained in:
parent
9e4f5cedfa
commit
a8269918a2
3 changed files with 498 additions and 0 deletions
318
w3/nanvas.js
Normal file
318
w3/nanvas.js
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* @author nuark (github: NuarkNoir, tg: nuark)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Double PI, yeah
|
||||
*/
|
||||
const DOUBLE_PI = Math.PI * 2;
|
||||
|
||||
/**
|
||||
* Base class for dynamic objects
|
||||
*/
|
||||
class Dynamic {
|
||||
/** @type {Number} */ x;
|
||||
/** @type {Number} */ y;
|
||||
|
||||
constructor(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates some data
|
||||
* @param {Nanvas} nanvas
|
||||
*/
|
||||
update(nanvas) {
|
||||
throw new Error("[Dynamic] Not implemented yet!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws dynamic and all
|
||||
* @param {Nanvas} nanvas
|
||||
*/
|
||||
draw(nanvas) {
|
||||
throw new Error("[Dynamic] Not implemented yet!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Particle class
|
||||
*/
|
||||
class Particle extends Dynamic {
|
||||
/** @type {Number} */ id;
|
||||
/** @type {Number} */ x;
|
||||
/** @type {Number} */ y;
|
||||
/** @type {Boolean} */ alive = false;
|
||||
/** @type {Number} */ aliveFor = 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Particle emitter class
|
||||
*/
|
||||
class ParticleEmmiter extends Dynamic {
|
||||
/** @type {Number} */ emitterSize = 20;
|
||||
/** @type {Number} */ poolSize = 10;
|
||||
/** @type {Number} */ particleLifeTime = 1.0 * 1000;
|
||||
/** @type {Number} */ spawnRate = 200.0;
|
||||
/** @type {Number} */ timeSinceLastSpawn = 0.0;
|
||||
|
||||
/** @type {Array.<Particle>} */ pool = new Array(this.poolSize);
|
||||
|
||||
/**
|
||||
* Constructs object
|
||||
* @param {Number} x position on x
|
||||
* @param {Number} y Position on y
|
||||
* @param {Number} dx Speed over x
|
||||
* @param {Number} dy Speed over y
|
||||
*/
|
||||
constructor(x, y, dx, dy) {
|
||||
super(x, y);
|
||||
this.dx = dx;
|
||||
this.dy = dy;
|
||||
this.lastFrameTime = Date.now();
|
||||
|
||||
for (let i = 0; i < this.poolSize; i++) {
|
||||
this.pool[i] = new Particle(this.x, this.y);
|
||||
this.pool[i].id = i;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates particles data
|
||||
* @param {Nanvas} nanvas
|
||||
*/
|
||||
update(nanvas) {
|
||||
const now = Date.now();
|
||||
const dt = now - this.lastFrameTime;
|
||||
this.lastFrameTime = now;
|
||||
this.timeSinceLastSpawn += dt;
|
||||
|
||||
if (this.timeSinceLastSpawn >= this.spawnRate) {
|
||||
this.timeSinceLastSpawn = 0.0;
|
||||
for (let i = 0; i < this.poolSize; i++) {
|
||||
if (!this.pool[i].alive) {
|
||||
this.pool[i].x = this.x + this.emitterSize/2;
|
||||
this.pool[i].y = this.y + this.emitterSize/2;
|
||||
this.pool[i].alive = true;
|
||||
this.pool[i].aliveFor = 0.0;
|
||||
console.log(`Spawned ${this.pool[i].id}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.poolSize; i++) {
|
||||
if (this.pool[i].alive) {
|
||||
this.pool[i].x += this.dx*dt;
|
||||
this.pool[i].y += this.dy*dt;
|
||||
this.pool[i].aliveFor += dt;
|
||||
if (this.pool[i].aliveFor >= this.particleLifeTime) {
|
||||
this.pool[i].alive = false;
|
||||
console.log(`Killed ${this.pool[i].id}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws emitter and particles
|
||||
* @param {Nanvas} nanvas
|
||||
*/
|
||||
draw(nanvas) {
|
||||
nanvas.square(this.x, this.y, this.emitterSize);
|
||||
for (let i = 0; i < this.poolSize; i++) {
|
||||
if (this.pool[i].alive) {
|
||||
nanvas.circle(this.pool[i].x, this.pool[i].y, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for working with canvas
|
||||
*/
|
||||
class Nanvas {
|
||||
/** @type {CanvasRenderingContext2D} */
|
||||
ctx = null;
|
||||
|
||||
/** @type {Number} */
|
||||
width;
|
||||
|
||||
/** @type {Number} */
|
||||
height;
|
||||
|
||||
/** @type {Array.<Array.<String, ...Number>>} */
|
||||
commands = [];
|
||||
|
||||
/** @type {Array.<Dynamic>} */
|
||||
dynamics = [];
|
||||
|
||||
/**
|
||||
* Pushes drawing style on stack
|
||||
*/
|
||||
push() {
|
||||
this.ctx.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops drawing style from stack
|
||||
*/
|
||||
pop() {
|
||||
this.ctx.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill background with colour
|
||||
* @param {String} color Fill color
|
||||
*/
|
||||
background(color) {
|
||||
this.push();
|
||||
|
||||
this.ctx.fillStyle = color;
|
||||
this.ctx.fillRect(0, 0, this.width, this.height);
|
||||
|
||||
this.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears canvas background
|
||||
*/
|
||||
clear() {
|
||||
this.background("white");
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws nifty grid
|
||||
*/
|
||||
grid() {
|
||||
this.push();
|
||||
|
||||
this.ctx.beginPath();
|
||||
for (var x = 0; x < this.width; x += 10) {
|
||||
this.ctx.moveTo(x, 0);
|
||||
this.ctx.lineTo(x, this.height);
|
||||
}
|
||||
for (var y = 0; y < this.height; y += 10) {
|
||||
this.ctx.moveTo(0, y);
|
||||
this.ctx.lineTo(this.width, y);
|
||||
}
|
||||
this.ctx.strokeStyle = "#eee";
|
||||
this.ctx.stroke();
|
||||
|
||||
this.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes commands into canvas
|
||||
* @param {Array.<Array.<String, ...Number>>} commands Commands array
|
||||
*/
|
||||
pushCommands(commands) {
|
||||
this.commands = commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears canvas commands
|
||||
*/
|
||||
clearCommands() {
|
||||
this.commands = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws static objects (commands)
|
||||
*/
|
||||
drawStatic() {
|
||||
this.commands.forEach(command => {
|
||||
let [cmd, ...args] = command;
|
||||
if (typeof (this[cmd]) !== typeof (() => { })) {
|
||||
throw new Error(`No such function: ${cmd}`);
|
||||
}
|
||||
this[cmd](...args);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws circle at postion `(x,y)` with radius `r`
|
||||
* @param {Number} x Position on x
|
||||
* @param {Number} y Position on y
|
||||
* @param {Number} r Radius
|
||||
*/
|
||||
circle(x, y, r) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.arc(x, y, r, 0, DOUBLE_PI);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws square at postion `(x,y)` with width `w`
|
||||
* @param {Number} x Position on x
|
||||
* @param {Number} y Position on y
|
||||
* @param {Number} r Width
|
||||
*/
|
||||
square(x, y, w) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.rect(x, y, w, w);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws Ellipse at postion `(x,y)` with radiais as `r1` and `r2`
|
||||
* @param {Number} x Position on x
|
||||
* @param {Number} y Position on y
|
||||
* @param {Number} r1 Radius 1
|
||||
* @param {Number} r2 Radius 2
|
||||
*/
|
||||
ellipse(x, y, r1, r2) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.ellipse(x, y, r1, r2, 0, 0, DOUBLE_PI);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws bezier curve with following parameters
|
||||
* @param {Number} h1x Position of first handle on x
|
||||
* @param {Number} h1y Position of first handle on y
|
||||
* @param {Number} h2x Position of second handle on x
|
||||
* @param {Number} h2y Position of second handle on y
|
||||
* @param {Number} x Position of end point on x
|
||||
* @param {Number} y Position of end point on y
|
||||
*/
|
||||
bezier(h1x, h1y, h2x, h2y, x, y) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.bezierCurveTo(h1x, h1y, h2x, h2y, x, y);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add dynamic object to canvas
|
||||
* @param {Dynamic} dynamic Dynamic object
|
||||
*/
|
||||
addDynamic(dynamic) {
|
||||
this.dynamics.push(dynamic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates and draws dynamics
|
||||
*/
|
||||
updateDynamics() {
|
||||
this.dynamics.forEach(dyn => dyn.update(this));
|
||||
this.dynamics.forEach(dyn => dyn.draw(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mounts Nanvas on existing canvas element and fixes some things
|
||||
* @param {HTMLElement} canvasElement
|
||||
* @returns {Nanvas}
|
||||
*/
|
||||
static mount(canvasElement, width = null, height = null) {
|
||||
const n = new Nanvas();
|
||||
n.ctx = canvasElement.getContext("2d");
|
||||
// fixing blurrynessssssssssssssss
|
||||
n.ctx.translate(0.5, 0.5);
|
||||
n.width = width === null ? canvasElement.width : width;
|
||||
n.height = height === null ? canvasElement.height : height;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue