Y2xhc3MgS29rYWNQNUV4dCB7CiAgICN0YXNrcyA9IG5ldyBNYXAoKQogICBhZGQodikgeyB0aGlzLiN0YXNrcy5zZXQodikgfQogICByZW1vdmUodikgeyB0aGlzLiN0YXNrcy5kZWxldGUodikgfQogICBnZXQgaXRlcmF0b3IoKSB7IHJldHVybiB0aGlzLiN0YXNrcy5rZXlzKCkgfQogICBkZWxheShzKSB7CiAgICAgIGlmICghcykgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlKSkKICAgICAgbGV0IHdhaXRlciA9IHt9OwogICAgICB0aGlzLmFkZCh3YWl0ZXIpCiAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHsKICAgICAgICAgd2FpdGVyLnVwZGF0ZSA9ICgpID0+IHsKICAgICAgICAgICAgaWYgKC0tcyA+IDApIHJldHVybgogICAgICAgICAgICB0aGlzLnJlbW92ZSh3YWl0ZXIpCiAgICAgICAgICAgIHJlc29sdmUoKQogICAgICAgICB9CiAgICAgIH0pCiAgIH0KICAgc3RlcCgpIHsKICAgICAgY29uc3QgeyBpdGVyYXRvciB9ID0gdGhpcwogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICBsZXQgbnQgPSBpdGVyYXRvci5uZXh0KCkKICAgICAgICAgaWYgKG50LmRvbmUpIGJyZWFrCiAgICAgICAgIGxldCB7IHZhbHVlIH0gPSBudAogICAgICAgICBpZiAodmFsdWUuY29uc3RydWN0b3IgPT09IEZ1bmN0aW9uKSB7CiAgICAgICAgICAgIHZhbHVlKCkKICAgICAgICAgICAgY29udGludWUKICAgICAgICAgfQogICAgICAgICB2YWx1ZS51cGRhdGUgJiYgdmFsdWUudXBkYXRlKCkKICAgICAgICAgdmFsdWUucmVkcmF3ICYmIHZhbHVlLnJlZHJhdygpCiAgICAgIH0KICAgfQp9CmNvbnN0IGtva2FjID0gbmV3IEtva2FjUDVFeHQKZnVuY3Rpb24gZHJhdygpIHsga29rYWMuc3RlcCgpIH0KYXN5bmMgZnVuY3Rpb24gc2V0dXAoKSB7CiAgIC8vIOuhnOyngeydgCBzZXR1cCDslYjsl5DshJzrp4wg7IaQIOuMgOuptCDrkJjrj4TroZ0g7L2U65Oc66W8IOq1rOyEse2VqAogICBjb25zdCBzaXplV2lkdGggPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjc3RnJykuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkud2lkdGg7CiAgIGNvbnN0IHNpemVIZWlnaHQgPSBzaXplV2lkdGggKiAuMwogICBjcmVhdGVDYW52YXMoc2l6ZVdpZHRoLCBzaXplSGVpZ2h0KTsKICAga29rYWMuYWRkKGUgPT4gYmFja2dyb3VuZCgwKSkKICAgbGV0IHJkID0gc2l6ZVdpZHRoIC8gMjAKICAgbGV0IHJvdW5kID0gc2l6ZVdpZHRoIC8gMTAwMAogICBsZXQgbHN0ID0gW10KICAgZm9yIChsZXQgaSA9IDA7IGkgPCAoKHNpemVXaWR0aCAtIHJkKSAvIHJkKTsgaSsrKSB7CiAgICAgIGZvciAobGV0IGlhID0gMDsgaWEgPCAoKHNpemVIZWlnaHQgLSByZCkgLyByZCk7IGlhKyspIHsKICAgICAgICAgbGV0IGNjID0geyByYWRpYW46IGkgKiAwLjEgKiBpYSwgeDogKHJkICogMSkgKyAoaSAqIHJkKSwgeTogKHJkICogMSkgKyAoaWEgKiByZCksIHI6IHJvdW5kLCBycjogcmQgfTsKICAgICAgICAgY2MudXBkYXRlID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICB0aGlzLnJhZGlhbiArPSAwLjEKICAgICAgICAgfQogICAgICAgICBjYy5yZWRyYXcgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIGxldCB4ID0gdGhpcy54ICsgKE1hdGguY29zKHRoaXMucmFkaWFuKSAqIHRoaXMucikKICAgICAgICAgICAgbGV0IHkgPSB0aGlzLnkgKyAoTWF0aC5zaW4odGhpcy5yYWRpYW4pICogdGhpcy5yKQogICAgICAgICAgICB0aGlzLmN4ID0geAogICAgICAgICAgICB0aGlzLmN5ID0geQogICAgICAgICB9CiAgICAgICAgIGtva2FjLmFkZChjYykKICAgICAgICAgbHN0LnB1c2goY2MpCiAgICAgIH0KICAgfQogICBsc3QuZm9yRWFjaCgoY2MsIGkpID0+IHsKICAgICAgbGV0IGxuID0geyByYWRpYW46IGkgKiAwLjAyIH0KICAgICAgbG4udXBkYXRlID0gZnVuY3Rpb24gKCkgewogICAgICAgICB0aGlzLngxID0gY2MuY3gKICAgICAgICAgdGhpcy55MSA9IGNjLmN5CiAgICAgICAgIHRoaXMucmFkaWFuICs9IDAuMDEKICAgICAgfQogICAgICBsbi5yZWRyYXcgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgIHN0cm9rZVdlaWdodChyZCAvIDEuMikKICAgICAgICAgc3Ryb2tlKDEzMCkKICAgICAgICAgbGV0IGxlbmd0aCA9IHJkIC8gMgogICAgICAgICBsZXQgZXggPSB0aGlzLngxICsgKGxlbmd0aCAqIE1hdGguY29zKHRoaXMucmFkaWFuKSkKICAgICAgICAgbGV0IGV5ID0gdGhpcy55MSArIChsZW5ndGggKiBNYXRoLnNpbih0aGlzLnJhZGlhbikpCiAgICAgICAgIGxpbmUodGhpcy54MSwgdGhpcy55MSwgZXgsIGV5KQogICAgICB9CiAgICAgIGtva2FjLmFkZChsbikKICAgfSkKfQ==
class KokacP5Ext {
#tasks = new Map()
add(v) { this.#tasks.set(v) }
remove(v) { this.#tasks.delete(v) }
get iterator() { return this.#tasks.keys() }
delay(s) {
if (!s) return new Promise(resolve => setTimeout(resolve))
let waiter = {};
this.add(waiter)
return new Promise(resolve => {
waiter.update = () => {
if (--s > 0) return
this.remove(waiter)
resolve()
}
})
}
step() {
const { iterator } = this
while (true) {
let nt = iterator.next()
if (nt.done) break
let { value } = nt
if (value.constructor === Function) {
value()
continue
}
value.update && value.update()
value.redraw && value.redraw()
}
}
}
const kokac = new KokacP5Ext
function draw() { kokac.step() }
async function setup() {
// 로직은 setup 안에서만 손 대면 되도록 코드를 구성함
const sizeWidth = document.querySelector('#stg').getBoundingClientRect().width;
const sizeHeight = sizeWidth * .3
createCanvas(sizeWidth, sizeHeight);
kokac.add(e => background(0))
let rd = sizeWidth / 20
let round = sizeWidth / 1000
let lst = []
for (let i = 0; i < ((sizeWidth - rd) / rd); i++) {
for (let ia = 0; ia < ((sizeHeight - rd) / rd); ia++) {
let cc = { radian: i * 0.1 * ia, x: (rd * 1) + (i * rd), y: (rd * 1) + (ia * rd), r: round, rr: rd };
cc.update = function () {
this.radian += 0.1
}
cc.redraw = function () {
let x = this.x + (Math.cos(this.radian) * this.r)
let y = this.y + (Math.sin(this.radian) * this.r)
this.cx = x
this.cy = y
}
kokac.add(cc)
lst.push(cc)
}
}
lst.forEach((cc, i) => {
let ln = { radian: i * 0.02 }
ln.update = function () {
this.x1 = cc.cx
this.y1 = cc.cy
this.radian += 0.01
}
ln.redraw = function () {
strokeWeight(rd / 1.2)
stroke(130)
let length = rd / 2
let ex = this.x1 + (length * Math.cos(this.radian))
let ey = this.y1 + (length * Math.sin(this.radian))
line(this.x1, this.y1, ex, ey)
}
kokac.add(ln)
})
}