Added Attack

used old slice anim + knife datatype, change when we have the chance.
This commit is contained in:
OfficialCHenry 2022-04-09 04:49:30 -04:00
parent 12b470614f
commit eefc91944d
19 changed files with 385 additions and 26 deletions

View File

@ -0,0 +1,15 @@
{
"numWeapons": 1,
"weapons": [
{
"weaponType": "slice",
"name": "knife",
"displayName": "Knife",
"animationSprite": "slice",
"spriteKey": "knife",
"damage": 1,
"cooldown": 3,
"useVolume": 0
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

View File

@ -0,0 +1,19 @@
{
"name": "slice",
"spriteSheetImage": "slice.png",
"spriteWidth": 16,
"spriteHeight": 16,
"columns": 4,
"rows": 1,
"durationType": "time",
"animations": [
{
"name": "NORMAL",
"frames": [ {"index": 0, "duration": 1} ]
},
{
"name": "SLICE",
"frames": [ {"index": 1, "duration": 2}, {"index": 2, "duration": 4}, {"index": 3, "duration": 2} ]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

View File

@ -0,0 +1,33 @@
{
"name": "test_dummy",
"spriteSheetImage": "test_dummy.png",
"spriteWidth": 32,
"spriteHeight": 32,
"columns": 1,
"rows": 2,
"durationType": "time",
"animations": [
{
"name": "IDLE",
"frames": [ {"index": 0, "duration": 540} ]
},
{
"name": "JUMP",
"frames":[ {"index": 0, "duration": 32}]
},
{
"name": "WALK",
"frames": [ {"index": 0, "duration": 540} ]
},
{
"name": "FALL",
"frames": [ {"index": 0, "duration": 540} ]
},
{
"name": "HURT",
"frames": [ {"index": 0, "duration": 250},
{"index": 1, "duration": 500},
{"index": 0, "duration": 250} ]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

View File

@ -25,7 +25,8 @@ import WeaponTypeRegistry from "./shattered_sword/Registry/WeaponTypeRegistry";
{name: "skill", keys: ["l","v"]},
{name: "inventory", keys: ["i","b"]},
{name: "pause", keys: ["escape"]},
{name: "tab", keys: ["tab"]}
{name: "tab", keys: ["tab"]} ,
{name: "spawn", keys: ["q"]} //debug feature to test enemy spawning, press q to spawn enemy at current location
],
useWebGL: false, // Tell the game we want to use webgl
showDebug: true // Whether to show debug messages. You can change this to true if you want

View File

@ -7,7 +7,7 @@ import GameNode from "../../Wolfie2D/Nodes/GameNode";
export default interface BattlerAI extends AI {
owner: GameNode;
health: number;
CURRENT_HP: number; //changed health to CURRENT_HP
damage: (damage: number) => void;
}

View File

@ -0,0 +1,112 @@
import Vec2 from "../../Wolfie2D/DataTypes/Vec2";
import { GraphicType } from "../../Wolfie2D/Nodes/Graphics/GraphicTypes";
import Rect from "../../Wolfie2D/Nodes/Graphics/Rect";
import Sprite from "../../Wolfie2D/Nodes/Sprites/Sprite";
import Scene from "../../Wolfie2D/Scene/Scene";
import Color from "../../Wolfie2D/Utils/Color";
import Item from "./items/Item";
export default class InventoryManager {
private position: Vec2;
private items: Array<Item>;
private inventorySlots: Array<Sprite>;
private slotSize: Vec2;
private padding: number;
private currentSlot: number;
private slotLayer: string;
private itemLayer: string;
private selectedSlot: Rect;
constructor(scene: Scene, size: number, inventorySlot: string, position: Vec2, padding: number, slotLayer: string, itemLayer: string){
this.items = new Array(size);
this.inventorySlots = new Array(size);
this.padding = padding;
this.position = position;
this.currentSlot = 0;
// Add layers
this.slotLayer = slotLayer;
scene.addUILayer(this.slotLayer).setDepth(100);
this.itemLayer = itemLayer;
scene.addUILayer(this.itemLayer).setDepth(101);
// Create the inventory slots
for(let i = 0; i < size; i++){
this.inventorySlots[i] = scene.add.sprite(inventorySlot, this.slotLayer);
}
this.slotSize = this.inventorySlots[0].size.clone();
// Position the inventory slots
for(let i = 0; i < size; i++){
this.inventorySlots[i].position.set(position.x + i*(this.slotSize.x + this.padding), position.y);
}
// Add a rect for the selected slot
this.selectedSlot = <Rect>scene.add.graphic(GraphicType.RECT, slotLayer, {position: this.position.clone(), size: this.slotSize.clone().inc(-2)});
this.selectedSlot.color = Color.WHITE;
this.selectedSlot.color.a = 0.2;
}
getItem(): Item {
return this.items[this.currentSlot];
}
/**
* Changes the currently selected slot
*/
changeSlot(slot: number): void {
this.currentSlot = slot;
this.selectedSlot.position.copy(this.inventorySlots[slot].position);
}
/**
* Gets the currently selected slot
*/
getSlot(): number {
return this.currentSlot;
}
/**
* Adds an item to the currently selected slot
*/
addItem(item: Item): boolean {
if(!this.items[this.currentSlot]){
// Add the item to the inventory
this.items[this.currentSlot] = item;
// Update the gui
item.moveSprite(new Vec2(this.position.x + this.currentSlot*(this.slotSize.x + this.padding), this.position.y), this.itemLayer);
return true;
}
// Failed to add item, something was already in the slot
return false;
}
/**
* Removes and returns an item from the the currently selected slot, if possible
*/
removeItem(): Item {
let item = this.items[this.currentSlot];
this.items[this.currentSlot] = null;
if(item){
return item;
} else {
return null;
}
}
setActive(active: boolean) {
if (active){
this.inventorySlots.forEach(slot => slot.alpha = 1.0);
}
else{
this.inventorySlots.forEach(slot => slot.alpha = 0.5);
}
}
}

View File

@ -0,0 +1,50 @@
import Vec2 from "../../../../Wolfie2D/DataTypes/Vec2";
import GameNode from "../../../../Wolfie2D/Nodes/GameNode";
import AnimatedSprite from "../../../../Wolfie2D/Nodes/Sprites/AnimatedSprite";
import Scene from "../../../../Wolfie2D/Scene/Scene";
import Sprite from "../../../../Wolfie2D/Nodes/Sprites/Sprite";
import WeaponType from "./WeaponType";
export default class Slice extends WeaponType {
initialize(options: Record<string, any>): void {
this.damage = options.damage;
this.cooldown = options.cooldown;
this.displayName = options.displayName;
this.spriteKey = options.spriteKey;
this.useVolume = options.useVolume;
}
doAnimation(attacker: GameNode, direction: Vec2, sliceSprite: AnimatedSprite): void {
// Rotate this with the game node
// TODO - need to rotate the anim properly
sliceSprite.rotation = attacker.rotation;
sliceSprite.rotation = (<Sprite>attacker).invertX? .5* Math.PI : 1.5 * Math.PI;
// Move the slice out from the player
//scale = num of pixels between center of sprite and atk anim
sliceSprite.position = attacker.position.clone().add(direction.scaled(65));
sliceSprite.scaleX = 4;
sliceSprite.scaleY = 4;
// Play the slice animation w/o loop, but queue the normal animation
sliceSprite.animation.play("SLICE");
sliceSprite.animation.queue("NORMAL", true);
}
createRequiredAssets(scene: Scene): [AnimatedSprite] {
let slice = scene.add.animatedSprite("slice", "primary");
slice.animation.play("NORMAL", true);
return [slice];
}
hits(node: GameNode, sliceSprite: AnimatedSprite): boolean {
return sliceSprite.boundary.overlaps(node.collisionShape);
}
clone(): WeaponType {
let newType = new Slice();
newType.initialize({damage: this.damage, cooldown: this.cooldown, displayName: this.displayName, spriteKey: this.spriteKey, useVolume: this.useVolume});
return newType;
}
}

View File

@ -10,6 +10,12 @@ import InAir from "./PlayerStates/InAir";
import Jump from "./PlayerStates/Jump";
import Walk from "./PlayerStates/Walk";
import Debug from "../../Wolfie2D/Debug/Debug";
import Item from "../GameSystems/items/Item";
import InventoryManager from "../GameSystems/InventoryManager";
import Input from "../../Wolfie2D/Input/Input";
import BattlerAI from "../AI/BattlerAI";
import MathUtils from "../../Wolfie2D/Utils/MathUtils";
export enum PlayerType {
PLATFORMER = "platformer",
@ -40,8 +46,8 @@ type Buffs = [
]
export default class PlayerController extends StateMachineAI {
protected owner: GameNode;
export default class PlayerController extends StateMachineAI implements BattlerAI{
owner: GameNode;
velocity: Vec2 = Vec2.ZERO;
speed: number = 200;
MIN_SPEED: number = 200;
@ -57,6 +63,20 @@ export default class PlayerController extends StateMachineAI {
CURRENT_DEF: number = 100;
tilemap: OrthogonalTilemap;
// TODO -
damage(damage: number): void {
this.CURRENT_HP -= damage;
}
private lookDirection: Vec2;
/** A list of items in the game world */
private items: Array<Item>;
// The inventory of the player
inventory: InventoryManager;
CURRENT_BUFFS: {
atk: 0;
hp: 0;
@ -91,7 +111,9 @@ export default class PlayerController extends StateMachineAI {
this.tilemap = this.owner.getScene().getTilemap(options.tilemap) as OrthogonalTilemap;
this.inventory = options.inventory;
this.lookDirection = new Vec2();
}
initializePlatformer(): void {
@ -132,5 +154,21 @@ export default class PlayerController extends StateMachineAI {
Debug.log("playerstate", "Player State: Fall");
}
Debug.log("playerspeed", "x: " + this.velocity.x + ", y:" + this.velocity.y);
//testing the attacks here, may be moved to another place latera
if(Input.isJustPressed("attack")){
let item = this.inventory.getItem();
//TODO - get proper look direction
this.lookDirection.x = (<Sprite>this.owner).invertX ? -1 : 1;
// If there is an item in the current slot, use it
if (item) {
item.use(this.owner, "player", this.lookDirection);
}
}
}
}

View File

@ -1,4 +1,6 @@
import GameEvent from "../../../Wolfie2D/Events/GameEvent";
import Sprite from "../../../Wolfie2D/Nodes/Sprites/Sprite";
import MathUtils from "../../../Wolfie2D/Utils/MathUtils";
import { PlayerStates } from "../PlayerController";
import PlayerState from "./PlayerState";
@ -9,6 +11,10 @@ export default abstract class InAir extends PlayerState {
let dir = this.getInputDirection();
if(dir.x !== 0){
(<Sprite>this.owner).invertX = MathUtils.sign(dir.x) < 0;
}
this.parent.velocity.x += dir.x * this.parent.speed/3.5 - 0.3*this.parent.velocity.x;
this.owner.move(this.parent.velocity.scaled(deltaT));

View File

@ -27,6 +27,8 @@ export default class OnGround extends PlayerState {
} else if(!this.owner.onGround){
this.finished("fall");
}
}
onExit(): Record<string, any> {

View File

@ -2,6 +2,7 @@ import Registry from "../../Wolfie2D/Registry/Registries/Registry";
import ResourceManager from "../../Wolfie2D/ResourceManager/ResourceManager";
import WeaponType from "../GameSystems/items/WeaponTypes/WeaponType";
import Slice from "../GameSystems/items/WeaponTypes/Slice";
export default class WeaponTemplateRegistry extends Registry<WeaponConstructor> {
@ -11,13 +12,15 @@ export default class WeaponTemplateRegistry extends Registry<WeaponConstructor>
//TODO -
// Load sprites for each weapon
//rm.image("something", "shattered_sword_assets/sprites/something.png");
rm.image("knife", "shattered_sword_assets/sprites/knife.png");
// Load spritesheets
//rm.spritesheet("weapon anim", "shattered_sword_assets/spritesheets/weapon anim.json");
rm.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json");
// Register default types
//this.registerItem("itemtype", itemTypefile);
this.registerItem("slice", Slice);
}

View File

@ -23,6 +23,10 @@ import Weapon from "../GameSystems/items/Weapon";
import BattleManager from "../GameSystems/BattleManager";
//import EnemyAI from "../AI/EnemyAI";
import BattlerAI from "../AI/BattlerAI";
import InventoryManager from "../GameSystems/InventoryManager";
import Item from "../GameSystems/items/Item";
@ -57,30 +61,53 @@ export default class GameLevel extends Scene {
// Health UI
protected healthLabel: Label;
// A list of items in the scene
private items: Array<Item>;
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");
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");
this.load.image("knife", "shattered_sword_assets/sprites/knife.png");
this.load.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json");
this.load.image("inventorySlot", "shattered_sword_assets/sprites/inventory.png");
}
startScene(): void {
// Do the game level standard initializations
this.initLayers();
this.initViewport();
// Create the battle manager
this.battleManager = new BattleManager();
// TODO
this.initializeWeapons();
// Initialize the items array - this represents items that are in the game world
this.items = new Array();
this.initPlayer();
this.subscribeToEvents();
this.addUI();
// Send the player and enemies to the battle manager
this.battleManager.setPlayers([<PlayerController>this.player._ai]);
// Initialize the timers
this.respawnTimer = new Timer(1000, () => {
if(GameLevel.livesCount === 0){
@ -98,6 +125,7 @@ export default class GameLevel extends Scene {
});
// Start the black screen fade out
this.levelTransitionScreen.tweens.play("fadeOut");
@ -118,9 +146,11 @@ export default class GameLevel extends Scene {
}
}
//update health UI
let playerAI = (<PlayerController>this.player.ai);
this.healthLabel.text = "Player Health: "+ playerAI.CURRENT_HP +'/' + (playerAI.MAX_HP );
//handle collisions
//handle collisions - may be in battle manager instead
//move background
@ -134,6 +164,7 @@ export default class GameLevel extends Scene {
}
/**
@ -248,10 +279,57 @@ export default class GameLevel extends Scene {
}
//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);
}
/**
* Initalizes all weapon types based of data from weaponData.json
*/
initializeWeapons(): void{
let weaponData = this.load.getObject("weaponData");
for(let i = 0; i < weaponData.numWeapons; i++){
let weapon = weaponData.weapons[i];
// Get the constructor of the prototype
let constr = RegistryManager.getRegistry("weaponTemplates").get(weapon.weaponType);
// Create a weapon type
let weaponType = new constr();
// Initialize the weapon type
weaponType.initialize(weapon);
// Register the weapon type
RegistryManager.getRegistry("weaponTypes").registerItem(weapon.name, weaponType)
}
}
/**
* Initializes the player
*/
protected initPlayer(): void {
//create the inventory
let inventory = new InventoryManager(this, 1, "inventorySlot", new Vec2(16, 16), 4, "slots1", "items1");
//add starting weapon to inventory
let startingWeapon = this.createWeapon("knife");
inventory.addItem(startingWeapon); //using slice to test right now
// Add the player
this.player = this.add.animatedSprite("player", "primary");
this.player.scale.set(2, 2);
@ -262,7 +340,16 @@ export default class GameLevel extends Scene {
this.player.position.copy(this.playerSpawn);
this.player.addPhysics(new AABB(Vec2.ZERO, new Vec2(32, 32))); //sets the collision shape
this.player.colliderOffset.set(0, 2);
this.player.addAI(PlayerController, {playerType: "platformer", tilemap: "Main"});
this.player.addAI(PlayerController, {
playerType: "platformer",
tilemap: "Main",
speed: 100,
health: 10,
inventory: inventory,
items: this.items,
inputEnabled: false,
range: 100
});
this.player.setGroup("player");
@ -277,19 +364,19 @@ export default class GameLevel extends Scene {
* @param tilePos The tilemap position to add the Enemy to
* @param aiOptions The options for the Enemy AI
*/
/*
protected addEnemy(spriteKey: string, tilePos: Vec2, aiOptions: Record<string, any>): void {
let enemy = this.add.animatedSprite(spriteKey, "primary");
enemy.position.set(tilePos.x*32, tilePos.y*32);
enemy.scale.set(2, 2);
enemy.addPhysics();
enemy.addAI(EnemyController, aiOptions); //TODO - add individual enemy AI
//enemy.addAI(EnemyAI, aiOptions); //TODO - add individual enemy AI
enemy.setGroup("Enemy");
enemy.setTrigger("player",Player_Events.PLAYER_HIT_ENEMY, null);
}
*/
protected handlePlayerEnemyCollision(player: AnimatedSprite, enemy: AnimatedSprite) {
@ -337,17 +424,5 @@ export default class GameLevel extends Scene {
}
}
//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

@ -20,6 +20,11 @@ export default class Tutorial extends GameLevel{
this.load.tilemapFromObject("forest1", this.map);
this.load.spritesheet("player", "shattered_sword_assets/spritesheets/Hiro.json")
// TODO - change when done testing
this.load.spritesheet("slice", "shattered_sword_assets/spritesheets/slice.json");
//load music here
}