survivors: adding health enemies dropping health packs

This commit is contained in:
Sheldan
2025-08-21 18:36:31 +02:00
parent 71f48404c9
commit 8ca64a19b7
5 changed files with 123 additions and 33 deletions

View File

@@ -4,7 +4,7 @@ import {Vector} from "./base.ts";
import {World} from "./World.ts"; import {World} from "./World.ts";
import type {Projectile} from "./projectile.ts"; import type {Projectile} from "./projectile.ts";
import {HomingProjectile, ProjectileStats, StraightProjectile} from "./projectile.ts"; import {HomingProjectile, ProjectileStats, StraightProjectile} from "./projectile.ts";
import {MoneyDrop} from "./drop.ts"; import {HealthPack, MoneyDrop} from "./drop.ts";
export abstract class Enemy implements Placeable, Drawable, Acting, Healthy { export abstract class Enemy implements Placeable, Drawable, Acting, Healthy {
protected _position: Vector; protected _position: Vector;
@@ -131,7 +131,7 @@ export class ShootingEnemy extends BasicEnemy implements Shooting {
static generateShootingEnemy(world: World, position?: Vector) { static generateShootingEnemy(world: World, position?: Vector) {
if(position === undefined) { if(position === undefined) {
position = new Vector(250, 250) position = world.randomPlace()
} }
let basicEnemy = new ShootingEnemy(position); let basicEnemy = new ShootingEnemy(position);
basicEnemy.size = 5; basicEnemy.size = 5;
@@ -160,4 +160,47 @@ export class EnemyStatus {
set health(value: number) { set health(value: number) {
this._health = value; this._health = value;
} }
}
export class HealthEnemy extends Enemy {
constructor(position: Vector) {
super(position);
}
protected size: number;
protected color: string;
draw(ctx: CanvasRenderingContext2D) {
drawDot(this._position, this.size, this.color, ctx)
}
move() {
}
act() {
super.act();
}
die() {
HealthPack.createHealthPack(this.world, this._position)
}
static createHealthEnemy(world: World, position?: Vector) {
if(position === undefined) {
position = world.randomPlace()
}
let basicEnemy = new HealthEnemy(position);
basicEnemy.size = 5;
basicEnemy.world = world;
basicEnemy.speed = 0;
basicEnemy.color = 'purple'
return basicEnemy;
}
getSize() {
return this.size
}
} }

View File

@@ -43,6 +43,11 @@ export class Player implements Drawable, Acting, Healthy {
this._status.health -= damage; this._status.health -= damage;
} }
heal(amount: number) {
this._status.health += amount;
this._status.health = Math.min(this._status.health, this._stats.health)
}
get health(): number { get health(): number {
return this._status.health; return this._status.health;
} }

View File

@@ -3,27 +3,17 @@ import {World} from "./World.ts";
import {drawDot, moveInDirectionOf} from "./utils.ts"; import {drawDot, moveInDirectionOf} from "./utils.ts";
import {Vector} from "./base.ts"; import {Vector} from "./base.ts";
export class MoneyDrop implements Drop { export abstract class BasicDrop implements Drop {
private world: World; protected world: World;
private worth: number; protected _position: Vector;
private _position: Vector; protected _color: string;
private _color: string; protected _size: number;
private _size: number;
constructor(world: World, position: Vector) { constructor(world: World, position: Vector) {
this.world = world; this.world = world;
this._position = position.clone(); this._position = position.clone();
} }
draw(ctx: CanvasRenderingContext2D) {
drawDot(this._position, this.getSize(), this._color, ctx)
}
pickup() {
this.world.player.status.wealth += this.worth
}
getPosition(): Vector { getPosition(): Vector {
return this._position; return this._position;
} }
@@ -31,6 +21,41 @@ export class MoneyDrop implements Drop {
move() { move() {
} }
pickup() {
}
act() {
let distanceToPlayer = this._position.distanceTo(this.world.player.position);
if(distanceToPlayer < (this.world.player.stats.size + this._size)) {
this.pickup()
this.world.removeDrop(this)
} else if(distanceToPlayer < this.world.player.stats.pullRange) {
let speedFactor = 125 / distanceToPlayer;
this._position = moveInDirectionOf(this._position, this.world.player.position, speedFactor)
}
}
getSize() {
return this._size
}
abstract draw(ctx: CanvasRenderingContext2D);
}
export class MoneyDrop extends BasicDrop {
private worth: number;
draw(ctx: CanvasRenderingContext2D) {
drawDot(this._position, this.getSize(), this._color, ctx)
}
pickup() {
this.world.player.status.wealth += this.worth
}
static createMoneyDrop(world: World, position?: Vector): MoneyDrop { static createMoneyDrop(world: World, position?: Vector): MoneyDrop {
if(!position) { if(!position) {
position = world.randomPlace() position = world.randomPlace()
@@ -43,19 +68,29 @@ export class MoneyDrop implements Drop {
return drop; return drop;
} }
act() {
let distanceToPlayer = this._position.distanceTo(this.world.player.position); }
if(distanceToPlayer < (this.world.player.stats.size + this._size)) {
this.pickup() export class HealthPack extends BasicDrop {
this.world.removeDrop(this) private healAmount: number;
} else if(distanceToPlayer < this.world.player.stats.pullRange) {
let speedFactor = 125 / distanceToPlayer; draw(ctx: CanvasRenderingContext2D) {
this._position = moveInDirectionOf(this._position, this.world.player.position, speedFactor) drawDot(this._position, this.getSize(), this._color, ctx)
}
pickup() {
this.world.player.heal(this.healAmount)
}
static createHealthPack(world: World, position?: Vector): HealthPack {
if(!position) {
position = world.randomPlace()
} }
let drop = new HealthPack(world, position)
drop.healAmount = 5;
drop._size = 2;
drop._color = 'green';
world.addDrop(drop)
return drop;
} }
getSize() {
return this._size
}
} }

View File

@@ -4,7 +4,7 @@ import {docReady} from "canvas-common";
import {World} from "./World.ts"; import {World} from "./World.ts";
import {Player} from "./Player.ts"; import {Player} from "./Player.ts";
import {Vector} from "./base.ts"; import {Vector} from "./base.ts";
import {BasicEnemy, Enemy, ShootingEnemy} from "./Enemies.ts"; import {BasicEnemy, Enemy, HealthEnemy, ShootingEnemy} from "./Enemies.ts";
import {HUD} from "./ui.ts"; import {HUD} from "./ui.ts";
import {Pistol} from "./weapons.ts"; import {Pistol} from "./weapons.ts";
@@ -110,8 +110,13 @@ docReady(function () {
world.addEnemy(BasicEnemy.generateBasicEnemy(world)) world.addEnemy(BasicEnemy.generateBasicEnemy(world))
world.addEnemy(ShootingEnemy.generateShootingEnemy(world, new Vector(350, 350))) world.addEnemy(ShootingEnemy.generateShootingEnemy(world, new Vector(350, 350)))
setInterval(() => { setInterval(() => {
world.addEnemy(ShootingEnemy.generateShootingEnemy(world, new Vector(Math.random() * world.size.x, Math.random() * world.size.y))) world.addEnemy(ShootingEnemy.generateShootingEnemy(world))
}, 1000) }, 1_000)
setInterval(() => {
world.addEnemy(HealthEnemy.createHealthEnemy(world))
}, 15_000)
player.addWeapon(Pistol.spawnPistol(world)) player.addWeapon(Pistol.spawnPistol(world))
let secondPistol = Pistol.spawnPistol(world, new Vector(-5, -5)); let secondPistol = Pistol.spawnPistol(world, new Vector(-5, -5));
player.addWeapon(secondPistol) player.addWeapon(secondPistol)

View File

@@ -43,6 +43,8 @@ export abstract class Projectile implements Acting, Placeable {
this.world.removeProjectile(this) this.world.removeProjectile(this)
} }
this.status.decreasePiercings() this.status.decreasePiercings()
} else {
this.world.removeProjectile(this)
} }
} }
} }