mirror of
https://github.com/Sheldan/canvas.git
synced 2026-01-01 14:58:51 +00:00
survivors: adding simple drops
moving size to world object adding dying for enemies and projectiles and theoretically for players adding pull range for player adding money stat display made pistol homing
This commit is contained in:
@@ -1,18 +1,19 @@
|
||||
import type {Acting, Drawable, Healthy, Moving, Shooting} from "./interfaces.ts";
|
||||
import type {Acting, Drawable, Healthy, Placeable, Shooting} from "./interfaces.ts";
|
||||
import {drawDot, moveInDirectionOf} from "./utils.ts";
|
||||
import {Vector} from "./base.ts";
|
||||
import {World} from "./World.ts";
|
||||
import type {Projectile} from "./projectile.ts";
|
||||
import {HomingProjectile, StraightProjectile} from "./projectile.ts";
|
||||
import {HomingProjectile, ProjectileStats, StraightProjectile} from "./projectile.ts";
|
||||
import {MoneyDrop} from "./drop.ts";
|
||||
|
||||
export abstract class Enemy implements Moving, Drawable, Acting, Healthy {
|
||||
export abstract class Enemy implements Placeable, Drawable, Acting, Healthy {
|
||||
protected _position: Vector;
|
||||
protected speed: number;
|
||||
protected world: World;
|
||||
protected status: EnemyStatus = new EnemyStatus(10);
|
||||
|
||||
constructor(position: Vector) {
|
||||
this._position = position;
|
||||
this._position = position.clone();
|
||||
}
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D) {
|
||||
@@ -33,9 +34,22 @@ export abstract class Enemy implements Moving, Drawable, Acting, Healthy {
|
||||
takeDamage(damage: number) {
|
||||
this.status.health -= damage;
|
||||
if(this.status.dead) {
|
||||
this.die()
|
||||
this.world.removeEnemy(this)
|
||||
}
|
||||
}
|
||||
|
||||
die() {
|
||||
MoneyDrop.createMoneyDrop(this.world, this._position);
|
||||
}
|
||||
|
||||
getSize() {
|
||||
}
|
||||
|
||||
dead() {
|
||||
return this.status.dead
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class BasicEnemy extends Enemy {
|
||||
@@ -80,6 +94,10 @@ export class BasicEnemy extends Enemy {
|
||||
basicEnemy.impactDamage = 2;
|
||||
return basicEnemy;
|
||||
}
|
||||
|
||||
getSize() {
|
||||
return this.size
|
||||
}
|
||||
}
|
||||
|
||||
export class ShootingEnemy extends BasicEnemy implements Shooting {
|
||||
@@ -105,7 +123,8 @@ export class ShootingEnemy extends BasicEnemy implements Shooting {
|
||||
}
|
||||
|
||||
createProjectile() {
|
||||
let projectile = StraightProjectile.createStraightProjectile(this.world, this._position, this.world.player.position, this)
|
||||
let stats = new ProjectileStats(0, 1, 5)
|
||||
let projectile = StraightProjectile.createStraightProjectile(this.world, this._position, this.world.player.position, this, stats)
|
||||
this.projectiles.push(projectile)
|
||||
return projectile
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export class Player implements Drawable, Acting, Healthy {
|
||||
player._color = 'blue';
|
||||
player._stats = Stats.defaultPlayerStats();
|
||||
player._speed = new Vector(0, 0)
|
||||
player._status = new Status(10);
|
||||
player._status = new Status(10, 0);
|
||||
return player;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,10 @@ export class Player implements Drawable, Acting, Healthy {
|
||||
return this._stats;
|
||||
}
|
||||
|
||||
get status(): Status {
|
||||
return this._status;
|
||||
}
|
||||
|
||||
get speed(): Vector {
|
||||
return this._speed;
|
||||
}
|
||||
@@ -66,27 +70,53 @@ export class Player implements Drawable, Acting, Healthy {
|
||||
act() {
|
||||
this._weapons.forEach(weapon => weapon.act())
|
||||
}
|
||||
|
||||
die() {
|
||||
}
|
||||
|
||||
getPosition(): Vector {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
getSize() {
|
||||
return this.stats.size
|
||||
}
|
||||
|
||||
dead() {
|
||||
return this.status.dead
|
||||
}
|
||||
}
|
||||
|
||||
export class Status {
|
||||
constructor(private _health: number) {
|
||||
constructor(private _health: number, private _wealth: number) {
|
||||
}
|
||||
|
||||
|
||||
get health(): number {
|
||||
return this._health;
|
||||
}
|
||||
|
||||
|
||||
set health(value: number) {
|
||||
this._health = value;
|
||||
}
|
||||
|
||||
get dead(): boolean {
|
||||
return this._health <= 0
|
||||
}
|
||||
|
||||
get wealth(): number {
|
||||
return this._wealth;
|
||||
}
|
||||
|
||||
set wealth(value: number) {
|
||||
this._wealth = value;
|
||||
}
|
||||
}
|
||||
|
||||
export class Stats {
|
||||
constructor(private _speed: number,
|
||||
private _size: number,
|
||||
private _health: number) {
|
||||
private _health: number,
|
||||
private _pullRange: number) {
|
||||
}
|
||||
|
||||
get speed(): number {
|
||||
@@ -105,12 +135,15 @@ export class Stats {
|
||||
this._size = value;
|
||||
}
|
||||
|
||||
get pullRange(): number {
|
||||
return this._pullRange;
|
||||
}
|
||||
|
||||
get health(): number {
|
||||
return this._health;
|
||||
}
|
||||
|
||||
public static defaultPlayerStats(): Stats {
|
||||
return new Stats(2, 5, 10);
|
||||
return new Stats(3, 5, 10, 150);
|
||||
}
|
||||
}
|
||||
@@ -3,27 +3,31 @@ import type {Player} from "./Player.ts";
|
||||
import {Player} from "./Player.ts";
|
||||
import {Projectile} from "./projectile.ts";
|
||||
import {Vector} from "./base.ts";
|
||||
import type {Moving} from "./interfaces.ts";
|
||||
import type {Drop, Placeable} from "./interfaces.ts";
|
||||
|
||||
export class World {
|
||||
private _enemies: [Enemy] = [];
|
||||
private _projectiles: [Projectile] = [];
|
||||
private _drops: [Drop] = [];
|
||||
private _player: Player;
|
||||
private _ctx: CanvasRenderingContext2D;
|
||||
private _size: Vector
|
||||
|
||||
|
||||
constructor(player: Player, ctx: CanvasRenderingContext2D) {
|
||||
constructor(player: Player, ctx: CanvasRenderingContext2D, size: Vector) {
|
||||
this._player = player;
|
||||
this._ctx = ctx;
|
||||
this._size = size;
|
||||
}
|
||||
|
||||
enemiesAct() {
|
||||
this._enemies.forEach(enemy => enemy.act())
|
||||
this._projectiles.forEach(projectile => projectile.act())
|
||||
this._drops.forEach(drop => drop.act())
|
||||
}
|
||||
|
||||
draw() {
|
||||
this._enemies.forEach(enemy => enemy.draw(this._ctx))
|
||||
this._drops.forEach(drop => drop.draw(this._ctx))
|
||||
this._projectiles.forEach(projectile => projectile.draw(this._ctx))
|
||||
this._player.draw(this._ctx);
|
||||
}
|
||||
@@ -32,6 +36,14 @@ export class World {
|
||||
this._projectiles.push(projectile)
|
||||
}
|
||||
|
||||
addDrop(drop: Drop) {
|
||||
this._drops.push(drop)
|
||||
}
|
||||
|
||||
removeDrop(drop: Drop) {
|
||||
this._drops = this._drops.filter(item => item !== drop)
|
||||
}
|
||||
|
||||
removeProjectile(projectile: Projectile) {
|
||||
this._projectiles = this._projectiles.filter(item => item !== projectile)
|
||||
}
|
||||
@@ -45,11 +57,20 @@ export class World {
|
||||
return this._enemies;
|
||||
}
|
||||
|
||||
|
||||
get size(): Vector {
|
||||
return this._size;
|
||||
}
|
||||
|
||||
addEnemy(enemy: Enemy) {
|
||||
this._enemies.push(enemy)
|
||||
}
|
||||
|
||||
getClosestTargetTo(point: Vector): [number, Moving | undefined] | undefined {
|
||||
randomPlace(): Vector {
|
||||
return new Vector(this.size.x * Math.random(), this.size.y * Math.random())
|
||||
}
|
||||
|
||||
getClosestTargetTo(point: Vector): [number, Placeable | undefined] | undefined {
|
||||
let currentTarget;
|
||||
let currentDistance = Number.MAX_SAFE_INTEGER;
|
||||
this._enemies.forEach(enemy => {
|
||||
|
||||
@@ -16,6 +16,10 @@ export class Vector {
|
||||
return Math.sqrt(this.x * this.x + this.y * this.y);
|
||||
}
|
||||
|
||||
clone() {
|
||||
return new Vector(this.x, this.y)
|
||||
}
|
||||
|
||||
distanceTo(point: Vector): number {
|
||||
return Math.sqrt(Math.pow(this.x - point.x, 2) + Math.pow(this.y - point.y, 2));
|
||||
}
|
||||
@@ -56,4 +60,31 @@ export class Vector {
|
||||
set y(value: number) {
|
||||
this._y = value;
|
||||
}
|
||||
}
|
||||
|
||||
export class Cooldown {
|
||||
private _currentValue;
|
||||
private _totalValue;
|
||||
|
||||
|
||||
constructor(totalValue) {
|
||||
this._totalValue = totalValue;
|
||||
this._currentValue = 0
|
||||
}
|
||||
|
||||
cooledDown(): boolean {
|
||||
return this.currentValue <= 0;
|
||||
}
|
||||
|
||||
get currentValue(): number {
|
||||
return this._currentValue;
|
||||
}
|
||||
|
||||
decreaseCooldown() {
|
||||
this._currentValue -= 1;
|
||||
}
|
||||
|
||||
resetCooldown() {
|
||||
this._currentValue = this._totalValue;
|
||||
}
|
||||
}
|
||||
61
absurd-survivors/src/drop.ts
Normal file
61
absurd-survivors/src/drop.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import type {Drop} from "./interfaces.ts";
|
||||
import {World} from "./World.ts";
|
||||
import {drawDot, moveInDirectionOf} from "./utils.ts";
|
||||
import {Vector} from "./base.ts";
|
||||
|
||||
export class MoneyDrop implements Drop {
|
||||
private world: World;
|
||||
private worth: number;
|
||||
private _position: Vector;
|
||||
private _color: string;
|
||||
private _size: number;
|
||||
|
||||
|
||||
constructor(world: World, position: Vector) {
|
||||
this.world = world;
|
||||
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 {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
move() {
|
||||
}
|
||||
|
||||
static createMoneyDrop(world: World, position?: Vector): MoneyDrop {
|
||||
if(!position) {
|
||||
position = world.randomPlace()
|
||||
}
|
||||
let drop = new MoneyDrop(world, position)
|
||||
drop.worth = 1;
|
||||
drop._size = 1;
|
||||
drop._color = 'yellow';
|
||||
world.addDrop(drop)
|
||||
return drop;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,10 +6,17 @@ export interface Acting {
|
||||
|
||||
export interface Healthy {
|
||||
takeDamage(damage: number);
|
||||
die();
|
||||
dead();
|
||||
}
|
||||
|
||||
export interface Moving {
|
||||
move()
|
||||
export interface Drop extends Drawable, Acting {
|
||||
pickup()
|
||||
}
|
||||
|
||||
export interface Placeable {
|
||||
move(any?: any)
|
||||
getSize();
|
||||
getPosition(): Vector;
|
||||
}
|
||||
|
||||
@@ -26,6 +33,10 @@ export interface Shooting {
|
||||
removeProjectile(projectile: Projectile)
|
||||
}
|
||||
|
||||
export interface Drawable {
|
||||
export interface Drawable extends Placeable {
|
||||
draw(ctx: CanvasRenderingContext2D);
|
||||
}
|
||||
|
||||
export interface DrawContainer {
|
||||
draw(ctx: CanvasRenderingContext2D);
|
||||
}
|
||||
@@ -17,14 +17,8 @@ let ctx: CanvasRenderingContext2D;
|
||||
let canvas;
|
||||
|
||||
export class Config {
|
||||
private _size: Vector = new Vector(window.innerWidth, window.innerHeight)
|
||||
private _fps: number = 60;
|
||||
|
||||
|
||||
get size(): Vector {
|
||||
return this._size;
|
||||
}
|
||||
|
||||
get fps(): number {
|
||||
return this._fps;
|
||||
}
|
||||
@@ -41,7 +35,7 @@ export class WorldState {
|
||||
|
||||
|
||||
function updateCanvas() {
|
||||
ctx.clearRect(0, 0, config.size.x, config.size.y);
|
||||
ctx.clearRect(0, 0, world.size.x, world.size.y);
|
||||
hud.draw(ctx)
|
||||
if(!state.ended) {
|
||||
world.enemiesAct()
|
||||
@@ -101,23 +95,22 @@ document.onkeydown = keyDown;
|
||||
docReady(function () {
|
||||
canvas = document.getElementById('canvas');
|
||||
|
||||
config = new Config();
|
||||
canvas.width = config.size.x;
|
||||
canvas.width = window.innerWidth;
|
||||
|
||||
canvas.height = config.size.y;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
|
||||
ctx = canvas.getContext("2d");
|
||||
|
||||
config = new Config();
|
||||
let player = Player.generatePlayer();
|
||||
|
||||
world = new World(player, ctx);
|
||||
world = new World(player, ctx, new Vector(window.innerWidth, window.innerHeight));
|
||||
state = new WorldState();
|
||||
|
||||
world.addEnemy(BasicEnemy.generateBasicEnemy(world))
|
||||
world.addEnemy(ShootingEnemy.generateShootingEnemy(world, new Vector(350, 350)))
|
||||
setInterval(() => {
|
||||
world.addEnemy(ShootingEnemy.generateShootingEnemy(world, new Vector(Math.random() * config.size.x, Math.random() * config.size.y)))
|
||||
world.addEnemy(ShootingEnemy.generateShootingEnemy(world, new Vector(Math.random() * world.size.x, Math.random() * world.size.y)))
|
||||
}, 1000)
|
||||
player.addWeapon(Pistol.spawnPistol(world))
|
||||
let secondPistol = Pistol.spawnPistol(world, new Vector(-5, -5));
|
||||
|
||||
@@ -1,55 +1,63 @@
|
||||
import type {Acting, Moving, Healthy} from "./interfaces.ts";
|
||||
import type {Acting, Placeable, Healthy} from "./interfaces.ts";
|
||||
import type {Vector} from "./base.ts";
|
||||
import {World} from "./World.ts";
|
||||
import {Vector} from "./base.ts";
|
||||
import {Cooldown, Vector} from "./base.ts";
|
||||
import {drawDot, moveInDirectionOf, straightMove} from "./utils.ts";
|
||||
import {InstanceOfUtils} from "./instance.ts";
|
||||
|
||||
export abstract class Projectile implements Acting, Moving {
|
||||
export abstract class Projectile implements Acting, Placeable {
|
||||
|
||||
protected position: Vector;
|
||||
protected speedVec: Vector;
|
||||
protected impact: number;
|
||||
protected world: World;
|
||||
protected size: number;
|
||||
protected parent: any;
|
||||
protected color: string
|
||||
private stats: ProjectileStats;
|
||||
private status: ProjectileStatus;
|
||||
|
||||
|
||||
constructor(position: Vector, speedVec: Vector, world: World, parent: any) {
|
||||
this.position = position;
|
||||
this.speedVec = speedVec;
|
||||
constructor(position: Vector, speedVec: Vector, stats: ProjectileStats, world: World, parent: any) {
|
||||
this.position = position.clone();
|
||||
this.speedVec = speedVec.clone();
|
||||
this.world = world;
|
||||
this.parent = parent;
|
||||
this.stats = stats;
|
||||
this.status = new ProjectileStatus(stats.piercings)
|
||||
}
|
||||
|
||||
act() {
|
||||
this.move()
|
||||
if(this.parent != this.world.player) {
|
||||
if(this.position.distanceTo(this.world.player.position) < (this.size + this.world.player.stats.size)) {
|
||||
this.impactPlayer()
|
||||
}
|
||||
}
|
||||
if(this.parent == this.world.player) {
|
||||
let closestTargetTo = this.world.getClosestTargetTo(this.position);
|
||||
if(closestTargetTo !== undefined && closestTargetTo[1] !== undefined && closestTargetTo[1]?.getPosition().distanceTo(this.position) < (this.size + this.world.player.stats.size)) {
|
||||
let target: Moving = closestTargetTo[1]!;
|
||||
if(InstanceOfUtils.instanceOfHealthy(target)) {
|
||||
let healthy = target as Healthy;
|
||||
healthy.takeDamage(this.impact)
|
||||
if(this.status.collisionCooldown.cooledDown()) {
|
||||
if(this.parent !== this.world.player) {
|
||||
if(this.position.distanceTo(this.world.player.position) < (this.stats.size + this.world.player.stats.size)) {
|
||||
this.impactPlayer()
|
||||
this.status.collisionCooldown.resetCooldown()
|
||||
}
|
||||
} else if(this.parent === this.world.player) {
|
||||
let closestTargetTo = this.world.getClosestTargetTo(this.position);
|
||||
if(closestTargetTo !== undefined && closestTargetTo[1] !== undefined && closestTargetTo[1]?.getPosition().distanceTo(this.position) < (this.stats.size + closestTargetTo[1]?.getSize())) {
|
||||
let target: Placeable = closestTargetTo[1]!;
|
||||
if(InstanceOfUtils.instanceOfHealthy(target)) {
|
||||
let healthy = target as Healthy;
|
||||
healthy.takeDamage(this.stats.damage)
|
||||
if(this.status.piercingsLeft <= 0) {
|
||||
this.world.removeProjectile(this)
|
||||
}
|
||||
this.status.decreasePiercings()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.status.collisionCooldown.decreaseCooldown();
|
||||
|
||||
}
|
||||
|
||||
impactPlayer() {
|
||||
this.world.player.takeDamage(this.impact)
|
||||
this.world.player.takeDamage(this.stats.damage)
|
||||
this.world.removeProjectile(this)
|
||||
};
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D) {
|
||||
drawDot(this.position, this.size, this.color, ctx)
|
||||
drawDot(this.position, this.stats.size, this.color, ctx)
|
||||
}
|
||||
|
||||
move() {
|
||||
@@ -59,24 +67,27 @@ export abstract class Projectile implements Acting, Moving {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
getSize() {
|
||||
return this.stats.size
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class StraightProjectile extends Projectile {
|
||||
|
||||
|
||||
constructor(position: Vector, dirVector: Vector, world: World, parent: any) {
|
||||
super(position, dirVector, world, parent);
|
||||
constructor(position: Vector, dirVector: Vector, stats: ProjectileStats, world: World, parent: any) {
|
||||
super(position, dirVector, stats, world, parent);
|
||||
}
|
||||
|
||||
move() {
|
||||
this.position = straightMove(this.position, this.speedVec)
|
||||
}
|
||||
|
||||
static createStraightProjectile(world: World, start: Vector, targetPosition: Vector, parent: any) {
|
||||
let projectile = new StraightProjectile(start, Vector.createVector(targetPosition, start).normalize().multiply(5), world, parent)
|
||||
projectile.impact = 1;
|
||||
projectile.size = 1
|
||||
projectile.color = 'red';
|
||||
static createStraightProjectile(world: World, start: Vector, targetPosition: Vector, parent: any, stats: ProjectileStats, color?: string) {
|
||||
let dirVector = Vector.createVector(targetPosition, start).normalize().multiply(2);
|
||||
let projectile = new StraightProjectile(start, dirVector, stats, world, parent)
|
||||
projectile.color = color === undefined ? 'red' : color!;
|
||||
world.addProjectile(projectile)
|
||||
return projectile;
|
||||
}
|
||||
@@ -84,17 +95,86 @@ export class StraightProjectile extends Projectile {
|
||||
|
||||
export class HomingProjectile extends Projectile {
|
||||
|
||||
move() {
|
||||
this.position = moveInDirectionOf(this.position, this.world.player.position, this.speedVec.vecLength())
|
||||
private target: Placeable;
|
||||
|
||||
|
||||
constructor(position: Vector, speedVec: Vector, stats: ProjectileStats, world: World, parent: any, target: Placeable) {
|
||||
super(position, speedVec, stats, world, parent);
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
static createHomingProjectile(world: World, start: Vector, parent: any) {
|
||||
let projectile = new HomingProjectile(start, new Vector(5, 1), world, parent)
|
||||
projectile.impact = 1;
|
||||
projectile.size = 1
|
||||
projectile.color = 'red';
|
||||
move() {
|
||||
if(InstanceOfUtils.instanceOfHealthy(this.target)) {
|
||||
let target = this.target as Healthy
|
||||
if(target.dead()) {
|
||||
if(this.position.distanceTo(this.target.getPosition()) < (this.target.getSize() + this.getSize())) {
|
||||
this.world.removeProjectile(this)
|
||||
return;
|
||||
}
|
||||
let closestTargetTo = this.world.getClosestTargetTo(this.world.player.position)
|
||||
if (closestTargetTo !== undefined && closestTargetTo[1] !== undefined) {
|
||||
this.target = closestTargetTo[1]!;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.position = moveInDirectionOf(this.position, this.target.getPosition(), this.speedVec.vecLength())
|
||||
}
|
||||
|
||||
static createHomingProjectile(world: World, start: Vector, parent: any, target: Placeable, stats: ProjectileStats, color?: string) {
|
||||
|
||||
let projectile = new HomingProjectile(start, new Vector(5, 1), stats, world, parent, target)
|
||||
projectile.color = color === undefined ? 'red' : color!;
|
||||
world.addProjectile(projectile)
|
||||
return projectile;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class ProjectileStatus {
|
||||
private _piercingsLeft: number;
|
||||
private _collisionCooldown: Cooldown;
|
||||
|
||||
constructor(piercingsLeft: number) {
|
||||
this._piercingsLeft = piercingsLeft;
|
||||
this._collisionCooldown = new Cooldown(10)
|
||||
}
|
||||
|
||||
get piercingsLeft(): number {
|
||||
return this._piercingsLeft;
|
||||
}
|
||||
|
||||
|
||||
get collisionCooldown(): Cooldown {
|
||||
return this._collisionCooldown;
|
||||
}
|
||||
|
||||
decreasePiercings() {
|
||||
this._piercingsLeft -= 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class ProjectileStats {
|
||||
private _piercings: number;
|
||||
private _size: number;
|
||||
private _damage: number;
|
||||
|
||||
constructor(piercings: number, size: number, damage: number) {
|
||||
this._piercings = piercings;
|
||||
this._size = size;
|
||||
this._damage = damage
|
||||
}
|
||||
|
||||
get piercings(): number {
|
||||
return this._piercings;
|
||||
}
|
||||
|
||||
get size(): number {
|
||||
return this._size;
|
||||
}
|
||||
|
||||
|
||||
get damage(): number {
|
||||
return this._damage;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
import type {World} from "./World.ts";
|
||||
import type {Drawable} from "./interfaces.ts";
|
||||
import type {Drawable, DrawContainer} from "./interfaces.ts";
|
||||
import {World} from "./World.ts";
|
||||
import type {Vector} from "./base.ts";
|
||||
import {Vector} from "./base.ts";
|
||||
|
||||
export class HUD implements Drawable{
|
||||
export class HUD implements DrawContainer {
|
||||
private health: HealthInfo;
|
||||
private world: World;
|
||||
|
||||
@@ -18,21 +16,59 @@ export class HUD implements Drawable{
|
||||
this.health.draw(ctx)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export class HealthInfo implements Drawable{
|
||||
export class HealthInfo implements DrawContainer {
|
||||
private bar: InfoBar;
|
||||
private statLabels: [StatLabel] = []
|
||||
private world: World;
|
||||
|
||||
constructor(world: World) {
|
||||
this.world = world;
|
||||
this.bar = new InfoBar(new Vector(0, 50), 50, 150, () => 'Health', () => this.world.player.health, () => this.world.player.stats.health)
|
||||
this.bar = new InfoBar(new Vector(0, 50), 50, 150, () => 'Health', () => this.world.player.status.health, () => this.world.player.stats.health)
|
||||
this.statLabels = [
|
||||
new StatLabel(new Vector(0, 150), () => 'Money', () => this.world.player.status.wealth)
|
||||
]
|
||||
}
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D) {
|
||||
this.bar.draw(ctx)
|
||||
this.statLabels.forEach(label => label.draw(ctx))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class StatLabel implements Drawable {
|
||||
private position: Vector;
|
||||
private borderColor: string = 'white';
|
||||
private textLambda: () => string;
|
||||
private valueLambda: () => number;
|
||||
|
||||
|
||||
constructor(position: Vector, textLambda: () => string, valueLambda: () => number) {
|
||||
this.position = position;
|
||||
this.textLambda = textLambda;
|
||||
this.valueLambda = valueLambda;
|
||||
}
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D) {
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = this.borderColor
|
||||
let value = this.valueLambda();
|
||||
ctx.fillText(`${value}`, this.position.x, this.position.y)
|
||||
ctx.fill()
|
||||
}
|
||||
|
||||
getPosition(): Vector {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
move(any?: any) {
|
||||
}
|
||||
|
||||
getSize() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class InfoBar implements Drawable {
|
||||
@@ -40,7 +76,7 @@ export class InfoBar implements Drawable {
|
||||
private height: number;
|
||||
private width: number;
|
||||
private fillColor: string = 'green';
|
||||
private borderColor: string = 'black';
|
||||
private borderColor: string = 'white';
|
||||
private textLambda: () => string;
|
||||
private valueLambda: () => number;
|
||||
private totalValueLambda: () => number;
|
||||
@@ -69,4 +105,14 @@ export class InfoBar implements Drawable {
|
||||
ctx.fill()
|
||||
}
|
||||
|
||||
getPosition(): Vector {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
move(any?: any) {
|
||||
}
|
||||
|
||||
getSize() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,7 @@ export function drawDot(position: Vector, size: number, color: string, ctx: Canv
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
export function moveInDirectionOf(position: Vector, target: Vector, speedFactor): Vector {
|
||||
export function moveInDirectionOf(position: Vector, target: Vector, speedFactor: number): Vector {
|
||||
let playerVector = Vector.createVector(target, position);
|
||||
let direction = playerVector.normalize()
|
||||
return position.add(direction.multiply(speedFactor))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type {Weapon} from "./interfaces.ts";
|
||||
import {drawDot} from "./utils.ts";
|
||||
import {Player} from "./Player.ts";
|
||||
import {Projectile, StraightProjectile} from "./projectile.ts";
|
||||
import {HomingProjectile, Projectile, ProjectileStats} from "./projectile.ts";
|
||||
import {World} from "./World.ts";
|
||||
import {Vector} from "./base.ts";
|
||||
|
||||
@@ -22,7 +22,7 @@ export class Pistol implements Weapon {
|
||||
}
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D) {
|
||||
drawDot(this.player.position.add(this.offset), this.size, this.color, ctx)
|
||||
drawDot(this.getPosition(), this.size, this.color, ctx)
|
||||
}
|
||||
|
||||
act() {
|
||||
@@ -37,7 +37,8 @@ export class Pistol implements Weapon {
|
||||
private createProjectile(): boolean {
|
||||
let closestTargetTo = this.world.getClosestTargetTo(this.world.player.position);
|
||||
if(closestTargetTo !== undefined && closestTargetTo[1] !== undefined) {
|
||||
let projectile = StraightProjectile.createStraightProjectile(this.world, this.player.position.add(this.offset), closestTargetTo[1]!.getPosition(), this.player)
|
||||
let stats = new ProjectileStats(0, 1, 5)
|
||||
let projectile = HomingProjectile.createHomingProjectile(this.world, this.getPosition(), this.player, closestTargetTo[1]!, stats, 'yellow')
|
||||
this.projectiles.push(projectile)
|
||||
return true
|
||||
} else {
|
||||
@@ -53,7 +54,18 @@ export class Pistol implements Weapon {
|
||||
pistol.offset = offset;
|
||||
pistol.size = 1;
|
||||
pistol.color = 'yellow';
|
||||
pistol.shootInterval = 10;
|
||||
pistol.shootInterval = 50;
|
||||
return pistol;
|
||||
}
|
||||
|
||||
getPosition(): Vector {
|
||||
return this.player.position.add(this.offset);
|
||||
}
|
||||
|
||||
move(any?: any) {
|
||||
}
|
||||
|
||||
getSize() {
|
||||
return this.size;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user