231 lines
7.7 KiB
C#
231 lines
7.7 KiB
C#
/*******************************************************************************************
|
|
*
|
|
* raylib [core] example - storage values
|
|
*
|
|
* Example complexity rating: [★★☆☆] 2/4
|
|
*
|
|
* Example originally created with raylib 1.4, last time updated with raylib 4.2
|
|
*
|
|
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
|
* BSD-like license that allows static linking with closed source software
|
|
*
|
|
* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
|
|
*
|
|
********************************************************************************************/
|
|
|
|
using static Raylib_cs.Raylib;
|
|
|
|
namespace Examples.Core;
|
|
|
|
public partial class StorageValues : IExample
|
|
{
|
|
private const int screenWidth = 800;
|
|
private const int screenHeight = 450;
|
|
private const string storageDataFile = "storage.data";
|
|
|
|
// NOTE: Storage positions must start with 0, directly related to file memory layout
|
|
private enum StorageData
|
|
{
|
|
Score,
|
|
HiScore
|
|
}
|
|
|
|
public string Name => "Core / Storage Values";
|
|
|
|
public string Title => "raylib [core] example - storage values";
|
|
|
|
private int score = 0;
|
|
private int hiscore = 0;
|
|
private int framesCounter = 0;
|
|
|
|
public void Init()
|
|
{
|
|
score = 0;
|
|
hiscore = 0;
|
|
framesCounter = 0;
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
// Update
|
|
//----------------------------------------------------------------------------------
|
|
if (IsKeyPressed(KeyboardKey.R))
|
|
{
|
|
score = GetRandomValue(1000, 2000);
|
|
hiscore = GetRandomValue(2000, 4000);
|
|
}
|
|
|
|
if (IsKeyPressed(KeyboardKey.Enter))
|
|
{
|
|
SaveStorageValue(storageDataFile, (int)StorageData.Score, score);
|
|
SaveStorageValue(storageDataFile, (int)StorageData.HiScore, hiscore);
|
|
}
|
|
else if (IsKeyPressed(KeyboardKey.Space))
|
|
{
|
|
// NOTE: If requested position could not be found, value 0 is returned
|
|
score = LoadStorageValue(storageDataFile, (int)StorageData.Score);
|
|
hiscore = LoadStorageValue(storageDataFile, (int)StorageData.HiScore);
|
|
}
|
|
|
|
framesCounter++;
|
|
//----------------------------------------------------------------------------------
|
|
|
|
// Draw
|
|
//----------------------------------------------------------------------------------
|
|
BeginDrawing();
|
|
ClearBackground(Color.RayWhite);
|
|
|
|
DrawText($"SCORE: {score}", 280, 130, 40, Color.Maroon);
|
|
DrawText($"HI-SCORE: {hiscore}", 210, 200, 50, Color.Black);
|
|
|
|
DrawText($"frames: {framesCounter}", 10, 10, 20, Color.Lime);
|
|
|
|
DrawText("Press R to generate random numbers", 220, 40, 20, Color.LightGray);
|
|
DrawText("Press ENTER to SAVE values", 250, 310, 20, Color.LightGray);
|
|
DrawText("Press SPACE to LOAD values", 252, 350, 20, Color.LightGray);
|
|
|
|
EndDrawing();
|
|
//----------------------------------------------------------------------------------
|
|
}
|
|
|
|
public void Unload()
|
|
{
|
|
}
|
|
|
|
public static int Main()
|
|
{
|
|
// Initialization
|
|
//--------------------------------------------------------------------------------------
|
|
InitWindow(screenWidth, screenHeight, "raylib [core] example - storage values");
|
|
|
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
var game = new StorageValues();
|
|
game.Init();
|
|
|
|
// Main game loop
|
|
while (!WindowShouldClose()) // Detect window close button or ESC key
|
|
{
|
|
game.Update();
|
|
}
|
|
|
|
game.Unload();
|
|
|
|
// De-Initialization
|
|
//--------------------------------------------------------------------------------------
|
|
CloseWindow(); // Close window and OpenGL context
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Save integer value to storage file (to defined position)
|
|
// NOTE: Storage positions is directly related to file memory layout (4 bytes each integer)
|
|
private static unsafe bool SaveStorageValue(string fileName, int position, int value)
|
|
{
|
|
using var fileNameBuffer = fileName.ToUtf8Buffer();
|
|
|
|
var success = false;
|
|
var dataSize = 0;
|
|
var newDataSize = 0;
|
|
|
|
var fileData = LoadFileData(fileNameBuffer.AsPointer(), &dataSize);
|
|
byte* newFileData = null;
|
|
|
|
if (fileData != null)
|
|
{
|
|
if (dataSize <= (position * sizeof(int)))
|
|
{
|
|
// Increase data size up to position and store value
|
|
newDataSize = (position + 1) * sizeof(int);
|
|
newFileData = (byte*)MemRealloc(fileData, (uint)newDataSize);
|
|
|
|
if (newFileData != null)
|
|
{
|
|
// RL_REALLOC succeded
|
|
var dataPtr = (int*)newFileData;
|
|
dataPtr[position] = value;
|
|
}
|
|
else
|
|
{
|
|
// RL_REALLOC failed
|
|
var positionInBytes = position * sizeof(int);
|
|
TraceLog(
|
|
TraceLogLevel.Warning,
|
|
@$"FILEIO: [{fileName}] Failed to realloc data ({dataSize}),
|
|
position in bytes({positionInBytes}) bigger than actual file size"
|
|
);
|
|
|
|
// We store the old size of the file
|
|
newFileData = fileData;
|
|
newDataSize = dataSize;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Store the old size of the file
|
|
newFileData = fileData;
|
|
newDataSize = dataSize;
|
|
|
|
// Replace value on selected position
|
|
var dataPtr = (int*)newFileData;
|
|
dataPtr[position] = value;
|
|
}
|
|
|
|
success = SaveFileData(fileNameBuffer.AsPointer(), newFileData, newDataSize);
|
|
MemFree(newFileData);
|
|
|
|
TraceLog(TraceLogLevel.Info, $"FILEIO: [{fileName}] Saved storage value: {value}");
|
|
}
|
|
else
|
|
{
|
|
TraceLog(TraceLogLevel.Info, $"FILEIO: [{fileName}] File created successfully");
|
|
|
|
dataSize = (position + 1) * sizeof(int);
|
|
fileData = (byte*)MemAlloc((uint)dataSize);
|
|
var dataPtr = (int*)fileData;
|
|
dataPtr[position] = value;
|
|
|
|
success = SaveFileData(fileNameBuffer.AsPointer(), fileData, dataSize);
|
|
UnloadFileData(fileData);
|
|
|
|
TraceLog(TraceLogLevel.Info, $"FILEIO: [{fileName}] Saved storage value: {value}");
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Load integer value from storage file (from defined position)
|
|
// NOTE: If requested position could not be found, value 0 is returned
|
|
private static unsafe int LoadStorageValue(string fileName, uint position)
|
|
{
|
|
using var fileNameBuffer = fileName.ToUtf8Buffer();
|
|
|
|
var value = 0;
|
|
var dataSize = 0;
|
|
var fileData = LoadFileData(fileNameBuffer.AsPointer(), &dataSize);
|
|
|
|
if (fileData != null)
|
|
{
|
|
if (dataSize < (position * 4))
|
|
{
|
|
TraceLog(
|
|
TraceLogLevel.Warning,
|
|
$"FILEIO: [{fileName}] Failed to find storage position: {value}"
|
|
);
|
|
}
|
|
else
|
|
{
|
|
var dataPtr = (int*)fileData;
|
|
value = dataPtr[position];
|
|
}
|
|
|
|
UnloadFileData(fileData);
|
|
|
|
TraceLog(TraceLogLevel.Info, $"FILEIO: [{fileName}] Loaded storage value: {value}");
|
|
}
|
|
|
|
return value;
|
|
}
|
|
}
|