Added world code.

This commit is contained in:
Steve 2018-02-02 19:10:12 +00:00
parent bac35a3bab
commit 3c7b3b5170
11 changed files with 521 additions and 8 deletions

View File

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

View File

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

View File

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

25
src/game/ending.c Normal file
View File

@ -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)
{
}

21
src/game/ending.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

@ -32,7 +32,7 @@ void initHud(void)
messageType = MSG_STANDARD;
}
void doLogic(void)
void doHud(void)
{
messageTime--;

View File

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

View File

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