From 4bf6ea3d872221ff757e0e61fa7f96a466dcd320 Mon Sep 17 00:00:00 2001 From: Marrub Date: Wed, 4 Oct 2017 05:07:02 -0400 Subject: [PATCH] Add animation system --- data/objdefs/player.dod | 54 +++++++++++++++++++++++++-- data/resdecl.rd | 10 +++-- src/extmem.nts | 5 ++- src/g_objdef.c | 22 ++++++++--- src/g_objdef.h | 11 +++--- src/g_object.c | 67 +++++++++++++++++++++++++++++++++ src/g_object.h | 41 +++++++++++++++++++- src/g_player.c | 83 ++++++++++++++++++++++++++++------------- src/g_player.h | 10 +++-- src/m_types.h | 6 ++- src/main.c | 2 +- 11 files changed, 259 insertions(+), 52 deletions(-) diff --git a/data/objdefs/player.dod b/data/objdefs/player.dod index dc76dea..10c8afd 100644 --- a/data/objdefs/player.dod +++ b/data/objdefs/player.dod @@ -1,12 +1,58 @@ // Copyright © 2017 Project Golan, all rights reserved. +frame PlayerIdle A "@sprites/Player/Idle.png" +frame PlayerLeft AB "@sprites/Player/TurnLeft%i.png" +frame PlayerRigh AB "@sprites/Player/TurnRight%i.png" +frame PlayerShot ABC "ent/shotfire%i" + +anim PlayerShot +{ + PlayerShot ABC 2 +} + +anim PlayerIdle +{ + PlayerIdle A -1 +} + +anim PlayerLeft +{ + PlayerIdle A 2 + PlayerLeft A 4 + PlayerLeft B -1 +} + +anim PlayerRigh +{ + PlayerIdle A 2 + PlayerRigh A 4 + PlayerRigh B -1 +} + +anim PlayerFLef +{ + PlayerLeft BA 3 + PlayerIdle A -1 +} + +anim PlayerFRig +{ + PlayerRigh BA 3 + PlayerIdle A -1 +} + entity Player { - health 1 subtype Player - size 4 - drawsize 16 + health 1 + size 6 + drawsize 30 friction 0.9 - sprite "ent/player" + + anim Idle = PlayerIdle + anim Left = PlayerLeft + anim Righ = PlayerRigh + anim FLef = PlayerFLef + anim FRig = PlayerFRig } // EOF diff --git a/data/resdecl.rd b/data/resdecl.rd index 76e41de..c54f60c 100644 --- a/data/resdecl.rd +++ b/data/resdecl.rd @@ -3,13 +3,17 @@ font "base" = "fonts/base.ttf", 24pt texture "gui/border" = "textures/Border.png" -texture "ent/player" = "sprites/Particle3_Pointer.png" -texture "ent/testobj" = "sprites/Particle3.png" -texture "ent/missile" = "sprites/Particle4.png" +texture "ent/testobj" = "sprites/Particle3.png" texture "ent/explosion1" = "sprites/Explosion1.png" texture "ent/explosion2" = "sprites/Explosion2.png" texture "ent/explosion3" = "sprites/Explosion3.png" +texture "ent/shotl" = "sprites/Player/ShotL.png" +texture "ent/shotr" = "sprites/Player/ShotR.png" +texture "ent/shotfire1" = "sprites/Player/ShotFire1.png" +texture "ent/shotfire2" = "sprites/Player/ShotFire2.png" +texture "ent/shotfire3" = "sprites/Player/ShotFire3.png" + texture "box" = "textures/Box.png" texture "empty" = "textures/Empty.png" diff --git a/src/extmem.nts b/src/extmem.nts index 69a2505..311fb6c 100644 --- a/src/extmem.nts +++ b/src/extmem.nts @@ -1 +1,4 @@ -extmem Entity subtype 1; +extmem Entity subtype 1; +extmem RenderThinker frame 1; +extmem RenderThinker ftime 1; +extmem RenderThinker curanim 1; diff --git a/src/g_objdef.c b/src/g_objdef.c index e1ca20d..b05944b 100644 --- a/src/g_objdef.c +++ b/src/g_objdef.c @@ -125,8 +125,9 @@ typedef struct G_frdcl typedef struct G_andcl { M_Vec_decl(G_frame, frame); - char name[32]; - size_t keyhash; + G_anima anim; + char name[32]; + size_t keyhash; struct G_andcl *next, **prev; } G_andcl; @@ -258,7 +259,7 @@ static void G_ObjDef_getEntAnim(G_dodst *st, G_etdcl *decl) G_manim *anim = &M_Vec_next(decl->anims); M_strbufcpy(anim->name, alias); anim->keyhash = M_StrHash(anim->name); - anim->anim = (G_anima){an->frameV, an->frameC}; + anim->anim = an->anim; decl->anim.insert(anim); } @@ -419,6 +420,8 @@ static void G_ObjDef_parseAnimDef(G_dodst *st) while(!st->drop(tok_bracec)) G_ObjDef_parseAnim(st, decl); + decl->anim = (G_anima){decl->frameV, decl->frameC}; + if(ins) { decl->keyhash = M_StrHash(decl->name); G_animsmap.insert(decl); @@ -556,12 +559,21 @@ G_entty const *G_ObjDef_GetType(char const *name) } // -// G_ObjDef_GetAnim +// G_ObjDef_GetTAni // -G_anima const *G_ObjDef_GetAnim(G_entty const *type, char const *name) +G_anima const *G_ObjDef_GetTAni(G_entty const *type, char const *name) { G_manim *anim = ((G_etdcl *)type)->anim.find(name); return anim ? &anim->anim : NULL; } +// +// G_ObjDef_GetAnim +// +G_anima const *G_ObjDef_GetAnim(char const *name) +{ + G_andcl *an = G_animsmap.find(name); + return an ? &an->anim : NULL; +} + // EOF diff --git a/src/g_objdef.h b/src/g_objdef.h index 397bea1..3038417 100644 --- a/src/g_objdef.h +++ b/src/g_objdef.h @@ -21,12 +21,12 @@ } while(0) #define G_ObjDef_createTask(type, ...) \ - (DGE_Task_Create(0, (type)->task, __VA_ARGS__)) + (DGE_Task_Create(0, (type)->task, (type), __VA_ARGS__)) // Extern Functions ----------------------------------------------------------| struct G_entty const *G_ObjDef_GetType(char const *name); -struct G_anima const *G_ObjDef_GetAnim(struct G_entty const *type, char const *name); +struct G_anima const *G_ObjDef_GetTAni(struct G_entty const *type, char const *name); // Types ---------------------------------------------------------------------| @@ -38,13 +38,13 @@ typedef struct G_frame // Frame typedef struct G_anima // Animation { - G_frame *frame; - msize count; + G_frame const *frame; + msize count; } G_anima; typedef struct G_entty // Entity Type { - __prop getAnim {call: G_ObjDef_GetAnim(this)} + __prop getAnim {call: G_ObjDef_GetTAni(this)} M_texid sprite; integ health; @@ -59,6 +59,7 @@ typedef struct G_entty // Entity Type // Extern Functions ----------------------------------------------------------| +G_anima const *G_ObjDef_GetAnim(char const *name); void G_ObjDef_Init(void); void G_ObjDef_Load(char const *fname); void G_ObjDef_AddType(char const *name, mword subtype, mword ext, DGE_CallbackType fptr); diff --git a/src/g_object.c b/src/g_object.c index a74fabe..35f1db8 100644 --- a/src/g_object.c +++ b/src/g_object.c @@ -9,6 +9,73 @@ // Extern Functions ----------------------------------------------------------| +// +// G_Object_AnimGet +// +G_anima const *G_Object_AnimGet(unsigned id, unsigned ofs) +{ + return (G_anima const *)DGE_Object_MemberGet(unsigned, id, ofs); +} + +// +// G_Object_AnimSet +// +void G_Object_AnimSet(unsigned id, unsigned ofs, G_anima const *an) +{ + DGE_Object_MemberSet(unsigned, id, ofs, (unsigned)an); +} + +// +// G_RenderThinker_Animate +// +void G_RenderThinker_Animate(unsigned id) +{ + G_rthnk th = {id}; + + if(th.ftime > 0) + th.ftime = th.ftime - 1; + + else if(th.ftime == 0 && th.curanim) + { + if(th.frame < th.curanim->count) + { + G_frame const *const fr = &th.curanim->frame[th.frame]; + th.sprite = fr->sprite; + th.ftime = fr->time; + th.frame = th.frame + 1; + } + else + th.sprite = 0; + } +} + +// +// G_RenderThinker_AnimSet +// +void G_RenderThinker_AnimSet(unsigned id, G_anima const *anim) +{ + G_rthnk th = {id}; + + if(anim && th.curanim != anim) + { + th.curanim = anim; + th.frame = 0; + th.ftime = 0; + } +} + +// +// G_RenderThinker_AnimSetForced +// +void G_RenderThinker_AnimSetForced(unsigned id, G_anima const *anim) +{ + G_rthnk th = {id}; + + th.curanim = anim; + th.frame = 0; + th.ftime = 0; +} + // // G_Entity_Create // diff --git a/src/g_object.h b/src/g_object.h index 43fcac7..383ad2d 100644 --- a/src/g_object.h +++ b/src/g_object.h @@ -10,10 +10,36 @@ __prop name {__get: DGE_Object_MemberGet(t, ->id, ofs), \ __set: DGE_Object_MemberSet(t, ->id, ofs)} +#define G_propMemFcn(ofs, fn, name) \ + __prop name {__get: fn##Get(->id, ofs), \ + __set: fn##Set(->id, ofs)} + #define G_propMemExt(base, ofs, t, name) \ G_propMemOfs(DGE_OME_##base + (ofs), t, name) #define G_Entity_propMem(ofs, t, name) G_propMemExt(Entity, ofs, t, name) +#define G_RenderThinker_propMem(ofs, t, name) \ + G_propMemExt(RenderThinker, ofs, t, name) + +#define G_RenderThinker_propExt() \ + G_propMemOfs(DGE_OME(RenderThinker.frame), unsigned, frame) \ + G_propMemOfs(DGE_OME(RenderThinker.ftime), unsigned, ftime) \ + G_propMemFcn(DGE_OME(RenderThinker.curanim), G_Object_Anim, curanim) \ + __prop animate {__call: G_RenderThinker_Animate(->id)} \ + __prop setAnim {__call: G_RenderThinker_AnimSet(->id)} \ + __prop fsetAnim {__call: G_RenderThinker_AnimSetForced(->id)} + +#define G_Entity_propExt() \ + G_propMemOfs(DGE_OME(Entity.subtype), int, subtype) + +// Extern Functions ----------------------------------------------------------| + +G_anima const *G_Object_AnimGet(unsigned id, unsigned ofs); +void G_Object_AnimSet(unsigned id, unsigned ofs, G_anima const *an); + +void G_RenderThinker_Animate(unsigned id); +void G_RenderThinker_AnimSet(unsigned id, G_anima const *anim); +void G_RenderThinker_AnimSetForced(unsigned id, G_anima const *anim); // Types ---------------------------------------------------------------------| @@ -26,8 +52,18 @@ enum G_subty subtype_max, }; +#define G_RenderThinker_props() DGE_RenderThinkerProps() \ + G_RenderThinker_propExt() +typedef struct G_rthnk // Render Thinker +{ + int id; + + G_RenderThinker_props() +} G_rthnk; + #define G_Entity_props() DGE_EntityProps() \ - G_propMemOfs(DGE_OME(Entity.subtype), int, subtype) + G_RenderThinker_propExt() \ + G_Entity_propExt() typedef struct G_entit // Entity { int id; @@ -36,7 +72,8 @@ typedef struct G_entit // Entity } G_entit; #define G_Missile_props() DGE_MissileEntityProps() \ - G_propMemOfs(DGE_OME(Entity.subtype), int, subtype) + G_RenderThinker_propExt() \ + G_Entity_propExt() typedef struct G_missl // Missile { int id; diff --git a/src/g_player.c b/src/g_player.c index 2bd1d19..8e400f9 100644 --- a/src/g_player.c +++ b/src/g_player.c @@ -4,6 +4,7 @@ #include "g_stage.h" #include "m_math.h" +#include "m_str.h" #include @@ -15,20 +16,20 @@ enum G_mslty { - missile_player, + missile_playerL, + missile_playerR, }; // Extern Objects ------------------------------------------------------------| -int G_Player_Count; -G_playr G_Player_InGame[G_Player_max]; +int G_Player_Count; // Static Functions ----------------------------------------------------------| // // G_Player_applyVelocity // -static void G_Player_applyVelocity(G_playr th) +static void G_Player_applyVelocity(G_entty const *ty, G_playr th) { DGE_Point3R ax = DGE_Input_GetAxis(1); accum vx = (accum)ax.x, vy = (accum)ax.y; @@ -39,10 +40,18 @@ static void G_Player_applyVelocity(G_playr th) sincosf(ang, &s, &c); + if(mag > 1) mag = 1; + if(mag < -1) mag = -1; + th.vx = th.vx + c * mag * 5; th.vy = th.vy - s * mag * 5; - // TODO: apply animation based on X velocity here + if(th.vx < 0) th.setAnim(ty->getAnim("Left")); + else if(th.vx > 0) th.setAnim(ty->getAnim("Righ")); + else if(th.lvx < 0) th.setAnim(ty->getAnim("FLef")); + else if(th.lvx > 0) th.setAnim(ty->getAnim("FRig")); + + th.lvx = th.vx; } // Extern Functions ----------------------------------------------------------| @@ -52,29 +61,35 @@ static void G_Player_applyVelocity(G_playr th) // void G_Missile_Fire(enum G_mslty type, unsigned owner, fixed x, fixed y, fixed z, ulfra yaw) { + G_entit ot = {owner}; G_missl th = {DGE_MissileEntity_Create(0)}; th.subtype = subtype_missile; - th.x = x; - th.y = y; - th.z = z; + th.x = ot.x + x; + th.y = ot.y + y; + th.z = ot.z + z; th.yaw = yaw; th.health = 1; th.damage = 1; th.owner = owner; + th.sz = 4; float s, c; sincosf(M_angle(yaw), &s, &c); switch(type) { - case missile_player: - th.sprite = DGE_Texture_Get(s"ent/missile"); - th.rsx = 3; + case missile_playerL: th.sprite = DGE_Texture_Get(s"ent/shotl"); goto player; + case missile_playerR: th.sprite = DGE_Texture_Get(s"ent/shotr"); goto player; + player: + th.cr = 0.3ulr; + th.cg = 0.9ulr; + th.cb = 0.1ulr; + th.ca = 0.7ulr; + th.rsx = 6; th.rsy = 16; - th.sx = 4; - th.sy = 4; - th.sz = 4; + th.sx = 6; + th.sy = 18; th.vx = c * 14; th.vy = s * 14; break; @@ -85,32 +100,50 @@ void G_Missile_Fire(enum G_mslty type, unsigned owner, fixed x, fixed y, fixed z // G_Player_Think // DGE_Callback -void G_Player_Think(unsigned id) +void G_Player_Think(G_entty const *ty, unsigned id) { - G_playr th = {id}; - // TODO: remove if david makes IEMs 0-init - th.ammo = 0; + G_playr th = {id}; + G_rthnk shot = {DGE_RenderThinker_Create(0)}; + + shot.rsx = 30; + shot.rsy = 24; + th.lives = 5; - th.nextfire = 0; + + th.setAnim(ty->getAnim("Idle")); DGE_Object_RefAdd(id); - G_Player_InGame[G_Player_Count++] = th; + DGE_Object_RefAdd(shot.id); while(th.health > 0) { - G_Player_applyVelocity(th); + G_Player_applyVelocity(ty, th); - if(th.nextfire < G_Time) { - G_Missile_Fire(missile_player, th.id, th.x - 7, th.y - 10, th.z, 0); - G_Missile_Fire(missile_player, th.id, th.x + 7, th.y - 10, th.z, 0); + if(G_Time < 70) + th.y = th.y + log(G_Time / 70.0) * 0.7hk; + + else if(th.nextfire < G_Time) + { + shot.fsetAnim(G_ObjDef_GetAnim("PlayerShot")); + G_Missile_Fire(missile_playerL, th.id, -18, -7, 0, 0); + G_Missile_Fire(missile_playerR, th.id, +18, -7, 0, 0); th.nextfire = G_Time + 3; } + shot.x = th.x; + shot.y = th.y - 20; + shot.z = th.z; + + shot.animate(); + th .animate(); + DGE_Task_Sleep(0, 1); } - G_Player_InGame[--G_Player_Count] = (G_playr){0}; DGE_Object_RefSub(id); + DGE_Object_RefSub(shot.id); + + DGE_Thinker_Unlink(shot.id); } // EOF diff --git a/src/g_player.h b/src/g_player.h index bee484e..120424e 100644 --- a/src/g_player.h +++ b/src/g_player.h @@ -13,14 +13,16 @@ enum { G_Player_ammo, G_Player_lives, + G_Player_lvx, G_Player_nextfire, G_Player_propC }; #define G_Player_props() G_Entity_props() \ - G_Player_propMem(unsigned, ammo) \ - G_Player_propMem(unsigned, lives) \ - G_Player_propMem(unsigned, nextfire) + G_Player_propMem(unsigned, ammo) \ + G_Player_propMem(unsigned, lives) \ + G_Player_propMem(DGE_Accum, lvx) \ + G_Player_propMem(unsigned, nextfire) typedef struct G_playr // Player { int id; @@ -35,6 +37,6 @@ extern G_playr G_Player_InGame[G_Player_max]; // Extern Functions ----------------------------------------------------------| -DGE_Callback void G_Player_Think(unsigned id); +DGE_Callback void G_Player_Think(G_entty const *ty, unsigned id); #endif diff --git a/src/m_types.h b/src/m_types.h index ac3573b..4350012 100644 --- a/src/m_types.h +++ b/src/m_types.h @@ -33,11 +33,13 @@ typedef int96_t int96; // Integer (96 bits) #endif #if __GDCC__ -typedef short accum fixed; // Fixed +typedef short accum fixed; // Fixed Point +typedef accum lfxpt; // Long Fixed Point typedef unsigned long fract ulfra; // Unsigned Long Fractional typedef long fract lfrac; // Long Fractional #else -typedef float fixed; +typedef float fixed; +typedef double lfxpt; #endif typedef unsigned M_texid; // Texture ID diff --git a/src/main.c b/src/main.c index 022b65c..e3c7a67 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ // G_TestObj_Think // DGE_Callback -void G_TestObj_Think(unsigned id) +void G_TestObj_Think(G_entty const *ty, unsigned id) { G_entit th = {id};