Add animation system
parent
866b3000e5
commit
4bf6ea3d87
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
extmem Entity subtype 1;
|
||||
extmem Entity subtype 1;
|
||||
extmem RenderThinker frame 1;
|
||||
extmem RenderThinker ftime 1;
|
||||
extmem RenderThinker curanim 1;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "g_stage.h"
|
||||
#include "m_math.h"
|
||||
#include "m_str.h"
|
||||
|
||||
#include <Doominati.h>
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
Loading…
Reference in New Issue