aboutsummaryrefslogtreecommitdiff
path: root/code/handmade.cpp
diff options
context:
space:
mode:
authorRaymaekers Luca <luca@spacehb.net>2025-08-25 13:44:00 +0200
committerRaymaekers Luca <luca@spacehb.net>2025-08-25 13:44:00 +0200
commit6f91de58faa3436a5c59fddaccb7418bd579117b (patch)
tree3b8d3fc1b1733d82f4b862226be895460572444e /code/handmade.cpp
parent10c5eaf9eaac3d550be2a05ab8a89157276bc336 (diff)
checkpoint
Diffstat (limited to 'code/handmade.cpp')
-rw-r--r--code/handmade.cpp749
1 files changed, 401 insertions, 348 deletions
diff --git a/code/handmade.cpp b/code/handmade.cpp
index 8a5b5ff..fb96977 100644
--- a/code/handmade.cpp
+++ b/code/handmade.cpp
@@ -1,15 +1,38 @@
#include "handmade.h"
#include "handmade_random.h"
-#include "handmade_graph.cpp"
-#define STB_TRUETYPE_IMPLEMENTATION
-#include "libs/stb_truetype.h"
+#include <curl/curl.h>
+#define STB_SPRINTF_IMPLEMENTATION
+#include "libs/stb_sprintf.h"
-// TODO(luca): Get rid of these.
+// TODO(luca): Get rid of this, do note that time.h is already included by curl.
#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
+//- Helpers
+internal color_rgb
+GetColorRGBForColorIndex(u32 Index)
+{
+ color_rgb Result = {};
+ color_rgb ColorGray = {0.23f, 0.23f, 0.24f};
+ color_rgb ColorYellow = {0.71f, 0.62f, 0.23f};
+ color_rgb ColorGreen = {0.32f, 0.55f, 0.31f};
+
+ if(0) {}
+ else if(Index == SquareColor_Gray) Result = ColorGray;
+ else if(Index == SquareColor_Yellow) Result = ColorYellow;
+ else if(Index == SquareColor_Green) Result = ColorGreen;
+
+ return Result;
+}
+
+void MemoryCopy(void *Dest, void *Source, size_t Count)
+{
+ u8 *DestinationByte = (u8 *)Dest;
+ u8 *SourceByte = (u8 *)Source;
+ while(Count--) *DestinationByte++ = *SourceByte++;
+}
+
+//- Sound
internal s16
GetSineSound(u32 SampleRate)
{
@@ -52,31 +75,7 @@ GameOutputSound(game_state *GameState, game_sound_output_buffer *SoundBuffer)
}
}
-internal void
-RenderWeirdGradient(game_offscreen_buffer *Buffer, int BlueOffset, int GreenOffset)
-{
- // TODO(casey): Let's see what the optimizer does
-
- u8 *Row = (u8 *)Buffer->Memory;
- for(int Y = 0;
- Y < Buffer->Height;
- ++Y)
- {
- u32 *Pixel = (u32 *)Row;
- for(int X = 0;
- X < Buffer->Width;
- ++X)
- {
- u8 Blue = (u8)(X + BlueOffset);
- u8 Green = (u8)(Y + GreenOffset);
-
- *Pixel++ = (Green | Blue);
- }
-
- Row += Buffer->Pitch;
- }
-}
-
+//- Rendering
internal void
DrawRectangle(game_offscreen_buffer *Buffer,
v2 vMin, v2 vMax,
@@ -135,6 +134,154 @@ DrawRectangle(game_offscreen_buffer *Buffer,
}
internal void
+DrawCharacter(game_offscreen_buffer *Buffer, u8 *FontBitmap,
+ int FontWidth, int FontHeight,
+ int XOffset, int YOffset,
+ color_rgb Color)
+{
+ s32 MinX = 0;
+ s32 MinY = 0;
+ s32 MaxX = FontWidth;
+ s32 MaxY = FontHeight;
+
+ if(XOffset < 0)
+ {
+ MinX = -XOffset;
+ XOffset = 0;
+ }
+ if(YOffset < 0)
+ {
+ MinY = -YOffset;
+ YOffset = 0;
+ }
+ if(XOffset + FontWidth > Buffer->Width)
+ {
+ MaxX -= ((XOffset + FontWidth) - Buffer->Width);
+ }
+ if(YOffset + FontHeight > Buffer->Height)
+ {
+ MaxY -= ((YOffset + FontHeight) - Buffer->Height);
+ }
+
+ u8 *Row = (u8 *)(Buffer->Memory) +
+ (YOffset*Buffer->Pitch) +
+ (XOffset*Buffer->BytesPerPixel);
+
+ for(int Y = MinY;
+ Y < MaxY;
+ Y++)
+ {
+ u32 *Pixel = (u32 *)Row;
+ for(int X = MinX;
+ X < MaxX;
+ X++)
+ {
+ u8 Brightness = FontBitmap[Y*FontWidth+X];
+ r32 Alpha = ((r32)Brightness/255.0f);
+
+ r32 DR = (r32)((*Pixel >> 16) & 0xFF);
+ r32 DG = (r32)((*Pixel >> 8) & 0xFF);
+ r32 DB = (r32)((*Pixel >> 0) & 0xFF);
+
+ r32 R = Color.R*255.0f*Alpha + DR*(1-Alpha);
+ r32 G = Color.G*255.0f*Alpha + DG*(1-Alpha);
+ r32 B = Color.B*255.0f*Alpha + DB*(1-Alpha);
+
+ u32 Value = ((0xFF << 24) |
+ ((u32)(R) << 16) |
+ ((u32)(G) << 8) |
+ ((u32)(B) << 0));
+ *Pixel++ = Value;
+ }
+
+ Row += Buffer->Pitch;
+ }
+}
+
+internal void
+DrawText(game_offscreen_buffer *Buffer, game_font *Font, r32 FontScale,
+ u32 TextLen, u8 *Text, v2 Offset, color_rgb Color, b32 IsUTF8)
+{
+ Assert(Font->Initialized);
+
+ for(u32 TextIndex = 0;
+ TextIndex < TextLen;
+ TextIndex++)
+ {
+ rune CharAt = 0;
+ if(IsUTF8)
+ {
+ CharAt = *(((rune *)Text) + TextIndex);
+ }
+ else
+ {
+ CharAt = Text[TextIndex];
+ }
+
+ s32 FontWidth, FontHeight;
+ s32 AdvanceWidth, LeftSideBearing;
+ s32 X0, Y0, X1, Y1;
+ u8 *FontBitmap = 0;
+ // TODO(luca): Get rid of malloc.
+ FontBitmap = stbtt_GetCodepointBitmap(&Font->Info,
+ FontScale, FontScale,
+ CharAt,
+ &FontWidth, &FontHeight, 0, 0);
+ stbtt_GetCodepointBitmapBox(&Font->Info, CharAt,
+ FontScale, FontScale,
+ &X0, &Y0, &X1, &Y1);
+ r32 YOffset = Offset.Y + Y0;
+ stbtt_GetCodepointHMetrics(&Font->Info, CharAt, &AdvanceWidth, &LeftSideBearing);
+ r32 XOffset = Offset.X + LeftSideBearing*FontScale;
+
+ DrawCharacter(Buffer, FontBitmap, FontWidth, FontHeight, XOffset, YOffset, Color);
+
+ Offset.X += (AdvanceWidth*FontScale);
+ free(FontBitmap);
+ }
+}
+
+internal void
+DrawTextWithAlternatingFonts(game_font *Font1, game_font *Font2,
+ game_offscreen_buffer *Buffer,
+ r32 FontScale,
+ rune *Text, u32 TextLen, v2 Offset, color_rgb Color)
+{
+ b32 FontToggle = false;
+ for(u32 TextIndex = 0;
+ TextIndex < TextLen;
+ TextIndex++)
+ {
+ FontToggle = !FontToggle;
+ game_font *Font = (FontToggle) ? Font1 : Font2;
+ Assert(Font->Initialized);
+
+ rune CharAt = Text[TextIndex];
+
+ s32 FontWidth, FontHeight;
+ s32 AdvanceWidth, LeftSideBearing;
+ s32 X0, Y0, X1, Y1;
+ u8 *FontBitmap = 0;
+ // TODO(luca): Get rid of malloc.
+ FontBitmap = stbtt_GetCodepointBitmap(&Font->Info,
+ FontScale, FontScale,
+ CharAt,
+ &FontWidth, &FontHeight, 0, 0);
+ stbtt_GetCodepointBitmapBox(&Font->Info, CharAt,
+ FontScale, FontScale,
+ &X0, &Y0, &X1, &Y1);
+ r32 YOffset = Offset.Y + Y0;
+ stbtt_GetCodepointHMetrics(&Font->Info, CharAt, &AdvanceWidth, &LeftSideBearing);
+ r32 XOffset = Offset.X + LeftSideBearing*FontScale;
+
+ DrawCharacter(Buffer, FontBitmap, FontWidth, FontHeight, XOffset, YOffset, Color);
+
+ Offset.X += (AdvanceWidth*FontScale);
+ free(FontBitmap);
+ }
+}
+
+internal void
DrawBitmap(game_offscreen_buffer *Buffer, loaded_bitmap Bitmap,
r32 RealX, r32 RealY,
s32 AlignX = 0, s32 AlignY = 0)
@@ -218,12 +365,6 @@ DrawBitmap(game_offscreen_buffer *Buffer, loaded_bitmap Bitmap,
}
-internal inline
-void MemCpy(char *Dest, char *Source, size_t Count)
-{
- while(Count--) *Dest++ = *Source++;
-}
-
#pragma pack(push, 1)
struct bitmap_header
{
@@ -311,154 +452,7 @@ DEBUGLoadBMP(thread_context *Thread, debug_platform_read_entire_file *DEBUGPlatf
return Result;
}
-internal void
-DrawCharacter(game_offscreen_buffer *Buffer, u8 *FontBitmap,
- int FontWidth, int FontHeight,
- int XOffset, int YOffset,
- color_rgb Color)
-{
- s32 MinX = 0;
- s32 MinY = 0;
- s32 MaxX = FontWidth;
- s32 MaxY = FontHeight;
-
- if(XOffset < 0)
- {
- MinX = -XOffset;
- XOffset = 0;
- }
- if(YOffset < 0)
- {
- MinY = -YOffset;
- YOffset = 0;
- }
- if(XOffset + FontWidth > Buffer->Width)
- {
- MaxX -= ((XOffset + FontWidth) - Buffer->Width);
- }
- if(YOffset + FontHeight > Buffer->Height)
- {
- MaxY -= ((YOffset + FontHeight) - Buffer->Height);
- }
-
- u8 *Row = (u8 *)(Buffer->Memory) +
- (YOffset*Buffer->Pitch) +
- (XOffset*Buffer->BytesPerPixel);
-
- for(int Y = MinY;
- Y < MaxY;
- Y++)
- {
- u32 *Pixel = (u32 *)Row;
- for(int X = MinX;
- X < MaxX;
- X++)
- {
- u8 Brightness = FontBitmap[Y*FontWidth+X];
- r32 Alpha = ((r32)Brightness/255.0f);
-
- r32 DR = (r32)((*Pixel >> 16) & 0xFF);
- r32 DG = (r32)((*Pixel >> 8) & 0xFF);
- r32 DB = (r32)((*Pixel >> 0) & 0xFF);
-
- r32 R = Color.R*255.0f*Alpha + DR*(1-Alpha);
- r32 G = Color.G*255.0f*Alpha + DG*(1-Alpha);
- r32 B = Color.B*255.0f*Alpha + DB*(1-Alpha);
-
- u32 Value = ((0xFF << 24) |
- ((u32)(R) << 16) |
- ((u32)(G) << 8) |
- ((u32)(B) << 0));
- *Pixel++ = Value;
- }
-
- Row += Buffer->Pitch;
- }
-}
-
-internal void
-DrawText(game_offscreen_buffer *Buffer, game_font *Font, r32 FontScale,
- u32 TextLen, u8 *Text, v2 Offset, color_rgb Color, b32 IsUTF8)
-{
- Assert(Font->Initialized);
-
- for(u32 TextIndex = 0;
- TextIndex < TextLen;
- TextIndex++)
- {
- rune CharAt = 0;
- if(IsUTF8)
- {
- CharAt = *(((rune *)Text) + TextIndex);
- }
- else
- {
- CharAt = Text[TextIndex];
- }
-
- s32 FontWidth, FontHeight;
- s32 AdvanceWidth, LeftSideBearing;
- s32 X0, Y0, X1, Y1;
- u8 *FontBitmap = 0;
- // TODO(luca): Get rid of malloc.
- FontBitmap = stbtt_GetCodepointBitmap(&Font->Info,
- FontScale, FontScale,
- CharAt,
- &FontWidth, &FontHeight, 0, 0);
- stbtt_GetCodepointBitmapBox(&Font->Info, CharAt,
- FontScale, FontScale,
- &X0, &Y0, &X1, &Y1);
- r32 YOffset = Offset.Y + Y0;
- stbtt_GetCodepointHMetrics(&Font->Info, CharAt, &AdvanceWidth, &LeftSideBearing);
- r32 XOffset = Offset.X + LeftSideBearing*FontScale;
-
- DrawCharacter(Buffer, FontBitmap, FontWidth, FontHeight, XOffset, YOffset, Color);
-
- Offset.X += (AdvanceWidth*FontScale);
- free(FontBitmap);
- }
-}
-
-internal void
-DrawTextWithAlternatingFonts(game_font *Font1, game_font *Font2,
- game_offscreen_buffer *Buffer,
- r32 FontScale,
- rune *Text, u32 TextLen, v2 Offset, color_rgb Color)
-{
- b32 FontToggle = false;
- for(u32 TextIndex = 0;
- TextIndex < TextLen;
- TextIndex++)
- {
- FontToggle = !FontToggle;
- game_font *Font = (FontToggle) ? Font1 : Font2;
- Assert(Font->Initialized);
-
- rune CharAt = Text[TextIndex];
-
- s32 FontWidth, FontHeight;
- s32 AdvanceWidth, LeftSideBearing;
- s32 X0, Y0, X1, Y1;
- u8 *FontBitmap = 0;
- // TODO(luca): Get rid of malloc.
- FontBitmap = stbtt_GetCodepointBitmap(&Font->Info,
- FontScale, FontScale,
- CharAt,
- &FontWidth, &FontHeight, 0, 0);
- stbtt_GetCodepointBitmapBox(&Font->Info, CharAt,
- FontScale, FontScale,
- &X0, &Y0, &X1, &Y1);
- r32 YOffset = Offset.Y + Y0;
- stbtt_GetCodepointHMetrics(&Font->Info, CharAt, &AdvanceWidth, &LeftSideBearing);
- r32 XOffset = Offset.X + LeftSideBearing*FontScale;
-
- DrawCharacter(Buffer, FontBitmap, FontWidth, FontHeight, XOffset, YOffset, Color);
-
- Offset.X += (AdvanceWidth*FontScale);
- free(FontBitmap);
- }
-}
-
+//- Wordled
internal b32
ValidLetterCountInGuess(rune *Word, u8 *Guess, rune Letter)
{
@@ -485,71 +479,133 @@ ValidLetterCountInGuess(rune *Word, u8 *Guess, rune Letter)
return Valid;
}
-internal void
-GetTodaysWordle(thread_context *Thread, game_memory *Memory, char *Word)
+//- Curl
+internal psize
+CurlCBLog(void *Buffer, psize ItemsSize, psize Size, void *UserPointer)
{
- struct tm *LocalTimeNow = 0;
+ psize Result = 0;
+ if(Size == 1)
+ {
+ Result = ItemsSize;
+ }
+ else
+ {
+ Result = Size;
+ }
+
+ Log((char *)Buffer);
+ return Result;
+}
+
+internal psize
+CurlCBWriteToArena(void *Buffer, psize Size, psize DataSize, void *UserPointer)
+{
+ Assert(Size == 1);
+ psize Result = DataSize;
+
+ memory_arena *Arena = (memory_arena *)UserPointer;
+
+ MemoryCopy((Arena->Base + Arena->Used), Buffer, DataSize);
+ Assert(Arena->Used + DataSize <= Arena->Size);
+ Arena->Used += DataSize;
+
+ return Result;
+}
+
+struct get_todays_wordle_curl_params
+{
+ b32 *Done;
+ memory_arena *Arena;
+ rune *Word;
+};
+
+PLATFORM_WORK_QUEUE_CALLBACK(GetTodaysWordleCurl)
+{
+ memory_arena *Arena = ((get_todays_wordle_curl_params *)Data)->Arena;
+ b32 *Done = ((get_todays_wordle_curl_params *)Data)->Done;
+ rune *Word = ((get_todays_wordle_curl_params *)Data)->Word;
+
+ char URL[] = "https://www.nytimes.com/svc/wordle/v2";
+
time_t Now = 0;
time(&Now);
- LocalTimeNow = localtime(&Now);
+ struct tm *LocalTimeNow = localtime(&Now);
- char URL[] = "https://www.nytimes.com/svc/wordle/v2";
- char URLBuffer[256] = {0};
- sprintf(URLBuffer, "%s/%d-%02d-%d.json", URL,
- LocalTimeNow->tm_year + 1900, LocalTimeNow->tm_mon + 1, LocalTimeNow->tm_mday);
- char OutputBuffer[4096] = {0};
- char *Command[] =
- {
- "/usr/bin/curl",
- "--silent",
- "--location",
- "--max-time", "10",
- URLBuffer, 0
- };
+ u8 URLBuffer[256] = {};
+ stbsp_sprintf((char *)URLBuffer, "%s/%d-%02d-%d.json", URL,
+ LocalTimeNow->tm_year + 1900,
+ LocalTimeNow->tm_mon + 1,
+ LocalTimeNow->tm_mday);
+
+ psize StartPos = Arena->Used;
+
+ CURL *CurlHandle = curl_easy_init();
- // TODO(luca): This should be asynchronous at least because in the case of no internet the application would not even start.
- int BytesOutputted = Memory->PlatformRunCommandAndGetOutput(Thread, OutputBuffer, Command);
- int Matches;
- int MatchedAt = 0;
+ // NOTE(luca): init to NULL is important
+ struct curl_slist *Headers = 0;
- for(int At = 0;
- At < BytesOutputted;
- At++)
+ // NOTE(luca): Cosplay as my computer.
+ Headers = curl_slist_append(Headers, "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0");
+#if 0
+ curl_easy_setopt(CurlHandle, CURLOPT_HEADERFUNCTION, CurlCBLog);
+#endif
+
+ if(CURLE_OK == (curl_easy_setopt(CurlHandle, CURLOPT_VERBOSE, 0L)) &&
+ CURLE_OK == (curl_easy_setopt(CurlHandle, CURLOPT_URL, URLBuffer)) &&
+ CURLE_OK == (curl_easy_setopt(CurlHandle, CURLOPT_WRITEFUNCTION, CurlCBWriteToArena)) &&
+ CURLE_OK == (curl_easy_setopt(CurlHandle, CURLOPT_WRITEDATA, Arena)) &&
+ CURLE_OK == (curl_easy_setopt(CurlHandle, CURLOPT_FOLLOWLOCATION, 1L)) &&
+ CURLE_OK == (curl_easy_setopt(CurlHandle, CURLOPT_HTTPHEADER, Headers)) &&
+ CURLE_OK == (curl_easy_perform(CurlHandle)))
{
- Matches = true;
- char ScanMatch[] = "solution";
- int ScanMatchSize = sizeof(ScanMatch) - 1;
- for(int ScanAt = 0;
- ScanAt < ScanMatchSize;
- ScanAt++)
+ char *Str = (char *)(Arena->Base + StartPos);
+ psize Size = (Arena->Used - StartPos);
+
+ char MatchStr[] = "\"solution\":";
+ b32 IsMatch = false;
+ psize MatchAt = 0;
+ for(psize ScanIndex = 0;
+ ((ScanIndex < Size) && (!IsMatch));
+ ScanIndex++)
{
- if((OutputBuffer + At)[ScanAt] != ScanMatch[ScanAt])
+ MatchAt = ScanIndex;
+ IsMatch = true;
+ for(psize MatchIndex = 0;
+ ((MatchIndex < (sizeof(MatchStr) - 1)) &&
+ (MatchIndex + ScanIndex < Size));
+ MatchIndex++)
{
- Matches = false;
- break;
+ if(MatchStr[MatchIndex] != Str[ScanIndex + MatchIndex])
+ {
+ IsMatch = false;
+ break;
+ }
}
}
- if(Matches)
+
+ if(IsMatch)
{
- MatchedAt = At;
- break;
+ MatchAt += (sizeof("\"solution\":\"") - 1);
+ for(psize CharIndex = 0;
+ CharIndex < WORDLE_LENGTH;
+ CharIndex++)
+ {
+ Word[CharIndex] = Str[MatchAt + CharIndex];
+ }
}
+
}
- if(Matches)
+ else
{
- int Start = 0;
- int End = 0;
- int Scan = MatchedAt;
- while(OutputBuffer[Scan++] != '"' && Scan < BytesOutputted);
- while(OutputBuffer[Scan++] != '"' && Scan < BytesOutputted);
- Start = Scan;
- while(OutputBuffer[Scan] != '"' && Scan < BytesOutputted) Scan++;
- End = Scan;
-
- MemCpy(Word, OutputBuffer+Start, End-Start);
+ Log("Failed to get HTML.");
}
+
+ curl_easy_cleanup(CurlHandle);
+
+ *Done = true;
}
+//- Input
internal void
AppendCharToInputText(game_state *GameState, rune Codepoint)
{
@@ -559,22 +615,7 @@ AppendCharToInputText(game_state *GameState, rune Codepoint)
}
}
-internal color_rgb
-GetColorRGBForColorIndex(u32 Index)
-{
- color_rgb Color = {};
- color_rgb ColorGray = {0.23f, 0.23f, 0.24f};
- color_rgb ColorYellow = {0.71f, 0.62f, 0.23f};
- color_rgb ColorGreen = {0.32f, 0.55f, 0.31f};
-
- if(0) {}
- else if(Index == SquareColor_Gray) Color = ColorGray;
- else if(Index == SquareColor_Yellow) Color = ColorYellow;
- else if(Index == SquareColor_Green) Color = ColorGreen;
-
- return Color;
-}
-
+//- Font
internal void
InitFont(thread_context *Thread, game_font *Font, game_memory *Memory, char *FilePath)
{
@@ -604,6 +645,7 @@ InitFont(thread_context *Thread, game_font *Font, game_memory *Memory, char *Fil
}
}
+//- Game callbacks
extern "C" GAME_UPDATE_AND_RENDER(GameUpdateAndRender)
{
Assert((&Input->Controllers[0].Terminator - &Input->Controllers[0].Buttons[0]) ==
@@ -621,20 +663,15 @@ extern "C" GAME_UPDATE_AND_RENDER(GameUpdateAndRender)
GameState->SelectedColor = SquareColor_Yellow;
GameState->ExportedPatternIndex = 0;
- // TODO(luca): Better GetTodaysWordle function using libcurl.
-#if 0
- GetTodaysWordle(Thread, Memory, GameState->WordleWord);
-#else
- char *Word = "sword";
- for(u32 Count = 0; Count < 5; Count++)
- {
- GameState->WordleWord[Count] = Word[Count];
- }
-#endif
+ InitializeArena(&GameState->ScratchArena, Megabytes(1), Memory->TransientStorage);
+ GameState->WordleWordIsValid = false;
GameState->TextInputCount = 0;
GameState->TextInputMode = true;
+ Log = Memory->PlatformLog;
+ curl_global_init(CURL_GLOBAL_ALL);
+
Memory->IsInitialized = true;
}
@@ -653,7 +690,6 @@ extern "C" GAME_UPDATE_AND_RENDER(GameUpdateAndRender)
{
Assert(Controller->Text.Count < ArrayCount(Controller->Text.Buffer));
-
// TODO(luca): This should use the minimum in case where there are more keys in the Keyboard.TextInputBuffer than in GameState->TextInputText
for(u32 InputIndex = 0;
InputIndex < Controller->Text.Count;
@@ -698,8 +734,6 @@ extern "C" GAME_UPDATE_AND_RENDER(GameUpdateAndRender)
else if(Button.Codepoint == '\n' ||
Button.Codepoint == '\r')
{
- printf("Test\n");
-
for(u32 InputIndex = 0;
InputIndex < ArrayCount(GameState->WordleWord);
InputIndex++)
@@ -713,18 +747,24 @@ extern "C" GAME_UPDATE_AND_RENDER(GameUpdateAndRender)
GameState->WordleWord[InputIndex] = ' ';
}
}
- // ???
+
+ GameState->WordleWordIsValid = true;
}
else
{
// Only allow characters the Wordle game would allow.
+ if((Button.Codepoint >= 'A' &&
+ (Button.Codepoint) <= 'Z'))
+ {
+ Button.Codepoint = (Button.Codepoint - 'A') + 'a';
+ }
+
if((Button.Codepoint >= 'a' && Button.Codepoint <= 'z') || Button.Codepoint == ' ')
{
AppendCharToInputText(GameState, Button.Codepoint);
}
}
-
}
if(WasPressed(Input->MouseButtons[PlatformMouseButton_ScrollUp]))
@@ -745,6 +785,16 @@ extern "C" GAME_UPDATE_AND_RENDER(GameUpdateAndRender)
GameState->TextInputMode = !GameState->TextInputMode;
}
+ if(WasPressed(Controller->ActionUp))
+ {
+ GameState->WordleWordIsValid = false;
+ Memory->PlatformAddEntry(Memory->HighPriorityQueue, GetTodaysWordleCurl, &(get_todays_wordle_curl_params){
+ .Done = &GameState->WordleWordIsValid,
+ .Arena = &GameState->ScratchArena,
+ .Word = GameState->WordleWord,
+ });
+ }
+
}
}
}
@@ -794,7 +844,7 @@ extern "C" GAME_UPDATE_AND_RENDER(GameUpdateAndRender)
GameState->PatternGrid[Y][X] = GameState->SelectedColor;
}
Color = GetColorRGBForColorIndex(GameState->SelectedColor);
- DrawRectangle(Buffer, vMin, vMax, color_rgb(0.0f));
+ DrawRectangle(Buffer, vMin, vMax, color_rgb(0.0f)); // Change to white
DrawRectangle(Buffer,
vMin + Padding, vMax - Padding,
Color);
@@ -876,118 +926,121 @@ extern "C" GAME_UPDATE_AND_RENDER(GameUpdateAndRender)
TextOffset = v2{16.0f, 16.0f + Baseline};
- DrawText(Buffer, &DefaultFont, FontScale,
- ArrayCount(GameState->WordleWord), (u8 *)GameState->WordleWord,
- TextOffset + -v2{8.0f, 0.0f}, color_rgb(1.0f), true);
-
- TextOffset.Y += YAdvance*2.0f;
-
- //-Matche the pattern
- rune *Word = GameState->WordleWord;
- debug_read_file_result WordsFile = Memory->DEBUGPlatformReadEntireFile(Thread, "../data/words.txt");
-
- int WordsCount = WordsFile.ContentsSize / WORDLE_LENGTH;
- if(WordsFile.Contents)
+ if(GameState->WordleWordIsValid)
{
- u8 *Words = (u8 *)WordsFile.Contents;
+ DrawText(Buffer, &DefaultFont, FontScale,
+ ArrayCount(GameState->WordleWord), (u8 *)GameState->WordleWord,
+ TextOffset + -v2{8.0f, 0.0f}, color_rgb(1.0f), true);
+
+ TextOffset.Y += YAdvance*2.0f;
- s32 PatternRowAt = 0;
- s32 PatternRowsCount = 6;
+ //-Matche the pattern
+ rune *Word = GameState->WordleWord;
+ debug_read_file_result WordsFile = Memory->DEBUGPlatformReadEntireFile(Thread, "../data/words.txt");
- for(s32 WordsIndex = 0;
- ((WordsIndex < WordsCount) &&
- (PatternRowAt < PatternRowsCount));
- WordsIndex++)
+ int WordsCount = WordsFile.ContentsSize / WORDLE_LENGTH;
+ if(WordsFile.Contents)
{
- // Match the pattern's row against the guess.
- // TODO(luca): Check if the guess == the word and skip it otherwise it would end the game.
- s32 PatternMatches = 1;
- u8 *Guess = &Words[WordsIndex*(WORDLE_LENGTH+1)];
- for(s32 CharIndex = 0;
- ((CharIndex < WORDLE_LENGTH) &&
- (PatternMatches));
- CharIndex++)
+ u8 *Words = (u8 *)WordsFile.Contents;
+
+ s32 PatternRowAt = 0;
+ s32 PatternRowsCount = 6;
+
+ for(s32 WordsIndex = 0;
+ ((WordsIndex < WordsCount) &&
+ (PatternRowAt < PatternRowsCount));
+ WordsIndex++)
{
- u8 GuessCh = Guess[CharIndex];
- s32 PatternValue = GameState->PatternGrid[PatternRowAt][CharIndex];
-
- if(PatternValue == SquareColor_Green)
- {
- PatternMatches = (GuessCh == Word[CharIndex]);
- }
- else if(PatternValue == SquareColor_Yellow)
+ // Match the pattern's row against the guess.
+ // TODO(luca): Check if the guess == the word and skip it otherwise it would end the game.
+ s32 PatternMatches = 1;
+ u8 *Guess = &Words[WordsIndex*(WORDLE_LENGTH+1)];
+ for(s32 CharIndex = 0;
+ ((CharIndex < WORDLE_LENGTH) &&
+ (PatternMatches));
+ CharIndex++)
{
- PatternMatches = 0;
- for(s32 CharAt = 0;
- CharAt < WORDLE_LENGTH;
- CharAt++)
+ u8 GuessCh = Guess[CharIndex];
+ s32 PatternValue = GameState->PatternGrid[PatternRowAt][CharIndex];
+
+ if(PatternValue == SquareColor_Green)
+ {
+ PatternMatches = (GuessCh == Word[CharIndex]);
+ }
+ else if(PatternValue == SquareColor_Yellow)
{
- if(Word[CharAt] == GuessCh)
+ PatternMatches = 0;
+ for(s32 CharAt = 0;
+ CharAt < WORDLE_LENGTH;
+ CharAt++)
{
- if(CharAt != CharIndex)
+ if(Word[CharAt] == GuessCh)
{
- // TODO(luca): Should also check that position does not match.
- PatternMatches = ValidLetterCountInGuess(Word, Guess, GuessCh);
+ if(CharAt != CharIndex)
+ {
+ // TODO(luca): Should also check that position does not match.
+ PatternMatches = ValidLetterCountInGuess(Word, Guess, GuessCh);
+ }
+ else
+ {
+ PatternMatches = 0;
+ }
+
+ break;
}
- else
- {
- PatternMatches = 0;
- }
-
- break;
}
+
}
-
- }
- // TODO(luca): Have one that can be either yellow/green
+ // TODO(luca): Have one that can be either yellow/green
#if 0
- else if(PatternValue == 1)
- {
- PatternMatches = 0;
- for(s32 CharAt = 0;
- CharAt < WORDLE_LENGTH;
- CharAt++)
+ else if(PatternValue == 1)
{
- if(Word[CharAt] == GuessCh)
+ PatternMatches = 0;
+ for(s32 CharAt = 0;
+ CharAt < WORDLE_LENGTH;
+ CharAt++)
{
- PatternMatches = ValidLetterCountInGuess(Word, Guess, GuessCh);
- break;
+ if(Word[CharAt] == GuessCh)
+ {
+ PatternMatches = ValidLetterCountInGuess(Word, Guess, GuessCh);
+ break;
+ }
}
}
- }
#endif
- else if(PatternValue == SquareColor_Gray)
- {
- PatternMatches = 1;
- for(s32 CharAt = 0;
- CharAt < WORDLE_LENGTH;
- CharAt++)
+ else if(PatternValue == SquareColor_Gray)
{
- if(Word[CharAt] == GuessCh)
+ PatternMatches = 1;
+ for(s32 CharAt = 0;
+ CharAt < WORDLE_LENGTH;
+ CharAt++)
{
- PatternMatches = 0;
- break;
+ if(Word[CharAt] == GuessCh)
+ {
+ PatternMatches = 0;
+ break;
+ }
}
}
}
- }
-
- if(PatternMatches)
- {
- DrawText(Buffer, &DefaultFont, FontScale,
- WORDLE_LENGTH, Guess,
- TextOffset, color_rgb(1.0f), false);
-
- TextOffset.Y += YAdvance;
- WordsIndex = 0;
- PatternRowAt++;
+ if(PatternMatches)
+ {
+ DrawText(Buffer, &DefaultFont, FontScale,
+ WORDLE_LENGTH, Guess,
+ TextOffset, color_rgb(1.0f), false);
+
+ TextOffset.Y += YAdvance;
+
+ WordsIndex = 0;
+ PatternRowAt++;
+ }
}
}
+
+ Memory->DEBUGPlatformFreeFileMemory(Thread, WordsFile.Contents, WordsFile.ContentsSize);
}
- Memory->DEBUGPlatformFreeFileMemory(Thread, WordsFile.Contents, WordsFile.ContentsSize);
-
// NOTE(luca): Debug code for drawing inputted text.
#if 1
{