Add animation system

master
Marrub 2017-10-04 05:07:02 -04:00
parent 866b3000e5
commit 4bf6ea3d87
11 changed files with 259 additions and 52 deletions

View File

@ -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

View File

@ -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"

View File

@ -1 +1,4 @@
extmem Entity subtype 1;
extmem Entity subtype 1;
extmem RenderThinker frame 1;
extmem RenderThinker ftime 1;
extmem RenderThinker curanim 1;

View File

@ -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

View File

@ -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);

View File

@ -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
//

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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};