mirror of
https://github.com/sigmasternchen/88x31breakout
synced 2025-03-15 07:59:00 +00:00
add system for launching balls
This commit is contained in:
parent
924e7d57c2
commit
3c6e1aff5f
8 changed files with 66 additions and 6 deletions
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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
3
src/game/parameters.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
export const defaultBallSpeed = 700; // pixel / s
|
||||||
|
export const startAngles = [Math.PI / 4, Math.PI * 3 / 4];
|
|
@ -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();
|
||||||
});
|
});
|
|
@ -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)];
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue