Fixed setup bug and changed chat to dialogue again.

This commit is contained in:
Kapendev 2024-08-13 22:55:15 +03:00
parent 4ccf2f9c89
commit fbd84bf531
19 changed files with 159 additions and 153 deletions

View file

@ -16,7 +16,7 @@ void gameStart() {
updateWindow!gameLoop();
}
mixin addGameStart!(gameStart, 640, 360);
mixin callGameStart!(gameStart, 640, 360);
```
> [!WARNING]
@ -55,19 +55,19 @@ The final line modifies the default app.d and dub.json files, downloads raylib,
* assets: This folder is used to store game assets.
* web: This folder is used for exporting to the web.
Once the installation is complete, you should be able to compile/run with:
Once the installation is complete, run the following command:
```bash
dub run
```
You can pass `offline` to the script if you don't want to download raylib.
For more info about exporting to web, read [this](#web-support).
If everything is set up correctly, a window will appear showing the message "Hello world!".
To avoid downloading raylib, pass `offline` to the script.
## Documentation
For an initial understanding, the [examples](examples) folder and the [engine.d](source/popka/game/engine.d) file can be a good starting point.
You can also read the [TOUR.md](TOUR.md) file for a more in-depth overview.
For an initial understanding, the [examples](examples) folder can be a good starting point.
For a more detailed overview, check the [TOUR.md](TOUR.md) file.
## Attributes and BetterC Support
@ -76,9 +76,8 @@ If you encounter errors with BetterC, try using the `-i` flag.
## Web Support
For exporting to web, your project needs to be compatible with BetterC.
To export a game to the web, the game must be compatible with BetterC.
The [web](web) folder contains a helper script to assist with the web export process.
If you use DUB, you can run the script with:
```bash
dub run popka:web

49
TOUR.md
View file

@ -1,12 +1,8 @@
# Tour
> [!WARNING]
> I am still working on this.
# Tour (WIP)
## Understanding the Code
Let's get started with Popka by creating a simple game that displays the classic message "Hello world!".
Open your app.d file and paste the following code:
To begin, open the main file of your project and copy-paste the following code:
```d
import popka;
@ -21,10 +17,11 @@ void gameStart() {
updateWindow!gameLoop();
}
mixin addGameStart!(gameStart, 640, 360);
mixin callGameStart!(gameStart, 640, 360);
```
Let's see how everything works:
This code will create a window that displays the message "Hello world!".
Here is a breakdown of how this code works:
1. Game Loop
@ -36,9 +33,9 @@ Let's see how everything works:
```
This function is the main loop of the game.
It runs every frame, and in this example, it draws the message "Hello world!" on the window.
The `return false` statement tells the game to keep running.
If true is returned, then the program will stop running.
It runs every frame and, in this example, draws the message "Hello world!".
The `return false` statement indicates that the game should continue running.
If `true` were returned, the game would stop.
2. Game Start
@ -47,27 +44,25 @@ Let's see how everything works:
lockResolution(320, 180);
updateWindow!gameLoop();
}
mixin addGameStart!(gameStart, 640, 360);
```
This function is the starting point of the game.
It runs only once, and in this example, it locks the game resolution to 320 pixels wide and 180 pixels tall.
The `updateWindow!gameLoop()` call starts the game loop.
It runs only once and, in this example, locks the game resolution to 320 pixels wide and 180 pixels tall.
The `updateWindow!gameLoop` call starts the main game loop.
3. Mixin
```d
mixin addGameStart!(gameStart, 640, 360)
mixin callGameStart!(gameStart, 640, 360)
```
The line makes sure the `gameStart` function runs when your game starts,
and in this example, it creates a game window that is 640 pixels wide and 360 pixels tall.
This line sets up the `gameStart` function to run when the game starts
and, in this example, creates a game window that is 640 pixels wide and 360 pixels tall.
In essence, a Popka game typically relies on two key functions:
* A game loop function.
* A game start function.
* A loop function.
* A start function.
## Drawing
@ -75,18 +70,18 @@ Popka provides a set of drawing functions.
While drawing is not pixel-perfect by default, you can enable pixel-perfect drawing by calling the `togglePixelPerfect` function.
```d
// Basic Drawing Functions
void drawRect(Rect area, Color color = white);
void drawVec2(Vec2 point, float size, Color color = white);
void drawCirc(Circ area, Color color = white);
void drawLine(Line area, float size, Color color = white);
void drawTexture(Texture texture, Vec2 position, Rect area, DrawOptions options = DrawOptions());
void drawTexture(Texture texture, Vec2 position, DrawOptions options = DrawOptions());
void drawRune(Font font, Vec2 position, dchar rune, DrawOptions options = DrawOptions());
void drawText(Font font, Vec2 position, IStr text, DrawOptions options = DrawOptions());
void drawDebugText(IStr text, Vec2 position = Vec2(8.0f), DrawOptions options = DrawOptions());
// Tile Map Drawing Functions
void drawTile(Texture texture, Vec2 position, int tileID, Vec2 tileSize, DrawOptions options = DrawOptions());
void drawTileMap(Texture texture, Vec2 position, TileMap tileMap, Camera camera, DrawOptions options = DrawOptions());
```
@ -95,5 +90,11 @@ void drawTileMap(Texture texture, Vec2 position, TileMap tileMap, Camera camera,
Functions that start with the word load/save will always try to read/write from/to the assets folder.
These functions handle both forward slashes and backslashes in file paths, ensuring compatibility across operating systems.
For instance, `loadText("levels/level5.txt")` and `loadText("levels\\level5.txt")` will function identically on any operating system.
Also, if you need text data for just a single frame, consider using the `loadTempText` function.
```d
loadText("levels/level5.txt");
loadText("levels\\level5.txt");
```
Both of these calls will function identically on any operating system.
Also, if text is needed for only a single frame, use the `loadTempText` function.

View file

@ -30,4 +30,4 @@ void gameStart() {
updateWindow!gameLoop();
}
mixin addGameStart!(gameStart, 640, 360);
mixin callGameStart!(gameStart, 640, 360);

View file

@ -66,4 +66,4 @@ void gameStart() {
updateWindow!gameLoop();
}
mixin addGameStart!(gameStart, 640, 360);
mixin callGameStart!(gameStart, 640, 360);

View file

@ -1,15 +1,15 @@
/// This example shows how to use the Popka chat system.
/// This example shows how to use the Popka dialogue system.
import popka;
// The game variables.
auto chat = Chat();
auto dialogue = Dialogue();
auto script = "
# This is a comment.
! choiceCount
* menuPoint
^ Select first choice. ^ Select second choice. ^ End chat.
^ Select first choice. ^ Select second choice. ^ End dialogue.
* choice1
> Bob
@ -34,34 +34,34 @@ auto script = "
bool gameLoop() {
// Update the game.
if (chat.canUpdate) {
if (chat.hasChoices) {
auto keys = digitChars[1 .. 1 + chat.choices.length];
if (dialogue.canUpdate) {
if (dialogue.hasChoices) {
auto keys = digitChars[1 .. 1 + dialogue.choices.length];
foreach (i, key; keys) {
if (key.isPressed) {
chat.pick(i);
dialogue.pick(i);
break;
}
}
} else if (Keyboard.space.isPressed) {
chat.update();
dialogue.update();
}
}
// Draw the chat.
if (chat.hasChoices) {
foreach (i, choice; chat.choices) {
// Draw the dialogue.
if (dialogue.hasChoices) {
foreach (i, choice; dialogue.choices) {
auto choicePosition = Vec2(8, 8 + i * 14);
drawDebugText("{}".format(i + 1), choicePosition);
drawDebugText(" | {}".format(choice), choicePosition);
}
} else if (chat.canUpdate) {
drawDebugText("{}: {}".format(chat.actor, chat.text));
} else if (dialogue.canUpdate) {
drawDebugText("{}: {}".format(dialogue.actor, dialogue.text));
} else {
drawDebugText("The chat has ended.");
drawDebugText("The dialogue has ended.");
}
// Draw the game info/
// Draw the game info.
auto infoPosition = Vec2(8, resolution.y - 2 - 14 * 2);
drawRect(Rect(0, resolution.y * 0.8, resolution.x, resolution.y), gray1);
drawDebugText("Press 1, 2 or 3 to select a choice.", infoPosition);
@ -71,11 +71,11 @@ bool gameLoop() {
void gameStart() {
lockResolution(320, 180);
// Parse the chat script of the game.
// The first update makes the chat go to the first available line.
chat.parse(script);
chat.update();
// Parse the dialogue script of the game.
// The first update makes the dialogue go to the first available line.
dialogue.parse(script);
dialogue.update();
updateWindow!gameLoop();
}
mixin addGameStart!(gameStart, 640, 360);
mixin callGameStart!(gameStart, 640, 360);

View file

@ -56,4 +56,4 @@ void gameStart() {
atlas.free();
}
mixin addGameStart!(gameStart, 640, 360);
mixin callGameStart!(gameStart, 640, 360);

View file

@ -1,18 +1,18 @@
/// This example serves as a classic hello-world program, introducing the fundamental structure of a Popka program.
import popka;
// The game loop. This is called every frame.
// If true is returned, then the game will stop running.
// The loop function. This is called every frame.
// If true is returned, then the game will stop.
bool gameLoop() {
drawDebugText("Hello world!");
return false;
}
// The game start. This is one time.
// The start function. This is called once.
void gameStart() {
lockResolution(320, 180);
updateWindow!gameLoop();
}
// Creates a main function that calls the given function and creates a game window that is 640 pixels wide and 360 pixels tall.
mixin addGameStart!(gameStart, 640, 360);
mixin callGameStart!(gameStart, 640, 360);

View file

@ -41,4 +41,4 @@ void gameStart() {
atlas.free();
}
mixin addGameStart!(gameStart, 640, 360);
mixin callGameStart!(gameStart, 640, 360);

View file

@ -79,4 +79,4 @@ void gameStart() {
updateWindow!gameLoop();
}
mixin addGameStart!(gameStart, 640, 360);
mixin callGameStart!(gameStart, 640, 360);

View file

@ -10,7 +10,7 @@ enum header = "// ---
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// Version: v0.0.15
// ---";
int main(string[] args) {

View file

@ -96,7 +96,7 @@ lib*
enum defaultAppContent = `import popka;
bool gameLoop() {
draw("Hello world!");
drawDebugText("Hello world!");
return false;
}
@ -105,7 +105,7 @@ void gameStart() {
updateWindow!gameLoop();
}
mixin addGameStart!(gameStart, 640, 360);
mixin callGameStart!(gameStart, 640, 360);
`;
/// Check if path exists and print an error message if needed.

View file

@ -3,20 +3,20 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// Version: v0.0.15
// ---
/// The `chat` module provides a simple and versatile dialogue system.
module popka.chat;
/// The `dialogue` module provides a simple and versatile dialogue system.
module popka.dialogue;
import popka.engine;
public import joka;
@safe @nogc nothrow:
enum ChatUnitKindChars = ".#*@>|^!+-$";
enum DialogueUnitKindChars = ".#*@>|^!+-$";
enum ChatUnitKind {
enum DialogueUnitKind {
pause = '.',
comment = '#',
point = '*',
@ -30,18 +30,19 @@ enum ChatUnitKind {
command = '$',
}
struct ChatUnit {
struct DialogueUnit {
LStr text;
ChatUnitKind kind;
DialogueUnitKind kind;
@safe @nogc nothrow:
void free() {
text.free();
this = DialogueUnit();
}
}
struct ChatValue {
struct DialogueValue {
LStr name;
long value;
@ -49,14 +50,15 @@ struct ChatValue {
void free() {
name.free();
this = DialogueValue();
}
}
alias ChatCommandRunner = void function(IStr[] args);
alias DialogueCommandRunner = void function(IStr[] args);
struct Chat {
List!ChatUnit units;
List!ChatValue values;
struct Dialogue {
List!DialogueUnit units;
List!DialogueValue values;
IStr text;
IStr actor;
Sz unitIndex;
@ -67,20 +69,20 @@ struct Chat {
return units.length == 0;
}
bool isKind(ChatUnitKind kind) {
bool isKind(DialogueUnitKind kind) {
return unitIndex < units.length && units[unitIndex].kind == kind;
}
bool hasChoices() {
return isKind(ChatUnitKind.menu);
return isKind(DialogueUnitKind.menu);
}
bool hasArgs() {
return isKind(ChatUnitKind.command);
return isKind(DialogueUnitKind.command);
}
bool hasEnded() {
return isKind(ChatUnitKind.pause);
return isKind(DialogueUnitKind.pause);
}
bool canUpdate() {
@ -93,7 +95,7 @@ struct Chat {
auto length = 0;
auto temp = hasChoices ? units[unitIndex].text.items : "";
while (temp.length != 0) {
buffer[length] = temp.skipValue(ChatUnitKind.menu).trim();
buffer[length] = temp.skipValue(DialogueUnitKind.menu).trim();
length += 1;
}
return buffer[0 .. length];
@ -121,7 +123,7 @@ struct Chat {
if (point.length == 0) {
foreach (i; unitIndex + 1 .. units.length) {
auto unit = units[i];
if (unit.kind == ChatUnitKind.point) {
if (unit.kind == DialogueUnitKind.point) {
unitIndex = i;
break;
}
@ -129,7 +131,7 @@ struct Chat {
} else {
foreach (i; 0 .. units.length) {
auto unit = units[i];
if (unit.kind == ChatUnitKind.point && unit.text.items == point) {
if (unit.kind == DialogueUnitKind.point && unit.text.items == point) {
unitIndex = i;
break;
}
@ -140,7 +142,7 @@ struct Chat {
void jump(Sz i) {
auto currPoint = 0;
foreach (j, unit; units.items) {
if (unit.kind == ChatUnitKind.point) {
if (unit.kind == DialogueUnitKind.point) {
if (currPoint == i) {
unitIndex = j;
break;
@ -161,7 +163,7 @@ struct Chat {
update();
}
void run(ChatCommandRunner runner) {
void run(DialogueCommandRunner runner) {
runner(args);
update();
}
@ -172,24 +174,24 @@ struct Chat {
unitIndex += 1;
text = units[unitIndex].text.items;
final switch (units[unitIndex].kind) {
case ChatUnitKind.line, ChatUnitKind.menu, ChatUnitKind.command, ChatUnitKind.pause: {
case DialogueUnitKind.line, DialogueUnitKind.menu, DialogueUnitKind.command, DialogueUnitKind.pause: {
break;
}
case ChatUnitKind.comment, ChatUnitKind.point: {
case DialogueUnitKind.comment, DialogueUnitKind.point: {
update();
break;
}
case ChatUnitKind.actor: {
case DialogueUnitKind.actor: {
actor = text;
update();
break;
}
case ChatUnitKind.jump: {
case DialogueUnitKind.jump: {
jump(text);
update();
break;
}
case ChatUnitKind.variable: {
case DialogueUnitKind.variable: {
auto variableIndex = -1;
auto view = text;
auto name = trim(skipValue(view, '='));
@ -206,7 +208,7 @@ struct Chat {
}
// Create variable if it does not exist.
if (variableIndex < 0) {
auto variable = ChatValue();
auto variable = DialogueValue();
variable.name.append(name);
values.append(variable);
variableIndex = cast(int) values.length - 1;
@ -236,7 +238,7 @@ struct Chat {
update();
break;
}
case ChatUnitKind.plus, ChatUnitKind.minus: {
case DialogueUnitKind.plus, DialogueUnitKind.minus: {
auto variableIndex = -1;
auto name = text;
// Find if variable exists.
@ -250,7 +252,7 @@ struct Chat {
if (variableIndex < 0) {
assert(0, "TODO: A variable that does not exist it an error for now.");
}
if (units[unitIndex].kind == ChatUnitKind.plus) {
if (units[unitIndex].kind == DialogueUnitKind.plus) {
values[variableIndex].value += 1;
} else {
values[variableIndex].value -= 1;
@ -268,7 +270,7 @@ struct Chat {
return Fault.invalid;
}
units.append(ChatUnit(LStr(), ChatUnitKind.pause));
units.append(DialogueUnit(LStr(), DialogueUnitKind.pause));
auto isFirstLine = true;
auto view = script;
while (view.length != 0) {
@ -280,20 +282,20 @@ struct Chat {
auto kind = line[0];
if (isFirstLine) {
isFirstLine = false;
if (kind == ChatUnitKind.pause) {
if (kind == DialogueUnitKind.pause) {
continue;
}
}
if (isValidChatUnitKind(kind)) {
auto realKind = cast(ChatUnitKind) kind;
units.append(ChatUnit(LStr(text), realKind));
if (isValidDialogueUnitKind(kind)) {
auto realKind = cast(DialogueUnitKind) kind;
units.append(DialogueUnit(LStr(text), realKind));
} else {
clear();
return Fault.invalid;
}
}
if (units.items[$ - 1].kind != ChatUnitKind.pause) {
units.append(ChatUnit(LStr(), ChatUnitKind.pause));
if (units.items[$ - 1].kind != DialogueUnitKind.pause) {
units.append(DialogueUnit(LStr(), DialogueUnitKind.pause));
}
return Fault.none;
}
@ -323,8 +325,8 @@ struct Chat {
}
}
bool isValidChatUnitKind(char c) {
foreach (kind; ChatUnitKindChars) {
bool isValidDialogueUnitKind(char c) {
foreach (kind; DialogueUnitKindChars) {
if (c == kind) {
return true;
}
@ -332,19 +334,19 @@ bool isValidChatUnitKind(char c) {
return false;
}
Result!Chat toChat(IStr script) {
auto value = Chat();
Result!Dialogue toDialogue(IStr script) {
auto value = Dialogue();
auto fault = value.parse(script);
if (fault) {
value.free();
}
return Result!Chat(value, fault);
return Result!Dialogue(value, fault);
}
Result!Chat loadChat(IStr path) {
Result!Dialogue loadDialogue(IStr path) {
auto temp = loadTempText(path);
if (temp.isNone) {
return Result!Chat(temp.fault);
return Result!Dialogue(temp.fault);
}
return toChat(temp.unwrap());
return toDialogue(temp.unwrap());
}

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// Version: v0.0.15
// ---
/// The `engine` module functions as a lightweight 2D game engine.
@ -25,7 +25,7 @@ ray.Camera2D _toRay(Camera camera) {
);
}
/// Returns a random integer between 0 and float.max (inclusive).
/// Returns a random integer between 0 and int.max (inclusive).
@trusted
int randi() {
return ray.GetRandomValue(0, int.max);
@ -37,7 +37,7 @@ float randf() {
return ray.GetRandomValue(0, cast(int) float.max) / cast(float) cast(int) float.max;
}
/// Sets the seed for the random number generator to something specific.
/// Sets the seed of the random number generator to the given value.
@trusted
void randomize(int seed) {
ray.SetRandomSeed(seed);
@ -48,19 +48,19 @@ void randomize() {
randomize(randi);
}
/// Converts a world point to a screen point based on the given camera.
/// Converts a world position to a screen position based on the given camera.
@trusted
Vec2 toScreenPosition(Vec2 point, Camera camera) {
return toPopka(ray.GetWorldToScreen2D(point.toRay(), camera._toRay()));
Vec2 toScreenPosition(Vec2 position, Camera camera) {
return toPopka(ray.GetWorldToScreen2D(position.toRay(), camera._toRay()));
}
/// Converts a screen point to a world point based on the given camera.
/// Converts a screen position to a world position based on the given camera.
@trusted
Vec2 toWorldPosition(Vec2 point, Camera camera) {
return toPopka(ray.GetScreenToWorld2D(point.toRay(), camera._toRay()));
Vec2 toWorldPosition(Vec2 position, Camera camera) {
return toPopka(ray.GetScreenToWorld2D(position.toRay(), camera._toRay()));
}
/// Returns the default font. This font should not be freed.
/// Returns the default Popka font. This font should not be freed.
@trusted
Font dfltFont() {
auto result = ray.GetFontDefault().toPopka();
@ -69,6 +69,7 @@ Font dfltFont() {
return result;
}
/// Returns an absolute path to the assets folder.
IStr assetsPath() {
return engineState.assetsPath.items;
}
@ -78,21 +79,21 @@ IStr toAssetsPath(IStr path) {
}
/// Loads a text file from the assets folder and returns its contents as a list.
/// Can handle both forward slashes and backslashes in file paths, ensuring compatibility across operating systems.
/// Can handle both forward slashes and backslashes in file paths.
Result!LStr loadText(IStr path) {
return readText(path.toAssetsPath());
}
/// Loads a text file from the assets folder and returns its contents as a slice.
/// The slice can be safely used until this function is called again.
/// Can handle both forward slashes and backslashes in file paths, ensuring compatibility across operating systems.
/// Can handle both forward slashes and backslashes in file paths.
Result!IStr loadTempText(IStr path) {
auto fault = readTextIntoBuffer(path.toAssetsPath(), engineState.tempText);
return Result!IStr(engineState.tempText.items, fault);
}
/// Loads an image file from the assets folder.
/// Can handle both forward slashes and backslashes in file paths, ensuring compatibility across operating systems.
/// Loads an image file (PNG) from the assets folder.
/// Can handle both forward slashes and backslashes in file paths.
@trusted
Result!Texture loadTexture(IStr path) {
auto value = ray.LoadTexture(path.toAssetsPath().toCStr().unwrapOr()).toPopka();
@ -106,20 +107,21 @@ Result!Viewport loadViewport(int width, int height) {
}
@trusted
/// Loads a font file (TTF) from the assets folder.
/// Can handle both forward slashes and backslashes in file paths.
Result!Font loadFont(IStr path, uint size, const(dchar)[] runes = []) {
auto value = ray.LoadFontEx(path.toAssetsPath.toCStr().unwrapOr(), size, cast(int*) runes.ptr, cast(int) runes.length).toPopka();
return Result!Font(value, value.isEmpty.toFault(Fault.cantFind));
}
/// Saves a text file to the assets folder.
/// Can handle both forward slashes and backslashes in file paths, ensuring compatibility across operating systems.
/// Can handle both forward slashes and backslashes in file paths.
Fault saveText(IStr path, IStr text) {
return writeText(path.toAssetsPath(), text);
}
/// Opens the game window with the given size and title.
/// This function does not work if the window is already open, because Popka only works with one window.
/// Usually you should avoid calling this function manually.
/// Opens a window with the given size and title.
/// You should avoid calling this function manually.
@trusted
void openWindow(int width, int height, IStr title = "Popka") {
if (ray.IsWindowReady) {
@ -135,7 +137,7 @@ void openWindow(int width, int height, IStr title = "Popka") {
engineState.fullscreenState.lastWindowSize = Vec2(width, height);
}
/// Updates the game window every frame with the specified loop function.
/// Updates the window every frame with the given loop function.
/// This function will return when the loop function returns true.
@trusted
void updateWindow(alias loopFunc)() {
@ -229,52 +231,49 @@ void updateWindow(alias loopFunc)() {
}
}
/// Closes the game window.
/// Usually you should avoid calling this function manually.
/// Closes the window.
/// You should avoid calling this function manually.
@trusted
void closeWindow() {
if (!ray.IsWindowReady) {
return;
}
engineState.tempText.free();
engineState.assetsPath.free();
engineState.viewport.free();
engineState.free();
ray.CloseAudioDevice();
ray.CloseWindow();
engineState = EngineState();
}
/// Sets the window background color to the given color.
void setBackgroundColor(Color color) {
engineState.backgroundColor = color;
}
/// Returns true if the FPS of the game is locked.
/// Returns true if the FPS is locked.
bool isFpsLocked() {
return engineState.flags.isFpsLocked;
}
/// Locks the FPS of the game to a specific value.
/// Locks the FPS to the given value.
@trusted
void lockFps(int target) {
engineState.flags.isFpsLocked = true;
ray.SetTargetFPS(target);
}
/// Unlocks the FPS of the game.
/// Unlocks the FPS.
@trusted
void unlockFps() {
engineState.flags.isFpsLocked = false;
ray.SetTargetFPS(0);
}
/// Returns true if the resolution of the game is locked.
/// Returns true if the resolution is locked.
bool isResolutionLocked() {
return !engineState.viewport.isEmpty;
}
/// Locks the resolution of the game to a specific value.
/// Locks the resolution to the given value.
@trusted
void lockResolution(int width, int height) {
if (!engineState.flags.isUpdating) {
@ -287,7 +286,7 @@ void lockResolution(int width, int height) {
}
}
/// Unlocks the resolution of the game.
/// Unlocks the resolution.
void unlockResolution() {
if (!engineState.flags.isUpdating) {
engineState.viewport.free();
@ -311,7 +310,6 @@ bool isCursorHidden() {
}
/// Hides the system cursor.
/// This function works only on desktop.
@trusted
void hideCursor() {
engineState.flags.isCursorHidden = true;
@ -319,7 +317,6 @@ void hideCursor() {
}
/// Shows the system cursor.
/// This function works only on desktop.
@trusted
void showCursor() {
engineState.flags.isCursorHidden = false;
@ -327,14 +324,12 @@ void showCursor() {
}
/// Returns true if the window is in fullscreen mode.
/// This function works only on desktop.
@trusted
bool isFullscreen() {
return ray.IsWindowFullscreen();
}
/// Changes the state of the fullscreen mode of the window.
/// This function works only on desktop.
@trusted
void toggleFullscreen() {
version(WebAssembly) {
@ -355,6 +350,7 @@ bool isPixelPerfect() {
return engineState.flags.isPixelPerfect;
}
/// Changes the state of the pixel perfect mode of the window.
void togglePixelPerfect() {
engineState.flags.isPixelPerfect = !engineState.flags.isPixelPerfect;
}
@ -760,7 +756,7 @@ void drawDebugText(IStr text, Vec2 position = Vec2(8.0f), DrawOptions options =
drawText(dfltFont, position, text, options);
}
mixin template addGameStart(alias startFunc, int width, int height, IStr title = "Popka") {
mixin template callGameStart(alias startFunc, int width, int height, IStr title = "Popka") {
version (D_BetterC) {
pragma(msg, "Popka is using the C main function.");
extern(C)

View file

@ -3,13 +3,12 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// Version: v0.0.15
// ---
// The `popka`` module imports all of its submodules.
module popka;
public import popka.chat;
public import popka.dialogue;
public import popka.engine;
public import popka.tilemap;
public import popka.types;

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// Version: v0.0.15
// ---
/// The `ray` module provides access to the raylib library.

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// Version: v0.0.15
// ---
/**********************************************************************************************

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// Version: v0.0.15
// ---
/**********************************************************************************************

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// Version: v0.0.15
// ---
/// The `tilemap` module provides a simple and fast tile map.

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// Version: v0.0.15
// ---
/// The `types` module defines all the types used within the `engine` module.
@ -170,6 +170,15 @@ struct EngineState {
Color backgroundColor;
LStr tempText;
LStr assetsPath;
@safe @nogc nothrow:
void free() {
viewport.free();
tempText.free();
assetsPath.free();
this = EngineState();
}
}
struct DrawOptions {