5802: Running, sitting and AFK anim. states r=def- a=VoxelDoesCode

Added in two more animation states, for running at a fast enough speed and for when you're AFK. Both of these states are bi-directional, and actually mirror very well inside the code.

The running animation I feel like gives a better explanation for how fast you're going, and stopping now would result in skidding. 
Old run cycle, which is just really fast walk:
https://user-images.githubusercontent.com/95713843/188262126-a2f63f92-88b5-408e-a1dd-af9288541c54.mp4
New run cycle:
https://user-images.githubusercontent.com/95713843/188262128-d7734eb7-fd43-4a6d-8605-c76b78ac759b.mp4

An AFK tee will also sit down and put its weapon behind its back; if not firing it. Very fitting with the many chairs and tables in maps.
![unknown](https://user-images.githubusercontent.com/95713843/188262188-1b6591a6-7a88-4fd3-8c25-fb150a28ed0f.png)

## Checklist

- [x] Tested the change ingame
- [x] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [x] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: VoxelDoesCode <bluheadcat@gmail.com>
This commit is contained in:
bors[bot] 2022-09-16 10:31:04 +00:00 committed by GitHub
commit b3f8e37dc6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 142 additions and 21 deletions

View file

@ -466,6 +466,18 @@ anim.back_foot.frames.Add(AnimKeyframe(0, -3, 0, -0.1))
anim.front_foot.frames.Add(AnimKeyframe(0, 3, 0, -0.1))
container.animations.Add(anim)
anim = Animation("sit_left")
anim.body.frames.Add(AnimKeyframe(0, 0, 3, 0))
anim.back_foot.frames.Add(AnimKeyframe(0, -12, 0, 0.1))
anim.front_foot.frames.Add(AnimKeyframe(0, -8, 0, 0.1))
container.animations.Add(anim)
anim = Animation("sit_right")
anim.body.frames.Add(AnimKeyframe(0, 0, 3, 0))
anim.back_foot.frames.Add(AnimKeyframe(0, 12, 0, -0.1))
anim.front_foot.frames.Add(AnimKeyframe(0, 8, 0, -0.1))
container.animations.Add(anim)
anim = Animation("walk")
anim.body.frames.Add(AnimKeyframe(0.0, 0, 0, 0))
anim.body.frames.Add(AnimKeyframe(0.2, 0,-1, 0))
@ -489,6 +501,52 @@ anim.front_foot.frames.Add(AnimKeyframe(0.8, 8, 0, 0))
anim.front_foot.frames.Add(AnimKeyframe(1.0,-10,-4, 0.2))
container.animations.Add(anim)
anim = Animation("run_left")
anim.body.frames.Add(AnimKeyframe(0.0, 0, -2, 0))
anim.body.frames.Add(AnimKeyframe(0.2, 0, 0, 0))
anim.body.frames.Add(AnimKeyframe(0.4, 0, 0, 0))
anim.body.frames.Add(AnimKeyframe(0.6, 0, -2, 0))
anim.body.frames.Add(AnimKeyframe(0.8, 0, 0, 0))
anim.body.frames.Add(AnimKeyframe(1.0, 0, -2, 0))
anim.back_foot.frames.Add(AnimKeyframe(0.0, 18, -11, -0.27))
anim.back_foot.frames.Add(AnimKeyframe(0.2, 6, 0, 0))
anim.back_foot.frames.Add(AnimKeyframe(0.4, -7, 0, 0))
anim.back_foot.frames.Add(AnimKeyframe(0.6, -13, -4.5, 0.05))
anim.back_foot.frames.Add(AnimKeyframe(0.8, 0, -11, -0.2))
anim.back_foot.frames.Add(AnimKeyframe(1.0, 18, -11, -0.27))
anim.front_foot.frames.Add(AnimKeyframe(0.0, -13, -4.5, 0.05))
anim.front_foot.frames.Add(AnimKeyframe(0.2, -14, -7, 0.1))
anim.front_foot.frames.Add(AnimKeyframe(0.4, 11, -13, -0.3))
anim.front_foot.frames.Add(AnimKeyframe(0.6, 18, -11, -0.27))
anim.front_foot.frames.Add(AnimKeyframe(0.8, 3, 0, -0.02))
anim.front_foot.frames.Add(AnimKeyframe(1.0, -13, -4.5, 0.05))
container.animations.Add(anim)
anim = Animation("run_right")
anim.body.frames.Add(AnimKeyframe(0.0, 0, -2, 0))
anim.body.frames.Add(AnimKeyframe(0.2, 0, 0, 0))
anim.body.frames.Add(AnimKeyframe(0.4, 0, -2, 0))
anim.body.frames.Add(AnimKeyframe(0.6, 0, 0, 0))
anim.body.frames.Add(AnimKeyframe(0.8, 0, 0, 0))
anim.body.frames.Add(AnimKeyframe(1.0, 0, -2, 0))
anim.back_foot.frames.Add(AnimKeyframe(0.0, -18, -11, 0.27))
anim.back_foot.frames.Add(AnimKeyframe(0.2, 0, -11, 0.2))
anim.back_foot.frames.Add(AnimKeyframe(0.4, 13, -4.5, -0.05))
anim.back_foot.frames.Add(AnimKeyframe(0.6, 7, 0, 0))
anim.back_foot.frames.Add(AnimKeyframe(0.8, -6, 0, 0))
anim.back_foot.frames.Add(AnimKeyframe(1.0, -18, -11, 0.27))
anim.front_foot.frames.Add(AnimKeyframe(0.0, 13, -4.5, -0.05))
anim.front_foot.frames.Add(AnimKeyframe(0.2, -3, 0, 0.02))
anim.front_foot.frames.Add(AnimKeyframe(0.4, -18, -11, 0.27))
anim.front_foot.frames.Add(AnimKeyframe(0.6, -11, -13, 0.3))
anim.front_foot.frames.Add(AnimKeyframe(0.8, 14, -7, -0.1))
anim.front_foot.frames.Add(AnimKeyframe(1.0, 13, -4.5, -0.05))
container.animations.Add(anim)
anim = Animation("hammer_swing")
anim.attach.frames.Add(AnimKeyframe(0.0, 0, 0, -0.10))
anim.attach.frames.Add(AnimKeyframe(0.3, 0, 0, 0.25))

View file

@ -4,6 +4,7 @@
#include <engine/demo.h>
#include <engine/graphics.h>
#include <engine/shared/config.h>
#include <game/gamecore.h>
#include <game/generated/client_data.h>
#include <game/generated/protocol.h>
@ -22,6 +23,7 @@
#include "players.h"
#include <base/color.h>
#include <base/math.h>
void CPlayers::RenderHand(CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset, float Alpha)
{
@ -408,26 +410,46 @@ void CPlayers::RenderPlayer(
RenderInfo.m_GotAirJump = Player.m_Jumped & 2 ? 0 : 1;
RenderInfo.m_FeetFlipped = false;
bool Stationary = Player.m_VelX <= 1 && Player.m_VelX >= -1;
bool InAir = !Collision()->CheckPoint(Player.m_X, Player.m_Y + 16);
bool Running = Player.m_VelX >= 5000 || Player.m_VelX <= -5000;
bool WantOtherDir = (Player.m_Direction == -1 && Vel.x > 0) || (Player.m_Direction == 1 && Vel.x < 0);
bool Inactive = m_pClient->m_aClients[ClientID].m_Afk || m_pClient->m_aClients[ClientID].m_Paused;
// evaluate animation
float WalkTime = fmod(Position.x, 100.0f) / 100.0f;
float RunTime = fmod(Position.x, 250.0f) / 250.0f;
// Don't do a moon walk outside the left border
if(WalkTime < 0)
{
// Don't do a moon walk outside the left border
WalkTime += 1;
}
if(RunTime < 0)
RunTime += 1;
CAnimState State;
State.Set(&g_pData->m_aAnimations[ANIM_BASE], 0);
if(InAir)
State.Add(&g_pData->m_aAnimations[ANIM_INAIR], 0, 1.0f); // TODO: some sort of time here
else if(Stationary)
State.Add(&g_pData->m_aAnimations[ANIM_IDLE], 0, 1.0f); // TODO: some sort of time here
{
if(Inactive)
{
State.Add(Direction.x < 0 ? &g_pData->m_aAnimations[ANIM_SIT_LEFT] : &g_pData->m_aAnimations[ANIM_SIT_RIGHT], 0, 1.0f); // TODO: some sort of time here
RenderInfo.m_FeetFlipped = true;
}
else
State.Add(&g_pData->m_aAnimations[ANIM_IDLE], 0, 1.0f); // TODO: some sort of time here
}
else if(!WantOtherDir)
State.Add(&g_pData->m_aAnimations[ANIM_WALK], WalkTime, 1.0f);
{
if(Running)
State.Add(Player.m_VelX < 0 ? &g_pData->m_aAnimations[ANIM_RUN_LEFT] : &g_pData->m_aAnimations[ANIM_RUN_RIGHT], RunTime, 1.0f);
else
State.Add(&g_pData->m_aAnimations[ANIM_WALK], WalkTime, 1.0f);
}
if(Player.m_Weapon == WEAPON_HAMMER)
State.Add(&g_pData->m_aAnimations[ANIM_HAMMER_SWING], clamp(LastAttackTime * 5.0f, 0.0f, 1.0f), 1.0f);
@ -470,27 +492,37 @@ void CPlayers::RenderPlayer(
vec2 Dir = Direction;
float Recoil = 0.0f;
vec2 WeaponPosition;
bool IsSit = Inactive && !InAir && Stationary;
if(Player.m_Weapon == WEAPON_HAMMER)
{
// Static position for hammer
// static position for hammer
WeaponPosition = Position + vec2(State.GetAttach()->m_X, State.GetAttach()->m_Y);
WeaponPosition.y += g_pData->m_Weapons.m_aId[CurrentWeapon].m_Offsety;
// if attack is under way, bash stuffs
if(Direction.x < 0)
{
Graphics()->QuadsSetRotation(-pi / 2 - State.GetAttach()->m_Angle * pi * 2);
WeaponPosition.x -= g_pData->m_Weapons.m_aId[CurrentWeapon].m_Offsetx;
if(IsSit)
WeaponPosition.y += 3.0f;
// if active and attack is under way, bash stuffs
if(!Inactive || LastAttackTime < m_pClient->m_aTuning[g_Config.m_ClDummy].GetWeaponFireDelay(Player.m_Weapon))
{
if(Direction.x < 0)
Graphics()->QuadsSetRotation(-pi / 2 - State.GetAttach()->m_Angle * pi * 2);
else
Graphics()->QuadsSetRotation(-pi / 2 + State.GetAttach()->m_Angle * pi * 2);
}
else
{
Graphics()->QuadsSetRotation(-pi / 2 + State.GetAttach()->m_Angle * pi * 2);
}
Graphics()->QuadsSetRotation(Direction.x < 0 ? 100.0f : 500.0f);
Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, WeaponPosition.x, WeaponPosition.y);
}
else if(Player.m_Weapon == WEAPON_NINJA)
{
WeaponPosition = Position;
WeaponPosition.y += g_pData->m_Weapons.m_aId[CurrentWeapon].m_Offsety;
if(IsSit)
WeaponPosition.y += 3.0f;
if(Direction.x < 0)
{
@ -561,6 +593,8 @@ void CPlayers::RenderPlayer(
Recoil = sinf(a * pi);
WeaponPosition = Position + Dir * g_pData->m_Weapons.m_aId[CurrentWeapon].m_Offsetx - Dir * Recoil * 10.0f;
WeaponPosition.y += g_pData->m_Weapons.m_aId[CurrentWeapon].m_Offsety;
if(IsSit)
WeaponPosition.y += 3.0f;
if(Player.m_Weapon == WEAPON_GUN && g_Config.m_ClOldGunPosition)
WeaponPosition.y -= 8;
Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, WeaponPosition.x, WeaponPosition.y);
@ -569,7 +603,7 @@ void CPlayers::RenderPlayer(
if(Player.m_Weapon == WEAPON_GUN || Player.m_Weapon == WEAPON_SHOTGUN)
{
// check if we're firing stuff
if(g_pData->m_Weapons.m_aId[CurrentWeapon].m_NumSpriteMuzzles) //prev.attackticks)
if(g_pData->m_Weapons.m_aId[CurrentWeapon].m_NumSpriteMuzzles) // prev.attackticks)
{
float AlphaMuzzle = 0.0f;
if(AttackTicksPassed < g_pData->m_Weapons.m_aId[CurrentWeapon].m_Muzzleduration + 3)
@ -810,7 +844,7 @@ void CPlayers::OnRender()
RenderHookCollLine(&m_pClient->m_aClients[ClientID].m_RenderPrev, &m_pClient->m_aClients[ClientID].m_RenderCur, ClientID);
//don't render offscreen
// don't render offscreen
vec2 *pRenderPos = &m_pClient->m_aClients[ClientID].m_RenderPos;
if(pRenderPos->x < ScreenX0 || pRenderPos->x > ScreenX1 || pRenderPos->y < ScreenY0 || pRenderPos->y > ScreenY1)
{

View file

@ -43,10 +43,18 @@ void CRenderTools::Init(IGraphics *pGraphics, ITextRender *pTextRender)
Graphics()->QuadsSetSubset(0, 0, 1, 1);
QuadContainerAddSprite(m_TeeQuadContainerIndex, 64.f * 0.4f);
// Feet
Graphics()->QuadsSetSubset(0, 0, 1, 1);
QuadContainerAddSprite(m_TeeQuadContainerIndex, -32.f, -16.f, 64.f, 32.f);
Graphics()->QuadsSetSubset(0, 0, 1, 1);
QuadContainerAddSprite(m_TeeQuadContainerIndex, -32.f, -16.f, 64.f, 32.f);
// Mirrored Feet
Graphics()->QuadsSetSubsetFree(1, 0, 0, 0, 0, 1, 1, 1);
QuadContainerAddSprite(m_TeeQuadContainerIndex, -32.f, -16.f, 64.f, 32.f);
Graphics()->QuadsSetSubsetFree(1, 0, 0, 0, 0, 1, 1, 1);
QuadContainerAddSprite(m_TeeQuadContainerIndex, -32.f, -16.f, 64.f, 32.f);
Graphics()->QuadContainerUpload(m_TeeQuadContainerIndex);
}
@ -297,6 +305,7 @@ void CRenderTools::RenderTee(CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote
int QuadOffset = 2;
int EyeQuadOffset = 0;
int TeeEye = 0;
switch(Emote)
{
case EMOTE_PAIN:
@ -338,6 +347,10 @@ void CRenderTools::RenderTee(CAnimState *pAnim, CTeeRenderInfo *pInfo, int Emote
float h = BaseSize / 2;
int QuadOffset = 7;
if(Dir.x < 0 && pInfo->m_FeetFlipped)
{
QuadOffset += 2;
}
Graphics()->QuadsSetRotation(pFoot->m_Angle * pi * 2);

View file

@ -48,6 +48,7 @@ public:
float m_Size;
int m_GotAirJump;
int m_TeeRenderFlags;
bool m_FeetFlipped;
};
// Tee Render Flags

View file

@ -62,6 +62,20 @@ int CTuningParams::PossibleTunings(const char *pStr, IConsole::FPossibleCallback
return Index;
}
float CTuningParams::GetWeaponFireDelay(int Weapon) const
{
switch(Weapon)
{
case WEAPON_HAMMER: return (float)m_HammerHitFireDelay / 1000.0f;
case WEAPON_GUN: return (float)m_GunFireDelay / 1000.0f;
case WEAPON_SHOTGUN: return (float)m_ShotgunFireDelay / 1000.0f;
case WEAPON_GRENADE: return (float)m_GrenadeFireDelay / 1000.0f;
case WEAPON_LASER: return (float)m_LaserFireDelay / 1000.0f;
case WEAPON_NINJA: return (float)m_NinjaFireDelay / 1000.0f;
default: dbg_assert(false, "invalid weapon"); return 0.0f; // this value should not be reached
}
}
float VelocityRamp(float Value, float Start, float Range, float Curvature)
{
if(Value < Start)
@ -266,7 +280,7 @@ void CCharacterCore::Tick(bool UseInput, bool DoDeferredTick)
int teleNr = 0;
int Hit = m_pCollision->IntersectLineTeleHook(m_HookPos, NewPos, &NewPos, 0, &teleNr);
//m_NewHook = false;
// m_NewHook = false;
if(Hit)
{
@ -354,8 +368,8 @@ void CCharacterCore::Tick(bool UseInput, bool DoDeferredTick)
}
// keep players hooked for a max of 1.5sec
//if(Server()->Tick() > hook_tick+(Server()->TickSpeed()*3)/2)
//release_hooked();
// if(Server()->Tick() > hook_tick+(Server()->TickSpeed()*3)/2)
// release_hooked();
}
// don't do this hook rutine when we are hook to a player
@ -405,8 +419,8 @@ void CCharacterCore::TickDeferred()
if(!pCharCore)
continue;
//player *p = (player*)ent;
//if(pCharCore == this) // || !(p->flags&FLAG_ALIVE)
// player *p = (player*)ent;
// if(pCharCore == this) // || !(p->flags&FLAG_ALIVE)
if(pCharCore == this || (m_Id != -1 && !m_pTeams->CanCollide(m_Id, i)))
continue; // make sure that we don't nudge our self

View file

@ -66,6 +66,7 @@ public:
bool Get(const char *pName, float *pValue) const;
static const char *Name(int Index) { return ms_apNames[Index]; }
int PossibleTunings(const char *pStr, IConsole::FPossibleCallback pfnCallback = IConsole::EmptyPossibleCommandCallback, void *pUser = nullptr);
float GetWeaponFireDelay(int Weapon) const;
};
inline void StrToInts(int *pInts, int Num, const char *pStr)
@ -167,7 +168,7 @@ enum
COREEVENT_HOOK_ATTACH_GROUND = 0x10,
COREEVENT_HOOK_HIT_NOHOOK = 0x20,
COREEVENT_HOOK_RETRACT = 0x40,
//COREEVENT_HOOK_TELE=0x80,
// COREEVENT_HOOK_TELE=0x80,
};
// show others values - do not change them
@ -320,7 +321,7 @@ private:
static bool IsSwitchActiveCb(int Number, void *pUser);
};
//input count
// input count
struct CInputCount
{
int m_Presses;