Particles processing, Bob, and entity actions.
This commit is contained in:
parent
7cd5fe999a
commit
0df09f914a
|
@ -61,19 +61,20 @@ void initWeapons(void)
|
|||
missileSprite[1] = getSprite("MissileLeft");
|
||||
}
|
||||
|
||||
void firePistol(Unit *owner)
|
||||
/* only used by Bob */
|
||||
void firePistol(void)
|
||||
{
|
||||
Bullet *bullet;
|
||||
|
||||
bullet = createBaseBullet(owner);
|
||||
bullet = createBaseBullet((Unit*)world.bob);
|
||||
bullet->weaponType = WPN_PISTOL;
|
||||
bullet->facing = owner->facing;
|
||||
bullet->facing = world.bob->facing;
|
||||
bullet->sprite[0] = bulletSprite[0];
|
||||
bullet->sprite[1] = bulletSprite[1];
|
||||
|
||||
owner->reload = 20;
|
||||
world.bob->reload = 20;
|
||||
|
||||
playSound(SND_PISTOL, CH_PLAYER);
|
||||
playSound(SND_PISTOL, CH_BOB);
|
||||
}
|
||||
|
||||
void fireAimedShot(Unit *owner)
|
||||
|
@ -124,7 +125,7 @@ void firePlasma(Unit *owner)
|
|||
|
||||
owner->reload = owner->type == ET_BOB ? 4 : 8;
|
||||
|
||||
playSound(SND_PLASMA, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON);
|
||||
playSound(SND_PLASMA, owner->type == ET_BOB ? CH_BOB : CH_WEAPON);
|
||||
}
|
||||
|
||||
void fireSpread(Unit *owner, int numberOfShots)
|
||||
|
@ -148,7 +149,7 @@ void fireSpread(Unit *owner, int numberOfShots)
|
|||
owner->reload = 16;
|
||||
}
|
||||
|
||||
playSound(SND_SPREAD, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON);
|
||||
playSound(SND_SPREAD, owner->type == ET_BOB ? CH_BOB : CH_WEAPON);
|
||||
}
|
||||
|
||||
void fireLaser(Unit *owner)
|
||||
|
@ -167,7 +168,7 @@ void fireLaser(Unit *owner)
|
|||
|
||||
owner->reload = owner->type == ET_BOB ? FPS / 2 : FPS;
|
||||
|
||||
playSound(SND_LASER, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON);
|
||||
playSound(SND_LASER, owner->type == ET_BOB ? CH_BOB : CH_WEAPON);
|
||||
}
|
||||
|
||||
void fireGrenade(Unit *owner)
|
||||
|
@ -187,7 +188,7 @@ void fireGrenade(Unit *owner)
|
|||
|
||||
owner->reload = FPS / 2;
|
||||
|
||||
playSound(SND_THROW, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON);
|
||||
playSound(SND_THROW, owner->type == ET_BOB ? CH_BOB : CH_WEAPON);
|
||||
}
|
||||
|
||||
void fireShotgun(Unit *owner)
|
||||
|
|
|
@ -209,7 +209,8 @@ enum
|
|||
enum
|
||||
{
|
||||
WS_IN_PROGRESS,
|
||||
WS_COMPLETE
|
||||
WS_COMPLETE,
|
||||
WS_GAME_OVER
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -289,7 +290,7 @@ enum
|
|||
enum
|
||||
{
|
||||
CH_ANY = -1,
|
||||
CH_PLAYER,
|
||||
CH_BOB,
|
||||
CH_EXPLODE,
|
||||
CH_WEAPON,
|
||||
CH_DEATH,
|
||||
|
|
|
@ -23,8 +23,29 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
static SDL_Rect *getCurrentSprite(void);
|
||||
static void (*superAnimate)(void);
|
||||
static void animate(void);
|
||||
static void tick(void);
|
||||
static void doAlive(void);
|
||||
static void doDying(void);
|
||||
static void doBobInWater(void);
|
||||
static void doBobInAir(void);
|
||||
static void handeImmunity(void);
|
||||
static void changeSprite(Sprite **sprite);
|
||||
static void load(cJSON *root);
|
||||
static void save(cJSON *root);
|
||||
static int completelyOnGround(void);
|
||||
void resetAtCheckpoint(void);
|
||||
void terminateJetpack(void);
|
||||
static void bobFly(void);
|
||||
static void bobWalk(void);
|
||||
static void bobSwim(void);
|
||||
static void fireWeapon(void);
|
||||
static void activate(int activate);
|
||||
static void changeEnvironment(void);
|
||||
|
||||
static Sprite *walkSprite[3];
|
||||
static Sprite *swimSprite[3];
|
||||
static Sprite *flySprite[3];
|
||||
static int checkpointTimer;
|
||||
|
||||
void initBob(void)
|
||||
{
|
||||
|
@ -34,18 +55,563 @@ void initBob(void)
|
|||
|
||||
u->type = ET_BOB;
|
||||
|
||||
u->sprite[FACING_LEFT] = getSprite("BobLeft");
|
||||
u->sprite[FACING_RIGHT] = getSprite("BobRight");
|
||||
u->sprite[FACING_DIE] = getSprite("BobSpin");
|
||||
memset(&world.bob->itemHead, 0, sizeof(Item));
|
||||
world.bob->itemTail = &world.bob->itemHead;
|
||||
|
||||
walkSprite[FACING_LEFT] = getSprite("BobLeft");
|
||||
walkSprite[FACING_RIGHT] = getSprite("BobRight");
|
||||
walkSprite[FACING_DIE] = getSprite("BobSpin");
|
||||
|
||||
swimSprite[FACING_LEFT] = getSprite("BobAquaLeft");
|
||||
swimSprite[FACING_RIGHT] = getSprite("BobAquaRight");
|
||||
swimSprite[FACING_DIE] = getSprite("BobAquaSpin");
|
||||
|
||||
flySprite[FACING_LEFT] = getSprite("BobJPLeft");
|
||||
flySprite[FACING_RIGHT] = getSprite("BobJPRight");
|
||||
flySprite[FACING_DIE] = getSprite("BobSpin");
|
||||
|
||||
changeSprite(walkSprite);
|
||||
|
||||
world.bob->health = world.bob->healthMax = game.hearts;
|
||||
world.bob->power = world.bob->powerMax = game.cells;
|
||||
|
||||
world.bob->weaponType = WPN_PISTOL;
|
||||
world.bob->reload = 0;
|
||||
|
||||
world.bob->flags |= EF_SWIMS | EF_BOMB_SHIELD;
|
||||
|
||||
superAnimate = u->animate;
|
||||
|
||||
world.bob->tick = tick;
|
||||
u->getCurrentSprite = getCurrentSprite;
|
||||
u->animate = animate;
|
||||
u->activate = activate;
|
||||
u->changeEnvironment = changeEnvironment;
|
||||
u->load = load;
|
||||
u->save = save;
|
||||
}
|
||||
|
||||
static void tick(void)
|
||||
{
|
||||
if (world.isTrainingMission || dev.cheatHealth)
|
||||
{
|
||||
world.bob->alive = ALIVE_ALIVE;
|
||||
world.bob->health = world.bob->healthMax;
|
||||
}
|
||||
|
||||
if (world.isTrainingMission)
|
||||
{
|
||||
world.bob->power = MIN(world.bob->power + 0.01, world.bob->powerMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
world.bob->power = MIN(world.bob->power + 0.00065, world.bob->powerMax);
|
||||
}
|
||||
|
||||
if (dev.cheatPower)
|
||||
{
|
||||
world.bob->power = world.bob->powerMax;
|
||||
}
|
||||
|
||||
if (dev.cheatReload && world.bob->reload > 4)
|
||||
{
|
||||
world.bob->reload = 4;
|
||||
}
|
||||
|
||||
switch (world.bob->alive)
|
||||
{
|
||||
case ALIVE_ALIVE:
|
||||
doAlive();
|
||||
break;
|
||||
case ALIVE_DYING:
|
||||
doDying();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void doAlive(void)
|
||||
{
|
||||
handeImmunity();
|
||||
|
||||
world.bob->checkpointTimer = MAX(world.bob->checkpointTimer - 1, 0);
|
||||
|
||||
world.bob->reload = limit(world.bob->reload - 1, 0, FPS);
|
||||
|
||||
switch (world.bob->environment)
|
||||
{
|
||||
case ENV_AIR:
|
||||
doBobInAir();
|
||||
break;
|
||||
|
||||
case ENV_WATER:
|
||||
doBobInWater();
|
||||
break;
|
||||
|
||||
case ENV_SLIME:
|
||||
if (world.bob->alive == ALIVE_ALIVE && world.bob->outTimer == 0)
|
||||
{
|
||||
world.bob->outTimer = FPS * 3;
|
||||
world.bob->stunTimer = 1;
|
||||
if (world.bob->flags & EF_IMMUNE)
|
||||
{
|
||||
world.bob->health--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ENV_LAVA:
|
||||
if (world.bob->alive == ALIVE_ALIVE && world.bob->outTimer == 0)
|
||||
{
|
||||
world.bob->outTimer = FPS * 3;
|
||||
world.bob->stunTimer = 1;
|
||||
if (world.bob->flags & EF_IMMUNE)
|
||||
{
|
||||
world.bob->health -= 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handeImmunity(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (world.bob->outTimer > 0)
|
||||
{
|
||||
world.bob->outTimer--;
|
||||
if (world.bob->outTimer <= 0)
|
||||
{
|
||||
world.betweenTimer = FPS / 2;
|
||||
resetAtCheckpoint();
|
||||
}
|
||||
}
|
||||
else if (world.bob->stunTimer > 0)
|
||||
{
|
||||
world.bob->stunTimer--;
|
||||
if (world.bob->stunTimer <= 0)
|
||||
{
|
||||
if (!world.bob->isOnGround && world.bob->environment != ENV_WATER)
|
||||
{
|
||||
world.bob->stunTimer = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
world.bob->spriteFrame = 0;
|
||||
world.bob->spriteTime = 0;
|
||||
world.bob->dy = 0;
|
||||
world.bob->flags &= ~EF_BOUNCES;
|
||||
world.bob->flags |= EF_FLICKER;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (world.bob->immuneTimer > 0)
|
||||
{
|
||||
world.bob->immuneTimer--;
|
||||
if (world.bob->immuneTimer <= 0)
|
||||
{
|
||||
world.bob->flags &= ~(EF_FLICKER | EF_IMMUNE);
|
||||
}
|
||||
}
|
||||
else if (world.bob->checkpointTimer == 0 && world.bob->isOnGround && completelyOnGround() && world.bob->environment == ENV_AIR && world.bob->riding == NULL)
|
||||
{
|
||||
for (i = MAX_CHECKPOINTS - 1 ; i > 0 ; i--)
|
||||
{
|
||||
world.bob->checkpoints[i].x = world.bob->checkpoints[i - 1].x;
|
||||
world.bob->checkpoints[i].y = world.bob->checkpoints[i - 1].y;
|
||||
}
|
||||
|
||||
world.bob->checkpoints[0].x = world.bob->x;
|
||||
world.bob->checkpoints[0].y = world.bob->y;
|
||||
checkpointTimer = FPS;
|
||||
}
|
||||
}
|
||||
|
||||
static int completelyOnGround(void)
|
||||
{
|
||||
int x1, x2, y;
|
||||
|
||||
x1 = (world.bob->x / MAP_TILE_SIZE);
|
||||
x2 = ((world.bob->x + world.bob->w) / MAP_TILE_SIZE);
|
||||
y = ((world.bob->y + world.bob->h + 8) / MAP_TILE_SIZE);
|
||||
|
||||
return isSolid(x1, y) && isSolid(x2, y);
|
||||
}
|
||||
|
||||
|
||||
static void activate(int activate)
|
||||
{
|
||||
if (world.bob->stunTimer <= 0)
|
||||
{
|
||||
if (world.bob->flags & (EF_WATER_BREATHING | EF_WEIGHTLESS))
|
||||
{
|
||||
world.bob->flags &= ~(EF_WATER_BREATHING | EF_WEIGHTLESS);
|
||||
changeSprite(walkSprite);
|
||||
}
|
||||
else if (world.bob->power > 0)
|
||||
{
|
||||
if (world.bob->environment == ENV_AIR)
|
||||
{
|
||||
world.bob->flags |= EF_WEIGHTLESS;
|
||||
changeSprite(flySprite);
|
||||
}
|
||||
else if (world.bob->environment == ENV_WATER)
|
||||
{
|
||||
world.bob->flags |= EF_WATER_BREATHING;
|
||||
changeSprite(swimSprite);
|
||||
}
|
||||
|
||||
world.bob->dy = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (world.bob->environment == ENV_AIR)
|
||||
{
|
||||
setGameplayMessage(MSG_STANDARD, _("Not enough power for jetpack"));
|
||||
}
|
||||
else
|
||||
{
|
||||
setGameplayMessage(MSG_STANDARD, _("Not enough power for aqualung"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doBobInAir(void)
|
||||
{
|
||||
world.bob->oxygen = limit(world.bob->oxygen + 4, 0, MAX_OXYGEN);
|
||||
|
||||
if (world.bob->flags & EF_WEIGHTLESS)
|
||||
{
|
||||
if (!dev.cheatPower)
|
||||
{
|
||||
world.bob->power = limit(world.bob->power - (1.0 / FPS), 0, world.bob->powerMax);
|
||||
}
|
||||
|
||||
if (--world.bob->jpEffectTimer <= 0)
|
||||
{
|
||||
addFlameParticles(world.bob->x + (world.bob->facing * 25) + rrnd(-1, 1), world.bob->y + 25 + rrnd(-1, 1));
|
||||
world.bob->jpEffectTimer = 1;
|
||||
}
|
||||
|
||||
if (world.bob->power == 0)
|
||||
{
|
||||
terminateJetpack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void terminateJetpack(void)
|
||||
{
|
||||
changeSprite(walkSprite);
|
||||
|
||||
world.bob->flags &= ~EF_WEIGHTLESS;
|
||||
}
|
||||
|
||||
static void doBobInWater(void)
|
||||
{
|
||||
if (world.bob->flags & EF_WATER_BREATHING)
|
||||
{
|
||||
if (!dev.cheatPower)
|
||||
{
|
||||
world.bob->power = limit(world.bob->power - (1.0 / FPS), 0, world.bob->powerMax);
|
||||
}
|
||||
|
||||
if (world.bob->power == 0)
|
||||
{
|
||||
world.bob->flags &= ~EF_WATER_BREATHING;
|
||||
changeSprite(walkSprite);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
world.bob->oxygen = limit(--world.bob->oxygen, 0, MAX_OXYGEN);
|
||||
|
||||
if (world.bob->oxygen == 0 && (world.frameCounter % 30) == 0)
|
||||
{
|
||||
world.bob->health--;
|
||||
playSound(SND_DROWN, CH_BOB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doDying(void)
|
||||
{
|
||||
world.bob->health--;
|
||||
|
||||
if (world.bob->health <= -(FPS * 2))
|
||||
{
|
||||
world.bob->alive = ALIVE_DEAD;
|
||||
|
||||
throwFleshChunks(world.bob->x + world.bob->w / 2, world.bob->y + world.bob->h / 2, rrnd(3, 6));
|
||||
|
||||
world.state = WS_GAME_OVER;
|
||||
|
||||
playSound(SND_SPLAT, CH_BOB);
|
||||
|
||||
game.deaths++;
|
||||
}
|
||||
}
|
||||
|
||||
void stunBob(void)
|
||||
{
|
||||
terminateJetpack();
|
||||
|
||||
world.bob->stunTimer = FPS;
|
||||
world.bob->immuneTimer = FPS * 2;
|
||||
world.bob->spriteFrame = 0;
|
||||
world.bob->spriteTime = 0;
|
||||
world.bob->flags &= ~EF_FLICKER;
|
||||
world.bob->flags |= (EF_BOUNCES | EF_IMMUNE);
|
||||
}
|
||||
|
||||
|
||||
void applyDamage(int damage)
|
||||
{
|
||||
if (!(world.bob->flags & EF_IMMUNE) && !world.isTrainingMission && !dev.cheatHealth && world.bob->alive != ALIVE_DEAD)
|
||||
{
|
||||
if (world.bob->health < 0)
|
||||
{
|
||||
world.bob->health = 0;
|
||||
world.bob->alive = ALIVE_ALIVE;
|
||||
}
|
||||
|
||||
world.bob->health -= damage;
|
||||
|
||||
if (world.bob->health > 0)
|
||||
{
|
||||
world.bob->immuneTimer = FPS * 2;
|
||||
|
||||
world.bob->flags |= EF_FLICKER | EF_IMMUNE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doBob(void)
|
||||
{
|
||||
if (world.bob->stunTimer <= 0 && world.bob->health > 0)
|
||||
{
|
||||
if (world.bob->flags & EF_WEIGHTLESS)
|
||||
{
|
||||
bobFly();
|
||||
}
|
||||
else if (world.bob->environment == ENV_AIR)
|
||||
{
|
||||
bobWalk();
|
||||
}
|
||||
else if (world.bob->environment == ENV_WATER)
|
||||
{
|
||||
bobSwim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void bobWalk(void)
|
||||
{
|
||||
world.bob->dx = 0;
|
||||
|
||||
if (game.config.control[CONTROL_LEFT])
|
||||
{
|
||||
world.bob->dx = -WALK_SPEED;
|
||||
world.bob->facing = FACING_LEFT;
|
||||
}
|
||||
|
||||
if (game.config.control[CONTROL_RIGHT])
|
||||
{
|
||||
world.bob->dx = WALK_SPEED;
|
||||
world.bob->facing = FACING_RIGHT;
|
||||
}
|
||||
|
||||
if (game.config.control[CONTROL_JUMP] && world.bob->isOnGround)
|
||||
{
|
||||
world.bob->dy = JUMP_POWER;
|
||||
}
|
||||
|
||||
if (game.config.control[CONTROL_FIRE] && world.bob->reload == 0)
|
||||
{
|
||||
fireWeapon();
|
||||
}
|
||||
}
|
||||
|
||||
static void bobSwim(void)
|
||||
{
|
||||
world.bob->dx = 0;
|
||||
world.bob->dy = 0.5f;
|
||||
|
||||
if (game.config.control[CONTROL_LEFT])
|
||||
{
|
||||
world.bob->dx = -SWIM_SPEED;
|
||||
world.bob->facing = FACING_LEFT;
|
||||
}
|
||||
|
||||
if (game.config.control[CONTROL_RIGHT])
|
||||
{
|
||||
world.bob->dx = SWIM_SPEED;
|
||||
world.bob->facing = FACING_RIGHT;
|
||||
}
|
||||
|
||||
if (game.config.control[CONTROL_JUMP] || game.config.control[CONTROL_UP])
|
||||
{
|
||||
world.bob->dy = -SWIM_SPEED;
|
||||
}
|
||||
|
||||
if (game.config.control[CONTROL_DOWN])
|
||||
{
|
||||
world.bob->dy = SWIM_SPEED;
|
||||
}
|
||||
|
||||
if (game.config.control[CONTROL_FIRE] && world.bob->reload == 0 && world.bob->weaponType == WPN_PISTOL)
|
||||
{
|
||||
firePistol();
|
||||
}
|
||||
}
|
||||
|
||||
static void bobFly(void)
|
||||
{
|
||||
if (game.config.control[CONTROL_LEFT])
|
||||
{
|
||||
world.bob->dx -= FLY_ACCEL;
|
||||
world.bob->facing = FACING_LEFT;
|
||||
}
|
||||
|
||||
if (game.config.control[CONTROL_RIGHT])
|
||||
{
|
||||
world.bob->dx += FLY_ACCEL;
|
||||
world.bob->facing = FACING_RIGHT;
|
||||
}
|
||||
|
||||
if (game.config.control[CONTROL_UP])
|
||||
{
|
||||
world.bob->dy -= FLY_ACCEL;
|
||||
}
|
||||
|
||||
if (game.config.control[CONTROL_DOWN])
|
||||
{
|
||||
world.bob->dy += FLY_ACCEL;
|
||||
}
|
||||
|
||||
if (game.config.control[CONTROL_FIRE] && world.bob->reload == 0)
|
||||
{
|
||||
fireWeapon();
|
||||
}
|
||||
|
||||
world.bob->dx = MIN(FLY_SPEED, MAX(world.bob->dx, -FLY_SPEED));
|
||||
world.bob->dy = MIN(FLY_SPEED, MAX(world.bob->dy, -FLY_SPEED));
|
||||
}
|
||||
|
||||
static void fireWeapon(void)
|
||||
{
|
||||
switch (world.bob->weaponType)
|
||||
{
|
||||
case WPN_PISTOL:
|
||||
firePistol();
|
||||
break;
|
||||
case WPN_PLASMA:
|
||||
firePlasma((Entity*)world.bob);
|
||||
break;
|
||||
case WPN_SPREAD:
|
||||
fireSpread((Entity*)world.bob, 3);
|
||||
game.statShotsFired[WPN_SPREAD] += 2;
|
||||
break;
|
||||
case WPN_LASER:
|
||||
fireLaser((Entity*)world.bob);
|
||||
break;
|
||||
case WPN_GRENADES:
|
||||
fireGrenade((Entity*)world.bob);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
game.statShotsFired[world.bob->weaponType]++;
|
||||
}
|
||||
|
||||
|
||||
static void changeEnvironment(void)
|
||||
{
|
||||
switch (world.bob->environment)
|
||||
{
|
||||
case ENV_AIR:
|
||||
case ENV_LAVA:
|
||||
case ENV_SLIME:
|
||||
world.bob->flags &= ~EF_WATER_BREATHING;
|
||||
changeSprite(walkSprite);
|
||||
break;
|
||||
case ENV_WATER:
|
||||
terminateJetpack();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void changeSprite(Sprite **sprite)
|
||||
{
|
||||
world.bob->sprite[0] = sprite[0];
|
||||
world.bob->sprite[1] = sprite[1];
|
||||
world.bob->sprite[2] = sprite[2];
|
||||
world.bob->spriteFrame = 0;
|
||||
world.bob->spriteTime = 0;
|
||||
}
|
||||
|
||||
void setCheckpoint(void)
|
||||
{
|
||||
world.bob->checkpoints[0].x = world.bob->x;
|
||||
world.bob->checkpoints[0].y = world.bob->y;
|
||||
}
|
||||
|
||||
void resetAtCheckpoint(void)
|
||||
{
|
||||
world.bob->x = world.bob->checkpoints[0].x;
|
||||
world.bob->y = world.bob->checkpoints[0].y;
|
||||
|
||||
world.bob->outTimer = 0;
|
||||
world.bob->flags |= EF_FLICKER;
|
||||
world.bob->flags &= ~EF_WEIGHTLESS;
|
||||
changeSprite(walkSprite);
|
||||
world.bob->environment = ENV_AIR;
|
||||
|
||||
if (!game.isResumingMission)
|
||||
{
|
||||
world.bob->immuneTimer = FPS * 2;
|
||||
addTeleportStars((Entity*)world.bob);
|
||||
if (world.state == WS_IN_PROGRESS)
|
||||
{
|
||||
playSound(SND_APPEAR, CH_ANY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void die(void)
|
||||
{
|
||||
world.bob->flags &= ~EF_WEIGHTLESS;
|
||||
|
||||
world.bob->flags |= EF_BOUNCES;
|
||||
|
||||
if (world.bob->environment == ENV_AIR)
|
||||
{
|
||||
world.bob->dy = -9;
|
||||
}
|
||||
|
||||
world.bob->dx = (randF() - randF()) * 5;
|
||||
|
||||
switch (rand() % 3)
|
||||
{
|
||||
case 0:
|
||||
playSound(SND_DEATH_1, CH_DEATH);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
playSound(SND_DEATH_2, CH_DEATH);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
playSound(SND_DEATH_3, CH_DEATH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void addBobItem(Item *i)
|
||||
{
|
||||
|
||||
|
|
|
@ -21,9 +21,34 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "../../common.h"
|
||||
#include "../../json/cJSON.h"
|
||||
|
||||
#define WALK_SPEED 5
|
||||
#define SWIM_SPEED 3
|
||||
#define FLY_ACCEL 0.1
|
||||
#define FLY_SPEED 8
|
||||
|
||||
extern Unit *createUnit(void);
|
||||
extern Sprite *getSprite(char *name);
|
||||
extern char *getLookupName(const char *prefix, long num);
|
||||
extern long lookup(const char *name);
|
||||
extern double randF(void);
|
||||
extern int rrnd(int low, int high);
|
||||
extern float limit(float i, float a, float b);
|
||||
extern int isSolid(int x, int y);
|
||||
extern void setGameplayMessage(int type, char *format, ...);
|
||||
extern void playSound(int snd, int ch);
|
||||
extern void addFlameParticles(float x, float y);
|
||||
extern void throwFleshChunks(float x, float y, int amount);
|
||||
extern void firePistol(void);
|
||||
extern void fireAimedShot(Entity *e);
|
||||
extern void fireMachineGun(Entity *e);
|
||||
extern void fireGrenade(Entity *e);
|
||||
extern void firePlasma(Entity *e);
|
||||
extern void fireSpread(Entity *e, int n);
|
||||
extern void fireLaser(Entity *e);
|
||||
extern void fireShotgun(Entity *e);
|
||||
extern void fireMissile(Entity *e);
|
||||
extern void addTeleportStars(Entity *e);
|
||||
|
||||
extern Dev dev;
|
||||
extern Game game;
|
||||
extern World world;
|
||||
|
|
|
@ -326,8 +326,8 @@ void reappear(void)
|
|||
do
|
||||
{
|
||||
r = (int) (rand() % MAX_CHECKPOINTS);
|
||||
self->x = world.checkpoints[r].x;
|
||||
self->y = world.checkpoints[r].y;
|
||||
self->x = world.bob->checkpoints[r].x;
|
||||
self->y = world.bob->checkpoints[r].y;
|
||||
valid = (self->x != 0 && self->y != 0);
|
||||
}
|
||||
while (!valid);
|
||||
|
|
|
@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
static void init(void);
|
||||
static void reset(void);
|
||||
static void action(void);
|
||||
static void applyDamage(int damage);
|
||||
static float bounce(float x);
|
||||
static SDL_Rect *getBounds(void);
|
||||
|
@ -54,6 +55,7 @@ void initEntity(Entity *e)
|
|||
|
||||
e->init = init;
|
||||
e->reset = reset;
|
||||
e->action = action;
|
||||
e->animate = animate;
|
||||
e->tick = tick;
|
||||
e->touch = touch;
|
||||
|
@ -79,6 +81,10 @@ static void reset(void)
|
|||
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Cannot reset() entity [name=%s, type=%d, x=%d, y=%d]", self->name, self->type, (int)self->x, (int)self->y);
|
||||
}
|
||||
|
||||
static void action(void)
|
||||
{
|
||||
}
|
||||
|
||||
static SDL_Rect *getBounds(void)
|
||||
{
|
||||
self->bounds.x = self->x;
|
||||
|
@ -141,24 +147,6 @@ static float bounce(float x)
|
|||
return x;
|
||||
}
|
||||
|
||||
void teleport(Entity *e, float tx, float ty)
|
||||
{
|
||||
e->tx = tx;
|
||||
e->ty = ty;
|
||||
|
||||
e->flags |= EF_TELEPORTING;
|
||||
|
||||
addTeleportStars(e);
|
||||
}
|
||||
|
||||
void activateEntities(char *names, int activate)
|
||||
{
|
||||
}
|
||||
|
||||
void teleportEntity(Entity *e, float tx, float ty)
|
||||
{
|
||||
}
|
||||
|
||||
static void applyDamage(int damage)
|
||||
{
|
||||
|
||||
|
@ -188,27 +176,3 @@ static void save(cJSON *root)
|
|||
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "Entity [name=%s, type=%d, x=%d, y=%d] cannot be saved", self->name, self->type, (int)self->x, (int)self->y);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void dropCarriedItem(void)
|
||||
{
|
||||
EntityExt *e;
|
||||
Item *i;
|
||||
|
||||
e = (EntityExt*)self;
|
||||
|
||||
if (e->carriedItem != NULL)
|
||||
{
|
||||
i = e->carriedItem;
|
||||
|
||||
i->x = (e->x + e->w / 2) - i->w / 2;
|
||||
i->y = e->y;
|
||||
|
||||
i->dx = i->dy = 0;
|
||||
|
||||
world.entityTail->next = (Entity*)i;
|
||||
world.entityTail = (Entity*)i;
|
||||
world.entityTail->next = NULL;
|
||||
|
||||
e->carriedItem = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,5 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#include "../common.h"
|
||||
|
||||
extern void addTeleportStars(Entity *e);
|
||||
|
||||
extern Entity *self;
|
||||
extern World world;
|
||||
|
|
|
@ -43,6 +43,6 @@ static void touch(Entity *other)
|
|||
|
||||
pickupItem();
|
||||
|
||||
playSound(SND_CHERRY, CH_PLAYER);
|
||||
playSound(SND_CHERRY, CH_BOB);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,6 +157,7 @@ struct EntityExt {
|
|||
struct Entity;
|
||||
char spriteName[MAX_NAME_LENGTH];
|
||||
Item *carriedItem;
|
||||
Entity *riding;
|
||||
};
|
||||
|
||||
struct Unit {
|
||||
|
@ -205,8 +206,14 @@ struct Item {
|
|||
|
||||
struct Bob {
|
||||
struct Unit;
|
||||
int checkpointTimer;
|
||||
int outTimer;
|
||||
int stunTimer;
|
||||
int immuneTimer;
|
||||
int power, powerMax;
|
||||
int jpEffectTimer;
|
||||
PointF checkpoints[MAX_CHECKPOINTS];
|
||||
Item itemHead, *itemTail;
|
||||
};
|
||||
|
||||
struct Structure {
|
||||
|
@ -322,12 +329,12 @@ typedef struct {
|
|||
int awaitingWidgetInput;
|
||||
int lastKeyPressed;
|
||||
int lastButtonPressed;
|
||||
int keyControls[CONTROL_MAX];
|
||||
} App;
|
||||
|
||||
typedef struct {
|
||||
int sound;
|
||||
int music;
|
||||
int control[CONTROL_MAX];
|
||||
} Config;
|
||||
|
||||
typedef struct {
|
||||
|
@ -435,12 +442,13 @@ typedef struct {
|
|||
int allObjectivesComplete;
|
||||
int frameCounter;
|
||||
int currentStatus;
|
||||
int isTrainingMission;
|
||||
int isBossMission;
|
||||
int isBossActive;
|
||||
int isOutpostMission;
|
||||
int isReturnVisit;
|
||||
int missionCompleteTimer;
|
||||
PointF checkpoints[MAX_CHECKPOINTS];
|
||||
int betweenTimer;
|
||||
Quadtree quadtree;
|
||||
Entity entityHead, *entityTail;
|
||||
Particle particleHead, *particleTail;
|
||||
|
|
|
@ -49,6 +49,10 @@ void initAtlasTest(void)
|
|||
|
||||
static void logic(void)
|
||||
{
|
||||
doEntities();
|
||||
|
||||
doParticles();
|
||||
|
||||
if (--timeout <= 0)
|
||||
{
|
||||
trackRandomEntity();
|
||||
|
|
|
@ -32,6 +32,8 @@ extern void loadWorld(char *filename);
|
|||
extern void drawMap(void);
|
||||
extern void drawEntities(void);
|
||||
extern void cameraTrack(Entity *e);
|
||||
extern void doEntities(void);
|
||||
extern void doParticles(void);
|
||||
|
||||
extern App app;
|
||||
extern World world;
|
||||
|
|
|
@ -27,6 +27,19 @@ void initEntities(void)
|
|||
atlasTexture = getTexture("gfx/atlas/atlas.png");
|
||||
}
|
||||
|
||||
void doEntities(void)
|
||||
{
|
||||
for (self = world.entityHead.next ; self != NULL ; self = self->next)
|
||||
{
|
||||
self->tick();
|
||||
|
||||
if (--self->thinkTime <= 0)
|
||||
{
|
||||
self->action();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawEntities(void)
|
||||
{
|
||||
int x, y;
|
||||
|
@ -39,3 +52,45 @@ void drawEntities(void)
|
|||
blitRect(atlasTexture->texture, x, y, self->getCurrentSprite(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void activateEntities(char *names, int activate)
|
||||
{
|
||||
}
|
||||
|
||||
void teleportEntity(Entity *e, float tx, float ty)
|
||||
{
|
||||
}
|
||||
|
||||
void dropCarriedItem(void)
|
||||
{
|
||||
EntityExt *e;
|
||||
Item *i;
|
||||
|
||||
e = (EntityExt*)self;
|
||||
|
||||
if (e->carriedItem != NULL)
|
||||
{
|
||||
i = e->carriedItem;
|
||||
|
||||
i->x = (e->x + e->w / 2) - i->w / 2;
|
||||
i->y = e->y;
|
||||
|
||||
i->dx = i->dy = 0;
|
||||
|
||||
world.entityTail->next = (Entity*)i;
|
||||
world.entityTail = (Entity*)i;
|
||||
world.entityTail->next = NULL;
|
||||
|
||||
e->carriedItem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void teleport(Entity *e, float tx, float ty)
|
||||
{
|
||||
e->tx = tx;
|
||||
e->ty = ty;
|
||||
|
||||
e->flags |= EF_TELEPORTING;
|
||||
|
||||
addTeleportStars(e);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
extern Texture *getTexture(const char *filename);
|
||||
extern void blitRect(SDL_Texture *texture, int x, int y, SDL_Rect *srcRect, int center);
|
||||
extern void addTeleportStars(Entity *e);
|
||||
|
||||
extern Entity *self;
|
||||
extern Camera camera;
|
||||
|
|
|
@ -44,6 +44,45 @@ void initParticles(void)
|
|||
teleportStarSprite = getSprite("TeleportStar");
|
||||
}
|
||||
|
||||
void doParticles(void)
|
||||
{
|
||||
Particle *p, *prev;
|
||||
int camMidX, camMidY;
|
||||
|
||||
camMidX = camera.x + (SCREEN_WIDTH / 2);
|
||||
camMidY = camera.y + (SCREEN_HEIGHT / 2);
|
||||
|
||||
prev = &world.particleHead;
|
||||
|
||||
for (p = world.particleHead.next ; p != NULL ; p = p->next)
|
||||
{
|
||||
animate(p);
|
||||
|
||||
p->x += p->dx;
|
||||
p->y += p->dy;
|
||||
|
||||
p->onScreen = 0;
|
||||
|
||||
if (--p->health <= 0 || (p->destroyAfterAnim && p->spriteTime == -1))
|
||||
{
|
||||
if (p == world.particleTail)
|
||||
{
|
||||
world.particleTail = prev;
|
||||
}
|
||||
|
||||
prev->next = p->next;
|
||||
free(p);
|
||||
p = prev;
|
||||
}
|
||||
else if (getDistance(camMidX, camMidY, p->x, p->y) < SCREEN_WIDTH)
|
||||
{
|
||||
p->onScreen = 1;
|
||||
}
|
||||
|
||||
prev = p;
|
||||
}
|
||||
}
|
||||
|
||||
void addBlood(float x, float y)
|
||||
{
|
||||
Particle *p;
|
||||
|
@ -198,45 +237,6 @@ void addTeleporterEffect(float x, float y)
|
|||
p->spriteFrame = (rand() % 12);
|
||||
}
|
||||
|
||||
void doParticles(void)
|
||||
{
|
||||
Particle *p, *prev;
|
||||
int camMidX, camMidY;
|
||||
|
||||
camMidX = camera.x + (SCREEN_WIDTH / 2);
|
||||
camMidY = camera.y + (SCREEN_HEIGHT / 2);
|
||||
|
||||
prev = &world.particleHead;
|
||||
|
||||
for (p = world.particleHead.next ; p != NULL ; p = p->next)
|
||||
{
|
||||
animate(p);
|
||||
|
||||
p->x += p->dx;
|
||||
p->y += p->dy;
|
||||
|
||||
p->onScreen = 0;
|
||||
|
||||
if (--p->health <= 0 || (p->destroyAfterAnim && p->spriteTime == -1))
|
||||
{
|
||||
if (p == world.particleTail)
|
||||
{
|
||||
world.particleTail = prev;
|
||||
}
|
||||
|
||||
prev->next = p->next;
|
||||
free(p);
|
||||
p = prev;
|
||||
}
|
||||
else if (getDistance(camMidX, camMidY, p->x, p->y) < SCREEN_WIDTH)
|
||||
{
|
||||
p->onScreen = 1;
|
||||
}
|
||||
|
||||
prev = p;
|
||||
}
|
||||
}
|
||||
|
||||
static void animate(Particle *p)
|
||||
{
|
||||
|
||||
|
|
|
@ -19,7 +19,3 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
|
||||
#include "player.h"
|
||||
|
||||
void stunBob(void)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ void loadWorld(char *filename)
|
|||
world.entityTail = &world.entityHead;
|
||||
world.triggerTail = &world.triggerHead;
|
||||
world.objectiveTail = &world.objectiveHead;
|
||||
world.particleTail = &world.particleHead;
|
||||
|
||||
text = readFile(filename);
|
||||
|
||||
|
|
Loading…
Reference in New Issue