Moved all enemy reading over to purely using config files. Removed all enemy enum dependencies. Removed bugs involving loading infinite maps by accident.

pull/28/head
sigonasr2 2 years ago
parent 13eff22485
commit 6a12a45cb2
  1. 49
      Crawler/Animation.cpp
  2. 7
      Crawler/Crawler.cpp
  3. 2
      Crawler/Crawler.h
  4. 4
      Crawler/Crawler.vcxproj
  5. 15
      Crawler/Crawler.vcxproj.filters
  6. 4
      Crawler/DEFINES.h
  7. 145
      Crawler/Monster.cpp
  8. 57
      Crawler/Monster.h
  9. 120
      Crawler/MonsterData.cpp
  10. 1
      Crawler/Player.cpp
  11. 15
      Crawler/RUN_STRATEGY.cpp
  12. 35
      Crawler/RunTowards.cpp
  13. 95
      Crawler/ShootAfar.cpp
  14. 12
      Crawler/TMXParser.h
  15. 5
      Crawler/Turret.cpp
  16. 2
      Crawler/Version.h
  17. 12
      Crawler/assets/config/MonsterStrategies.txt
  18. 65
      Crawler/assets/config/Monsters.txt
  19. 2
      Crawler/assets/config/Player.txt
  20. 1
      Crawler/assets/config/gfx/gfx.txt
  21. BIN
      Crawler/assets/monsters/Blue Slime.png
  22. BIN
      Crawler/assets/monsters/Flower Turret.png
  23. BIN
      Crawler/assets/monsters/Flower Turret.xcf
  24. BIN
      Crawler/assets/monsters/Green Slime.png
  25. BIN
      Crawler/assets/monsters/Red Slime.png
  26. BIN
      Crawler/assets/monsters/Yellow Slime.png

@ -171,55 +171,6 @@ void sig::Animation::InitializeAnimations(){
} }
ANIMATION_DATA["WIZARD_CAST_W"]=pl_wizard_cast_w; ANIMATION_DATA["WIZARD_CAST_W"]=pl_wizard_cast_w;
//Load slime animations.
for(int slime=0;slime<4;slime++){
std::string colorName="";
switch(slime){
case 0:{
colorName="GREEN";
}break;
case 1:{
colorName="BLUE";
}break;
case 2:{
colorName="RED";
}break;
case 3:{
colorName="YELLOW";
}break;
}
for(int state=0;state<5;state++){
Animate2D::FrameSequence anim;
if(state==4){//These are death animations.
anim=Animate2D::FrameSequence(0.1f,Animate2D::Style::OneShot);
}
if(state==2){//These are death animations.
anim=Animate2D::FrameSequence(0.06f);
}
for (int frame=0;frame<10;frame++){
anim.AddFrame({&game->GFX_Slime_Sheet,{vi2d{frame,state+5*slime}*24,{24,24}}});
}
std::string stateName="";
switch(state){
case 0:{
stateName="IDLE";
}break;
case 1:{
stateName="ROLL";
}break;
case 2:{
stateName="JUMP";
}break;
case 3:{
stateName="SPIT";
}break;
case 4:{
stateName="DIE";
}break;
}
ANIMATION_DATA[colorName+"_SLIME_"+stateName]=anim;
}
}
CreateHorizontalAnimationSequence(game->GFX_Effect_GroundSlam_Back,5,{64,64},"GROUND_SLAM_ATTACK_BACK",{0.02,Animate2D::Style::OneShot}); CreateHorizontalAnimationSequence(game->GFX_Effect_GroundSlam_Back,5,{64,64},"GROUND_SLAM_ATTACK_BACK",{0.02,Animate2D::Style::OneShot});
CreateHorizontalAnimationSequence(game->GFX_Effect_GroundSlam_Front,5,{64,64},"GROUND_SLAM_ATTACK_FRONT",{0.02,Animate2D::Style::OneShot}); CreateHorizontalAnimationSequence(game->GFX_Effect_GroundSlam_Front,5,{64,64},"GROUND_SLAM_ATTACK_FRONT",{0.02,Animate2D::Style::OneShot});
CreateHorizontalAnimationSequence(game->GFX_Battlecry_Effect,5,{84,84},"BATTLECRY_EFFECT",{0.02,Animate2D::Style::OneShot}); CreateHorizontalAnimationSequence(game->GFX_Battlecry_Effect,5,{84,84},"BATTLECRY_EFFECT",{0.02,Animate2D::Style::OneShot});

@ -94,7 +94,6 @@ bool Crawler::OnUserCreate(){
//Graphics //Graphics
LOADIMG(GFX_Warrior_Sheet) LOADIMG(GFX_Warrior_Sheet)
LOADIMG(GFX_Slime_Sheet)
LOADIMG(GFX_Circle) LOADIMG(GFX_Circle)
LOADIMG(GFX_Effect_GroundSlam_Back) LOADIMG(GFX_Effect_GroundSlam_Back)
LOADIMG(GFX_Effect_GroundSlam_Front) LOADIMG(GFX_Effect_GroundSlam_Front)
@ -904,14 +903,12 @@ void Crawler::LoadLevel(MapName map){
for(auto key:MAP_DATA[map].SpawnerData){ for(auto key:MAP_DATA[map].SpawnerData){
SpawnerTag&spawnData=MAP_DATA[map].SpawnerData[key.first]; SpawnerTag&spawnData=MAP_DATA[map].SpawnerData[key.first];
std::vector<std::pair<MonsterName,vf2d>>monster_list; std::vector<std::pair<int,vf2d>>monster_list;
vf2d spawnerRadius=vf2d{spawnData.ObjectData.GetFloat("width"),spawnData.ObjectData.GetFloat("height")}/2; vf2d spawnerRadius=vf2d{spawnData.ObjectData.GetFloat("width"),spawnData.ObjectData.GetFloat("height")}/2;
for(XMLTag&monster:spawnData.monsters){ for(XMLTag&monster:spawnData.monsters){
int monsterTypeID=monster.GetInteger("value")-1; int monsterTypeID=monster.GetInteger("value")-1;
if(monsterTypeID>=0&&monsterTypeID<MonsterName::END){ monster_list.push_back({monsterTypeID,{monster.GetInteger("x")-spawnData.ObjectData.GetFloat("x"),monster.GetInteger("y")-spawnData.ObjectData.GetFloat("y")}});
monster_list.push_back({MonsterName(monsterTypeID),{monster.GetInteger("x")-spawnData.ObjectData.GetFloat("x"),monster.GetInteger("y")-spawnData.ObjectData.GetFloat("y")}});
}
} }
SPAWNER_LIST.push_back(MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list,spawnData.upperLevel}); SPAWNER_LIST.push_back(MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list,spawnData.upperLevel});
} }

@ -22,7 +22,7 @@ class Crawler : public olc::PixelGameEngine
friend class sig::Animation; friend class sig::Animation;
Camera2D camera; Camera2D camera;
std::unique_ptr<Player>player; std::unique_ptr<Player>player;
Renderable GFX_Warrior_Sheet,GFX_Slime_Sheet, Renderable GFX_Warrior_Sheet,
GFX_Effect_GroundSlam_Back,GFX_Effect_GroundSlam_Front, GFX_Effect_GroundSlam_Back,GFX_Effect_GroundSlam_Front,
GFX_Heart,GFX_BLOCK_BUBBLE,GFX_Ranger_Sheet,GFX_Wizard_Sheet, GFX_Heart,GFX_BLOCK_BUBBLE,GFX_Ranger_Sheet,GFX_Wizard_Sheet,
GFX_Battlecry_Effect,GFX_Mana,GFX_SonicSlash,GFX_EnergyParticle, GFX_Battlecry_Effect,GFX_Mana,GFX_SonicSlash,GFX_EnergyParticle,

@ -305,6 +305,7 @@
<ClCompile Include="LightningBoltEmitter.cpp" /> <ClCompile Include="LightningBoltEmitter.cpp" />
<ClCompile Include="Map.cpp" /> <ClCompile Include="Map.cpp" />
<ClCompile Include="Meteor.cpp" /> <ClCompile Include="Meteor.cpp" />
<ClCompile Include="RunTowards.cpp" />
<ClCompile Include="Pathfinding.cpp" /> <ClCompile Include="Pathfinding.cpp" />
<ClCompile Include="pixelGameEngine.cpp" /> <ClCompile Include="pixelGameEngine.cpp" />
<ClCompile Include="Player.cpp" /> <ClCompile Include="Player.cpp" />
@ -312,8 +313,11 @@
<ClCompile Include="MonsterData.cpp" /> <ClCompile Include="MonsterData.cpp" />
<ClCompile Include="PulsatingFire.cpp" /> <ClCompile Include="PulsatingFire.cpp" />
<ClCompile Include="Ranger.cpp" /> <ClCompile Include="Ranger.cpp" />
<ClCompile Include="RUN_STRATEGY.cpp" />
<ClCompile Include="ShootAfar.cpp" />
<ClCompile Include="Thief.cpp" /> <ClCompile Include="Thief.cpp" />
<ClCompile Include="Trapper.cpp" /> <ClCompile Include="Trapper.cpp" />
<ClCompile Include="Turret.cpp" />
<ClCompile Include="Warrior.cpp" /> <ClCompile Include="Warrior.cpp" />
<ClCompile Include="utils.cpp" /> <ClCompile Include="utils.cpp" />
<ClCompile Include="Witch.cpp" /> <ClCompile Include="Witch.cpp" />

@ -37,6 +37,9 @@
<Filter Include="Configurations\Classes"> <Filter Include="Configurations\Classes">
<UniqueIdentifier>{fd547111-0670-4be5-85cf-28fbd92c765f}</UniqueIdentifier> <UniqueIdentifier>{fd547111-0670-4be5-85cf-28fbd92c765f}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Source Files\Monster Strategies">
<UniqueIdentifier>{3d2f7a3f-5781-45ab-a66d-c6d57d9de13c}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="olcPixelGameEngine.h"> <ClInclude Include="olcPixelGameEngine.h">
@ -215,6 +218,18 @@
<ClCompile Include="ChargedArrow.cpp"> <ClCompile Include="ChargedArrow.cpp">
<Filter>Source Files\Bullet Types</Filter> <Filter>Source Files\Bullet Types</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="RunTowards.cpp">
<Filter>Source Files\Monster Strategies</Filter>
</ClCompile>
<ClCompile Include="ShootAfar.cpp">
<Filter>Source Files\Monster Strategies</Filter>
</ClCompile>
<ClCompile Include="Turret.cpp">
<Filter>Source Files\Monster Strategies</Filter>
</ClCompile>
<ClCompile Include="RUN_STRATEGY.cpp">
<Filter>Source Files\Monster Strategies</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="cpp.hint" /> <None Include="cpp.hint" />

@ -4,12 +4,12 @@
#define INCLUDE_SPAWNER_LIST extern std::vector<MonsterSpawner>SPAWNER_LIST; #define INCLUDE_SPAWNER_LIST extern std::vector<MonsterSpawner>SPAWNER_LIST;
#define INCLUDE_DAMAGENUMBER_LIST extern std::vector<std::shared_ptr<DamageNumber>>DAMAGENUMBER_LIST; #define INCLUDE_DAMAGENUMBER_LIST extern std::vector<std::shared_ptr<DamageNumber>>DAMAGENUMBER_LIST;
#define INCLUDE_game extern Crawler*game; #define INCLUDE_game extern Crawler*game;
#define INCLUDE_MONSTER_DATA extern std::map<MonsterName,MonsterData>MONSTER_DATA; #define INCLUDE_MONSTER_DATA extern std::map<int,MonsterData>MONSTER_DATA;
#define INCLUDE_BULLET_LIST extern std::vector<std::unique_ptr<Bullet>>BULLET_LIST; #define INCLUDE_BULLET_LIST extern std::vector<std::unique_ptr<Bullet>>BULLET_LIST;
#define INCLUDE_PARTICLE_LIST extern std::vector<Particle>PARTICLE_LIST; #define INCLUDE_PARTICLE_LIST extern std::vector<Particle>PARTICLE_LIST;
#define INCLUDE_EMITTER_LIST extern std::vector<std::unique_ptr<Emitter>>EMITTER_LIST; #define INCLUDE_EMITTER_LIST extern std::vector<std::unique_ptr<Emitter>>EMITTER_LIST;
#define INCLUDE_DATA extern utils::datafile DATA; #define INCLUDE_DATA extern utils::datafile DATA;
#define INCLUDE_STRATEGY_DATA extern safemap<std::string,MonsterStrategy>STRATEGY_DATA; #define INCLUDE_STRATEGY_DATA extern safemap<std::string,int>STRATEGY_DATA;
#define ACCESS_PLAYER Player*p=game->GetPlayer(); #define ACCESS_PLAYER Player*p=game->GetPlayer();

@ -15,10 +15,11 @@ INCLUDE_BULLET_LIST
INCLUDE_DATA INCLUDE_DATA
INCLUDE_STRATEGY_DATA INCLUDE_STRATEGY_DATA
safemap<std::string,MonsterStrategy>STRATEGY_DATA; safemap<std::string,int>STRATEGY_DATA;
std::map<int,Renderable*>MonsterData::imgs;
Monster::Monster(vf2d pos,MonsterData data,bool upperLevel): Monster::Monster(vf2d pos,MonsterData data,bool upperLevel):
pos(pos),hp(data.GetHealth()),maxhp(data.GetHealth()),atk(data.GetAttack()),moveSpd(data.GetMoveSpdMult()),size(data.GetSizeMult()),strategy(data.GetAIStrategy()),type(data.GetType()),upperLevel(upperLevel){ pos(pos),hp(data.GetHealth()),maxhp(data.GetHealth()),atk(data.GetAttack()),moveSpd(data.GetMoveSpdMult()),size(data.GetSizeMult()),strategy(data.GetAIStrategy()),id(data.GetID()),upperLevel(upperLevel){
bool firstAnimation=true; bool firstAnimation=true;
for(std::string&anim:data.GetAnimations()){ for(std::string&anim:data.GetAnimations()){
animation.AddState(anim,ANIMATION_DATA[anim]); animation.AddState(anim,ANIMATION_DATA[anim]);
@ -59,10 +60,13 @@ void Monster::UpdateAnimation(std::string state){
animation.ChangeState(internal_animState,state); animation.ChangeState(internal_animState,state);
} }
void Monster::PerformJumpAnimation(){ void Monster::PerformJumpAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[type].GetJumpAnimation()); animation.ChangeState(internal_animState,MONSTER_DATA[id].GetJumpAnimation());
} }
void Monster::PerformShootAnimation(){ void Monster::PerformShootAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[type].GetShootAnimation()); animation.ChangeState(internal_animState,MONSTER_DATA[id].GetShootAnimation());
}
void Monster::PerformIdleAnimation(){
animation.ChangeState(internal_animState,MONSTER_DATA[id].GetIdleAnimation());
} }
bool Monster::SetX(float x){ bool Monster::SetX(float x){
vf2d newPos={x,pos.y}; vf2d newPos={x,pos.y};
@ -138,124 +142,7 @@ bool Monster::Update(float fElapsedTime){
facingDirection=LEFT; facingDirection=LEFT;
} }
} }
switch(strategy){ Monster::STRATEGY::RUN_STRATEGY(*this,fElapsedTime);
case RUN_TOWARDS:{
targetAcquireTimer=std::max(0.f,targetAcquireTimer-fElapsedTime);
if(targetAcquireTimer==0){
targetAcquireTimer=3;
target=geom2d::line(pos,game->GetPlayer()->GetPos()).upoint(1.2);
SetState(MOVE_TOWARDS);
hasHitPlayer=false;
}
switch(state){
case MOVE_TOWARDS:{
if(geom2d::line(pos,target).length()>100*fElapsedTime*GetMoveSpdMult()){
vf2d newPos=pos+geom2d::line(pos,target).vector().norm()*100*fElapsedTime*GetMoveSpdMult();
if(!SetX(newPos.x)||!SetY(newPos.y)){
StartPathfinding(4);
}
PerformJumpAnimation();
} else {
SetState(NORMAL);//Revert state once we've finished moving towards target.
UpdateAnimation(MONSTER_DATA[type].GetAnimations()[0]);
}
}break;
case PATH_AROUND:{
PathAroundBehavior(fElapsedTime);
}break;
default:{
}
}
}break;
case SHOOT_AFAR:{
targetAcquireTimer=std::max(0.f,targetAcquireTimer-fElapsedTime);
attackCooldownTimer=std::max(0.f,attackCooldownTimer-fElapsedTime);
if(queueShotTimer>0){
queueShotTimer-=fElapsedTime;
if(queueShotTimer<0){
queueShotTimer=0;
{
BULLET_LIST.push_back(std::make_unique<Bullet>(Bullet(pos + vf2d{ 0,-4 }, geom2d::line(pos + vf2d{ 0,-4 }, game->GetPlayer()->GetPos()).vector().norm() * 24 * 3.f, 2, GetAttack(),upperLevel,false, { 75 / 2,162 / 2,225 / 2 })));
}
}
}
geom2d::line line(pos,game->GetPlayer()->GetPos());
if(targetAcquireTimer==0&&queueShotTimer==0){
targetAcquireTimer=1;
if(line.length()<24*6){
target=line.upoint(-1.2);
if(canMove){
SetState(MOVE_AWAY);
} else {
SetState(NORMAL);
}
} else
if(line.length()>24*7){
target=line.upoint(1.2);
SetState(MOVE_TOWARDS);
} else {
SetState(NORMAL);
}
}
canMove=true;
geom2d::line moveTowardsLine=geom2d::line(pos,target);
bool pathfindingDecision=false;
switch(state){
case MOVE_TOWARDS:{
if(moveTowardsLine.length()>1){
vf2d newPos=pos+moveTowardsLine.vector().norm()*100*fElapsedTime*GetMoveSpdMult();
bool movedX=SetX(newPos.x);
bool movedY=SetY(newPos.y);
pathfindingDecision=movedX|movedY;
canMove=movedX&&movedY;
}
if(!pathfindingDecision){
StartPathfinding(2.5);
}else
if(line.length()<=24*7){
SetState(NORMAL);
}
if(moveTowardsLine.vector().x>0){
facingDirection=RIGHT;
} else {
facingDirection=LEFT;
}
PerformJumpAnimation();
}break;
case MOVE_AWAY:{
if(moveTowardsLine.length()>1){
vf2d newPos=pos+moveTowardsLine.vector().norm()*100*fElapsedTime*GetMoveSpdMult();
bool movedX=SetX(newPos.x);
bool movedY=SetY(newPos.y);
pathfindingDecision=movedX|movedY;
canMove=movedX&&movedY;
}
if(!pathfindingDecision){
StartPathfinding(2.5);
}else
if(line.length()>=24*6){
SetState(NORMAL);
}
if(moveTowardsLine.vector().x>0){
facingDirection=RIGHT;
} else {
facingDirection=LEFT;
}
PerformJumpAnimation();
}break;
case PATH_AROUND:{
PathAroundBehavior(fElapsedTime);
}break;
default:{
if(attackCooldownTimer==0){
attackCooldownTimer=1;
queueShotTimer=0.7;
PerformShootAnimation();
}
}
}
}break;
}
if(vel.x>0){ if(vel.x>0){
vel.x=std::max(0.f,vel.x-friction*fElapsedTime); vel.x=std::max(0.f,vel.x-friction*fElapsedTime);
} else { } else {
@ -292,9 +179,9 @@ void Monster::Draw(){
} }
} }
void Monster::Collision(Player*p){ void Monster::Collision(Player*p){
if(MONSTER_DATA[type].GetCollisionDmg()>0&&!hasHitPlayer){ if(MONSTER_DATA[id].GetCollisionDmg()>0&&!hasHitPlayer){
hasHitPlayer=true; hasHitPlayer=true;
p->Hurt(MONSTER_DATA[type].GetCollisionDmg(),OnUpperLevel()); p->Hurt(MONSTER_DATA[id].GetCollisionDmg(),OnUpperLevel());
} }
Collision(); Collision();
} }
@ -302,7 +189,7 @@ void Monster::Collision(Monster&m){
Collision(); Collision();
} }
void Monster::Collision(){ void Monster::Collision(){
if(strategy==RUN_TOWARDS&&GetState()==MOVE_TOWARDS){ if(strategy==0&&GetState()==MOVE_TOWARDS){//The run towards strategy causes state to return to normal upon a collision.
SetState(NORMAL); SetState(NORMAL);
} }
} }
@ -331,7 +218,7 @@ void Monster::Moved(){
} }
} }
std::string Monster::GetDeathAnimationName(){ std::string Monster::GetDeathAnimationName(){
return MONSTER_DATA[type].GetDeathAnimation(); return MONSTER_DATA[id].GetDeathAnimation();
} }
bool Monster::Hurt(int damage,bool onUpperLevel){ bool Monster::Hurt(int damage,bool onUpperLevel){
if(hp<=0||onUpperLevel!=OnUpperLevel()) return false; if(hp<=0||onUpperLevel!=OnUpperLevel()) return false;
@ -363,7 +250,7 @@ vf2d&Monster::GetTargetPos(){
} }
MonsterSpawner::MonsterSpawner(){} MonsterSpawner::MonsterSpawner(){}
MonsterSpawner::MonsterSpawner(vf2d pos,vf2d range,std::vector<std::pair<MonsterName,vf2d>>monsters,bool upperLevel): MonsterSpawner::MonsterSpawner(vf2d pos,vf2d range,std::vector<std::pair<int,vf2d>>monsters,bool upperLevel):
pos(pos),range(range),monsters(monsters),upperLevel(upperLevel){ pos(pos),range(range),monsters(monsters),upperLevel(upperLevel){
} }
bool MonsterSpawner::SpawnTriggered(){ bool MonsterSpawner::SpawnTriggered(){
@ -378,7 +265,7 @@ vf2d MonsterSpawner::GetPos(){
void MonsterSpawner::SetTriggered(bool trigger,bool spawnMonsters){ void MonsterSpawner::SetTriggered(bool trigger,bool spawnMonsters){
triggered=trigger; triggered=trigger;
if(spawnMonsters){ if(spawnMonsters){
for(std::pair<MonsterName,vf2d>&monsterInfo:monsters){ for(std::pair<int,vf2d>&monsterInfo:monsters){
MONSTER_LIST.push_back(Monster(pos+monsterInfo.second,MONSTER_DATA[monsterInfo.first],DoesUpperLevelSpawning())); MONSTER_LIST.push_back(Monster(pos+monsterInfo.second,MONSTER_DATA[monsterInfo.first],DoesUpperLevelSpawning()));
} }
} }
@ -448,7 +335,7 @@ void Monster::SetState(State newState){
void Monster::InitializeStrategies(){ void Monster::InitializeStrategies(){
int readCounter=0; int readCounter=0;
while(DATA["MonsterStrategy"].HasProperty(std::to_string(readCounter))){ while(DATA["MonsterStrategy"].HasProperty(std::to_string(readCounter))){
STRATEGY_DATA[DATA["MonsterStrategy"][std::to_string(readCounter)]["Name"].GetString()]=MonsterStrategy(readCounter); STRATEGY_DATA[DATA["MonsterStrategy"][std::to_string(readCounter)]["Name"].GetString()]=readCounter;
readCounter++; readCounter++;
} }
STRATEGY_DATA.SetInitialized(); STRATEGY_DATA.SetInitialized();

@ -8,52 +8,38 @@
struct Player; struct Player;
enum MonsterStrategy{ enum MonsterAnimation{
/// <summary> IDLE,
/// NOTE: When adding a new strategy, update MonsterStrategies.txt!! JUMP,
/// </summary> SHOOT,
RUN_TOWARDS, DEATH
SHOOT_AFAR,
TURRET
};
enum MonsterName{
SLIME_GREEN,
SLIME_BLUE,
SLIME_RED,
SLIME_YELLOW,
FLOWER_TURRET,
///////////////////////////////////////////////////////////////////////////////////////////////////////////
/*//*/END,//Used for detecting the end of the list, DO NOT USE OR TOUCH. Add all monsters above this//*//*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////
}; };
struct MonsterData{ struct MonsterData{
private: private:
int id;
std::string name;
int hp; int hp;
int atk; int atk;
float moveSpd;//1.0=100% float moveSpd;//1.0=100%
float size; float size;
std::vector<std::string> animations; std::vector<std::string> animations;
MonsterStrategy strategy; int strategy;
MonsterName type;
int collisionDmg; int collisionDmg;
std::string jumpAnimation="WARRIOR_IDLE_S"; std::string jumpAnimation="WARRIOR_IDLE_S";
std::string shootAnimation="WARRIOR_IDLE_S"; std::string shootAnimation="WARRIOR_IDLE_S";
std::string deathAnimation="WARRIOR_IDLE_S"; std::string deathAnimation="WARRIOR_IDLE_S";
public: public:
MonsterData(); MonsterData();
//When specifying animations, the first one will become the default animation. The last becomes the death animation. MonsterData(int id,std::string name,int hp,int atk,std::vector<std::string>animations,float moveSpd=1.0f,float size=1.0f,int strategy=0,int collisionDmg=0);
MonsterData(MonsterName type,int hp,int atk,std::vector<std::string>animations,std::string jumpAnimation,std::string shootAnimation,std::string deathAnimation,float moveSpd=1.0f,float size=1.0f,MonsterStrategy strategy=RUN_TOWARDS,int collisionDmg=0);
int GetHealth(); int GetHealth();
int GetAttack(); int GetAttack();
float GetMoveSpdMult(); float GetMoveSpdMult();
float GetSizeMult(); float GetSizeMult();
MonsterName GetType(); int GetAIStrategy();
MonsterStrategy GetAIStrategy();
int GetCollisionDmg(); int GetCollisionDmg();
int GetID();
std::string GetIdleAnimation();
std::string GetJumpAnimation(); std::string GetJumpAnimation();
std::string GetShootAnimation(); std::string GetShootAnimation();
std::string GetDeathAnimation(); std::string GetDeathAnimation();
@ -61,10 +47,13 @@ struct MonsterData{
return animations; return animations;
} }
static void InitializeMonsterData(); static void InitializeMonsterData();
static std::map<int,Renderable*>imgs;
}; };
struct Monster{ struct Monster{
friend struct STRATEGY;
private: private:
int id=0;
vf2d pos; vf2d pos;
vf2d vel={0,0}; vf2d vel={0,0};
float friction=400; float friction=400;
@ -77,13 +66,12 @@ struct Monster{
float attackCooldownTimer=0; float attackCooldownTimer=0;
float queueShotTimer=0; float queueShotTimer=0;
Key facingDirection; Key facingDirection;
MonsterStrategy strategy; int strategy;
State state=State::NORMAL; State state=State::NORMAL;
Animate2D::Animation<std::string>animation; Animate2D::Animation<std::string>animation;
Animate2D::AnimationState internal_animState; Animate2D::AnimationState internal_animState;
float randomFrameOffset=0.f; float randomFrameOffset=0.f;
float deathTimer=0.f; float deathTimer=0.f;
MonsterName type;
std::vector<Buff>buffList; std::vector<Buff>buffList;
std::string GetDeathAnimationName(); std::string GetDeathAnimationName();
bool hasHitPlayer=false; bool hasHitPlayer=false;
@ -125,6 +113,7 @@ public:
bool SetY(float y); bool SetY(float y);
void PerformJumpAnimation(); void PerformJumpAnimation();
void PerformShootAnimation(); void PerformShootAnimation();
void PerformIdleAnimation();
bool OnUpperLevel(); bool OnUpperLevel();
void Moved(); void Moved();
void StartPathfinding(float pathingTime); void StartPathfinding(float pathingTime);
@ -134,19 +123,27 @@ public:
State GetState(); State GetState();
void SetState(State newState); void SetState(State newState);
static void InitializeStrategies(); static void InitializeStrategies();
private:
static struct STRATEGY{
static void RUN_STRATEGY(Monster&m,float fElapsedTime);
static void RUN_TOWARDS(Monster&m,float fElapsedTime);
static void SHOOT_AFAR(Monster&m,float fElapsedTime);
static void TURRET(Monster&m,float fElapsedTime);
};
}; };
struct MonsterSpawner{ struct MonsterSpawner{
private: private:
vf2d pos; vf2d pos;
vf2d range; vf2d range;
std::vector<std::pair<MonsterName,vf2d>>monsters; std::vector<std::pair<int,vf2d>>monsters;
bool triggered=false; bool triggered=false;
bool upperLevel=false; bool upperLevel=false;
public: public:
MonsterSpawner(); MonsterSpawner();
//For the monster list, the second pair item is the position relative to the spawner to spawn the monster. //For the monster list, the second pair item is the position relative to the spawner to spawn the monster.
MonsterSpawner(vf2d pos,vf2d range,std::vector<std::pair<MonsterName,vf2d>>MONSTER_LIST,bool upperLevel=false); MonsterSpawner(vf2d pos,vf2d range,std::vector<std::pair<int,vf2d>>MONSTER_LIST,bool upperLevel=false);
bool SpawnTriggered(); bool SpawnTriggered();
vf2d GetRange(); vf2d GetRange();
vf2d GetPos(); vf2d GetPos();

@ -7,47 +7,98 @@
INCLUDE_DATA INCLUDE_DATA
INCLUDE_STRATEGY_DATA INCLUDE_STRATEGY_DATA
INCLUDE_ANIMATION_DATA
std::map<MonsterName,MonsterData>MONSTER_DATA; std::map<int,MonsterData>MONSTER_DATA;
MonsterData::MonsterData(){} MonsterData::MonsterData(){}
MonsterData::MonsterData(MonsterName type,int hp,int atk,std::vector<std::string>animations,std::string jumpAnimation,std::string shootAnimation,std::string deathAnimation MonsterData::MonsterData(int id,std::string name,int hp,int atk,std::vector<std::string>animations,float moveSpd,float size,int strategy,int collisionDmg):
,float moveSpd,float size,MonsterStrategy strategy,int collisionDmg): id(id),name(name),hp(hp),atk(atk),moveSpd(moveSpd),size(size),strategy(strategy),animations(animations),collisionDmg(collisionDmg){}
type(type),hp(hp),atk(atk),moveSpd(moveSpd),size(size),strategy(strategy),animations(animations),collisionDmg(collisionDmg)
,jumpAnimation(jumpAnimation),shootAnimation(shootAnimation),deathAnimation(deathAnimation){
}
void MonsterData::InitializeMonsterData(){ void MonsterData::InitializeMonsterData(){
for(int i=0;i<MonsterName::END;i++){ int id=0;
std::string ID=DATA["Monsters"][std::to_string(i)]["DisplayName"].GetString(1); while(DATA["Monsters"].HasProperty(std::to_string(id))){
std::string MonsterName=DATA["Monsters"][std::to_string(id)]["DisplayName"].GetString();
std::vector<std::string>animations{ std::vector<std::string>animations{
ID+"_JUMP", MonsterName+"_IDLE",
ID+"_SPIT", MonsterName+"_JUMP",
ID+"_DIE", MonsterName+"_SPIT",
ID+"_IDLE", MonsterName+"_DIE",
}; };
MonsterData::imgs[id]=new Renderable();
MonsterData::imgs[id]->Load("assets/monsters/"+MonsterName+".png");
for(int i=0;i<animations.size();i++){
std::string animationConfigName="";
std::string imgName="";
switch(i){
case 0:{
animationConfigName="Idle";
imgName="_IDLE";
}break;
case 1:{
animationConfigName="Jump";
imgName="_JUMP";
}break;
case 2:{
animationConfigName="Shoot";
imgName="_SPIT";
}break;
case 3:{
animationConfigName="Death";
imgName="_DIE";
}break;
}
Animate2D::Style style=Animate2D::Style::Repeat;
if(DATA["Monsters"][std::to_string(id)][animationConfigName+"Animation"].GetString(2)=="Repeat"){
style=Animate2D::Style::Repeat;
} else
if(DATA["Monsters"][std::to_string(id)][animationConfigName+"Animation"].GetString(2)=="OneShot"){
style=Animate2D::Style::OneShot;
} else
if(DATA["Monsters"][std::to_string(id)][animationConfigName+"Animation"].GetString(2)=="PingPong"){
style=Animate2D::Style::PingPong;
} else
if(DATA["Monsters"][std::to_string(id)][animationConfigName+"Animation"].GetString(2)=="Reverse"){
style=Animate2D::Style::Reverse;
}
auto CreateHorizontalAnimationSequence=[&](Renderable&img,int frameCount,vf2d size,std::string state,int row,AnimationData data={}){
Animate2D::FrameSequence anim(data.frameDuration,data.style);
for(int i=0;i<frameCount;i++){
anim.AddFrame({&img,{{int(i*size.x),int(row*size.y)},size}});
}
ANIMATION_DATA[state]=anim;
};
int frameCount = DATA["Monsters"][std::to_string(id)][animationConfigName+"Animation"].GetInt(0);
vf2d frameSize = vf2d{float(DATA["Monsters"][std::to_string(id)]["SheetFrameSize"].GetInt(0)),float(DATA["Monsters"][std::to_string(id)]["SheetFrameSize"].GetInt(1))};
CreateHorizontalAnimationSequence(*MonsterData::imgs[id],frameCount,frameSize,MonsterName+imgName,i,AnimationData{float(DATA["Monsters"][std::to_string(id)][animationConfigName+"Animation"].GetReal(1)),style});
}
//Add additional custom animations defined in the config. //Add additional custom animations defined in the config.
int animationCounter=0; int animationCounter=0;
while(DATA["Monsters"][std::to_string(i)].HasProperty("ANIMATION["+std::to_string(animationCounter)+"]")){ while(DATA["Monsters"][std::to_string(id)].HasProperty("ANIMATION["+std::to_string(animationCounter)+"]")){
animations.push_back(DATA["Monsters"][std::to_string(i)]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString()); animations.push_back(DATA["Monsters"][std::to_string(id)]["ANIMATION["+std::to_string(animationCounter)+"]"].GetString());
animationCounter++; animationCounter++;
} }
MonsterData monster( MonsterData monster(
MonsterName(i), id,
DATA["Monsters"][std::to_string(i)]["Health"].GetInt(), MonsterName,
DATA["Monsters"][std::to_string(i)]["Attack"].GetInt(), DATA["Monsters"][std::to_string(id)]["Health"].GetInt(),
DATA["Monsters"][std::to_string(id)]["Attack"].GetInt(),
animations, animations,
ID+"_JUMP", DATA["Monsters"][std::to_string(id)]["MoveSpd"].GetReal()/100,
ID+"_SPIT", DATA["Monsters"][std::to_string(id)]["Size"].GetReal()/100,
ID+"_DIE", STRATEGY_DATA[DATA["Monsters"][std::to_string(id)]["Strategy"].GetString()],
DATA["Monsters"][std::to_string(i)]["MoveSpd"].GetReal()/100, DATA["Monsters"][std::to_string(id)]["CollisionDmg"].GetInt()
DATA["Monsters"][std::to_string(i)]["Size"].GetReal()/100,
STRATEGY_DATA[DATA["Monsters"][std::to_string(i)]["Strategy"].GetString()],
DATA["Monsters"][std::to_string(i)]["CollisionDmg"].GetInt()
); );
MONSTER_DATA[MonsterName(i)]=monster; MONSTER_DATA[id]=monster;
id++;
} }
} }
int MonsterData::GetHealth(){ int MonsterData::GetHealth(){
@ -65,21 +116,22 @@ float MonsterData::GetSizeMult(){
int MonsterData::GetCollisionDmg(){ int MonsterData::GetCollisionDmg(){
return collisionDmg; return collisionDmg;
} }
MonsterName MonsterData::GetType(){ int MonsterData::GetID(){
return type; return id;
} }
MonsterStrategy MonsterData::GetAIStrategy(){ int MonsterData::GetAIStrategy(){
return strategy; return strategy;
} }
std::string MonsterData::GetIdleAnimation(){
return animations[IDLE];
}
std::string MonsterData::GetJumpAnimation(){ std::string MonsterData::GetJumpAnimation(){
return jumpAnimation; return animations[JUMP];
} }
std::string MonsterData::GetShootAnimation(){ std::string MonsterData::GetShootAnimation(){
return shootAnimation; return animations[SHOOT];
} }
std::string MonsterData::GetDeathAnimation(){
std::string MonsterData::GetDeathAnimation() return animations[DEATH];
{
return deathAnimation;
} }

@ -169,6 +169,7 @@ void Player::Knockback(vf2d vel){
} }
void Player::Update(float fElapsedTime){ void Player::Update(float fElapsedTime){
Ability&rightClickAbility=GetRightClickAbility(), Ability&rightClickAbility=GetRightClickAbility(),
&ability=GetAbility1(), &ability=GetAbility1(),
&ability2=GetAbility2(), &ability2=GetAbility2(),

@ -0,0 +1,15 @@
#include "Monster.h"
void Monster::STRATEGY::RUN_STRATEGY(Monster&m,float fElapsedTime){
switch(m.strategy){
case 0:{//Run Towards
Monster::STRATEGY::RUN_TOWARDS(m,fElapsedTime);
}break;
case 1:{//Shoot Afar
Monster::STRATEGY::SHOOT_AFAR(m,fElapsedTime);
}break;
case 2:{//Turret.
Monster::STRATEGY::TURRET(m,fElapsedTime);
}break;
}
}

@ -0,0 +1,35 @@
#include "Monster.h"
#include "DEFINES.h"
#include "Crawler.h"
INCLUDE_game
INCLUDE_MONSTER_DATA
void Monster::STRATEGY::RUN_TOWARDS(Monster&m,float fElapsedTime){
m.targetAcquireTimer=std::max(0.f,m.targetAcquireTimer-fElapsedTime);
if(m.targetAcquireTimer==0){
m.targetAcquireTimer=3;
m.target=geom2d::line(m.pos,game->GetPlayer()->GetPos()).upoint(1.2);
m.SetState(MOVE_TOWARDS);
m.hasHitPlayer=false;
}
switch(m.state){
case MOVE_TOWARDS:{
if(geom2d::line(m.pos,m.target).length()>100*fElapsedTime*m.GetMoveSpdMult()){
vf2d newPos=m.pos+geom2d::line(m.pos,m.target).vector().norm()*100*fElapsedTime*m.GetMoveSpdMult();
if(!m.SetX(newPos.x)||!m.SetY(newPos.y)){
m.StartPathfinding(4);
}
m.PerformJumpAnimation();
} else {
m.SetState(NORMAL);//Revert state once we've finished moving towards target.
m.UpdateAnimation(MONSTER_DATA[m.id].GetIdleAnimation());
}
}break;
case PATH_AROUND:{
m.PathAroundBehavior(fElapsedTime);
}break;
default:{
}
}
}

@ -0,0 +1,95 @@
#include "Monster.h"
#include "DEFINES.h"
#include "Crawler.h"
INCLUDE_BULLET_LIST
INCLUDE_game
void Monster::STRATEGY::SHOOT_AFAR(Monster&m,float fElapsedTime){
m.targetAcquireTimer=std::max(0.f,m.targetAcquireTimer-fElapsedTime);
m.attackCooldownTimer=std::max(0.f,m.attackCooldownTimer-fElapsedTime);
if(m.queueShotTimer>0){
m.queueShotTimer-=fElapsedTime;
if(m.queueShotTimer<0){
m.queueShotTimer=0;
{
BULLET_LIST.push_back(std::make_unique<Bullet>(Bullet(m.pos + vf2d{ 0,-4 }, geom2d::line(m.pos + vf2d{ 0,-4 }, game->GetPlayer()->GetPos()).vector().norm() * 24 * 3.f, 2, m.GetAttack(),m.upperLevel,false, { 75 / 2,162 / 2,225 / 2 })));
}
}
}
geom2d::line line(m.pos,game->GetPlayer()->GetPos());
if(m.targetAcquireTimer==0&&m.queueShotTimer==0){
m.targetAcquireTimer=1;
if(line.length()<24*6){
m.target=line.upoint(-1.2);
if(m.canMove){
m.SetState(MOVE_AWAY);
} else {
m.SetState(NORMAL);
}
} else
if(line.length()>24*7){
m.target=line.upoint(1.2);
m.SetState(MOVE_TOWARDS);
} else {
m.SetState(NORMAL);
}
}
m.canMove=true;
geom2d::line moveTowardsLine=geom2d::line(m.pos,m.target);
bool pathfindingDecision=false;
switch(m.state){
case MOVE_TOWARDS:{
if(moveTowardsLine.length()>1){
vf2d newPos=m.pos+moveTowardsLine.vector().norm()*100*fElapsedTime*m.GetMoveSpdMult();
bool movedX=m.SetX(newPos.x);
bool movedY=m.SetY(newPos.y);
pathfindingDecision=movedX|movedY;
m.canMove=movedX&&movedY;
}
if(!pathfindingDecision){
m.StartPathfinding(2.5);
}else
if(line.length()<=24*7){
m.SetState(NORMAL);
}
if(moveTowardsLine.vector().x>0){
m.facingDirection=RIGHT;
} else {
m.facingDirection=LEFT;
}
m.PerformJumpAnimation();
}break;
case MOVE_AWAY:{
if(moveTowardsLine.length()>1){
vf2d newPos=m.pos+moveTowardsLine.vector().norm()*100*fElapsedTime*m.GetMoveSpdMult();
bool movedX=m.SetX(newPos.x);
bool movedY=m.SetY(newPos.y);
pathfindingDecision=movedX|movedY;
m.canMove=movedX&&movedY;
}
if(!pathfindingDecision){
m.StartPathfinding(2.5);
}else
if(line.length()>=24*6){
m.SetState(NORMAL);
}
if(moveTowardsLine.vector().x>0){
m.facingDirection=RIGHT;
} else {
m.facingDirection=LEFT;
}
m.PerformJumpAnimation();
}break;
case PATH_AROUND:{
m.PathAroundBehavior(fElapsedTime);
}break;
default:{
if(m.attackCooldownTimer==0){
m.attackCooldownTimer=1;
m.queueShotTimer=0.7;
m.PerformShootAnimation();
}
}
}
}

@ -61,6 +61,7 @@ class TMXParser{
XMLTag monsterTag; XMLTag monsterTag;
XMLTag spawnerLinkTag; XMLTag spawnerLinkTag;
std::vector<XMLTag>accumulatedMonsterTags; std::vector<XMLTag>accumulatedMonsterTags;
bool infiniteMap=false;
public: public:
TMXParser(std::string file); TMXParser(std::string file);
}; };
@ -209,6 +210,10 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
XMLTag newTag=ReadNextTag(); XMLTag newTag=ReadNextTag();
if (newTag.tag=="map") { if (newTag.tag=="map") {
if(stoi(newTag.data["infinite"])==1){
infiniteMap=true;
return;
}
parsedMapInfo.MapData={stoi(newTag.data["width"]),stoi(newTag.data["height"])}; parsedMapInfo.MapData={stoi(newTag.data["width"]),stoi(newTag.data["height"])};
} else } else
if (newTag.tag=="tileset") { if (newTag.tag=="tileset") {
@ -269,7 +274,7 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
std::string accumulator=""; std::string accumulator="";
while (f.good()) { while (f.good()&&!infiniteMap) {
std::string data; std::string data;
f>>data; f>>data;
if (data.empty()) continue; if (data.empty()) continue;
@ -306,10 +311,13 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
} }
} }
if(infiniteMap){
std::cout<<"Infinite map detected. Parsing stopped early."<<std::endl;
}
for(XMLTag&monster:accumulatedMonsterTags){ for(XMLTag&monster:accumulatedMonsterTags){
parsedMapInfo.SpawnerData[monster.GetInteger("spawnerLink")].monsters.push_back(monster); parsedMapInfo.SpawnerData[monster.GetInteger("spawnerLink")].monsters.push_back(monster);
} }
std::cout<<"Parsed Map Data:\n"<<parsedMapInfo<<"\n"; std::cout<<"Parsed Map Data:\n"<<parsedMapInfo<<"\n";
} }
#endif #endif

@ -0,0 +1,5 @@
#include "Monster.h"
void Monster::STRATEGY::TURRET(Monster&m,float fElapsedTime){
}

@ -2,7 +2,7 @@
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 0 #define VERSION_PATCH 0
#define VERSION_BUILD 976 #define VERSION_BUILD 988
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -12,7 +12,7 @@
# ========================================== # ==========================================
# ========================================== # ==========================================
# #
# Monster0 # 0
# { # {
# Name = Green Slime # Name = Green Slime
# Health = 10 # Health = 10
@ -23,7 +23,7 @@
# MoveSpd = 110 # MoveSpd = 110
# Size = 80 # Size = 80
# #
# Strategy = RUN_TOWARDS # Strategy = Run Towards
# WaitTime = 5 # WaitTime = 5
# #
# [....Cut for length purposes] # [....Cut for length purposes]
@ -38,7 +38,7 @@ MonsterStrategy
{ {
0 0
{ {
Name = RUN_TOWARDS Name = Run Towards
# How long to wait before attempting to path again. # How long to wait before attempting to path again.
WaitTime = 2 WaitTime = 2
# How far the monster will travel before reassessing for a new path. # How far the monster will travel before reassessing for a new path.
@ -46,7 +46,7 @@ MonsterStrategy
} }
1 1
{ {
Name = SHOOT_AFAR Name = Shoot Afar
# How far away the monster attempts to distance itself from the player # How far away the monster attempts to distance itself from the player
Range = 800 Range = 800
# How often the enemy shoots. # How often the enemy shoots.
@ -57,8 +57,8 @@ MonsterStrategy
} }
2 2
{ {
Name = TURRET Name = Turret
# How far away the monster starts from shooting from # How far away the monster starts shooting from
Range = 800 Range = 800
# How often the enemy shoots. # How often the enemy shoots.
ShootingSpeed = 1 ShootingSpeed = 1

@ -2,7 +2,7 @@ Monsters
{ {
0 0
{ {
DisplayName = Green Slime, GREEN_SLIME DisplayName = Green Slime
Health = 10 Health = 10
Attack = 5 Attack = 5
@ -11,14 +11,23 @@ Monsters
MoveSpd = 110 MoveSpd = 110
Size = 80 Size = 80
Strategy = RUN_TOWARDS Strategy = Run Towards
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 10, 0.1, Repeat
JumpAnimation = 10, 0.06, Repeat
ShootAnimation = 10, 0.1, OneShot
DeathAnimation = 10, 0.1, OneShot
#Additional custom animations go down below. Start with ANIMATION[0] #Additional custom animations go down below. Start with ANIMATION[0]
#ANIMATION[0] = MY_NEW_ANIMATION #ANIMATION[0] = MY_NEW_ANIMATION
} }
1 1
{ {
DisplayName = Blue Slime, BLUE_SLIME DisplayName = Blue Slime
Health = 30 Health = 30
Attack = 10 Attack = 10
@ -27,14 +36,23 @@ Monsters
MoveSpd = 80 MoveSpd = 80
Size = 100 Size = 100
Strategy = SHOOT_AFAR Strategy = Shoot Afar
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 10, 0.1, Repeat
JumpAnimation = 10, 0.06, Repeat
ShootAnimation = 10, 0.1, OneShot
DeathAnimation = 10, 0.1, OneShot
#Additional custom animations go down below. Start with ANIMATION[0] #Additional custom animations go down below. Start with ANIMATION[0]
#ANIMATION[0] = MY_NEW_ANIMATION #ANIMATION[0] = MY_NEW_ANIMATION
} }
2 2
{ {
DisplayName = Red Slime, RED_SLIME DisplayName = Red Slime
Health = 25 Health = 25
Attack = 10 Attack = 10
@ -43,14 +61,23 @@ Monsters
MoveSpd = 95 MoveSpd = 95
Size = 120 Size = 120
Strategy = RUN_TOWARDS Strategy = Run Towards
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 10, 0.1, Repeat
JumpAnimation = 10, 0.06, Repeat
ShootAnimation = 10, 0.1, OneShot
DeathAnimation = 10, 0.1, OneShot
#Additional custom animations go down below. Start with ANIMATION[0] #Additional custom animations go down below. Start with ANIMATION[0]
#ANIMATION[0] = MY_NEW_ANIMATION #ANIMATION[0] = MY_NEW_ANIMATION
} }
3 3
{ {
DisplayName = Yellow Slime, YELLOW_SLIME DisplayName = Yellow Slime
Health = 175 Health = 175
Attack = 10 Attack = 10
@ -59,14 +86,23 @@ Monsters
MoveSpd = 40 MoveSpd = 40
Size = 160 Size = 160
Strategy = RUN_TOWARDS Strategy = Run Towards
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 10, 0.1, Repeat
JumpAnimation = 10, 0.06, Repeat
ShootAnimation = 10, 0.1, OneShot
DeathAnimation = 10, 0.1, OneShot
#Additional custom animations go down below. Start with ANIMATION[0] #Additional custom animations go down below. Start with ANIMATION[0]
#ANIMATION[0] = MY_NEW_ANIMATION #ANIMATION[0] = MY_NEW_ANIMATION
} }
4 4
{ {
DisplayName = Flower Turret, FLOWER_TURRET DisplayName = Flower Turret
Health = 40 Health = 40
Attack = 10 Attack = 10
@ -75,7 +111,16 @@ Monsters
MoveSpd = 0 MoveSpd = 0
Size = 100 Size = 100
Strategy = TURRET Strategy = Turret
#Size of each animation frame
SheetFrameSize = 24,24
# Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse)
IdleAnimation = 7, 0.1, PingPong
JumpAnimation = 1, 0.1, OneShot
ShootAnimation = 5, 0.1, OneShot
DeathAnimation = 5, 0.2, OneShot
#Additional custom animations go down below. Start with ANIMATION[0] #Additional custom animations go down below. Start with ANIMATION[0]
#ANIMATION[0] = MY_NEW_ANIMATION #ANIMATION[0] = MY_NEW_ANIMATION

@ -1,6 +1,6 @@
Player Player
{ {
BaseHealth = 1000 BaseHealth = 100
BaseMana = 100 BaseMana = 100
MoveSpd = 100 MoveSpd = 100

@ -3,7 +3,6 @@ GFX_Prefix = assets/
Images Images
{ {
GFX_Warrior_Sheet = nico-warrior.png GFX_Warrior_Sheet = nico-warrior.png
GFX_Slime_Sheet = slime.png
GFX_Circle = circle.png GFX_Circle = circle.png
GFX_Effect_GroundSlam_Back = ground-slam-attack-back.png GFX_Effect_GroundSlam_Back = ground-slam-attack-back.png
GFX_Effect_GroundSlam_Front = ground-slam-attack-front.png GFX_Effect_GroundSlam_Front = ground-slam-attack-front.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Loading…
Cancel
Save