Win checking
This commit is contained in:
parent
d2df62cdbe
commit
9c0aad2e75
|
|
@ -59,6 +59,14 @@ export default class Player extends Character {
|
||||||
return this.inventory.find(i => i.type === ItemType.WEAPON_ROCKET_LAUNCHER);
|
return this.inventory.find(i => i.type === ItemType.WEAPON_ROCKET_LAUNCHER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get keys() {
|
||||||
|
return this.inventory.find(i => i.type === ItemType.ITEM_KEYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
get fuel() {
|
||||||
|
return this.inventory.find(i => i.type === ItemType.ITEM_FUEL);
|
||||||
|
}
|
||||||
|
|
||||||
public heal(player: Player) {
|
public heal(player: Player) {
|
||||||
player.health += this.healingAmount;
|
player.health += this.healingAmount;
|
||||||
}
|
}
|
||||||
|
|
@ -77,11 +85,11 @@ export default class Player extends Character {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public hasItem(item: Item | null | undefined): boolean {
|
public hasItem(item: Item | ItemTypeImage | null | undefined): boolean {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const itemIndex = this.inventory.findIndex(i => i === item);
|
const itemIndex = this.inventory.findIndex(i => i === item || i.type === item);
|
||||||
|
|
||||||
return itemIndex >= 0;
|
return itemIndex >= 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import Entity from "./entity";
|
import Entity from "./entity";
|
||||||
import type Item from "./item";
|
import type Item from "./item";
|
||||||
|
import { ItemType } from "./item";
|
||||||
import planks from './assets/items/planks.jpg';
|
|
||||||
|
|
||||||
export enum TileType {
|
export enum TileType {
|
||||||
NORMAL,
|
NORMAL,
|
||||||
|
|
@ -69,7 +68,7 @@ export default class Tile extends Entity {
|
||||||
y += (Number(this.top < doorway.top) - Number(doorway.top < this.top)) * 0.5;
|
y += (Number(this.top < doorway.top) - Number(doorway.top < this.top)) * 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.drawImage(planks, x - 0.2, y - 0.2, 0.4, 0.4);
|
ctx.drawImage(ItemType.ITEM_PLANKS, x - 0.2, y - 0.2, 0.4, 0.4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,21 @@ export default class TileMap extends Entity {
|
||||||
private state = GameState.NORMAL;
|
private state = GameState.NORMAL;
|
||||||
private availableTiles: Tile[] = [];
|
private availableTiles: Tile[] = [];
|
||||||
|
|
||||||
|
public keysFound = false;
|
||||||
|
public fuelFound = false;
|
||||||
|
public bossKilled = false;
|
||||||
|
public readonly foundPlayers: Set<Player>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
position: [number, number],
|
position: [number, number],
|
||||||
private mapSize: number,
|
private mapSize: number,
|
||||||
private tileSize: number,
|
private tileSize: number,
|
||||||
private spinner: Spinner,
|
private spinner: Spinner,
|
||||||
numPlayers: number = 2,
|
numPlayers: number = 2,
|
||||||
) {
|
) {
|
||||||
super(position, [mapSize * tileSize, mapSize * tileSize]);
|
super(position, [mapSize * tileSize, mapSize * tileSize]);
|
||||||
this.players = shuffle(Object.values(Players)).slice(0, numPlayers);
|
this.players = shuffle(Object.values(Players)).slice(0, numPlayers);
|
||||||
|
this.foundPlayers = new Set(this.players);
|
||||||
this.startTile = this.createMap();
|
this.startTile = this.createMap();
|
||||||
this.findAvailableTiles();
|
this.findAvailableTiles();
|
||||||
}
|
}
|
||||||
|
|
@ -237,8 +243,10 @@ export default class TileMap extends Entity {
|
||||||
} else if (item instanceof Player) {
|
} else if (item instanceof Player) {
|
||||||
tile.removeItem(item);
|
tile.removeItem(item);
|
||||||
this.players.push(item);
|
this.players.push(item);
|
||||||
|
this.foundPlayers.add(item);
|
||||||
} else if (item.isBoss && this.player.removeItem(this.player.rocketLauncher)) {
|
} else if (item.isBoss && this.player.removeItem(this.player.rocketLauncher)) {
|
||||||
tile.killEnemy();
|
tile.killEnemy();
|
||||||
|
this.bossKilled = true;
|
||||||
} else if (item.isEnemy) {
|
} else if (item.isEnemy) {
|
||||||
this.state = GameState.FIGHT;
|
this.state = GameState.FIGHT;
|
||||||
break;
|
break;
|
||||||
|
|
@ -246,6 +254,14 @@ export default class TileMap extends Entity {
|
||||||
alert(`Unknown item found: ${item}`);
|
alert(`Unknown item found: ${item}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (tile.type === TileType.END) {
|
||||||
|
if (this.player.removeItem(this.player.fuel)) {
|
||||||
|
this.fuelFound = true;
|
||||||
|
}
|
||||||
|
if (this.player.removeItem(this.player.keys)) {
|
||||||
|
this.keysFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this.state === GameState.NORMAL) {
|
if (this.state === GameState.NORMAL) {
|
||||||
this.nextPlayer();
|
this.nextPlayer();
|
||||||
}
|
}
|
||||||
|
|
@ -325,6 +341,18 @@ export default class TileMap extends Entity {
|
||||||
private nextPlayer() {
|
private nextPlayer() {
|
||||||
this.spinner.stop();
|
this.spinner.stop();
|
||||||
this.currentPlayerIdx = (this.currentPlayerIdx + 1) % this.players.length;
|
this.currentPlayerIdx = (this.currentPlayerIdx + 1) % this.players.length;
|
||||||
|
if (this.win) {
|
||||||
|
const endTile = this.tiles.findLast(t => t.type === TileType.END);
|
||||||
|
if (endTile) {
|
||||||
|
for (const player of this.players) {
|
||||||
|
const path = Pathfinding.findPath(player.tile, endTile);
|
||||||
|
player.moveTo(endTile, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(alert, 2000, "🎉🎉🎉 ПОБЕДА! 🚗 🎉🎉🎉");
|
||||||
|
} else if (this.currentPlayerIdx === 0) {
|
||||||
|
// TODO zombies turn
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private killEnemy() {
|
private killEnemy() {
|
||||||
|
|
@ -339,6 +367,28 @@ export default class TileMap extends Entity {
|
||||||
this.setNormalState();
|
this.setNormalState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get win() {
|
||||||
|
if (!this.keysFound || !this.fuelFound || !this.bossKilled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const endTiles = this.tiles.filter(t => t.type === TileType.END);
|
||||||
|
for (const tile of endTiles) {
|
||||||
|
if (tile.items.length !== 0) return false;
|
||||||
|
}
|
||||||
|
for (const player of Object.values(Players)) {
|
||||||
|
if (!this.foundPlayers.has(player)) return false;
|
||||||
|
if (player.isDead) continue;
|
||||||
|
|
||||||
|
if (endTiles.every((tile) => {
|
||||||
|
const path = Pathfinding.findPath(player.tile, tile);
|
||||||
|
return path.length === 0;
|
||||||
|
})) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected draw(ctx: CanvasRenderingContext2D): void {
|
protected draw(ctx: CanvasRenderingContext2D): void {
|
||||||
ctx.scale(1 / this.width, 1 / this.height);
|
ctx.scale(1 / this.width, 1 / this.height);
|
||||||
|
|
||||||
|
|
@ -363,6 +413,46 @@ export default class TileMap extends Entity {
|
||||||
ctx.strokeStyle = 'yellow';
|
ctx.strokeStyle = 'yellow';
|
||||||
|
|
||||||
ctx.strokeRect(this.player.tile.centerX - w / 2, this.player.tile.centerY - w / 2, w, w);
|
ctx.strokeRect(this.player.tile.centerX - w / 2, this.player.tile.centerY - w / 2, w, w);
|
||||||
|
|
||||||
|
let x = this.width + this.tileSize / 2 + 10;
|
||||||
|
let y = this.height - this.tileSize / 2;
|
||||||
|
for (const player of Object.values(Players)) {
|
||||||
|
this.drawItem(ctx, player.type, x, y, w, this.foundPlayers.has(player));
|
||||||
|
x += this.tileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = this.width + this.tileSize / 2 + 10;
|
||||||
|
y = this.height - 3 * this.tileSize / 2;
|
||||||
|
for (const [item, found] of zip(
|
||||||
|
[ItemType.ITEM_KEYS, ItemType.ITEM_FUEL, ItemType.ENEMY_BOSS],
|
||||||
|
[this.keysFound, this.fuelFound, this.bossKilled],
|
||||||
|
)) {
|
||||||
|
this.drawItem(ctx, item, x, y, w, found);
|
||||||
|
x += this.tileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = this.width + this.tileSize / 2 + 10;
|
||||||
|
y = this.height - 5 * this.tileSize / 2;
|
||||||
|
for (const tile of this.tiles) {
|
||||||
|
if (tile.type !== TileType.END) continue;
|
||||||
|
|
||||||
|
this.drawItem(ctx, ItemType.ENEMY_ZOMBIE, x, y, w, tile.items.length === 0);
|
||||||
|
x += this.tileSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private drawItem(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
img: HTMLImageElement,
|
||||||
|
x: number, y: number, w: number,
|
||||||
|
found: boolean,
|
||||||
|
) {
|
||||||
|
ctx.drawImage(img, x - w / 2, y - w / 2, w, w);
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
ctx.fillStyle = `rgba(255, 255, 255, 0.6)`;
|
||||||
|
ctx.fillRect(x - w / 2, y - w / 2, w, w);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(dt: number) {
|
public update(dt: number) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue