From 3c6e1aff5ffc983d861e0331f20c35848780444b Mon Sep 17 00:00:00 2001 From: sigmasternchen Date: Wed, 30 Oct 2024 22:45:44 +0100 Subject: [PATCH] add system for launching balls --- src/game/Ball.ts | 14 ++++++++++++++ src/game/Game.ts | 27 +++++++++++++++++++++++++-- src/game/Paddle.ts | 10 +++++++++- src/game/Position.ts | 7 +++++++ src/game/geometry.ts | 2 +- src/game/parameters.ts | 3 +++ src/index.ts | 1 + src/utils.ts | 8 ++++++-- 8 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 src/game/parameters.ts diff --git a/src/game/Ball.ts b/src/game/Ball.ts index e42cc43..f98d866 100644 --- a/src/game/Ball.ts +++ b/src/game/Ball.ts @@ -1,8 +1,12 @@ import {Position} from "./Position"; import {ballSize} from "./geometry"; +import {choice} from "../utils"; +import {defaultBallSpeed, startAngles} from "./parameters"; export class Ball { private _position: Position; + private phi: number; + private speed: number; private readonly element: HTMLElement; constructor() { @@ -28,4 +32,14 @@ export class Ball { public setup(gameElement: HTMLElement): void { gameElement.appendChild(this.element); } + + public launch() { + this.phi = choice(startAngles); + this.speed = defaultBallSpeed; + } + + public tick(delta: number) { + this._position = this._position.moveInDirection(this.phi, this.speed * delta / 1000); + this.redraw(); + } } \ No newline at end of file diff --git a/src/game/Game.ts b/src/game/Game.ts index f58d654..fdb1686 100644 --- a/src/game/Game.ts +++ b/src/game/Game.ts @@ -10,6 +10,9 @@ export class Game { private paddle: Paddle; private balls: Ball[]; + private running: boolean = false; + private lastTickTimestamp: number = 0; + constructor(root: HTMLElement) { this.root = root; this.root.style.height = fieldHeight + "px"; @@ -26,7 +29,27 @@ export class Game { public setup(): void { this.banners.forEach(banner => banner.setup(this.root)); - this.paddle.setup(this.root); + this.paddle.setup(this.root, this.ballLaunchHandler.bind(this)); this.balls.forEach(ball => ball.setup(this.root)); } -} \ No newline at end of file + + private ballLaunchHandler(ball: Ball): void { + this.balls.push(ball); + ball.launch(); + } + + public run(): void { + this.running = true; + requestAnimationFrame(this.tick.bind(this)) + } + + private tick(timestamp: number): void { + const delta = timestamp - this.lastTickTimestamp; + this.lastTickTimestamp = timestamp; + + this.balls.forEach(ball => ball.tick.bind(ball)(delta)); + if (this.running) { + requestAnimationFrame(this.tick.bind(this)); + } + } +} diff --git a/src/game/Paddle.ts b/src/game/Paddle.ts index 6a47a38..83bceb4 100644 --- a/src/game/Paddle.ts +++ b/src/game/Paddle.ts @@ -41,12 +41,20 @@ export class Paddle { this.redraw(); } - public setup(gameElement: HTMLElement): void { + public setup(gameElement: HTMLElement, ballLaunchHandler: (ball: Ball) => void): void { gameElement.appendChild(this.element); gameElement.addEventListener("mousemove", this.mouseHandler.bind(this)); gameElement.addEventListener("mouseenter", this.mouseHandler.bind(this)); gameElement.addEventListener("mouseleave", this.mouseHandler.bind(this)); + gameElement.addEventListener("click", () => { + if (this.ball) { + const ball = this.ball; + this.ball = null; + ballLaunchHandler(ball); + } + }); + if (this.ball) { this.ball.setup(gameElement); } diff --git a/src/game/Position.ts b/src/game/Position.ts index eb4cb5e..9dbbb04 100644 --- a/src/game/Position.ts +++ b/src/game/Position.ts @@ -15,4 +15,11 @@ export class Position { get y(): number { return this._y; } + + public moveInDirection(phi: number, distance: number): Position { + return new Position( + this._x + Math.cos(phi) * distance, + this._y - Math.sin(phi) * distance + ); + } } \ No newline at end of file diff --git a/src/game/geometry.ts b/src/game/geometry.ts index ff82fbe..bb3da57 100644 --- a/src/game/geometry.ts +++ b/src/game/geometry.ts @@ -5,4 +5,4 @@ export const fieldHeight = 500; export const paddleY = fieldHeight - 20; export const paddleHeight = 10; -export const ballSize = 15; \ No newline at end of file +export const ballSize = 15; diff --git a/src/game/parameters.ts b/src/game/parameters.ts new file mode 100644 index 0000000..d915693 --- /dev/null +++ b/src/game/parameters.ts @@ -0,0 +1,3 @@ + +export const defaultBallSpeed = 700; // pixel / s +export const startAngles = [Math.PI / 4, Math.PI * 3 / 4]; \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 921c678..31443e4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,4 +4,5 @@ window.addEventListener("load", async () => { const game = new Game(document.getElementById("game")); await game.load(); game.setup(); + game.run(); }); \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts index 2cd98d1..4b1d5aa 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -7,8 +7,12 @@ export function shuffleInPlace(array: any[]) { } } -export function toShuffled (array: T[]) { +export function toShuffled (array: T[]): T[] { const copy = [...array]; shuffleInPlace(copy); return copy; -} \ No newline at end of file +} + +export function choice (array: T[]): T { + return array[0 | (Math.random() * array.length)]; +}