mirror of
https://github.com/Sheldan/canvas.git
synced 2026-01-01 14:58:51 +00:00
survivors: adding items and item drops
adding rarities to items adding drops to enemies
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import type {Acting, Drawable, Healthy, Placeable, Shooting} from "./interfaces.ts";
|
||||
import type {Acting, ChanceEntry, 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 {ProjectileStats, StraightProjectile} from "./projectile.ts";
|
||||
import {HealthPack, LevelDrop, MoneyDrop} from "./drop.ts";
|
||||
import {HealthPack, ItemDrop, LevelDrop, MoneyDrop} from "./drop.ts";
|
||||
import {ItemManagement} from "./items.ts";
|
||||
|
||||
export abstract class Enemy implements Placeable, Drawable, Acting, Healthy {
|
||||
protected _position: Vector;
|
||||
@@ -12,8 +13,11 @@ export abstract class Enemy implements Placeable, Drawable, Acting, Healthy {
|
||||
protected world: World;
|
||||
protected size: number
|
||||
protected status: EnemyStatus = new EnemyStatus(10);
|
||||
protected drops: KillChanceTable;
|
||||
|
||||
constructor(position: Vector) {
|
||||
this.drops = new KillChanceTable();
|
||||
this.drops.addDrop( {chance: 10, creationMethod: this.spawnMoney})
|
||||
this._position = position.clone();
|
||||
}
|
||||
|
||||
@@ -41,7 +45,14 @@ export abstract class Enemy implements Placeable, Drawable, Acting, Healthy {
|
||||
}
|
||||
|
||||
die() {
|
||||
MoneyDrop.spawnMoneyDrop(this.world, this._position);
|
||||
let draw = this.drops.draw();
|
||||
if(draw) {
|
||||
draw.creationMethod(this)
|
||||
}
|
||||
}
|
||||
|
||||
spawnMoney(enemy: Enemy) {
|
||||
MoneyDrop.spawnMoneyDrop(enemy.world, enemy._position);
|
||||
}
|
||||
|
||||
getSize() {
|
||||
@@ -225,9 +236,9 @@ export class ContainerEnemy extends Enemy {
|
||||
super(position);
|
||||
this.status.health = 5;
|
||||
this.drops = new KillChanceTable();
|
||||
this.drops.addDrop( {chance: 50, creationMethod: this.spawnHealthPack})
|
||||
this.drops.addDrop( {chance: 50, creationMethod: this.spawnLevelUp})
|
||||
this.drops.addDrop( {chance: 10, creationMethod: this.spawnEnemy})
|
||||
ItemManagement.getItemsWithRarityFactor().forEach(drop => {
|
||||
this.drops.addDrop(drop)
|
||||
})
|
||||
this.drops.calculateProbs()
|
||||
}
|
||||
|
||||
@@ -245,7 +256,11 @@ export class ContainerEnemy extends Enemy {
|
||||
}
|
||||
|
||||
die() {
|
||||
this.drops.draw().creationMethod(this)
|
||||
let draw = this.drops.draw();
|
||||
if(draw) {
|
||||
let item = draw.creationMethod(this);
|
||||
ItemDrop.spawnItemDrop(this.world, item, this._position)
|
||||
}
|
||||
}
|
||||
|
||||
spawnHealthPack(enemy: ContainerEnemy) {
|
||||
@@ -282,10 +297,6 @@ export class ContainerEnemy extends Enemy {
|
||||
}
|
||||
}
|
||||
|
||||
export interface ChanceEntry {
|
||||
chance: number;
|
||||
creationMethod: (any: any) => void;
|
||||
}
|
||||
|
||||
export class KillChanceTable {
|
||||
private chances: ChanceEntry[] = []
|
||||
@@ -300,6 +311,9 @@ export class KillChanceTable {
|
||||
}
|
||||
|
||||
draw() {
|
||||
if(this.chances.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
let change = Math.random();
|
||||
for (const value of this.chances) {
|
||||
change -= value.chance;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type {Acting, Drawable, Healthy, Leveling, Weapon} from "./interfaces.ts";
|
||||
import type {Acting, Drawable, Healthy, Item, Leveling, Weapon} from "./interfaces.ts";
|
||||
import {Vector} from "./base.ts";
|
||||
import {drawDot, getCoordinatesSplit} from "./utils.ts";
|
||||
|
||||
@@ -8,7 +8,8 @@ export class Player implements Drawable, Acting, Healthy {
|
||||
private _color: string;
|
||||
|
||||
private _status: PlayerStatus;
|
||||
private _weapons: [Weapon] = []
|
||||
private _weapons: Weapon[] = []
|
||||
private _items: Item[] = []
|
||||
|
||||
// temp
|
||||
private _speed: Vector;
|
||||
@@ -47,6 +48,10 @@ export class Player implements Drawable, Acting, Healthy {
|
||||
this._weapons.push(weapon)
|
||||
}
|
||||
|
||||
addItem(item: Item) {
|
||||
this._items.push(item)
|
||||
}
|
||||
|
||||
move(direction: Vector) {
|
||||
this._position = this.position.add(direction)
|
||||
}
|
||||
@@ -173,6 +178,31 @@ export class PlayerStats {
|
||||
this._weaponRangeFactor += 0.1
|
||||
}
|
||||
|
||||
|
||||
set speed(value: number) {
|
||||
this._speed = value;
|
||||
}
|
||||
|
||||
set size(value: number) {
|
||||
this._size = value;
|
||||
}
|
||||
|
||||
set health(value: number) {
|
||||
this._health = value;
|
||||
}
|
||||
|
||||
set pullRange(value: number) {
|
||||
this._pullRange = value;
|
||||
}
|
||||
|
||||
set weaponRange(value: number) {
|
||||
this._weaponRange = value;
|
||||
}
|
||||
|
||||
set weaponRangeFactor(value: number) {
|
||||
this._weaponRangeFactor = value;
|
||||
}
|
||||
|
||||
get speed(): number {
|
||||
return this._speed;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type {Drop} from "./interfaces.ts";
|
||||
import type {Drop, Item} from "./interfaces.ts";
|
||||
import {World} from "./World.ts";
|
||||
import {drawDot, moveInDirectionOf} from "./utils.ts";
|
||||
import {Vector} from "./base.ts";
|
||||
import {rarityColor} from "./items.ts";
|
||||
|
||||
export abstract class BasicDrop implements Drop {
|
||||
protected world: World;
|
||||
@@ -120,4 +121,37 @@ export class LevelDrop extends BasicDrop {
|
||||
return drop;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class ItemDrop extends BasicDrop {
|
||||
|
||||
private item: Item;
|
||||
|
||||
|
||||
constructor(world: World, position: Vector, item: Item) {
|
||||
super(world, position);
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
pickup() {
|
||||
this.item.pickup(this.world.player, this.world)
|
||||
}
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D) {
|
||||
ctx.fillStyle = rarityColor(this.item.getRarity())
|
||||
ctx.fillText(this.item.name() + '', this._position.x, this._position.y)
|
||||
}
|
||||
|
||||
static spawnItemDrop(world: World, item: Item, position?: Vector) {
|
||||
world.addDrop(this.createItemDrop(world, item, position))
|
||||
}
|
||||
|
||||
static createItemDrop(world: World, item: Item, position?: Vector) {
|
||||
if(!position) {
|
||||
position = world.randomPlace()
|
||||
}
|
||||
let drop = new ItemDrop(world, position, item)
|
||||
drop.size = 3
|
||||
return drop
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
import {Vector} from "./base.ts";
|
||||
import type {Player} from "./Player.ts";
|
||||
import type {Rarity} from "./items.ts";
|
||||
import type {World} from "./World.ts";
|
||||
|
||||
export interface Acting {
|
||||
act()
|
||||
@@ -15,6 +18,17 @@ export interface Leveling {
|
||||
level()
|
||||
}
|
||||
|
||||
export interface Item {
|
||||
pickup(player: Player, world: World);
|
||||
name(): string
|
||||
getRarity(): Rarity;
|
||||
}
|
||||
|
||||
export interface ChanceEntry {
|
||||
chance: number;
|
||||
creationMethod: (any: any) => any;
|
||||
}
|
||||
|
||||
export interface Drop extends Drawable, Acting {
|
||||
pickup()
|
||||
}
|
||||
|
||||
157
absurd-survivors/src/items.ts
Normal file
157
absurd-survivors/src/items.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
import type {ChanceEntry, Item} from "./interfaces.ts";
|
||||
import {Player} from "./Player.ts";
|
||||
import {randomItem} from "./utils.ts";
|
||||
import {HomingPistol, Pistol, SpreadWeapon} from "./weapons.ts";
|
||||
import type {World} from "./World.ts";
|
||||
|
||||
export enum Rarity {
|
||||
GARBAGE= 'GARBAGE',
|
||||
COMMON = 'COMMON',
|
||||
UNCOMMON = 'UNCOMMON',
|
||||
RARE = 'RARE',
|
||||
EPIC = 'EPIC',
|
||||
LEGENDARY = 'LEGENDARY',
|
||||
GODLY = 'GODLY'
|
||||
}
|
||||
|
||||
export class ItemManagement {
|
||||
|
||||
private static ITEMS: Item[] = []
|
||||
|
||||
static addItem(item: Item) {
|
||||
this.ITEMS.push(item)
|
||||
}
|
||||
|
||||
static getItemsWithRarityFactor(): ChanceEntry[] {
|
||||
let items: ChanceEntry[] = []
|
||||
this.ITEMS.forEach((item) => {
|
||||
items.push({chance: rarityWeight(item.getRarity()), creationMethod: () => item})
|
||||
})
|
||||
return items;
|
||||
}
|
||||
|
||||
static getRandomItem() {
|
||||
return randomItem(this.ITEMS)
|
||||
}
|
||||
|
||||
static initializeItems() {
|
||||
this.ITEMS.push(new SpeedUp())
|
||||
this.ITEMS.push(new HealthUp())
|
||||
this.ITEMS.push(new HomingPistolItem())
|
||||
this.ITEMS.push(new PistolItem())
|
||||
this.ITEMS.push(new SpreadWeaponItem())
|
||||
}
|
||||
}
|
||||
|
||||
export function rarityWeight(rarity: Rarity): number {
|
||||
switch (rarity) {
|
||||
case Rarity.GARBAGE: return 80;
|
||||
case Rarity.COMMON: return 65;
|
||||
case Rarity.UNCOMMON: return 50;
|
||||
case Rarity.RARE: return 30;
|
||||
case Rarity.EPIC: return 15;
|
||||
case Rarity.LEGENDARY: return 5;
|
||||
case Rarity.GODLY: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
export function rarityColor(rarity: Rarity): string {
|
||||
switch (rarity) {
|
||||
case Rarity.GARBAGE: return 'white';
|
||||
case Rarity.COMMON: return 'gray';
|
||||
case Rarity.UNCOMMON: return 'blue';
|
||||
case Rarity.RARE: return 'green';
|
||||
case Rarity.EPIC: return 'orange';
|
||||
case Rarity.LEGENDARY: return 'violett';
|
||||
case Rarity.GODLY: return 'red';
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class BaseItem implements Item {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
pickup(player: Player, world: World) {
|
||||
player.addItem(this)
|
||||
}
|
||||
|
||||
abstract name();
|
||||
abstract getRarity(): Rarity;
|
||||
}
|
||||
|
||||
export class SpeedUp extends BaseItem {
|
||||
pickup(player: Player, world: World) {
|
||||
player.stats.speed += 1
|
||||
super.pickup(player, world)
|
||||
}
|
||||
|
||||
name() {
|
||||
return 'speed'
|
||||
}
|
||||
|
||||
getRarity(): Rarity {
|
||||
return Rarity.COMMON;
|
||||
}
|
||||
}
|
||||
|
||||
export class HealthUp extends BaseItem {
|
||||
pickup(player: Player, world: World) {
|
||||
player.stats.health += 1
|
||||
super.pickup(player, world)
|
||||
}
|
||||
|
||||
name() {
|
||||
return 'health'
|
||||
}
|
||||
|
||||
getRarity(): Rarity {
|
||||
return Rarity.COMMON;
|
||||
}
|
||||
}
|
||||
|
||||
export class HomingPistolItem extends BaseItem {
|
||||
pickup(player: Player, world: World) {
|
||||
player.addWeapon(HomingPistol.generateHomingPistol(world))
|
||||
super.pickup(player, world)
|
||||
}
|
||||
|
||||
name() {
|
||||
return 'homingp'
|
||||
}
|
||||
|
||||
getRarity(): Rarity {
|
||||
return Rarity.RARE;
|
||||
}
|
||||
}
|
||||
|
||||
export class PistolItem extends BaseItem {
|
||||
pickup(player: Player, world: World) {
|
||||
player.addWeapon(Pistol.generatePistol(world))
|
||||
super.pickup(player, world)
|
||||
}
|
||||
|
||||
name() {
|
||||
return 'pistol'
|
||||
}
|
||||
|
||||
getRarity(): Rarity {
|
||||
return Rarity.RARE;
|
||||
}
|
||||
}
|
||||
|
||||
export class SpreadWeaponItem extends BaseItem {
|
||||
pickup(player: Player, world: World) {
|
||||
player.addWeapon(SpreadWeapon.generateSpreadWeapon(world))
|
||||
super.pickup(player, world)
|
||||
}
|
||||
|
||||
name() {
|
||||
return 'spreadp'
|
||||
}
|
||||
|
||||
getRarity(): Rarity {
|
||||
return Rarity.EPIC;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ import {docReady} from "canvas-common";
|
||||
import {World} from "./World.ts";
|
||||
import {Player} from "./Player.ts";
|
||||
import {Vector} from "./base.ts";
|
||||
import {BasicEnemy, ContainerEnemy, Enemy, HealthEnemy, ShootingEnemy} from "./Enemies.ts";
|
||||
import {BasicEnemy, ContainerEnemy, HealthEnemy, ShootingEnemy} from "./Enemies.ts";
|
||||
import {HUD} from "./ui.ts";
|
||||
import {HomingPistol, Pistol, SpreadWeapon} from "./weapons.ts";
|
||||
import {MoneyDrop} from "./drop.ts";
|
||||
import {Pistol} from "./weapons.ts";
|
||||
import {ItemManagement} from "./items.ts";
|
||||
|
||||
|
||||
let hud: HUD;
|
||||
@@ -122,10 +122,10 @@ docReady(function () {
|
||||
}, 10_000)
|
||||
|
||||
player.addWeapon(Pistol.generatePistol(world))
|
||||
player.addWeapon(HomingPistol.generateHomingPistol(world))
|
||||
player.addWeapon(SpreadWeapon.generateSpreadWeapon(world))
|
||||
hud = new HUD(world);
|
||||
|
||||
ItemManagement.initializeItems()
|
||||
|
||||
requestAnimationFrame(updateCanvas);
|
||||
|
||||
})
|
||||
|
||||
@@ -77,4 +77,8 @@ export function getCoordinatesSplit(amount: number) {
|
||||
points.push(new Vector(x, y))
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
export function randomItem(items: any[]) {
|
||||
return items[Math.floor(Math.random() * items.length)]
|
||||
}
|
||||
Reference in New Issue
Block a user