fixed spelling, added assassinAI, need to get gun working for archer

This commit is contained in:
OfficialCHenry 2022-05-06 01:14:09 -04:00
parent 1f7aa6d766
commit 5ff8353e3a
18 changed files with 280 additions and 37 deletions

View File

@ -1,5 +1,5 @@
{
"numWeapons": 1,
"numWeapons": 2,
"weapons": [
{
"weaponType": "slice",
@ -10,6 +10,16 @@
"damage": 50,
"cooldown": 500,
"useVolume": 0
},
{
"weaponType": "semiAutoGun",
"name": "pistol",
"displayName": "Pistol",
"spriteKey": "pistol",
"damage": 2,
"cooldown": 500,
"useVolume": 320,
"color": "#FFEEDD"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

View File

@ -0,0 +1,19 @@
import AnimatedSprite from "../../Wolfie2D/Nodes/Sprites/AnimatedSprite";
import EnemyAI, { EnemyStates } from "./EnemyAI";
import ArcherAttack from "./EnemyStates/ArcherAttack";
import Weapon from "../GameSystems/items/Weapon";
export default class ArcherAI extends EnemyAI {
/** The weapon this AI has */
weapon: Weapon;
initializeAI(owner: AnimatedSprite, options: Record<string, any>): void {
super.initializeAI(owner, options);
this.addState(EnemyStates.ATTACK, new ArcherAttack(this, owner));
this.weapon = options.weapon;
}
}

View File

@ -0,0 +1,17 @@
import Vec2 from "../../Wolfie2D/DataTypes/Vec2";
import AnimatedSprite from "../../Wolfie2D/Nodes/Sprites/AnimatedSprite";
import EnemyAI, { EnemyStates } from "./EnemyAI";
import AssassinAttack from "./EnemyStates/AssassinAttack";
export default class AssassinAI extends EnemyAI {
initializeAI(owner: AnimatedSprite, options: Record<string, any>): void {
super.initializeAI(owner, options);
this.addState(EnemyStates.ATTACK, new AssassinAttack(this, owner));
}
canAttack(position: Vec2): boolean {
return this.attackTimer.isStopped() && this.owner.position.distanceTo(position)<=150;
}
}

View File

@ -18,7 +18,7 @@ export default class BullAI extends EnemyAI {
collideWithPlayer(player: PlayerController): void {
player.damage(10);
if (this.isAttaking && !player.invincible && !player.godMode) {
if (this.isAttacking && !player.invincible && !player.godMode) {
player.bleedCounter += 3;
}
}

View File

@ -64,7 +64,7 @@ export default class EnemyAI extends StateMachineAI implements BattlerAI {
attackTimer : Timer;
isCharging: boolean = false;
isAttaking: boolean = false;
isAttacking: boolean = false;
damageTimer: Timer;
physicWidth: number;
@ -112,7 +112,7 @@ export default class EnemyAI extends StateMachineAI implements BattlerAI {
console.log(damage +" damage taken, "+this.CURRENT_HP+" hp left");
this.CURRENT_HP -= damage;
//TODO -
if (!this.isAttaking && !this.isCharging) {
if (!this.isAttacking && !this.isCharging) {
this.owner.animation.play("HURT",false);
}

View File

@ -0,0 +1,25 @@
import EnemyAI, { EnemyStates } from "../EnemyAI";
import AnimatedSprite from "../../../Wolfie2D/Nodes/Sprites/AnimatedSprite";
import Attack from "./Attack";
import ArcherAI from "../ArcherAI";
import Sprite from "../../../Wolfie2D/Nodes/Sprites/Sprite";
//TODO - unfinished
export default class ArcherAttack extends Attack {
onEnter(options: Record<string, any>): void {
}
update(deltaT: number): void {
this.parent.direction = this.parent.getPlayerPosition().x - this.owner.position.x >= 0 ? 1 : 0;
let dir = this.parent.getPlayerPosition().clone().sub(this.owner.position).normalize();
(<ArcherAI>this.parent).weapon.use(this.owner, "enemy", dir.scale(1,0));
(<Sprite>this.owner).invertX = this.parent.direction === 1 ? true : false ;
this.finished(EnemyStates.ALERT);
}
onExit(): Record<string, any> {
return null;
}
}

View File

@ -0,0 +1,73 @@
import EnemyAI, { EnemyStates } from "../EnemyAI";
import AnimatedSprite from "../../../Wolfie2D/Nodes/Sprites/AnimatedSprite";
import Attack from "./Attack";
import AssassinAI from "../ArcherAI";
import Sprite from "../../../Wolfie2D/Nodes/Sprites/Sprite";
import Timer from "../../../Wolfie2D/Timing/Timer";
import Vec2 from "../../../Wolfie2D/DataTypes/Vec2";
//TODO - unfinished
export default class AssassinAttack extends Attack {
runTimer: Timer;
startPosition : Vec2;
pauseTimer : Timer;
onEnter(options: Record<string, any>): void {
super.onEnter(options);
this.runTimer = new Timer(500);
this.pauseTimer = new Timer(1000);
this.owner.alpha = 1; //unstealth to attack
this.startPosition = this.owner.position;
if(this.parent.getPlayerPosition() !==null)
this.owner.position = this.parent.getPlayerPosition().clone().add(new Vec2( (<Sprite>this.parent.player).invertX ? 64 : -64 ,0));
this.pauseTimer.start();
}
update(deltaT: number): void {
if( this.pauseTimer.isStopped()){
if (this.runTimer.isStopped() && this.parent.isAttacking || !this.canWalk()) {
this.emitter.fireEvent(this.attacked);
}
while (this.receiver.hasNextEvent()) {
let event = this.receiver.getNextEvent().type;
switch (event) {
case this.charged:
this.parent.isCharging = false;
this.parent.isAttacking = true;
this.runTimer.start();
(<AnimatedSprite>this.owner).animation.play("ATTACK", true);
if(this.parent.getPlayerPosition() !==null)
this.parent.direction = this.parent.getPlayerPosition().x - this.owner.position.x >= 0 ? 1 : 0;
break;
case this.attacked:
this.parent.isAttacking = false;
this.finished(EnemyStates.ALERT);
break;
}
}
this.parent.velocity.x = this.parent.direction * 500;
(<Sprite>this.owner).invertX = this.parent.direction === 1 ? true : false ;
super.update(deltaT);
}
}
onExit(): Record<string, any> {
this.owner.alpha = .2; //stealth again
//this.owner.position = this.startPosition;
return null;
}
}

View File

@ -14,7 +14,7 @@ export default class TigerAttack extends Attack {
}
update(deltaT: number): void {
if (this.runTimer.isStopped() && this.parent.isAttaking || !this.canWalk()) {
if (this.runTimer.isStopped() && this.parent.isAttacking || !this.canWalk()) {
this.emitter.fireEvent(this.attacked);
}
while (this.receiver.hasNextEvent()) {
@ -22,13 +22,13 @@ export default class TigerAttack extends Attack {
switch (event) {
case this.charged:
this.parent.isCharging = false;
this.parent.isAttaking = true;
this.parent.isAttacking = true;
this.runTimer.start();
(<AnimatedSprite>this.owner).animation.play("ATTACK", true);
this.parent.direction = this.parent.getPlayerPosition().x - this.owner.position.x >= 0 ? 1 : 0;
break;
case this.attacked:
this.parent.isAttaking = false;
this.parent.isAttacking = false;
this.finished(EnemyStates.ALERT);
break;
}

View File

@ -27,7 +27,7 @@ export default abstract class EnemyState extends State {
}
update(deltaT: number): void {
if (!this.parent.damageTimer.isStopped() && !this.parent.isAttaking && !this.parent.isCharging) {
if (!this.parent.damageTimer.isStopped() && !this.parent.isAttacking && !this.parent.isCharging) {
this.parent.velocity.x = 0;
}
// Do gravity

View File

@ -11,12 +11,12 @@ export default class SnakeAttack extends Attack {
switch (event) {
case this.charged:
this.parent.isCharging = false;
this.parent.isAttaking = true;
this.parent.isAttacking = true;
(<AnimatedSprite>this.owner).animation.play("ATTACK", false, this.attacked);
(<AABB>this.owner.collisionShape).halfSize.x += 3.5;
break;
case this.attacked:
this.parent.isAttaking = false;
this.parent.isAttacking = false;
(<AABB>this.owner.collisionShape).halfSize.x -= 3.5;
this.finished(EnemyStates.ALERT);
break;

View File

@ -14,7 +14,7 @@ export default class TigerAttack extends Attack {
}
update(deltaT: number): void {
if (this.parent.isAttaking && this.owner.onGround) {
if (this.parent.isAttacking && this.owner.onGround) {
this.emitter.fireEvent(this.attacked);
}
while (this.receiver.hasNextEvent()) {
@ -22,14 +22,14 @@ export default class TigerAttack extends Attack {
switch (event) {
case this.charged:
this.parent.isCharging = false;
this.parent.isAttaking = true;
this.parent.isAttacking = true;
(<AnimatedSprite>this.owner).animation.play("ATTACK", true);
this.velocity = (this.parent.getPlayerPosition().x - this.owner.position.x)/1.5;
this.parent.direction = this.velocity >= 0 ? 1 : 0;
this.parent.velocity.y = -800;
break;
case this.attacked:
this.parent.isAttaking = false;
this.parent.isAttacking = false;
this.finished(EnemyStates.ALERT);
break;
}

View File

@ -11,7 +11,7 @@ export default class SnakeAI extends EnemyAI {
collideWithPlayer(player: PlayerController): void {
player.damage(10);
if (this.isAttaking && !player.invincible && !player.godMode) {
if (this.isAttacking && !player.invincible && !player.godMode) {
player.poisonCounter = 5;
}
}

View File

@ -23,7 +23,7 @@ export default class TigerAI extends EnemyAI {
collideWithPlayer(player: PlayerController): void {
player.damage(10);
if (this.isAttaking && !player.invincible && !player.godMode) {
if (this.isAttacking && !player.invincible && !player.godMode) {
player.bleedCounter += 3;
}
}

View File

@ -0,0 +1,102 @@
import AABB from "../../../../Wolfie2D/DataTypes/Shapes/AABB";
import Vec2 from "../../../../Wolfie2D/DataTypes/Vec2";
import GameNode, { TweenableProperties } from "../../../../Wolfie2D/Nodes/GameNode";
import { GraphicType } from "../../../../Wolfie2D/Nodes/Graphics/GraphicTypes";
import Line from "../../../../Wolfie2D/Nodes/Graphics/Line";
import OrthogonalTilemap from "../../../../Wolfie2D/Nodes/Tilemaps/OrthogonalTilemap";
import Scene from "../../../../Wolfie2D/Scene/Scene";
import Color from "../../../../Wolfie2D/Utils/Color";
import { EaseFunctionType } from "../../../../Wolfie2D/Utils/EaseFunctions";
import { Player_Events } from "../../../sword_enums";
import WeaponType from "./WeaponType";
export default class SemiAutoGun extends WeaponType {
color: Color;
private hexColor: string;
initialize(options: Record<string, any>): void {
this.damage = options.damage;
this.cooldown = options.cooldown;
this.hexColor = options.color;
this.color = Color.fromStringHex(options.color);
this.displayName = options.displayName;
this.spriteKey = options.spriteKey;
this.useVolume = options.useVolume;
}
doAnimation(shooter: GameNode, direction: Vec2, line: Line): void {
let start = shooter.position.clone();
let end = shooter.position.clone().add(direction.scaled(900));
let delta = end.clone().sub(start);
// Iterate through the tilemap region until we find a collision
let minX = Math.min(start.x, end.x);
let maxX = Math.max(start.x, end.x);
let minY = Math.min(start.y, end.y);
let maxY = Math.max(start.y, end.y);
// Get the wall tilemap
let walls = <OrthogonalTilemap>shooter.getScene().getLayer("Wall").getItems()[0];
let minIndex = walls.getColRowAt(new Vec2(minX, minY));
let maxIndex = walls.getColRowAt(new Vec2(maxX, maxY));
let tileSize = walls.getTileSize();
for(let col = minIndex.x; col <= maxIndex.x; col++){
for(let row = minIndex.y; row <= maxIndex.y; row++){
if(walls.isTileCollidable(col, row)){
// Get the position of this tile
let tilePos = new Vec2(col * tileSize.x + tileSize.x/2, row * tileSize.y + tileSize.y/2);
// Create a collider for this tile
let collider = new AABB(tilePos, tileSize.scaled(1/2));
let hit = collider.intersectSegment(start, delta, Vec2.ZERO);
if(hit !== null && start.distanceSqTo(hit.pos) < start.distanceSqTo(end)){
console.log("Found hit");
end = hit.pos;
}
}
}
}
line.start = start;
line.end = end;
line.tweens.play("fade");
}
createRequiredAssets(scene: Scene): [Line] {
let line = <Line>scene.add.graphic(GraphicType.LINE, "primary", {start: new Vec2(-1, 1), end: new Vec2(-1, -1)});
line.color = this.color;
line.tweens.add("fade", {
startDelay: 0,
duration: 300,
effects: [
{
property: TweenableProperties.alpha,
start: 1,
end: 0,
ease: EaseFunctionType.OUT_SINE
}
],
onEnd: Player_Events.UNLOAD_ASSET
});
return [line];
}
hits(node: GameNode, line: Line): boolean {
return node.collisionShape.getBoundingRect().intersectSegment(line.start, line.end.clone().sub(line.start)) !== null;
}
clone(): WeaponType {
let newType = new SemiAutoGun();
newType.initialize({color: this.hexColor,damage: this.damage, cooldown: this.cooldown, displayName: this.displayName, spriteKey: this.spriteKey, useVolume: this.useVolume});
return newType;
}
}

View File

@ -3,7 +3,7 @@ import ResourceManager from "../../Wolfie2D/ResourceManager/ResourceManager";
import WeaponType from "../GameSystems/items/WeaponTypes/WeaponType";
import Slice from "../GameSystems/items/WeaponTypes/Slice";
import SemiAutoGun from "../GameSystems/items/WeaponTypes/SemiAutoGun";
export default class WeaponTemplateRegistry extends Registry<WeaponConstructor> {
public preload(): void {
@ -13,6 +13,7 @@ export default class WeaponTemplateRegistry extends Registry<WeaponConstructor>
// Load sprites for each weapon
//rm.image("something", "shattered_sword_assets/sprites/something.png");
rm.image("knife", "shattered_sword_assets/sprites/knife.png");
rm.image("pistol", "shattered_sword_assets/sprites/pistol.png");
// Load spritesheets
//rm.spritesheet("weapon anim", "shattered_sword_assets/spritesheets/weapon anim.json");
@ -21,6 +22,7 @@ export default class WeaponTemplateRegistry extends Registry<WeaponConstructor>
// Register default types
//this.registerItem("itemtype", itemTypefile);
this.registerItem("slice", Slice);
this.registerItem("semiAutoGun", SemiAutoGun);
}

View File

@ -23,6 +23,8 @@ import EnemyAI from "../AI/EnemyAI";
import SnakeAI from "../AI/SnakeAI";
import SlimeAI from "../AI/SlimeAI";
import TigerAI from "../AI/TigerAI";
import ArcherAI from "../AI/ArcherAI";
import AssassinAI from "../AI/AssassinAi";
import BattlerAI from "../AI/BattlerAI";
import InventoryManager from "../GameSystems/InventoryManager";
import Item from "../GameSystems/items/Item";
@ -170,6 +172,7 @@ export default class GameLevel extends Scene {
this.load.image("knife", "shattered_sword_assets/sprites/knife.png");
this.load.image("pistol","shattered_sword_assets/sprites/pistol.png");
this.load.image("inventorySlot", "shattered_sword_assets/sprites/inventory.png");
this.load.image("black", "shattered_sword_assets/images/black.png");
this.load.image("poisoning", "shattered_sword_assets/images/poisoning.png");
@ -271,6 +274,12 @@ export default class GameLevel extends Scene {
while(this.receiver.hasNextEvent()){
let event = this.receiver.getNextEvent();
if(event.isType(Player_Events.UNLOAD_ASSET)){
console.log(event.data);
let asset = this.sceneGraph.getNode(event.data.get("node"));
asset.destroy();
}
if (this.gameStateStack.peek() === GameState.GAMING) {
switch(event.type){
case Player_Events.PLAYER_COLLIDE:
@ -854,8 +863,11 @@ export default class GameLevel extends Scene {
//TODO - give each enemy unique weapon
protected initializeEnemies( enemies: Enemy[]){
for (let enemy of enemies) {
switch (enemy.type) {
case "Snake": //Snake enemies drop from sky("trees")? or could just be very abundant
this.addEnemy("Snake", enemy.position.scale(32), SnakeAI, {
player: this.player,
@ -866,6 +878,7 @@ export default class GameLevel extends Scene {
exp: 50,
})
break;
case "Tiger": //Tiger can be miniboss for now?
this.addEnemy("Tiger", enemy.position.scale(32), TigerAI, {
player: this.player,
@ -936,23 +949,6 @@ export default class GameLevel extends Scene {
}
/**
* Increments the amount of life the player has
* @param amt The amount to add to the player life
*/
/*
protected incPlayerLife(amt: number): void {
GameLevel.livesCount += amt;
this.livesCountLabel.text = "Lives: " + GameLevel.livesCount;
if (GameLevel.livesCount === 0){
InputWrapper.disableInput();
this.player.disablePhysics();
this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "player_death", loop: false, holdReference: false});
this.player.tweens.play("death");
}
}
*/
/**
* Returns the player to spawn
@ -978,9 +974,6 @@ export default class GameLevel extends Scene {
this.player.position.set(this.playerSpawn.x,this.playerSpawn.y);
//TODO - decrease player health or can kill player here
//(<PlayerController>this.player._ai).CURRENT_HP *= .75;
//this.emitter.fireEvent(Player_Events.PLAYER_KILLED);
}
}

View File

@ -12,8 +12,10 @@ export enum Player_Events {
BOSS_KILLED = "BossKilled",
GIVE_REGULAR_BUFF = "GiveRegularBuff",
GIVE_SPECIAL_BUFF = "GiveSpecialBuff",
PLAYER_COLLIDE = "PlayerCollide"
PLAYER_COLLIDE = "PlayerCollide",
UNLOAD_ASSET = "UnloadAsset"
}
export enum Damage_Type {
NORMAL_DAMAGE = "NormalDamage",
ENVIRONMENT_DAMAGE = "EnvironmentDamage",