173 lines
5.1 KiB
TypeScript
173 lines
5.1 KiB
TypeScript
|
|
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;
|
|
} */
|