Added shell for game weapon system

This commit is contained in:
OfficialCHenry 2022-04-08 18:01:21 -04:00
parent 63f5a2a3a0
commit e6c285e9c1
12 changed files with 310 additions and 2 deletions

View File

@ -1,6 +1,9 @@
import Game from "./Wolfie2D/Loop/Game"; import Game from "./Wolfie2D/Loop/Game";
import MainMenu from "./shattered_sword/Scenes/MainMenu"; import MainMenu from "./shattered_sword/Scenes/MainMenu";
import RegistryManager from "./Wolfie2D/Registry/RegistryManager";
import WeaponTemplateRegistry from "./shattered_sword/Registry/WeaponRegistry";
import WeaponTypeRegistry from "./shattered_sword/Registry/WeaponTypeRegistry";
// The main function is your entrypoint into Wolfie2D. Specify your first scene and any options here. // The main function is your entrypoint into Wolfie2D. Specify your first scene and any options here.
(function main(){ (function main(){
@ -28,6 +31,14 @@ import MainMenu from "./shattered_sword/Scenes/MainMenu";
showDebug: true // Whether to show debug messages. You can change this to true if you want showDebug: true // Whether to show debug messages. You can change this to true if you want
} }
// Set up custom registries
let weaponTemplateRegistry = new WeaponTemplateRegistry();
RegistryManager.addCustomRegistry("weaponTemplates", weaponTemplateRegistry);
let weaponTypeRegistry = new WeaponTypeRegistry();
RegistryManager.addCustomRegistry("weaponTypes", weaponTypeRegistry);
// Create a game with the options specified // Create a game with the options specified
const game = new Game(options); const game = new Game(options);

View File

@ -0,0 +1,13 @@
import AI from "../../Wolfie2D/DataTypes/Interfaces/AI";
import GameEvent from "../../Wolfie2D/Events/GameEvent";
import GameNode from "../../Wolfie2D/Nodes/GameNode";
//TODO -
export default interface BattlerAI extends AI {
owner: GameNode;
health: number;
damage: (damage: number) => void;
}

View File

View File

@ -0,0 +1,47 @@
import GameNode from "../../Wolfie2D/Nodes/GameNode";
import BattlerAI from "../AI/BattlerAI";
import Weapon from "./items/Weapon";
export default class BattleManager {
players: Array<BattlerAI>;
enemies: Array<BattlerAI>;
handleInteraction(attackerType: string, weapon: Weapon) {
//may be unneeded since we are controlling the player -
//we determine enemy collision there
/*
if (attackerType === "player") {
// Check for collisions with enemies
for (let enemy of this.enemies) {
if (weapon.hits(enemy.owner)) {
enemy.damage(weapon.type.damage);
}
}
} else {
// Check for collision with player
for (let player of this.players) {
if (weapon.hits(player.owner)) {
player.damage(weapon.type.damage);
}
}
}
*/
// Check for collision with player
for (let player of this.players) {
if (weapon.hits(player.owner)) {
player.damage(weapon.type.damage);
}
}
}
setPlayers(player: Array<BattlerAI>): void {
this.players = player;
}
setEnemies(enemies: Array<BattlerAI>): void {
this.enemies = enemies;
}
}

View File

@ -0,0 +1,28 @@
import Vec2 from "../../../Wolfie2D/DataTypes/Vec2";
import GameNode from "../../../Wolfie2D/Nodes/GameNode";
import Sprite from "../../../Wolfie2D/Nodes/Sprites/Sprite";
export default abstract class Item {
/** The sprite that represents this weapon in the world or in an inventory */
sprite: Sprite;
constructor(sprite: Sprite){
this.sprite = sprite;
}
moveSprite(position: Vec2, layer?: string){
// Change the layer if needed
if(layer){
let currentLayer = this.sprite.getLayer();
currentLayer.removeNode(this.sprite);
let newLayer = this.sprite.getScene().getLayer(layer);
newLayer.addNode(this.sprite);
this.sprite.setLayer(newLayer);
}
// Move the sprite
this.sprite.position.copy(position);
}
abstract use(user: GameNode, ...args: any): void;
}

View File

@ -0,0 +1,78 @@
//TODO import Vec2 from "../../../Wolfie2D/DataTypes/Vec2";
import Emitter from "../../../Wolfie2D/Events/Emitter";
import GameNode from "../../../Wolfie2D/Nodes/GameNode";
import Sprite from "../../../Wolfie2D/Nodes/Sprites/Sprite";
import Timer from "../../../Wolfie2D/Timing/Timer";
import BattleManager from "../BattleManager";
import Item from "./Item";
import WeaponType from "./WeaponTypes/WeaponType";
import Vec2 from "../../../Wolfie2D/DataTypes/Vec2";
export default class Weapon extends Item {
/** The type of this weapon */
type: WeaponType;
/** A list of assets this weapon needs to be animated */
assets: Array<any>;
/** An event emitter to hook into the EventQueue */
emitter: Emitter
/** The battle manager */
battleManager: BattleManager;
/** The cooldown timer for this weapon's use */
cooldownTimer: Timer;
constructor(sprite: Sprite, type: WeaponType, battleManager: BattleManager){
super(sprite);
// Set the weapon type
this.type = type.clone();
// Keep a reference to the sprite of this weapon
this.sprite = sprite;
// Create an event emitter
this.emitter = new Emitter();
// Save a reference to the battler manager
this.battleManager = battleManager;
// Create the cooldown timer
this.cooldownTimer = new Timer(type.cooldown);
}
// @override
/**
* Uses this weapon in the specified direction.
* This only works if the cooldown timer has ended
*/
use(user: GameNode, userType: string, direction: Vec2): boolean {
// If the cooldown timer is still running, we can't use the weapon
if(!this.cooldownTimer.isStopped()){
return false;
}
// Rely on the weapon type to create any necessary assets
this.assets = this.type.createRequiredAssets(this.sprite.getScene());
// Do a type specific weapon animation
this.type.doAnimation(user, direction, ...this.assets);
// Apply damage
this.battleManager.handleInteraction(userType, this);
// Reset the cooldown timer
this.cooldownTimer.start();
return true;
}
/**
* A check for whether or not this weapon hit a node
*/
hits(node: GameNode): boolean {
return this.type.hits(node, ...this.assets);
}
}

View File

@ -0,0 +1,35 @@
import GameNode from "../../../../Wolfie2D/Nodes/GameNode";
import Scene from "../../../../Wolfie2D/Scene/Scene";
export default abstract class WeaponType {
/** The key for this sprite image */
spriteKey: string;
/** How much damage this weapon does */
damage: number;
/** Display name */
displayName: string;
/** The use cooldown of the weapon */
cooldown: number;
/** How loud it is to use this weapon */
useVolume: number;
/**
* Initializes this weapon type with data
*/
abstract initialize(options: Record<string, any>): void;
/**
* The animation to do when this weapon is used
*/
abstract doAnimation(...args: any): void;
abstract createRequiredAssets(scene: Scene): Array<any>;
abstract hits(node: GameNode, ...args: any): boolean;
abstract clone(): WeaponType;
}

View File

@ -0,0 +1,32 @@
import Registry from "../../Wolfie2D/Registry/Registries/Registry";
import ResourceManager from "../../Wolfie2D/ResourceManager/ResourceManager";
import WeaponType from "../GameSystems/items/WeaponTypes/WeaponType";
export default class WeaponTemplateRegistry extends Registry<WeaponConstructor> {
public preload(): void {
const rm = ResourceManager.getInstance();
//TODO -
// Load sprites for each weapon
//rm.image("something", "shattered_sword_assets/sprites/something.png");
// Load spritesheets
//rm.spritesheet("weapon anim", "shattered_sword_assets/spritesheets/weapon anim.json");
// Register default types
//this.registerItem("itemtype", itemTypefile);
}
public registerAndPreloadItem(key: string): void {}
public registerItem(key: string, constr: WeaponConstructor): void {
this.add(key, constr);
}
}
type WeaponConstructor = new (...args: any) => WeaponType;

View File

@ -0,0 +1,14 @@
import Registry from "../../Wolfie2D/Registry/Registries/Registry";
import WeaponType from "../GameSystems/items/WeaponTypes/WeaponType";
export default class WeaponTypeRegistry extends Registry<WeaponType> {
public preload(): void {}
// We don't need this for this assignment
public registerAndPreloadItem(key: string): void {}
public registerItem(key: string, type: WeaponType): void {
this.add(key, type);
}
}

View File

@ -17,6 +17,14 @@ import { EaseFunctionType } from "../../Wolfie2D/Utils/EaseFunctions";
import PlayerController from "../Player/PlayerController"; import PlayerController from "../Player/PlayerController";
import MainMenu from "./MainMenu"; import MainMenu from "./MainMenu";
import { Player_Events } from "../sword_enums"; import { Player_Events } from "../sword_enums";
import RegistryManager from "../../Wolfie2D/Registry/RegistryManager";
import WeaponType from "../GameSystems/items/WeaponTypes/WeaponType";
import Weapon from "../GameSystems/items/Weapon";
import BattleManager from "../GameSystems/BattleManager";
//import EnemyAI from "../AI/EnemyAI";
import BattlerAI from "../AI/BattlerAI";
// TODO // TODO
/** /**
@ -42,12 +50,27 @@ export default class GameLevel extends Scene {
// Screen fade in/out for level start and end // Screen fade in/out for level start and end
protected levelTransitionTimer: Timer; protected levelTransitionTimer: Timer;
protected levelTransitionScreen: Rect; protected levelTransitionScreen: Rect;
// The battle manager for the scene
private battleManager: BattleManager;
// Health UI // Health UI
protected healthLabel: Label; protected healthLabel: Label;
loadScene(): void {
//can load player sprite here
//can load enemy sprite here
// Load the scene info
//this.load.object("weaponData", "shattered_sword_assets/data/weaponData.json");
// Load in the enemy info
//this.load.object("enemyData", "shattered_sword_assets/data/enemy.json");
// Load in item info
//this.load.object("itemData", "shattered_sword_assets/data/items.json");
}
startScene(): void { startScene(): void {
@ -211,6 +234,18 @@ export default class GameLevel extends Scene {
}); });
// Initialize all enemies
//this.initializeEnemies();
// Send the player and enemies to the battle manager
//this.battleManager.setPlayers([<BattlerAI>this.player._ai]);
//this.battleManager.setEnemies(this.enemies.map(enemy => <BattlerAI>enemy._ai));
// Subscribe to relevant events
//this.receiver.subscribe("");
} }
/** /**
@ -258,7 +293,7 @@ export default class GameLevel extends Scene {
protected handlePlayerEnemyCollision(player: AnimatedSprite, enemy: AnimatedSprite) { protected handlePlayerEnemyCollision(player: AnimatedSprite, enemy: AnimatedSprite) {
//collisions are handled by the battleManager - no need for this in gamelevel for now
} }
/** /**
@ -301,4 +336,18 @@ export default class GameLevel extends Scene {
this.player.position.set(this.playerSpawn.x,this.playerSpawn.y); this.player.position.set(this.playerSpawn.x,this.playerSpawn.y);
} }
} }
//TODO - determine whether we will have weapon datatype
/**
*
* Creates and returns a new weapon
* @param type The weaponType of the weapon, as a string
*/
createWeapon(type: string): Weapon {
let weaponType = <WeaponType>RegistryManager.getRegistry("weaponTypes").get(type);
let sprite = this.add.sprite(weaponType.spriteKey, "primary");
return new Weapon(sprite, weaponType, this.battleManager);
}
} }

View File

@ -9,6 +9,7 @@ import GameLevel from "./GameLevel";
export default class Tutorial extends GameLevel{ export default class Tutorial extends GameLevel{
loadScene(): void { loadScene(): void {
super.loadScene();
// Load resources // Load resources
// this.load.tilemap("forest1", "shattered_sword_assets/tilemaps/Tutorial.json"); // this.load.tilemap("forest1", "shattered_sword_assets/tilemaps/Tutorial.json");
// let map = localStorage.getItem("map"); // let map = localStorage.getItem("map");