Compare commits
No commits in common. "54e75eed31abcf1eee7327ff63cc786b1111f940" and "6b8b20d2868935e23591cc9dfcb4932549ce6c53" have entirely different histories.
54e75eed31
...
6b8b20d286
10
TODO.md
10
TODO.md
@ -1,10 +0,0 @@
|
|||||||
# TODO
|
|
||||||
|
|
||||||
- ellipse
|
|
||||||
- smooth/nosmooth
|
|
||||||
- curves
|
|
||||||
|
|
||||||
- lerp
|
|
||||||
|
|
||||||
- clipping
|
|
||||||
- text
|
|
@ -1,25 +1,27 @@
|
|||||||
|
import { artworld } from "./world.js";
|
||||||
import { Vector2 } from "./math.js";
|
import { Vector2 } from "./math.js";
|
||||||
import { Color } from "./color.js";
|
import { Color } from "./color.js";
|
||||||
import { Random } from "./random.js";
|
import { Random } from "./random.js";
|
||||||
import { World } from "./world.js";
|
|
||||||
import { getVal } from "./variables.js";
|
function cloneObject(obj) {
|
||||||
|
for (let [k, v] of Object.entries(obj)) {
|
||||||
|
console.log(k, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Drawable {
|
export class Drawable {
|
||||||
constructor(parent) {
|
constructor(parent) {
|
||||||
this._parent = null;
|
this._parent = parent;
|
||||||
this._world = null;
|
this._updates = [];
|
||||||
// if parent is provided, then delegate to parent class
|
|
||||||
if (parent instanceof World) {
|
|
||||||
parent.registerDrawable(this);
|
|
||||||
} else if (parent) {
|
|
||||||
parent.addChild(this);
|
|
||||||
}
|
|
||||||
this._fill = parent ? parent._fill : null;
|
this._fill = parent ? parent._fill : null;
|
||||||
this._stroke = parent ? parent._stroke : null;
|
this._stroke = parent ? parent._stroke : null;
|
||||||
this._strokeWeight = parent ? parent._strokeWeight : null;
|
this._strokeWeight = parent ? parent._strokeWeight : null;
|
||||||
this._zIndex = parent ? parent._zIndex : null;
|
this._z_index = parent ? parent._z_index : null;
|
||||||
this._posVec = new Vector2(0, 0);
|
this._posVec = new Vector2(0, 0);
|
||||||
this._animations = [];
|
if (this._parent) {
|
||||||
|
this._parent.addChild(this);
|
||||||
|
}
|
||||||
|
artworld.register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
copy() {
|
copy() {
|
||||||
@ -30,22 +32,7 @@ export class Drawable {
|
|||||||
throw new Error("draw() must be implemented on child class");
|
throw new Error("draw() must be implemented on child class");
|
||||||
}
|
}
|
||||||
|
|
||||||
animate(setter, func, args) {
|
|
||||||
this._animations.push({ setter, func, args });
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
update(t) {
|
|
||||||
for (let anim of this._animations) {
|
|
||||||
this[anim.setter](anim.func(t), anim.args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
world(world) {
|
|
||||||
this._world = world;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
fill(color) {
|
fill(color) {
|
||||||
this._fill = color;
|
this._fill = color;
|
||||||
@ -78,7 +65,7 @@ export class Drawable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
z(scalar) {
|
z(scalar) {
|
||||||
this._zIndex = scalar;
|
this._z_index = scalar;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +77,10 @@ export class Drawable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
random() {
|
random() {
|
||||||
this._posVec = new Vector2(Random.under(100), Random.under(100));
|
this._posVec = new Vector2(
|
||||||
|
Random.under(artworld.width),
|
||||||
|
Random.under(artworld.height),
|
||||||
|
);
|
||||||
this._stroke = new Color(
|
this._stroke = new Color(
|
||||||
Random.under(360),
|
Random.under(360),
|
||||||
Random.between(30, 60),
|
Random.between(30, 60),
|
||||||
@ -109,14 +99,14 @@ export class Drawable {
|
|||||||
get worldPos() {
|
get worldPos() {
|
||||||
// offset from parent if needed
|
// offset from parent if needed
|
||||||
return this._parent
|
return this._parent
|
||||||
? this._parent.worldPos.add(getVal(this._posVec))
|
? this._parent.worldPos.add(this._posVec)
|
||||||
: getVal(this._posVec);
|
: this._posVec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Group extends Drawable {
|
export class Group extends Drawable {
|
||||||
constructor(parent) {
|
constructor() {
|
||||||
super(parent);
|
super();
|
||||||
this._children = [];
|
this._children = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,9 +127,6 @@ export class Group extends Drawable {
|
|||||||
newGroup._parent = this._parent;
|
newGroup._parent = this._parent;
|
||||||
newGroup._parent.addChild(newGroup);
|
newGroup._parent.addChild(newGroup);
|
||||||
}
|
}
|
||||||
if (this._world) {
|
|
||||||
this._world.registerDrawable(newGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
return newGroup;
|
return newGroup;
|
||||||
}
|
}
|
||||||
@ -148,11 +135,7 @@ export class Group extends Drawable {
|
|||||||
|
|
||||||
addChild(drawable) {
|
addChild(drawable) {
|
||||||
this._children.push(drawable);
|
this._children.push(drawable);
|
||||||
// probably alraedy true, but make sure
|
|
||||||
drawable._parent = this;
|
drawable._parent = this;
|
||||||
if (this._world) {
|
|
||||||
this._world.registerDrawable(drawable);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
export { artworld } from "./world.js";
|
||||||
export { Color, Pico8 } from "./color.js";
|
export { Color, Pico8 } from "./color.js";
|
||||||
export { Vector2, degToRad, radToDeg } from "./math.js";
|
export { Vector2, degToRad, radToDeg } from "./math.js";
|
||||||
export { Line, Rect, Circle, Arc, Polygon } from "./shapes.js";
|
export { Line, Rect, Circle, Arc } from "./shapes.js";
|
||||||
export { Group } from "./drawable.js";
|
export { Group } from "./drawable.js";
|
||||||
export { Random } from "./random.js";
|
export { Random } from "./random.js";
|
||||||
export { Var } from "./variables.js";
|
|
||||||
export { World } from "./world.js";
|
|
||||||
|
@ -27,16 +27,6 @@ export class Vector2 {
|
|||||||
return new Vector2(s * this.x, s * this.y);
|
return new Vector2(s * this.x, s * this.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
distance(other) {
|
|
||||||
return Math.sqrt(
|
|
||||||
Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
get magnitude() {
|
|
||||||
return Math.sqrt(this.x * this.x + this.y * this.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static random(x, y) {
|
static random(x, y) {
|
||||||
let theta = Random.radians();
|
let theta = Random.radians();
|
||||||
// if neither specified, use (1, 1)
|
// if neither specified, use (1, 1)
|
||||||
|
@ -16,8 +16,4 @@ export class Random {
|
|||||||
static radians() {
|
static radians() {
|
||||||
return Math.random() * Math.PI * 2;
|
return Math.random() * Math.PI * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static choice(array) {
|
|
||||||
return array[Math.floor(Random.under(array.length))];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Vector2 } from "./math.js";
|
import { Vector2 } from "./math.js";
|
||||||
import { Drawable } from "./drawable.js";
|
import { Drawable } from "./drawable.js";
|
||||||
import { Random } from "./random.js";
|
import { Random } from "./random.js";
|
||||||
import { getVal } from "./variables.js";
|
|
||||||
|
|
||||||
function makeCopy(Cls, obj, override) {
|
function makeCopy(Cls, obj, override) {
|
||||||
// make new object, will be registered with world, but no _parent yet
|
// make new object, will be registered with world, but no _parent yet
|
||||||
@ -12,10 +11,6 @@ function makeCopy(Cls, obj, override) {
|
|||||||
if (newObj._parent) {
|
if (newObj._parent) {
|
||||||
newObj._parent.addChild(newObj);
|
newObj._parent.addChild(newObj);
|
||||||
}
|
}
|
||||||
// attach to world
|
|
||||||
if (newObj._world) {
|
|
||||||
newObj._world.registerDrawable(newObj);
|
|
||||||
}
|
|
||||||
return newObj;
|
return newObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,18 +24,10 @@ export class Line extends Drawable {
|
|||||||
return makeCopy(Line, this, overrides);
|
return makeCopy(Line, this, overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
random(range = 100) {
|
|
||||||
super.random();
|
|
||||||
this._offsetVec = Vector2.random(range, range);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
this._world.prepareDraw(this);
|
artworld.setStrokeColor(this._stroke);
|
||||||
this._world.drawLine(
|
artworld.setStrokeWeight(this._strokeWeight);
|
||||||
this.worldPos,
|
artworld.drawLine(this.worldPos, this.worldPos.add(this._offsetVec));
|
||||||
this.worldPos.add(getVal(this._offsetVec)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
to(vec) {
|
to(vec) {
|
||||||
@ -61,26 +48,13 @@ export class Arc extends Drawable {
|
|||||||
this._startAngle = 0;
|
this._startAngle = 0;
|
||||||
this._endAngle = 180;
|
this._endAngle = 180;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(overrides) {
|
copy(overrides) {
|
||||||
return makeCopy(Arc, this, overrides);
|
return makeCopy(Arc, this, overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
random(range = 100) {
|
|
||||||
super.random();
|
|
||||||
this._r = Random.between(20, range);
|
|
||||||
this._startAngle = Random.radians();
|
|
||||||
this._endAngle = Random.radians();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
draw() {
|
draw() {
|
||||||
this._world.prepareDraw(this);
|
artworld.prepareDraw(this);
|
||||||
this._world.drawArc(
|
artworld.drawArc(this.worldPos, this._r, this._startAngle, this._endAngle);
|
||||||
this.worldPos,
|
|
||||||
this._r,
|
|
||||||
this._startAngle,
|
|
||||||
this._endAngle,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
radius(scalar) {
|
radius(scalar) {
|
||||||
@ -106,15 +80,9 @@ export class Circle extends Drawable {
|
|||||||
return makeCopy(Circle, this, overrides);
|
return makeCopy(Circle, this, overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
random(range = 100) {
|
|
||||||
super.random();
|
|
||||||
this._r = Random.between(20, range);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
this._world.prepareDraw(this);
|
artworld.prepareDraw(this);
|
||||||
this._world.drawArc(this.worldPos, this._r, 0, 2 * Math.PI);
|
artworld.drawArc(this.worldPos, this._r, 0, 2 * Math.PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
radius(scalar) {
|
radius(scalar) {
|
||||||
@ -130,7 +98,7 @@ export class Rect extends Drawable {
|
|||||||
this._height = 50;
|
this._height = 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
random(range = 100) {
|
random(range) {
|
||||||
super.random();
|
super.random();
|
||||||
this._width = Random.between(20, range);
|
this._width = Random.between(20, range);
|
||||||
this._height = Random.between(20, range);
|
this._height = Random.between(20, range);
|
||||||
@ -141,8 +109,8 @@ export class Rect extends Drawable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
this._world.prepareDraw(this);
|
artworld.prepareDraw(this);
|
||||||
this._world.drawRect(this.worldPos, this._width, this._height);
|
artworld.drawRect(this.worldPos, this._width, this._height);
|
||||||
}
|
}
|
||||||
|
|
||||||
size(w, h) {
|
size(w, h) {
|
||||||
@ -171,67 +139,3 @@ export class Rect extends Drawable {
|
|||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Polygon extends Drawable {
|
|
||||||
constructor(parent) {
|
|
||||||
super(parent);
|
|
||||||
this._points = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
random(n = 7) {
|
|
||||||
super.random();
|
|
||||||
let points = [];
|
|
||||||
let i;
|
|
||||||
// generate points
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
points.push(
|
|
||||||
new Vector2(Random.between(50, 200), Random.between(50, 200)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// sort points by distance for mostly convex (but not always) polygons
|
|
||||||
this._points.push(points.shift()); // take first element
|
|
||||||
while (points.length) {
|
|
||||||
let closestIdx = 0;
|
|
||||||
let closestDist = 999999999;
|
|
||||||
let dist;
|
|
||||||
for (let j = 0; j < points.length; j++) {
|
|
||||||
dist = this._points[this._points.length - 1].distance(points[j]);
|
|
||||||
if (dist < closestDist) {
|
|
||||||
closestDist = dist;
|
|
||||||
closestIdx = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._points.push(points[closestIdx]);
|
|
||||||
points.splice(closestIdx, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
copy(overrides) {
|
|
||||||
return makeCopy(Polygon, this, overrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
draw() {
|
|
||||||
this._world.prepareDraw(this);
|
|
||||||
this._world.drawPolygon(this.worldPos, this._points);
|
|
||||||
}
|
|
||||||
|
|
||||||
point(vector, to_modify = null) {
|
|
||||||
if (to_modify !== null) {
|
|
||||||
this._points[to_modify] = vector;
|
|
||||||
} else {
|
|
||||||
this._points.push(point);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
// TODO
|
|
||||||
// contains(x, y) {
|
|
||||||
// return (
|
|
||||||
// x > this.x &&
|
|
||||||
// x < this.x + this._width &&
|
|
||||||
// y > this.y &&
|
|
||||||
// y < this.pos.y + this._height
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
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,29 +0,0 @@
|
|||||||
export function getVal(x) {
|
|
||||||
return x && x.getValue ? x.getValue() : x;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Var {
|
|
||||||
constructor(value) {
|
|
||||||
if (typeof value === "function") {
|
|
||||||
this._updateFunc = value;
|
|
||||||
this._value = this._updateFunc(0);
|
|
||||||
} else {
|
|
||||||
this._value = value;
|
|
||||||
this._updateFunc = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateFunc(func) {
|
|
||||||
this._updateFunc = func;
|
|
||||||
}
|
|
||||||
|
|
||||||
update(t) {
|
|
||||||
if (this._updateFunc) {
|
|
||||||
this._value = this._updateFunc(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getValue() {
|
|
||||||
return this._value;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +1,11 @@
|
|||||||
import { Timer } from "./timer.js";
|
|
||||||
import { getVal, Var } from "./variables.js";
|
|
||||||
|
|
||||||
export class World {
|
export class World {
|
||||||
constructor(canvasId) {
|
constructor() {
|
||||||
this.ctx = null;
|
|
||||||
this.drawables = [];
|
this.drawables = [];
|
||||||
this.variables = [];
|
this.ctx = null;
|
||||||
this.backgroundColor = "white";
|
}
|
||||||
this.timer = new Timer();
|
|
||||||
this.targetFrameRate = 60;
|
bindCanvas(id) {
|
||||||
this.stepSize = 1000 / this.targetFrameRate;
|
this.ctx = document.getElementById(id).getContext("2d");
|
||||||
this.lastTick = this.timer.time();
|
|
||||||
this.numTicks = 0;
|
|
||||||
this.ctx = document.getElementById(canvasId).getContext("2d");
|
|
||||||
this.ctx.canvas.width = 1000;
|
|
||||||
this.ctx.canvas.height = 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get width() {
|
get width() {
|
||||||
@ -25,55 +16,14 @@ export class World {
|
|||||||
return this.ctx.canvas.height;
|
return this.ctx.canvas.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
var(value) {
|
register(drawable) {
|
||||||
let v = new Var(value);
|
this.drawables.push(drawable);
|
||||||
this.variables.push(v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
registerDrawable(thing) {
|
|
||||||
this.drawables.push(thing);
|
|
||||||
thing._world = this;
|
|
||||||
return thing;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
this.ctx.fillStyle = this.backgroundColor;
|
for (let d of this.drawables.sort((a, b) => a._z_index - b._z_index)) {
|
||||||
this.ctx.beginPath();
|
|
||||||
this.ctx.fillRect(0, 0, this.width, this.height);
|
|
||||||
this.ctx.fill();
|
|
||||||
this.ctx.save();
|
|
||||||
this.ctx.translate(500, 500);
|
|
||||||
for (let d of this.drawables.sort((a, b) => a._zIndex - b._zIndex)) {
|
|
||||||
d.draw();
|
d.draw();
|
||||||
}
|
}
|
||||||
this.ctx.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
tick() {
|
|
||||||
this.numTicks++;
|
|
||||||
for (let d of this.drawables) {
|
|
||||||
d.update(this.numTicks);
|
|
||||||
}
|
|
||||||
for (let v of this.variables) {
|
|
||||||
v.update(this.numTicks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get updatesPerSecond() {
|
|
||||||
return (this.numTicks / this.timer.time()) * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 /////////////////
|
||||||
@ -81,21 +31,21 @@ export class World {
|
|||||||
prepareDraw(drawable) {
|
prepareDraw(drawable) {
|
||||||
this._stroke = false;
|
this._stroke = false;
|
||||||
this._fill = false;
|
this._fill = false;
|
||||||
let stroke = getVal(drawable._stroke);
|
if (drawable._stroke) {
|
||||||
let fill = getVal(drawable._fill);
|
this.ctx.lineWidth = drawable._strokeWeight;
|
||||||
if (stroke) {
|
this.ctx.strokeStyle = drawable._stroke.toStr
|
||||||
this.ctx.lineWidth = getVal(drawable._strokeWeight);
|
? drawable._stroke.toStr()
|
||||||
this.ctx.strokeStyle = stroke.toStr ? stroke.toStr() : stroke;
|
: drawable._stroke;
|
||||||
this._stroke = true;
|
this._stroke = true;
|
||||||
} else if (fill) {
|
} else if (drawable._fill) {
|
||||||
this.ctx.fillStyle = fill.toStr ? fill.toStr() : fill;
|
this.ctx.fillStyle = drawable._fill.toStr
|
||||||
|
? drawable._fill.toStr()
|
||||||
|
: drawable._fill;
|
||||||
this._fill = true;
|
this._fill = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawLine(from, to) {
|
drawLine(from, to) {
|
||||||
from = getVal(from);
|
|
||||||
to = getVal(to);
|
|
||||||
this.ctx.beginPath();
|
this.ctx.beginPath();
|
||||||
this.ctx.moveTo(from.x, from.y);
|
this.ctx.moveTo(from.x, from.y);
|
||||||
this.ctx.lineTo(to.x, to.y);
|
this.ctx.lineTo(to.x, to.y);
|
||||||
@ -103,38 +53,19 @@ export class World {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawArc(center, radius, fromAngle, toAngle) {
|
drawArc(center, radius, fromAngle, toAngle) {
|
||||||
center = getVal(center);
|
|
||||||
this.ctx.beginPath();
|
this.ctx.beginPath();
|
||||||
this.ctx.arc(
|
this.ctx.arc(center.x, center.y, radius, fromAngle, toAngle);
|
||||||
center.x,
|
|
||||||
center.y,
|
|
||||||
getVal(radius),
|
|
||||||
getVal(fromAngle),
|
|
||||||
getVal(toAngle),
|
|
||||||
);
|
|
||||||
if (this._stroke) this.ctx.stroke();
|
if (this._stroke) this.ctx.stroke();
|
||||||
if (this._fill) this.ctx.fill();
|
if (this._fill) this.ctx.fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
drawRect(center, width, height) {
|
drawRect(center, width, height) {
|
||||||
center = getVal(center);
|
|
||||||
width = getVal(width);
|
|
||||||
height = getVal(height);
|
|
||||||
this.ctx.beginPath();
|
this.ctx.beginPath();
|
||||||
this.ctx.rect(center.x - width / 2, center.y - height / 2, width, height);
|
this.ctx.rect(center.x - width / 2, center.y - height / 2, width, height);
|
||||||
if (this._stroke) this.ctx.stroke();
|
if (this._stroke) this.ctx.stroke();
|
||||||
if (this._fill) this.ctx.fill();
|
if (this._fill) this.ctx.fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
drawPolygon(center, points) {
|
|
||||||
center = getVal(center);
|
|
||||||
this.ctx.beginPath();
|
|
||||||
this.ctx.moveTo(center.x + points[0].x, center.y + points[0].y);
|
|
||||||
for (let i = 1; i < points.length; i++) {
|
|
||||||
this.ctx.lineTo(center.x + points[i].x, center.y + points[i].y);
|
|
||||||
}
|
|
||||||
this.ctx.lineTo(center.x + points[0].x, center.y + points[0].y);
|
|
||||||
if (this._stroke) this.ctx.stroke();
|
|
||||||
if (this._fill) this.ctx.fill();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// singleton (for now)
|
||||||
|
export const artworld = new World();
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
import {
|
|
||||||
World,
|
|
||||||
Color,
|
|
||||||
Pico8,
|
|
||||||
Group,
|
|
||||||
Circle,
|
|
||||||
Random,
|
|
||||||
Vector2,
|
|
||||||
degToRad,
|
|
||||||
} from "../artworld/index.js";
|
|
||||||
let world = new World("mainCanvas");
|
|
||||||
window.world = world;
|
|
||||||
|
|
||||||
class Ball extends Circle {
|
|
||||||
constructor() {
|
|
||||||
super(world);
|
|
||||||
this.speed = new Vector2(0, Random.between(9, 15));
|
|
||||||
}
|
|
||||||
|
|
||||||
update() {
|
|
||||||
this.move(this.speed);
|
|
||||||
if (this.worldPos.y > world.height + 20) {
|
|
||||||
this.y(-20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class GravityBall extends Circle {
|
|
||||||
constructor() {
|
|
||||||
super(world);
|
|
||||||
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 > world.height - 10) {
|
|
||||||
this.speed = this.speed.scale(-0.98); // bounce w/ dampening
|
|
||||||
this.y(world.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);
|
|
||||||
}
|
|
||||||
world.loopStep();
|
|
38
examples/circles.html
Normal file
38
examples/circles.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<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;
|
||||||
|
|
||||||
|
function* color_cycle() {
|
||||||
|
while (true) {
|
||||||
|
yield Pico8.RED;
|
||||||
|
yield Pico8.ORANGE;
|
||||||
|
yield Pico8.YELLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let cycle = color_cycle();
|
||||||
|
|
||||||
|
let g = new Group().pos(new Vector2(250, 250));
|
||||||
|
for (let r = 20; r < 100; r += 12) {
|
||||||
|
new Circle(g).radius(r).fill(cycle.next().value).z(-r).strokeWeight(0);
|
||||||
|
}
|
||||||
|
for (let r = 100; r < 250; r += 12) {
|
||||||
|
new Circle(g).radius(r).fill(cycle.next().value).z(-r).strokeWeight(0);
|
||||||
|
}
|
||||||
|
artworld.draw();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,18 +0,0 @@
|
|||||||
import { World, Pico8, Group, Circle, Vector2 } from "../artworld/index.js";
|
|
||||||
let world = new World("mainCanvas");
|
|
||||||
window.world = world;
|
|
||||||
|
|
||||||
function* color_cycle() {
|
|
||||||
while (true) {
|
|
||||||
yield Pico8.RED;
|
|
||||||
yield Pico8.ORANGE;
|
|
||||||
yield Pico8.YELLOW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let cycle = color_cycle();
|
|
||||||
|
|
||||||
let g = new Group(world);
|
|
||||||
for (let r = 20; r < 500; r += 20) {
|
|
||||||
new Circle(g).radius(r).fill(cycle.next().value).z(-r).strokeWeight(0);
|
|
||||||
}
|
|
||||||
world.draw();
|
|
@ -1,51 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head> </head>
|
|
||||||
<body>
|
|
||||||
<canvas id="mainCanvas" width="500" height="500"></canvas>
|
|
||||||
<script type="module">
|
|
||||||
import {
|
|
||||||
artworld,
|
|
||||||
Color,
|
|
||||||
Pico8,
|
|
||||||
Group,
|
|
||||||
Rect,
|
|
||||||
Random,
|
|
||||||
Vector2,
|
|
||||||
Line,
|
|
||||||
Circle,
|
|
||||||
degToRad,
|
|
||||||
} from "../artworld/index.js";
|
|
||||||
artworld.bindCanvas("mainCanvas");
|
|
||||||
window.artworld = artworld;
|
|
||||||
|
|
||||||
function colorFunc(t) {
|
|
||||||
return [Pico8.RED, Pico8.ORANGE, Pico8.GREEN, Pico8.BLUE][
|
|
||||||
Math.floor(t / 60) % 4
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
function sizeFuncFactory(minSize, factor) {
|
|
||||||
return (t) => Math.sin(t / 100) * factor + minSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
function timeAngle(t) {
|
|
||||||
return (t / 6000) * Math.PI * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
let g = new Group().pos(new Vector2(250, 250));
|
|
||||||
new Circle(g)
|
|
||||||
.fill(Pico8.BLACK)
|
|
||||||
.z(1)
|
|
||||||
.animate("radius", sizeFuncFactory(200, 50));
|
|
||||||
new Circle(g)
|
|
||||||
.z(10)
|
|
||||||
.animate("fill", colorFunc)
|
|
||||||
.animate("radius", sizeFuncFactory(190, 50));
|
|
||||||
new Circle(g).radius(20).fill(Pico8.BLACK).z(50);
|
|
||||||
|
|
||||||
new Line(g).to(Vector2.polar(200, 0)).z(100).animate("angle", timeAngle);
|
|
||||||
|
|
||||||
artworld.loopStep();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
28
examples/copies.html
Normal file
28
examples/copies.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<html>
|
||||||
|
<head> </head>
|
||||||
|
<body>
|
||||||
|
<canvas id="mainCanvas" width="500" height="500"></canvas>
|
||||||
|
<script type="module">
|
||||||
|
import {
|
||||||
|
artworld,
|
||||||
|
Color,
|
||||||
|
Pico8,
|
||||||
|
Group,
|
||||||
|
Circle,
|
||||||
|
Random,
|
||||||
|
Vector2,
|
||||||
|
} from "../artworld/index.js";
|
||||||
|
artworld.bindCanvas("mainCanvas");
|
||||||
|
window.artworld = artworld;
|
||||||
|
|
||||||
|
let g = new Group().pos(new Vector2(0, 0));
|
||||||
|
let c = new Circle(g).radius(80).stroke(Pico8.RED).strokeWeight(5);
|
||||||
|
for (let i = 0; i < 15; i++) {
|
||||||
|
c = c.copy().move(new Vector2(45, 45));
|
||||||
|
}
|
||||||
|
g.copy().move(new Vector2(200, 0)).stroke(Pico8.GREEN);
|
||||||
|
g.copy().move(new Vector2(-200, 0)).stroke(Pico8.BLUE);
|
||||||
|
artworld.draw();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,20 +0,0 @@
|
|||||||
import {
|
|
||||||
World,
|
|
||||||
Color,
|
|
||||||
Pico8,
|
|
||||||
Group,
|
|
||||||
Circle,
|
|
||||||
Random,
|
|
||||||
Vector2,
|
|
||||||
} from "../artworld/index.js";
|
|
||||||
let world = new World("mainCanvas");
|
|
||||||
window.world = world;
|
|
||||||
|
|
||||||
let g = new Group(world).pos(new Vector2(0, 0));
|
|
||||||
let c = new Circle(g).radius(80).stroke(Pico8.RED).strokeWeight(5);
|
|
||||||
for (let i = 0; i < 15; i++) {
|
|
||||||
c = c.copy().move(new Vector2(45, 45));
|
|
||||||
}
|
|
||||||
g.copy().move(new Vector2(200, 0)).stroke(Pico8.GREEN);
|
|
||||||
g.copy().move(new Vector2(-200, 0)).stroke(Pico8.BLUE);
|
|
||||||
world.draw();
|
|
@ -1,41 +0,0 @@
|
|||||||
import {
|
|
||||||
World,
|
|
||||||
Pico8,
|
|
||||||
Group,
|
|
||||||
Vector2,
|
|
||||||
Line,
|
|
||||||
Circle,
|
|
||||||
} from "../artworld/index.js";
|
|
||||||
|
|
||||||
let world = new World("mainCanvas");
|
|
||||||
window.world = world;
|
|
||||||
// This is an experiment to separate the declaration of
|
|
||||||
// "what the data does" from "what it looks like".
|
|
||||||
|
|
||||||
// First we use `Var` to define "what the data does"
|
|
||||||
// variables are expected to regularly *vary*!
|
|
||||||
|
|
||||||
// Variables are defined as functions that update with time.
|
|
||||||
// It is also possible to define static variables.
|
|
||||||
let color = world.var(
|
|
||||||
(t) =>
|
|
||||||
[Pico8.RED, Pico8.ORANGE, Pico8.GREEN, Pico8.BLUE][Math.floor(t / 60) % 4],
|
|
||||||
);
|
|
||||||
// We can create dependencies between them: here the inner & outer
|
|
||||||
// radii should be 10 pixels apart.
|
|
||||||
let outerR = world.var((t) => Math.sin(t / 100) * 50 + 200);
|
|
||||||
let innerR = world.var(() => outerR.getValue() - 10);
|
|
||||||
// We take this composition a bit further here, the radius of the clock
|
|
||||||
// hand grows & shrinks with the edge.
|
|
||||||
let lineTo = world.var((t) => {
|
|
||||||
let angle = (t / 6000) * Math.PI * 2;
|
|
||||||
return Vector2.polar(innerR.getValue(), angle);
|
|
||||||
});
|
|
||||||
|
|
||||||
let g = new Group(world);
|
|
||||||
new Circle(g).fill(Pico8.BLACK).z(1).radius(outerR);
|
|
||||||
new Circle(g).z(10).fill(color).radius(innerR);
|
|
||||||
new Circle(g).radius(20).fill(Pico8.BLACK).z(50);
|
|
||||||
new Line(g).to(lineTo).z(100);
|
|
||||||
|
|
||||||
world.loopStep();
|
|
@ -1,113 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>JS Module Loader</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
display: flex;
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
height: 100vh;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
#sidebar {
|
|
||||||
width: 200px;
|
|
||||||
background: #f4f4f4;
|
|
||||||
padding: 10px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
#file-list button {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
margin: 5px 0;
|
|
||||||
padding: 10px;
|
|
||||||
text-align: left;
|
|
||||||
border: none;
|
|
||||||
background: #ddd;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
#file-list button:hover {
|
|
||||||
background: #bbb;
|
|
||||||
}
|
|
||||||
#main {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
#mainCanvas {
|
|
||||||
width: 500px;
|
|
||||||
height: 500px;
|
|
||||||
background: #eee;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
#output {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
background: #222;
|
|
||||||
color: #ffb300;
|
|
||||||
padding: 10px;
|
|
||||||
overflow: auto;
|
|
||||||
font-family: monospace;
|
|
||||||
flex: 1;
|
|
||||||
max-height: 50%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="sidebar">
|
|
||||||
<h3>Files</h3>
|
|
||||||
<div id="file-list"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="main">
|
|
||||||
<canvas id="mainCanvas"></canvas>
|
|
||||||
<div id="output">Script output will appear here...</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const jsFiles = [
|
|
||||||
"balls.js",
|
|
||||||
"circles.js",
|
|
||||||
"copies.js",
|
|
||||||
"dataclock.js",
|
|
||||||
"lines.js",
|
|
||||||
"liskov.js",
|
|
||||||
"polygons.js",
|
|
||||||
"rect.js",
|
|
||||||
"spiral.js",
|
|
||||||
];
|
|
||||||
|
|
||||||
async function loadAndRunModule(fileName) {
|
|
||||||
const canvas = document.getElementById("mainCanvas");
|
|
||||||
const outputDiv = document.getElementById("output");
|
|
||||||
|
|
||||||
// Clear the canvas
|
|
||||||
const ctx = canvas.getContext("2d");
|
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
||||||
|
|
||||||
outputDiv.textContent = `Loading ${fileName}...\n`;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// import the module dynamically with cache busting
|
|
||||||
const module = await import(`./${fileName}?t=${Date.now()}`);
|
|
||||||
// TODO: get source code
|
|
||||||
} catch (err) {
|
|
||||||
outputDiv.textContent += `Error loading ${fileName}:\n${err}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderFileList() {
|
|
||||||
const fileListDiv = document.getElementById("file-list");
|
|
||||||
jsFiles.forEach((file) => {
|
|
||||||
const btn = document.createElement("button");
|
|
||||||
btn.textContent = file;
|
|
||||||
btn.onclick = () => loadAndRunModule(file);
|
|
||||||
fileListDiv.appendChild(btn);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
renderFileList();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
19
examples/lines.html
Normal file
19
examples/lines.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<html>
|
||||||
|
<head> </head>
|
||||||
|
<body>
|
||||||
|
<canvas id="mainCanvas" width="800" height="800"></canvas>
|
||||||
|
<script type="module">
|
||||||
|
import { artworld, Color, Line, Vector2 } from "../artworld/index.js";
|
||||||
|
artworld.bindCanvas("mainCanvas");
|
||||||
|
window.artworld = artworld;
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
new Line()
|
||||||
|
.pos(new Vector2(5 * i * 14, 5))
|
||||||
|
.to(new Vector2(5 * i * 14, 140))
|
||||||
|
.stroke(new Color(20 * i, 50, 50))
|
||||||
|
.strokeWeight(1 + i);
|
||||||
|
}
|
||||||
|
artworld.draw();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,11 +0,0 @@
|
|||||||
import { World, Color, Line, Vector2 } from "../artworld/index.js";
|
|
||||||
let world = new World("mainCanvas");
|
|
||||||
window.world = world;
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
new Line(world)
|
|
||||||
.pos(new Vector2(5 * i * 14, 5))
|
|
||||||
.to(new Vector2(5 * i * 14, 140))
|
|
||||||
.stroke(new Color(20 * i, 50, 50))
|
|
||||||
.strokeWeight(1 + i);
|
|
||||||
}
|
|
||||||
world.draw();
|
|
@ -1,10 +0,0 @@
|
|||||||
import { World, Rect, Arc, Line, Circle, Random } from "../artworld/index.js";
|
|
||||||
let world = new World("mainCanvas");
|
|
||||||
|
|
||||||
let types = [Rect, Line, Circle, Arc];
|
|
||||||
|
|
||||||
for (let i = 0; i < 100; i++) {
|
|
||||||
let Cls = Random.choice(types);
|
|
||||||
new Cls(world).random().strokeWeight(2);
|
|
||||||
}
|
|
||||||
world.draw();
|
|
@ -1,9 +0,0 @@
|
|||||||
import { World, Polygon } from "../artworld/index.js";
|
|
||||||
let world = new World("mainCanvas");
|
|
||||||
|
|
||||||
for (let i = 1; i < 8; i++) {
|
|
||||||
new Polygon(world).random(3 + i);
|
|
||||||
new Polygon(world).random(i * 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
world.draw();
|
|
@ -1,11 +0,0 @@
|
|||||||
import { World, Pico8, Rect } from "../artworld/index.js";
|
|
||||||
let world = new World("mainCanvas");
|
|
||||||
window.world = world;
|
|
||||||
|
|
||||||
for (let i = 0; i < 50; i++) {
|
|
||||||
new Rect(world).random(200).fill(Pico8.BLACK).z(10);
|
|
||||||
new Rect(world).random(150).fill(Pico8.DARK_BLUE).z(15);
|
|
||||||
new Rect(world).random(100).fill(Pico8.DARK_GREY).z(20);
|
|
||||||
new Rect(world).random(50).fill(Pico8.LIGHT_GREY).z(30);
|
|
||||||
}
|
|
||||||
world.draw();
|
|
28
examples/rects.html
Normal file
28
examples/rects.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<html>
|
||||||
|
<head> </head>
|
||||||
|
<body>
|
||||||
|
<canvas id="mainCanvas" width="500" height="500"></canvas>
|
||||||
|
<script type="module">
|
||||||
|
import {
|
||||||
|
artworld,
|
||||||
|
Color,
|
||||||
|
Pico8,
|
||||||
|
Group,
|
||||||
|
Rect,
|
||||||
|
Random,
|
||||||
|
Vector2,
|
||||||
|
degToRad,
|
||||||
|
} from "../artworld/index.js";
|
||||||
|
artworld.bindCanvas("mainCanvas");
|
||||||
|
window.artworld = artworld;
|
||||||
|
|
||||||
|
for (let i = 0; i < 50; i++) {
|
||||||
|
new Rect().random(200).fill(Pico8.BLACK).z(10);
|
||||||
|
new Rect().random(150).fill(Pico8.DARK_BLUE).z(15);
|
||||||
|
new Rect().random(100).fill(Pico8.DARK_GREY).z(20);
|
||||||
|
new Rect().random(50).fill(Pico8.LIGHT_GREY).z(30);
|
||||||
|
}
|
||||||
|
artworld.draw();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
58
examples/spiral.html
Normal file
58
examples/spiral.html
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<html>
|
||||||
|
<head> </head>
|
||||||
|
<body>
|
||||||
|
<canvas id="mainCanvas" width="800" height="800"></canvas>
|
||||||
|
<script type="module">
|
||||||
|
import {
|
||||||
|
artworld,
|
||||||
|
Color,
|
||||||
|
Group,
|
||||||
|
Line,
|
||||||
|
Random,
|
||||||
|
Vector2,
|
||||||
|
degToRad,
|
||||||
|
} from "../artworld/index.js";
|
||||||
|
artworld.bindCanvas("mainCanvas");
|
||||||
|
window.artworld = artworld;
|
||||||
|
|
||||||
|
function* spirals() {
|
||||||
|
while (true) {
|
||||||
|
let g = new Group();
|
||||||
|
for (let d = 0; d < 180; d += 10) {
|
||||||
|
if (Random.chance(0.9)) {
|
||||||
|
new Line(g).to(Vector2.polar(190 - d, degToRad(d)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yield g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeGrid(iterable, rows, cols, opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
let width = opts.width || 50;
|
||||||
|
let height = opts.height || 50;
|
||||||
|
let xOff = opts.xOff || 0;
|
||||||
|
let yOff = opts.yOff || 0;
|
||||||
|
for (let c = 0; c < cols; c++) {
|
||||||
|
for (let r = 0; r < rows; r++) {
|
||||||
|
let result = iterable.next().value;
|
||||||
|
if (result === undefined) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
result.pos(new Vector2(width * c + xOff, height * r + yOff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
makeGrid(spirals(), 4, 3, {
|
||||||
|
width: 220,
|
||||||
|
height: 120,
|
||||||
|
xOff: 80,
|
||||||
|
yOff: 10,
|
||||||
|
});
|
||||||
|
|
||||||
|
artworld.draw();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,51 +0,0 @@
|
|||||||
import {
|
|
||||||
World,
|
|
||||||
Pico8,
|
|
||||||
Group,
|
|
||||||
Line,
|
|
||||||
Random,
|
|
||||||
Vector2,
|
|
||||||
degToRad,
|
|
||||||
} from "../artworld/index.js";
|
|
||||||
const world = new World("mainCanvas");
|
|
||||||
window.world = world;
|
|
||||||
|
|
||||||
function* spirals() {
|
|
||||||
while (true) {
|
|
||||||
let g = new Group(world);
|
|
||||||
let rc = Random.choice(Object.values(Pico8));
|
|
||||||
for (let d = 0; d < 180; d += 10) {
|
|
||||||
if (Random.chance(0.9)) {
|
|
||||||
new Line(g).to(Vector2.polar(190 - d, degToRad(d))).stroke(rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yield g;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeGrid(iterable, rows, cols, opts) {
|
|
||||||
opts = opts || {};
|
|
||||||
let width = opts.width || 50;
|
|
||||||
let height = opts.height || 50;
|
|
||||||
let xOff = opts.xOff || 0;
|
|
||||||
let yOff = opts.yOff || 0;
|
|
||||||
for (let c = 0; c < cols; c++) {
|
|
||||||
for (let r = 0; r < rows; r++) {
|
|
||||||
let result = iterable.next().value;
|
|
||||||
if (result === undefined) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
result.pos(new Vector2(width * c + xOff, height * r + yOff));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
makeGrid(spirals(), 4, 3, {
|
|
||||||
width: 220,
|
|
||||||
height: 120,
|
|
||||||
xOff: 80,
|
|
||||||
yOff: 10,
|
|
||||||
});
|
|
||||||
|
|
||||||
world.draw();
|
|
Loading…
Reference in New Issue
Block a user