fixed archer AI, added lasergun for boss, added speed cheat, changed buff generator, fixed isplayervisible bug, added lastplayerposition to enemyAI

This commit is contained in:
OfficialCHenry 2022-05-07 23:26:48 -04:00
parent cf3c3cf860
commit 7dcf7f09dc
13 changed files with 185 additions and 28 deletions

View File

@ -1,5 +1,5 @@
{
"numWeapons": 2,
"numWeapons": 3,
"weapons": [
{
"weaponType": "slice",
@ -16,10 +16,20 @@
"name": "pistol",
"displayName": "Pistol",
"spriteKey": "pistol",
"damage": 2,
"damage": 15,
"cooldown": 500,
"useVolume": 320,
"color": "#FFEEDD"
},
{
"weaponType": "laserGun",
"name": "laserGun",
"displayName": "laserGun",
"spriteKey": "laserGun",
"damage": 30,
"cooldown": 650,
"useVolume": 320,
"color": "#15E631"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

View File

@ -2,8 +2,7 @@ import AnimatedSprite from "../../Wolfie2D/Nodes/Sprites/AnimatedSprite";
import EnemyAI, { EnemyStates } from "./EnemyAI";
import ArcherAttack from "./EnemyStates/ArcherAttack";
import Weapon from "../GameSystems/items/Weapon";
import Vec2 from "../../Wolfie2D/DataTypes/Vec2";
export default class ArcherAI extends EnemyAI {
@ -16,4 +15,8 @@ export default class ArcherAI extends EnemyAI {
this.addState(EnemyStates.ATTACK, new ArcherAttack(this, owner));
this.weapon = options.weapon;
}
canAttack(position: Vec2): boolean {
return this.attackTimer.isStopped() && this.owner.position.distanceTo(position)<=96;
}
}

View File

@ -70,6 +70,7 @@ export default class EnemyAI extends StateMachineAI implements BattlerAI {
physicWidth: number;
physicHeight: number;
lastPlayerPosition: Vec2;
initializeAI(owner: AnimatedSprite, options: Record<string, any>): void {
this.owner = owner;
@ -198,6 +199,7 @@ export default class EnemyAI extends StateMachineAI implements BattlerAI {
}
}
}
this.lastPlayerPosition = pos;
return pos;
}
@ -206,7 +208,10 @@ export default class EnemyAI extends StateMachineAI implements BattlerAI {
* @returns position of the player if visible, else null
*/
getPlayerPosition(): Vec2 {
return this.isPlayerVisible(this.player.position);
if(this.isPlayerVisible(this.player.position) == null){
return this.lastPlayerPosition;
}
return this.isPlayerVisible(this.player.position) ;
}
update(deltaT: number){

View File

@ -3,23 +3,31 @@ import AnimatedSprite from "../../../Wolfie2D/Nodes/Sprites/AnimatedSprite";
import Attack from "./Attack";
import ArcherAI from "../ArcherAI";
import Sprite from "../../../Wolfie2D/Nodes/Sprites/Sprite";
import Timer from "../../../Wolfie2D/Timing/Timer";
//TODO - unfinished
export default class ArcherAttack extends Attack {
pauseTimer : Timer;
onEnter(options: Record<string, any>): void {
super.onEnter(options);
this.pauseTimer = new Timer(1000);
this.pauseTimer.start();
}
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);
if(this.pauseTimer.isStopped()){
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);
}
super.update(deltaT);
}
onExit(): Record<string, any> {
return null;
}
}

View File

@ -21,12 +21,9 @@ export default class AssassinAttack extends Attack {
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();
}

View File

@ -67,7 +67,7 @@ export default class Weapon extends Item {
this.assets = this.type.createRequiredAssets(this.sprite.getScene());
// Do a type specific weapon animation
this.type.doAnimation(user, direction, this.EXTRA_RANGE, ...this.assets);
this.type.doAnimation(user, direction, ...this.assets, this.EXTRA_RANGE);
// Apply damage
this.battleManager.handleInteraction(userType, this, user);

View File

@ -0,0 +1,103 @@
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 laserGun 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().add(shooter.colliderOffset);
let end = shooter.position.clone().add(direction.scaled(900)).add(shooter.colliderOffset);
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.thickness = 25;
line.tweens.add("fade", {
startDelay: 0,
duration: 800,
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 laserGun();
newType.initialize({damage: this.damage, color: this.hexColor, cooldown: this.cooldown, displayName: this.displayName, spriteKey: this.spriteKey, useVolume: this.useVolume});
return newType;
}
}

View File

@ -26,8 +26,8 @@ export default class SemiAutoGun extends WeaponType {
}
doAnimation(shooter: GameNode, direction: Vec2, line: Line): void {
let start = shooter.position.clone();
let end = shooter.position.clone().add(direction.scaled(900));
let start = shooter.position.clone().add(shooter.colliderOffset);
let end = shooter.position.clone().add(direction.scaled(900)).add(shooter.colliderOffset);
let delta = end.clone().sub(start);
// Iterate through the tilemap region until we find a collision
@ -72,10 +72,11 @@ export default class SemiAutoGun extends WeaponType {
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.thickness = 5;
line.tweens.add("fade", {
startDelay: 0,
duration: 300,
duration: 600,
effects: [
{
property: TweenableProperties.alpha,

View File

@ -15,7 +15,7 @@ export default class Slice extends WeaponType {
this.useVolume = options.useVolume;
}
doAnimation(attacker: GameNode, direction: Vec2, extraRange:number,sliceSprite: AnimatedSprite): void {
doAnimation(attacker: GameNode, direction: Vec2, sliceSprite: AnimatedSprite, extraRange:number): void {
// Rotate this with the game node
// TODO - need to rotate the anim properly

View File

@ -391,7 +391,14 @@ export default class PlayerController extends StateMachineAI implements BattlerA
PlayerController.buffPool.sort(() => 0.5 - Math.random());
// Get sub-array of first 3 elements after shuffled
let shuffled = PlayerController.buffPool.slice(0, 3); //3 buff categories
//let shuffled = PlayerController.buffPool.slice(0, 3); //3 buff categories
let shuffled = new Set<BuffCategory>();
while(shuffled.size < 3){
shuffled.add(PlayerController.buffPool.slice(0,1)[0]);
PlayerController.buffPool.sort(() => 0.5 - Math.random());
}
//random number from 5 to 15 if no value given
let num = Math.floor(Math.random() *10) +5;
@ -459,8 +466,7 @@ export default class PlayerController extends StateMachineAI implements BattlerA
let selected = new Array();
while( shuffled.length != 0){
let cat = shuffled.pop();
for ( let cat of shuffled){
switch(cat){
case BuffCategory.ATTACK:
attackBuffs.sort(() => 0.5 - Math.random());
@ -532,7 +538,8 @@ export default class PlayerController extends StateMachineAI implements BattlerA
}
else if (!init){
//increase weight of selected buff category
PlayerController.buffPool.push(buff.category);
if(buff.category != BuffCategory.EXTRA)
PlayerController.buffPool.push(buff.category);
PlayerController.appliedBuffs.push(buff);
}
// TODO

View File

@ -4,6 +4,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";
import laserGun from "../GameSystems/items/WeaponTypes/laserGun";
export default class WeaponTemplateRegistry extends Registry<WeaponConstructor> {
public preload(): void {
@ -14,6 +15,7 @@ export default class WeaponTemplateRegistry extends Registry<WeaponConstructor>
//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");
rm.image("laserGun", "shattered_sword_assets/sprites/laserGun.png");
// Load spritesheets
//rm.spritesheet("weapon anim", "shattered_sword_assets/spritesheets/weapon anim.json");
@ -23,6 +25,7 @@ export default class WeaponTemplateRegistry extends Registry<WeaponConstructor>
//this.registerItem("itemtype", itemTypefile);
this.registerItem("slice", Slice);
this.registerItem("semiAutoGun", SemiAutoGun);
this.registerItem("laserGun",laserGun);
}

View File

@ -169,6 +169,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("laserGun","shattered_sword_assets/sprites/laserGun.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");
@ -555,7 +556,8 @@ export default class GameLevel extends Scene {
Player_Events.LEVEL_END,
Player_Events.PLAYER_KILLED,
Player_Events.GIVE_REGULAR_BUFF,
Player_Events.GIVE_SPECIAL_BUFF
Player_Events.GIVE_SPECIAL_BUFF,
Player_Events.UNLOAD_ASSET
]);
this.receiver.subscribe("buff1");
this.receiver.subscribe("buff2");
@ -860,10 +862,24 @@ export default class GameLevel extends Scene {
//TODO - give each enemy unique weapon
protected initializeEnemies( enemies: Enemy[]){
let pistol = this.createWeapon("pistol");
for (let enemy of enemies) {
switch (enemy.type) {
/*
case "Snake":
this.addEnemy("Archer", enemy.position.scale(32), ArcherAI, {
player: this.player,
health: 50,
tilemap: "Main",
size: new Vec2(14,10),
offset : new Vec2(0, 22),
exp: 50,
weapon: pistol
})
break;
*/
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,
@ -874,7 +890,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,
@ -1148,6 +1164,10 @@ export default class GameLevel extends Scene {
case "SLD":
(<PlayerController>this.player._ai).CURRENT_SHIELD = parseInt(commands[2]);
break;
case "SPD":
(<PlayerController>this.player._ai).speed = parseInt(commands[2]);
(<PlayerController>this.player._ai).MIN_SPEED = parseInt(commands[2]);
break;
default:
break;
}