Comply with ansi C and clean up.

This commit is contained in:
2026-07-15 13:26:36 -07:00
parent ffc4310646
commit a829ac8647
7 changed files with 465 additions and 291 deletions
+7 -4
View File
@@ -14,8 +14,8 @@ endif
CC = clang CC = clang
UFLAGS = UFLAGS =
FLAGS = -Wall -Wextra \ FLAGS = -ansi -pedantic -pedantic-errors -Wno-long-long -Wall -Wextra \
-Wincompatible-pointer-types \ -Wincompatible-pointer-types \
-Wint-conversion -Wimplicit-int-float-conversion -Wformat \ -Wint-conversion -Wimplicit-int-float-conversion -Wformat \
-Wno-strict-prototypes -Wno-missing-field-initializers \ -Wno-strict-prototypes -Wno-missing-field-initializers \
@@ -48,10 +48,13 @@ EXE=handmadehero
default: tags libhandmade $(EXE) default: tags libhandmade $(EXE)
libhandmade: handmade.c libhandmade: handmade.c
@ $(CC) $(FLAGS) $(UFLAGS) -fPIC -shared $(INCLUDE) $^ $(LIBS) $(FRAMEWORKS) -o libhandmade.so @ $(CC) $(FLAGS) $(UFLAGS) -fPIC -shared $(INCLUDE) $^ $(LIBS) \
$(FRAMEWORKS) -o libhandmade.so
$(EXE): sdl_handmade.c libhandmade $(EXE): sdl_handmade.c libhandmade
@ $(CC) $(FLAGS) $(UFLAGS) $(INCLUDE) sdl_handmade.c $(LIBS) $(FRAMEWORKS) -o $@ $(ifneq $(filter $(DETECTED_OS), macos linux), /link /FORCE:MULTIPLE) @ $(CC) $(FLAGS) $(UFLAGS) $(INCLUDE) sdl_handmade.c $(LIBS) \
$(FRAMEWORKS) -o $@ $(ifneq $(filter $(DETECTED_OS), macos linux), \
/link /FORCE:MULTIPLE)
run: run:
@ ./$(EXE) @ ./$(EXE)
+247 -154
View File
@@ -49,7 +49,8 @@ static void ClearBackground(struct game_offscreen_buffer *Buffer)
int Width = Buffer->Width; int Width = Buffer->Width;
int Height = Buffer->Height; int Height = Buffer->Height;
for(int X = 0; X < Width * Height; X++) { int X;
for(X = 0; X < Width * Height; X++) {
unsigned int *Pixel = &((unsigned int *)Buffer->Memory)[X]; unsigned int *Pixel = &((unsigned int *)Buffer->Memory)[X];
*Pixel = 0xFFFFFF; *Pixel = 0xFFFFFF;
} }
@@ -59,13 +60,24 @@ static void DrawRectangle(struct game_offscreen_buffer *Buffer,
struct v2 vMin, struct v2 vMax, struct v2 vMin, struct v2 vMax,
float R, float G, float B) float R, float G, float B)
{ {
int MinX = RoundFloatToInt(vMin.X); int Y, X;
int MinY = RoundFloatToInt(vMin.Y);
int MaxX = RoundFloatToInt(vMax.X);
int MaxY = RoundFloatToInt(vMax.Y);
int Width = Buffer->Width; int Width, Height;
int Height = Buffer->Height;
int MinX, MinY, MaxX, MaxY;
unsigned int Color;
unsigned char *Row;
unsigned int *Pixel;
MinX = RoundFloatToInt(vMin.X);
MinY = RoundFloatToInt(vMin.Y);
MaxX = RoundFloatToInt(vMax.X);
MaxY = RoundFloatToInt(vMax.Y);
Width = Buffer->Width;
Height = Buffer->Height;
if(MinX < 0) if(MinX < 0)
MinX = 0; MinX = 0;
@@ -80,16 +92,16 @@ static void DrawRectangle(struct game_offscreen_buffer *Buffer,
/*unsigned int Color = (unsigned int)((RoundFloatToInt(R * 255.0f) << 16) | /*unsigned int Color = (unsigned int)((RoundFloatToInt(R * 255.0f) << 16) |
(RoundFloatToInt(G * 255.0f) << 8) | (RoundFloatToInt(G * 255.0f) << 8) |
(RoundFloatToInt(B * 255.0f) << 0));*/ (RoundFloatToInt(B * 255.0f) << 0));*/
unsigned int Color = (unsigned int)((RoundFloatToInt(255.0f) << 24) | Color = (unsigned int)((RoundFloatToInt(255.0f) << 24) |
(RoundFloatToInt(R * 255.0f) << 16) | (RoundFloatToInt(R * 255.0f) << 16) |
(RoundFloatToInt(G * 255.0f) << 8) | (RoundFloatToInt(G * 255.0f) << 8) |
(RoundFloatToInt(B * 255.0f) << 0)); (RoundFloatToInt(B * 255.0f) << 0));
unsigned char *Row = ((unsigned char *)Buffer->Memory + Row = ((unsigned char *)Buffer->Memory + MinX*Buffer->BytesPerPixel +
MinX*Buffer->BytesPerPixel + MinY*Buffer->Pitch); MinY*Buffer->Pitch);
for(int Y = MinY; Y < MaxY; Y++) { for(Y = MinY; Y < MaxY; Y++) {
unsigned int *Pixel = (unsigned int *)Row; Pixel = (unsigned int *)Row;
for(int X = MinX; X < MaxX; X++) { for(X = MinX; X < MaxX; X++) {
*(unsigned int *)Pixel = Color; *(unsigned int *)Pixel = Color;
Pixel++; Pixel++;
} }
@@ -101,24 +113,35 @@ static void DrawBitmap(struct game_offscreen_buffer *Buffer,
struct loaded_bitmap *Bitmap, struct loaded_bitmap *Bitmap,
float RelX, float RelY, int AlignX, int AlignY) float RelX, float RelY, int AlignX, int AlignY)
{ {
int MinX, MinY, MaxX, MaxY;
int Width, Height;
int SourceOffsetX, SourceOffsetY;
unsigned int *SourceRow;
unsigned char *DestRow;
int Y, X;
RelX -= (float)AlignX; RelX -= (float)AlignX;
RelY -= (float)AlignY; RelY -= (float)AlignY;
int MinX = RoundFloatToInt(RelX); MinX = RoundFloatToInt(RelX);
int MinY = RoundFloatToInt(RelY); MinY = RoundFloatToInt(RelY);
int MaxX = RoundFloatToInt(RelX + (float)Bitmap->Width); MaxX = RoundFloatToInt(RelX + (float)Bitmap->Width);
int MaxY = RoundFloatToInt(RelY + (float)Bitmap->Height); MaxY = RoundFloatToInt(RelY + (float)Bitmap->Height);
int Width = Buffer->Width; Width = Buffer->Width;
int Height = Buffer->Height; Height = Buffer->Height;
int SourceOffsetX = 0; SourceOffsetX = 0;
if(MinX < 0) { if(MinX < 0) {
SourceOffsetX = -MinX; SourceOffsetX = -MinX;
MinX = 0; MinX = 0;
} }
int SourceOffsetY = 0; SourceOffsetY = 0;
if(MinY < 0) { if(MinY < 0) {
SourceOffsetY = -MinY; SourceOffsetY = -MinY;
MinY = 0; MinY = 0;
@@ -129,15 +152,15 @@ static void DrawBitmap(struct game_offscreen_buffer *Buffer,
if(MaxY > Height) if(MaxY > Height)
MaxY = Height; MaxY = Height;
unsigned int *SourceRow = SourceRow =
Bitmap->Pixels + Bitmap->Width*(Bitmap->Height - 1); Bitmap->Pixels + Bitmap->Width*(Bitmap->Height - 1);
SourceRow += -Bitmap->Width*SourceOffsetY + SourceOffsetX; SourceRow += -Bitmap->Width*SourceOffsetY + SourceOffsetX;
unsigned char *DestRow = ((unsigned char *)Buffer->Memory + DestRow = ((unsigned char *)Buffer->Memory +
MinX*Buffer->BytesPerPixel + MinY*Buffer->Pitch); MinX*Buffer->BytesPerPixel + MinY*Buffer->Pitch);
for(int Y = MinY; Y < MaxY; Y++) { for(Y = MinY; Y < MaxY; Y++) {
unsigned int *Dest = (unsigned int *)DestRow; unsigned int *Dest = (unsigned int *)DestRow;
unsigned int *Source = SourceRow; unsigned int *Source = SourceRow;
for(int X = MinX; X < MaxX; X++) { for(X = MinX; X < MaxX; X++) {
float SA = (float)((*Source >> 24) & 0xFF); float SA = (float)((*Source >> 24) & 0xFF);
float SR = (float)((*Source >> 16) & 0xFF); float SR = (float)((*Source >> 16) & 0xFF);
float SG = (float)((*Source >> 8) & 0xFF); float SG = (float)((*Source >> 8) & 0xFF);
@@ -149,7 +172,7 @@ static void DrawBitmap(struct game_offscreen_buffer *Buffer,
float A = SA / 255.0f; float A = SA / 255.0f;
// TODO: This should be replaced by premultiplied alpha. /* TODO: This should be replaced by premultiplied alpha. */
float R = (1.0f-A)*DR + A*SR; float R = (1.0f-A)*DR + A*SR;
float G = (1.0f-A)*DG + A*SG; float G = (1.0f-A)*DG + A*SG;
float B = (1.0f-A)*DB + A*SB; float B = (1.0f-A)*DB + A*SB;
@@ -198,47 +221,56 @@ static struct loaded_bitmap DEBUGLoadBMP(struct thread_context *Thread,
const char *), char *FileName) const char *), char *FileName)
{ {
struct loaded_bitmap Result; struct loaded_bitmap Result;
struct debug_read_file_result ReadResult;
memset(&Result, 0, sizeof(Result)); memset(&Result, 0, sizeof(Result));
struct debug_read_file_result ReadResult = ReadResult = DEBUGPlatformReadEntireFile(Thread, FileName);
DEBUGPlatformReadEntireFile(Thread, FileName);
if(ReadResult.ContentsSize > 0) { if(ReadResult.ContentsSize > 0) {
struct bitmap_header *Header = struct bitmap_header *Header;
(struct bitmap_header *)ReadResult.Contents;
unsigned int *Pixels = unsigned int *Pixels;
(unsigned int *)((unsigned char *)ReadResult.Contents +
Header->BitmapOffset); unsigned int RedMask, GreenMask, BlueMask, AlphaMask;
struct bit_scan_result RedShift, GreenShift,
BlueShift, AlphaShift;
unsigned int *SourceDest;
int X, Y;
Header = (struct bitmap_header *)ReadResult.Contents;
Pixels = (unsigned int *)((unsigned char *)ReadResult.Contents +
Header->BitmapOffset);
Result.Pixels = Pixels; Result.Pixels = Pixels;
Result.Width = Header->Width; Result.Width = Header->Width;
Result.Height = Header->Height; Result.Height = Header->Height;
ASSERT(Header->Compression == 3); ASSERT(Header->Compression == 3);
// NOTE: The byte order in memory is determined by the Header. /* NOTE: The byte order in memory is determined by the Header. */
unsigned int RedMask = Header->RedMask; RedMask = Header->RedMask;
unsigned int GreenMask = Header->GreenMask; GreenMask = Header->GreenMask;
unsigned int BlueMask = Header->BlueMask; BlueMask = Header->BlueMask;
unsigned int AlphaMask = ~(RedMask | GreenMask | BlueMask); AlphaMask = ~(RedMask | GreenMask | BlueMask);
struct bit_scan_result RedShift = RedShift = FindLeastSignificantSetBit(RedMask);
FindLeastSignificantSetBit(RedMask); GreenShift = FindLeastSignificantSetBit(GreenMask);
struct bit_scan_result GreenShift = BlueShift = FindLeastSignificantSetBit(BlueMask);
FindLeastSignificantSetBit(GreenMask); AlphaShift = FindLeastSignificantSetBit(AlphaMask);
struct bit_scan_result BlueShift =
FindLeastSignificantSetBit(BlueMask);
struct bit_scan_result AlphaShift =
FindLeastSignificantSetBit(AlphaMask);
ASSERT(RedShift.Found); ASSERT(RedShift.Found);
ASSERT(GreenShift.Found); ASSERT(GreenShift.Found);
ASSERT(BlueShift.Found); ASSERT(BlueShift.Found);
ASSERT(AlphaShift.Found); ASSERT(AlphaShift.Found);
unsigned int *SourceDest = Pixels; SourceDest = Pixels;
for(int Y = 0; Y < Header->Height; Y++) { for(Y = 0; Y < Header->Height; Y++) {
for(int X = 0; X < Header->Width; X++) { for(X = 0; X < Header->Width; X++) {
unsigned int C = *SourceDest; unsigned int C = *SourceDest;
*SourceDest = ((((C >> AlphaShift.Index) & 0xFF) << 24) | *SourceDest = ((((C >> AlphaShift.Index) & 0xFF) << 24) |
@@ -279,9 +311,10 @@ static void InitializePlayer(struct entity *Entity)
static unsigned int AddEntity(struct game_state *GameState) static unsigned int AddEntity(struct game_state *GameState)
{ {
unsigned int EntityIndex = ++GameState->EntityCount; unsigned int EntityIndex = ++GameState->EntityCount;
struct entity *Entity;
ASSERT(GameState->EntityCount < ARRAY_SIZE(GameState->Entities)); ASSERT(GameState->EntityCount < ARRAY_SIZE(GameState->Entities));
struct entity *Entity = &GameState->Entities[EntityIndex]; Entity = &GameState->Entities[EntityIndex];
memset(Entity, 0, sizeof(struct entity)); memset(Entity, 0, sizeof(struct entity));
return EntityIndex; return EntityIndex;
@@ -290,38 +323,48 @@ static unsigned int AddEntity(struct game_state *GameState)
static void MovePlayer(struct game_state *GameState, static void MovePlayer(struct game_state *GameState,
struct entity *Entity, float dt, struct v2 ddPlayer) struct entity *Entity, float dt, struct v2 ddPlayer)
{ {
struct tile_map *TileMap = GameState->World->TileMap; struct tile_map *TileMap;
float PlayerSpeed;
struct tile_map_position OldPlayerP, NewPlayerP;
struct v2 PlayerDelta;
TileMap = GameState->World->TileMap;
if((ddPlayer.X != 0.0f) && (ddPlayer.Y != 0.0f)) if((ddPlayer.X != 0.0f) && (ddPlayer.Y != 0.0f))
ddPlayer = V2Multiply(0.7071067811865475244f, ddPlayer); ddPlayer = V2Multiply(0.7071067811865475244f, ddPlayer);
float PlayerSpeed = 10.0f; PlayerSpeed = 10.0f;
ddPlayer = V2Multiply(PlayerSpeed, ddPlayer); ddPlayer = V2Multiply(PlayerSpeed, ddPlayer);
ddPlayer = V2Add(ddPlayer, V2Unary(V2Multiply(1.5f, Entity->dP))); ddPlayer = V2Add(ddPlayer, V2Unary(V2Multiply(1.5f, Entity->dP)));
struct tile_map_position OldPlayerP = Entity->P; OldPlayerP = Entity->P;
struct tile_map_position NewPlayerP = OldPlayerP; NewPlayerP = OldPlayerP;
struct v2 PlayerDelta = V2Add(V2Multiply(0.5f, V2Multiply(Square(dt), PlayerDelta = V2Add(V2Multiply(0.5f, V2Multiply(Square(dt), ddPlayer)),
ddPlayer)), V2Multiply(dt, Entity->dP));
V2Multiply(dt, Entity->dP));
NewPlayerP.Offset = V2Add(PlayerDelta, NewPlayerP.Offset); NewPlayerP.Offset = V2Add(PlayerDelta, NewPlayerP.Offset);
Entity->dP = V2Add(V2Multiply(dt, ddPlayer), Entity->dP); Entity->dP = V2Add(V2Multiply(dt, ddPlayer), Entity->dP);
NewPlayerP = RecannonicalizePosition(TileMap, NewPlayerP); NewPlayerP = RecannonicalizePosition(TileMap, NewPlayerP);
{
#if 1 #if 1
struct tile_map_position PlayerLeft; struct tile_map_position PlayerLeft, PlayerRight;
int Collided;
struct tile_map_position ColP;
PlayerLeft = NewPlayerP; PlayerLeft = NewPlayerP;
PlayerLeft.Offset.X -= 0.5f*Entity->Width; PlayerLeft.Offset.X -= 0.5f*Entity->Width;
PlayerLeft = RecannonicalizePosition(TileMap, PlayerLeft); PlayerLeft = RecannonicalizePosition(TileMap, PlayerLeft);
struct tile_map_position PlayerRight;
PlayerRight = NewPlayerP; PlayerRight = NewPlayerP;
PlayerRight.Offset.X += 0.5f*Entity->Width; PlayerRight.Offset.X += 0.5f*Entity->Width;
PlayerRight = RecannonicalizePosition(TileMap, PlayerRight); PlayerRight = RecannonicalizePosition(TileMap, PlayerRight);
int Collided = 0; Collided = 0;
struct tile_map_position ColP;
memset(&ColP, 0, sizeof(ColP)); memset(&ColP, 0, sizeof(ColP));
if(!IsTileMapPointEmpty(TileMap, NewPlayerP)) { if(!IsTileMapPointEmpty(TileMap, NewPlayerP)) {
ColP = NewPlayerP; ColP = NewPlayerP;
@@ -339,16 +382,20 @@ static void MovePlayer(struct game_state *GameState,
if(Collided) { if(Collided) {
struct v2 r = { 0, 0 }; struct v2 r = { 0, 0 };
if(ColP.AbsTileX < Entity->P.AbsTileX) { if(ColP.AbsTileX < Entity->P.AbsTileX) {
r = (struct v2){ 1, 0 }; r.X = 1;
r.Y = 0;
} }
if(ColP.AbsTileX > Entity->P.AbsTileX) { if(ColP.AbsTileX > Entity->P.AbsTileX) {
r = (struct v2){ -1, 0 }; r.X = -1;
r.Y = 0;
} }
if(ColP.AbsTileY < Entity->P.AbsTileY) { if(ColP.AbsTileY < Entity->P.AbsTileY) {
r = (struct v2){ 0, 1 }; r.X = 0;
r.Y = 1;
} }
if(ColP.AbsTileY > Entity->P.AbsTileY) { if(ColP.AbsTileY > Entity->P.AbsTileY) {
r = (struct v2){ 0, -1 }; r.X = 0;
r.Y = -1;
} }
Entity->dP = V2Subtract(Entity->dP, Entity->dP = V2Subtract(Entity->dP,
@@ -393,6 +440,7 @@ static void MovePlayer(struct game_state *GameState,
} }
} }
#endif #endif
}
if(!AreOnSameTile(&OldPlayerP, &Entity->P)) { if(!AreOnSameTile(&OldPlayerP, &Entity->P)) {
unsigned int NewTileValue = GetTileValueByPos(TileMap, Entity->P); unsigned int NewTileValue = GetTileValueByPos(TileMap, Entity->P);
@@ -424,16 +472,49 @@ void UpdateAndRender(struct thread_context *Thread,
struct game_offscreen_buffer *Buffer, struct game_offscreen_buffer *Buffer,
struct game_sound_output_buffer *SoundBuffer) struct game_sound_output_buffer *SoundBuffer)
{ {
ASSERT((&Input->Controllers[0].Terminator -
&Input->Controllers[0].Buttons[0]) ==
ARRAY_SIZE(Input->Controllers[0].Buttons));
ASSERT(sizeof(struct game_state) <= Memory->PermanentStorageSize);
struct game_state *GameState; struct game_state *GameState;
struct world *World;
struct tile_map *TileMap;
int TileSideInPixels;
float MetersToPixels;
unsigned int ControllerIndex;
struct entity *CameraFollowingEntity;
float ScreenCenterX, ScreenCenterY;
int RelRow, RelColumn;
struct entity *Entity;
unsigned int EntityIndex;
ASSERT((&Input->Controllers[0].u.s.Terminator -
&Input->Controllers[0].u.Buttons[0]) ==
ARRAY_SIZE(Input->Controllers[0].u.Buttons));
ASSERT(sizeof(struct game_state) <= Memory->PermanentStorageSize);
GameState = (struct game_state *)Memory->PermanentStorage; GameState = (struct game_state *)Memory->PermanentStorage;
if(!Memory->IsInitialized) { if(!Memory->IsInitialized) {
// NOTE: Reserve entity slot 0 for null entity struct hero_bitmaps *Bitmap;
struct world *World;
struct tile_map *TileMap;
unsigned int RandomNumberIndex;
unsigned int TilesPerWidth, TilesPerHeight;
unsigned int ScreenX, ScreenY;
unsigned int AbsTileZ;
int DoorTop, DoorBottom, DoorLeft, DoorRight, DoorUp, DoorDown;
unsigned int ScreenIndex;
/* NOTE: Reserve entity slot 0 for null entity */
AddEntity(GameState); AddEntity(GameState);
GameState->rect_pos.X = 0.0f; GameState->rect_pos.X = 0.0f;
@@ -464,8 +545,6 @@ void UpdateAndRender(struct thread_context *Thread,
GameState->Backdrop = DEBUGLoadBMP(Thread, GameState->Backdrop = DEBUGLoadBMP(Thread,
Memory->DEBUGPlatformReadEntireFile, "data/test_background.bmp"); Memory->DEBUGPlatformReadEntireFile, "data/test_background.bmp");
struct hero_bitmaps *Bitmap;
Bitmap = &GameState->HeroBitmaps[0]; Bitmap = &GameState->HeroBitmaps[0];
Bitmap->AlignX = 72; Bitmap->AlignX = 72;
Bitmap->AlignY = 182; Bitmap->AlignY = 182;
@@ -527,10 +606,10 @@ void UpdateAndRender(struct thread_context *Thread,
sizeof(struct game_state)); sizeof(struct game_state));
GameState->World = PUSH_STRUCT(&GameState->WorldArena, struct world); GameState->World = PUSH_STRUCT(&GameState->WorldArena, struct world);
struct world *World = GameState->World; World = GameState->World;
World->TileMap = PUSH_STRUCT(&GameState->WorldArena, struct tile_map); World->TileMap = PUSH_STRUCT(&GameState->WorldArena, struct tile_map);
struct tile_map *TileMap = World->TileMap; TileMap = World->TileMap;
TileMap->ChunkShift = 4; TileMap->ChunkShift = 4;
TileMap->ChunkMask = (1 << TileMap->ChunkShift) - 1; TileMap->ChunkMask = (1 << TileMap->ChunkShift) - 1;
@@ -547,33 +626,39 @@ void UpdateAndRender(struct thread_context *Thread,
TileMap->TileSideInMeters = 1.4f; TileMap->TileSideInMeters = 1.4f;
unsigned int RandomNumberIndex = 0; RandomNumberIndex = 0;
unsigned int TilesPerWidth = 17; TilesPerWidth = 17;
unsigned int TilesPerHeight = 9; TilesPerHeight = 9;
unsigned int ScreenX = 0; ScreenX = 0;
unsigned int ScreenY = 0; ScreenY = 0;
unsigned int AbsTileZ = 0; AbsTileZ = 0;
int DoorTop = 0; DoorTop = 0;
int DoorBottom = 0; DoorBottom = 0;
int DoorLeft = 0; DoorLeft = 0;
int DoorRight = 0; DoorRight = 0;
int DoorUp = 0; DoorUp = 0;
int DoorDown = 0; DoorDown = 0;
for(unsigned int ScreenIndex = 0; ScreenIndex < 100; ScreenIndex++) { for(ScreenIndex = 0; ScreenIndex < 100; ScreenIndex++) {
ASSERT(RandomNumberIndex < ARRAY_SIZE(RandomNumberTable));
/* TODO: Random number generator. */ /* TODO: Random number generator. */
unsigned int RandomChoice; unsigned int RandomChoice;
int CreatedZDoor;
unsigned int TileY, TileX;
ASSERT(RandomNumberIndex < ARRAY_SIZE(RandomNumberTable));
if(DoorUp || DoorDown) { if(DoorUp || DoorDown) {
RandomChoice = RandomNumberTable[RandomNumberIndex++] % 2; RandomChoice = RandomNumberTable[RandomNumberIndex++] % 2;
} else { } else {
RandomChoice = RandomNumberTable[RandomNumberIndex++] % 3; RandomChoice = RandomNumberTable[RandomNumberIndex++] % 3;
} }
int CreatedZDoor = 0; CreatedZDoor = 0;
if(RandomChoice == 2) { if(RandomChoice == 2) {
CreatedZDoor = 1; CreatedZDoor = 1;
@@ -589,14 +674,8 @@ void UpdateAndRender(struct thread_context *Thread,
DoorTop = 1; DoorTop = 1;
} }
for(unsigned int TileY = 0; for(TileY = 0; TileY < TilesPerHeight; TileY++) {
TileY < TilesPerHeight; for(TileX = 0; TileX < TilesPerWidth; TileX++) {
TileY++)
{
for(unsigned int TileX = 0;
TileX < TilesPerWidth;
TileX++)
{
unsigned int AbsTileX = ScreenX * TilesPerWidth + TileX; unsigned int AbsTileX = ScreenX * TilesPerWidth + TileX;
unsigned int AbsTileY = ScreenY * TilesPerHeight + TileY; unsigned int AbsTileY = ScreenY * TilesPerHeight + TileY;
@@ -669,58 +748,56 @@ void UpdateAndRender(struct thread_context *Thread,
Memory->IsInitialized = 1; Memory->IsInitialized = 1;
} }
struct world *World = GameState->World; World = GameState->World;
struct tile_map *TileMap = World->TileMap; TileMap = World->TileMap;
int TileSideInPixels = 60; TileSideInPixels = 60;
float MetersToPixels = MetersToPixels = (float)TileSideInPixels / TileMap->TileSideInMeters;
(float)TileSideInPixels / TileMap->TileSideInMeters;
for(unsigned int ControllerIndex = 0; for(ControllerIndex = 0;
ControllerIndex < ARRAY_SIZE(Input->Controllers); ControllerIndex < ARRAY_SIZE(Input->Controllers);
ControllerIndex++) ControllerIndex++)
{ {
struct game_controller_input *Controller = struct game_controller_input *Controller;
GetController(Input, ControllerIndex); struct entity *ControllingEntity;
struct entity *ControllingEntity =
GetEntity(GameState, Controller = GetController(Input, ControllerIndex);
GameState->PlayerIndexForController[ControllerIndex]); ControllingEntity = GetEntity(GameState,
GameState->PlayerIndexForController[ControllerIndex]);
if(ControllingEntity) { if(ControllingEntity) {
struct v2 ddPlayer; /* accerlation */ struct v2 ddPlayer; /* accerlation */
memset(&ddPlayer, 0, sizeof(ddPlayer)); memset(&ddPlayer, 0, sizeof(ddPlayer));
if(Controller->IsAnalog) { if(Controller->IsAnalog) {
ddPlayer = (struct v2){ Controller->StickAverageX, ddPlayer.X = Controller->StickAverageX;
Controller->StickAverageY }; ddPlayer.Y = -Controller->StickAverageY;
} else { } else {
if(Controller->u.s.MoveUp.EndedDown) {
if(Controller->MoveUp.EndedDown) {
GameState->rect_pos.Y -= 1.0f; GameState->rect_pos.Y -= 1.0f;
ddPlayer.Y = 1.0f; ddPlayer.Y = 1.0f;
} }
if(Controller->MoveDown.EndedDown) { if(Controller->u.s.MoveDown.EndedDown) {
GameState->rect_pos.Y += 1.0f; GameState->rect_pos.Y += 1.0f;
ddPlayer.Y = -1.0f; ddPlayer.Y = -1.0f;
} }
if(Controller->MoveLeft.EndedDown) { if(Controller->u.s.MoveLeft.EndedDown) {
GameState->rect_pos.X -= 1.0f; GameState->rect_pos.X -= 1.0f;
ddPlayer.X = -1.0f; ddPlayer.X = -1.0f;
} }
if(Controller->MoveRight.EndedDown) { if(Controller->u.s.MoveRight.EndedDown) {
GameState->rect_pos.X += 1.0f; GameState->rect_pos.X += 1.0f;
ddPlayer.X = 1.0f; ddPlayer.X = 1.0f;
} }
} }
MovePlayer(GameState, ControllingEntity, Input->dtForFrame, MovePlayer(GameState, ControllingEntity, Input->dtForFrame,
ddPlayer); ddPlayer);
} else { } else {
if(Controller->Start.EndedDown) { if(Controller->u.s.Start.EndedDown) {
unsigned int EntityIndex = AddEntity(GameState); unsigned int EntityIndex = AddEntity(GameState);
ControllingEntity = GetEntity(GameState, EntityIndex); ControllingEntity = GetEntity(GameState, EntityIndex);
InitializePlayer(ControllingEntity); InitializePlayer(ControllingEntity);
@@ -730,14 +807,15 @@ void UpdateAndRender(struct thread_context *Thread,
} }
} }
struct entity *CameraFollowingEntity = CameraFollowingEntity =
GetEntity(GameState, GameState->CameraFollowingEntityIndex); GetEntity(GameState, GameState->CameraFollowingEntityIndex);
if(CameraFollowingEntity) { if(CameraFollowingEntity) {
struct tile_map_difference Diff;
GameState->CameraP.AbsTileZ = CameraFollowingEntity->P.AbsTileZ; GameState->CameraP.AbsTileZ = CameraFollowingEntity->P.AbsTileZ;
struct tile_map_difference Diff = Diff = SubtractInFloat(TileMap, &CameraFollowingEntity->P,
SubtractInFloat(TileMap, &CameraFollowingEntity->P, &GameState->CameraP);
&GameState->CameraP);
if(Diff.dXY.X > (9.0f*TileMap->TileSideInMeters)) { if(Diff.dXY.X > (9.0f*TileMap->TileSideInMeters)) {
GameState->CameraP.AbsTileX += 17; GameState->CameraP.AbsTileX += 17;
} }
@@ -758,11 +836,11 @@ void UpdateAndRender(struct thread_context *Thread,
DrawBitmap(Buffer, &GameState->Backdrop, 0.0f, 0.0f, 0, 0); DrawBitmap(Buffer, &GameState->Backdrop, 0.0f, 0.0f, 0, 0);
float ScreenCenterX = 0.5f * (float)Buffer->Width; ScreenCenterX = 0.5f * (float)Buffer->Width;
float ScreenCenterY = 0.5f * (float)Buffer->Height; ScreenCenterY = 0.5f * (float)Buffer->Height;
for(int RelRow = -10; RelRow < 10; RelRow++) { for(RelRow = -10; RelRow < 10; RelRow++) {
for(int RelColumn = -20; RelColumn < 20; RelColumn++) { for(RelColumn = -20; RelColumn < 20; RelColumn++) {
unsigned int Column = GameState->CameraP.AbsTileX + RelColumn; unsigned int Column = GameState->CameraP.AbsTileX + RelColumn;
unsigned int Row = GameState->CameraP.AbsTileY + RelRow; unsigned int Row = GameState->CameraP.AbsTileY + RelRow;
@@ -770,7 +848,12 @@ void UpdateAndRender(struct thread_context *Thread,
GameState->CameraP.AbsTileZ); GameState->CameraP.AbsTileZ);
if(TileID > 1) { if(TileID > 1) {
struct v2 TileSide, Center;
struct v2 Min, Max;
float Gray = 0.5f; float Gray = 0.5f;
if(TileID == 2) { if(TileID == 2) {
Gray = 1.0f; Gray = 1.0f;
} }
@@ -785,48 +868,58 @@ void UpdateAndRender(struct thread_context *Thread,
Gray = 0.0f; Gray = 0.0f;
} }
struct v2 TileSide = { 0.5f*(float)TileSideInPixels, TileSide.X = 0.5f*(float)TileSideInPixels;
0.5f*(float)TileSideInPixels }; TileSide.Y = 0.5f*(float)TileSideInPixels;
struct v2 Center = { ScreenCenterX - Center.X = ScreenCenterX -
MetersToPixels*GameState->CameraP.Offset.X + MetersToPixels*GameState->CameraP.Offset.X +
(float)RelColumn*(float)TileSideInPixels, (float)RelColumn*(float)TileSideInPixels;
ScreenCenterY + MetersToPixels * Center.Y = ScreenCenterY + MetersToPixels *
GameState->CameraP.Offset.Y - GameState->CameraP.Offset.Y -
(float)RelRow*(float)TileSideInPixels }; (float)RelRow*(float)TileSideInPixels;
struct v2 Min = V2Subtract(Center, TileSide); Min = V2Subtract(Center, TileSide);
struct v2 Max = V2Add(Center, TileSide); Max = V2Add(Center, TileSide);
DrawRectangle(Buffer, Min, Max, Gray, Gray, Gray); DrawRectangle(Buffer, Min, Max, Gray, Gray, Gray);
} }
} }
} }
struct entity *Entity = GameState->Entities; Entity = GameState->Entities;
for(unsigned int EntityIndex = 0;
for(EntityIndex = 0;
EntityIndex < GameState->EntityCount; EntityIndex < GameState->EntityCount;
EntityIndex++, Entity++) EntityIndex++, Entity++)
{ {
if(Entity->Exists) { if(Entity->Exists) {
struct tile_map_difference Diff = struct tile_map_difference Diff;
SubtractInFloat(TileMap, &Entity->P, &GameState->CameraP);
float PlayerR, PlayerG, PlayerB;
float PlayerGroundPointX, PlayerGroundPointY;
struct v2 PlayerLeftTop, PlayerWidthHeight;
struct hero_bitmaps *Bitmap;
Diff = SubtractInFloat(TileMap, &Entity->P, &GameState->CameraP);
PlayerR = 1.0f;
PlayerG = 0.0f;
PlayerB = 0.0f;
PlayerGroundPointX = ScreenCenterX + MetersToPixels*Diff.dXY.X;
PlayerGroundPointY = ScreenCenterY - MetersToPixels*Diff.dXY.Y;
PlayerLeftTop.X =
PlayerGroundPointX - 0.5f * MetersToPixels*Entity->Width;
PlayerLeftTop.Y =
PlayerGroundPointY - MetersToPixels*Entity->Height;
PlayerWidthHeight.X = Entity->Width;
PlayerWidthHeight.X = Entity->Height;
float PlayerR = 1.0f;
float PlayerG = 0.0f;
float PlayerB = 0.0f;
float PlayerGroundPointX =
ScreenCenterX + MetersToPixels*Diff.dXY.X;
float PlayerGroundPointY =
ScreenCenterY - MetersToPixels*Diff.dXY.Y;
struct v2 PlayerLeftTop =
{ PlayerGroundPointX - 0.5f * MetersToPixels*Entity->Width,
PlayerGroundPointY - MetersToPixels*Entity->Height };
struct v2 PlayerWidthHeight = { Entity->Width, Entity->Height };
DrawRectangle(Buffer, PlayerLeftTop, DrawRectangle(Buffer, PlayerLeftTop,
V2Add(PlayerLeftTop, V2Multiply(MetersToPixels, V2Add(PlayerLeftTop, V2Multiply(MetersToPixels,
PlayerWidthHeight)), PlayerWidthHeight)),
PlayerR, PlayerG, PlayerB); PlayerR, PlayerG, PlayerB);
struct hero_bitmaps *Bitmap = Bitmap = &GameState->HeroBitmaps[Entity->FacingDirection];
&GameState->HeroBitmaps[Entity->FacingDirection];
DrawBitmap(Buffer, &Bitmap->Torso, DrawBitmap(Buffer, &Bitmap->Torso,
PlayerGroundPointX, PlayerGroundPointY, PlayerGroundPointX, PlayerGroundPointY,
Bitmap->AlignX, Bitmap->AlignY); Bitmap->AlignX, Bitmap->AlignY);
+3 -3
View File
@@ -83,8 +83,8 @@ struct game_controller_input {
/* NOTE: All buttons must be added above this line. */ /* NOTE: All buttons must be added above this line. */
struct game_button_state Terminator; struct game_button_state Terminator;
}; } s;
}; } u;
}; };
struct game_input { struct game_input {
@@ -197,7 +197,7 @@ struct hero_bitmaps {
struct entity { struct entity {
int Exists; int Exists;
struct tile_map_position P; struct tile_map_position P;
struct v2 dP; // velocity struct v2 dP; /* velocity */
unsigned int FacingDirection; unsigned int FacingDirection;
float Height, Width; float Height, Width;
}; };
+1 -1
View File
@@ -5,7 +5,7 @@
math.h. */ math.h. */
#include <math.h> #include <math.h>
#include <string.h> // memset #include <string.h> /* memset */
float AbsoluteValue(float Real32) float AbsoluteValue(float Real32)
{ {
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef HANDMADE_MATH_H #ifndef HANDMADE_MATH_H
#define HANDMADE_MATH_H #define HANDMADE_MATH_H
// TODO: Make these static. /* TODO: Make these static. */
struct v2 { struct v2 {
float X, Y; float X, Y;
float E[2]; float E[2];
+17 -12
View File
@@ -41,12 +41,13 @@ GetTileValueUnchecked(struct tile_map *TileMap,
struct tile_chunk *TileChunk, struct tile_chunk *TileChunk,
unsigned int TileX, unsigned int TileY) unsigned int TileX, unsigned int TileY)
{ {
unsigned int TileChunkValue;
ASSERT(TileChunk); ASSERT(TileChunk);
ASSERT(TileX < TileMap->ChunkDim); ASSERT(TileX < TileMap->ChunkDim);
ASSERT(TileY < TileMap->ChunkDim); ASSERT(TileY < TileMap->ChunkDim);
unsigned int TileChunkValue = TileChunkValue = TileChunk->Tiles[TileY * TileMap->ChunkDim + TileX];
TileChunk->Tiles[TileY * TileMap->ChunkDim + TileX];
return TileChunkValue; return TileChunkValue;
} }
@@ -140,9 +141,10 @@ static void SetTileValue(struct memory_arena *Arena,
ASSERT(TileChunk); ASSERT(TileChunk);
if(!TileChunk->Tiles) { if(!TileChunk->Tiles) {
unsigned int TileCount = TileMap->ChunkDim*TileMap->ChunkDim; unsigned int TileCount = TileMap->ChunkDim*TileMap->ChunkDim;
unsigned int TileIndex;
TileChunk->Tiles = PUSH_ARRAY(Arena, TileCount, unsigned int); TileChunk->Tiles = PUSH_ARRAY(Arena, TileCount, unsigned int);
for(unsigned int TileIndex = 0; for(TileIndex = 0;
TileIndex < TileCount; TileIndex < TileCount;
TileIndex++) TileIndex++)
{ {
@@ -154,15 +156,13 @@ static void SetTileValue(struct memory_arena *Arena,
ChunkPos.RelTileY, TileValue); ChunkPos.RelTileY, TileValue);
} }
// /* TODO: Do these belong more in a "positioning" or "geometry" file? */
// TODO: Do these belong more in a "positioning" or "geometry" file?
//
static void CannonicalizeCoord(struct tile_map *TileMap, unsigned int *Tile, static void CannonicalizeCoord(struct tile_map *TileMap, unsigned int *Tile,
float *TileRel) float *TileRel)
{ {
// NOTE: The world is assumed to be toroidal topology. If you step off /* NOTE: The world is assumed to be toroidal topology. If you step off
// one end, you come back on the other. * one end, you come back on the other.*/
int Offset = RoundFloatToInt(*TileRel / TileMap->TileSideInMeters); int Offset = RoundFloatToInt(*TileRel / TileMap->TileSideInMeters);
*Tile += Offset; *Tile += Offset;
*TileRel -= (float)Offset * TileMap->TileSideInMeters; *TileRel -= (float)Offset * TileMap->TileSideInMeters;
@@ -198,15 +198,20 @@ SubtractInFloat(struct tile_map *TileMap,
{ {
struct tile_map_difference Result; struct tile_map_difference Result;
struct v2 dTileXY = { ((float)A->AbsTileX - (float)B->AbsTileX), struct v2 dTileXY;
((float)A->AbsTileY - (float)B->AbsTileY) };
float dTileZ = (float)A->AbsTileZ - (float)B->AbsTileZ; float dTileZ;
dTileXY.X = (float)A->AbsTileX - (float)B->AbsTileX;
dTileXY.Y = (float)A->AbsTileY - (float)B->AbsTileY;
dTileZ = (float)A->AbsTileZ - (float)B->AbsTileZ;
Result.dXY = V2Add(V2Multiply(TileMap->TileSideInMeters, Result.dXY = V2Add(V2Multiply(TileMap->TileSideInMeters,
dTileXY), dTileXY),
V2Subtract(A->Offset, B->Offset)); V2Subtract(A->Offset, B->Offset));
// TODO: Incomplete . . . /* TODO: Incomplete . . . */
Result.dZ = TileMap->TileSideInMeters*dTileZ; Result.dZ = TileMap->TileSideInMeters*dTileZ;
return Result; return Result;
+189 -116
View File
@@ -1,7 +1,6 @@
#include "core.h" #include "core.h"
// Remove SDL's entry point. #if OS_WINDOWS /* Remove SDL's entry point. */
#if OS_WINDOWS
#define SDL_MAIN_HANDLED #define SDL_MAIN_HANDLED
#endif #endif
@@ -35,7 +34,7 @@
/* NOTE: This is so it compiles on ARM. */ /* NOTE: This is so it compiles on ARM. */
#if ARCHITECTURE_X64 || ARCHITECTURE_X86 #if ARCHITECTURE_X64 || ARCHITECTURE_X86
#if OS_MACOS || OS_LINUX #if OS_MACOS || OS_LINUX
#include <x86intrin.h> // TODO: What is the equivalent on Windows? #include <x86intrin.h>
#endif #endif
#endif #endif
@@ -72,8 +71,12 @@ static int str_len(char *str)
static unsigned int SafeTruncateUInt64(unsigned long long Value) static unsigned int SafeTruncateUInt64(unsigned long long Value)
{ {
unsigned int Result;
ASSERT(Value <= 0xFFFFFFFF); ASSERT(Value <= 0xFFFFFFFF);
unsigned int Result = (unsigned int)Value;
Result = (unsigned int)Value;
return Result; return Result;
} }
@@ -81,14 +84,19 @@ struct debug_read_file_result
DEBUGPlatformReadEntireFile(struct thread_context *Thread, DEBUGPlatformReadEntireFile(struct thread_context *Thread,
const char *Filename) const char *Filename)
{ {
(void)Thread;
struct debug_read_file_result Result; struct debug_read_file_result Result;
SDL_RWops *FileHandle;
memset(&Result, 0, sizeof(Result)); memset(&Result, 0, sizeof(Result));
SDL_RWops *FileHandle = SDL_RWFromFile(Filename, "r"); FileHandle = SDL_RWFromFile(Filename, "r");
if(FileHandle) { if(FileHandle) {
long long FileSize = SDL_RWsize(FileHandle); long long FileSize;
unsigned int ObjectsRead;
FileSize = SDL_RWsize(FileHandle);
if(FileSize >= 0) { if(FileSize >= 0) {
Result.ContentsSize = SafeTruncateUInt64(FileSize); Result.ContentsSize = SafeTruncateUInt64(FileSize);
} else { } else {
@@ -104,7 +112,7 @@ DEBUGPlatformReadEntireFile(struct thread_context *Thread,
return Result; return Result;
} }
unsigned int ObjectsRead = SDL_RWread(FileHandle, ObjectsRead = SDL_RWread(FileHandle,
(void *)Result.Contents, Result.ContentsSize, 1); (void *)Result.Contents, Result.ContentsSize, 1);
if(ObjectsRead == 0) { if(ObjectsRead == 0) {
free(Result.Contents); free(Result.Contents);
@@ -225,13 +233,15 @@ static void
SDLResizeTexture(struct offscreen_buffer *Buffer, SDLResizeTexture(struct offscreen_buffer *Buffer,
SDL_Renderer *Renderer, int Width, int Height) SDL_Renderer *Renderer, int Width, int Height)
{ {
int BytesPerPixel;
if(Buffer->Texture) if(Buffer->Texture)
SDL_DestroyTexture(Buffer->Texture); SDL_DestroyTexture(Buffer->Texture);
if(Buffer->Memory) if(Buffer->Memory)
free(Buffer->Memory); free(Buffer->Memory);
int BytesPerPixel = 4; BytesPerPixel = 4;
Buffer->Texture = SDL_CreateTexture(Renderer, Buffer->Texture = SDL_CreateTexture(Renderer,
SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_ARGB8888,
@@ -248,8 +258,12 @@ static void SDLDisplayBufferInWindow(struct offscreen_buffer *Buffer,
SDL_Window *Window, SDL_Window *Window,
SDL_Renderer *Renderer) SDL_Renderer *Renderer)
{ {
int OffsetX = 10; int OffsetX, OffsetY;
int OffsetY = 10;
struct sdl_window_size WinSize;
OffsetX = 10;
OffsetY = 10;
SDL_SetRenderDrawColor(Renderer, 0, 0, 0, 255); SDL_SetRenderDrawColor(Renderer, 0, 0, 0, 255);
SDL_RenderClear(Renderer); SDL_RenderClear(Renderer);
@@ -261,17 +275,23 @@ static void SDLDisplayBufferInWindow(struct 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); */
struct sdl_window_size WinSize = SDLGetBorderedWindowSize(Window); WinSize = SDLGetBorderedWindowSize(Window);
if(WinSize.Width >= Buffer->Width*2 && if(WinSize.Width >= Buffer->Width*2 &&
WinSize.Height >= Buffer->Height*2) WinSize.Height >= Buffer->Height*2)
{ {
SDL_Rect dest_rect = SDL_Rect dest_rect;
{ OffsetX, OffsetY, Buffer->Width*2, Buffer->Height*2 }; dest_rect.x = OffsetX;
dest_rect.y = OffsetY;
dest_rect.w = Buffer->Width*2;
dest_rect.h = Buffer->Height*2;
SDL_RenderCopy(Renderer, Buffer->Texture, 0, SDL_RenderCopy(Renderer, Buffer->Texture, 0,
(const SDL_Rect *)(&dest_rect)); (const SDL_Rect *)(&dest_rect));
} else { } else {
SDL_Rect dest_rect = SDL_Rect dest_rect;
{ OffsetX, OffsetY, RESOLUTION_WIDTH, RESOLUTION_HEIGHT }; dest_rect.x = OffsetX;
dest_rect.y = OffsetY;
dest_rect.w = RESOLUTION_WIDTH;
dest_rect.h = RESOLUTION_HEIGHT;
SDL_RenderCopy(Renderer, Buffer->Texture, 0, SDL_RenderCopy(Renderer, Buffer->Texture, 0,
(const SDL_Rect *)(&dest_rect)); (const SDL_Rect *)(&dest_rect));
} }
@@ -282,7 +302,9 @@ static void SDLInitControllers()
{ {
int MaxJoysticks = SDL_NumJoysticks(); int MaxJoysticks = SDL_NumJoysticks();
int ControllerIndex = 0; int ControllerIndex = 0;
for(int JoystickIndex = 0; JoystickIndex < MaxJoysticks; JoystickIndex++)
int JoystickIndex;
for(JoystickIndex = 0; JoystickIndex < MaxJoysticks; JoystickIndex++)
{ {
if(!SDL_IsGameController(JoystickIndex)) if(!SDL_IsGameController(JoystickIndex))
continue; continue;
@@ -460,40 +482,40 @@ static void SDLProcessMessages(struct sdl_state *SDLState,
if(Event.key.repeat == 0) { if(Event.key.repeat == 0) {
if(KeyCode == SDLK_w) { if(KeyCode == SDLK_w) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->MoveUp, IsDown); &KeyboardController->u.s.MoveUp, IsDown);
} else if(KeyCode == SDLK_s) { } else if(KeyCode == SDLK_s) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->MoveDown, IsDown); &KeyboardController->u.s.MoveDown, IsDown);
} else if(KeyCode == SDLK_a) { } else if(KeyCode == SDLK_a) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->MoveLeft, IsDown); &KeyboardController->u.s.MoveLeft, IsDown);
} else if(KeyCode == SDLK_d) { } else if(KeyCode == SDLK_d) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->MoveRight, IsDown); &KeyboardController->u.s.MoveRight, IsDown);
} else if(KeyCode == SDLK_q) { } else if(KeyCode == SDLK_q) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->LeftShoulder, IsDown); &KeyboardController->u.s.LeftShoulder, IsDown);
} else if(KeyCode == SDLK_e) { } else if(KeyCode == SDLK_e) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->RightShoulder, IsDown); &KeyboardController->u.s.RightShoulder, IsDown);
} else if(KeyCode == SDLK_UP) { } else if(KeyCode == SDLK_UP) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->ActionUp, IsDown); &KeyboardController->u.s.ActionUp, IsDown);
} else if(KeyCode == SDLK_DOWN) { } else if(KeyCode == SDLK_DOWN) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->ActionDown, IsDown); &KeyboardController->u.s.ActionDown, IsDown);
} else if(KeyCode == SDLK_LEFT) { } else if(KeyCode == SDLK_LEFT) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->ActionLeft, IsDown); &KeyboardController->u.s.ActionLeft, IsDown);
} else if(KeyCode == SDLK_RIGHT) { } else if(KeyCode == SDLK_RIGHT) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->ActionRight, IsDown); &KeyboardController->u.s.ActionRight, IsDown);
} else if(KeyCode == SDLK_ESCAPE) { } else if(KeyCode == SDLK_ESCAPE) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->Back, IsDown); &KeyboardController->u.s.Back, IsDown);
} else if(KeyCode == SDLK_SPACE) { } else if(KeyCode == SDLK_SPACE) {
SDLProcessKeyboardMessage( SDLProcessKeyboardMessage(
&KeyboardController->Start, IsDown); &KeyboardController->u.s.Start, IsDown);
} }
} }
@@ -689,10 +711,6 @@ void GetExecutablePath(char *path, size_t path_size)
static void SDLGetEXEDirPath(char *path, size_t path_size) static void SDLGetEXEDirPath(char *path, size_t path_size)
{ {
GetExecutablePath(path, path_size);
unsigned int len = str_len(path);
unsigned int i = len;
#if OS_MACOS || OS_LINUX #if OS_MACOS || OS_LINUX
char delimeter = '/'; char delimeter = '/';
#elif OS_WINDOWS #elif OS_WINDOWS
@@ -701,6 +719,12 @@ static void SDLGetEXEDirPath(char *path, size_t path_size)
#error Unknown OS: OS uses forward or backward slashes for paths? #error Unknown OS: OS uses forward or backward slashes for paths?
#endif #endif
unsigned int len, i;
GetExecutablePath(path, path_size);
len = str_len(path);
i = len;
while(path[i] != delimeter || i == 0) { while(path[i] != delimeter || i == 0) {
i--; i--;
} }
@@ -722,6 +746,9 @@ U64 __rdtsc()
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct sdl_state SDLState; struct sdl_state SDLState;
SDL_Window *Window;
memset(&SDLState, 0, sizeof(SDLState)); memset(&SDLState, 0, sizeof(SDLState));
SDLGetEXEDirPath(SDLState.EXEDirPath, sizeof(SDLState.EXEDirPath)); SDLGetEXEDirPath(SDLState.EXEDirPath, sizeof(SDLState.EXEDirPath));
@@ -738,19 +765,21 @@ int main(int argc, char *argv[])
* before everything is ready. */ * before everything is ready. */
/* TODO: SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, in non-debug /* TODO: SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, in non-debug
* build */ * build */
SDL_Window *Window = SDL_CreateWindow("Handmade Hero", Window = SDL_CreateWindow("Handmade Hero",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
RESOLUTION_WIDTH+20, RESOLUTION_HEIGHT+20, RESOLUTION_WIDTH+20, RESOLUTION_HEIGHT+20,
SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE/* | SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE/* |
SDL_WINDOW_ALWAYS_ON_TOP*/); SDL_WINDOW_ALWAYS_ON_TOP*/);
if(Window) { if(Window) {
SDL_DisplayMode display_mode;
SDL_Renderer *Renderer;
LastWindow = Window; LastWindow = Window;
SDL_DisplayMode display_mode;
SDL_GetCurrentDisplayMode(0, &display_mode); SDL_GetCurrentDisplayMode(0, &display_mode);
SDL_Renderer *Renderer = Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_PRESENTVSYNC);
SDL_CreateRenderer(Window, -1, SDL_RENDERER_PRESENTVSYNC);
/* NOTE: For future reference, the custom window bar should use /* NOTE: For future reference, the custom window bar should use
* SDL_SetWindowHitTest to define areas that will be used to drag * SDL_SetWindowHitTest to define areas that will be used to drag
@@ -764,11 +793,27 @@ int main(int argc, char *argv[])
/* SDL_RenderPresent(Renderer) is enough to display the window. */ /* SDL_RenderPresent(Renderer) is enough to display the window. */
if(Renderer) { if(Renderer) {
struct thread_context TempContext; struct thread_context TempContext;
SDL_Cursor *PointerCursor;
SDL_Rect UsableDisplayRect;
struct sdl_window_size CurrentWindowSize;
struct sdl_sound_output SoundOutput;
#if BUILD_DEBUG
void *BaseAddress = (void *)TB(2);
#else
void *BaseAddress = (void *)(0);
#endif
struct game_memory GameMemory;
memset(&TempContext, 0, sizeof(TempContext)); memset(&TempContext, 0, sizeof(TempContext));
/* TODO: Make it a global. */ /* TODO: Make it a global. */
SDL_Cursor *PointerCursor = PointerCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
SDL_SetCursor(PointerCursor); SDL_SetCursor(PointerCursor);
#if !BUILD_INTERNAL #if !BUILD_INTERNAL
if(SDL_ShowCursor(SDL_DISABLE) < 0) { if(SDL_ShowCursor(SDL_DISABLE) < 0) {
@@ -776,10 +821,8 @@ int main(int argc, char *argv[])
} }
#endif #endif
SDL_Rect UsableDisplayRect;
SDL_GetDisplayUsableBounds(0, &UsableDisplayRect); SDL_GetDisplayUsableBounds(0, &UsableDisplayRect);
struct sdl_window_size CurrentWindowSize = CurrentWindowSize = SDLGetBorderedWindowSize(Window);
SDLGetBorderedWindowSize(Window);
SDLSetBorderedWindowPosition(Window, SDLSetBorderedWindowPosition(Window,
(UsableDisplayRect.x + UsableDisplayRect.w - (UsableDisplayRect.x + UsableDisplayRect.w -
CurrentWindowSize.Width), CurrentWindowSize.Width),
@@ -795,7 +838,6 @@ int main(int argc, char *argv[])
SDLResizeTexture(&GlobalBackbuffer, Renderer, SDLResizeTexture(&GlobalBackbuffer, Renderer,
RESOLUTION_WIDTH, RESOLUTION_HEIGHT); RESOLUTION_WIDTH, RESOLUTION_HEIGHT);
struct sdl_sound_output SoundOutput;
memset(&SoundOutput, 0, sizeof(SoundOutput)); memset(&SoundOutput, 0, sizeof(SoundOutput));
SoundOutput.SamplesPerSecond = 48000; SoundOutput.SamplesPerSecond = 48000;
SoundOutput.BytesPerSample = sizeof(short) * 2; SoundOutput.BytesPerSample = sizeof(short) * 2;
@@ -815,14 +857,7 @@ int main(int argc, char *argv[])
/*SoundOutput.Samples = malloc(SoundOutput.SecondaryBufferSize);*/ /*SoundOutput.Samples = malloc(SoundOutput.SecondaryBufferSize);*/
/* NOTE: calloc auto clears to zero */ /* NOTE: calloc auto clears to zero */
/* SDLClearSoundBuffer(&SoundOutput); */ /* SDLClearSoundBuffer(&SoundOutput); */
#if BUILD_DEBUG
void *BaseAddress = (void *)TB(2);
#else
void *BaseAddress = (void *)(0);
#endif
struct game_memory GameMemory;
memset(&GameMemory, 0, sizeof(GameMemory)); memset(&GameMemory, 0, sizeof(GameMemory));
GameMemory.PermanentStorageSize = MB(64); GameMemory.PermanentStorageSize = MB(64);
GameMemory.TransientStorageSize = GB(1); GameMemory.TransientStorageSize = GB(1);
@@ -863,24 +898,65 @@ int main(int argc, char *argv[])
unsigned long long LastCounter; unsigned long long LastCounter;
unsigned long long LastCycleCount; unsigned long long LastCycleCount;
int MonitorRefreshHz = SDLGetWindowRefreshRate(Window); int MonitorRefreshHz, GameUpdateHz;
/*GameUpdateHz = MonitorRefreshHz;*/ float TargetSecondsPerFrame;
int GameUpdateHz = 30; /* NOTE: Temporarily target 30 FPS. */
float TargetSecondsPerFrame = 1.0f / (float)GameUpdateHz;
struct game_input *NewInput = &Input[0]; struct game_input *NewInput, *OldInput;
struct game_input *OldInput = &Input[1];
struct sdl_game_code Game;
unsigned long long FPSLastCounter;
MonitorRefreshHz = SDLGetWindowRefreshRate(Window);
/*GameUpdateHz = MonitorRefreshHz;*/
GameUpdateHz = 30; /* NOTE: Temporarily target 30 FPS. */
TargetSecondsPerFrame = 1.0f / (float)GameUpdateHz;
NewInput = &Input[0];
OldInput = &Input[1];
memset(Input, 0, sizeof(Input)); memset(Input, 0, sizeof(Input));
GlobalPerfCountFrequency = SDL_GetPerformanceFrequency(); GlobalPerfCountFrequency = SDL_GetPerformanceFrequency();
struct sdl_game_code Game = SDLLoadGameCode(SDLState.DLLPath); Game = SDLLoadGameCode(SDLState.DLLPath);
SDL_ShowWindow(Window); // Everything is ready; display the window. SDL_ShowWindow(Window); // Everything is ready; display the window.
unsigned long long FPSLastCounter = SDLGetWallClock(); FPSLastCounter = SDLGetWallClock();
while(GlobalRunning) { while(GlobalRunning) {
unsigned int NewDLLWriteTime;
int MouseX, MouseY;
int WindowX, WindowY;
unsigned int SDLMouseButtons;
struct game_controller_input *OldKeyboardController,
*NewKeyboardController;
struct game_controller_input ZeroController;
unsigned int ButtonIndex;
unsigned int ControllerIndex;
int TargetQueueBytes;
int BytesToWrite;
struct game_sound_output_buffer SoundBuffer;
struct thread_context Context;
struct game_offscreen_buffer Buffer;
unsigned long long WorkCounter;
float WorkSecondsElapsed;
float SecondsElapsedForFrame;
unsigned long long EndCounter;
float MSPerFrame;
float FPS;
NewInput->dtForFrame = TargetSecondsPerFrame; NewInput->dtForFrame = TargetSecondsPerFrame;
LastCounter = SDLGetWallClock(); LastCounter = SDLGetWallClock();
@@ -891,24 +967,20 @@ int main(int argc, char *argv[])
* on MacOS ARM; I have not checked MacOS x64. */ * on MacOS ARM; I have not checked MacOS x64. */
LastCycleCount = __rdtsc(); LastCycleCount = __rdtsc();
unsigned int NewDLLWriteTime = NewDLLWriteTime = GetLastWriteTime(SDLState.DLLPath);
GetLastWriteTime(SDLState.DLLPath);
if(NewDLLWriteTime > Game.DLLLastWriteTime) { if(NewDLLWriteTime > Game.DLLLastWriteTime) {
SDLUnloadGameCode(&Game); SDLUnloadGameCode(&Game);
Game = SDLLoadGameCode(SDLState.DLLPath); Game = SDLLoadGameCode(SDLState.DLLPath);
} }
int MouseX, MouseY;
SDL_GetGlobalMouseState(&MouseX, &MouseY); SDL_GetGlobalMouseState(&MouseX, &MouseY);
int WindowX, WindowY;
SDL_GetWindowPosition(Window, &WindowX, &WindowY); SDL_GetWindowPosition(Window, &WindowX, &WindowY);
NewInput->MouseX = MouseX - WindowX; NewInput->MouseX = MouseX - WindowX;
NewInput->MouseY = MouseY - WindowY; NewInput->MouseY = MouseY - WindowY;
unsigned int SDLMouseButtons = SDLMouseButtons = SDL_GetMouseState(NULL, NULL);
SDL_GetMouseState(NULL, NULL);
NewInput->MouseZ = 0; /* TODO: Support mouse wheel? */ NewInput->MouseZ = 0; /* TODO: Support mouse wheel? */
SDLProcessKeyboardMessage(&(NewInput->MouseButtons[0]), SDLProcessKeyboardMessage(&(NewInput->MouseButtons[0]),
SDL_BUTTON_LMASK & SDLMouseButtons); SDL_BUTTON_LMASK & SDLMouseButtons);
@@ -923,49 +995,53 @@ int main(int argc, char *argv[])
SDLProcessKeyboardMessage(&(NewInput->MouseButtons[4]), SDLProcessKeyboardMessage(&(NewInput->MouseButtons[4]),
SDL_BUTTON_X2MASK & SDLMouseButtons); SDL_BUTTON_X2MASK & SDLMouseButtons);
struct game_controller_input *OldKeyboardController = OldKeyboardController = GetController(OldInput, 0);
GetController(OldInput, 0); NewKeyboardController = GetController(NewInput, 0);
struct game_controller_input *NewKeyboardController =
GetController(NewInput, 0);
struct game_controller_input ZeroController;
memset(&ZeroController, 0, sizeof(ZeroController)); memset(&ZeroController, 0, sizeof(ZeroController));
*NewKeyboardController = ZeroController; *NewKeyboardController = ZeroController;
NewKeyboardController->IsConnected = 1; NewKeyboardController->IsConnected = 1;
for(unsigned int ButtonIndex = 0; for(ButtonIndex = 0;
ButtonIndex < ButtonIndex <
ARRAY_SIZE(NewKeyboardController->Buttons); ARRAY_SIZE(NewKeyboardController->u.Buttons);
ButtonIndex++) ButtonIndex++)
{ {
NewKeyboardController-> NewKeyboardController->u.
Buttons[ButtonIndex].EndedDown = Buttons[ButtonIndex].EndedDown =
OldKeyboardController-> OldKeyboardController->u.
Buttons[ButtonIndex].EndedDown; Buttons[ButtonIndex].EndedDown;
} }
SDLProcessMessages(&SDLState, NewKeyboardController); SDLProcessMessages(&SDLState, NewKeyboardController);
for(unsigned int ControllerIndex = 0; for(ControllerIndex = 0;
ControllerIndex < MAX_CONTROLLERS; ControllerIndex < MAX_CONTROLLERS;
ControllerIndex++) ControllerIndex++)
{ {
struct game_controller_input *OldController = struct game_controller_input *OldController,
*NewController;
OldController =
GetController(OldInput, ControllerIndex+1); GetController(OldInput, ControllerIndex+1);
struct game_controller_input *NewController = NewController =
GetController(NewInput, ControllerIndex+1); GetController(NewInput, ControllerIndex+1);
if(ControllerHandles[ControllerIndex] != 0 && if(ControllerHandles[ControllerIndex] != 0 &&
SDL_GameControllerGetAttached( SDL_GameControllerGetAttached(
ControllerHandles[ControllerIndex])) ControllerHandles[ControllerIndex]))
{ {
short StickX, StickY;
float Threshold;
NewController->IsAnalog = NewController->IsAnalog =
OldController->IsAnalog; OldController->IsAnalog;
NewController->IsConnected = 1; NewController->IsConnected = 1;
short StickX = SDL_GameControllerGetAxis( StickX = SDL_GameControllerGetAxis(
ControllerHandles[ControllerIndex], ControllerHandles[ControllerIndex],
SDL_CONTROLLER_AXIS_LEFTX); SDL_CONTROLLER_AXIS_LEFTX);
short StickY = SDL_GameControllerGetAxis( StickY = SDL_GameControllerGetAxis(
ControllerHandles[ControllerIndex], ControllerHandles[ControllerIndex],
SDL_CONTROLLER_AXIS_LEFTY); SDL_CONTROLLER_AXIS_LEFTY);
@@ -1015,94 +1091,91 @@ int main(int argc, char *argv[])
NewController->IsAnalog = 0; NewController->IsAnalog = 0;
} }
float Threshold = 0.5f; Threshold = 0.5f;
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[(NewController-> ControllerHandles[(NewController->
StickAverageY < -Threshold) ? 1 : 0], StickAverageY < -Threshold) ? 1 : 0],
&OldController->MoveUp, &OldController->u.s.MoveUp,
SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_BUTTON_A,
&NewController->MoveUp); &NewController->u.s.MoveUp);
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[(NewController-> ControllerHandles[(NewController->
StickAverageY > Threshold) ? 1 : 0], StickAverageY > Threshold) ? 1 : 0],
&OldController->MoveDown, &OldController->u.s.MoveDown,
SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_BUTTON_A,
&NewController->MoveDown); &NewController->u.s.MoveDown);
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[(NewController-> ControllerHandles[(NewController->
StickAverageX < -Threshold) ? 1 : 0], StickAverageX < -Threshold) ? 1 : 0],
&OldController->MoveLeft, &OldController->u.s.MoveLeft,
SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_BUTTON_A,
&NewController->MoveLeft); &NewController->u.s.MoveLeft);
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[(NewController-> ControllerHandles[(NewController->
StickAverageX > Threshold) ? 1 : 0], StickAverageX > Threshold) ? 1 : 0],
&OldController->MoveRight, &OldController->u.s.MoveRight,
SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_BUTTON_A,
&NewController->MoveRight); &NewController->u.s.MoveRight);
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[ControllerIndex], ControllerHandles[ControllerIndex],
&OldController->ActionDown, &OldController->u.s.ActionDown,
SDL_CONTROLLER_BUTTON_A, SDL_CONTROLLER_BUTTON_A,
&NewController->ActionDown); &NewController->u.s.ActionDown);
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[ControllerIndex], ControllerHandles[ControllerIndex],
&OldController->ActionRight, &OldController->u.s.ActionRight,
SDL_CONTROLLER_BUTTON_B, SDL_CONTROLLER_BUTTON_B,
&NewController->ActionRight); &NewController->u.s.ActionRight);
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[ControllerIndex], ControllerHandles[ControllerIndex],
&OldController->ActionLeft, &OldController->u.s.ActionLeft,
SDL_CONTROLLER_BUTTON_X, SDL_CONTROLLER_BUTTON_X,
&NewController->ActionLeft); &NewController->u.s.ActionLeft);
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[ControllerIndex], ControllerHandles[ControllerIndex],
&OldController->ActionUp, &OldController->u.s.ActionUp,
SDL_CONTROLLER_BUTTON_Y, SDL_CONTROLLER_BUTTON_Y,
&NewController->ActionUp); &NewController->u.s.ActionUp);
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[ControllerIndex], ControllerHandles[ControllerIndex],
&OldController->LeftShoulder, &OldController->u.s.LeftShoulder,
SDL_CONTROLLER_BUTTON_LEFTSHOULDER, SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
&NewController->LeftShoulder); &NewController->u.s.LeftShoulder);
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[ControllerIndex], ControllerHandles[ControllerIndex],
&OldController->RightShoulder, &OldController->u.s.RightShoulder,
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
&NewController->RightShoulder); &NewController->u.s.RightShoulder);
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[ControllerIndex], ControllerHandles[ControllerIndex],
&OldController->Start, &OldController->u.s.Start,
SDL_CONTROLLER_BUTTON_START, SDL_CONTROLLER_BUTTON_START,
&NewController->Start); &NewController->u.s.Start);
SDLProcessInputDigitalButton( SDLProcessInputDigitalButton(
ControllerHandles[ControllerIndex], ControllerHandles[ControllerIndex],
&OldController->Back, &OldController->u.s.Back,
SDL_CONTROLLER_BUTTON_BACK, SDL_CONTROLLER_BUTTON_BACK,
&NewController->Back); &NewController->u.s.Back);
} else { } else {
/* NOTE: This controller is not plugged in. */ /* NOTE: This controller is not plugged in. */
NewController->IsConnected = 0; NewController->IsConnected = 0;
} }
} }
int TargetQueueBytes = SoundOutput.LatencySampleCount * TargetQueueBytes = SoundOutput.LatencySampleCount *
SoundOutput.BytesPerSample; SoundOutput.BytesPerSample;
int BytesToWrite = BytesToWrite =
TargetQueueBytes - SDL_GetQueuedAudioSize(1); TargetQueueBytes - SDL_GetQueuedAudioSize(1);
struct game_sound_output_buffer SoundBuffer;
SoundBuffer.SamplesPerSecond = SoundBuffer.SamplesPerSecond =
SoundOutput.SamplesPerSecond; SoundOutput.SamplesPerSecond;
SoundBuffer.SampleCount = SoundBuffer.SampleCount =
BytesToWrite / SoundOutput.BytesPerSample; BytesToWrite / SoundOutput.BytesPerSample;
SoundBuffer.Samples = (short *)SoundOutput.Samples; SoundBuffer.Samples = (short *)SoundOutput.Samples;
struct thread_context Context;
memset(&Context, 0, sizeof(Context)); memset(&Context, 0, sizeof(Context));
struct game_offscreen_buffer Buffer;
Buffer.Memory = GlobalBackbuffer.Memory; Buffer.Memory = GlobalBackbuffer.Memory;
Buffer.Width = GlobalBackbuffer.Width; Buffer.Width = GlobalBackbuffer.Width;
Buffer.Height = GlobalBackbuffer.Height; Buffer.Height = GlobalBackbuffer.Height;
@@ -1117,11 +1190,11 @@ int main(int argc, char *argv[])
SDLFillSoundBuffer(&SoundOutput, BytesToWrite); SDLFillSoundBuffer(&SoundOutput, BytesToWrite);
unsigned long long WorkCounter = SDLGetWallClock(); WorkCounter = SDLGetWallClock();
float WorkSecondsElapsed = WorkSecondsElapsed =
SDLGetSecondsElapsed(LastCounter, WorkCounter); SDLGetSecondsElapsed(LastCounter, WorkCounter);
float SecondsElapsedForFrame = WorkSecondsElapsed; SecondsElapsedForFrame = WorkSecondsElapsed;
if(SecondsElapsedForFrame < TargetSecondsPerFrame) { if(SecondsElapsedForFrame < TargetSecondsPerFrame) {
while(SecondsElapsedForFrame < TargetSecondsPerFrame) while(SecondsElapsedForFrame < TargetSecondsPerFrame)
{ {
@@ -1141,15 +1214,15 @@ int main(int argc, char *argv[])
/* TODO: Logging. */ /* TODO: Logging. */
} }
unsigned long long EndCounter = SDLGetWallClock(); EndCounter = SDLGetWallClock();
SDLDisplayBufferInWindow(&GlobalBackbuffer, Window, SDLDisplayBufferInWindow(&GlobalBackbuffer, Window,
Renderer); Renderer);
float MSPerFrame = MSPerFrame =
1000.0f * 1000.0f *
SDLGetSecondsElapsed(LastCounter, EndCounter); SDLGetSecondsElapsed(LastCounter, EndCounter);
float FPS = 1000.0f / MSPerFrame; FPS = 1000.0f / MSPerFrame;
LastCounter = EndCounter; LastCounter = EndCounter;