Day 36. 25:01. Need to draw assets.
This commit is contained in:
@@ -15,18 +15,19 @@ endif
|
||||
CC = clang
|
||||
|
||||
UFLAGS =
|
||||
# NOTE: We comply with C89 (plain C), however the standard has no 64-bit
|
||||
# support. But, every compiler at that time supported long long,
|
||||
# hence we ignore the incompliance in our code.
|
||||
# NOTE: We allow function declrations with specifying void
|
||||
# (ex, void test() is allowed).
|
||||
FLAGS = -ansi -pedantic -pedantic-errors -Wno-long-long \
|
||||
-Wno-overlength-strings -Wincompatible-pointer-types \
|
||||
-Wint-conversion -Wimplicit-int-float-conversion -Wformat \
|
||||
-Wno-strict-prototypes -Wall -Wextra -fno-caret-diagnostics \
|
||||
-fno-show-column -Wno-missing-field-initializers \
|
||||
# NOTE: This project's code bases itself on C89 (plain C) standard, however
|
||||
# allowing a few convenient features of newer standards. Mid-scope
|
||||
# variable declarations, comments that begin with '//', long long,
|
||||
# designated initializers, compound literals, and anonymous structures
|
||||
# are allowed as they are convenient. Everything else that has come out
|
||||
# of modern standards is pretty much destructive and should not be used.
|
||||
FLAGS = -Wall -Wextra \
|
||||
-Wincompatible-pointer-types \
|
||||
-Wint-conversion -Wimplicit-int-float-conversion -Wformat \
|
||||
-Wno-strict-prototypes -Wno-missing-field-initializers \
|
||||
-Wno-unused-function -Wno-unused-parameter -Wno-unused-variable \
|
||||
-Wno-unused-but-set-variable
|
||||
-Wno-unused-but-set-variable \
|
||||
-fno-caret-diagnostics -fno-show-column
|
||||
|
||||
ifeq ($(DETECTED_OS),macos)
|
||||
UFLAGS = -glldb
|
||||
|
||||
+93
-118
@@ -5,7 +5,7 @@
|
||||
#include "handmade_intrinsics.h"
|
||||
#include "handmade_random.h"
|
||||
#include "handmade_tile.h"
|
||||
#include "handmade_tile.cpp"
|
||||
#include "handmade_tile.c"
|
||||
|
||||
#include <string.h> /* memset */
|
||||
|
||||
@@ -44,12 +44,10 @@ static void GameOutputSound(game_state *GameState,
|
||||
|
||||
static void ClearBackground(game_offscreen_buffer *Buffer)
|
||||
{
|
||||
S32 Width, Height, X;
|
||||
S32 Width = Buffer->Width;
|
||||
S32 Height = Buffer->Height;
|
||||
|
||||
Width = Buffer->Width;
|
||||
Height = Buffer->Height;
|
||||
|
||||
for(X = 0; X < Width * Height; X++) {
|
||||
for(S32 X = 0; X < Width * Height; X++) {
|
||||
U32 *Pixel = &((U32 *)Buffer->Memory)[X];
|
||||
*Pixel = 0xFFFFFF;
|
||||
}
|
||||
@@ -68,10 +66,6 @@ static void DrawRectangle(game_offscreen_buffer *Buffer,
|
||||
S32 Width = Buffer->Width;
|
||||
S32 Height = Buffer->Height;
|
||||
|
||||
U8 *Row;
|
||||
S32 Y, X;
|
||||
U32 Color;
|
||||
|
||||
if(MinX < 0)
|
||||
MinX = 0;
|
||||
if(MinY < 0)
|
||||
@@ -82,15 +76,15 @@ static void DrawRectangle(game_offscreen_buffer *Buffer,
|
||||
if(MaxY > Height)
|
||||
MaxY = Height;
|
||||
|
||||
Color = (U32)((RoundF32toS32(R * 255.0f) << 16) |
|
||||
(RoundF32toS32(G * 255.0f) << 8) |
|
||||
(RoundF32toS32(B * 255.0f) << 0));
|
||||
U32 Color = (U32)((RoundF32toS32(R * 255.0f) << 16) |
|
||||
(RoundF32toS32(G * 255.0f) << 8) |
|
||||
(RoundF32toS32(B * 255.0f) << 0));
|
||||
|
||||
Row = ((U8 *)Buffer->Memory + MinX*Buffer->BytesPerPixel +
|
||||
MinY*Buffer->Pitch);
|
||||
for(Y = MinY; Y < MaxY; Y++) {
|
||||
U8 *Row = ((U8 *)Buffer->Memory + MinX*Buffer->BytesPerPixel +
|
||||
MinY*Buffer->Pitch);
|
||||
for(S32 Y = MinY; Y < MaxY; Y++) {
|
||||
U32 *Pixel = (U32 *)Row;
|
||||
for(X = MinX; X < MaxX; X++) {
|
||||
for(S32 X = MinX; X < MaxX; X++) {
|
||||
*(U32 *)Pixel = Color;
|
||||
Pixel++;
|
||||
}
|
||||
@@ -102,60 +96,36 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
game_input *Input, game_offscreen_buffer *Buffer,
|
||||
game_sound_output_buffer *SoundBuffer)
|
||||
{
|
||||
#define TILEMAP_COUNT_X 256
|
||||
#define TILEMAP_COUNT_Y 256
|
||||
|
||||
game_state *GameState;
|
||||
U32 ControllerIndex;
|
||||
|
||||
F32 PlayerR, PlayerG, PlayerB,
|
||||
PlayerWidth, PlayerHeight,
|
||||
PlayerLeft, PlayerTop;
|
||||
F32 ScreenCenterX, ScreenCenterY;
|
||||
|
||||
world *World;
|
||||
tile_map *TileMap;
|
||||
|
||||
S32 TileSideInPixels;
|
||||
F32 MetersToPixels;
|
||||
|
||||
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);
|
||||
|
||||
PlayerHeight = 1.4f;
|
||||
PlayerWidth = 0.75f * PlayerHeight;
|
||||
#define TILEMAP_COUNT_X 256
|
||||
#define TILEMAP_COUNT_Y 256
|
||||
|
||||
game_state *GameState;
|
||||
|
||||
F32 PlayerHeight = 1.4f;
|
||||
F32 PlayerWidth = 0.75f * PlayerHeight;
|
||||
|
||||
GameState = (game_state *)Memory->PermanentStorage;
|
||||
if(!Memory->IsInitialized) {
|
||||
U32 TilesPerWidth, TilesPerHeight;
|
||||
|
||||
U32 ScreenX, ScreenY;
|
||||
U32 ScreenIndex;
|
||||
|
||||
tile_map *TileMap;
|
||||
world *World;
|
||||
|
||||
U32 AbsTileZ;
|
||||
B32 DoorTop, DoorBottom, DoorLeft, DoorRight, DoorUp, DoorDown;
|
||||
|
||||
U32 RandomNumberIndex;
|
||||
|
||||
GameState->PlayerP.AbsTileX = 2;
|
||||
GameState->PlayerP.AbsTileY = 3;
|
||||
GameState->PlayerP.TileRelX = 5.0f;
|
||||
GameState->PlayerP.TileRelY = 5.0f;
|
||||
GameState->PlayerP.OffsetX = 5.0f;
|
||||
GameState->PlayerP.OffsetY = 5.0f;
|
||||
|
||||
InitializeArena(&GameState->WorldArena,
|
||||
Memory->PermanentStorageSize - sizeof(game_state),
|
||||
(U8 *)Memory->PermanentStorage + sizeof(game_state));
|
||||
|
||||
GameState->World = PUSH_STRUCT(&GameState->WorldArena, world);
|
||||
World = GameState->World;
|
||||
world *World = GameState->World;
|
||||
World->TileMap = PUSH_STRUCT(&GameState->WorldArena, tile_map);
|
||||
|
||||
TileMap = World->TileMap;
|
||||
tile_map *TileMap = World->TileMap;
|
||||
|
||||
TileMap->ChunkShift = 4;
|
||||
TileMap->ChunkMask = (1 << TileMap->ChunkShift) - 1;
|
||||
@@ -174,34 +144,37 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
|
||||
TileMap->TileSideInMeters = 1.4f;
|
||||
|
||||
RandomNumberIndex = 0;
|
||||
U32 RandomNumberIndex = 0;
|
||||
|
||||
TilesPerWidth = 17;
|
||||
TilesPerHeight = 9;
|
||||
ScreenX = 0;
|
||||
ScreenY = 0;
|
||||
U32 TilesPerWidth = 17;
|
||||
U32 TilesPerHeight = 9;
|
||||
U32 ScreenX = 0;
|
||||
U32 ScreenY = 0;
|
||||
|
||||
AbsTileZ = 0;
|
||||
|
||||
DoorTop = FALSE;
|
||||
DoorBottom = FALSE;
|
||||
DoorLeft = FALSE;
|
||||
DoorRight = FALSE;
|
||||
DoorUp = FALSE;
|
||||
DoorDown = FALSE;
|
||||
for(ScreenIndex = 0; ScreenIndex < 100; ScreenIndex++) {
|
||||
/* TODO: Random number generator. */
|
||||
U32 TileX, TileY;
|
||||
U32 RandomChoice;
|
||||
U32 AbsTileZ = 0;
|
||||
|
||||
B32 DoorTop = FALSE;
|
||||
B32 DoorBottom = FALSE;
|
||||
B32 DoorLeft = FALSE;
|
||||
B32 DoorRight = FALSE;
|
||||
B32 DoorUp = FALSE;
|
||||
B32 DoorDown = FALSE;
|
||||
for(U32 ScreenIndex = 0; ScreenIndex < 100; ScreenIndex++) {
|
||||
ASSERT(RandomNumberIndex < ARRAY_SIZE(RandomNumberTable));
|
||||
|
||||
/* TODO: Random number generator. */
|
||||
U32 RandomChoice;
|
||||
if(DoorUp || DoorDown) {
|
||||
RandomChoice = RandomNumberTable[RandomNumberIndex++] % 2;
|
||||
} else {
|
||||
RandomChoice = RandomNumberTable[RandomNumberIndex++] % 3;
|
||||
}
|
||||
|
||||
B32 CreatedZDoor = FALSE;
|
||||
|
||||
if(RandomChoice == 2) {
|
||||
CreatedZDoor = TRUE;
|
||||
|
||||
if(AbsTileZ == 0) {
|
||||
DoorUp = TRUE;
|
||||
} else {
|
||||
@@ -213,8 +186,8 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
DoorTop = TRUE;
|
||||
}
|
||||
|
||||
for(TileY = 0; TileY < TilesPerHeight; TileY++) {
|
||||
for(TileX = 0; TileX < TilesPerWidth; TileX++) {
|
||||
for(U32 TileY = 0; TileY < TilesPerHeight; TileY++) {
|
||||
for(U32 TileX = 0; TileX < TilesPerWidth; TileX++) {
|
||||
U32 AbsTileX = ScreenX * TilesPerWidth + TileX;
|
||||
U32 AbsTileY = ScreenY * TilesPerHeight + TileY;
|
||||
|
||||
@@ -259,16 +232,12 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DoorLeft = DoorRight;
|
||||
DoorBottom = DoorTop;
|
||||
|
||||
if(DoorUp) {
|
||||
DoorDown = TRUE;
|
||||
DoorUp = FALSE;
|
||||
} else if (DoorDown) {
|
||||
DoorUp = TRUE;
|
||||
DoorDown = FALSE;
|
||||
if(CreatedZDoor) {
|
||||
DoorDown = !DoorDown;
|
||||
DoorUp = !DoorUp;
|
||||
} else {
|
||||
DoorUp = FALSE;
|
||||
DoorDown = FALSE;
|
||||
@@ -293,13 +262,13 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
Memory->IsInitialized = TRUE;
|
||||
}
|
||||
|
||||
World = GameState->World;
|
||||
TileMap = World->TileMap;
|
||||
world *World = GameState->World;
|
||||
tile_map *TileMap = World->TileMap;
|
||||
|
||||
TileSideInPixels = 60;
|
||||
MetersToPixels = (F32)TileSideInPixels / TileMap->TileSideInMeters;
|
||||
S32 TileSideInPixels = 60;
|
||||
F32 MetersToPixels = (F32)TileSideInPixels / TileMap->TileSideInMeters;
|
||||
|
||||
for(ControllerIndex = 0;
|
||||
for(U32 ControllerIndex = 0;
|
||||
ControllerIndex < ARRAY_SIZE(Input->Controllers);
|
||||
ControllerIndex++)
|
||||
{
|
||||
@@ -310,8 +279,6 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
F32 dPlayerX = 0.0f;
|
||||
F32 dPlayerY = 0.0f;
|
||||
|
||||
tile_map_position NewPlayerP, PlayerLeft, PlayerRight;
|
||||
|
||||
if(Controller->u.buttons.MoveUp.EndedDown) {
|
||||
dPlayerY = 1.0f;
|
||||
}
|
||||
@@ -325,48 +292,58 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
dPlayerX = 1.0f;
|
||||
}
|
||||
|
||||
{
|
||||
F32 PlayerSpeed = 2.0f;
|
||||
F32 PlayerSpeed = 2.0f;
|
||||
|
||||
if(Controller->u.buttons.ActionUp.EndedDown)
|
||||
PlayerSpeed = 10.0f;
|
||||
if(Controller->u.buttons.ActionUp.EndedDown)
|
||||
PlayerSpeed = 10.0f;
|
||||
|
||||
dPlayerX *= PlayerSpeed;
|
||||
dPlayerY *= PlayerSpeed;
|
||||
}
|
||||
dPlayerX *= PlayerSpeed;
|
||||
dPlayerY *= PlayerSpeed;
|
||||
|
||||
tile_map_position NewPlayerP;
|
||||
NewPlayerP = GameState->PlayerP;
|
||||
NewPlayerP.TileRelX += Input->dtForFrame*dPlayerX;
|
||||
NewPlayerP.TileRelY += Input->dtForFrame*dPlayerY;
|
||||
NewPlayerP.OffsetX += Input->dtForFrame*dPlayerX;
|
||||
NewPlayerP.OffsetY += Input->dtForFrame*dPlayerY;
|
||||
NewPlayerP = RecannonicalizePosition(TileMap, NewPlayerP);
|
||||
|
||||
tile_map_position PlayerLeft;
|
||||
PlayerLeft = NewPlayerP;
|
||||
PlayerLeft.TileRelX -= 0.5f*PlayerWidth;
|
||||
PlayerLeft.OffsetX -= 0.5f*PlayerWidth;
|
||||
PlayerLeft = RecannonicalizePosition(TileMap, PlayerLeft);
|
||||
|
||||
tile_map_position PlayerRight;
|
||||
PlayerRight = NewPlayerP;
|
||||
PlayerRight.TileRelX += 0.5f*PlayerWidth;
|
||||
PlayerRight.OffsetX += 0.5f*PlayerWidth;
|
||||
PlayerRight = RecannonicalizePosition(TileMap, PlayerRight);
|
||||
|
||||
if(IsTileMapPointEmpty(TileMap, NewPlayerP) &&
|
||||
IsTileMapPointEmpty(TileMap, PlayerLeft) &&
|
||||
IsTileMapPointEmpty(TileMap, PlayerRight))
|
||||
{
|
||||
if(!AreOnSameTile(&GameState->PlayerP, &NewPlayerP)) {
|
||||
U32 NewTileValue =
|
||||
GetTileValueByPos(TileMap, NewPlayerP);
|
||||
|
||||
if(NewTileValue == 3) {
|
||||
NewPlayerP.AbsTileZ++;
|
||||
} else if(NewTileValue == 4) {
|
||||
NewPlayerP.AbsTileZ--;
|
||||
}
|
||||
}
|
||||
GameState->PlayerP = NewPlayerP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScreenCenterX = 0.5f * (F32)Buffer->Width;
|
||||
ScreenCenterY = 0.5f * (F32)Buffer->Height;
|
||||
F32 ScreenCenterX = 0.5f * (F32)Buffer->Width;
|
||||
F32 ScreenCenterY = 0.5f * (F32)Buffer->Height;
|
||||
|
||||
DrawRectangle(Buffer, 0.0f, 0.0f,
|
||||
(F32)Buffer->Width, (F32)Buffer->Height,
|
||||
0.0f, 1.0f, 0.0f);
|
||||
{
|
||||
S32 RelRow, RelColumn;
|
||||
for(RelRow = -10; RelRow < 10; RelRow++) {
|
||||
for(RelColumn = -20; RelColumn < 20; RelColumn++) {
|
||||
for(S32 RelRow = -10; RelRow < 10; RelRow++) {
|
||||
for(S32 RelColumn = -20; RelColumn < 20; RelColumn++) {
|
||||
U32 Column = GameState->PlayerP.AbsTileX + RelColumn;
|
||||
U32 Row = GameState->PlayerP.AbsTileY + RelRow;
|
||||
|
||||
@@ -376,8 +353,6 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
GameState->PlayerP.AbsTileZ);
|
||||
|
||||
if(TileID > 0) {
|
||||
F32 CenterX, CenterY, MinX, MinY, MaxX, MaxY;
|
||||
|
||||
F32 Gray = 0.5f;
|
||||
if(TileID == 2) {
|
||||
Gray = 1.0f;
|
||||
@@ -394,16 +369,16 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
}
|
||||
|
||||
|
||||
CenterX = ScreenCenterX -
|
||||
MetersToPixels*GameState->PlayerP.TileRelX +
|
||||
(F32)RelColumn*(F32)TileSideInPixels;
|
||||
CenterY = ScreenCenterY +
|
||||
MetersToPixels*GameState->PlayerP.TileRelY -
|
||||
(F32)RelRow*(F32)TileSideInPixels;
|
||||
MinX = CenterX - 0.5f*(F32)TileSideInPixels;
|
||||
MinY = CenterY - 0.5f*(F32)TileSideInPixels;
|
||||
MaxX = CenterX + 0.5f*(F32)TileSideInPixels;
|
||||
MaxY = CenterY + 0.5f*(F32)TileSideInPixels;
|
||||
F32 CenterX = ScreenCenterX -
|
||||
MetersToPixels*GameState->PlayerP.OffsetX +
|
||||
(F32)RelColumn*(F32)TileSideInPixels;
|
||||
F32 CenterY = ScreenCenterY +
|
||||
MetersToPixels*GameState->PlayerP.OffsetY -
|
||||
(F32)RelRow*(F32)TileSideInPixels;
|
||||
F32 MinX = CenterX - 0.5f*(F32)TileSideInPixels;
|
||||
F32 MinY = CenterY - 0.5f*(F32)TileSideInPixels;
|
||||
F32 MaxX = CenterX + 0.5f*(F32)TileSideInPixels;
|
||||
F32 MaxY = CenterY + 0.5f*(F32)TileSideInPixels;
|
||||
DrawRectangle(Buffer,
|
||||
MinX, MinY, MaxX, MaxY,
|
||||
Gray, Gray, Gray);
|
||||
@@ -412,11 +387,11 @@ void UpdateAndRender(thread_context *Thread, game_memory *Memory,
|
||||
}
|
||||
}
|
||||
|
||||
PlayerR = 1.0f;
|
||||
PlayerG = 0.0f;
|
||||
PlayerB = 0.0f;
|
||||
PlayerLeft = ScreenCenterX - 0.5f * MetersToPixels*PlayerWidth;
|
||||
PlayerTop = ScreenCenterY - MetersToPixels*PlayerHeight;
|
||||
F32 PlayerR = 1.0f;
|
||||
F32 PlayerG = 0.0f;
|
||||
F32 PlayerB = 0.0f;
|
||||
F32 PlayerLeft = ScreenCenterX - 0.5f * MetersToPixels*PlayerWidth;
|
||||
F32 PlayerTop = ScreenCenterY - MetersToPixels*PlayerHeight;
|
||||
DrawRectangle(Buffer,
|
||||
PlayerLeft, PlayerTop,
|
||||
PlayerLeft + MetersToPixels*PlayerWidth,
|
||||
|
||||
@@ -21,29 +21,6 @@ static tile_chunk *GetTileChunk(tile_map *TileMap,
|
||||
return TileChunk;
|
||||
}
|
||||
|
||||
static void CannonicalizeCoord(tile_map *TileMap, U32 *Tile, F32 *TileRel)
|
||||
{
|
||||
/* NOTE: The world is assumed to be toroidal topology. If you step off
|
||||
one end, you come back on the other. */
|
||||
S32 Offset = RoundF32toS32(*TileRel / TileMap->TileSideInMeters);
|
||||
*Tile += Offset;
|
||||
*TileRel -= (F32)Offset * TileMap->TileSideInMeters;
|
||||
|
||||
ASSERT(*TileRel >= -0.5f*TileMap->TileSideInMeters);
|
||||
ASSERT(*TileRel <= 0.5f*TileMap->TileSideInMeters);
|
||||
}
|
||||
|
||||
static tile_map_position RecannonicalizePosition(tile_map *TileMap,
|
||||
tile_map_position Pos)
|
||||
{
|
||||
tile_map_position Result = Pos;
|
||||
|
||||
CannonicalizeCoord(TileMap, &Result.AbsTileX, &Result.TileRelX);
|
||||
CannonicalizeCoord(TileMap, &Result.AbsTileY, &Result.TileRelY);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static tile_chunk_position GetChunkPositionFor(tile_map *TileMap,
|
||||
U32 AbsTileX,
|
||||
U32 AbsTileY,
|
||||
@@ -63,26 +40,14 @@ static tile_chunk_position GetChunkPositionFor(tile_map *TileMap,
|
||||
static U32 GetTileValueUnchecked(tile_map *TileMap, tile_chunk *TileChunk,
|
||||
U32 TileX, U32 TileY)
|
||||
{
|
||||
U32 TileChunkValue;
|
||||
|
||||
ASSERT(TileChunk);
|
||||
ASSERT(TileX < TileMap->ChunkDim);
|
||||
ASSERT(TileY < TileMap->ChunkDim);
|
||||
|
||||
TileChunkValue = TileChunk->Tiles[TileY * TileMap->ChunkDim + TileX];
|
||||
U32 TileChunkValue = TileChunk->Tiles[TileY * TileMap->ChunkDim + TileX];
|
||||
return TileChunkValue;
|
||||
}
|
||||
|
||||
static void SetTileValueUnchecked(tile_map *TileMap, tile_chunk *TileChunk,
|
||||
U32 TileX, U32 TileY, U32 TileValue)
|
||||
{
|
||||
ASSERT(TileChunk);
|
||||
ASSERT(TileX < TileMap->ChunkDim);
|
||||
ASSERT(TileY < TileMap->ChunkDim);
|
||||
|
||||
TileChunk->Tiles[TileY * TileMap->ChunkDim + TileX] = TileValue;
|
||||
}
|
||||
|
||||
static U32 GetTileChunkValue(tile_map *TileMap, tile_chunk *TileChunk,
|
||||
U32 TestTileX, U32 TestTileY)
|
||||
{
|
||||
@@ -98,18 +63,6 @@ static U32 GetTileChunkValue(tile_map *TileMap, tile_chunk *TileChunk,
|
||||
return TileChunkValue;
|
||||
}
|
||||
|
||||
static void SetTileChunkValue(tile_map *TileMap, tile_chunk *TileChunk,
|
||||
U32 TestTileX, U32 TestTileY,
|
||||
U32 TileValue)
|
||||
{
|
||||
if(TileChunk && TileChunk->Tiles) {
|
||||
SetTileValueUnchecked(TileMap,
|
||||
TileChunk,
|
||||
TestTileX, TestTileY,
|
||||
TileValue);
|
||||
}
|
||||
}
|
||||
|
||||
static U32 GetTileValue(tile_map *TileMap,
|
||||
U32 AbsTileX, U32 AbsTileY, U32 AbsTileZ)
|
||||
{
|
||||
@@ -127,15 +80,43 @@ static U32 GetTileValue(tile_map *TileMap,
|
||||
return TileChunkValue;
|
||||
}
|
||||
|
||||
static B32 IsTileMapPointEmpty(tile_map *TileMap, tile_map_position CanPos)
|
||||
static U32 GetTileValueByPos(tile_map *TileMap, tile_map_position Pos)
|
||||
{
|
||||
B32 Empty;
|
||||
|
||||
U32 TileChunkValue = GetTileValue(TileMap,
|
||||
CanPos.AbsTileX,
|
||||
CanPos.AbsTileY,
|
||||
CanPos.AbsTileZ);
|
||||
Empty = (TileChunkValue == 1);
|
||||
Pos.AbsTileX,
|
||||
Pos.AbsTileY,
|
||||
Pos.AbsTileZ);
|
||||
return TileChunkValue;
|
||||
}
|
||||
|
||||
static void SetTileValueUnchecked(tile_map *TileMap, tile_chunk *TileChunk,
|
||||
U32 TileX, U32 TileY, U32 TileValue)
|
||||
{
|
||||
ASSERT(TileChunk);
|
||||
ASSERT(TileX < TileMap->ChunkDim);
|
||||
ASSERT(TileY < TileMap->ChunkDim);
|
||||
|
||||
TileChunk->Tiles[TileY * TileMap->ChunkDim + TileX] = TileValue;
|
||||
}
|
||||
|
||||
static void SetTileChunkValue(tile_map *TileMap, tile_chunk *TileChunk,
|
||||
U32 TestTileX, U32 TestTileY,
|
||||
U32 TileValue)
|
||||
{
|
||||
if(TileChunk && TileChunk->Tiles) {
|
||||
SetTileValueUnchecked(TileMap,
|
||||
TileChunk,
|
||||
TestTileX, TestTileY,
|
||||
TileValue);
|
||||
}
|
||||
}
|
||||
|
||||
static B32 IsTileMapPointEmpty(tile_map *TileMap, tile_map_position Pos)
|
||||
{
|
||||
U32 TileChunkValue = GetTileValueByPos(TileMap, Pos);
|
||||
B32 Empty = ((TileChunkValue == 1) ||
|
||||
(TileChunkValue == 3) ||
|
||||
(TileChunkValue == 4));
|
||||
return Empty;
|
||||
}
|
||||
|
||||
@@ -144,22 +125,22 @@ static void SetTileValue(memory_arena *Arena,
|
||||
U32 AbsTileX, U32 AbsTileY, U32 AbsTileZ,
|
||||
U32 TileValue)
|
||||
{
|
||||
tile_chunk_position ChunkPos;
|
||||
tile_chunk *TileChunk;
|
||||
|
||||
ChunkPos = GetChunkPositionFor(TileMap, AbsTileX, AbsTileY, AbsTileZ);
|
||||
TileChunk = GetTileChunk(TileMap,
|
||||
ChunkPos.TileChunkX,
|
||||
ChunkPos.TileChunkY,
|
||||
ChunkPos.TileChunkZ);
|
||||
tile_chunk_position ChunkPos = GetChunkPositionFor(TileMap,
|
||||
AbsTileX,
|
||||
AbsTileY,
|
||||
AbsTileZ);
|
||||
tile_chunk *TileChunk = GetTileChunk(TileMap,
|
||||
ChunkPos.TileChunkX,
|
||||
ChunkPos.TileChunkY,
|
||||
ChunkPos.TileChunkZ);
|
||||
|
||||
ASSERT(TileChunk);
|
||||
if(!TileChunk->Tiles) {
|
||||
U32 TileCount = TileMap->ChunkDim*TileMap->ChunkDim;
|
||||
U32 TileIndex;
|
||||
|
||||
TileChunk->Tiles = PUSH_ARRAY(Arena, TileCount, U32);
|
||||
for(TileIndex = 0; TileIndex < TileCount; TileIndex++) {
|
||||
for(U32 TileIndex = 0; TileIndex < TileCount; TileIndex++) {
|
||||
TileChunk->Tiles[TileIndex] = 1;
|
||||
}
|
||||
|
||||
@@ -170,3 +151,38 @@ static void SetTileValue(memory_arena *Arena,
|
||||
ChunkPos.RelTileY,
|
||||
TileValue);
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: Do these belong more in a "positioning" or "geometry" file?
|
||||
//
|
||||
|
||||
static void CannonicalizeCoord(tile_map *TileMap, U32 *Tile, F32 *TileRel)
|
||||
{
|
||||
// NOTE: The world is assumed to be toroidal topology. If you step off
|
||||
// one end, you come back on the other.
|
||||
S32 Offset = RoundF32toS32(*TileRel / TileMap->TileSideInMeters);
|
||||
*Tile += Offset;
|
||||
*TileRel -= (F32)Offset * TileMap->TileSideInMeters;
|
||||
|
||||
ASSERT(*TileRel >= -0.5f*TileMap->TileSideInMeters);
|
||||
ASSERT(*TileRel <= 0.5f*TileMap->TileSideInMeters);
|
||||
}
|
||||
|
||||
static tile_map_position RecannonicalizePosition(tile_map *TileMap,
|
||||
tile_map_position Pos)
|
||||
{
|
||||
tile_map_position Result = Pos;
|
||||
|
||||
CannonicalizeCoord(TileMap, &Result.AbsTileX, &Result.OffsetX);
|
||||
CannonicalizeCoord(TileMap, &Result.AbsTileY, &Result.OffsetY);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static B32 AreOnSameTile(tile_map_position *A, tile_map_position *B)
|
||||
{
|
||||
B32 Result = ((A->AbsTileX == B->AbsTileX) &&
|
||||
(A->AbsTileY == B->AbsTileY) &&
|
||||
(A->AbsTileZ == B->AbsTileZ));
|
||||
return Result;
|
||||
}
|
||||
+3
-3
@@ -6,9 +6,9 @@ typedef struct tile_map_position {
|
||||
U32 AbsTileY;
|
||||
U32 AbsTileZ;
|
||||
|
||||
/* NOTE: Tile-relative X and Y. */
|
||||
F32 TileRelX;
|
||||
F32 TileRelY;
|
||||
/* NOTE: X and Y relative to tile center. */
|
||||
F32 OffsetX;
|
||||
F32 OffsetY;
|
||||
} tile_map_position;
|
||||
|
||||
typedef struct tile_chunk_position {
|
||||
|
||||
+81
-153
@@ -50,10 +50,8 @@ static S32 str_len(char *str)
|
||||
|
||||
static U32 SafeTruncateUInt64(U64 Value)
|
||||
{
|
||||
U32 Result;
|
||||
|
||||
ASSERT(Value <= 0xFFFFFFFF);
|
||||
Result = (U32)Value;
|
||||
U32 Result = (U32)Value;
|
||||
return Result;
|
||||
}
|
||||
|
||||
@@ -61,17 +59,14 @@ debug_read_file_result DEBUGPlatformReadEntireFile(thread_context *Thread,
|
||||
const char *Filename)
|
||||
{
|
||||
debug_read_file_result Result;
|
||||
S32 FileHandle;
|
||||
struct stat FileStatus;
|
||||
U32 BytesToRead;
|
||||
U8 *NextByteLocation;
|
||||
|
||||
memset(&Result, 0, sizeof(Result));
|
||||
FileHandle = open(Filename, O_RDONLY);
|
||||
|
||||
S32 FileHandle = open(Filename, O_RDONLY);
|
||||
if(FileHandle == -1) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
struct stat FileStatus;
|
||||
if(fstat(FileHandle, &FileStatus) == -1) {
|
||||
close(FileHandle);
|
||||
return Result;
|
||||
@@ -85,12 +80,10 @@ debug_read_file_result DEBUGPlatformReadEntireFile(thread_context *Thread,
|
||||
return Result;
|
||||
}
|
||||
|
||||
BytesToRead = Result.ContentsSize;
|
||||
NextByteLocation = (U8 *)Result.Contents;
|
||||
U32 BytesToRead = Result.ContentsSize;
|
||||
U8 *NextByteLocation = (U8 *)Result.Contents;
|
||||
while(BytesToRead) {
|
||||
U32 BytesRead;
|
||||
|
||||
BytesRead = read(FileHandle, NextByteLocation, BytesToRead);
|
||||
U32 BytesRead = read(FileHandle, NextByteLocation, BytesToRead);
|
||||
if(BytesRead == (U32)-1) {
|
||||
free(Result.Contents);
|
||||
Result.Contents = 0;
|
||||
@@ -111,17 +104,13 @@ B32 DEBUGPlatformWriteEntireFile(thread_context *Thread,
|
||||
const char *Filename, U32 MemorySize,
|
||||
void *Memory)
|
||||
{
|
||||
S32 FileHandle;
|
||||
U32 BytesToWrite;
|
||||
U8 *NextByteLocation;
|
||||
|
||||
FileHandle = open(Filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR |
|
||||
S_IRGRP | S_IROTH);
|
||||
S32 FileHandle = open(Filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR |
|
||||
S_IRGRP | S_IROTH);
|
||||
if(FileHandle == -1)
|
||||
return FALSE;
|
||||
|
||||
BytesToWrite = MemorySize;
|
||||
NextByteLocation = (U8*)Memory;
|
||||
U32 BytesToWrite = MemorySize;
|
||||
U8 *NextByteLocation = (U8*)Memory;
|
||||
while(BytesToWrite) {
|
||||
U32 BytesWritten;
|
||||
|
||||
@@ -155,15 +144,13 @@ static sdl_window_dimension SDLGetWindowDimension(SDL_Window *Window)
|
||||
static void SDLResizeTexture(offscreen_buffer *Buffer,
|
||||
SDL_Renderer *Renderer, int Width, int Height)
|
||||
{
|
||||
S32 BytesPerPixel;
|
||||
|
||||
if(Buffer->Texture)
|
||||
SDL_DestroyTexture(Buffer->Texture);
|
||||
|
||||
if(Buffer->Memory)
|
||||
free(Buffer->Memory);
|
||||
|
||||
BytesPerPixel = 4;
|
||||
S32 BytesPerPixel = 4;
|
||||
|
||||
Buffer->Texture = SDL_CreateTexture(Renderer, SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
@@ -179,7 +166,6 @@ static void SDLDisplayBufferInWindow(offscreen_buffer Buffer,
|
||||
SDL_Window *Window,
|
||||
SDL_Renderer *Renderer)
|
||||
{
|
||||
SDL_Rect dest_rect;
|
||||
S32 OffsetX = 10;
|
||||
S32 OffsetY = 10;
|
||||
|
||||
@@ -193,21 +179,17 @@ 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 = OffsetX;
|
||||
dest_rect.y = OffsetY;
|
||||
dest_rect.w = RESOLUTION_WIDTH;
|
||||
dest_rect.h = RESOLUTION_HEIGHT;
|
||||
SDL_Rect dest_rect = { OffsetX, OffsetY,
|
||||
RESOLUTION_WIDTH, RESOLUTION_HEIGHT };
|
||||
SDL_RenderCopy(Renderer, Buffer.Texture, 0, (const SDL_Rect *)(&dest_rect));
|
||||
SDL_RenderPresent(Renderer);
|
||||
}
|
||||
|
||||
static void SDLInitControllers()
|
||||
{
|
||||
S32 MaxJoysticks, ControllerIndex, JoystickIndex;
|
||||
|
||||
MaxJoysticks = SDL_NumJoysticks();
|
||||
ControllerIndex = 0;
|
||||
for(JoystickIndex = 0; JoystickIndex < MaxJoysticks; JoystickIndex++) {
|
||||
S32 MaxJoysticks = SDL_NumJoysticks();
|
||||
S32 ControllerIndex = 0;
|
||||
for(S32 JoystickIndex = 0; JoystickIndex < MaxJoysticks; JoystickIndex++) {
|
||||
if(!SDL_IsGameController(JoystickIndex))
|
||||
continue;
|
||||
if(ControllerIndex >= MAX_CONTROLLERS)
|
||||
@@ -221,9 +203,7 @@ static void SDLInitControllers()
|
||||
/*
|
||||
static void SDLDeinitControllers()
|
||||
{
|
||||
S32 ControllerIndex;
|
||||
|
||||
for(ControllerIndex = 0;
|
||||
for(S32 ControllerIndex = 0;
|
||||
ControllerIndex < MAX_CONTROLLERS;
|
||||
ControllerIndex++)
|
||||
{
|
||||
@@ -236,7 +216,6 @@ static void SDLDeinitControllers()
|
||||
static void SDLInitSound(S32 SamplesPerSecond, S32 BufferSize)
|
||||
{
|
||||
SDL_AudioSpec AudioSettings;
|
||||
|
||||
memset(&AudioSettings, 0, sizeof(AudioSettings));
|
||||
|
||||
AudioSettings.freq = SamplesPerSecond;
|
||||
@@ -283,12 +262,8 @@ static void SDLProcessInputDigitalButton(SDL_GameController *Controller,
|
||||
|
||||
static void HandleEvent(SDL_Event *Event)
|
||||
{
|
||||
/* TODO: Should this be below scopes? */
|
||||
SDL_Window *Window;
|
||||
SDL_Renderer *Renderer;
|
||||
|
||||
Window = SDL_GetWindowFromID(Event->window.windowID);
|
||||
Renderer = SDL_GetRenderer(Window);
|
||||
SDL_Window *Window = SDL_GetWindowFromID(Event->window.windowID);
|
||||
SDL_Renderer *Renderer = SDL_GetRenderer(Window);
|
||||
|
||||
switch(Event->type) {
|
||||
case SDL_QUIT: {
|
||||
@@ -404,13 +379,11 @@ static void SDLProcessMessages(sdl_state *SDLState,
|
||||
}
|
||||
|
||||
if(WasDown) {
|
||||
B32 AltKeyWasDown;
|
||||
|
||||
/* NOTE: If your window manager already uses an Alt+F4
|
||||
* keybind to close programs, then we are likely
|
||||
* to see SDL_QUIT event occur before our
|
||||
* keybind. */
|
||||
AltKeyWasDown = (Event.key.keysym.mod & KMOD_ALT);
|
||||
B32 AltKeyWasDown = (Event.key.keysym.mod & KMOD_ALT);
|
||||
if(KeyCode == SDLK_F4 && AltKeyWasDown)
|
||||
GlobalRunning = FALSE;
|
||||
#if BUILD_INTERNAL
|
||||
@@ -429,9 +402,7 @@ static void SDLProcessMessages(sdl_state *SDLState,
|
||||
|
||||
static F32 SDLProcessInputStickValue(F32 Value, S32 DeadZoneThreshold)
|
||||
{
|
||||
F32 Result;
|
||||
|
||||
Result = 0.0f;
|
||||
F32 Result = 0.0f;
|
||||
if(Value < -(F32)DeadZoneThreshold)
|
||||
Result = ((Value + (F32)DeadZoneThreshold) /
|
||||
(32768.0f - (F32)DeadZoneThreshold));
|
||||
@@ -445,11 +416,9 @@ static F32 SDLProcessInputStickValue(F32 Value, S32 DeadZoneThreshold)
|
||||
#define DEFAULT_REFRESH_RATE 60
|
||||
static S32 SDLGetWindowRefreshRate(SDL_Window *Window)
|
||||
{
|
||||
S32 DisplayIndex;
|
||||
S32 DisplayIndex = SDL_GetWindowDisplayIndex(Window);
|
||||
|
||||
SDL_DisplayMode Mode;
|
||||
|
||||
DisplayIndex = SDL_GetWindowDisplayIndex(Window);
|
||||
|
||||
if(SDL_GetDesktopDisplayMode(DisplayIndex, &Mode) != 0)
|
||||
return DEFAULT_REFRESH_RATE;
|
||||
if(Mode.refresh_rate == 0)
|
||||
@@ -482,7 +451,6 @@ typedef struct sdl_game_code {
|
||||
static U32 GetLastWriteTime(const char *FileName)
|
||||
{
|
||||
struct stat file_info;
|
||||
|
||||
memset(&file_info, 0, sizeof(file_info));
|
||||
if(stat(FileName, &file_info) != 0) {
|
||||
/* TODO: Diagnostic. perror("stat failed"); */
|
||||
@@ -561,11 +529,9 @@ void GetExecutablePath(char *path, size_t path_size)
|
||||
|
||||
static void SDLGetEXEDirPath(char *path, size_t path_size)
|
||||
{
|
||||
U32 len, i;
|
||||
|
||||
GetExecutablePath(path, path_size);
|
||||
len = str_len(path);
|
||||
i = len;
|
||||
U32 len = str_len(path);
|
||||
U32 i = len;
|
||||
while(path[i] != '/' || i == 0) {
|
||||
i--;
|
||||
}
|
||||
@@ -590,8 +556,6 @@ U64 __rdtsc()
|
||||
* drawing into a bitmap. */
|
||||
void SDLSetProgramIcon(SDL_Window *Window)
|
||||
{
|
||||
SDL_Surface *icon;
|
||||
|
||||
U32 Rmask, Gmask, Bmask, Amask;
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
S32 shift_by = (program_icon.bytes_per_pixel == 3) ? 8 : 0;
|
||||
@@ -606,12 +570,12 @@ void SDLSetProgramIcon(SDL_Window *Window)
|
||||
Amask = (program_icon.bytes_per_pixel == 3) ? 0 : 0xff000000;
|
||||
#endif
|
||||
|
||||
icon = SDL_CreateRGBSurfaceFrom(
|
||||
(void *)program_icon.pixel_data,
|
||||
program_icon.width, program_icon.height,
|
||||
program_icon.bytes_per_pixel * 8,
|
||||
program_icon.bytes_per_pixel * program_icon.width,
|
||||
Rmask, Gmask, Bmask, Amask);
|
||||
SDL_Surface * icon = SDL_CreateRGBSurfaceFrom(
|
||||
(void *)program_icon.pixel_data,
|
||||
program_icon.width, program_icon.height,
|
||||
program_icon.bytes_per_pixel * 8,
|
||||
program_icon.bytes_per_pixel * program_icon.width,
|
||||
Rmask, Gmask, Bmask, Amask);
|
||||
if(icon) {
|
||||
SDL_SetWindowIcon(Window, icon);
|
||||
SDL_FreeSurface(icon);
|
||||
@@ -623,8 +587,6 @@ void SDLSetProgramIcon(SDL_Window *Window)
|
||||
S32 main(S32 argc, char *argv[])
|
||||
{
|
||||
sdl_state SDLState;
|
||||
SDL_Window *Window;
|
||||
|
||||
memset(&SDLState, 0, sizeof(SDLState));
|
||||
|
||||
SDLGetEXEDirPath(SDLState.EXEDirPath, sizeof(SDLState.EXEDirPath));
|
||||
@@ -642,20 +604,20 @@ S32 main(S32 argc, char *argv[])
|
||||
/* NOTE: Floating windows are not supported oficially by Wayland
|
||||
* protocol. However, SDL_WINDOW_ALWAYS_ON_TOP does work on KDE
|
||||
* under Wayland. I have not tested GNOME. */
|
||||
Window = SDL_CreateWindow("Handmade Hero", SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
RESOLUTION_WIDTH, RESOLUTION_HEIGHT,
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
SDL_Window *Window = SDL_CreateWindow("Handmade Hero",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
RESOLUTION_WIDTH, RESOLUTION_HEIGHT,
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
/*SDL_WINDOW_RESIZABLE |
|
||||
SDL_WINDOW_ALWAYS_ON_TOP);*/
|
||||
|
||||
if(Window) {
|
||||
SDL_Renderer *Renderer;
|
||||
|
||||
SDL_DisplayMode display_mode;
|
||||
SDL_GetCurrentDisplayMode(0, &display_mode);
|
||||
|
||||
Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
SDL_Renderer *Renderer =
|
||||
SDL_CreateRenderer(Window, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
SDL_SetWindowPosition(Window, (display_mode.w - RESOLUTION_WIDTH),
|
||||
(display_mode.h - RESOLUTION_HEIGHT));
|
||||
|
||||
@@ -666,11 +628,6 @@ S32 main(S32 argc, char *argv[])
|
||||
* its actual size. */
|
||||
/* SDL_RenderPresent(Renderer) is enough to display the window. */
|
||||
if(Renderer) {
|
||||
sdl_window_dimension Dimension;
|
||||
sdl_sound_output SoundOutput;
|
||||
game_memory GameMemory;
|
||||
S32 ReplayIndex;
|
||||
|
||||
#if BUILD_DEBUG
|
||||
void *BaseAddress = (void *)TB(2);
|
||||
#else
|
||||
@@ -686,10 +643,11 @@ S32 main(S32 argc, char *argv[])
|
||||
|
||||
GlobalRunning = TRUE;
|
||||
|
||||
Dimension = SDLGetWindowDimension(Window);
|
||||
sdl_window_dimension Dimension = SDLGetWindowDimension(Window);
|
||||
SDLResizeTexture(&GlobalBackbuffer, Renderer, Dimension.Width,
|
||||
Dimension.Height);
|
||||
|
||||
sdl_sound_output SoundOutput;
|
||||
memset(&SoundOutput, 0, sizeof(SoundOutput));
|
||||
SoundOutput.SamplesPerSecond = 48000;
|
||||
SoundOutput.BytesPerSample = sizeof(S16) * 2;
|
||||
@@ -712,6 +670,7 @@ S32 main(S32 argc, char *argv[])
|
||||
/* NOTE: calloc auto clears to zero */
|
||||
/* SDLClearSoundBuffer(&SoundOutput); */
|
||||
|
||||
game_memory GameMemory;
|
||||
memset(&GameMemory, 0, sizeof(GameMemory));
|
||||
GameMemory.PermanentStorageSize = MB(64);
|
||||
GameMemory.TransientStorageSize = GB(1);
|
||||
@@ -735,65 +694,29 @@ S32 main(S32 argc, char *argv[])
|
||||
(U8 *)(GameMemory.PermanentStorage) +
|
||||
GameMemory.PermanentStorageSize;
|
||||
|
||||
for(ReplayIndex = 0;
|
||||
ReplayIndex < (S32)ARRAY_SIZE(SDLState.ReplayBuffers);
|
||||
ReplayIndex++)
|
||||
{
|
||||
sdl_replay_buffer *ReplayBuffer =
|
||||
&SDLState.ReplayBuffers[ReplayIndex];
|
||||
ReplayBuffer->MemoryBlock = mmap(NULL,
|
||||
(size_t)SDLState.TotalSize,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_PRIVATE,
|
||||
-1, 0);
|
||||
if(ReplayBuffer->MemoryBlock) {
|
||||
} else {
|
||||
/* TODO: Change this to log message. */
|
||||
}
|
||||
}
|
||||
|
||||
if(SoundOutput.Samples &&
|
||||
GameMemory.PermanentStorage &&
|
||||
GameMemory.TransientStorage)
|
||||
{
|
||||
game_input Input[2];
|
||||
game_input *NewInput, *OldInput;
|
||||
sdl_game_code Game;
|
||||
F32 TargetSecondsPerFrame;
|
||||
S32 MonitorRefreshHz, GameUpdateHz;
|
||||
|
||||
U64 LastCounter;
|
||||
U64 LastCycleCount;
|
||||
|
||||
MonitorRefreshHz = SDLGetWindowRefreshRate(Window);
|
||||
S32 MonitorRefreshHz = SDLGetWindowRefreshRate(Window);
|
||||
/*GameUpdateHz = MonitorRefreshHz;*/
|
||||
GameUpdateHz = 30; /* NOTE: Temporarily target 30 FPS. */
|
||||
TargetSecondsPerFrame = 1.0f / (F32)GameUpdateHz;
|
||||
S32 GameUpdateHz = 30; /* NOTE: Temporarily target 30 FPS. */
|
||||
F32 TargetSecondsPerFrame = 1.0f / (F32)GameUpdateHz;
|
||||
|
||||
NewInput = &Input[0];
|
||||
OldInput = &Input[1];
|
||||
game_input *NewInput = &Input[0];
|
||||
game_input *OldInput = &Input[1];
|
||||
memset(&Input, 0, sizeof(Input));
|
||||
|
||||
GlobalPerfCountFrequency = SDL_GetPerformanceFrequency();
|
||||
|
||||
Game = SDLLoadGameCode(SDLState.DLLPath);
|
||||
sdl_game_code Game = SDLLoadGameCode(SDLState.DLLPath);
|
||||
|
||||
while(GlobalRunning) {
|
||||
thread_context Context;
|
||||
U32 NewDLLWriteTime, ButtonIndex, ControllerIndex,
|
||||
SDLMouseButtons;
|
||||
game_controller_input *OldKeyboardController,
|
||||
*NewKeyboardController;
|
||||
game_controller_input ZeroController;
|
||||
S32 TargetQueueBytes, BytesToWrite;
|
||||
game_sound_output_buffer SoundBuffer;
|
||||
game_offscreen_buffer Buffer;
|
||||
U64 WorkCounter, EndCounter;
|
||||
F32 WorkSecondsElapsed, SecondsElapsedForFrame;
|
||||
F64 MSPerFrame, FPS;
|
||||
U64 EndCycleCount, CyclesElapsed;
|
||||
F64 MCPF;
|
||||
|
||||
NewInput->dtForFrame = TargetSecondsPerFrame;
|
||||
|
||||
LastCounter = SDLGetWallClock();
|
||||
@@ -805,14 +728,15 @@ S32 main(S32 argc, char *argv[])
|
||||
* have not checked MacOS x64. */
|
||||
LastCycleCount = __rdtsc();
|
||||
|
||||
NewDLLWriteTime = GetLastWriteTime(SDLState.DLLPath);
|
||||
U32 NewDLLWriteTime = GetLastWriteTime(SDLState.DLLPath);
|
||||
if(NewDLLWriteTime > Game.DLLLastWriteTime) {
|
||||
SDLUnloadGameCode(&Game);
|
||||
Game = SDLLoadGameCode(SDLState.DLLPath);
|
||||
}
|
||||
|
||||
SDLMouseButtons = SDL_GetMouseState(&(NewInput->MouseX),
|
||||
&(NewInput->MouseY));
|
||||
U32 SDLMouseButtons =
|
||||
SDL_GetMouseState(&(NewInput->MouseX),
|
||||
&(NewInput->MouseY));
|
||||
NewInput->MouseZ = 0; /* TODO: Support mouse wheel? */
|
||||
SDLProcessKeyboardMessage(&(NewInput->MouseButtons[0]),
|
||||
SDL_BUTTON_LMASK & SDLMouseButtons);
|
||||
@@ -828,13 +752,16 @@ S32 main(S32 argc, char *argv[])
|
||||
SDLProcessKeyboardMessage(&(NewInput->MouseButtons[4]),
|
||||
SDL_BUTTON_X2MASK & SDLMouseButtons);
|
||||
|
||||
OldKeyboardController = GetController(OldInput, 0);
|
||||
NewKeyboardController = GetController(NewInput, 0);
|
||||
game_controller_input *OldKeyboardController =
|
||||
GetController(OldInput, 0);
|
||||
game_controller_input *NewKeyboardController =
|
||||
GetController(NewInput, 0);
|
||||
game_controller_input ZeroController;
|
||||
memset(&ZeroController, 0, sizeof(ZeroController));
|
||||
*NewKeyboardController = ZeroController;
|
||||
NewKeyboardController->IsConnected = TRUE;
|
||||
|
||||
for(ButtonIndex = 0;
|
||||
for(U32 ButtonIndex = 0;
|
||||
ButtonIndex < ARRAY_SIZE(
|
||||
NewKeyboardController->u.Buttons);
|
||||
ButtonIndex++)
|
||||
@@ -848,11 +775,12 @@ S32 main(S32 argc, char *argv[])
|
||||
|
||||
SDLProcessMessages(&SDLState, NewKeyboardController);
|
||||
|
||||
for(ControllerIndex = 0;
|
||||
for(U32 ControllerIndex = 0;
|
||||
ControllerIndex < MAX_CONTROLLERS;
|
||||
ControllerIndex++)
|
||||
{
|
||||
game_controller_input *OldController, *NewController;
|
||||
game_controller_input *OldController,
|
||||
*NewController;
|
||||
|
||||
OldController =
|
||||
GetController(OldInput, ControllerIndex+1);
|
||||
@@ -863,18 +791,15 @@ S32 main(S32 argc, char *argv[])
|
||||
SDL_GameControllerGetAttached(
|
||||
ControllerHandles[ControllerIndex]))
|
||||
{
|
||||
S16 StickX, StickY;
|
||||
float Threshold;
|
||||
|
||||
NewController->IsAnalog =
|
||||
OldController->IsAnalog;
|
||||
NewController->IsConnected = TRUE;
|
||||
|
||||
StickX =
|
||||
S16 StickX =
|
||||
SDL_GameControllerGetAxis(
|
||||
ControllerHandles[ControllerIndex],
|
||||
SDL_CONTROLLER_AXIS_LEFTX);
|
||||
StickY =
|
||||
S16 StickY =
|
||||
SDL_GameControllerGetAxis(
|
||||
ControllerHandles[ControllerIndex],
|
||||
SDL_CONTROLLER_AXIS_LEFTY);
|
||||
@@ -925,7 +850,7 @@ S32 main(S32 argc, char *argv[])
|
||||
NewController->IsAnalog = FALSE;
|
||||
}
|
||||
|
||||
Threshold = 0.5f;
|
||||
F32 Threshold = 0.5f;
|
||||
SDLProcessInputDigitalButton(
|
||||
ControllerHandles[
|
||||
(NewController->StickAverageY <
|
||||
@@ -1002,18 +927,21 @@ S32 main(S32 argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
TargetQueueBytes = SoundOutput.LatencySampleCount *
|
||||
SoundOutput.BytesPerSample;
|
||||
BytesToWrite =
|
||||
S32 TargetQueueBytes = SoundOutput.LatencySampleCount *
|
||||
SoundOutput.BytesPerSample;
|
||||
S32 BytesToWrite =
|
||||
TargetQueueBytes - SDL_GetQueuedAudioSize(1);
|
||||
game_sound_output_buffer SoundBuffer;
|
||||
SoundBuffer.SamplesPerSecond =
|
||||
SoundOutput.SamplesPerSecond;
|
||||
SoundBuffer.SampleCount =
|
||||
BytesToWrite / SoundOutput.BytesPerSample;
|
||||
SoundBuffer.Samples = (short *)SoundOutput.Samples;
|
||||
|
||||
thread_context Context;
|
||||
memset(&Context, 0, sizeof(Context));
|
||||
|
||||
game_offscreen_buffer Buffer;
|
||||
Buffer.Memory = GlobalBackbuffer.Memory;
|
||||
Buffer.Width = GlobalBackbuffer.Width;
|
||||
Buffer.Height = GlobalBackbuffer.Height;
|
||||
@@ -1028,11 +956,11 @@ S32 main(S32 argc, char *argv[])
|
||||
|
||||
SDLFillSoundBuffer(&SoundOutput, BytesToWrite);
|
||||
|
||||
WorkCounter = SDLGetWallClock();
|
||||
WorkSecondsElapsed = SDLGetSecondsElapsed(LastCounter,
|
||||
WorkCounter);
|
||||
U64 WorkCounter = SDLGetWallClock();
|
||||
F32 WorkSecondsElapsed =
|
||||
SDLGetSecondsElapsed(LastCounter, WorkCounter);
|
||||
|
||||
SecondsElapsedForFrame = WorkSecondsElapsed;
|
||||
F32 SecondsElapsedForFrame = WorkSecondsElapsed;
|
||||
if(SecondsElapsedForFrame < TargetSecondsPerFrame) {
|
||||
while(SecondsElapsedForFrame < TargetSecondsPerFrame) {
|
||||
SecondsElapsedForFrame =
|
||||
@@ -1046,21 +974,21 @@ S32 main(S32 argc, char *argv[])
|
||||
/* TODO: Logging. */
|
||||
}
|
||||
|
||||
EndCounter = SDLGetWallClock();
|
||||
U64 EndCounter = SDLGetWallClock();
|
||||
|
||||
SDLDisplayBufferInWindow(GlobalBackbuffer, Window,
|
||||
Renderer);
|
||||
|
||||
MSPerFrame = 1000.0 * SDLGetSecondsElapsed(LastCounter,
|
||||
EndCounter);
|
||||
FPS = 0.0;
|
||||
F64 MSPerFrame = 1000.0 *
|
||||
SDLGetSecondsElapsed(LastCounter, EndCounter);
|
||||
F64 FPS = 0.0;
|
||||
|
||||
LastCounter = EndCounter;
|
||||
|
||||
#if 0
|
||||
EndCycleCount = __rdtsc();
|
||||
CyclesElapsed = EndCycleCount - LastCycleCount;
|
||||
MCPF = ((double)CyclesElapsed / (1000.0 * 1000.0));
|
||||
U64 EndCycleCount = __rdtsc();
|
||||
U64 CyclesElapsed = EndCycleCount - LastCycleCount;
|
||||
F64 MCPF = ((double)CyclesElapsed / (1000.0 * 1000.0));
|
||||
fprintf(stderr, "%.02f ms/f, %.02f/s, %.02f mc/f\n",
|
||||
MSPerFrame, FPS, MCPF);
|
||||
LastCycleCount = EndCycleCount;
|
||||
|
||||
@@ -34,22 +34,9 @@ typedef struct sdl_sound_output {
|
||||
* For example, linux/limits.h PATH_MAX says 4096. */
|
||||
#define SDL_STATE_PATH_SIZE 1024
|
||||
|
||||
typedef struct sdl_replay_buffer {
|
||||
char ReplayFilename[SDL_STATE_PATH_SIZE];
|
||||
void *MemoryBlock;
|
||||
} sdl_replay_buffer;
|
||||
|
||||
typedef struct sdl_state {
|
||||
U64 TotalSize;
|
||||
void *GameMmemoryBlock;
|
||||
sdl_replay_buffer ReplayBuffers[4];
|
||||
|
||||
S32 RecordingHandle;
|
||||
S32 InputRecordingIndex;
|
||||
|
||||
/* NOTE: These functions might be NULL. Check before calling them! */
|
||||
S32 PlaybackHandle;
|
||||
S32 InputPlayingIndex;
|
||||
|
||||
char EXEDirPath[SDL_STATE_PATH_SIZE];
|
||||
char DLLPath[SDL_STATE_PATH_SIZE];
|
||||
|
||||
Reference in New Issue
Block a user