Day 29 complete.

This commit is contained in:
2026-04-03 18:05:35 -07:00
parent 457ff9707f
commit cd8f62f530
3 changed files with 209 additions and 43 deletions
+171 -25
View File
@@ -3,6 +3,7 @@
#include "sdl_handmade.h" #include "sdl_handmade.h"
#include <math.h> #include <math.h>
#include <string.h> /* memset */
static void GameOutputSound(game_state *GameState, static void GameOutputSound(game_state *GameState,
game_sound_output_buffer *SoundBuffer, game_sound_output_buffer *SoundBuffer,
@@ -121,35 +122,176 @@ static void RenderRectangle(game_offscreen_buffer *Buffer, S32 MouseX,
} }
} }
static tile_map *GetTileMap(world *World, S32 TileMapX, S32 TileMapY)
{
tile_map *TileMap = NULL;
if((TileMapX >= 0) && (TileMapX < World->TileMapCountX) &&
(TileMapY >= 0) && (TileMapY < World->TileMapCountY))
{
TileMap =
&World->TileMaps[TileMapY*World->TileMapCountX + TileMapX];
}
return TileMap;
}
static U32 GetTileValueUnchecked(tile_map *TileMap, S32 TileX, S32 TileY)
{
U32 TileMapValue = TileMap->Tiles[TileY*TileMap->CountX + TileX];
return TileMapValue;
}
static B32 IsTileMapPointEmpty(tile_map *TileMap, F32 TestX, F32 TestY)
{
B32 Empty = FALSE;
S32 PlayerTileX =
(S32)((TestX - TileMap->UpperLeftX) / TileMap->TileWidth);
S32 PlayerTileY =
(S32)((TestY - TileMap->UpperLeftY) / TileMap->TileHeight);
if((PlayerTileX >= 0) && (PlayerTileX < TileMap->CountX) &&
(PlayerTileY >= 0) && (PlayerTileY < TileMap->CountY))
{
U32 TileMapValue =
GetTileValueUnchecked(TileMap, PlayerTileX, PlayerTileY);
Empty = (TileMapValue == 0);
}
return Empty;
}
static B32 IsWorldPointEmpty(world *World,
S32 TileMapX, S32 TileMapY,
F32 TestX, F32 TestY)
{
B32 Empty = FALSE;
tile_map *TileMap = GetTileMap(World, TileMapX, TileMapY);
S32 PlayerTileX, PlayerTileY;
TileMap = GetTileMap(World, TileMapX, TileMapY);
if(TileMap) {
S32 PlayerTileX =
(S32)((TestX - TileMap->UpperLeftX) / TileMap->TileWidth);
S32 PlayerTileY =
(S32)((TestY - TileMap->UpperLeftY) / TileMap->TileHeight);
if((PlayerTileX >= 0) && (PlayerTileX < TileMap->CountX) &&
(PlayerTileY >= 0) && (PlayerTileY < TileMap->CountY))
{
U32 TileMapValue =
GetTileValueUnchecked(TileMap, PlayerTileX, PlayerTileY);
Empty = (TileMapValue == 0);
}
}
return Empty;
}
void UpdateAndRender(thread_context *Thread, game_memory *Memory, void UpdateAndRender(thread_context *Thread, game_memory *Memory,
game_input *Input, game_offscreen_buffer *Buffer, game_input *Input, game_offscreen_buffer *Buffer,
game_sound_output_buffer *SoundBuffer) game_sound_output_buffer *SoundBuffer)
{ {
#define TILEMAP_COUNT_X 17
#define TILEMAP_COUNT_Y 9
game_state *GameState; game_state *GameState;
U32 ControllerIndex; U32 ControllerIndex;
S32 Row, Column; S32 Row, Column;
U32 TileMap[9][17] = {
{1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1}, U32 Tiles00[TILEMAP_COUNT_Y][TILEMAP_COUNT_X] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1}, {1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1},
{1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1}, {1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0}, {1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
{1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1}, {1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1},
{1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1}, {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
}; };
F32 UpperLeftX, UpperLeftY, TileWidth, TileHeight; U32 Tiles01[TILEMAP_COUNT_Y][TILEMAP_COUNT_X] = {
{1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
U32 Tiles10[TILEMAP_COUNT_Y][TILEMAP_COUNT_X] = {
{1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
};
U32 Tiles11[TILEMAP_COUNT_Y][TILEMAP_COUNT_X] = {
{1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
F32 PlayerR, PlayerG, PlayerB, PlayerWidth, PlayerHeight, F32 PlayerR, PlayerG, PlayerB, PlayerWidth, PlayerHeight,
PlayerLeft, PlayerTop; PlayerLeft, PlayerTop;
tile_map TileMaps[2][2];
tile_map *TileMap;
world World;
ASSERT((&Input->Controllers[0].u.buttons.Terminator - ASSERT((&Input->Controllers[0].u.buttons.Terminator -
&Input->Controllers[0].u.Buttons[0]) == &Input->Controllers[0].u.Buttons[0]) ==
ARRAY_SIZE(Input->Controllers[0].u.Buttons)); ARRAY_SIZE(Input->Controllers[0].u.Buttons));
ASSERT(sizeof(game_state) <= Memory->PermanentStorageSize); ASSERT(sizeof(game_state) <= Memory->PermanentStorageSize);
memset(&World, 0, sizeof(World));
TileMaps[0][0].CountX = TILEMAP_COUNT_X;
TileMaps[0][0].CountY = TILEMAP_COUNT_Y;
TileMaps[0][0].UpperLeftX = 0.0f;
TileMaps[0][0].UpperLeftY = 0.0f;
TileMaps[0][0].TileWidth = 57.0f;
TileMaps[0][0].TileHeight = 57.0f;
TileMaps[0][0].Tiles = (U32 *)Tiles00;
TileMaps[0][1] = TileMaps[0][0];
TileMaps[0][1].Tiles = (U32 *)Tiles01;
TileMaps[1][0] = TileMaps[0][0];
TileMaps[1][0].Tiles = (U32 *)Tiles10;
TileMaps[1][1] = TileMaps[0][0];
TileMaps[1][1].Tiles = (U32 *)Tiles11;
TileMap = &TileMaps[0][0];
World.TileMaps = (tile_map *)TileMaps;
PlayerWidth = 0.75f * TileMap->TileWidth;
PlayerHeight = TileMap->TileHeight;
GameState = (game_state *)Memory->PermanentStorage; GameState = (game_state *)Memory->PermanentStorage;
if(!Memory->IsInitialized) { if(!Memory->IsInitialized) {
GameState->PlayerX = 200.0f;
GameState->PlayerY = 200.0f;
Memory->IsInitialized = TRUE; Memory->IsInitialized = TRUE;
} }
@@ -164,6 +306,8 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
F32 dPlayerX = 0.0f; F32 dPlayerX = 0.0f;
F32 dPlayerY = 0.0f; F32 dPlayerY = 0.0f;
F32 NewPlayerX, NewPlayerY;
if(Controller->u.buttons.MoveUp.EndedDown) { if(Controller->u.buttons.MoveUp.EndedDown) {
dPlayerY = -1.0f; dPlayerY = -1.0f;
} }
@@ -177,14 +321,23 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
dPlayerX = 1.0f; dPlayerX = 1.0f;
} }
dPlayerX *= 64.0f; dPlayerX *= 100.0f;
dPlayerY *= 64.0f; dPlayerY *= 100.0f;
GameState->PlayerX += Input->dtForFrame * dPlayerX; NewPlayerX = RoundF32toS32(GameState->PlayerX +
GameState->PlayerY += Input->dtForFrame * dPlayerY; Input->dtForFrame*dPlayerX);
NewPlayerY = RoundF32toS32(GameState->PlayerY +
Input->dtForFrame*dPlayerY);
GameState->PlayerX = RoundF32toS32(GameState->PlayerX); if(IsTileMapPointEmpty(TileMap, NewPlayerX - 0.5f*PlayerWidth,
GameState->PlayerY = RoundF32toS32(GameState->PlayerY); NewPlayerY) &&
IsTileMapPointEmpty(TileMap, NewPlayerX + 0.5f*PlayerWidth,
NewPlayerY) &&
IsTileMapPointEmpty(TileMap, NewPlayerX, NewPlayerY))
{
GameState->PlayerX = NewPlayerX;
GameState->PlayerY = NewPlayerY;
}
} }
} }
@@ -192,23 +345,18 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
(F32)(Buffer->Width), (F32)(Buffer->Height), (F32)(Buffer->Width), (F32)(Buffer->Height),
0.0f, 1.0f, 0.0f); 0.0f, 1.0f, 0.0f);
UpperLeftX = 0.0f; for(Row = 0; Row < TILEMAP_COUNT_Y; Row++) {
UpperLeftY = 0.0f; for(Column = 0; Column < TILEMAP_COUNT_X; Column++) {
TileWidth = 57.0f;
TileHeight = 57.0f;
for(Row = 0; Row < 9; Row++) {
for(Column = 0; Column < 17; Column++) {
F32 MinX, MinY, MaxX, MaxY; F32 MinX, MinY, MaxX, MaxY;
U32 TileID = TileMap[Row][Column]; U32 TileID = GetTileValueUnchecked(TileMap, Column, Row);
F32 Gray = 0.5f; F32 Gray = 0.5f;
if(TileID) { if(TileID) {
Gray = 1.0f; Gray = 1.0f;
} }
MinX = UpperLeftX + (F32)(Column) * TileWidth; MinX = TileMap->UpperLeftX + (F32)(Column) * TileMap->TileWidth;
MinY = UpperLeftY + (F32)(Row) * TileHeight; MinY = TileMap->UpperLeftY + (F32)(Row) * TileMap->TileHeight;
MaxX = MinX + TileWidth; MaxX = MinX + TileMap->TileWidth;
MaxY = MinY + TileHeight; MaxY = MinY + TileMap->TileHeight;
DrawRectangle(Buffer, MinX, MinY, MaxX, MaxY, Gray, Gray, Gray); DrawRectangle(Buffer, MinX, MinY, MaxX, MaxY, Gray, Gray, Gray);
} }
} }
@@ -216,8 +364,6 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
PlayerR = 1.0f; PlayerR = 1.0f;
PlayerG = 0.0f; PlayerG = 0.0f;
PlayerB = 0.0f; PlayerB = 0.0f;
PlayerWidth = 0.75f * TileWidth;
PlayerHeight = TileHeight;
PlayerLeft = GameState->PlayerX - 0.5f*PlayerWidth; PlayerLeft = GameState->PlayerX - 0.5f*PlayerWidth;
PlayerTop = GameState->PlayerY - PlayerHeight; PlayerTop = GameState->PlayerY - PlayerHeight;
DrawRectangle(Buffer, DrawRectangle(Buffer,
+19
View File
@@ -136,6 +136,25 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
* *
*/ */
typedef struct tile_map {
S32 CountX;
S32 CountY;
F32 UpperLeftX;
F32 UpperLeftY;
F32 TileWidth;
F32 TileHeight;
U32 *Tiles;
} tile_map;
typedef struct world {
S32 TileMapCountX;
S32 TileMapCountY;
tile_map *TileMaps;
} world;
typedef struct game_state { typedef struct game_state {
F32 PlayerX; F32 PlayerX;
F32 PlayerY; F32 PlayerY;
+14 -13
View File
@@ -178,6 +178,11 @@ static void SDLDisplayBufferInWindow(offscreen_buffer Buffer,
SDL_Renderer *Renderer) SDL_Renderer *Renderer)
{ {
SDL_Rect dest_rect; SDL_Rect dest_rect;
S32 OffsetX = 10;
S32 OffsetY = 10;
SDL_SetRenderDrawColor(Renderer, 0, 0, 0, 255);
SDL_RenderClear(Renderer);
if(SDL_UpdateTexture(Buffer.Texture, 0, Buffer.Memory, Buffer.Pitch)) { if(SDL_UpdateTexture(Buffer.Texture, 0, Buffer.Memory, Buffer.Pitch)) {
/* TODO: Do something about this error! */ /* TODO: Do something about this error! */
@@ -186,8 +191,8 @@ static void SDLDisplayBufferInWindow(offscreen_buffer Buffer,
/* TODO: We temporarily introduce the target rectangle to avoid /* TODO: We temporarily introduce the target rectangle to avoid
* stretching the canvas. */ * stretching the canvas. */
/* SDL_RenderCopy(Renderer, Buffer.Texture, 0, 0); */ /* SDL_RenderCopy(Renderer, Buffer.Texture, 0, 0); */
dest_rect.x = 0; dest_rect.x = OffsetX;
dest_rect.y = 0; dest_rect.y = OffsetY;
dest_rect.w = RESOLUTION_WIDTH; dest_rect.w = RESOLUTION_WIDTH;
dest_rect.h = RESOLUTION_HEIGHT; dest_rect.h = RESOLUTION_HEIGHT;
SDL_RenderCopy(Renderer, Buffer.Texture, 0, (const SDL_Rect *)(&dest_rect)); SDL_RenderCopy(Renderer, Buffer.Texture, 0, (const SDL_Rect *)(&dest_rect));
@@ -684,6 +689,13 @@ static void SDLGetDLLPath(char *path, size_t path_size, char *exe_path)
snprintf(path, path_size, "%s%s", exe_path, GAME_DLL_NAME); snprintf(path, path_size, "%s%s", exe_path, GAME_DLL_NAME);
} }
#if !(__x86_64__ || __i386__)
U64 __rdtsc()
{
return 0;
}
#endif
S32 main(S32 argc, char *argv[]) S32 main(S32 argc, char *argv[])
{ {
sdl_state SDLState; sdl_state SDLState;
@@ -818,9 +830,7 @@ S32 main(S32 argc, char *argv[])
S32 MonitorRefreshHz, GameUpdateHz; S32 MonitorRefreshHz, GameUpdateHz;
U64 LastCounter; U64 LastCounter;
#if __x86_64__ || __i386__
U64 LastCycleCount; U64 LastCycleCount;
#endif
MonitorRefreshHz = SDLGetWindowRefreshRate(Window); MonitorRefreshHz = SDLGetWindowRefreshRate(Window);
/*GameUpdateHz = MonitorRefreshHz;*/ /*GameUpdateHz = MonitorRefreshHz;*/
@@ -848,23 +858,19 @@ S32 main(S32 argc, char *argv[])
U64 WorkCounter, EndCounter; U64 WorkCounter, EndCounter;
F32 WorkSecondsElapsed, SecondsElapsedForFrame; F32 WorkSecondsElapsed, SecondsElapsedForFrame;
F64 MSPerFrame, FPS; F64 MSPerFrame, FPS;
#if __x86_64__ || __i386__
U64 EndCycleCount, CyclesElapsed; U64 EndCycleCount, CyclesElapsed;
F64 MCPF; F64 MCPF;
#endif
NewInput->dtForFrame = TargetSecondsPerFrame; NewInput->dtForFrame = TargetSecondsPerFrame;
LastCounter = SDLGetWallClock(); LastCounter = SDLGetWallClock();
#if __x86_64__ || __i386__
/* NOTE: rdtsc reports clock cylces, however it is not /* NOTE: rdtsc reports clock cylces, however it is not
* meant for really precise profiler work as the * meant for really precise profiler work as the
* value returned is varied. */ * value returned is varied. */
/* Also, __rdtsc is not available on MacOS ARM; I /* Also, __rdtsc is not available on MacOS ARM; I
* have not checked MacOS x64. */ * have not checked MacOS x64. */
LastCycleCount = __rdtsc(); LastCycleCount = __rdtsc();
#endif
NewDLLWriteTime = GetLastWriteTime(SDLState.DLLPath); NewDLLWriteTime = GetLastWriteTime(SDLState.DLLPath);
if(NewDLLWriteTime > Game.DLLLastWriteTime) { if(NewDLLWriteTime > Game.DLLLastWriteTime) {
@@ -1126,17 +1132,12 @@ S32 main(S32 argc, char *argv[])
LastCounter = EndCounter; LastCounter = EndCounter;
#if 0 #if 0
#if __x86_64__ || __i386__
EndCycleCount = __rdtsc(); EndCycleCount = __rdtsc();
CyclesElapsed = EndCycleCount - LastCycleCount; CyclesElapsed = EndCycleCount - LastCycleCount;
MCPF = ((double)CyclesElapsed / (1000.0 * 1000.0)); MCPF = ((double)CyclesElapsed / (1000.0 * 1000.0));
fprintf(stderr, "%.02f ms/f, %.02f/s, %.02f mc/f\n", fprintf(stderr, "%.02f ms/f, %.02f/s, %.02f mc/f\n",
MSPerFrame, FPS, MCPF); MSPerFrame, FPS, MCPF);
LastCycleCount = EndCycleCount; LastCycleCount = EndCycleCount;
#else
fprintf(stderr, "%.02f ms/f, %.02f/s\n",
MSPerFrame, FPS);
#endif
#endif #endif
SWAP(game_input *, NewInput, OldInput); SWAP(game_input *, NewInput, OldInput);