Frog behavior implemented.

pull/30/head
sigonasr2 1 year ago
parent 62a2119ab2
commit e8d2ec9e9d
  1. 3
      Adventures in Lestoria/BulletTypes.h
  2. 49
      Adventures in Lestoria/Frog.cpp
  3. 16
      Adventures in Lestoria/FrogTongue.cpp
  4. 4
      Adventures in Lestoria/Monster.cpp
  5. 2
      Adventures in Lestoria/Monster.h
  6. 1
      Adventures in Lestoria/MonsterStrategyHelpers.h
  7. 4
      Adventures in Lestoria/Player.cpp
  8. 7
      Adventures in Lestoria/RUN_STRATEGY.cpp
  9. 2
      Adventures in Lestoria/Version.h
  10. 15
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  11. BIN
      Adventures in Lestoria/assets/tongue.png
  12. BIN
      Adventures in Lestoria/assets/tongue_end.png

@ -85,7 +85,8 @@ struct FrogTongue:public Bullet{
float tongueLength;
float tongueSpd;
float duration;
FrogTongue(vf2d pos,vf2d targetPos,float lifetime,int damage,bool upperLevel,bool friendly=false,Pixel col=WHITE);
float knockbackStrength;
FrogTongue(vf2d pos,vf2d targetPos,float lifetime,int damage,bool upperLevel,float knockbackStrength=1.0f,bool friendly=false,Pixel col=WHITE);
void Update(float fElapsedTime)override;
bool PlayerHit(Player*player)override;
bool MonsterHit(Monster&monster)override;

@ -40,12 +40,15 @@ All rights reserved.
#include "AdventuresInLestoria.h"
#include "MonsterStrategyHelpers.h"
#include "util.h"
#include "BulletTypes.h"
INCLUDE_game
INCLUDE_BULLET_LIST
using A=Attribute;
void Monster::STRATEGY::FROG(Monster&m,float fElapsedTime,std::string strategy){
m.F(A::LOCKON_WAITTIME)=std::max(0.0f,m.F(A::LOCKON_WAITTIME)-fElapsedTime);
phase:
switch(m.I(A::PHASE)){
case 0:{ //Move towards phase.
@ -55,6 +58,23 @@ void Monster::STRATEGY::FROG(Monster&m,float fElapsedTime,std::string strategy){
m.F(A::LOCKON_WAITTIME)=ConfigFloat("Lockon Wait Time");
m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos();
float dirToPlayer=util::angleTo(m.GetPos(),m.V(A::LOCKON_POS));
#pragma region Face towards lockon direction
if(abs(dirToPlayer)<0.5f*PI){ //This sprite is supposed to be facing right (flipped)
m.facingDirection=RIGHT;
m.spriteRot=dirToPlayer;
}else{
m.facingDirection=LEFT;
if(dirToPlayer>0){
m.spriteRot=-PI+dirToPlayer;
}else{
m.spriteRot=PI+dirToPlayer;
}
}
#pragma endregion
goto phase;
}
float dirToPlayer=util::angleTo(m.GetPos(),m.target);
#pragma region Face towards target direction
if(abs(dirToPlayer)<0.5f*PI){ //This sprite is supposed to be facing right (flipped)
m.facingDirection=RIGHT;
m.spriteRot=dirToPlayer;
@ -66,30 +86,27 @@ void Monster::STRATEGY::FROG(Monster&m,float fElapsedTime,std::string strategy){
m.spriteRot=PI+dirToPlayer;
}
}
goto phase;
}
float dirToPlayer=util::angleTo(m.GetPos(),m.target);
if(abs(dirToPlayer)<0.5f*PI){ //This sprite is supposed to be facing right (flipped)
m.facingDirection=RIGHT;
m.spriteRot=dirToPlayer;
}else{
m.facingDirection=LEFT;
if(dirToPlayer>0){
m.spriteRot=-PI+dirToPlayer;
}else{
m.spriteRot=PI+dirToPlayer;
}
}
#pragma endregion
RUN_TOWARDS(m,fElapsedTime,"Run Towards");
m.PerformJumpAnimation();
}break;
case 1:{
m.F(A::LOCKON_WAITTIME)=std::max(0.0f,m.F(A::LOCKON_WAITTIME)-fElapsedTime);
if(m.F(A::LOCKON_WAITTIME)==0.0f){
m.I(A::PHASE)=0;
m.F(A::LOCKON_WAITTIME)=ConfigFloat("Attack Duration");
vf2d tongueMaxRangePos=geom2d::line<float>(m.GetPos(),m.V(A::LOCKON_POS)).upoint(ConfigFloat("Tongue Max Range")/ConfigFloat("Range"));
CreateBullet(FrogTongue)(m.pos,tongueMaxRangePos,ConfigFloat("Attack Duration"),m.GetAttack(),m.OnUpperLevel(),ConfigFloat("Tongue Knockback Strength"),false,ConfigPixel("Tongue Color"))EndBullet;
m.PerformShootAnimation();
m.I(A::PHASE)=2;
}
m.PerformIdleAnimation();
}break;
case 2:{
if(m.F(A::LOCKON_WAITTIME)==0.0f){
m.F(A::LOCKON_WAITTIME)=ConfigFloat("Attack Recovery Time");
m.I(A::PHASE)=0;
}
}break;
default:{
ERR(std::format("Unhandled phase {} for {} strategy!",m.I(A::PHASE),strategy));
}

@ -44,8 +44,8 @@ INCLUDE_game
INCLUDE_MONSTER_LIST
INCLUDE_GFX
FrogTongue::FrogTongue(vf2d pos,vf2d targetPos,float lifetime,int damage,bool upperLevel,bool friendly,Pixel col)
:Bullet(pos,{},0,damage,upperLevel,friendly,col),targetPos(targetPos),tongueSpd(tongueSpd),tongueLength(0.f){
FrogTongue::FrogTongue(vf2d pos,vf2d targetPos,float lifetime,int damage,bool upperLevel,float knockbackStrength,bool friendly,Pixel col)
:Bullet(pos,{},0,damage,upperLevel,friendly,col),targetPos(targetPos),tongueSpd(tongueSpd),tongueLength(0.f),knockbackStrength(knockbackStrength){
this->lifetime=lifetime;
duration=lifetime;
}
@ -53,9 +53,9 @@ void FrogTongue::Update(float fElapsedTime){
geom2d::line<float>lineToTarget(pos,targetPos);
vf2d drawVec=lineToTarget.vector().norm()*3;
tongueLength=util::lerp(0,lineToTarget.length(),sin((lifetime*PI)/duration));
tongueLength=util::lerp(0,lineToTarget.length(),pow(sin((lifetime*PI)/duration),20.f));
vf2d tongueEndPos=geom2d::line<float>(pos+drawVec,targetPos).upoint(sin((lifetime*PI)/duration));
vf2d tongueEndPos=geom2d::line<float>(pos+drawVec,targetPos).upoint(pow(sin((lifetime*PI)/duration),20.f));
geom2d::line<float>tongueLine(pos+drawVec,tongueEndPos);
if(!friendly&&geom2d::overlaps(game->GetPlayer()->Hitbox(),tongueLine)){
@ -73,19 +73,25 @@ void FrogTongue::Update(float fElapsedTime){
bool FrogTongue::PlayerHit(Player*player){
if(!deactivated){
player->Hurt(damage,OnUpperLevel(),0);
geom2d::line<float>lineToTarget(pos,targetPos);
vf2d drawVec=lineToTarget.vector().norm()*3;
player->Knockback(geom2d::line<float>(pos+drawVec,targetPos).vector()*knockbackStrength);
deactivated=true;
}
return false;
}
bool FrogTongue::MonsterHit(Monster&monster){
monster.Hurt(damage,OnUpperLevel(),0);
geom2d::line<float>lineToTarget(pos,targetPos);
vf2d drawVec=lineToTarget.vector().norm()*3;
monster.Knockback(geom2d::line<float>(pos+drawVec,targetPos).vector()*knockbackStrength);
return false;
}
void FrogTongue::Draw(){
geom2d::line<float>lineToTarget(pos,targetPos);
vf2d drawVec=lineToTarget.vector().norm()*3;
vf2d tongueEndPos=geom2d::line<float>(pos+drawVec,targetPos).upoint(sin((lifetime*PI)/duration));
vf2d tongueEndPos=geom2d::line<float>(pos+drawVec,targetPos).upoint(pow(sin((lifetime*PI)/duration),20.f));
game->view.DrawRotatedDecal(pos+drawVec,GFX["tongue.png"].Decal(),drawVec.polar().y,{0.f,1.f},{tongueLength,1.0f},col);
game->view.DrawRotatedDecal(tongueEndPos,GFX["tongue_end.png"].Decal(),drawVec.polar().y,{2.f,2.f},{1.f,1.f},col);

@ -577,4 +577,8 @@ const EventName&Monster::GetWalkSound(){
geom2d::circle<float>Monster::Hitbox(){
return {GetPos(),12*GetSizeMult()};
}
void Monster::Knockback(const vf2d&vel){
this->vel+=vel;
}

@ -170,6 +170,7 @@ public:
const EventName&GetHurtSound();
const EventName&GetDeathSound();
const EventName&GetWalkSound();
void Knockback(const vf2d&vel);
private:
std::string name;
vf2d pos;
@ -225,6 +226,7 @@ private:
struct STRATEGY{
static int _GetInt(Monster&m,std::string param,std::string strategy,int index=0);
static float _GetFloat(Monster&m,std::string param,std::string strategy,int index=0);
static Pixel _GetPixel(Monster&m,std::string param,std::string strategy,int index=0);
static std::string _GetString(Monster&m,std::string param,std::string strategy,int index=0);
static void RUN_STRATEGY(Monster&m,float fElapsedTime);
static void RUN_TOWARDS(Monster&m,float fElapsedTime,std::string strategy);

@ -38,6 +38,7 @@ All rights reserved.
#pragma once
#define ConfigInt(param) _GetInt(m,param,strategy)
#define ConfigFloat(param) _GetFloat(m,param,strategy)
#define ConfigPixel(param) _GetPixel(m,param,strategy)
#define ConfigString(param) _GetString(m,param,strategy)
#define ConfigIntArr(param,ind) _GetInt(m,param,strategy,ind)
#define ConfigFloatArr(param,ind) _GetFloat(m,param,strategy,ind)

@ -537,10 +537,6 @@ void Player::Update(float fElapsedTime){
}
}
if(game->GetKey(G).bPressed){
CreateBullet(FrogTongue)(GetPos(),game->GetWorldMousePos(),1.f,10,OnUpperLevel(),true,RED)EndBullet;
}
#pragma region Warrior
switch(GetState()){
case State::SWING_SWORD:{

@ -63,6 +63,13 @@ std::string Monster::STRATEGY::_GetString(Monster&m,std::string param,std::strin
return DATA["MonsterStrategy"][strategy].GetProperty(param).GetString(index);
}
}
Pixel Monster::STRATEGY::_GetPixel(Monster&m,std::string param,std::string strategy,int index){
if(DATA["Monsters"][m.name].HasProperty(param)){
return DATA["Monsters"][m.name].GetProperty(param).GetPixel(index);
} else {
return DATA["MonsterStrategy"][strategy].GetProperty(param).GetPixel(index);
}
}
void Monster::STRATEGY::RUN_STRATEGY(Monster&m,float fElapsedTime){
m.GetStrategy()(m,fElapsedTime,m.strategy);

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 1
#define VERSION_BUILD 5750
#define VERSION_BUILD 5760
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -174,5 +174,20 @@ MonsterStrategy
# How long to wait after getting in range and locking on to the player, before firing tongue.
Lockon Wait Time = 1.5s
# How long the tongue attack lasts for.
Attack Duration = 1.0s
# Max range of the tongue attack.
Tongue Max Range = 450
# How long to wait before starting its seeking phase over again.
Attack Recovery Time = 0.5s
# The color of the tongue RGBA
Tongue Color = 95,23,31,255
# A multiplier for the knockback strength of the tongue. (1 is quite small)
Tongue Knockback Strength = 2
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 B

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 B

After

Width:  |  Height:  |  Size: 4.1 KiB

Loading…
Cancel
Save