Files
kawaii-jumper/src/app/home/home.page.ts

535 lines
15 KiB
TypeScript

import { Component, OnInit } from '@angular/core';
import { Socket } from 'ngx-socket-io';
import { Position } from '../../../../Kawaii-Jumper-server/src/position';
import {
PlayerDTO,
PlayerDTOList,
PlayerList,
StringNumber,
StringVector,
Vector,
} from './types.dto';
import { MapTile } from '../../../../Kawaii-Jumper-server/src/mapTile';
import { getXFromAngle } from './getXFromAngle';
import { getAngleBetweenTwoPoints } from './getAngleBetweenTwoPoints';
import { getYFromAngle } from './getYFromAngle';
import { applyGravity } from './applyGravity';
import { IsIntersecting } from './isIntersecting';
import { drawMap } from './drawMap';
import { Globals } from './globals';
import { Players } from './players';
import { MySocket } from './mySocket';
import { DeltaTime } from './deltaTime';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
globals: Globals;
players: Players;
mySocket: MySocket;
deltaTime: DeltaTime;
myLastPosition: Position = { x: 0, y: 0 };
jumpPower = Date.now();
lastPointerPosition: Position = { x: 0, y: 0 };
keysDown: { [key: number]: boolean } = {};
mapBuilder = false;
builtMap: MapTile[] = [];
constructor(private socket: Socket) {
this.globals = Globals.getInstance();
this.players = Players.getInstance();
this.deltaTime = DeltaTime.getInstance();
this.globals.socket = socket;
this.mySocket = MySocket.getInstance();
this.globals.pageHeight = window.innerHeight;
this.globals.pageWidth = window.innerWidth;
this.setupSocketListeners();
}
ngOnInit(): void {
this.globals.setupCanvas();
this.setListeners();
this.gameLoop();
}
setupSocketListeners() {
this.mySocket.onId((id: string) => (this.globals.socketId = id));
this.mySocket.onMap((map: MapTile[]) => (this.globals.map = map));
this.mySocket.onPlayerConnected((players: PlayerDTOList) =>
this.players.addMultiplaPlayers(players),
);
this.mySocket.onNewPlayerConnected((player: PlayerDTO) =>
this.players.addPlayer(player),
);
this.mySocket.onPlayerDisconnected((id: string) =>
this.players.removePlayer(id),
);
this.mySocket.onUpdatedPlayerColor((playersColor: StringNumber) =>
this.players.updatePlayerColor(playersColor),
);
this.mySocket.onUpdatedPlayerPosition((playersPosition: StringVector) =>
this.players.updatePlayerPosition(playersPosition),
);
this.mySocket.onUpdatedPlayerDirection((playersDirection: StringNumber) =>
this.players.updatePlayerDirection(playersDirection),
);
}
getJumpPower(): number {
let power = Date.now() - this.jumpPower;
return Math.abs(getXFromAngle(power / 1000) * 1.4);
}
getJumpDirection(x: number, y: number) {
return getAngleBetweenTwoPoints(
{
x:
this.players.getMyself().getPosition().x +
this.globals.playerSize.x / 2,
y:
this.players.getMyself().getPosition().y +
this.globals.playerSize.y / 2,
},
{
x: x * this.globals.canvasScale,
y: y * this.globals.canvasScale,
},
);
}
clickEndListener($event): Position {
console.log('click');
if (!this.players.getMyself()) return;
console.log('I found myself');
if (!this.players.getMyself().isGrounded()) return;
console.log('I am grounded');
this.players.getMyself().swapColor();
this.socket.emit('updatedColor', this.players.getMyself().getColor());
this.players.getMyself().setGrounded(false);
const angle = this.getJumpDirection($event.offsetX, $event.offsetY);
this.players.getMyself().jump(angle, this.getJumpPower());
this.socket.emit(
'updatedDirection',
this.players.getMyself().getDirection(),
);
this.globals.sounds[0].play();
return this.players.getMyself().getMovingVelocity();
}
mapClickListenerEnd($event) {
this.builtMap.push({
color: 0,
x: $event.offsetX * this.globals.canvasScale,
y: $event.offsetY * this.globals.canvasScale,
w: 130,
h: 30,
});
console.log(this.builtMap);
}
moveListener($event): void {
if (!this.globals.socketId) return;
this.lastPointerPosition = {
x: $event.offsetX * this.globals.canvasScale,
y: $event.offsetY * this.globals.canvasScale,
};
}
setListeners() {
window.addEventListener('keydown', (e) => this.keyListener(e, true));
window.addEventListener('keyup', (e) => this.keyListener(e, false));
window.addEventListener('mouseup', (e) => this.mapBuilder ? this.mapClickListenerEnd(e) : this.clickEndListener(e));
window.addEventListener('touchend', (e) => this.clickEndListener(e));
window.addEventListener('mousemove', (e) => this.moveListener(e));
}
keyListener($event, state) {
this.keysDown[$event.keyCode] = state;
}
detectCollisions() {
const player = this.players.getMyself();
for (let block of this.globals.map) {
if (block.color !== this.players.getMyself().getColor()) continue;
const playerWidth = this.globals.playerSize.x;
const playerHeight = this.globals.playerSize.y;
const myPosition = player.getPosition();
const playerTopLeft: Position = myPosition;
const playerTopRight: Position = {
x: myPosition.x + playerWidth,
y: myPosition.y,
};
const playerBottomLeft: Position = {
x: myPosition.x,
y: myPosition.y + playerHeight,
};
const playerBottomRight: Position = {
x: myPosition.x + playerWidth,
y: myPosition.y + playerHeight,
};
const blockTopLeft: Position = { x: block.x, y: block.y };
const blockTopRight: Position = { x: block.x + block.w, y: block.y };
const blockBottomLeft: Position = { x: block.x, y: block.y + block.h };
const blockBottomRight: Position = {
x: block.x + block.w,
y: block.y + block.h,
};
if (
IsIntersecting(
playerTopRight,
playerBottomRight,
blockTopLeft,
blockTopRight,
) &&
IsIntersecting(
playerBottomLeft,
playerBottomRight,
blockTopLeft,
blockBottomLeft,
)
) {
const dx = this.getDistanceX(playerBottomRight, blockTopLeft);
const dy = this.getDistanceY(playerBottomRight, blockTopLeft);
console.log('collision on top left corner of platform');
return dx < dy
? this.players.getMyself().touchRight(blockTopLeft.x)
: this.players.getMyself().touchBottom(blockTopLeft.y);
}
if (
IsIntersecting(
playerTopRight,
playerBottomRight,
blockBottomLeft,
blockBottomRight,
) &&
IsIntersecting(
playerTopLeft,
playerTopRight,
blockTopLeft,
blockBottomLeft,
)
) {
const dx = this.getDistanceX(playerTopRight, blockBottomLeft);
const dy = this.getDistanceY(playerTopRight, blockBottomLeft);
console.log('collision on bottom left corner of platform');
return dx < dy
? this.players.getMyself().touchRight(blockBottomLeft.x)
: this.players.getMyself().touchTop(blockBottomLeft.y);
}
if (
IsIntersecting(
playerTopLeft,
playerBottomLeft,
blockTopLeft,
blockTopRight,
) &&
IsIntersecting(
playerBottomLeft,
playerBottomRight,
blockTopRight,
blockBottomRight,
)
) {
const dx = this.getDistanceX(playerBottomLeft, blockTopRight);
const dy = this.getDistanceY(playerBottomLeft, blockTopRight);
console.log('collision on top right corner of platform');
return dx < dy
? this.players.getMyself().touchLeft(blockTopRight.x)
: this.players.getMyself().touchBottom(blockTopRight.y);
}
if (
IsIntersecting(
playerTopLeft,
playerBottomLeft,
blockBottomLeft,
blockBottomRight,
) &&
IsIntersecting(
playerTopLeft,
playerTopRight,
blockTopRight,
blockBottomRight,
)
) {
const dx = this.getDistanceX(playerTopLeft, blockBottomRight);
const dy = this.getDistanceY(playerTopLeft, blockBottomRight);
console.log('collision on bottom right corner of platform');
return dx < dy
? this.players.getMyself().touchLeft(blockBottomRight.x)
: this.players.getMyself().touchTop(blockBottomRight.y);
}
if (
IsIntersecting(
playerTopLeft,
playerTopRight,
blockTopLeft,
blockBottomLeft,
) &&
IsIntersecting(
playerBottomLeft,
playerBottomRight,
blockTopLeft,
blockBottomLeft,
)
) {
console.log(
'collision on left side of platform (platform bigger than player)',
);
return this.players.getMyself().touchRight(blockBottomLeft.x);
}
if (
IsIntersecting(
playerTopLeft,
playerTopRight,
blockTopRight,
blockBottomRight,
) &&
IsIntersecting(
playerBottomLeft,
playerBottomRight,
blockTopRight,
blockBottomRight,
)
) {
console.log(
'collision on right side of platform (platform bigger than player)',
);
return this.players.getMyself().touchLeft(blockBottomRight.x);
}
if (
IsIntersecting(
playerTopLeft,
playerBottomLeft,
blockBottomLeft,
blockBottomRight,
) &&
IsIntersecting(
playerTopRight,
playerBottomRight,
blockBottomLeft,
blockBottomRight,
)
) {
console.log(
'collision on bottom side of platform (platform bigger than player)',
);
return this.players.getMyself().touchTop(blockBottomLeft.y);
}
if (
IsIntersecting(
playerTopLeft,
playerBottomLeft,
blockTopLeft,
blockTopRight,
) &&
IsIntersecting(
playerTopRight,
playerBottomRight,
blockTopLeft,
blockTopRight,
)
) {
console.log(
'collision on top side of platform (platform bigger than player)',
);
return this.players.getMyself().touchBottom(blockTopLeft.y);
}
if (
IsIntersecting(
playerTopLeft,
playerBottomLeft,
blockTopLeft,
blockTopRight,
)
) {
console.log(
'collision on right side of platform (platform smaller than player)',
);
return this.players.getMyself().touchLeft(blockTopRight.x);
}
if (
IsIntersecting(
playerTopRight,
playerBottomRight,
blockTopLeft,
blockTopRight,
)
) {
console.log(
'collision on left side of platform (platform smaller than player)',
);
return this.players.getMyself().touchRight(blockTopLeft.x);
}
if (
IsIntersecting(
playerTopLeft,
playerTopRight,
blockTopLeft,
blockBottomLeft,
)
) {
console.log(
'collision on bottom side of platform (platform smaller than player)',
);
return this.players.getMyself().touchTop(blockBottomLeft.y);
}
if (
IsIntersecting(
playerBottomLeft,
playerBottomRight,
blockTopLeft,
blockBottomLeft,
)
) {
console.log(
'collision on top side of platform (platform smaller than player)',
);
return this.players.getMyself().touchBottom(blockTopLeft.y);
}
}
/* MAP BOUNDS */
if (
this.players.getMyself().getPosition().y >
this.globals.height - this.globals.playerSize.y
) {
this.players.getMyself().touchBottom(this.globals.height);
}
if (this.players.getMyself().getPosition().x < 0) {
this.players.getMyself().touchLeft(0);
}
if (
this.players.getMyself().getPosition().x >
this.globals.width - this.globals.playerSize.x
) {
this.players.getMyself().touchRight(this.globals.width);
}
}
updatePlayerPosition() {
if (!this.players.getMyself()) return;
this.detectCollisions();
if (
this.players.getMyself().getPosition().x !== this.myLastPosition.x ||
this.players.getMyself().getPosition().y !== this.myLastPosition.y
) {
this.socket.emit(
'updatedPosition',
this.players.getMyself().getPosition(),
);
this.myLastPosition = { ...this.players.getMyself().getPosition() };
}
}
getDistanceX(p1: Position, p2: Position): number {
return Math.abs(p1.x - p2.x);
}
getDistanceY(p1: Position, p2: Position): number {
return Math.abs(p1.y - p2.y);
}
drawPointer() {
if (!this.globals.socketId) return;
this.globals.context.strokeStyle = '#00ff0066';
this.globals.context.lineWidth = 5;
const angle = getAngleBetweenTwoPoints(
{
x:
this.players.getMyself().getPosition().x +
this.globals.playerSize.x / 2,
y:
this.players.getMyself().getPosition().y +
this.globals.playerSize.y / 2,
},
this.lastPointerPosition,
);
this.globals.context.beginPath();
this.globals.context.moveTo(
this.players.getMyself().getPosition().x + this.globals.playerSize.x / 2,
this.players.getMyself().getPosition().y + this.globals.playerSize.y / 2,
);
this.globals.context.lineTo(
this.players.getMyself().getPosition().x +
this.globals.playerSize.x / 2 +
getXFromAngle(angle) * this.getJumpPower() * 50,
this.players.getMyself().getPosition().y +
this.globals.playerSize.y / 2 +
getYFromAngle(angle) * this.getJumpPower() * 50,
);
this.globals.context.stroke();
}
gameLoop() {
this.globals.context.fillStyle = 'gray';
this.globals.context.drawImage(
this.globals.backgroudnImage,
0,
0,
this.globals.width,
this.globals.height,
);
drawMap(
this.globals.map,
this.globals.context,
this.globals.platformImages,
);
if (this.mapBuilder) {
drawMap(
this.builtMap,
this.globals.context,
this.globals.platformImages,
);
}
this.deltaTime.updateDeltaTime();
this.players.tick();
this.players.draw();
this.updatePlayerPosition();
this.drawPointer();
requestAnimationFrame(() => {
this.gameLoop();
});
}
}