Compare commits

5 Commits

Author SHA1 Message Date
ee9f65f016 update 2024-12-08 21:21:43 +00:00
d522c16206 update' 2024-11-24 20:21:44 +00:00
7b9b6f3200 update 2024-11-24 20:21:08 +00:00
2a1b24af1f feat: day 31 2024-11-24 11:17:30 +00:00
5ddc837101 update 2024-10-19 23:02:52 +01:00
11 changed files with 428 additions and 91 deletions

View File

@@ -1,2 +0,0 @@
call build || exit /b %errorlevel%
devenv .\build\handmade_win32.exe

View File

@@ -1,2 +0,0 @@
call build || exit /b %errorlevel%
.\build\handmade_win32.exe

View File

@@ -9,7 +9,7 @@ set commonCompilerFlags=^
-Oi %= Always use intrinsics =%^ -Oi %= Always use intrinsics =%^
-EHa- %= Disable exception handling =%^ -EHa- %= Disable exception handling =%^
-GR- %= Never use runtime type info from C++ =%^ -GR- %= Never use runtime type info from C++ =%^
-WX -W4 -wd4201 -wd4100 -wd4189 %= Compiler warnings, -WX warnings as errors, -W4 warning level 4, -wdXXXX disable warning XXXX =%^ -WX -W4 -wd4201 -wd4100 -wd4189 -wd4505 %= Compiler warnings, -WX warnings as errors, -W4 warning level 4, -wdXXXX disable warning XXXX =%^
-DHANDMADE_INTERNAL=1 -DHANDMADE_SLOW=1 -DHANDMADE_WIN32=1 %= Custom #defines =%^ -DHANDMADE_INTERNAL=1 -DHANDMADE_SLOW=1 -DHANDMADE_WIN32=1 %= Custom #defines =%^
-FC %= Full path of source code file in diagnostics =%^ -FC %= Full path of source code file in diagnostics =%^
-Zi %= Generate debugger info =% -Zi %= Generate debugger info =%

1
misc/cmds/run.bat Normal file
View File

@@ -0,0 +1 @@
.\build\handmade_win32.exe

2
misc/hh.bat Normal file
View File

@@ -0,0 +1,2 @@
call .\misc\cmds\%1.bat || exit /b %errorlevel%
.\build\handmade_win32.exe

View File

@@ -1,106 +1,246 @@
#include "handmade.h" #include "handmade.h"
#include "handmade_tile.cpp"
#define PI32 3.141592653589f internal void drawRectangle(GameOffscreenBuffer *buffer, real32 realMinX, real32 realMinY, real32 realMaxX, real32 realMaxY, real32 R, real32 G, real32 B) {
int32 minX = roundReal32ToInt32(realMinX);
int32 minY = roundReal32ToInt32(realMinY);
int32 maxX = roundReal32ToInt32(realMaxX);
int32 maxY = roundReal32ToInt32(realMaxY);
uint32 color = (roundReal32ToUInt32(R*255.0f) << 16) |
(roundReal32ToUInt32(G*255.0f) << 8) |
(roundReal32ToUInt32(B*255.0f) << 0);
if (minX < 0) {
minX = 0;
}
if (minY < 0) {
minY = 0;
}
if (maxX > buffer->width) {
maxX = buffer->width;
}
if (maxY > buffer->height) {
maxY = buffer->height;
}
internal void renderSmallRect(GameOffscreenBuffer *buffer, int playerX, int playerY) {
uint8 *endOfBuffer = (uint8 *)buffer->memory + buffer->pitch*buffer->height; uint8 *endOfBuffer = (uint8 *)buffer->memory + buffer->pitch*buffer->height;
uint32 color = 0xFFFFFFFF; uint8 *row = ((uint8 *)buffer->memory + minX*buffer->bytesPerPixel + minY*buffer->pitch);
int top = playerY; for (int y = minY; y < maxY; y++) {
int bottom = playerY + 10; uint32 *pixel = (uint32 *)row;
for (int x = playerX; x < playerX + 10; x++) { for (int x = minX; x < maxX; x++) {
uint8 *pixel = ((uint8 *)buffer->memory + x * buffer->bytesPerPixel + top*buffer->pitch); *pixel++ = color;
for (int y = top; y < bottom; y++) {
if ((pixel >= buffer->memory) && (pixel + 4 < endOfBuffer)) {
*(uint32 *)pixel = color;
}
pixel += buffer->pitch;
}
}
}
internal void outputSineSound(GameSoundOutputBuffer *soundBuffer, GameState *state) {
int16 toneVolume = 3000;
int wavePeriod = soundBuffer->samplesPerSecond/state->toneHz;
#if 0
int16 *sampleOut = soundBuffer->samples;
for (int sampleIndex = 0; sampleIndex < soundBuffer->sampleCount; sampleIndex++) {
state->tSine += 2.0f * PI32 / (real32)wavePeriod;
int16 sampleValue = (int16)(sin(state->tSine) * (real32)toneVolume);
*sampleOut++ = sampleValue;
*sampleOut++ = sampleValue;
}
#endif
}
internal void renderWeirdGradient(GameOffscreenBuffer *buffer, int xOffset, int yOffset) {
uint8 *row = (uint8 *)buffer->memory;
for (int y = 0; y < buffer->height; y++) {
uint32 *pixel = (uint32*)row;
for (int x = 0; x < buffer->width; x++) {
uint8 blue = (uint8)(x + xOffset);
uint8 green = (uint8)(y + yOffset);
*pixel++ = (green << 8) | blue;
} }
row += buffer->pitch; row += buffer->pitch;
} }
} }
internal void outputSound(GameSoundOutputBuffer *soundBuffer, GameState *state) {
int16 toneVolume = 3000;
int16 *sampleOut = soundBuffer->samples;
for (int sampleIndex = 0; sampleIndex < soundBuffer->sampleCount; sampleIndex++) {
int16 sampleValue = 0;
*sampleOut++ = sampleValue;
*sampleOut++ = sampleValue;
}
}
internal void initialiseArena(MemoryArena *arena, memory_index size, uint8 *base) {
arena->size = size;
arena->base = base;
arena->used = 0;
}
internal void *_pushSize(MemoryArena *arena, memory_index size) {
Assert((arena->used + size) <= arena->size);
void *result = (void *)(arena->base + arena->used);
arena->used += size;
return result;
}
#define pushStruct(arena, type) (type *)_pushSize(arena, sizeof(type))
#define pushArray(arena, count, type) (type *)_pushSize(arena, (count)*sizeof(type))
extern "C" GAME_UPDATE_AND_RENDER(gameUpdateAndRender) { extern "C" GAME_UPDATE_AND_RENDER(gameUpdateAndRender) {
Assert(sizeof(GameState) <= memory->permanentStorageSize); Assert(sizeof(GameState) <= memory->permanentStorageSize);
GameState *state = (GameState*)memory->permanentStorage; GameState *state = (GameState*)memory->permanentStorage;
const int WORLD_WIDTH = 2;
const int WORLD_HEIGHT = 2;
if (!memory->isInitialised) { if (!memory->isInitialised) {
DebugReadFileResult bmpMem = memory->debugReadEntireFile(ctx, __FILE__); state->playerPos.absTileX = 3;
if (bmpMem.contents) { state->playerPos.absTileY = 3;
if (false) { state->playerPos.x = 5.0f;
memory->debugWriteEntireFile(ctx, "c:/source/repos/handmade/src/test.cpp", bmpMem.contentsSize, bmpMem.contents); state->playerPos.y = 5.0f;
initialiseArena(
&state->worldArena,
memory->permanentStorageSize - sizeof(GameState),
(uint8*)memory->permanentStorage + sizeof(GameState)
);
state->world = pushStruct(&state->worldArena, World);
World *world = state->world;
world->tileMap = pushStruct(&state->worldArena, TileMap);
TileMap *tileMap = state->world->tileMap;
tileMap->chunkShift = 8;
tileMap->chunkMask = 0xFF;
tileMap->chunkDim = 256;
tileMap->tileChunkCountX = 4;
tileMap->tileChunkCountY = 4;
tileMap->tileSideInMeters = 1.4f;
tileMap->tileSideInPixels = 60;
tileMap->metersToPixels = tileMap->tileSideInPixels / tileMap->tileSideInMeters;
tileMap->tileChunks = pushArray(&state->worldArena, tileMap->tileChunkCountX*tileMap->tileChunkCountY, TileChunk);
for (uint32 y = 0; y < tileMap->tileChunkCountY; y++) {
for (uint32 x = 0; x < tileMap->tileChunkCountX; x++) {
tileMap->tileChunks[y*tileMap->tileChunkCountX + x].tiles = pushArray(&state->worldArena, tileMap->chunkDim*tileMap->chunkDim, uint32);
}
}
uint32 tilesPerWidth = 17;
uint32 tilesPerHeight = 9;
for (uint32 screenY = 0; screenY < 32; screenY++) {
for (uint32 screenX = 0; screenX < 32; screenX++) {
for (uint32 tileY = 0; tileY < tilesPerHeight; tileY++) {
for (uint32 tileX = 0; tileX < tilesPerWidth; tileX++) {
uint32 absTileX = screenX*tilesPerWidth + tileX;
uint32 absTileY = screenY*tilesPerHeight + tileY;
setTileMapValue(&state->worldArena, tileMap, absTileX, absTileY, (tileX == tileY && (tileX % 5 == 0)));
}
}
} }
memory->debugFreeFileMemory(ctx, bmpMem.contents);
} }
state->toneHz = 440;
state->tSine = 0;
state->playerY = 100;
state->playerX = 100;
state->blueOffset = 0;
state->greenOffset = 0;
memory->isInitialised = true; memory->isInitialised = true;
} }
real32 screenCenterX = 0.5f*(real32)videoBuf->width;
real32 screenCenterY = 0.5f*(real32)videoBuf->height;
// uint32 tiles[TILEMAP_WIDTH][TILEMAP_HEIGHT] = {
// {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
// {1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
// {1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1},
// {1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1},
// {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
// {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
// };
TileMap *tilemap = state->world->tileMap;
// player
real32 playerR = 1.0f;
real32 playerG = 1.0f;
real32 playerB = 0.5f;
real32 playerWidth = 0.7f;
real32 playerHeight = 1.4f;
for (int controllerIndex = 0; controllerIndex < ArrayCount(input->controllers); controllerIndex++) { for (int controllerIndex = 0; controllerIndex < ArrayCount(input->controllers); controllerIndex++) {
GameControllerInput *controllerInput = &input->controllers[controllerIndex]; GameControllerInput *controller = &input->controllers[controllerIndex];
if (controllerInput->btnDown.endedDown) { real32 dPlayerX = 0.0f;
state->playerY -= 30; real32 dPlayerY = 0.0f;
if (controller->stickUp.endedDown) {
dPlayerY = 1.0f;
}
if (controller->stickDown.endedDown) {
dPlayerY = -1.0f;
}
if (controller->stickLeft.endedDown) {
dPlayerX = -1.0f;
}
if (controller->stickRight.endedDown) {
dPlayerX = 1.0f;
} }
if (controllerInput->stickRight.endedDown) { dPlayerX *= 6.0f;
state->playerX += 10; dPlayerY *= 6.0f;
}
if (controllerInput->stickLeft.endedDown) { TileMapPosition newPlayerPos = state->playerPos;
state->playerX -= 10; newPlayerPos.x += dPlayerX * input->dtForFrame;
} newPlayerPos.y += dPlayerY * input->dtForFrame;
if (controllerInput->stickDown.endedDown) { newPlayerPos = recanonicalisePosition(tilemap, newPlayerPos);
state->playerY += 10;
} TileMapPosition playerBottomLeft = newPlayerPos;
if (controllerInput->stickUp.endedDown) { playerBottomLeft.x -= 0.5f * playerWidth;
state->playerY -= 10; playerBottomLeft = recanonicalisePosition(tilemap, playerBottomLeft);
TileMapPosition playerTopLeft = newPlayerPos;
playerTopLeft.x -= 0.5f * playerWidth;
playerTopLeft.y += playerWidth;
playerTopLeft = recanonicalisePosition(tilemap, playerTopLeft);
TileMapPosition playerBottomRight = newPlayerPos;
playerBottomRight.x += 0.5f * playerWidth;
playerBottomRight = recanonicalisePosition(tilemap, playerBottomRight);
TileMapPosition playerTopRight = newPlayerPos;
playerTopRight.x += 0.5f * playerWidth;
playerTopRight.y += playerWidth;
playerTopRight = recanonicalisePosition(tilemap, playerTopRight);
if (
isTileMapPointEmpty(tilemap, playerTopLeft) &&
isTileMapPointEmpty(tilemap, playerTopRight) &&
isTileMapPointEmpty(tilemap, playerBottomLeft) &&
isTileMapPointEmpty(tilemap, playerBottomRight)
) {
state->playerPos = newPlayerPos;
} }
} }
renderWeirdGradient(videoBuf, state->greenOffset, state->blueOffset); // clearscreen
renderSmallRect(videoBuf, state->playerX, state->playerY); drawRectangle(videoBuf, 0.0f, 0.0f, (real32)videoBuf->width, (real32)videoBuf->height, 1.0f, 0.0f, 1.0f);
renderSmallRect(videoBuf, input->mouseX, input->mouseY);
for (int i = 0; i < ArrayCount(input->mouseButtons); i++) { for (int32 relRow = -10; relRow < 10; relRow++) {
if (input->mouseButtons[i].endedDown) { for (int32 relCol = -20; relCol < 20; relCol++) {
renderSmallRect(videoBuf, 10 + i * 20, 10); uint32 col = state->playerPos.absTileX + relCol;
uint32 row = state->playerPos.absTileY + relRow;
int32 tileId = getTileValue(tilemap, col, row);
real32 fill = 0.5f;
if (tileId == 1) {
fill = 1.0f;
}
if ((row == state->playerPos.absTileY) && (col == state->playerPos.absTileX)) {
fill = 0.0f;
}
real32 minX = screenCenterX - tilemap->metersToPixels*state->playerPos.x + ((real32)relCol)*tilemap->tileSideInPixels;
real32 minY = screenCenterY + tilemap->metersToPixels*state->playerPos.y - ((real32)relRow)*tilemap->tileSideInPixels;
real32 maxX = minX + tilemap->tileSideInPixels;
real32 maxY = minY - tilemap->tileSideInPixels;
drawRectangle(videoBuf, minX, maxY, maxX, minY, fill, fill, fill);
} }
} }
real32 playerLeft = screenCenterX - 0.5f*tilemap->metersToPixels*playerWidth;
real32 playerTop = screenCenterY - tilemap->metersToPixels*playerHeight;
drawRectangle(videoBuf, playerLeft, playerTop, playerLeft + tilemap->metersToPixels*playerWidth, playerTop + tilemap->metersToPixels*playerHeight, playerR, playerG, playerB);
} }
extern "C" GAME_GET_SOUND_SAMPLES(gameGetSoundSamples) { extern "C" GAME_GET_SOUND_SAMPLES(gameGetSoundSamples) {
outputSineSound(soundBuf, (GameState*)memory->permanentStorage); outputSound(soundBuf, (GameState*)memory->permanentStorage);
} }

View File

@@ -1,9 +1,8 @@
#pragma once
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <math.h>
#pragma once
/* /*
* --------------- * ---------------
@@ -46,11 +45,15 @@ typedef uint16_t uint16;
typedef uint32_t uint32; typedef uint32_t uint32;
typedef uint64_t uint64; typedef uint64_t uint64;
typedef size_t MemoryIndex;
typedef int8_t int8; typedef int8_t int8;
typedef int16_t int16; typedef int16_t int16;
typedef int32_t int32; typedef int32_t int32;
typedef int64_t int64; typedef int64_t int64;
typedef size_t memory_index;
typedef float real32; typedef float real32;
typedef double real64; typedef double real64;
@@ -137,6 +140,7 @@ struct GameInput {
int32 mouseX; int32 mouseX;
int32 mouseY; int32 mouseY;
int32 mouseZ; int32 mouseZ;
real32 dtForFrame;
GameControllerInput controllers[5]; GameControllerInput controllers[5];
}; };
@@ -152,13 +156,23 @@ struct GameMemory {
DebugPrintfFn *debug_printf; DebugPrintfFn *debug_printf;
}; };
#include "handmade_tile.h"
#include "handmade_intrinsics.h"
struct World {
TileMap *tileMap;
};
struct MemoryArena {
memory_index size;
uint8 *base;
memory_index used;
};
struct GameState { struct GameState {
int toneHz; TileMapPosition playerPos;
int greenOffset; World *world;
int blueOffset; MemoryArena worldArena;
real32 tSine;
int playerY;
int playerX;
}; };
// === Game to platform services === // === Game to platform services ===

37
src/handmade_intrinsics.h Normal file
View File

@@ -0,0 +1,37 @@
#pragma once
#include "handmade.h"
#include "math.h"
#define PI32 3.141592653589f
inline int32 roundReal32ToUInt32(real32 realNum) {
return (uint32)(realNum + 0.5f);
}
inline int32 roundReal32ToInt32(real32 realNum) {
return (int32)(realNum + 0.5f);
}
inline int32 floorReal32ToInt32(real32 realNum) {
return (int32)floorf(realNum);
}
inline int32 truncateReal32ToInt32(real32 realNum) {
return (int32)realNum;
}
inline real32 sin(real32 angle) {
return sinf(angle);
}
inline real32 cos(real32 angle) {
return cosf(angle);
}
inline real32 atan2(real32 y, real32 x) {
return atan2f(y, x);
}
inline uint32 absoluteInt32ToUInt32(int32 signedInt32) {
return signedInt32 > 0 ? (uint32)signedInt32 : (uint32)(-1*signedInt32);
}

95
src/handmade_tile.cpp Normal file
View File

@@ -0,0 +1,95 @@
#pragma once
#include "handmade.h"
inline TileChunk *getTileChunk(TileMap *tileMap, uint32 tileChunkX, uint32 tileChunkY) {
TileChunk *tileChunk = NULL;
if ((tileChunkX >= 0) && (tileChunkX < tileMap->tileChunkCountX) &&
(tileChunkY >= 0) && (tileChunkY < tileMap->tileChunkCountY)
) {
tileChunk = &tileMap->tileChunks[tileChunkY * tileMap->tileChunkCountX + tileChunkX];
}
return tileChunk;
}
inline void recanonicaliseOrd(TileMap *tileMap, uint32 *tileOrd, real32* ord) {
int32 offset = floorReal32ToInt32(*ord / tileMap->tileSideInMeters);
*tileOrd += offset;
*ord -= offset*tileMap->tileSideInMeters;
Assert(*ord >= 0.0f);
Assert(*ord < tileMap->tileSideInMeters);
}
inline TileChunkPosition getChunkPosition(TileMap* tileMap, uint32 absTileX, uint32 absTileY) {
TileChunkPosition result = {};
result.tileChunkX = absTileX >> tileMap->chunkShift;
result.tileChunkY = absTileY >> tileMap->chunkShift;
result.relTileX = absTileX & tileMap->chunkMask;
result.relTileY = absTileY & tileMap->chunkMask;
return result;
}
inline uint32 getTileValueUnchecked(TileMap *tileMap, TileChunk *tileChunk, uint32 testTileX, uint32 testTileY) {
Assert(tileChunk);
Assert(testTileX < tileMap->chunkDim);
Assert(testTileY < tileMap->chunkDim);
return tileChunk->tiles[testTileY * tileMap->chunkDim + testTileX];
}
inline void setTileValueUnchecked(TileMap *tileMap, TileChunk *tileChunk, uint32 testTileX, uint32 testTileY, uint32 tileValue) {
Assert(tileChunk);
Assert(testTileX < tileMap->chunkDim);
Assert(testTileY < tileMap->chunkDim);
tileChunk->tiles[testTileY * tileMap->chunkDim + testTileX] = tileValue;
}
inline uint32 getTileValue(TileMap *tileMap, TileChunk* tileChunk, uint32 testTileX, uint32 testTileY) {
uint32 tileValue = 0;
if (tileChunk) {
tileValue = getTileValueUnchecked(tileMap, tileChunk, testTileX, testTileY);
}
return tileValue;
}
inline void setTileValue(TileMap *tileMap, TileChunk* tileChunk, uint32 testTileX, uint32 testTileY, uint32 tileValue) {
if (tileChunk) {
setTileValueUnchecked(tileMap, tileChunk, testTileX, testTileY, tileValue);
}
}
inline uint32 getTileValue(TileMap *tileMap, uint32 testTileX, uint32 testTileY) {
uint32 tileValue = 0;
TileChunkPosition chunkPos = getChunkPosition(tileMap, testTileX, testTileY);
TileChunk *tileChunk = getTileChunk(tileMap, chunkPos.tileChunkX, chunkPos.tileChunkY);
tileValue = getTileValue(tileMap, tileChunk, testTileX, testTileY);
return tileValue;
}
inline TileMapPosition recanonicalisePosition(TileMap *tileMap, TileMapPosition pos) {
TileMapPosition result = pos;
recanonicaliseOrd(tileMap, &result.absTileX, &result.x);
recanonicaliseOrd(tileMap, &result.absTileY, &result.y);
return result;
}
internal bool32 isTileMapPointEmpty(TileMap *tileMap, TileMapPosition testPos) {
bool32 isEmpty = false;
TileChunkPosition chunkPos = getChunkPosition(tileMap, testPos.absTileX, testPos.absTileY);
TileChunk *tileChunk = getTileChunk(tileMap, chunkPos.tileChunkX, chunkPos.tileChunkY);
isEmpty = (getTileValue(tileMap, tileChunk, chunkPos.relTileX, chunkPos.relTileY) == 0);
return isEmpty;
}
internal void setTileMapValue(MemoryArena *arena, TileMap *tileMap, uint32 absTileX, uint32 absTileY, uint32 tileValue) {
TileChunkPosition chunkPos = getChunkPosition(tileMap, absTileX, absTileY);
TileChunk *tileChunk = getTileChunk(tileMap, chunkPos.tileChunkX, chunkPos.tileChunkY);
Assert(tileChunk);
setTileValue(tileMap, tileChunk, chunkPos.relTileX, chunkPos.relTileY, tileValue);
}

41
src/handmade_tile.h Normal file
View File

@@ -0,0 +1,41 @@
#pragma once
#include "handmade.h"
struct TileChunk {
uint32 *tiles;
};
struct TileChunkPosition {
uint32 tileChunkX;
uint32 tileChunkY;
uint32 relTileX;
uint32 relTileY;
};
struct TileMapPosition {
// tile map x and y and tile x and y packed, lower 8 bits are tile X,Y and upper 24 bits map X,Y
// ---- ---- ---- ---- ---- ---- : ---- ----
// TILE MAP ORD : TILE ORD
uint32 absTileX;
uint32 absTileY;
// Sub-tile position
real32 x;
real32 y;
};
struct TileMap {
uint32 chunkShift;
uint32 chunkMask;
uint32 chunkDim;
real32 tileSideInMeters;
int32 tileSideInPixels;
real32 metersToPixels;
uint32 tileChunkCountX;
uint32 tileChunkCountY;
TileChunk *tileChunks;
};

View File

@@ -128,9 +128,18 @@ internal Win32WindowDimensions win32GetWindowDimensions(HWND window) {
internal void win32DrawBufferInWindow(Win32OffscreenBuffer *buffer, HWND window) { internal void win32DrawBufferInWindow(Win32OffscreenBuffer *buffer, HWND window) {
Win32WindowDimensions winDims = win32GetWindowDimensions(window); Win32WindowDimensions winDims = win32GetWindowDimensions(window);
StretchDIBits( HDC dc = GetDC(window);
GetDC(window),
0, 0, winDims.width, winDims.height, int offsetX = 10;
int offsetY = 10;
PatBlt(dc, 0, 0, winDims.width, offsetY, BLACKNESS);
PatBlt(dc, 0, offsetY + buffer->height, winDims.width, winDims.height, BLACKNESS);
PatBlt(dc, 0, 0, offsetX, winDims.height, BLACKNESS);
PatBlt(dc, offsetX + buffer->width, 0, winDims.width, winDims.height, BLACKNESS);
StretchDIBits(dc,
offsetX, offsetY, buffer->width, buffer->height,
0, 0, buffer->width, buffer->height, 0, 0, buffer->width, buffer->height,
buffer->memory, buffer->memory,
&buffer->info, &buffer->info,
@@ -519,8 +528,8 @@ void win32GetFullPathToLocalFile(Win32State *state, char *filename, int filename
catStrings(state->onePastLastExeFilenameSlash - state->exeFilename, state->exeFilename, filenameSize, filename, (size_t)MAX_PATH, maxPathBuffer); catStrings(state->onePastLastExeFilenameSlash - state->exeFilename, state->exeFilename, filenameSize, filename, (size_t)MAX_PATH, maxPathBuffer);
} }
#define WINDOW_WIDTH 1280 #define WINDOW_WIDTH 960
#define WINDOW_HEIGHT 720 #define WINDOW_HEIGHT 540
int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLine, int commandShow) { int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLine, int commandShow) {
Win32State win32State = {}; Win32State win32State = {};
@@ -649,6 +658,8 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, PSTR commandLin
int64 lastCycleCount = __rdtsc(); int64 lastCycleCount = __rdtsc();
while (globalRunning) { while (globalRunning) {
newInput->dtForFrame = targetSecondsPerFrame;
FILETIME newWriteTime = win32GetLastWriteTime(sourceGameCodeDLLFullPath); FILETIME newWriteTime = win32GetLastWriteTime(sourceGameCodeDLLFullPath);
if (CompareFileTime(&newWriteTime, &game.lastWriteTime) != 0) { if (CompareFileTime(&newWriteTime, &game.lastWriteTime) != 0) {
win32UnloadGameCode(&game); win32UnloadGameCode(&game);