From 3d366a1a6ce460f160c454c93343706752871973 Mon Sep 17 00:00:00 2001 From: Emma Date: Sat, 11 Feb 2023 18:39:19 -0700 Subject: [PATCH] drawImage and drawSprite --- EngineSprites.png | Bin 0 -> 4428 bytes PurpleEngine.png | Bin 0 -> 1578 bytes bundle.js | 40 +++++++++++++++++++++++++++++++++++++++- canvas.ts | 9 +++++++++ main.ts | 14 +++++++++++--- 5 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 EngineSprites.png create mode 100644 PurpleEngine.png diff --git a/EngineSprites.png b/EngineSprites.png new file mode 100644 index 0000000000000000000000000000000000000000..0bb1b60107d2161bdc48a3941e0a9a26d1c0b3aa GIT binary patch literal 4428 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 literal 0 HcmV?d00001 diff --git a/bundle.js b/bundle.js index 5d21220..03df1c3 100644 --- a/bundle.js +++ b/bundle.js @@ -59,6 +59,7 @@ class Vector { this.y += y ?? 0; this.z += z ?? 0; } + return this; } sub(v, y, z) { if (arguments.length === 1 && typeof v !== 'number') { @@ -73,6 +74,7 @@ class Vector { this.y -= y ?? 0; this.z -= z ?? 0; } + return this; } mult(v) { if (typeof v === 'number') { @@ -96,6 +98,7 @@ class Vector { this.y /= v.y; this.z /= v.z; } + return this; } rotate(angle) { const prev_x = this.x; @@ -103,6 +106,7 @@ class Vector { const s = Math.sin(angle); this.x = c * this.x - s * this.y; this.y = s * prev_x + c * this.y; + return this; } dist(v) { const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; @@ -135,6 +139,7 @@ class Vector { this.x = lerp_val(this.x, x, amt); this.y = lerp_val(this.y, y, amt); this.z = lerp_val(this.z, z, amt); + return this; } normalize() { const m = this.mag(); @@ -148,6 +153,7 @@ class Vector { this.normalize(); this.mult(high); } + return this; } heading() { return -Math.atan2(-this.y, this.x); @@ -251,6 +257,7 @@ class Doodler { return this.ctx.canvas.height; } draggables = []; + clickables = []; constructor({ width , height , canvas , bg , framerate }){ if (!canvas) { canvas = document.createElement('canvas'); @@ -381,6 +388,12 @@ class Doodler { cb(); this.ctx.restore(); } + drawImage(img, at, w, h) { + w && h ? this.ctx.drawImage(img, at.x, at.y, w, h) : this.ctx.drawImage(img, at.x, at.y); + } + drawSprite(img, spritePos, sWidth, sHeight, at, width, height) { + this.ctx.drawImage(img, spritePos.x, spritePos.y, sWidth, sHeight, at.x, at.y, width, height); + } setStyle(style) { const ctx = this.ctx; ctx.fillStyle = style?.color || style?.fillColor || 'black'; @@ -410,6 +423,19 @@ class Doodler { } this.draggables = this.draggables.filter((d)=>d.point !== point); } + registerClickable(p1, p2, cb) { + const top = Math.min(p1.y, p2.y); + const left = Math.min(p1.x, p2.x); + const bottom = Math.max(p1.y, p2.y); + const right = Math.max(p1.x, p2.x); + this.clickables.push({ + onClick: cb, + checkBound: (p)=>p.y >= top && p.x >= left && p.y <= bottom && p.x <= right + }); + } + unregisterClickable(cb) { + this.clickables = this.clickables.filter((c)=>c.onClick !== cb); + } addDragEvents({ onDragEnd , onDragStart , point }) { const d = this.draggables.find((d)=>d.point === point); if (d) { @@ -418,12 +444,18 @@ class Doodler { } } onClick(e) { + const mouse = new Vector(this.mouseX, this.mouseY); for (const d of this.draggables){ - if (d.point.dist(new Vector(this.mouseX, this.mouseY)) <= d.radius) { + if (d.point.dist(mouse) <= d.radius) { d.beingDragged = true; d.onDragStart?.call(null); } else d.beingDragged = false; } + for (const c of this.clickables){ + if (c.checkBound(mouse)) { + c.onClick(); + } + } } offClick(e) { for (const d of this.draggables){ @@ -474,6 +506,10 @@ const movingVector = new Vector(100, 300); let angleMultiplier = 0; const v = new Vector(30, 30); doodler.registerDraggable(v, 20); +const img = new Image(); +img.src = './EngineSprites.png'; +img.hidden; +document.body.append(img); doodler.createLayer(()=>{ doodler.line(new Vector(100, 100), new Vector(200, 200)); doodler.dot(new Vector(300, 300)); @@ -490,9 +526,11 @@ doodler.createLayer(()=>{ let rotatedOrigin = new Vector(200, 200); doodler.drawRotated(rotatedOrigin, Math.PI * angleMultiplier, ()=>{ doodler.drawCenteredSquare(rotatedOrigin, 30); + doodler.drawSprite(img, new Vector(0, 40), 80, 20, new Vector(160, 300), 80, 20); }); movingVector.set((movingVector.x + 1) % 400, movingVector.y); angleMultiplier += .001; + doodler.drawSprite(img, new Vector(0, 40), 80, 20, new Vector(100, 300), 80, 20); }); document.addEventListener('keyup', (e)=>{ e.preventDefault(); diff --git a/canvas.ts b/canvas.ts index f99a259..0932005 100644 --- a/canvas.ts +++ b/canvas.ts @@ -195,6 +195,15 @@ export class Doodler { this.ctx.restore(); } + drawImage(img: HTMLImageElement, at: Vector): void; + drawImage(img: HTMLImageElement, at: Vector, w: number, h: number): void; + drawImage(img: HTMLImageElement, at: Vector, w?: number, h?: number) { + w && h ? this.ctx.drawImage(img, at.x, at.y, w, h) : this.ctx.drawImage(img, at.x, at.y); + } + drawSprite(img: HTMLImageElement, spritePos: Vector, sWidth: number, sHeight: number, at: Vector, width: number, height: number) { + this.ctx.drawImage(img, spritePos.x, spritePos.y, sWidth, sHeight, at.x, at.y, width, height); + } + setStyle(style?: IStyle) { const ctx = this.ctx; ctx.fillStyle = style?.color || style?.fillColor || 'black'; diff --git a/main.ts b/main.ts index 8922b85..e4d8d96 100644 --- a/main.ts +++ b/main.ts @@ -9,8 +9,13 @@ initializeDoodler({ const movingVector = new Vector(100, 300); let angleMultiplier = 0; -const v = new Vector(30,30); +const v = new Vector(30, 30); doodler.registerDraggable(v, 20) +const img = new Image(); +img.src = './EngineSprites.png' +img.hidden +document.body.append(img) + doodler.createLayer(() => { doodler.line(new Vector(100, 100), new Vector(200, 200)) @@ -22,14 +27,17 @@ doodler.createLayer(() => { doodler.drawCenteredSquare(new Vector(200, 200), 40, { color: 'purple', weight: 5 }) doodler.drawBezier(new Vector(100, 150), movingVector, new Vector(150, 300), new Vector(100, 250)) - let rotatedOrigin = new Vector(200,200) - doodler.drawRotated(rotatedOrigin, Math.PI*angleMultiplier, () => { + let rotatedOrigin = new Vector(200, 200) + doodler.drawRotated(rotatedOrigin, Math.PI * angleMultiplier, () => { doodler.drawCenteredSquare(rotatedOrigin, 30) + doodler.drawSprite(img, new Vector(0, 40), 80, 20, new Vector(160, 300), 80, 20) }) movingVector.set((movingVector.x + 1) % 400, movingVector.y); angleMultiplier += .001; + + doodler.drawSprite(img, new Vector(0, 40), 80, 20, new Vector(100, 300), 80, 20) }); document.addEventListener('keyup', e => {