Day 29 complete.
This commit is contained in:
+171
-25
@@ -3,6 +3,7 @@
|
||||
#include "sdl_handmade.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h> /* memset */
|
||||
|
||||
static void GameOutputSound(game_state *GameState,
|
||||
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,
|
||||
game_input *Input, game_offscreen_buffer *Buffer,
|
||||
game_sound_output_buffer *SoundBuffer)
|
||||
{
|
||||
#define TILEMAP_COUNT_X 17
|
||||
#define TILEMAP_COUNT_Y 9
|
||||
|
||||
game_state *GameState;
|
||||
U32 ControllerIndex;
|
||||
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, 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},
|
||||
{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, 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, 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,
|
||||
PlayerLeft, PlayerTop;
|
||||
|
||||
tile_map TileMaps[2][2];
|
||||
tile_map *TileMap;
|
||||
world World;
|
||||
|
||||
ASSERT((&Input->Controllers[0].u.buttons.Terminator -
|
||||
&Input->Controllers[0].u.Buttons[0]) ==
|
||||
ARRAY_SIZE(Input->Controllers[0].u.Buttons));
|
||||
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;
|
||||
if(!Memory->IsInitialized) {
|
||||
GameState->PlayerX = 200.0f;
|
||||
GameState->PlayerY = 200.0f;
|
||||
|
||||
Memory->IsInitialized = TRUE;
|
||||
}
|
||||
|
||||
@@ -164,6 +306,8 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
F32 dPlayerX = 0.0f;
|
||||
F32 dPlayerY = 0.0f;
|
||||
|
||||
F32 NewPlayerX, NewPlayerY;
|
||||
|
||||
if(Controller->u.buttons.MoveUp.EndedDown) {
|
||||
dPlayerY = -1.0f;
|
||||
}
|
||||
@@ -177,14 +321,23 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
dPlayerX = 1.0f;
|
||||
}
|
||||
|
||||
dPlayerX *= 64.0f;
|
||||
dPlayerY *= 64.0f;
|
||||
dPlayerX *= 100.0f;
|
||||
dPlayerY *= 100.0f;
|
||||
|
||||
GameState->PlayerX += Input->dtForFrame * dPlayerX;
|
||||
GameState->PlayerY += Input->dtForFrame * dPlayerY;
|
||||
NewPlayerX = RoundF32toS32(GameState->PlayerX +
|
||||
Input->dtForFrame*dPlayerX);
|
||||
NewPlayerY = RoundF32toS32(GameState->PlayerY +
|
||||
Input->dtForFrame*dPlayerY);
|
||||
|
||||
GameState->PlayerX = RoundF32toS32(GameState->PlayerX);
|
||||
GameState->PlayerY = RoundF32toS32(GameState->PlayerY);
|
||||
if(IsTileMapPointEmpty(TileMap, NewPlayerX - 0.5f*PlayerWidth,
|
||||
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),
|
||||
0.0f, 1.0f, 0.0f);
|
||||
|
||||
UpperLeftX = 0.0f;
|
||||
UpperLeftY = 0.0f;
|
||||
TileWidth = 57.0f;
|
||||
TileHeight = 57.0f;
|
||||
|
||||
for(Row = 0; Row < 9; Row++) {
|
||||
for(Column = 0; Column < 17; Column++) {
|
||||
for(Row = 0; Row < TILEMAP_COUNT_Y; Row++) {
|
||||
for(Column = 0; Column < TILEMAP_COUNT_X; Column++) {
|
||||
F32 MinX, MinY, MaxX, MaxY;
|
||||
U32 TileID = TileMap[Row][Column];
|
||||
U32 TileID = GetTileValueUnchecked(TileMap, Column, Row);
|
||||
F32 Gray = 0.5f;
|
||||
if(TileID) {
|
||||
Gray = 1.0f;
|
||||
}
|
||||
MinX = UpperLeftX + (F32)(Column) * TileWidth;
|
||||
MinY = UpperLeftY + (F32)(Row) * TileHeight;
|
||||
MaxX = MinX + TileWidth;
|
||||
MaxY = MinY + TileHeight;
|
||||
MinX = TileMap->UpperLeftX + (F32)(Column) * TileMap->TileWidth;
|
||||
MinY = TileMap->UpperLeftY + (F32)(Row) * TileMap->TileHeight;
|
||||
MaxX = MinX + TileMap->TileWidth;
|
||||
MaxY = MinY + TileMap->TileHeight;
|
||||
DrawRectangle(Buffer, MinX, MinY, MaxX, MaxY, Gray, Gray, Gray);
|
||||
}
|
||||
}
|
||||
@@ -216,8 +364,6 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
PlayerR = 1.0f;
|
||||
PlayerG = 0.0f;
|
||||
PlayerB = 0.0f;
|
||||
PlayerWidth = 0.75f * TileWidth;
|
||||
PlayerHeight = TileHeight;
|
||||
PlayerLeft = GameState->PlayerX - 0.5f*PlayerWidth;
|
||||
PlayerTop = GameState->PlayerY - PlayerHeight;
|
||||
DrawRectangle(Buffer,
|
||||
|
||||
+21
-2
@@ -106,8 +106,8 @@ typedef struct game_memory {
|
||||
|
||||
U64 PermanentStorageSize;
|
||||
void *PermanentStorage; /* WARNING: This memory is REQUIRED to be zero
|
||||
initialized!!! (Done by the OS
|
||||
layer.) */
|
||||
initialized!!! (Done by the OS
|
||||
layer.) */
|
||||
|
||||
U64 TransientStorageSize;
|
||||
void *TransientStorage; /* WARNING: This memory is REQUIRED to be zero
|
||||
@@ -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 {
|
||||
F32 PlayerX;
|
||||
F32 PlayerY;
|
||||
|
||||
+14
-13
@@ -178,6 +178,11 @@ static void SDLDisplayBufferInWindow(offscreen_buffer Buffer,
|
||||
SDL_Renderer *Renderer)
|
||||
{
|
||||
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)) {
|
||||
/* 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
|
||||
* stretching the canvas. */
|
||||
/* SDL_RenderCopy(Renderer, Buffer.Texture, 0, 0); */
|
||||
dest_rect.x = 0;
|
||||
dest_rect.y = 0;
|
||||
dest_rect.x = OffsetX;
|
||||
dest_rect.y = OffsetY;
|
||||
dest_rect.w = RESOLUTION_WIDTH;
|
||||
dest_rect.h = RESOLUTION_HEIGHT;
|
||||
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);
|
||||
}
|
||||
|
||||
#if !(__x86_64__ || __i386__)
|
||||
U64 __rdtsc()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
S32 main(S32 argc, char *argv[])
|
||||
{
|
||||
sdl_state SDLState;
|
||||
@@ -818,9 +830,7 @@ S32 main(S32 argc, char *argv[])
|
||||
S32 MonitorRefreshHz, GameUpdateHz;
|
||||
|
||||
U64 LastCounter;
|
||||
#if __x86_64__ || __i386__
|
||||
U64 LastCycleCount;
|
||||
#endif
|
||||
|
||||
MonitorRefreshHz = SDLGetWindowRefreshRate(Window);
|
||||
/*GameUpdateHz = MonitorRefreshHz;*/
|
||||
@@ -848,23 +858,19 @@ S32 main(S32 argc, char *argv[])
|
||||
U64 WorkCounter, EndCounter;
|
||||
F32 WorkSecondsElapsed, SecondsElapsedForFrame;
|
||||
F64 MSPerFrame, FPS;
|
||||
#if __x86_64__ || __i386__
|
||||
U64 EndCycleCount, CyclesElapsed;
|
||||
F64 MCPF;
|
||||
#endif
|
||||
|
||||
NewInput->dtForFrame = TargetSecondsPerFrame;
|
||||
|
||||
LastCounter = SDLGetWallClock();
|
||||
|
||||
#if __x86_64__ || __i386__
|
||||
/* NOTE: rdtsc reports clock cylces, however it is not
|
||||
* meant for really precise profiler work as the
|
||||
* value returned is varied. */
|
||||
/* Also, __rdtsc is not available on MacOS ARM; I
|
||||
* have not checked MacOS x64. */
|
||||
LastCycleCount = __rdtsc();
|
||||
#endif
|
||||
|
||||
NewDLLWriteTime = GetLastWriteTime(SDLState.DLLPath);
|
||||
if(NewDLLWriteTime > Game.DLLLastWriteTime) {
|
||||
@@ -1126,17 +1132,12 @@ S32 main(S32 argc, char *argv[])
|
||||
LastCounter = EndCounter;
|
||||
|
||||
#if 0
|
||||
#if __x86_64__ || __i386__
|
||||
EndCycleCount = __rdtsc();
|
||||
CyclesElapsed = EndCycleCount - LastCycleCount;
|
||||
MCPF = ((double)CyclesElapsed / (1000.0 * 1000.0));
|
||||
fprintf(stderr, "%.02f ms/f, %.02f/s, %.02f mc/f\n",
|
||||
MSPerFrame, FPS, MCPF);
|
||||
LastCycleCount = EndCycleCount;
|
||||
#else
|
||||
fprintf(stderr, "%.02f ms/f, %.02f/s\n",
|
||||
MSPerFrame, FPS);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
SWAP(game_input *, NewInput, OldInput);
|
||||
|
||||
Reference in New Issue
Block a user