Implement ground slam animation

pull/28/head
sigonasr2 1 year ago
parent 515c74aa9f
commit 7e543a3021
  1. 1
      Crawler/Animation.h
  2. 110
      Crawler/Crawler.cpp
  3. 10
      Crawler/Crawler.h
  4. 6
      Crawler/Crawler.vcxproj
  5. 12
      Crawler/Crawler.vcxproj.filters
  6. 7
      Crawler/DEFINES.h
  7. 34
      Crawler/Effect.cpp
  8. 18
      Crawler/Effect.h
  9. 2
      Crawler/Monster.h
  10. 15
      Crawler/Player.cpp
  11. BIN
      Crawler/assets/ground-slam-attack-back.png
  12. BIN
      Crawler/assets/ground-slam-attack-front.png
  13. 9
      Crawler/cpp.hint

@ -7,4 +7,5 @@ enum AnimationState{
BLUE_SLIME_IDLE,BLUE_SLIME_ROLL,BLUE_SLIME_JUMP,BLUE_SLIME_SPIT,BLUE_SLIME_DIE,
RED_SLIME_IDLE,RED_SLIME_ROLL,RED_SLIME_JUMP,RED_SLIME_SPIT,RED_SLIME_DIE,
YELLOW_SLIME_IDLE,YELLOW_SLIME_ROLL,YELLOW_SLIME_JUMP,YELLOW_SLIME_SPIT,YELLOW_SLIME_DIE,
GROUND_SLAM_ATTACK_BACK,GROUND_SLAM_ATTACK_FRONT,
};

@ -29,6 +29,8 @@ bool Crawler::OnUserCreate(){
GFX_Pl_Sheet.Load("assets/nico-warrior.png");
GFX_Slime_Sheet.Load("assets/slime.png");
GFX_Circle.Load("assets/circle.png");
GFX_Effect_GroundSlam_Back.Load("assets/ground-slam-attack-back.png");
GFX_Effect_GroundSlam_Front.Load("assets/ground-slam-attack-front.png");
//Animations
InitializeAnimations();
@ -52,6 +54,7 @@ bool Crawler::OnUserCreate(){
bool Crawler::OnUserUpdate(float fElapsedTime){
HandleUserInput(fElapsedTime);
UpdateEffects(fElapsedTime);
player.Update(fElapsedTime);
for(Monster&m:MONSTER_LIST){
m.Update(fElapsedTime);
@ -111,11 +114,18 @@ void Crawler::InitializeAnimations(){
ANIMATION_DATA[AnimationState(AnimationState::GREEN_SLIME_IDLE+state+slime*5)]=anim;
}
}
Animate2D::FrameSequence effect_groundslam_back(0.02f,Animate2D::Style::OneShot),effect_groundslam_front(0.02f,Animate2D::Style::OneShot);
for(int i=0;i<5;i++){
effect_groundslam_back.AddFrame({&GFX_Effect_GroundSlam_Back,{{i*64,0},{64,64}}});
effect_groundslam_front.AddFrame({&GFX_Effect_GroundSlam_Front,{{i*64,0},{64,64}}});
}
ANIMATION_DATA[AnimationState::GROUND_SLAM_ATTACK_BACK]=effect_groundslam_back;
ANIMATION_DATA[AnimationState::GROUND_SLAM_ATTACK_FRONT]=effect_groundslam_front;
}
void Crawler::HandleUserInput(float fElapsedTime){
bool setIdleAnimation=true;
if(GetKey(SPACE).bPressed){
if(GetKey(SPACE).bPressed&&player.GetState()==State::NORMAL){
player.Spin(Player::GROUND_SLAM_SPIN_TIME,14*PI);
}
if(GetKey(RIGHT).bHeld){
@ -182,55 +192,55 @@ void Crawler::HandleUserInput(float fElapsedTime){
if(GetKey(UP).bHeld){
player.UpdateAnimation(AnimationState::WALK_N);
} else
if(GetKey(DOWN).bHeld){
player.UpdateAnimation(AnimationState::WALK_S);
} else
if(GetKey(LEFT).bHeld){
player.UpdateAnimation(AnimationState::WALK_W);
}
if(GetKey(DOWN).bHeld){
player.UpdateAnimation(AnimationState::WALK_S);
} else
if(GetKey(LEFT).bHeld){
player.UpdateAnimation(AnimationState::WALK_W);
}
}
if(GetKey(LEFT).bReleased){
player.SetLastReleasedMovementKey(LEFT);
if(GetKey(RIGHT).bHeld){
player.UpdateAnimation(AnimationState::WALK_E);
} else
if(GetKey(DOWN).bHeld){
player.UpdateAnimation(AnimationState::WALK_S);
} else
if(GetKey(UP).bHeld){
player.UpdateAnimation(AnimationState::WALK_N);
}
if(GetKey(DOWN).bHeld){
player.UpdateAnimation(AnimationState::WALK_S);
} else
if(GetKey(UP).bHeld){
player.UpdateAnimation(AnimationState::WALK_N);
}
}
if(GetKey(DOWN).bReleased){
player.SetLastReleasedMovementKey(DOWN);
if(GetKey(RIGHT).bHeld){
player.UpdateAnimation(AnimationState::WALK_E);
} else
if(GetKey(UP).bHeld){
player.UpdateAnimation(AnimationState::WALK_N);
} else
if(GetKey(LEFT).bHeld){
player.UpdateAnimation(AnimationState::WALK_W);
}
if(GetKey(UP).bHeld){
player.UpdateAnimation(AnimationState::WALK_N);
} else
if(GetKey(LEFT).bHeld){
player.UpdateAnimation(AnimationState::WALK_W);
}
}
if(setIdleAnimation){
switch(player.GetLastReleasedMovementKey()){
case UP:{
player.UpdateAnimation(AnimationState::IDLE_N);
}break;
case DOWN:{
player.UpdateAnimation(AnimationState::IDLE_S);
}break;
case LEFT:{
player.UpdateAnimation(AnimationState::IDLE_W);
}break;
case RIGHT:{
player.UpdateAnimation(AnimationState::IDLE_E);
}break;
default:{
player.UpdateAnimation(AnimationState::IDLE_S);
}
case UP:{
player.UpdateAnimation(AnimationState::IDLE_N);
}break;
case DOWN:{
player.UpdateAnimation(AnimationState::IDLE_S);
}break;
case LEFT:{
player.UpdateAnimation(AnimationState::IDLE_W);
}break;
case RIGHT:{
player.UpdateAnimation(AnimationState::IDLE_E);
}break;
default:{
player.UpdateAnimation(AnimationState::IDLE_S);
}
}
} else {
//We have moved.
@ -243,6 +253,27 @@ void Crawler::UpdateCamera(float fElapsedTime){
view.SetWorldOffset(vi2d(camera.GetViewPosition()));
}
void Crawler::UpdateEffects(float fElapsedTime){
for(std::vector<Effect>::iterator it=backgroundEffects.begin();it!=backgroundEffects.end();++it){
Effect&e=*it;
if(!e.Update(fElapsedTime)){
it=backgroundEffects.erase(it);
if(it==backgroundEffects.end()){
break;
}
}
}
for(std::vector<Effect>::iterator it=foregroundEffects.begin();it!=foregroundEffects.end();++it){
Effect&e=*it;
if(!e.Update(fElapsedTime)){
it=foregroundEffects.erase(it);
if(it==foregroundEffects.end()){
break;
}
}
}
}
void Crawler::RenderWorld(float fElapsedTime){
Clear({100,180,100});
for (int x = view.GetTopLeftTile().x/24-1; x <= view.GetBottomRightTile().x/24; x++){
@ -260,6 +291,9 @@ void Crawler::RenderWorld(float fElapsedTime){
vf2d shadowScale=vf2d{8/3.f,1}/std::max(1.f,player.GetZ()/4);
view.DrawDecal(player.GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6},GFX_Circle.Decal(),shadowScale);
}
for(Effect&e:backgroundEffects){
e.Draw();
}
for(Monster&m:monstersBefore){
view.DrawPartialDecal(m.GetPos()-vf2d{12,12}*m.GetSizeMult(),m.GetFrame().GetSourceImage()->Decal(),m.GetFrame().GetSourceRect().pos,m.GetFrame().GetSourceRect().size,vf2d(m.GetSizeMult(),m.GetSizeMult()));
}
@ -267,6 +301,9 @@ void Crawler::RenderWorld(float fElapsedTime){
for(Monster&m:monstersAfter){
view.DrawPartialDecal(m.GetPos()-vf2d{12,12}*m.GetSizeMult(),m.GetFrame().GetSourceImage()->Decal(),m.GetFrame().GetSourceRect().pos,m.GetFrame().GetSourceRect().size,vf2d(m.GetSizeMult(),m.GetSizeMult()));
}
for(Effect&e:foregroundEffects){
e.Draw();
}
for(std::vector<DamageNumber>::iterator it=DAMAGENUMBER_LIST.begin();it!=DAMAGENUMBER_LIST.end();++it){
DamageNumber&dn=*it;
dn.lifeTime+=fElapsedTime;
@ -283,6 +320,11 @@ void Crawler::RenderWorld(float fElapsedTime){
}
}
void Crawler::AddEffect(Effect foreground,Effect background){
foregroundEffects.push_back(foreground);
backgroundEffects.push_back(background);
}
int main()
{
Crawler demo;

@ -6,24 +6,28 @@
#include "olcPGEX_TransformedView.h"
#include "Player.h"
#include "olcUTIL_Camera2D.h"
#include "Effect.h"
class Crawler : public olc::PixelGameEngine
{
const vi2d WORLD_SIZE={64,8};
Camera2D camera;
TileTransformedView view;
Player player;
Renderable GFX_Pl_Sheet,GFX_Slime_Sheet,GFX_Circle;
Renderable GFX_Pl_Sheet,GFX_Slime_Sheet,GFX_Circle,
GFX_Effect_GroundSlam_Back,GFX_Effect_GroundSlam_Front;
std::vector<Effect>foregroundEffects,backgroundEffects;
public:
Crawler();
public:
TileTransformedView view;
bool OnUserCreate() override;
bool OnUserUpdate(float fElapsedTime) override;
void InitializeAnimations();
void HandleUserInput(float fElapsedTime);
void UpdateCamera(float fElapsedTime);
void UpdateEffects(float fElapsedTime);
void RenderWorld(float fElapsedTime);
void AddEffect(Effect foreground,Effect background);
};

@ -132,6 +132,8 @@
<ClInclude Include="Animation.h" />
<ClInclude Include="Crawler.h" />
<ClInclude Include="DamageNumber.h" />
<ClInclude Include="DEFINES.h" />
<ClInclude Include="Effect.h" />
<ClInclude Include="Monster.h" />
<ClInclude Include="olcPGEX_TransformedView.h" />
<ClInclude Include="olcPixelGameEngine.h" />
@ -144,11 +146,15 @@
<ItemGroup>
<ClCompile Include="Crawler.cpp" />
<ClCompile Include="DamageNumber.cpp" />
<ClCompile Include="Effect.cpp" />
<ClCompile Include="pixelGameEngine.cpp" />
<ClCompile Include="Player.cpp" />
<ClCompile Include="Monster.cpp" />
<ClCompile Include="MonsterData.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

@ -48,6 +48,12 @@
<ClInclude Include="State.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Effect.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DEFINES.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Player.cpp">
@ -68,5 +74,11 @@
<ClCompile Include="pixelGameEngine.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Effect.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
</ItemGroup>
</Project>

@ -0,0 +1,7 @@
#pragma once
#define INCLUDE_ANIMATION_DATA extern std::map<AnimationState,Animate2D::FrameSequence>ANIMATION_DATA;
#define INCLUDE_MONSTER_LIST extern std::vector<Monster>MONSTER_LIST;
#define INCLUDE_SPAWNER_LIST extern std::vector<MonsterSpawner>SPAWNER_LIST;
#define INCLUDE_DAMAGENUMBER_LIST extern std::vector<DamageNumber>DAMAGENUMBER_LIST;
#define INCLUDE_game extern Crawler*game;
#define INCLUDE_MONSTER_DATA extern std::map<MonsterName,MonsterData>MONSTER_DATA;

@ -0,0 +1,34 @@
#include "DEFINES.h"
#include "Effect.h"
#include "Crawler.h"
INCLUDE_ANIMATION_DATA
INCLUDE_game
Effect::Effect(vf2d pos,float lifetime,AnimationState animation,float fadeout)
:pos(pos),lifetime(lifetime),fadeout(fadeout),original_fadeoutTime(fadeout){
this->animation.AddState(animation,ANIMATION_DATA[animation]);
}
bool Effect::Update(float fElapsedTime){
lifetime-=fElapsedTime;
if(lifetime<=0){
fadeout-=fElapsedTime;
if(fadeout<=0){
return false;
}
}
animation.UpdateState(internal_animState,fElapsedTime);
}
void Effect::Draw(){
if(fadeout==0){
game->view.DrawPartialDecal(pos-GetFrame().GetSourceRect().size/2,GetFrame().GetSourceImage()->Decal(),GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size);
} else {
game->view.DrawPartialDecal(pos-GetFrame().GetSourceRect().size/2,GetFrame().GetSourceImage()->Decal(),GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,{1,1},{255,255,255,uint8_t(fadeout/original_fadeoutTime*255)});
}
}
Animate2D::Frame Effect::GetFrame(){
return animation.GetFrame(internal_animState);
}

@ -0,0 +1,18 @@
#pragma once
#include "olcPixelGameEngine.h"
#include "Animation.h"
#include "olcUTIL_Animate2D.h"
struct Effect{
vf2d pos;
float lifetime;
float fadeout;
Effect(vf2d pos,float lifetime,AnimationState animation,float fadeout=0.0f);
bool Update(float fElapsedTime);
Animate2D::Frame GetFrame();
void Draw();
private:
Animate2D::Animation<AnimationState>animation;
Animate2D::AnimationState internal_animState;
float original_fadeoutTime;
};

@ -26,7 +26,7 @@ struct MonsterData{
MonsterName type;
public:
MonsterData();
//When specifying animations, the first one will become the default animation.
//When specifying animations, the first one will become the default animation. The last becomes the death animation.
MonsterData(MonsterName type,int hp,int atk,std::vector<AnimationState>animations,float moveSpd=1.0f,float size=1.0f,MonsterStrategy strategy=RUN_TOWARDS);
int GetHealth();
int GetAttack();

@ -2,14 +2,14 @@
#include "Player.h"
#include "Crawler.h"
#include "DamageNumber.h"
#include "DEFINES.h"
extern std::map<MonsterName,MonsterData>MONSTER_DATA;
extern std::vector<Monster>MONSTER_LIST;
extern std::map<AnimationState,Animate2D::FrameSequence>ANIMATION_DATA;
extern std::vector<MonsterSpawner>SPAWNER_LIST;
extern std::vector<DamageNumber>DAMAGENUMBER_LIST;
extern Crawler*game;
INCLUDE_MONSTER_DATA
INCLUDE_MONSTER_LIST
INCLUDE_ANIMATION_DATA
INCLUDE_SPAWNER_LIST
INCLUDE_DAMAGENUMBER_LIST
INCLUDE_game
const float Player::GROUND_SLAM_SPIN_TIME=0.6f;
@ -116,6 +116,7 @@ void Player::Update(float fElapsedTime){
state=NORMAL;
spin_angle=0;
z=0;
game->AddEffect(Effect{GetPos(),0.5,AnimationState::GROUND_SLAM_ATTACK_FRONT,0.6f},Effect{GetPos(),0.5,AnimationState::GROUND_SLAM_ATTACK_BACK,0.6f});
}
if(lastAnimationFlip>0){
lastAnimationFlip=std::max(0.f,lastAnimationFlip-fElapsedTime);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 912 B

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 812 B

After

Width:  |  Height:  |  Size: 10 KiB

@ -0,0 +1,9 @@
// Hint files help the Visual Studio IDE interpret Visual C++ identifiers
// such as names of functions and macros.
// For more information see https://go.microsoft.com/fwlink/?linkid=865984
#define INCLUDE_ANIMATION_DATA
#define INCLUDE_SPAWNER_LIST
#define INCLUDE_DAMAGENUMBER_LIST
#define INCLUDE_game
#define INCLUDE_MONSTER_LIST
#define INCLUDE_MONSTER_DATA
Loading…
Cancel
Save