animation basics
This commit is contained in:
parent
627ce43e4f
commit
ff593dcd92
@ -26,6 +26,9 @@ export class Drawable {
|
|||||||
throw new Error("draw() must be implemented on child class");
|
throw new Error("draw() must be implemented on child class");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do nothing by default
|
||||||
|
update() {}
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
|
|
||||||
fill(color) {
|
fill(color) {
|
||||||
|
34
artworld/timer.js
Normal file
34
artworld/timer.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
export class Timer {
|
||||||
|
constructor() {
|
||||||
|
this._pausedAt = null;
|
||||||
|
this._elapsed = 0;
|
||||||
|
this._lastStarted = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
pause() {
|
||||||
|
if (!this.isPaused) {
|
||||||
|
this._pausedAt = performance.now();
|
||||||
|
// store time since last pause
|
||||||
|
this._elapsed += this._pausedAt - this._lastStarted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unpause() {
|
||||||
|
if (this.isPaused) {
|
||||||
|
this.lastStarted = performance.now();
|
||||||
|
this._pausedAt = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get isPaused() {
|
||||||
|
return this._pausedAt !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
time() {
|
||||||
|
if (this.isPaused) {
|
||||||
|
return this._elapsed;
|
||||||
|
} else {
|
||||||
|
return this._elapsed + (performance.now() - this._lastStarted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,14 @@
|
|||||||
|
import { Timer } from "./timer.js";
|
||||||
|
|
||||||
export class World {
|
export class World {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.drawables = [];
|
|
||||||
this.ctx = null;
|
this.ctx = null;
|
||||||
|
this.drawables = [];
|
||||||
|
this.backgroundColor = "white";
|
||||||
|
this.timer = new Timer();
|
||||||
|
this.targetFrameRate = 60;
|
||||||
|
this.stepSize = 1000 / this.targetFrameRate;
|
||||||
|
this.lastTick = this.timer.time();
|
||||||
}
|
}
|
||||||
|
|
||||||
bindCanvas(id) {
|
bindCanvas(id) {
|
||||||
@ -16,16 +23,39 @@ export class World {
|
|||||||
return this.ctx.canvas.height;
|
return this.ctx.canvas.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO rename
|
||||||
register(drawable) {
|
register(drawable) {
|
||||||
this.drawables.push(drawable);
|
this.drawables.push(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
|
this.ctx.fillStyle = "white";
|
||||||
|
this.ctx.beginPath();
|
||||||
|
this.ctx.fillRect(0, 0, this.width, this.height);
|
||||||
|
this.ctx.fill();
|
||||||
for (let d of this.drawables.sort((a, b) => a._z_index - b._z_index)) {
|
for (let d of this.drawables.sort((a, b) => a._z_index - b._z_index)) {
|
||||||
d.draw();
|
d.draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tick() {
|
||||||
|
for (let d of this.drawables) {
|
||||||
|
d.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loopStep() {
|
||||||
|
window.requestAnimationFrame(() => this.loopStep());
|
||||||
|
|
||||||
|
let curTime = this.timer.time();
|
||||||
|
// tick appropriate number of times
|
||||||
|
while (curTime - this.lastTick > this.stepSize) {
|
||||||
|
this.lastTick += this.stepSize;
|
||||||
|
this.tick();
|
||||||
|
}
|
||||||
|
this.draw();
|
||||||
|
}
|
||||||
|
|
||||||
// Canvas 2D /////////////////
|
// Canvas 2D /////////////////
|
||||||
|
|
||||||
prepareDraw(drawable) {
|
prepareDraw(drawable) {
|
||||||
|
63
examples/balls.html
Normal file
63
examples/balls.html
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<html>
|
||||||
|
<head> </head>
|
||||||
|
<body>
|
||||||
|
<canvas id="mainCanvas" width="500" height="500"></canvas>
|
||||||
|
<script type="module">
|
||||||
|
import {
|
||||||
|
artworld,
|
||||||
|
Color,
|
||||||
|
Pico8,
|
||||||
|
Group,
|
||||||
|
Circle,
|
||||||
|
Random,
|
||||||
|
Vector2,
|
||||||
|
degToRad,
|
||||||
|
} from "../artworld/index.js";
|
||||||
|
artworld.bindCanvas("mainCanvas");
|
||||||
|
window.artworld = artworld;
|
||||||
|
|
||||||
|
class Ball extends Circle {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.speed = new Vector2(0, Random.between(9, 15));
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.move(this.speed);
|
||||||
|
if (this.worldPos.y > artworld.height + 20) {
|
||||||
|
this.y(-20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GravityBall extends Circle {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.accel = new Vector2(0, 0.5);
|
||||||
|
this.speed = Vector2.random(0, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.speed = this.speed.add(this.accel);
|
||||||
|
this.move(this.speed);
|
||||||
|
if (this.worldPos.y > artworld.height - 10) {
|
||||||
|
this.speed = this.speed.scale(-0.98); // bounce w/ dampening
|
||||||
|
this.y(artworld.height - 10.01);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < 21; i++) {
|
||||||
|
new Ball()
|
||||||
|
.pos(new Vector2(40 * i, 0))
|
||||||
|
.radius(10)
|
||||||
|
.fill(Pico8.BLUE);
|
||||||
|
new GravityBall()
|
||||||
|
.pos(new Vector2(20 + 40 * i, 0))
|
||||||
|
.radius(10)
|
||||||
|
.fill(Pico8.PURPLE);
|
||||||
|
}
|
||||||
|
artworld.loopStep();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user