Sonic Slash implemented for Warrior. Build updated w/new features.

pull/28/head
sigonasr2 1 year ago
parent dd75b5b52d
commit ccfeae19d4
  1. 5
      Crawler/Animation.h
  2. 26
      Crawler/Bullet.cpp
  3. 15
      Crawler/Bullet.h
  4. 110
      Crawler/Crawler.cpp
  5. 6
      Crawler/Crawler.h
  6. 3
      Crawler/DEFINES.h
  7. 79
      Crawler/Player.cpp
  8. 1
      Crawler/State.h
  9. 2
      Crawler/Version.h
  10. BIN
      Crawler/assets/nico-warrior.png
  11. BIN
      Crawler/assets/nico-warrior.xcf
  12. BIN
      Crawler/pge.data
  13. 2
      Crawler/pge.js
  14. BIN
      Crawler/pge.wasm

@ -8,10 +8,11 @@ enum AnimationState{
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,
SWINGSWORD_S,SWINGSWORD_E,SWINGSWORD_N,SWINGSWORD_W,
WARRIOR_SWINGSWORD_S,WARRIOR_SWINGSWORD_E,WARRIOR_SWINGSWORD_N,WARRIOR_SWINGSWORD_W,
RANGER_WALK_S,RANGER_WALK_E,RANGER_WALK_N,RANGER_WALK_W,
RANGER_IDLE_S,RANGER_IDLE_E,RANGER_IDLE_N,RANGER_IDLE_W,
WIZARD_WALK_S,WIZARD_WALK_E,WIZARD_WALK_N,WIZARD_WALK_W,
WIZARD_IDLE_S,WIZARD_IDLE_E,WIZARD_IDLE_N,WIZARD_IDLE_W,
BATTLECRY_EFFECT,
BATTLECRY_EFFECT,SONICSLASH,
WARRIOR_SWINGSONICSWORD_S,WARRIOR_SWINGSONICSWORD_E,WARRIOR_SWINGSONICSWORD_N,WARRIOR_SWINGSONICSWORD_W,
};

@ -1,4 +1,28 @@
#include "Bullet.h"
#include "Crawler.h"
#include "DEFINES.h"
INCLUDE_ANIMATION_DATA
INCLUDE_game
Bullet::Bullet(vf2d pos,vf2d vel,float radius,int damage,Pixel col)
:pos(pos),vel(vel),radius(radius),damage(damage),col(col){};
:pos(pos),vel(vel),radius(radius),damage(damage),col(col){};
Bullet::Bullet(vf2d pos,vf2d vel,float radius,int damage,AnimationState animation,bool hitsMultiple,float lifetime,bool rotatesWithAngle,Pixel col)
:pos(pos),vel(vel),radius(radius),damage(damage),col(col),animated(true),rotates(rotatesWithAngle),lifetime(lifetime),hitsMultiple(hitsMultiple){
this->animation.AddState(animation,ANIMATION_DATA[animation]);
this->animation.ChangeState(internal_animState,animation);
};
Animate2D::Frame Bullet::GetFrame(){
return animation.GetFrame(internal_animState);
}
void Bullet::Draw(){
if(animated){
game->view.DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotates?atan2(vel.y,vel.x)-PI/2:0,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,{1,1},col);
} else {
game->view.FillCircle(pos,radius,col);
game->view.DrawCircle(pos,radius,WHITE,0xAA);
}
}

@ -1,5 +1,8 @@
#pragma once
#include "olcPixelGameEngine.h"
#include "Animation.h"
#include "olcUTIL_Animate2D.h"
#include "Monster.h"
struct Bullet{
vf2d pos;
@ -7,5 +10,17 @@ struct Bullet{
float radius;
int damage;
Pixel col;
float lifetime=99999;
bool hitsMultiple=false;
bool rotates=false;
bool animated=false;
Animate2D::Animation<AnimationState>animation;
Animate2D::AnimationState internal_animState;
std::map<Monster*,bool>hitList;
Bullet(vf2d pos,vf2d vel,float radius,int damage,Pixel col=WHITE);
//Initializes a bullet with an animation.
Bullet(vf2d pos,vf2d vel,float radius,int damage,AnimationState animation,bool hitsMultiple=false,float lifetime=999999,bool rotatesWithAngle=false,Pixel col=WHITE);
public:
Animate2D::Frame GetFrame();
void Draw();
};

@ -15,6 +15,7 @@ std::vector<Monster>MONSTER_LIST;
std::vector<MonsterSpawner>SPAWNER_LIST;
std::vector<DamageNumber>DAMAGENUMBER_LIST;
std::vector<Bullet>BULLET_LIST;
std::vector<Bullet>PLAYER_BULLET_LIST;
Crawler*game;
Crawler::Crawler()
@ -43,6 +44,7 @@ bool Crawler::OnUserCreate(){
GFX_Wizard_Sheet.Load("assets/nico-wizard.png");
GFX_Battlecry_Effect.Load("assets/battlecry_effect.png");
GFX_Mana.Load("assets/mana.png");
GFX_SonicSlash.Load("assets/sonicslash.png");
//Animations
InitializeAnimations();
@ -55,6 +57,14 @@ bool Crawler::OnUserCreate(){
player.AddAnimation(AnimationState::WARRIOR_IDLE_E);
player.AddAnimation(AnimationState::WARRIOR_IDLE_S);
player.AddAnimation(AnimationState::WARRIOR_IDLE_W);
player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E);
player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S);
player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N);
player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W);
player.AddAnimation(AnimationState::RANGER_WALK_N);
player.AddAnimation(AnimationState::RANGER_WALK_E);
player.AddAnimation(AnimationState::RANGER_WALK_S);
@ -71,10 +81,6 @@ bool Crawler::OnUserCreate(){
player.AddAnimation(AnimationState::WIZARD_IDLE_E);
player.AddAnimation(AnimationState::WIZARD_IDLE_S);
player.AddAnimation(AnimationState::WIZARD_IDLE_W);
player.AddAnimation(AnimationState::SWINGSWORD_E);
player.AddAnimation(AnimationState::SWINGSWORD_S);
player.AddAnimation(AnimationState::SWINGSWORD_N);
player.AddAnimation(AnimationState::SWINGSWORD_W);
view=TileTransformedView{GetScreenSize(),{1,1}};
player.SetClass(WARRIOR);
@ -177,22 +183,31 @@ void Crawler::InitializeAnimations(){
pl_warrior_idle_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,1}*24,{24,24}}});
ANIMATION_DATA[AnimationState::WARRIOR_IDLE_N]=pl_warrior_idle_n;
Animate2D::FrameSequence pl_warrior_swing_s(0.05),pl_warrior_swing_n(0.05),pl_warrior_swing_e(0.05),pl_warrior_swing_w(0.05);
Animate2D::FrameSequence pl_warrior_sonic_swing_s(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_n(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_e(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_w(0.1,Animate2D::Style::OneShot);
for (int i=0;i<4;i++){
pl_warrior_swing_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,0}*24,{24,24}}});
pl_warrior_sonic_swing_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,4}*24,{24,24}}});
}
for (int i=0;i<4;i++){
pl_warrior_swing_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,1}*24,{24,24}}});
pl_warrior_sonic_swing_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,5}*24,{24,24}}});
}
for (int i=0;i<4;i++){
pl_warrior_swing_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,2}*24,{24,24}}});
pl_warrior_sonic_swing_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,6}*24,{24,24}}});
}
for (int i=0;i<4;i++){
pl_warrior_swing_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,3}*24,{24,24}}});
}
ANIMATION_DATA[AnimationState::SWINGSWORD_N]=pl_warrior_swing_n;
ANIMATION_DATA[AnimationState::SWINGSWORD_E]=pl_warrior_swing_e;
ANIMATION_DATA[AnimationState::SWINGSWORD_S]=pl_warrior_swing_s;
ANIMATION_DATA[AnimationState::SWINGSWORD_W]=pl_warrior_swing_w;
pl_warrior_sonic_swing_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,7}*24,{24,24}}});
}
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_N]=pl_warrior_swing_n;
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_E]=pl_warrior_swing_e;
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_S]=pl_warrior_swing_s;
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_W]=pl_warrior_swing_w;
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_N]=pl_warrior_sonic_swing_n;
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_E]=pl_warrior_sonic_swing_e;
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_S]=pl_warrior_sonic_swing_s;
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_W]=pl_warrior_sonic_swing_w;
//Ranger animations
Animate2D::FrameSequence pl_ranger_walk_s{0.2};
@ -298,6 +313,11 @@ void Crawler::InitializeAnimations(){
battlecry_effect.AddFrame({&GFX_Battlecry_Effect,{{i*84,0},{84,84}}});
}
ANIMATION_DATA[AnimationState::BATTLECRY_EFFECT]=battlecry_effect;
Animate2D::FrameSequence sonicslash_effect(0.04f,Animate2D::Style::OneShot);
for(int i=0;i<4;i++){
sonicslash_effect.AddFrame({&GFX_SonicSlash,{{i*60,0},{60,60}}});
}
ANIMATION_DATA[AnimationState::SONICSLASH]=sonicslash_effect;
}
bool Crawler::LeftHeld(){
@ -470,16 +490,16 @@ void Crawler::HandleUserInput(float fElapsedTime){
setIdleAnimation=false;
switch(player.GetFacingDirection()){
case UP:{
player.UpdateAnimation(AnimationState::SWINGSWORD_N);
player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
}break;
case DOWN:{
player.UpdateAnimation(AnimationState::SWINGSWORD_S);
player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
}break;
case LEFT:{
player.UpdateAnimation(AnimationState::SWINGSWORD_W);
player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
}break;
case RIGHT:{
player.UpdateAnimation(AnimationState::SWINGSWORD_E);
player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
}break;
}
player.SetSwordSwingTimer(player.GetSwordSwingTimer()-fElapsedTime);
@ -489,7 +509,7 @@ void Crawler::HandleUserInput(float fElapsedTime){
}
}
if(player.GetState()==State::BLOCK){
if(player.GetState()!=State::NORMAL){
setIdleAnimation=false;
}
@ -518,6 +538,17 @@ void Crawler::HandleUserInput(float fElapsedTime){
}
void Crawler::UpdateCamera(float fElapsedTime){
lastWorldShakeAdjust=std::max(0.f,lastWorldShakeAdjust-fElapsedTime);
if(worldShakeTime-fElapsedTime>0){
if(lastWorldShakeAdjust==0){
lastWorldShakeAdjust=float(rand()%int(WORLD_SHAKE_ADJUST_MAX_TIME*1000))/1000+0.05;
worldShakeVel={float(rand()%1000)/1000*100-50,float(rand()%1000)/1000*100-50};
}
worldShake+=worldShakeVel*fElapsedTime;
} else {
camera.SetTarget(player.GetPos());
}
worldShakeTime=std::max(0.f,worldShakeTime-fElapsedTime);
camera.Update(fElapsedTime);
view.SetWorldOffset(vi2d(camera.GetViewPosition()));
}
@ -560,6 +591,45 @@ void Crawler::UpdateBullets(float fElapsedTime){
break;
}
}
b.lifetime-=fElapsedTime;
if(b.lifetime<=0){
it=BULLET_LIST.erase(it);
if(it==BULLET_LIST.end()){
break;
}
}
b.animation.UpdateState(b.internal_animState,fElapsedTime);
}
for(std::vector<Bullet>::iterator it=PLAYER_BULLET_LIST.begin();it!=PLAYER_BULLET_LIST.end();++it){
Bullet&b=*it;
b.pos+=b.vel*fElapsedTime;
for(Monster&m:MONSTER_LIST){
if(geom2d::overlaps(geom2d::circle(m.GetPos(),12*m.GetSizeMult()),geom2d::circle(b.pos,b.radius))){
if(b.hitList.find(&m)==b.hitList.end()&&m.Hurt(b.damage)){
if(!b.hitsMultiple){
it=PLAYER_BULLET_LIST.erase(it);
if(it==PLAYER_BULLET_LIST.end()){
break;
}
}
b.hitList[&m]=true;
}
}
}
if(b.pos.x<view.GetWorldTL().x||b.pos.x>view.GetWorldBR().x||b.pos.y<view.GetWorldTL().y||b.pos.y>view.GetWorldBR().y){
it=PLAYER_BULLET_LIST.erase(it);
if(it==PLAYER_BULLET_LIST.end()){
break;
}
}
b.lifetime-=fElapsedTime;
if(b.lifetime<=0){
it=PLAYER_BULLET_LIST.erase(it);
if(it==PLAYER_BULLET_LIST.end()){
break;
}
}
b.animation.UpdateState(b.internal_animState,fElapsedTime);
}
}
void Crawler::HurtEnemies(vf2d pos,float radius,int damage){
@ -606,8 +676,10 @@ void Crawler::RenderWorld(float fElapsedTime){
e.Draw();
}
for(Bullet&b:BULLET_LIST){
view.FillCircle(b.pos,b.radius,b.col);
view.DrawCircle(b.pos,b.radius,WHITE,0xAA);
b.Draw();
}
for(Bullet&b:PLAYER_BULLET_LIST){
b.Draw();
}
for(std::vector<DamageNumber>::iterator it=DAMAGENUMBER_LIST.begin();it!=DAMAGENUMBER_LIST.end();++it){
DamageNumber&dn=*it;
@ -712,6 +784,12 @@ vf2d Crawler::GetWorldMousePos(){
return GetMousePos()+view.GetWorldOffset();
}
void Crawler::SetupWorldShake(float duration){
worldShakeTime=duration;
worldShake=player.GetPos();
camera.SetTarget(worldShake);
}
int main()
{
Crawler demo;

@ -17,6 +17,11 @@ class Crawler : public olc::PixelGameEngine
GFX_Heart,GFX_BLOCK_BUBBLE,GFX_Ranger_Sheet,GFX_Wizard_Sheet,
GFX_Battlecry_Effect,GFX_Mana,GFX_SonicSlash;
std::vector<Effect>foregroundEffects,backgroundEffects;
vf2d worldShake={};
float worldShakeTime=0;
float lastWorldShakeAdjust=0;
vf2d worldShakeVel={};
const float WORLD_SHAKE_ADJUST_MAX_TIME=0.4;
public:
Crawler();
@ -47,4 +52,5 @@ public:
bool UpReleased();
bool DownReleased();
Player&GetPlayer();
void SetupWorldShake(float duration);
};

@ -6,4 +6,5 @@
#define INCLUDE_game extern Crawler*game;
#define INCLUDE_MONSTER_DATA extern std::map<MonsterName,MonsterData>MONSTER_DATA;
#define INCLUDE_BULLET_LIST extern std::vector<Bullet>BULLET_LIST;
#define INCLUDE_CLASS_DATA extern std::map<Class,ClassData>CLASS_DATA;
#define INCLUDE_CLASS_DATA extern std::map<Class,ClassData>CLASS_DATA;
#define INCLUDE_PLAYER_BULLET_LIST extern std::vector<Bullet>PLAYER_BULLET_LIST;

@ -2,6 +2,7 @@
#include "Player.h"
#include "Crawler.h"
#include "DamageNumber.h"
#include "Bullet.h"
#include "DEFINES.h"
INCLUDE_MONSTER_DATA
@ -10,6 +11,7 @@ INCLUDE_ANIMATION_DATA
INCLUDE_SPAWNER_LIST
INCLUDE_DAMAGENUMBER_LIST
INCLUDE_CLASS_DATA
INCLUDE_PLAYER_BULLET_LIST
INCLUDE_game
const float Player::GROUND_SLAM_SPIN_TIME=0.6f;
@ -150,7 +152,7 @@ void Player::Update(float fElapsedTime){
z=50*sin(3.3*(GROUND_SLAM_SPIN_TIME-spin_attack_timer)/GROUND_SLAM_SPIN_TIME);
spin_attack_timer=std::max(0.f,spin_attack_timer-fElapsedTime);
} else {
state=NORMAL;
SetState(NORMAL);
spin_angle=0;
z=0;
game->HurtEnemies(pos,3*12,GetAttack()*2.5);
@ -163,9 +165,29 @@ void Player::Update(float fElapsedTime){
}break;
case BLOCK:{
if(rightClickAbility.COOLDOWN_TIME-rightClickAbility.cooldown>3){
state=NORMAL;
SetState(NORMAL);
}
}break;
case SWING_SONIC_SWORD:{
if(ability3.COOLDOWN_TIME-ability3.cooldown>0.5){
SetState(NORMAL);
switch(facingDirection){
case DOWN:{
UpdateAnimation(AnimationState::WARRIOR_IDLE_S);
}break;
case RIGHT:{
UpdateAnimation(AnimationState::WARRIOR_IDLE_E);
}break;
case LEFT:{
UpdateAnimation(AnimationState::WARRIOR_IDLE_W);
}break;
case UP:{
UpdateAnimation(AnimationState::WARRIOR_IDLE_N);
}break;
}
}
animation.UpdateState(internal_animState,fElapsedTime);
}break;
default:{
//Update animations normally.
animation.UpdateState(internal_animState,fElapsedTime);
@ -226,18 +248,18 @@ void Player::Update(float fElapsedTime){
swordSwingTimer=0.2;
SetState(State::SWING_SWORD);
switch(facingDirection){
case DOWN:{
UpdateAnimation(AnimationState::SWINGSWORD_S);
}break;
case RIGHT:{
UpdateAnimation(AnimationState::SWINGSWORD_E);
}break;
case LEFT:{
UpdateAnimation(AnimationState::SWINGSWORD_W);
}break;
case UP:{
UpdateAnimation(AnimationState::SWINGSWORD_N);
}break;
case DOWN:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
}break;
case RIGHT:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
}break;
case LEFT:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
}break;
case UP:{
UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
}break;
}
}
}
@ -308,7 +330,34 @@ void Player::Update(float fElapsedTime){
if(ability3.cooldown==0&&GetMana()>=ability3.manaCost&&game->GetKey(CTRL).bPressed){
switch(cl){
case WARRIOR:{
//TODO
ability3.cooldown=ability3.COOLDOWN_TIME;
SetState(State::SWING_SONIC_SWORD);
AddBuff(BuffType::SLOWDOWN,0.5,1);
vf2d bulletVel={};
switch(GetFacingDirection()){
case UP:{
vel.y=70;
bulletVel.y=-400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N);
}break;
case LEFT:{
vel.x=70;
bulletVel.x=-400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W);
}break;
case RIGHT:{
vel.x=-70;
bulletVel.x=400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E);
}break;
case DOWN:{
vel.y=-70;
bulletVel.y=400;
UpdateAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S);
}break;
}
PLAYER_BULLET_LIST.push_back(Bullet(pos,bulletVel,30,GetAttack()*8,AnimationState::SONICSLASH,true,2.25,true));
game->SetupWorldShake(0.5);
}break;
case THIEF:{
}break;

@ -3,6 +3,7 @@
enum State{
NORMAL,
SWING_SWORD,
SWING_SONIC_SWORD,
SPIN,
MOVE_TOWARDS,
MOVE_AWAY,

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 179 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.
Loading…
Cancel
Save