Added world code.
This commit is contained in:
parent
bac35a3bab
commit
3c7b3b5170
|
@ -33,7 +33,7 @@ OBJS += atlas.o atlasTest.o aquaBlob.o
|
|||
OBJS += battery.o blaze.o bob.o boss.o blobBoss.o
|
||||
OBJS += camera.o cannon.o cardReader.o cell.o cherry.o combat.o consumable.o
|
||||
OBJS += debris.o destructable.o door.o draw.o
|
||||
OBJS += effects.o entities.o entity.o entityFactory.o exit.o explosions.o eyeDroid.o eyeDroidCommander.o evilBlob.o
|
||||
OBJS += effects.o ending.o entities.o entity.o entityFactory.o exit.o explosions.o eyeDroid.o eyeDroidCommander.o evilBlob.o
|
||||
OBJS += fleshChunk.o frost.o
|
||||
OBJS += game.o grenade.o
|
||||
OBJS += heart.o horizontalDoor.o horizontalLaserTrap.o hub.o hud.o
|
||||
|
|
|
@ -208,8 +208,13 @@ enum
|
|||
|
||||
enum
|
||||
{
|
||||
WS_START,
|
||||
WS_IN_PROGRESS,
|
||||
WS_PAUSED,
|
||||
WS_GAME_COMPLETE,
|
||||
WS_OBSERVING,
|
||||
WS_COMPLETE,
|
||||
WS_MISSION_COMPLETE,
|
||||
WS_GAME_OVER
|
||||
};
|
||||
|
||||
|
|
|
@ -631,6 +631,10 @@ int numCarriedItems(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void dropCarriedItems(void)
|
||||
{
|
||||
}
|
||||
|
||||
static SDL_Rect *getCurrentSprite(void)
|
||||
{
|
||||
if (world.bob->alive == ALIVE_ALIVE && world.bob->stunTimer <= 0)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright (C) 2018 Parallel Realities
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "ending.h"
|
||||
|
||||
void initEnding(void)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
Copyright (C) 2018 Parallel Realities
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "../common.h"
|
|
@ -58,6 +58,7 @@ typedef struct {
|
|||
int cheatLevels;
|
||||
int cheatReload;
|
||||
int cheatBlind;
|
||||
int cheatNoEnemies;
|
||||
int fps;
|
||||
} Dev;
|
||||
|
||||
|
@ -129,7 +130,9 @@ struct Entity {
|
|||
int isSolid;
|
||||
int isStatic;
|
||||
int isOnGround;
|
||||
int isOnScreen;
|
||||
int isMissionTarget;
|
||||
int observationTime;
|
||||
SDL_Rect bounds;
|
||||
unsigned long flags;
|
||||
void (*init)(void);
|
||||
|
@ -436,9 +439,8 @@ typedef struct {
|
|||
int state;
|
||||
int minEnemySpawnTime, maxEnemySpawnTime;
|
||||
unsigned long entityCounter;
|
||||
Bob *bob;
|
||||
Boss *boss;
|
||||
Map map;
|
||||
int entityChaseTimer;
|
||||
int showingInfoMessage;
|
||||
int allObjectivesComplete;
|
||||
int frameCounter;
|
||||
int currentStatus;
|
||||
|
@ -448,8 +450,18 @@ typedef struct {
|
|||
int isOutpostMission;
|
||||
int isReturnVisit;
|
||||
int missionCompleteTimer;
|
||||
int observationTimer;
|
||||
int gameOverTimer;
|
||||
int betweenTimer;
|
||||
int mapAnimTimer;
|
||||
int enemySpawnTimer;
|
||||
int helperItemTimer;
|
||||
int spawnInterval;
|
||||
int numToSpawn;
|
||||
Bob *bob;
|
||||
Boss *boss;
|
||||
Entity *entityToTrack;
|
||||
Map map;
|
||||
Quadtree quadtree;
|
||||
Entity entityHead, *entityTail;
|
||||
Particle particleHead, *particleTail;
|
||||
|
|
|
@ -96,7 +96,7 @@ Widget *getWidgetAt(int x, int y)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void hideAll(void)
|
||||
void hideAllWidgets(void)
|
||||
{
|
||||
Widget *w;
|
||||
|
||||
|
@ -112,7 +112,7 @@ void showWidgetGroup(char *group)
|
|||
{
|
||||
Widget *w;
|
||||
|
||||
hideAll();
|
||||
hideAllWidgets();
|
||||
|
||||
for (w = widgetHead.next ; w != NULL ; w = w->next)
|
||||
{
|
||||
|
|
|
@ -114,3 +114,23 @@ Entity *findEntity(char *name)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Entity *getRandomObjectiveEntity(void)
|
||||
{
|
||||
Entity *rtn, *e;
|
||||
|
||||
rtn = (Entity*)world.bob;
|
||||
|
||||
for (e = world.entityHead.next ; e != NULL ; e = e->next)
|
||||
{
|
||||
if (e->isMissionTarget)
|
||||
{
|
||||
if (rand() % 4 == 0)
|
||||
{
|
||||
rtn = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ void initHud(void)
|
|||
messageType = MSG_STANDARD;
|
||||
}
|
||||
|
||||
void doLogic(void)
|
||||
void doHud(void)
|
||||
{
|
||||
messageTime--;
|
||||
|
||||
|
|
|
@ -20,21 +20,418 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#include "world.h"
|
||||
|
||||
static void doWorldStart(void);
|
||||
static void doWorldInProgress(void);
|
||||
static void doWorldObserving(void);
|
||||
static void doWorldPaused(void);
|
||||
static void doWorldComplete(void);
|
||||
static void doGameComplete(void);
|
||||
static void doGameOver(void);
|
||||
static void doCommon(void);
|
||||
static void addHelperItems(void);
|
||||
static void spawnEnemies(void);
|
||||
static int canAdd(Unit *u, int mx, int my);
|
||||
void startMission(void);
|
||||
|
||||
static Texture *background;
|
||||
static Entity* entitiesToObserve[MAX_ENTS_TO_OBSERVE];
|
||||
|
||||
void initWorld(void)
|
||||
{
|
||||
background = getTexture(world.background);
|
||||
|
||||
initObjectives();
|
||||
|
||||
world.enemySpawnTimer = (FPS * rrnd(world.minEnemySpawnTime, world.maxEnemySpawnTime));
|
||||
|
||||
world.state = WS_START;
|
||||
|
||||
if (world.isBossMission)
|
||||
{
|
||||
startMission();
|
||||
hideAllWidgets();
|
||||
world.betweenTimer = 0;
|
||||
}
|
||||
|
||||
if (!game.isResumingMission)
|
||||
{
|
||||
game.missionsPlayed++;
|
||||
}
|
||||
}
|
||||
|
||||
void doWorld(void)
|
||||
{
|
||||
if (world.betweenTimer == 0)
|
||||
{
|
||||
switch (world.state)
|
||||
{
|
||||
case WS_START:
|
||||
doWorldStart();
|
||||
break;
|
||||
case WS_IN_PROGRESS:
|
||||
doWorldInProgress();
|
||||
break;
|
||||
case WS_OBSERVING:
|
||||
doWorldObserving();
|
||||
break;
|
||||
case WS_PAUSED:
|
||||
doWorldPaused();
|
||||
break;
|
||||
case WS_COMPLETE:
|
||||
doWorldComplete();
|
||||
break;
|
||||
case WS_GAME_OVER:
|
||||
doGameOver();
|
||||
break;
|
||||
case WS_GAME_COMPLETE:
|
||||
doGameComplete();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (--world.mapAnimTimer < 0)
|
||||
{
|
||||
world.mapAnimTimer = 4;
|
||||
}
|
||||
}
|
||||
|
||||
void startMission(void)
|
||||
{
|
||||
world.state = WS_IN_PROGRESS;
|
||||
world.betweenTimer = FPS / 2;
|
||||
resetAtCheckpoint();
|
||||
world.entityToTrack = (Entity*)world.bob;
|
||||
}
|
||||
|
||||
static void doWorldStart(void)
|
||||
{
|
||||
if (world.entityToTrack == NULL)
|
||||
{
|
||||
world.entityToTrack = getRandomObjectiveEntity();
|
||||
|
||||
cameraTrack(world.entityToTrack);
|
||||
}
|
||||
|
||||
world.entityChaseTimer = MAX(world.entityChaseTimer - 1, 0);
|
||||
|
||||
doCommon();
|
||||
}
|
||||
|
||||
static void doWorldInProgress(void)
|
||||
{
|
||||
if (!world.showingInfoMessage)
|
||||
{
|
||||
doBob();
|
||||
|
||||
doCommon();
|
||||
|
||||
doLocationTriggers();
|
||||
|
||||
if (world.allObjectivesComplete && world.state != WS_COMPLETE)
|
||||
{
|
||||
world.bob->flags |= EF_IMMUNE;
|
||||
|
||||
if (strcmp(world.id, "teeka") == 0)
|
||||
{
|
||||
world.state = WS_GAME_COMPLETE;
|
||||
}
|
||||
else
|
||||
{
|
||||
world.state = WS_COMPLETE;
|
||||
}
|
||||
|
||||
world.missionCompleteTimer = FPS * 3;
|
||||
|
||||
stopMusic();
|
||||
}
|
||||
}
|
||||
|
||||
if (world.observationTimer > 0)
|
||||
{
|
||||
world.observationTimer--;
|
||||
|
||||
if (world.observationTimer == FPS * 1.5)
|
||||
{
|
||||
world.entityToTrack = entitiesToObserve[0];
|
||||
|
||||
world.state = WS_OBSERVING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doWorldObserving(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
world.observationTimer--;
|
||||
|
||||
if (world.observationTimer == 0)
|
||||
{
|
||||
for (i = 0 ; i < MAX_ENTS_TO_OBSERVE ; i++)
|
||||
{
|
||||
entitiesToObserve[i]->observationTime = SDL_GetTicks() + 5000;
|
||||
}
|
||||
|
||||
memset(entitiesToObserve, 0, sizeof(Entity*) * MAX_ENTS_TO_OBSERVE);
|
||||
world.entityToTrack = (Entity*)world.bob;
|
||||
world.state = WS_IN_PROGRESS;
|
||||
}
|
||||
}
|
||||
|
||||
static void doWorldPaused(void)
|
||||
{
|
||||
animateSprites();
|
||||
}
|
||||
|
||||
static void doWorldComplete(void)
|
||||
{
|
||||
world.missionCompleteTimer--;
|
||||
|
||||
if (world.missionCompleteTimer <= 0)
|
||||
{
|
||||
|
||||
}
|
||||
else if (world.missionCompleteTimer == FPS * 1.5)
|
||||
{
|
||||
dropCarriedItems();
|
||||
world.bob->flags |= EF_GONE;
|
||||
addTeleportStars((Entity*)world.bob);
|
||||
playSound(SND_TELEPORT, CH_BOB);
|
||||
}
|
||||
else
|
||||
{
|
||||
doBob();
|
||||
}
|
||||
|
||||
doCommon();
|
||||
}
|
||||
|
||||
static void doGameComplete(void)
|
||||
{
|
||||
world.missionCompleteTimer--;
|
||||
|
||||
if (world.missionCompleteTimer <= 0)
|
||||
{
|
||||
initEnding();
|
||||
}
|
||||
else
|
||||
{
|
||||
doBob();
|
||||
}
|
||||
|
||||
doCommon();
|
||||
}
|
||||
|
||||
static void doGameOver(void)
|
||||
{
|
||||
world.gameOverTimer--;
|
||||
|
||||
doCommon();
|
||||
|
||||
if (world.gameOverTimer <= -(FPS * 5))
|
||||
{
|
||||
initTitle();
|
||||
}
|
||||
}
|
||||
|
||||
static void doCommon(void)
|
||||
{
|
||||
animateSprites();
|
||||
|
||||
world.frameCounter++;
|
||||
world.frameCounter %= 4096;
|
||||
|
||||
doHud();
|
||||
|
||||
if (world.minEnemySpawnTime > 0 && !dev.cheatNoEnemies)
|
||||
{
|
||||
spawnEnemies();
|
||||
}
|
||||
|
||||
if (world.isBossMission && --world.helperItemTimer <= 0)
|
||||
{
|
||||
addHelperItems();
|
||||
}
|
||||
|
||||
doEntities();
|
||||
|
||||
doParticles();
|
||||
}
|
||||
|
||||
static void addHelperItems(void)
|
||||
{
|
||||
int x, y, w, h;
|
||||
|
||||
w = world.map.bounds.w - world.map.bounds.x;
|
||||
h = world.map.bounds.h - world.map.bounds.y;
|
||||
|
||||
x = world.map.bounds.x + (rand() % w);
|
||||
y = world.map.bounds.y + 1;
|
||||
|
||||
if (world.map.data[x / MAP_TILE_SIZE][y / MAP_TILE_SIZE] == 0)
|
||||
{
|
||||
dropRandomCherry(x, y);
|
||||
}
|
||||
|
||||
x = world.map.bounds.x + (rand() % w);
|
||||
y = world.map.bounds.y + (rand() % h);
|
||||
|
||||
if (world.map.data[x / MAP_TILE_SIZE][y / MAP_TILE_SIZE] == 0)
|
||||
{
|
||||
addRandomWeapon(x, y);
|
||||
}
|
||||
|
||||
world.helperItemTimer = FPS * rrnd(3, 5);
|
||||
}
|
||||
|
||||
static void spawnEnemies(void)
|
||||
{
|
||||
char name[MAX_NAME_LENGTH];
|
||||
int r, x, y;
|
||||
Unit *u;
|
||||
|
||||
if (world.numToSpawn == 0)
|
||||
{
|
||||
if (--world.enemySpawnTimer <= 0)
|
||||
{
|
||||
world.numToSpawn = 3 + (rand() % 3);
|
||||
world.spawnInterval = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (--world.spawnInterval <= 0)
|
||||
{
|
||||
r = (rand() % world.numEnemyTypes);
|
||||
|
||||
x = world.bob->x;
|
||||
x += ((randF() - randF()) * 5) * MAP_TILE_SIZE;
|
||||
|
||||
y = world.bob->y;
|
||||
y += ((randF() - randF()) * 5) * MAP_TILE_SIZE;
|
||||
|
||||
if (x >= world.map.bounds.x && y >= world.map.bounds.y && x < world.map.bounds.w + SCREEN_WIDTH - 64 && y < world.map.bounds.h + SCREEN_HEIGHT - 64)
|
||||
{
|
||||
sprintf(name, "%s%s", world.enemyTypes[r], (rand() % 2 ? "Blob" : "Droid"));
|
||||
|
||||
u = (Unit*) createEntity(name);
|
||||
|
||||
u->animate();
|
||||
u->setSize();
|
||||
|
||||
x /= MAP_TILE_SIZE;
|
||||
y /= MAP_TILE_SIZE;
|
||||
|
||||
if (canAdd(u, x, y))
|
||||
{
|
||||
u->x = x * MAP_TILE_SIZE;
|
||||
u->y = y * MAP_TILE_SIZE;
|
||||
|
||||
u->spawnedIn = 1;
|
||||
u->canCarryItem = 0;
|
||||
addTeleportStars((Entity*)u);
|
||||
playSound(SND_APPEAR, CH_ANY);
|
||||
}
|
||||
}
|
||||
|
||||
world.spawnInterval = rrnd(FPS / 4, FPS / 2);
|
||||
|
||||
if (--world.numToSpawn <= 0)
|
||||
{
|
||||
world.enemySpawnTimer = (FPS * rrnd(world.minEnemySpawnTime, world.maxEnemySpawnTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int canAdd(Unit *u, int mx, int my)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (isSolid(mx, my))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isLiquid(mx, my) && (!(u->flags & EF_WATER_BREATHING)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(u->flags & EF_WEIGHTLESS))
|
||||
{
|
||||
for (i = 0 ; i < 10 ; i++)
|
||||
{
|
||||
if (isLiquid(mx, my + i))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isWalkable(mx, my + i))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* long drop */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int getMissionStatus(void)
|
||||
{
|
||||
Objective *o;
|
||||
Entity *e;
|
||||
int status;
|
||||
|
||||
status = MS_COMPLETE;
|
||||
|
||||
for (o = world.objectiveHead.next ; o != NULL ; o = o->next)
|
||||
{
|
||||
if (o->required && o->currentValue < o->targetValue)
|
||||
{
|
||||
return MS_INCOMPLETE;
|
||||
}
|
||||
|
||||
if (o->currentValue < o->totalValue)
|
||||
{
|
||||
status = MS_PARTIAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (status == MS_COMPLETE)
|
||||
{
|
||||
for (e = world.entityHead.next ; e != NULL ; e = e->next)
|
||||
{
|
||||
if (e->type == ET_HEART_CELL)
|
||||
{
|
||||
return MS_MISSING_HEART_CELL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void observeActivation(Entity *e)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (e->observationTime < SDL_GetTicks() && !e->isOnScreen)
|
||||
{
|
||||
for (i = 0 ; i < MAX_ENTS_TO_OBSERVE ; i++)
|
||||
{
|
||||
if (entitiesToObserve[i] == NULL)
|
||||
{
|
||||
entitiesToObserve[i] = e;
|
||||
world.observationTimer = FPS * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "Can't observe entity - out of array space");
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,35 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#include "../common.h"
|
||||
|
||||
extern Texture *getTexture(const char *filename);
|
||||
#define MAX_ENTS_TO_OBSERVE 12
|
||||
|
||||
extern Texture *getTexture(const char *filename);
|
||||
extern void initObjectives(void);
|
||||
extern Entity *getRandomObjectiveEntity(void);
|
||||
extern void doBob(void);
|
||||
extern void doLocationTriggers(void);
|
||||
extern void dropCarriedItems(void);
|
||||
extern void playSound(int snd, int ch);
|
||||
extern void initEnding(void);
|
||||
extern void initTitle(void);
|
||||
extern int rrnd(int low, int high);
|
||||
extern void hideAllWidgets(void);
|
||||
extern void resetAtCheckpoint(void);
|
||||
extern void cameraTrack(Entity *e);
|
||||
extern void stopMusic(void);
|
||||
extern void animateSprites(void);
|
||||
extern void addTeleportStars(Entity *e);
|
||||
extern double randF(void);
|
||||
extern int isSolid(int x, int y);
|
||||
extern int isLiquid(int x, int y);
|
||||
extern int isWalkable(int x, int y);
|
||||
extern void doEntities(void);
|
||||
extern void doParticles(void);
|
||||
extern void doHud(void);
|
||||
extern Entity *createEntity(char *typeStr);
|
||||
extern void dropRandomCherry(int x, int y);
|
||||
extern void addRandomWeapon(int x, int y);
|
||||
|
||||
extern Dev dev;
|
||||
extern Game game;
|
||||
extern World world;
|
||||
|
|
Loading…
Reference in New Issue