Draw tiles for loading screen #325

This commit is contained in:
Cong
2022-01-30 12:10:03 +11:00
parent 68dbefad00
commit d13c37a260
35 changed files with 382 additions and 222 deletions

View File

@@ -26,6 +26,7 @@ set(CDOGS_SDL_SOURCES
game.c
game_loop.c
hiscores.c
loading_screens.c
mainmenu.c
menu.c
menu_utils.c
@@ -45,6 +46,7 @@ set(CDOGS_SDL_HEADERS
game.h
game_loop.h
hiscores.h
loading_screens.h
mainmenu.h
menu.h
menu_utils.h

View File

@@ -22,7 +22,7 @@
This file incorporates work covered by the following copyright and
permission notice:
Copyright (c) 2013-2017, 2019-2021 Cong Xu
Copyright (c) 2013-2017, 2019-2022 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -87,6 +87,7 @@
#include "briefing_screens.h"
#include "command_line.h"
#include "credits.h"
#include "loading_screens.h"
#include "mainmenu.h"
#include "prep.h"
@@ -182,20 +183,21 @@ int main(int argc, char *argv[])
goto bail;
}
FontLoadFromJSON(&gFont, "graphics/font.png", "graphics/font.json");
DrawGameLoadingScreen(&gGraphicsDevice, "Loading graphics...");
LoadingScreenInit(&gLoadingScreen, &gGraphicsDevice);
LoadingScreenDraw(&gLoadingScreen, "Loading graphics...");
PicManagerLoad(&gPicManager);
GetDataFilePath(buf, "");
LOG(LM_MAIN, LL_INFO, "data dir(%s)", buf);
LOG(LM_MAIN, LL_INFO, "config dir(%s)", GetConfigFilePath(""));
DrawGameLoadingScreen(&gGraphicsDevice, "Loading autosaves...");
LoadingScreenDraw(&gLoadingScreen, "Loading autosaves...");
AutosaveInit(&gAutosave);
#ifndef __EMSCRIPTEN__
AutosaveLoad(&gAutosave, GetConfigFilePath(AUTOSAVE_FILE));
#endif
DrawGameLoadingScreen(&gGraphicsDevice, "Initializing network client...");
LoadingScreenDraw(&gLoadingScreen, "Initializing network client...");
#ifndef __EMSCRIPTEN__
if (enet_initialize() != 0)
{
@@ -206,7 +208,7 @@ int main(int argc, char *argv[])
NetClientInit(&gNetClient);
#endif
DrawGameLoadingScreen(&gGraphicsDevice, "Initializing sound device...");
LoadingScreenDraw(&gLoadingScreen, "Initializing sound device...");
SoundInitialize(&gSoundDevice, "sounds");
if (!gSoundDevice.isInitialised)
{
@@ -216,36 +218,35 @@ int main(int argc, char *argv[])
EventInit(&gEventHandlers);
gEventHandlers.DemoQuitTimer = demoQuitTimer;
NetServerInit(&gNetServer);
TileClassesInit(&gTileClasses);
DrawGameLoadingScreen(&gGraphicsDevice, "Loading character sprites...");
LoadingScreenDraw(&gLoadingScreen, "Loading character sprites...");
CharSpriteClassesInit(&gCharSpriteClasses);
DrawGameLoadingScreen(&gGraphicsDevice, "Loading particles...");
LoadingScreenDraw(&gLoadingScreen, "Loading particles...");
ParticleClassesInit(&gParticleClasses, "data/particles.json");
DrawGameLoadingScreen(&gGraphicsDevice, "Loading ammo...");
LoadingScreenDraw(&gLoadingScreen, "Loading ammo...");
AmmoInitialize(&gAmmo, "data/ammo.json");
DrawGameLoadingScreen(&gGraphicsDevice, "Loading bullets and weapons...");
LoadingScreenDraw(&gLoadingScreen, "Loading bullets and weapons...");
BulletAndWeaponInitialize(
&gBulletClasses, &gWeaponClasses, "data/bullets.json",
"data/guns.json");
DrawGameLoadingScreen(&gGraphicsDevice, "Loading character classes...");
LoadingScreenDraw(&gLoadingScreen, "Loading character classes...");
CharacterClassesInitialize(
&gCharacterClasses, "data/character_classes.json");
#ifndef __EMSCRIPTEN__
DrawGameLoadingScreen(&gGraphicsDevice, "Loading player templates...");
LoadingScreenDraw(&gLoadingScreen, "Loading player templates...");
PlayerTemplatesLoad(&gPlayerTemplates, &gCharacterClasses);
#endif
DrawGameLoadingScreen(&gGraphicsDevice, "Loading pickups...");
LoadingScreenDraw(&gLoadingScreen, "Loading pickups...");
PickupClassesInit(
&gPickupClasses, "data/pickups.json", &gAmmo, &gWeaponClasses);
DrawGameLoadingScreen(&gGraphicsDevice, "Loading map objects...");
LoadingScreenDraw(&gLoadingScreen, "Loading map objects...");
MapObjectsInit(
&gMapObjects, "data/map_objects.json", &gAmmo, &gWeaponClasses);
CollisionSystemInit(&gCollisionSystem);
CampaignInit(&gCampaign);
PlayerDataInit(&gPlayerDatas);
DrawGameLoadingScreen(&gGraphicsDevice, "Loading main menu...");
LoadingScreenDraw(&gLoadingScreen, "Loading main menu...");
LoopRunner l = LoopRunnerNew(NULL);
LoopRunnerPush(&l, MainMenu(&gGraphicsDevice, &l));
if (connectAddr.host != 0)
@@ -293,6 +294,8 @@ int main(int argc, char *argv[])
LoopRunnerTerminate(&l);
bail:
LoadingScreenReload(&gLoadingScreen);
LoadingScreenDraw(&gLoadingScreen, "Quitting...");
NetServerTerminate(&gNetServer);
PlayerDataTerminate(&gPlayerDatas);
MapObjectsTerminate(&gMapObjects);
@@ -311,7 +314,6 @@ bail:
CollisionSystemTerminate(&gCollisionSystem);
CharSpriteClassesTerminate(&gCharSpriteClasses);
TileClassesTerminate(&gTileClasses);
PicManagerTerminate(&gPicManager);
FontTerminate(&gFont);
GraphicsTerminate(&gGraphicsDevice);
@@ -321,6 +323,7 @@ bail:
SoundTerminate(&gSoundDevice, true);
ConfigDestroy(&gConfig);
LogTerminate();
LoadingScreenTerminate(&gLoadingScreen);
SDLJBN_Quit();
SDL_Quit();

View File

@@ -418,7 +418,10 @@ static void DoBuffer(
{
DrawBufferFix(b);
}
DrawBufferDraw(b, offset, NULL);
DrawBufferArgs args;
memset(&args, 0, sizeof args);
args.HUD = ConfigGetBool(&gConfig, "Graphics.ShowHUD");
DrawBufferDraw(b, offset, &args);
}
void CameraDrawMode(const Camera *camera)

View File

@@ -88,7 +88,6 @@ void CampaignSettingTerminateAll(CampaignSetting *setting)
// Unload previous custom data
SoundClear(gSoundDevice.customSounds);
PicManagerClearCustom(&gPicManager);
TileClassesClearCustom(&gTileClasses);
ParticleClassesClear(&gParticleClasses.CustomClasses);
AmmoClassesClear(&gAmmo.CustomAmmo);
PlayerTemplatesClear(&gPlayerTemplates.CustomClasses);

View File

@@ -149,9 +149,9 @@ struct vec2i MapAddDoorGroup(
char doorClassName[CDOGS_FILENAME_MAX];
const DoorType type = GetDoorType(isHorizontal, i, doorGroupCount);
DoorGetClassName(doorClassName, door, doorKey, type);
const TileClass *doorClass = StrTileClass(doorClassName);
const TileClass *doorClass = StrTileClass(mb->Map->TileClasses, doorClassName);
DoorGetClassName(doorClassName, door, "open", type);
const TileClass *doorClassOpen = StrTileClass(doorClassName);
const TileClass *doorClassOpen = StrTileClass(mb->Map->TileClasses, doorClassName);
const struct vec2i vI = svec2i_add(v, svec2i_scale(dv, (float)i));
Tile *tile = MapGetTile(mb->Map, vI);
tile->Door.Class = doorClass;
@@ -168,6 +168,7 @@ struct vec2i MapAddDoorGroup(
{
// Change the tile below to shadow, cast by this door
tileB->Class = TileClassesGetMaskedTile(
mb->Map->TileClasses,
tileB->Class, tileB->Class->Style, "shadow",
tileB->Class->Mask, tileB->Class->MaskAlt);
}
@@ -177,7 +178,7 @@ struct vec2i MapAddDoorGroup(
{
// special door cavity picture
DoorGetClassName(doorClassName, door, "wall", type);
tile->Door.Class2 = StrTileClass(doorClassName);
tile->Door.Class2 = StrTileClass(mb->Map->TileClasses, doorClassName);
}
}
@@ -493,7 +494,7 @@ static void DoorGetClassName(
TileClassGetName(buf, door, door->Style, type, mask, maskAlt);
}
void DoorAddClass(
TileClasses *c, PicManager *pm, const TileClass *base, const char *key,
map_t c, PicManager *pm, const TileClass *base, const char *key,
const DoorType type)
{
char buf[CDOGS_FILENAME_MAX];

View File

@@ -68,7 +68,7 @@ struct vec2i MapAddDoorGroup(
MapBuilder *mb, const struct vec2i v, const int keyFlags);
void DoorAddClass(
TileClasses *c, PicManager *pm, const TileClass *base, const char *key,
map_t c, PicManager *pm, const TileClass *base, const char *key,
const DoorType type);
// Legacy door style int to str

View File

@@ -170,9 +170,9 @@ static void DrawChatters(
DrawBuffer *b, const struct vec2i offset, const Tile *t,
const struct vec2i pos, const bool useFog);
static void DrawExtra(
DrawBuffer *b, struct vec2i offset, GrafxDrawExtra *extra);
DrawBuffer *b, struct vec2i offset, const DrawBufferArgs *args);
void DrawBufferDraw(DrawBuffer *b, struct vec2i offset, GrafxDrawExtra *extra)
void DrawBufferDraw(DrawBuffer *b, struct vec2i offset, const DrawBufferArgs *args)
{
// First draw the floor tiles (which do not obstruct anything)
DrawTiles(b, offset, DrawFloor);
@@ -182,7 +182,7 @@ void DrawBufferDraw(DrawBuffer *b, struct vec2i offset, GrafxDrawExtra *extra)
DrawTiles(b, offset, DrawWallsAndThings);
// Draw things that are above everything
DrawTiles(b, offset, DrawThingsAbove);
if (ConfigGetBool(&gConfig, "Graphics.ShowHUD"))
if (args->HUD)
{
// Draw objective highlights, for visible and always-visible objectives
DrawTiles(b, offset, DrawObjectiveHighlights);
@@ -190,10 +190,7 @@ void DrawBufferDraw(DrawBuffer *b, struct vec2i offset, GrafxDrawExtra *extra)
DrawTiles(b, offset, DrawChatters);
}
// Draw editor-only things
if (extra)
{
DrawExtra(b, offset, extra);
}
DrawExtra(b, offset, args);
}
static void DrawFloor(
@@ -457,17 +454,20 @@ static void DrawGuideImage(
const DrawBuffer *b, const Pic *guideImage, const uint8_t alpha);
static void DrawObjectNames(DrawBuffer *b, const struct vec2i offset);
static void DrawExtra(
DrawBuffer *b, struct vec2i offset, GrafxDrawExtra *extra)
DrawBuffer *b, struct vec2i offset, const DrawBufferArgs *args)
{
// Draw guide image
if (!PicIsNone(extra->guideImage) && extra->guideImageAlpha > 0)
if (args->GuideImage && !PicIsNone(args->GuideImage) && args->GuideImageAlpha > 0)
{
DrawGuideImage(b, extra->guideImage, extra->guideImageAlpha);
DrawGuideImage(b, args->GuideImage, args->GuideImageAlpha);
}
if (args->Editor)
{
// Draw pickups, in case they are obscured by walls
DrawPickups(b, &gMap, offset);
DrawEditorTiles(b, &gMap, offset);
DrawObjectNames(b, offset);
}
// Draw pickups, in case they are obscured by walls
DrawPickups(b, &gMap, offset);
DrawEditorTiles(b, &gMap, offset);
DrawObjectNames(b, offset);
}
static void DrawPickups(

View File

@@ -48,10 +48,9 @@
*/
#pragma once
#include "draw/draw_buffer.h"
#include "gamedata.h"
#include "grafx_bg.h"
#define WALL_OFFSET_Y (-12)
void DrawBufferDraw(DrawBuffer *b, struct vec2i offset, GrafxDrawExtra *extra);
void DrawBufferDraw(DrawBuffer *b, struct vec2i offset, const DrawBufferArgs *args);

View File

@@ -22,7 +22,7 @@
This file incorporates work covered by the following copyright and
permission notice:
Copyright (c) 2013-2014, 2018-2019 Cong Xu
Copyright (c) 2013-2014, 2018-2019, 2022 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -58,12 +58,7 @@
void DrawBufferInit(DrawBuffer *b, struct vec2i size, GraphicsDevice *g)
{
b->OrigSize = size;
CArrayInit(&b->tiles, sizeof(Tile *));
for (int i = 0; i < size.x * size.y; i++)
{
const Tile *t = NULL;
CArrayPushBack(&b->tiles, &t);
}
CArrayInitFillZero(&b->tiles, sizeof(Tile *), size.x * size.y);
b->g = g;
CArrayInit(&b->displaylist, sizeof(const Thing *));
CArrayReserve(&b->displaylist, 32);

View File

@@ -44,27 +44,27 @@
static void DrawBackgroundWithRenderer(
GraphicsDevice *g, WindowContext *wc, SDL_Texture *target,
SDL_Texture *src, DrawBuffer *buffer, const HSV tint,
const struct vec2 pos, GrafxDrawExtra *extra);
const struct vec2 pos, const DrawBufferArgs *args);
void GrafxDrawBackground(
GraphicsDevice *g, DrawBuffer *buffer, const HSV tint,
const struct vec2 pos, GrafxDrawExtra *extra)
const struct vec2 pos, const DrawBufferArgs *args)
{
DrawBackgroundWithRenderer(
g, &g->gameWindow, g->bkgTgt, g->bkg, buffer, tint, pos, extra);
g, &g->gameWindow, g->bkgTgt, g->bkg, buffer, tint, pos, args);
if (g->cachedConfig.SecondWindow)
{
DrawBackgroundWithRenderer(
g, &g->secondWindow, g->bkgTgt2, g->bkg2, buffer, tint, pos,
extra);
args);
}
}
static void DrawBackground(
GraphicsDevice *g, SDL_Texture *t, DrawBuffer *buffer, Map *map,
const struct vec2 pos, GrafxDrawExtra *extra);
const struct vec2 pos, const DrawBufferArgs *args);
static void DrawBackgroundWithRenderer(
GraphicsDevice *g, WindowContext *wc, SDL_Texture *target,
SDL_Texture *src, DrawBuffer *buffer, const HSV tint,
const struct vec2 pos, GrafxDrawExtra *extra)
const struct vec2 pos, const DrawBufferArgs *args)
{
SDL_RendererInfo ri;
if (SDL_GetRendererInfo(wc->renderer, &ri) != 0)
@@ -84,7 +84,7 @@ static void DrawBackgroundWithRenderer(
LOG(LM_GFX, LL_ERROR, "cannot set render target: %s", SDL_GetError());
}
wc->bkgMask = ColorTint(colorWhite, tint);
DrawBackground(g, src, buffer, &gMap, pos, extra);
DrawBackground(g, src, buffer, &gMap, pos, args);
if (SDL_SetRenderTarget(wc->renderer, NULL) != 0)
{
LOG(LM_GFX, LL_ERROR, "cannot set render target: %s", SDL_GetError());
@@ -92,11 +92,11 @@ static void DrawBackgroundWithRenderer(
}
static void DrawBackground(
GraphicsDevice *g, SDL_Texture *t, DrawBuffer *buffer, Map *map,
const struct vec2 pos, GrafxDrawExtra *extra)
const struct vec2 pos, const DrawBufferArgs *args)
{
BlitClearBuf(g);
DrawBufferSetFromMap(buffer, map, pos, X_TILES);
DrawBufferDraw(buffer, svec2i_zero(), extra);
DrawBufferDraw(buffer, svec2i_zero(), args);
BlitUpdateFromBuf(g, t);
BlitClearBuf(g);
}
@@ -107,18 +107,20 @@ void GrafxRedrawBackground(GraphicsDevice *g, const struct vec2 pos)
DrawBuffer buffer;
DrawBufferInit(&buffer, svec2i(X_TILES, Y_TILES), g);
const HSV tint = {rand() * 360.0 / RAND_MAX, rand() * 1.0 / RAND_MAX, 0.5};
GrafxDrawBackground(g, &buffer, tint, pos, NULL);
DrawBufferArgs args;
memset(&args, 0, sizeof args);
GrafxDrawBackground(g, &buffer, tint, pos, &args);
DrawBufferTerminate(&buffer);
}
void GrafxMakeBackground(
GraphicsDevice *device, DrawBuffer *buffer, Campaign *co,
struct MissionOptions *mo, Map *map, HSV tint, const bool isEditor,
struct vec2 pos, GrafxDrawExtra *extra)
struct vec2 pos, const DrawBufferArgs *args)
{
CampaignAndMissionSetup(co, mo);
GameEventsInit(&gGameEvents);
MapBuild(map, mo->missionData, co, mo->index);
MapBuild(map, mo->missionData, true, mo->index, GAME_MODE_NORMAL, &co->Setting.characters);
InitializeBadGuys();
CreateEnemies();
MapMarkAllAsVisited(map);
@@ -135,6 +137,6 @@ void GrafxMakeBackground(
}
// Process the events that place dynamic objects
HandleGameEvents(&gGameEvents, NULL, NULL, NULL, NULL);
GrafxDrawBackground(device, buffer, tint, pos, extra);
GrafxDrawBackground(device, buffer, tint, pos, args);
GameEventsTerminate(&gGameEvents);
}

View File

@@ -1,7 +1,7 @@
/*
C-Dogs SDL
A port of the legendary (and fun) action/arcade cdogs.
Copyright (c) 2013-2014, 2016-2017, 2020 Cong Xu
Copyright (c) 2013-2014, 2016-2017, 2020, 2022 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -33,15 +33,17 @@
typedef struct
{
const Pic *guideImage;
uint8_t guideImageAlpha;
} GrafxDrawExtra;
bool Editor;
const Pic *GuideImage;
uint8_t GuideImageAlpha;
bool HUD;
} DrawBufferArgs;
void GrafxDrawBackground(
GraphicsDevice *g, DrawBuffer *buffer, const HSV tint,
const struct vec2 pos, GrafxDrawExtra *extra);
const struct vec2 pos, const DrawBufferArgs *args);
void GrafxRedrawBackground(GraphicsDevice *g, const struct vec2 pos);
void GrafxMakeBackground(
GraphicsDevice *device, DrawBuffer *buffer, Campaign *co,
struct MissionOptions *mo, Map *map, HSV tint, const bool isEditor,
struct vec2 pos, GrafxDrawExtra *extra);
struct vec2 pos, const DrawBufferArgs *args);

View File

@@ -85,9 +85,9 @@ static void HandleGameEvent(
LOG(LM_MAP, LL_DEBUG, "set tile %s/%s/%s pos(%d, %d) x%d",
e.u.TileSet.ClassName, e.u.TileSet.DoorClassName,
e.u.TileSet.DoorClass2Name, pos.x, pos.y, e.u.TileSet.RunLength);
const TileClass *tileClass = StrTileClass(e.u.TileSet.ClassName);
const TileClass *doorClass = StrTileClass(e.u.TileSet.DoorClassName);
const TileClass *doorClass2 = StrTileClass(e.u.TileSet.DoorClass2Name);
const TileClass *tileClass = StrTileClass(gMap.TileClasses, e.u.TileSet.ClassName);
const TileClass *doorClass = StrTileClass(gMap.TileClasses, e.u.TileSet.DoorClassName);
const TileClass *doorClass2 = StrTileClass(gMap.TileClasses, e.u.TileSet.DoorClass2Name);
for (int i = 0; i <= e.u.TileSet.RunLength; i++)
{
Tile *t = MapGetTile(&gMap, pos);

View File

@@ -272,9 +272,9 @@ void MapShowExitArea(Map *map, const int i)
const int bottom = top + exit->R.Size.y;
const TileClass *exitClass = TileClassesGetExit(
&gTileClasses, &gPicManager, gMission.missionData->ExitStyle, false);
map->TileClasses, &gPicManager, gMission.missionData->ExitStyle, false);
const TileClass *exitShadowClass = TileClassesGetExit(
&gTileClasses, &gPicManager, gMission.missionData->ExitStyle, true);
map->TileClasses, &gPicManager, gMission.missionData->ExitStyle, true);
struct vec2i v;
v.y = top;
@@ -478,6 +478,7 @@ void MapTerminate(Map *map)
}
}
CArrayTerminate(&map->Tiles);
TileClassesTerminate(map->TileClasses);
LOSTerminate(&map->LOS);
CArrayTerminate(&map->access);
PathCacheTerminate(&gPathCache);
@@ -489,6 +490,7 @@ void MapInit(Map *map, const struct vec2i size)
// Init map
memset(map, 0, sizeof *map);
map->TileClasses = TileClassesNew();
CArrayInit(&map->Tiles, sizeof(Tile));
map->Size = size;
LOSInit(map);

View File

@@ -97,6 +97,7 @@ typedef struct
typedef struct
{
map_t TileClasses;
CArray Tiles; // of Tile
struct vec2i Size;

View File

@@ -22,7 +22,7 @@
This file incorporates work covered by the following copyright and
permission notice:
Copyright (c) 2013-2014, 2017-2021 Cong Xu
Copyright (c) 2013-2014, 2017-2022 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -69,15 +69,12 @@ static void MapSetupDoors(MapBuilder *mb);
static void MapAddDrains(MapBuilder *mb);
static void MapGenerateRandomExitArea(Map *map, const int mission);
void MapBuild(
Map *m, const Mission *mission, const Campaign *co, const int missionIndex)
Map *m, const Mission *mission, const bool loadDynamic, const int missionIndex, const GameMode mode, const CharacterStore *characters)
{
MapBuilder mb;
MapBuilderInit(&mb, m, mission, co);
MapBuilderInit(&mb, m, mission, mode, characters);
MapInit(mb.Map, mb.mission->Size);
// Re-seed RNG so results are consistent
CampaignSeedRandom(co);
switch (mb.mission->Type)
{
case MAPTYPE_CLASSIC:
@@ -142,14 +139,14 @@ void MapBuild(
}
}
if (!co->IsClient)
if (loadDynamic)
{
MapLoadDynamic(&mb);
ActorsPilotVehicles();
}
MapBuilderTerminate(&mb);
}
void SetupWallTileClasses(PicManager *pm, const TileClass *base)
void SetupWallTileClasses(Map *m, PicManager *pm, const TileClass *base)
{
for (int i = 0; i < WALL_TYPE_COUNT; i++)
{
@@ -157,11 +154,11 @@ void SetupWallTileClasses(PicManager *pm, const TileClass *base)
pm, "wall", base->Style, IntWallType(i), base->Mask, base->MaskAlt,
false);
TileClassesAdd(
&gTileClasses, pm, base, base->Style, IntWallType(i), base->Mask,
m->TileClasses, pm, base, base->Style, IntWallType(i), base->Mask,
base->MaskAlt);
}
}
void SetupFloorTileClasses(PicManager *pm, const TileClass *base)
void SetupFloorTileClasses(Map *m, PicManager *pm, const TileClass *base)
{
for (int i = 0; i < FLOOR_TYPES; i++)
{
@@ -169,11 +166,11 @@ void SetupFloorTileClasses(PicManager *pm, const TileClass *base)
pm, "tile", base->Style, IntTileType(i), base->Mask, base->MaskAlt,
false);
TileClassesAdd(
&gTileClasses, pm, base, base->Style, IntTileType(i), base->Mask,
m->TileClasses, pm, base, base->Style, IntTileType(i), base->Mask,
base->MaskAlt);
}
}
void SetupDoorTileClasses(PicManager *pm, const TileClass *base)
void SetupDoorTileClasses(Map *m, PicManager *pm, const TileClass *base)
{
const char *doorStyles[] = {"yellow", "green", "blue", "red",
"open", "wall", "normal"};
@@ -181,7 +178,7 @@ void SetupDoorTileClasses(PicManager *pm, const TileClass *base)
{
for (DoorType type = DOORTYPE_H; type < DOORTYPE_COUNT; type++)
{
DoorAddClass(&gTileClasses, pm, base, doorStyles[i], type);
DoorAddClass(m->TileClasses, pm, base, doorStyles[i], type);
}
}
}
@@ -233,12 +230,13 @@ static int MapGetAccessFlags(const MapBuilder *mb, const struct vec2i v)
}
void MapBuilderInit(
MapBuilder *mb, Map *m, const Mission *mission, const Campaign *co)
MapBuilder *mb, Map *m, const Mission *mission, const GameMode mode, const CharacterStore *characters)
{
memset(mb, 0, sizeof *mb);
mb->Map = m;
mb->mission = mission;
mb->co = co;
mb->mode = mode;
mb->characters = characters;
const int mapSize = mission->Size.x * mission->Size.y;
CArrayInitFillZero(&mb->access, sizeof(uint16_t), mapSize);
@@ -648,6 +646,7 @@ static void MapSetupTilesAndWalls(MapBuilder *mb)
{
Tile *t = MapGetTile(mb->Map, pos);
t->Class = TileClassesGetMaskedTile(
mb->Map->TileClasses,
t->Class, t->Class->Style, "alt1", t->Class->Mask,
t->Class->MaskAlt);
}
@@ -659,6 +658,7 @@ static void MapSetupTilesAndWalls(MapBuilder *mb)
{
Tile *t = MapGetTile(mb->Map, pos);
t->Class = TileClassesGetMaskedTile(
mb->Map->TileClasses,
t->Class, t->Class->Style, "alt2", t->Class->Mask,
t->Class->MaskAlt);
}
@@ -682,17 +682,20 @@ static void MapSetupTile(MapBuilder *mb, const struct vec2i pos)
if (tc->Type == TILE_CLASS_FLOOR)
{
t->Class = TileClassesGetMaskedTile(
mb->Map->TileClasses,
tc, tc->Style, canSeeTileAbove ? "normal" : "shadow", tc->Mask,
tc->MaskAlt);
}
else if (tc->Type == TILE_CLASS_WALL)
{
t->Class = TileClassesGetMaskedTile(
mb->Map->TileClasses,
tc, tc->Style, MapGetWallPic(mb, pos), tc->Mask, tc->MaskAlt);
}
else if (tc->Type == TILE_CLASS_DOOR)
{
t->Class = TileClassesGetMaskedTile(
mb->Map->TileClasses,
tc, tc->Style, "normal_h", tc->Mask, tc->MaskAlt);
}
else if (tc->Type == TILE_CLASS_NOTHING)
@@ -1500,6 +1503,10 @@ static void MapAddDrains(MapBuilder *mb)
// Randomly add drainage tiles for classic map type;
// For other map types drains are regular map objects
const MapObject *drain = StrMapObject("drain0");
if (drain == NULL)
{
return;
}
for (int i = 0; i < mb->Map->Size.x * mb->Map->Size.y / 45; i++)
{
// Make sure drain tiles aren't next to each other

View File

@@ -22,7 +22,7 @@
This file incorporates work covered by the following copyright and
permission notice:
Copyright (c) 2013-2015, 2017-2021 Cong Xu
Copyright (c) 2013-2015, 2017-2022 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -48,7 +48,7 @@
*/
#pragma once
#include "campaigns.h"
#include "game_mode.h"
#include "map.h"
#include "mission.h"
@@ -56,7 +56,8 @@ typedef struct
{
Map *Map;
const Mission *mission;
const Campaign *co;
GameMode mode;
const CharacterStore *characters;
// internal data structures to help build the map
CArray access; // of uint16_t
@@ -65,10 +66,9 @@ typedef struct
} MapBuilder;
void MapBuild(
Map *m, const Mission *mission, const Campaign *co,
const int missionIndex);
Map *m, const Mission *mission, const bool loadDynamic, const int missionIndex, const GameMode mode, const CharacterStore *characters);
void MapBuilderInit(
MapBuilder *mb, Map *m, const Mission *mission, const Campaign *co);
MapBuilder *mb, Map *m, const Mission *mission, const GameMode mode, const CharacterStore *characters);
void MapBuilderTerminate(MapBuilder *mb);
void MapLoadDynamic(MapBuilder *mb);
@@ -139,6 +139,6 @@ void MapBuildTile(
uint16_t GenerateAccessMask(int *accessLevel);
void SetupWallTileClasses(PicManager *pm, const TileClass *base);
void SetupFloorTileClasses(PicManager *pm, const TileClass *base);
void SetupDoorTileClasses(PicManager *pm, const TileClass *base);
void SetupWallTileClasses(Map *m, PicManager *pm, const TileClass *base);
void SetupFloorTileClasses(Map *m, PicManager *pm, const TileClass *base);
void SetupDoorTileClasses(Map *m, PicManager *pm, const TileClass *base);

View File

@@ -39,7 +39,7 @@ static void PlaceRooms(MapBuilder *mb);
void MapCaveLoad(MapBuilder *mb)
{
// TODO: multiple tile types
MissionSetupTileClasses(&gPicManager, &mb->mission->u.Cave.TileClasses);
MissionSetupTileClasses(mb->Map, &gPicManager, &mb->mission->u.Cave.TileClasses);
// Randomly set a percentage of the tiles as walls
for (int i = 0; i < mb->mission->u.Cave.FillPercent * mb->Map->Size.x *
@@ -464,7 +464,7 @@ static void PlaceRooms(MapBuilder *mb)
room.Size.x, room.Size.y);
}
// Set keys for rooms
if (AreKeysAllowed(gCampaign.Entry.Mode) &&
if (AreKeysAllowed(mb->mode) &&
mb->mission->u.Cave.DoorsEnabled)
{
while (rooms.size > 0)

View File

@@ -80,7 +80,7 @@ void MapClassicLoad(MapBuilder *mb)
// create inaccessible areas on the map.
// TODO: multiple tile types
MissionSetupTileClasses(&gPicManager, &mb->mission->u.Classic.TileClasses);
MissionSetupTileClasses(mb->Map, &gPicManager, &mb->mission->u.Classic.TileClasses);
MapFillRect(
mb, Rect2iNew(svec2i_zero(), mb->mission->Size),
@@ -119,7 +119,7 @@ void MapClassicLoad(MapBuilder *mb)
}
MapBuildRoom(
mb, v, size, doorMin, doorMax,
AreKeysAllowed(gCampaign.Entry.Mode), isOverlapRoom,
AreKeysAllowed(mb->mode), isOverlapRoom,
overlapAccess);
count++;
}

View File

@@ -141,7 +141,7 @@ void MapInteriorLoad(MapBuilder *mb, const int missionIndex)
{
// TODO: multiple tile types
MissionSetupTileClasses(
&gPicManager, &mb->mission->u.Interior.TileClasses);
mb->Map, &gPicManager, &mb->mission->u.Interior.TileClasses);
CArray areas;
CArrayInit(&areas, sizeof(BSPArea));

View File

@@ -42,7 +42,7 @@ void MapStaticLoad(MapBuilder *mb)
{
// Tile classes
if (hashmap_iterate(
mb->mission->u.Static.TileClasses, AddTileClass, NULL) != MAP_OK)
mb->mission->u.Static.TileClasses, AddTileClass, mb->Map) != MAP_OK)
{
CASSERT(false, "failed to add static tile classes");
}
@@ -59,23 +59,23 @@ void MapStaticLoad(MapBuilder *mb)
}
static int AddTileClass(any_t data, any_t item)
{
UNUSED(data);
Map *m = data;
TileClass *t = item;
// Attach base style to tile class for convenience in editors etc
CSTRDUP(t->StyleType, TileClassBaseStyleType(t->Type));
TileClassesAdd(
&gTileClasses, &gPicManager, t, t->Style, t->StyleType, t->Mask,
m->TileClasses, &gPicManager, t, t->Style, t->StyleType, t->Mask,
t->MaskAlt);
switch (t->Type)
{
case TILE_CLASS_DOOR:
SetupDoorTileClasses(&gPicManager, t);
SetupDoorTileClasses(m, &gPicManager, t);
break;
case TILE_CLASS_WALL:
SetupWallTileClasses(&gPicManager, t);
SetupWallTileClasses(m, &gPicManager, t);
break;
case TILE_CLASS_FLOOR:
SetupFloorTileClasses(&gPicManager, t);
SetupFloorTileClasses(m, &gPicManager, t);
break;
default:
break;
@@ -90,7 +90,7 @@ void MapStaticLoadTile(MapBuilder *mb, const struct vec2i v)
const int idx = v.y * mb->Map->Size.x + v.x;
uint16_t tileAccess =
*(uint16_t *)CArrayGet(&mb->mission->u.Static.Access, idx);
if (!AreKeysAllowed(gCampaign.Entry.Mode))
if (!AreKeysAllowed(mb->mode))
{
tileAccess = 0;
}
@@ -100,7 +100,7 @@ void MapStaticLoadTile(MapBuilder *mb, const struct vec2i v)
MapBuildSetAccess(mb, v, tileAccess);
}
static void AddCharacters(const CArray *characters);
static void AddCharacters(const MapBuilder *mb, const CArray *characters);
static void AddObjectives(MapBuilder *mb, const CArray *objectives);
static void AddKeys(MapBuilder *mb, const CArray *keys);
static void AddPickups(const CArray *pickups);
@@ -115,17 +115,17 @@ void MapStaticLoadDynamic(MapBuilder *mb)
}
CA_FOREACH_END()
if (ModeHasNPCs(gCampaign.Entry.Mode))
if (ModeHasNPCs(mb->mode))
{
AddCharacters(&mb->mission->u.Static.Characters);
AddCharacters(mb, &mb->mission->u.Static.Characters);
}
if (HasObjectives(gCampaign.Entry.Mode))
if (HasObjectives(mb->mode))
{
AddObjectives(mb, &mb->mission->u.Static.Objectives);
}
if (AreKeysAllowed(gCampaign.Entry.Mode))
if (AreKeysAllowed(mb->mode))
{
AddKeys(mb, &mb->mission->u.Static.Keys);
}
@@ -135,17 +135,18 @@ void MapStaticLoadDynamic(MapBuilder *mb)
// Process the events to place dynamic objects
HandleGameEvents(&gGameEvents, NULL, NULL, NULL, NULL);
}
static void AddCharacter(const CharacterPlaces *cps);
static void AddCharacters(const CArray *characters)
static void AddCharacter(const MapBuilder *mb, const CharacterPlaces *cps);
static void AddCharacters(const MapBuilder *mb, const CArray *characters)
{
CA_FOREACH(const CharacterPlaces, cps, *characters)
AddCharacter(cps);
AddCharacter(mb, cps);
CA_FOREACH_END()
}
static void AddCharacter(const CharacterPlaces *cps)
static void AddCharacter(const MapBuilder *mb, const CharacterPlaces *cps)
{
CASSERT(mb->characters != NULL, "cannot add characters");
const Character *c = CArrayGet(
&gCampaign.Setting.characters.OtherChars, cps->Index);
&mb->characters->OtherChars, cps->Index);
CA_FOREACH(const CharacterPlace, cp, cps->Places)
GameEvent e = GameEventNewActorAdd(Vec2CenterOfTile(cp->Pos), c, true);
e.u.ActorAdd.CharId = cps->Index;
@@ -180,9 +181,10 @@ static void AddObjective(MapBuilder *mb, const ObjectivePositions *op)
switch (o->Type)
{
case OBJECTIVE_KILL: {
const int charId = CharacterStoreGetSpecialId(&mb->co->Setting.characters, pi->Index);
CASSERT(mb->characters != NULL, "cannot add kill objective");
const int charId = CharacterStoreGetSpecialId(mb->characters, pi->Index);
const Character *c = CArrayGet(
&gCampaign.Setting.characters.OtherChars, charId);
&mb->characters->OtherChars, charId);
GameEvent e = GameEventNewActorAdd(pos, c, true);
e.u.ActorAdd.CharId = charId;
e.u.ActorAdd.ThingFlags = ObjectiveToThing(op->Index);
@@ -198,10 +200,11 @@ static void AddObjective(MapBuilder *mb, const ObjectivePositions *op)
false);
break;
case OBJECTIVE_RESCUE: {
CASSERT(mb->characters != NULL, "cannot add rescue objective");
const int charId = CharacterStoreGetPrisonerId(
&mb->co->Setting.characters, pi->Index);
mb->characters, pi->Index);
const Character *c = CArrayGet(
&gCampaign.Setting.characters.OtherChars, charId);
&mb->characters->OtherChars, charId);
GameEvent e = GameEventNewActorAdd(pos, c, true);
e.u.ActorAdd.CharId = charId;
e.u.ActorAdd.ThingFlags = ObjectiveToThing(op->Index);

View File

@@ -357,12 +357,12 @@ void SetupMission(Mission *m, struct MissionOptions *mo, int missionIndex)
SetupBadguysForMission(m);
SetupWeapons(&mo->Weapons, &m->Weapons);
}
void MissionSetupTileClasses(PicManager *pm, const MissionTileClasses *mtc)
void MissionSetupTileClasses(Map *m, PicManager *pm, const MissionTileClasses *mtc)
{
SetupWallTileClasses(pm, &mtc->Wall);
SetupFloorTileClasses(pm, &mtc->Floor);
SetupFloorTileClasses(pm, &mtc->Room);
SetupDoorTileClasses(pm, &mtc->Door);
SetupWallTileClasses(m, pm, &mtc->Wall);
SetupFloorTileClasses(m, pm, &mtc->Floor);
SetupFloorTileClasses(m, pm, &mtc->Room);
SetupDoorTileClasses(m, pm, &mtc->Door);
}
void MissionTileClassesInitDefault(MissionTileClasses *mtc)
{

View File

@@ -228,7 +228,7 @@ void MissionTerminate(Mission *m);
MissionTileClasses *MissionGetTileClasses(Mission *m);
void SetupMission(Mission *m, struct MissionOptions *mo, int missionIndex);
void MissionSetupTileClasses(PicManager *pm, const MissionTileClasses *mtc);
void MissionSetupTileClasses(Map *m, PicManager *pm, const MissionTileClasses *mtc);
void MissionTileClassesInitDefault(MissionTileClasses *mtc);
void MissionTileClassesCopy(
MissionTileClasses *dst, const MissionTileClasses *src);

View File

@@ -1,7 +1,7 @@
/*
C-Dogs SDL
A port of the legendary (and fun) action/arcade cdogs.
Copyright (c) 2018-2021 Cong Xu
Copyright (c) 2018-2022 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,6 @@
#include "sys_config.h"
TileClasses gTileClasses;
TileClass gTileFloor = {
"tile", NULL, NULL, NULL, { 255, 255, 255, 255 }, { 255, 255, 255, 255 },
true, false, false, false, TILE_CLASS_FLOOR, NULL,
@@ -80,20 +79,13 @@ TileClassType StrTileClassType(const char *s)
return TILE_CLASS_NOTHING;
}
void TileClassesInit(TileClasses *c)
map_t TileClassesNew(void)
{
c->classes = hashmap_new();
c->customClasses = hashmap_new();
return hashmap_new();
}
void TileClassesClearCustom(TileClasses *c)
void TileClassesTerminate(map_t c)
{
TileClassesTerminate(c);
TileClassesInit(c);
}
void TileClassesTerminate(TileClasses *c)
{
hashmap_destroy(c->classes, TileClassDestroy);
hashmap_destroy(c->customClasses, TileClassDestroy);
hashmap_destroy(c, TileClassDestroy);
}
void TileClassDestroy(any_t data)
{
@@ -167,7 +159,7 @@ void TileClassCopy(TileClass *dst, const TileClass *src)
if (src->StyleType) CSTRDUP(dst->StyleType, TileClassBaseStyleType(src->Type));
if (src->DamageBullet) CSTRDUP(dst->DamageBullet, src->DamageBullet);
}
const TileClass *StrTileClass(const char *name)
const TileClass *StrTileClass(map_t c, const char *name)
{
if (name == NULL || strlen(name) == 0)
{
@@ -175,12 +167,7 @@ const TileClass *StrTileClass(const char *name)
}
LOG(LM_MAIN, LL_TRACE, "get tile class %s", name);
TileClass *t;
int error = hashmap_get(gTileClasses.customClasses, name, (any_t *)&t);
if (error == MAP_OK)
{
return t;
}
error = hashmap_get(gTileClasses.classes, name, (any_t *)&t);
const int error = hashmap_get(c, name, (any_t *)&t);
if (error == MAP_OK)
{
return t;
@@ -256,15 +243,15 @@ void TileClassReloadPic(TileClass *t, PicManager *pm)
}
}
const TileClass *TileClassesGetMaskedTile(
const TileClass *baseClass, const char *style, const char *type,
map_t c, const TileClass *baseClass, const char *style, const char *type,
const color_t mask, const color_t maskAlt)
{
char buf[256];
TileClassGetName(buf, baseClass, style, type, mask, maskAlt);
return StrTileClass(buf);
return StrTileClass(c, buf);
}
TileClass *TileClassesAdd(
TileClasses *c, PicManager *pm, const TileClass *baseClass,
map_t c, PicManager *pm, const TileClass *baseClass,
const char *style, const char *type,
const color_t mask, const color_t maskAlt)
{
@@ -274,7 +261,7 @@ TileClass *TileClassesAdd(
char buf[CDOGS_PATH_MAX];
TileClassGetName(buf, t, style, type, mask, maskAlt);
const int error = hashmap_put(c->customClasses, buf, t);
const int error = hashmap_put(c, buf, t);
if (error != MAP_OK)
{
LOG(LM_MAIN, LL_ERROR, "failed to add tile class %s: %d", buf, error);
@@ -318,12 +305,12 @@ const Pic *TileClassGetPic(const PicManager *pm, const TileClass *tc)
}
const TileClass *TileClassesGetExit(
TileClasses *c, PicManager *pm, const char *style, const bool isShadow)
map_t c, PicManager *pm, const char *style, const bool isShadow)
{
char buf[256];
const char *type = isShadow ? "shadow" : "normal";
TileClassGetName(buf, &gTileExit, style, type, colorWhite, colorWhite);
const TileClass *t = StrTileClass(buf);
const TileClass *t = StrTileClass(c, buf);
if (t != &gTileNothing)
{
return t;

View File

@@ -1,7 +1,7 @@
/*
C-Dogs SDL
A port of the legendary (and fun) action/arcade cdogs.
Copyright (c) 2018-2021 Cong Xu
Copyright (c) 2018-2022 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -72,12 +72,6 @@ typedef struct
char *DamageBullet;
} TileClass;
typedef struct
{
map_t classes; // of TileClass *
map_t customClasses; // of TileClass *
} TileClasses;
extern TileClasses gTileClasses;
extern TileClass gTileFloor;
extern TileClass gTileRoom;
extern TileClass gTileWall;
@@ -85,9 +79,8 @@ extern TileClass gTileNothing;
extern TileClass gTileExit;
extern TileClass gTileDoor;
void TileClassesInit(TileClasses *c);
void TileClassesClearCustom(TileClasses *c);
void TileClassesTerminate(TileClasses *c);
map_t TileClassesNew(void);
void TileClassesTerminate(map_t c);
void TileClassDestroy(any_t data);
void TileClassTerminate(TileClass *tc);
void TileClassLoadJSON(TileClass *tc, json_t *node);
@@ -103,12 +96,12 @@ void TileClassInitDefault(
void TileClassReloadPic(TileClass *t, PicManager *pm);
const char *TileClassBaseStyleType(const TileClassType type);
void TileClassCopy(TileClass *dst, const TileClass *src);
const TileClass *StrTileClass(const char *name);
const TileClass *StrTileClass(map_t c, const char *name);
const TileClass *TileClassesGetMaskedTile(
const TileClass *baseClass, const char *style, const char *type,
map_t c, const TileClass *baseClass, const char *style, const char *type,
const color_t mask, const color_t maskAlt);
TileClass *TileClassesAdd(
TileClasses *c, PicManager *pm, const TileClass *baseClass,
map_t c, PicManager *pm, const TileClass *baseClass,
const char *style, const char *type,
const color_t mask, const color_t maskAlt);
const Pic *TileClassGetPic(const PicManager *pm, const TileClass *tc);
@@ -117,4 +110,4 @@ void TileClassGetName(
const color_t mask, const color_t maskAlt);
void TileClassGetBaseName(char *buf, const TileClass *tc);
const TileClass *TileClassesGetExit(
TileClasses *c, PicManager *pm, const char *style, const bool isShadow);
map_t c, PicManager *pm, const char *style, const bool isShadow);

View File

@@ -151,9 +151,11 @@ static void MakeBackground(const bool changedMission)
ec.camera = Vec2CenterOfTile(focusTile);
}
GrafxDrawExtra extra;
extra.guideImage = &brush.GuideImagePic;
extra.guideImageAlpha = brush.GuideImageAlpha;
DrawBufferArgs args;
memset(&args, 0, sizeof args);
args.Editor = true;
args.GuideImage = &brush.GuideImagePic;
args.GuideImageAlpha = brush.GuideImageAlpha;
DrawBufferTerminate(&sDrawBuffer);
ClearScreen(ec.g);
@@ -190,10 +192,12 @@ static void Display(HandleInputResult result)
MakeBackground(false);
}
GrafxDrawExtra extra;
extra.guideImage = &brush.GuideImagePic;
extra.guideImageAlpha = brush.GuideImageAlpha;
GrafxDrawBackground(ec.g, &sDrawBuffer, tintNone, ec.camera, &extra);
DrawBufferArgs args;
memset(&args, 0, sizeof args);
args.Editor = true;
args.GuideImage = &brush.GuideImagePic;
args.GuideImageAlpha = brush.GuideImageAlpha;
GrafxDrawBackground(ec.g, &sDrawBuffer, tintNone, ec.camera, &args);
BlitClearBuf(ec.g);
// Draw brush highlight tiles
@@ -1259,7 +1263,6 @@ int main(int argc, char *argv[])
gConfig = ConfigLoad(GetConfigFilePath(CONFIG_FILE));
PicManagerInit(&gPicManager);
TileClassesInit(&gTileClasses);
// Hardcode config settings
ConfigGet(&gConfig, "Graphics.ScaleFactor")->u.Int.Value = 2;
ConfigGet(&gConfig, "Graphics.ScaleMode")->u.Enum.Value = SCALE_MODE_NN;

View File

@@ -227,7 +227,7 @@ static void EditorBrushPaintTilesAt(void *data, struct vec2i pos)
EditorBrush *b = paintData->brush;
Mission *m = paintData->mission;
MapBuilder mb;
MapBuilderInit(&mb, &gMap, m, NULL);
MapBuilderInit(&mb, &gMap, m, NULL, GAME_MODE_NORMAL, NULL);
for (v.y = 0; v.y < b->BrushSize; v.y++)
{
for (v.x = 0; v.x < b->BrushSize; v.x++)
@@ -323,7 +323,7 @@ EditorResult EditorBrushStartPainting(EditorBrush *b, Mission *m, int isMain)
data.Fill = MissionFillTile;
data.IsSame = MissionIsTileSame;
PaintFloodFillData pData;
MapBuilderInit(&pData.mb, &gMap, m, NULL);
MapBuilderInit(&pData.mb, &gMap, m, NULL, GAME_MODE_NORMAL, NULL);
pData.m = m;
pData.fromType = tile;
pData.toType = b->PaintType;

View File

@@ -286,7 +286,7 @@ static void MissionDrawExitStyle(
const int idx = PicManagerGetExitStyleIndex(&gPicManager, m->ExitStyle);
DrawStyleArea(
svec2i_add(pos, o->Pos), "Exit",
TileClassesGetExit(&gTileClasses, &gPicManager, m->ExitStyle, false)
TileClassesGetExit(gMap.TileClasses, &gPicManager, m->ExitStyle, false)
->Pic,
idx, (int)gPicManager.exitStyleNames.size, UIObjectIsHighlighted(o));
}
@@ -515,7 +515,8 @@ static EditorResult MissionChangeType(void *data, int d)
memset(&map, 0, sizeof map);
MissionOptionsTerminate(&gMission);
CampaignAndMissionSetup(mct->C, &gMission);
MapBuild(&map, gMission.missionData, mct->C, gMission.index);
CampaignSeedRandom(mct->C);
MapBuild(&map, gMission.missionData, true, gMission.index, GAME_MODE_NORMAL, &mct->C->Setting.characters);
MissionConvertToType(gMission.missionData, &map, mct->Type);
MapTerminate(&map);
return EDITOR_RESULT_CHANGED;

View File

@@ -106,7 +106,7 @@ static int FloorStyleIndex(const char *style);
static int WallStyleIndex(const char *style);
static int DoorStyleIndex(const char *style);
static const TileClass *GetOrAddTileClass(
const TileClass *base, PicManager *pm, const char *style,
map_t c, const TileClass *base, PicManager *pm, const char *style,
const color_t mask, const color_t maskAlt);
static bool Draw(SDL_Window *win, struct nk_context *ctx, void *data);
EditorResult TileBrush(
@@ -150,21 +150,21 @@ EditorResult TileBrush(
CA_FOREACH(const GLuint, texid, data.texIdsFloorStyles)
const char *style = *(char **)CArrayGet(&pm->tileStyleNames, _ca_index);
const TileClass *styleClass = GetOrAddTileClass(
&gTileFloor, pm, style, colorBattleshipGrey, colorOfficeGreen);
gMap.TileClasses, &gTileFloor, pm, style, colorBattleshipGrey, colorOfficeGreen);
LoadTexFromPic(*texid, styleClass->Pic);
CA_FOREACH_END()
TexArrayInit(&data.texIdsWallStyles, pm->wallStyleNames.size);
CA_FOREACH(const GLuint, texid, data.texIdsWallStyles)
const char *style = *(char **)CArrayGet(&pm->wallStyleNames, _ca_index);
const TileClass *styleClass = GetOrAddTileClass(
&gTileWall, pm, style, colorGravel, colorOfficeGreen);
gMap.TileClasses, &gTileWall, pm, style, colorGravel, colorOfficeGreen);
LoadTexFromPic(*texid, styleClass->Pic);
CA_FOREACH_END()
TexArrayInit(&data.texIdsDoorStyles, pm->doorStyleNames.size);
CA_FOREACH(const GLuint, texid, data.texIdsDoorStyles)
const char *style = *(char **)CArrayGet(&pm->doorStyleNames, _ca_index);
const TileClass *styleClass =
GetOrAddTileClass(&gTileDoor, pm, style, colorWhite, colorOfficeGreen);
GetOrAddTileClass(gMap.TileClasses, &gTileDoor, pm, style, colorWhite, colorOfficeGreen);
LoadTexFromPic(*texid, styleClass->Pic);
CA_FOREACH_END()
@@ -568,15 +568,15 @@ static int DoorStyleIndex(const char *style)
}
static const TileClass *GetOrAddTileClass(
const TileClass *base, PicManager *pm, const char *style,
map_t c, const TileClass *base, PicManager *pm, const char *style,
const color_t mask, const color_t maskAlt)
{
const TileClass *styleClass = TileClassesGetMaskedTile(
base, style, TileClassBaseStyleType(base->Type), mask, maskAlt);
c, base, style, TileClassBaseStyleType(base->Type), mask, maskAlt);
if (styleClass == &gTileNothing)
{
styleClass = TileClassesAdd(
&gTileClasses, pm, base, style, TileClassBaseStyleType(base->Type),
c, pm, base, style, TileClassBaseStyleType(base->Type),
mask, maskAlt);
}
return styleClass;

View File

@@ -22,7 +22,7 @@
This file incorporates work covered by the following copyright and
permission notice:
Copyright (c) 2013-2021 Cong Xu
Copyright (c) 2013-2022 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -70,6 +70,7 @@
#include "briefing_screens.h"
#include "hiscores.h"
#include "loading_screens.h"
#include "prep.h"
#include "screens_end.h"
@@ -143,13 +144,14 @@ static void RunGameTerminate(GameLoopData *data)
}
static void RunGameOnEnter(GameLoopData *data)
{
DrawGameLoadingScreen(&gGraphicsDevice, "Starting game...");
LoadingScreenDraw(&gLoadingScreen, "Starting game...");
RunGameData *rData = data->Data;
RunGameReset(rData);
MapBuild(rData->map, rData->m->missionData, rData->co, rData->m->index);
CampaignSeedRandom(rData->co);
MapBuild(rData->map, rData->m->missionData, !rData->co->IsClient, rData->m->index, rData->co->Entry.Mode, &rData->co->Setting.characters);
// Seed random if PVP mode (otherwise players will always spawn in same
// position)
@@ -258,6 +260,8 @@ static void RunGameOnExit(GameLoopData *data)
LOG(LM_MAIN, LL_INFO, "Game finished");
LoadingScreenDraw(&gLoadingScreen, "Debriefing...");
// Flush events
HandleGameEvents(&gGameEvents, NULL, NULL, NULL, NULL);

View File

@@ -177,7 +177,6 @@ void LoopRunnerTerminate(LoopRunner *l)
static void GameLoopOnEnter(GameLoopData *data);
static void GameLoopOnExit(GameLoopData *data);
typedef struct
{
GameLoopResult Result;

128
src/loading_screens.c Normal file
View File

@@ -0,0 +1,128 @@
/*
C-Dogs SDL
A port of the legendary (and fun) action/arcade cdogs.
Copyright (c) 2022 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "loading_screens.h"
#include <cdogs/draw/draw.h>
#include <cdogs/files.h>
#include <cdogs/font.h>
#include <cdogs/map_build.h>
#include <cdogs/pic_manager.h>
#include <cdogs/pics.h>
#include <cdogs/tile_class.h>
LoadingScreen gLoadingScreen;
void LoadingScreenInit(LoadingScreen *l, GraphicsDevice *g)
{
memset(l, 0, sizeof *l);
l->g = g;
}
void LoadingScreenTerminate(LoadingScreen *l)
{
MapTerminate(&l->m);
DrawBufferTerminate(&l->db);
}
static void LazyLoad(LoadingScreen *l)
{
if (l->logo == NULL)
{
l->logo = PicManagerGetPic(&gPicManager, "logo");
}
// Create map large enough to cover the entire screen
const struct vec2i mapSize = svec2i(X_TILES, Y_TILES);
if (gPicManager.tileStyleNames.size > 0 &&
(l->m.Size.x < mapSize.x || l->m.Size.y < mapSize.y))
{
// Map with floors only
Mission m;
MissionInit(&m);
m.Type = MAPTYPE_CLASSIC;
m.Size = mapSize;
TileClassInit(
&m.u.Classic.TileClasses.Floor, &gPicManager, &gTileFloor,
IntFloorStyle(rand() % FLOOR_STYLE_COUNT),
TileClassBaseStyleType(TILE_CLASS_FLOOR),
RangeToColor(rand() % COLORRANGE_COUNT),
RangeToColor(rand() % COLORRANGE_COUNT));
m.u.Classic.ExitEnabled = false;
MapBuild(&l->m, &m, false, 0, GAME_MODE_NORMAL, NULL);
MapMarkAllAsVisited(&l->m);
DrawBufferInit(&l->db, mapSize, l->g);
}
}
static int ReloadTileClass(any_t data, any_t item)
{
PicManager *pm = data;
TileClass *t = item;
TileClassReloadPic(t, pm);
return MAP_OK;
}
void LoadingScreenReload(LoadingScreen *l)
{
if (hashmap_iterate(l->m.TileClasses, ReloadTileClass, &gPicManager) != MAP_OK)
{
CASSERT(false, "failed to reload tile classes");
}
}
void LoadingScreenDraw(LoadingScreen *l, const char *loadingText)
{
WindowContextPreRender(&l->g->gameWindow);
LazyLoad(l);
if (!svec2i_is_zero(l->m.Size))
{
DrawBufferSetFromMap(&l->db, &l->m, Vec2CenterOfTile(svec2i_scale_divide(l->m.Size, 2)), X_TILES);
DrawBufferArgs args;
memset(&args, 0, sizeof args);
DrawBufferDraw(&l->db, svec2i_zero(), &args);
}
if (l->logo)
{
const struct vec2i pos = svec2i(
CENTER_X(svec2i_zero(), l->g->cachedConfig.Res, l->logo->size.x),
CENTER_Y(
svec2i_zero(), svec2i_scale_divide(l->g->cachedConfig.Res, 2),
l->logo->size.y));
PicRender(
l->logo, l->g->gameWindow.renderer, pos, colorWhite, 0, svec2_one(),
SDL_FLIP_NONE, Rect2iZero());
}
FontOpts opts = FontOptsNew();
opts.HAlign = ALIGN_CENTER;
opts.VAlign = ALIGN_CENTER;
opts.Area = svec2i(l->g->cachedConfig.Res.x, l->g->cachedConfig.Res.y / 2);
FontStrOpt(loadingText, svec2i(0, l->g->cachedConfig.Res.y / 2), opts);
WindowContextPostRender(&l->g->gameWindow);
}

49
src/loading_screens.h Normal file
View File

@@ -0,0 +1,49 @@
/*
C-Dogs SDL
A port of the legendary (and fun) action/arcade cdogs.
Copyright (c) 2022 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <cdogs/draw/draw_buffer.h>
#include <cdogs/grafx.h>
#include <cdogs/map.h>
#include <cdogs/pic.h>
typedef struct
{
const Pic *logo;
GraphicsDevice *g;
Map m;
DrawBuffer db;
} LoadingScreen;
extern LoadingScreen gLoadingScreen;
void LoadingScreenInit(LoadingScreen *l, GraphicsDevice *g);
void LoadingScreenTerminate(LoadingScreen *l);
void LoadingScreenReload(LoadingScreen *l);
void LoadingScreenDraw(LoadingScreen *l, const char *loadingText);

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2013-2021 Cong Xu
Copyright (c) 2013-2022 Cong Xu
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -47,6 +47,7 @@
#include "autosave.h"
#include "briefing_screens.h"
#include "game.h"
#include "loading_screens.h"
#include "menu.h"
#include "prep.h"
@@ -100,7 +101,7 @@ static void GenerateLiveBackground(MainMenuData *data)
GameEventsInit(&gGameEvents);
gCampaign.MissionIndex = 0;
MapBuild(&gMap, gMission.missionData, &gCampaign, gMission.index);
MapBuild(&gMap, gMission.missionData, true, gMission.index, GAME_MODE_NORMAL, &gCampaign.Setting.characters);
// Add AI player
GameEvent e = GameEventNew(GAME_EVENT_PLAYER_DATA);
@@ -243,8 +244,10 @@ static void MainMenuDraw(GameLoopData *data)
MenuDraw(&mData->ms);
const struct vec2 pos =
Vec2CenterOfTile(svec2i_scale_divide(gMap.Size, 2));
DrawBufferArgs args;
memset(&args, 0, sizeof args);
GrafxDrawBackground(
mData->graphics, &mData->buffer, mData->bgTint, pos, NULL);
mData->graphics, &mData->buffer, mData->bgTint, pos, &args);
}
static menu_t *MenuCreateStart(
@@ -351,7 +354,8 @@ static menu_t *CreateStartGameMode(
}
static void StartGameMode(menu_t *menu, void *data)
{
DrawGameLoadingScreen(&gGraphicsDevice, "Loading game...");
LoadingScreenReload(&gLoadingScreen);
LoadingScreenDraw(&gLoadingScreen, "Loading game...");
UNUSED(menu);
StartGameModeData *mData = data;
gCampaign.Entry.Mode = mData->GameMode;

View File

@@ -75,36 +75,11 @@
#include "briefing_screens.h"
#include "game.h"
#include "loading_screens.h"
#include "namegen.h"
#include "password.h"
#include "player_select_menus.h"
void DrawGameLoadingScreen(GraphicsDevice *g, const char *loadingText)
{
WindowContextPreRender(&g->gameWindow);
const Pic *logo = PicManagerGetPic(&gPicManager, "logo");
if (logo)
{
const struct vec2i pos = svec2i(
CENTER_X(svec2i_zero(), g->cachedConfig.Res, logo->size.x),
CENTER_Y(
svec2i_zero(), svec2i_scale_divide(g->cachedConfig.Res, 2),
logo->size.y));
PicRender(
logo, g->gameWindow.renderer, pos, colorWhite, 0, svec2_one(),
SDL_FLIP_NONE, Rect2iZero());
}
FontOpts opts = FontOptsNew();
opts.HAlign = ALIGN_CENTER;
opts.VAlign = ALIGN_CENTER;
opts.Area = svec2i(g->cachedConfig.Res.x, g->cachedConfig.Res.y / 2);
FontStrOpt(loadingText, svec2i(0, g->cachedConfig.Res.y / 2), opts);
WindowContextPostRender(&g->gameWindow);
}
typedef struct
{
MenuSystem ms;
@@ -233,7 +208,7 @@ static void NumPlayersTerminate(GameLoopData *data)
static void NumPlayersOnEnter(GameLoopData *data)
{
UNUSED(data);
DrawGameLoadingScreen(&gGraphicsDevice, "Loading...");
LoadingScreenDraw(&gLoadingScreen, "Loading...");
MusicPlayFromChunk(
&gSoundDevice.music, MUSIC_BRIEFING,
&gCampaign.Setting.CustomSongs[MUSIC_BRIEFING]);

View File

@@ -54,8 +54,6 @@
#include "game_loop.h"
void DrawGameLoadingScreen(GraphicsDevice *g, const char *loadingText);
// Wait for the server to send us the current campaign
GameLoopData *ScreenWaitForCampaignDef(void);