diff --git a/README.md b/README.md index 03eee5d..cebb886 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > A JS / Canvas workshop rövid összefoglalója ## Mi az a JavaScript? - + Egy magasszintű, gyengén típusos, értelmezett nyelv. + + Egy magas szintű, gyengén típusos, értelmezett nyelv. + A "böngészőben fut". + Változatos módon tudja befolyásolni az oldal állapotát. + A háttérben aszinkron módon képes szerverekkel kommunikálni ([AJAX](https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX)) @@ -12,7 +12,7 @@ + [HTMLMediaElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement) + **[Canvas](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API)** + etc. -+ És természetesen minden olyan dologra képes, ami egy magasszintű nyelvtől elvárható. ++ És természetesen minden olyan dologra képes, ami egy magas szintű nyelvtől elvárható. ### [Kristóf nagyon jó JavaScript összefoglalója](https://github.com/kripod/schdesign-web-workshop/blob/master/notes/js.md) ### Egy nem annyira jó, viszont annál tömörebb összefoglaló + A konzolra kiírni (böngészőben **F12**-vel megnyitható) a ```console.log("szöveg");``` hívással lehet. diff --git a/index.html b/index.html index db339ab..bb13fe4 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + @@ -9,7 +9,7 @@ @@ -21,9 +21,10 @@

Avoid

- the red balls by moving your cursor (or finger) on the screen. Try - eliminating the enemy balls by getting them to collide with each - other. Good luck! + A relentless swarm is closing in on you. Guide your light across + the screen with your cursor (or finger), stay out of reach, and + outsmart your pursuers by luring them into crashing into one + another. How long can you survive?

diff --git a/js/CanvasHandler.js b/js/CanvasHandler.js index 2a9d5cc..5b80ff6 100644 --- a/js/CanvasHandler.js +++ b/js/CanvasHandler.js @@ -38,6 +38,14 @@ class CanvasHandler { return unit * Math.sqrt(this.width * this.height); } + clientToCanvas(clientX, clientY) { + const rect = this.canvas.getBoundingClientRect(); + return [ + ((clientX - rect.left) / rect.width) * this.width, + ((clientY - rect.top) / rect.height) * this.height, + ]; + } + get width() { return this.canvas.width / window.devicePixelRatio; } diff --git a/js/InputHandler.js b/js/InputHandler.js index 9e73e72..fb5f31a 100644 --- a/js/InputHandler.js +++ b/js/InputHandler.js @@ -1,14 +1,18 @@ class InputHandler { - constructor(idOfWatchedArea) { - const elem = document.getElementById(idOfWatchedArea); + constructor(canvasHandler) { + const elem = canvasHandler.canvas; - const handleMouse = ({ offsetX, offsetY }) => - this.setPointerPosition([offsetX, offsetY]); - const handleTouch = ({ touches }) => - this.setPointerPosition([touches[0].clientX, touches[0].clientY]); + const handleMouse = ({ clientX, clientY }) => + this.setPointerPosition(canvasHandler.clientToCanvas(clientX, clientY)); + + const handleTouch = (event) => { + event.preventDefault(); + const { clientX, clientY } = event.touches[0]; + this.setPointerPosition(canvasHandler.clientToCanvas(clientX, clientY)); + }; elem.addEventListener("mousemove", handleMouse); - elem.addEventListener("touchmove", handleTouch); + elem.addEventListener("touchmove", handleTouch, { passive: false }); this.pointerPosition = [0, 0]; } diff --git a/js/main.js b/js/main.js index a3be31d..f40517f 100644 --- a/js/main.js +++ b/js/main.js @@ -1,7 +1,8 @@ -const enemySpawnFrequency = 4.5; +const enemySpawnFrequencyPerSecond = 4.5; +const maxDeltaTimeInMs = 50; const canvasHandler = new CanvasHandler("canvas"); -const inputHandler = new InputHandler("canvas"); +const inputHandler = new InputHandler(canvasHandler); let game; function newGame() { @@ -27,11 +28,16 @@ class Circle { this.position = add(this.position, limit(deltaPosition, maxDistance)); } } + draw(canvasHandler) { canvasHandler.drawCircle(this.position, this.size, this.color); } + isTouching(other) { - return magnitude(subtract(this.position, other.position)) < 2 * this.size; + return ( + magnitude(subtract(this.position, other.position)) < + this.size + other.size + ); } } @@ -46,8 +52,8 @@ class Game { ); this.circleHolder = [this.player]; - this.spawnInterval = 1000 / enemySpawnFrequency; - this.previousSpawn = this.previousTimestamp = 0; + this.spawnInterval = 1000 / enemySpawnFrequencyPerSecond; + this.previousSpawn = this.previousTime = 0; this.score = 0; this.menuBox = document.getElementById("menuBox").style; @@ -55,16 +61,19 @@ class Game { "none"; this.isActive = true; - window.requestAnimationFrame(this.nextFrame.bind(this)); + this.boundNextFrame = this.nextFrame.bind(this); + window.requestAnimationFrame(this.boundNextFrame); } + nextFrame(timestamp) { if (this.isActive) { canvasHandler.fillCanvas("rgba(165, 64, 45, 0.1)"); this.spawnEnemyIfNeeded(timestamp); this.moveCircles(timestamp); - window.requestAnimationFrame(this.nextFrame.bind(this)); + window.requestAnimationFrame(this.boundNextFrame); } } + spawnEnemyIfNeeded(timestamp) { if (timestamp - this.previousSpawn > this.spawnInterval) { this.circleHolder.push( @@ -84,31 +93,42 @@ class Game { this.score++; } } + moveCircles(timestamp) { const deltaTime = this.getDeltaTime(timestamp); + const collided = new Set(); for (let i = 0; i < this.circleHolder.length; i++) { this.circleHolder[i].move(deltaTime); this.circleHolder[i].draw(canvasHandler); for (let j = i + 1; j < this.circleHolder.length; j++) { if (this.circleHolder[i].isTouching(this.circleHolder[j])) { - if (this.circleHolder[i] == this.player) this.showEndScreen(); - else { - this.circleHolder.splice(i, 1); - this.circleHolder.splice(j - 1, 1); + if (this.circleHolder[i] === this.player) { + this.showEndScreen(); + return; } + collided.add(i).add(j); } } } + + if (collided.size > 0) { + this.circleHolder = this.circleHolder.filter( + (_, index) => !collided.has(index) + ); + } } + getDeltaTime(timestamp) { const tempPreviousTime = this.previousTime; this.previousTime = timestamp; - return timestamp - tempPreviousTime; + return Math.min(timestamp - tempPreviousTime, maxDeltaTimeInMs); } + showEndScreen() { document.getElementById("endText").style.display = "block"; document.getElementById("endScore").innerHTML = `Your score: ${this.score}`; + document.getElementById("startButton").textContent = "Play again"; this.menuBox.display = "flex"; this.isActive = false; }