import {Vector, VectorInteger} from "./Vector.js"; import {Component, Moving} from "./interface.js"; class Rectangle implements Component { ctx: CanvasRenderingContext2D; pos: VectorInteger; color: string; width: number; height: number; constructor(ctx: CanvasRenderingContext2D, pos: VectorInteger, color: string, width: number, height: number) { this.ctx = ctx; this.pos = Object.assign({}, pos); this.color = color; this.width = width; this.height = height; } update() { this.ctx.fillStyle = this.color; this.ctx.fillRect(this.pos.x, this.pos.y, this.width, this.height); } clear(pos?: VectorInteger) { if (pos) this.ctx.clearRect(pos.x, pos.y, this.width, this.height); else this.ctx.clearRect(this.pos.x, this.pos.y, this.width, this.height); } collision(collider: Rectangle): boolean { // Collision WIP. To redo var myleft = this.pos.x; var myright = this.pos.x + (this.width); var mytop = this.pos.y; var mybottom = this.pos.y + (this.height); var otherleft = collider.pos.x; var otherright = collider.pos.x + (collider.width); var othertop = collider.pos.y; var otherbottom = collider.pos.y + (collider.height); if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) { return false; } else return true; } } class MovingRectangle extends Rectangle implements Moving { dir: Vector = new Vector(0,0); speed: number; readonly baseSpeed: number; constructor(ctx: CanvasRenderingContext2D, pos: VectorInteger, color: string, width: number, height: number, baseSpeed: number) { super(ctx, pos, color, width, height); this.baseSpeed = baseSpeed; this.speed = baseSpeed; } move(delta: number) { // Math.floor WIP until VectorInteger debug // console.log("delta: "+ delta); // console.log("speed: "+ this.speed); // console.log("speed*delta: "+ this.speed * delta); this.pos.x += Math.floor(this.dir.x * this.speed * delta); this.pos.y += Math.floor(this.dir.y * this.speed * delta); } moveAndCollide(delta: number, colliderArr: Rectangle[]) { let oldPos = Object.assign({}, this.pos); this.move(delta); if (colliderArr.some(this.collision, this)) { this.pos.x = oldPos.x; this.pos.y = oldPos.y; } else { this.clear(oldPos); this.update(); } } } class Racket extends MovingRectangle { constructor(ctx: CanvasRenderingContext2D, pos: VectorInteger, color: string, width: number, height: number, baseSpeed: number) { super(ctx, pos, color, width, height, baseSpeed); } } class Ball extends MovingRectangle { constructor(ctx: CanvasRenderingContext2D, pos: VectorInteger, color: string, size: number, baseSpeed: number) { super(ctx, pos, color, size, size, baseSpeed); } bounce(collider?: Rectangle) { /* Could be more generic, but testing only Racket is enough, because in Pong collider can only be Racket or Wall. */ if (collider instanceof Racket) { this._bouncePlayer(collider); } else { this._bounceWall(); } } moveAndBounce(delta: number, colliderArr: Rectangle[]) { let oldPos = Object.assign({}, this.pos); this.move(delta); let i = colliderArr.findIndex(this.collision, this); if (i != -1) { this.bounce(colliderArr[i]); this.move(delta); } this.clear(oldPos); this.update(); } private _bounceWall() { // Should be enough for Wall this.dir.y = this.dir.y * -1; } private _bouncePlayer(collider: Racket) { // WIP // Bounce for Racket need to be more complexe than this this.speed += this.baseSpeed/20; this.dir.x = this.dir.x * -1; } } class Line extends Rectangle { gapeCount: number = 0; segmentCount: number; segmentWidth: number; segmentHeight: number; constructor(ctx: CanvasRenderingContext2D, pos: VectorInteger, color: string, width: number, height: number, gapeCount?: number) { super(ctx, pos, color, width, height); if (gapeCount) this.gapeCount = gapeCount; this.segmentCount = this.gapeCount * 2 + 1; this.segmentWidth = this.width; this.segmentHeight = this.height / this.segmentCount; // for Horizontal Line // this.segmentWidth = this.width / this.segmentCount; // this.segmentHeight = this.height; } update() { this.ctx.fillStyle = this.color; let pos: VectorInteger = new VectorInteger; let i = 0; while (i < this.segmentCount) { // for Horizontal Line // pos.y = this.pos.y; // pos.x = this.pos.x + this.segmentWidth * i; pos.x = this.pos.x; pos.y = this.pos.y + this.segmentHeight * i; this.ctx.fillRect(pos.x, pos.y, this.segmentWidth, this.segmentHeight); i += 2; } } } export {Rectangle, MovingRectangle, Racket, Ball, Line} // How to handle const export in initGame ? // example for class Rectangle /* constructor(ctx?: CanvasRenderingContext2D, pos?: VectorInteger, color?: string, width?: number, height?: number) { if (ctx && pos && color && width && height) this.init(ctx, pos, color, width, height); } // constructor() {} init(ctx: CanvasRenderingContext2D, pos: VectorInteger, color: string, width: number, height: number) { this.ctx = ctx; this.pos = Object.assign({}, pos); this.color = color; this.width = width; this.height = height; } */