add system for launching balls

This commit is contained in:
sigmasternchen 2024-10-30 22:45:44 +01:00
parent 924e7d57c2
commit 3c6e1aff5f
8 changed files with 66 additions and 6 deletions

View file

@ -1,8 +1,12 @@
import {Position} from "./Position"; import {Position} from "./Position";
import {ballSize} from "./geometry"; import {ballSize} from "./geometry";
import {choice} from "../utils";
import {defaultBallSpeed, startAngles} from "./parameters";
export class Ball { export class Ball {
private _position: Position; private _position: Position;
private phi: number;
private speed: number;
private readonly element: HTMLElement; private readonly element: HTMLElement;
constructor() { constructor() {
@ -28,4 +32,14 @@ export class Ball {
public setup(gameElement: HTMLElement): void { public setup(gameElement: HTMLElement): void {
gameElement.appendChild(this.element); 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();
}
} }

View file

@ -10,6 +10,9 @@ export class Game {
private paddle: Paddle; private paddle: Paddle;
private balls: Ball[]; private balls: Ball[];
private running: boolean = false;
private lastTickTimestamp: number = 0;
constructor(root: HTMLElement) { constructor(root: HTMLElement) {
this.root = root; this.root = root;
this.root.style.height = fieldHeight + "px"; this.root.style.height = fieldHeight + "px";
@ -26,7 +29,27 @@ export class Game {
public setup(): void { public setup(): void {
this.banners.forEach(banner => banner.setup(this.root)); 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)); this.balls.forEach(ball => ball.setup(this.root));
} }
}
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));
}
}
}

View file

@ -41,12 +41,20 @@ export class Paddle {
this.redraw(); this.redraw();
} }
public setup(gameElement: HTMLElement): void { public setup(gameElement: HTMLElement, ballLaunchHandler: (ball: Ball) => void): void {
gameElement.appendChild(this.element); gameElement.appendChild(this.element);
gameElement.addEventListener("mousemove", this.mouseHandler.bind(this)); gameElement.addEventListener("mousemove", this.mouseHandler.bind(this));
gameElement.addEventListener("mouseenter", this.mouseHandler.bind(this)); gameElement.addEventListener("mouseenter", this.mouseHandler.bind(this));
gameElement.addEventListener("mouseleave", 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) { if (this.ball) {
this.ball.setup(gameElement); this.ball.setup(gameElement);
} }

View file

@ -15,4 +15,11 @@ export class Position {
get y(): number { get y(): number {
return this._y; 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
);
}
} }

View file

@ -5,4 +5,4 @@ export const fieldHeight = 500;
export const paddleY = fieldHeight - 20; export const paddleY = fieldHeight - 20;
export const paddleHeight = 10; export const paddleHeight = 10;
export const ballSize = 15; export const ballSize = 15;

3
src/game/parameters.ts Normal file
View file

@ -0,0 +1,3 @@
export const defaultBallSpeed = 700; // pixel / s
export const startAngles = [Math.PI / 4, Math.PI * 3 / 4];

View file

@ -4,4 +4,5 @@ window.addEventListener("load", async () => {
const game = new Game(document.getElementById("game")); const game = new Game(document.getElementById("game"));
await game.load(); await game.load();
game.setup(); game.setup();
game.run();
}); });

View file

@ -7,8 +7,12 @@ export function shuffleInPlace(array: any[]) {
} }
} }
export function toShuffled <T> (array: T[]) { export function toShuffled <T> (array: T[]): T[] {
const copy = [...array]; const copy = [...array];
shuffleInPlace(copy); shuffleInPlace(copy);
return copy; return copy;
} }
export function choice <T> (array: T[]): T {
return array[0 | (Math.random() * array.length)];
}