mirror of
https://github.com/Kapendev/parin.git
synced 2025-04-28 05:59:54 +03:00
Fixed setup bug and changed chat to dialogue again.
This commit is contained in:
parent
4ccf2f9c89
commit
fbd84bf531
19 changed files with 159 additions and 153 deletions
15
README.md
15
README.md
|
@ -16,7 +16,7 @@ void gameStart() {
|
||||||
updateWindow!gameLoop();
|
updateWindow!gameLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin addGameStart!(gameStart, 640, 360);
|
mixin callGameStart!(gameStart, 640, 360);
|
||||||
```
|
```
|
||||||
|
|
||||||
> [!WARNING]
|
> [!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.
|
* assets: This folder is used to store game assets.
|
||||||
* web: This folder is used for exporting to the web.
|
* 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
|
```bash
|
||||||
dub run
|
dub run
|
||||||
```
|
```
|
||||||
|
|
||||||
You can pass `offline` to the script if you don't want to download raylib.
|
If everything is set up correctly, a window will appear showing the message "Hello world!".
|
||||||
For more info about exporting to web, read [this](#web-support).
|
To avoid downloading raylib, pass `offline` to the script.
|
||||||
|
|
||||||
## Documentation
|
## 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.
|
For an initial understanding, the [examples](examples) folder can be a good starting point.
|
||||||
You can also read the [TOUR.md](TOUR.md) file for a more in-depth overview.
|
For a more detailed overview, check the [TOUR.md](TOUR.md) file.
|
||||||
|
|
||||||
## Attributes and BetterC Support
|
## Attributes and BetterC Support
|
||||||
|
|
||||||
|
@ -76,9 +76,8 @@ If you encounter errors with BetterC, try using the `-i` flag.
|
||||||
|
|
||||||
## Web Support
|
## 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.
|
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
|
```bash
|
||||||
dub run popka:web
|
dub run popka:web
|
||||||
|
|
49
TOUR.md
49
TOUR.md
|
@ -1,12 +1,8 @@
|
||||||
# Tour
|
# Tour (WIP)
|
||||||
|
|
||||||
> [!WARNING]
|
|
||||||
> I am still working on this.
|
|
||||||
|
|
||||||
## Understanding the Code
|
## Understanding the Code
|
||||||
|
|
||||||
Let's get started with Popka by creating a simple game that displays the classic message "Hello world!".
|
To begin, open the main file of your project and copy-paste the following code:
|
||||||
Open your app.d file and paste the following code:
|
|
||||||
|
|
||||||
```d
|
```d
|
||||||
import popka;
|
import popka;
|
||||||
|
@ -21,10 +17,11 @@ void gameStart() {
|
||||||
updateWindow!gameLoop();
|
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
|
1. Game Loop
|
||||||
|
|
||||||
|
@ -36,9 +33,9 @@ Let's see how everything works:
|
||||||
```
|
```
|
||||||
|
|
||||||
This function is the main loop of the game.
|
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.
|
It runs every frame and, in this example, draws the message "Hello world!".
|
||||||
The `return false` statement tells the game to keep running.
|
The `return false` statement indicates that the game should continue running.
|
||||||
If true is returned, then the program will stop running.
|
If `true` were returned, the game would stop.
|
||||||
|
|
||||||
2. Game Start
|
2. Game Start
|
||||||
|
|
||||||
|
@ -47,27 +44,25 @@ Let's see how everything works:
|
||||||
lockResolution(320, 180);
|
lockResolution(320, 180);
|
||||||
updateWindow!gameLoop();
|
updateWindow!gameLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin addGameStart!(gameStart, 640, 360);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This function is the starting point of the game.
|
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.
|
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 game loop.
|
The `updateWindow!gameLoop` call starts the main game loop.
|
||||||
|
|
||||||
3. Mixin
|
3. Mixin
|
||||||
|
|
||||||
```d
|
```d
|
||||||
mixin addGameStart!(gameStart, 640, 360)
|
mixin callGameStart!(gameStart, 640, 360)
|
||||||
```
|
```
|
||||||
|
|
||||||
The line makes sure the `gameStart` function runs when your game starts,
|
This line sets up the `gameStart` function to run when the game starts
|
||||||
and in this example, it creates a game window that is 640 pixels wide and 360 pixels tall.
|
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:
|
In essence, a Popka game typically relies on two key functions:
|
||||||
|
|
||||||
* A game loop function.
|
* A loop function.
|
||||||
* A game start function.
|
* A start function.
|
||||||
|
|
||||||
## Drawing
|
## 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.
|
While drawing is not pixel-perfect by default, you can enable pixel-perfect drawing by calling the `togglePixelPerfect` function.
|
||||||
|
|
||||||
```d
|
```d
|
||||||
// Basic Drawing Functions
|
|
||||||
void drawRect(Rect area, Color color = white);
|
void drawRect(Rect area, Color color = white);
|
||||||
void drawVec2(Vec2 point, float size, Color color = white);
|
void drawVec2(Vec2 point, float size, Color color = white);
|
||||||
void drawCirc(Circ area, Color color = white);
|
void drawCirc(Circ area, Color color = white);
|
||||||
void drawLine(Line area, float size, 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, Rect area, DrawOptions options = DrawOptions());
|
||||||
void drawTexture(Texture texture, Vec2 position, DrawOptions options = DrawOptions());
|
void drawTexture(Texture texture, Vec2 position, DrawOptions options = DrawOptions());
|
||||||
|
|
||||||
void drawRune(Font font, Vec2 position, dchar rune, 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 drawText(Font font, Vec2 position, IStr text, DrawOptions options = DrawOptions());
|
||||||
void drawDebugText(IStr text, Vec2 position = Vec2(8.0f), 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 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());
|
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.
|
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.
|
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.
|
||||||
|
|
|
@ -30,4 +30,4 @@ void gameStart() {
|
||||||
updateWindow!gameLoop();
|
updateWindow!gameLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin addGameStart!(gameStart, 640, 360);
|
mixin callGameStart!(gameStart, 640, 360);
|
||||||
|
|
|
@ -66,4 +66,4 @@ void gameStart() {
|
||||||
updateWindow!gameLoop();
|
updateWindow!gameLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin addGameStart!(gameStart, 640, 360);
|
mixin callGameStart!(gameStart, 640, 360);
|
||||||
|
|
|
@ -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;
|
import popka;
|
||||||
|
|
||||||
// The game variables.
|
// The game variables.
|
||||||
auto chat = Chat();
|
auto dialogue = Dialogue();
|
||||||
auto script = "
|
auto script = "
|
||||||
# This is a comment.
|
# This is a comment.
|
||||||
|
|
||||||
! choiceCount
|
! choiceCount
|
||||||
|
|
||||||
* menuPoint
|
* menuPoint
|
||||||
^ Select first choice. ^ Select second choice. ^ End chat.
|
^ Select first choice. ^ Select second choice. ^ End dialogue.
|
||||||
|
|
||||||
* choice1
|
* choice1
|
||||||
> Bob
|
> Bob
|
||||||
|
@ -34,34 +34,34 @@ auto script = "
|
||||||
|
|
||||||
bool gameLoop() {
|
bool gameLoop() {
|
||||||
// Update the game.
|
// Update the game.
|
||||||
if (chat.canUpdate) {
|
if (dialogue.canUpdate) {
|
||||||
if (chat.hasChoices) {
|
if (dialogue.hasChoices) {
|
||||||
auto keys = digitChars[1 .. 1 + chat.choices.length];
|
auto keys = digitChars[1 .. 1 + dialogue.choices.length];
|
||||||
foreach (i, key; keys) {
|
foreach (i, key; keys) {
|
||||||
if (key.isPressed) {
|
if (key.isPressed) {
|
||||||
chat.pick(i);
|
dialogue.pick(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (Keyboard.space.isPressed) {
|
} else if (Keyboard.space.isPressed) {
|
||||||
chat.update();
|
dialogue.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the chat.
|
// Draw the dialogue.
|
||||||
if (chat.hasChoices) {
|
if (dialogue.hasChoices) {
|
||||||
foreach (i, choice; chat.choices) {
|
foreach (i, choice; dialogue.choices) {
|
||||||
auto choicePosition = Vec2(8, 8 + i * 14);
|
auto choicePosition = Vec2(8, 8 + i * 14);
|
||||||
drawDebugText("{}".format(i + 1), choicePosition);
|
drawDebugText("{}".format(i + 1), choicePosition);
|
||||||
drawDebugText(" | {}".format(choice), choicePosition);
|
drawDebugText(" | {}".format(choice), choicePosition);
|
||||||
}
|
}
|
||||||
} else if (chat.canUpdate) {
|
} else if (dialogue.canUpdate) {
|
||||||
drawDebugText("{}: {}".format(chat.actor, chat.text));
|
drawDebugText("{}: {}".format(dialogue.actor, dialogue.text));
|
||||||
} else {
|
} 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);
|
auto infoPosition = Vec2(8, resolution.y - 2 - 14 * 2);
|
||||||
drawRect(Rect(0, resolution.y * 0.8, resolution.x, resolution.y), gray1);
|
drawRect(Rect(0, resolution.y * 0.8, resolution.x, resolution.y), gray1);
|
||||||
drawDebugText("Press 1, 2 or 3 to select a choice.", infoPosition);
|
drawDebugText("Press 1, 2 or 3 to select a choice.", infoPosition);
|
||||||
|
@ -71,11 +71,11 @@ bool gameLoop() {
|
||||||
|
|
||||||
void gameStart() {
|
void gameStart() {
|
||||||
lockResolution(320, 180);
|
lockResolution(320, 180);
|
||||||
// Parse the chat script of the game.
|
// Parse the dialogue script of the game.
|
||||||
// The first update makes the chat go to the first available line.
|
// The first update makes the dialogue go to the first available line.
|
||||||
chat.parse(script);
|
dialogue.parse(script);
|
||||||
chat.update();
|
dialogue.update();
|
||||||
updateWindow!gameLoop();
|
updateWindow!gameLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin addGameStart!(gameStart, 640, 360);
|
mixin callGameStart!(gameStart, 640, 360);
|
||||||
|
|
|
@ -56,4 +56,4 @@ void gameStart() {
|
||||||
atlas.free();
|
atlas.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin addGameStart!(gameStart, 640, 360);
|
mixin callGameStart!(gameStart, 640, 360);
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
/// This example serves as a classic hello-world program, introducing the fundamental structure of a Popka program.
|
/// This example serves as a classic hello-world program, introducing the fundamental structure of a Popka program.
|
||||||
import popka;
|
import popka;
|
||||||
|
|
||||||
// The game loop. This is called every frame.
|
// The loop function. This is called every frame.
|
||||||
// If true is returned, then the game will stop running.
|
// If true is returned, then the game will stop.
|
||||||
bool gameLoop() {
|
bool gameLoop() {
|
||||||
drawDebugText("Hello world!");
|
drawDebugText("Hello world!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The game start. This is one time.
|
// The start function. This is called once.
|
||||||
void gameStart() {
|
void gameStart() {
|
||||||
lockResolution(320, 180);
|
lockResolution(320, 180);
|
||||||
updateWindow!gameLoop();
|
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.
|
// 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);
|
||||||
|
|
|
@ -41,4 +41,4 @@ void gameStart() {
|
||||||
atlas.free();
|
atlas.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin addGameStart!(gameStart, 640, 360);
|
mixin callGameStart!(gameStart, 640, 360);
|
||||||
|
|
|
@ -79,4 +79,4 @@ void gameStart() {
|
||||||
updateWindow!gameLoop();
|
updateWindow!gameLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin addGameStart!(gameStart, 640, 360);
|
mixin callGameStart!(gameStart, 640, 360);
|
||||||
|
|
|
@ -10,7 +10,7 @@ enum header = "// ---
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Email: alexandroskapretsos@gmail.com
|
// Email: alexandroskapretsos@gmail.com
|
||||||
// Project: https://github.com/Kapendev/popka
|
// Project: https://github.com/Kapendev/popka
|
||||||
// Version: v0.0.14
|
// Version: v0.0.15
|
||||||
// ---";
|
// ---";
|
||||||
|
|
||||||
int main(string[] args) {
|
int main(string[] args) {
|
||||||
|
|
|
@ -96,7 +96,7 @@ lib*
|
||||||
enum defaultAppContent = `import popka;
|
enum defaultAppContent = `import popka;
|
||||||
|
|
||||||
bool gameLoop() {
|
bool gameLoop() {
|
||||||
draw("Hello world!");
|
drawDebugText("Hello world!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ void gameStart() {
|
||||||
updateWindow!gameLoop();
|
updateWindow!gameLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
mixin addGameStart!(gameStart, 640, 360);
|
mixin callGameStart!(gameStart, 640, 360);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
/// Check if path exists and print an error message if needed.
|
/// Check if path exists and print an error message if needed.
|
||||||
|
|
|
@ -3,20 +3,20 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Email: alexandroskapretsos@gmail.com
|
// Email: alexandroskapretsos@gmail.com
|
||||||
// Project: https://github.com/Kapendev/popka
|
// Project: https://github.com/Kapendev/popka
|
||||||
// Version: v0.0.14
|
// Version: v0.0.15
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
/// The `chat` module provides a simple and versatile dialogue system.
|
/// The `dialogue` module provides a simple and versatile dialogue system.
|
||||||
module popka.chat;
|
module popka.dialogue;
|
||||||
|
|
||||||
import popka.engine;
|
import popka.engine;
|
||||||
public import joka;
|
public import joka;
|
||||||
|
|
||||||
@safe @nogc nothrow:
|
@safe @nogc nothrow:
|
||||||
|
|
||||||
enum ChatUnitKindChars = ".#*@>|^!+-$";
|
enum DialogueUnitKindChars = ".#*@>|^!+-$";
|
||||||
|
|
||||||
enum ChatUnitKind {
|
enum DialogueUnitKind {
|
||||||
pause = '.',
|
pause = '.',
|
||||||
comment = '#',
|
comment = '#',
|
||||||
point = '*',
|
point = '*',
|
||||||
|
@ -30,18 +30,19 @@ enum ChatUnitKind {
|
||||||
command = '$',
|
command = '$',
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChatUnit {
|
struct DialogueUnit {
|
||||||
LStr text;
|
LStr text;
|
||||||
ChatUnitKind kind;
|
DialogueUnitKind kind;
|
||||||
|
|
||||||
@safe @nogc nothrow:
|
@safe @nogc nothrow:
|
||||||
|
|
||||||
void free() {
|
void free() {
|
||||||
text.free();
|
text.free();
|
||||||
|
this = DialogueUnit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChatValue {
|
struct DialogueValue {
|
||||||
LStr name;
|
LStr name;
|
||||||
long value;
|
long value;
|
||||||
|
|
||||||
|
@ -49,14 +50,15 @@ struct ChatValue {
|
||||||
|
|
||||||
void free() {
|
void free() {
|
||||||
name.free();
|
name.free();
|
||||||
|
this = DialogueValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
alias ChatCommandRunner = void function(IStr[] args);
|
alias DialogueCommandRunner = void function(IStr[] args);
|
||||||
|
|
||||||
struct Chat {
|
struct Dialogue {
|
||||||
List!ChatUnit units;
|
List!DialogueUnit units;
|
||||||
List!ChatValue values;
|
List!DialogueValue values;
|
||||||
IStr text;
|
IStr text;
|
||||||
IStr actor;
|
IStr actor;
|
||||||
Sz unitIndex;
|
Sz unitIndex;
|
||||||
|
@ -67,20 +69,20 @@ struct Chat {
|
||||||
return units.length == 0;
|
return units.length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isKind(ChatUnitKind kind) {
|
bool isKind(DialogueUnitKind kind) {
|
||||||
return unitIndex < units.length && units[unitIndex].kind == kind;
|
return unitIndex < units.length && units[unitIndex].kind == kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasChoices() {
|
bool hasChoices() {
|
||||||
return isKind(ChatUnitKind.menu);
|
return isKind(DialogueUnitKind.menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasArgs() {
|
bool hasArgs() {
|
||||||
return isKind(ChatUnitKind.command);
|
return isKind(DialogueUnitKind.command);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasEnded() {
|
bool hasEnded() {
|
||||||
return isKind(ChatUnitKind.pause);
|
return isKind(DialogueUnitKind.pause);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canUpdate() {
|
bool canUpdate() {
|
||||||
|
@ -93,7 +95,7 @@ struct Chat {
|
||||||
auto length = 0;
|
auto length = 0;
|
||||||
auto temp = hasChoices ? units[unitIndex].text.items : "";
|
auto temp = hasChoices ? units[unitIndex].text.items : "";
|
||||||
while (temp.length != 0) {
|
while (temp.length != 0) {
|
||||||
buffer[length] = temp.skipValue(ChatUnitKind.menu).trim();
|
buffer[length] = temp.skipValue(DialogueUnitKind.menu).trim();
|
||||||
length += 1;
|
length += 1;
|
||||||
}
|
}
|
||||||
return buffer[0 .. length];
|
return buffer[0 .. length];
|
||||||
|
@ -121,7 +123,7 @@ struct Chat {
|
||||||
if (point.length == 0) {
|
if (point.length == 0) {
|
||||||
foreach (i; unitIndex + 1 .. units.length) {
|
foreach (i; unitIndex + 1 .. units.length) {
|
||||||
auto unit = units[i];
|
auto unit = units[i];
|
||||||
if (unit.kind == ChatUnitKind.point) {
|
if (unit.kind == DialogueUnitKind.point) {
|
||||||
unitIndex = i;
|
unitIndex = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +131,7 @@ struct Chat {
|
||||||
} else {
|
} else {
|
||||||
foreach (i; 0 .. units.length) {
|
foreach (i; 0 .. units.length) {
|
||||||
auto unit = units[i];
|
auto unit = units[i];
|
||||||
if (unit.kind == ChatUnitKind.point && unit.text.items == point) {
|
if (unit.kind == DialogueUnitKind.point && unit.text.items == point) {
|
||||||
unitIndex = i;
|
unitIndex = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +142,7 @@ struct Chat {
|
||||||
void jump(Sz i) {
|
void jump(Sz i) {
|
||||||
auto currPoint = 0;
|
auto currPoint = 0;
|
||||||
foreach (j, unit; units.items) {
|
foreach (j, unit; units.items) {
|
||||||
if (unit.kind == ChatUnitKind.point) {
|
if (unit.kind == DialogueUnitKind.point) {
|
||||||
if (currPoint == i) {
|
if (currPoint == i) {
|
||||||
unitIndex = j;
|
unitIndex = j;
|
||||||
break;
|
break;
|
||||||
|
@ -161,7 +163,7 @@ struct Chat {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(ChatCommandRunner runner) {
|
void run(DialogueCommandRunner runner) {
|
||||||
runner(args);
|
runner(args);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
@ -172,24 +174,24 @@ struct Chat {
|
||||||
unitIndex += 1;
|
unitIndex += 1;
|
||||||
text = units[unitIndex].text.items;
|
text = units[unitIndex].text.items;
|
||||||
final switch (units[unitIndex].kind) {
|
final switch (units[unitIndex].kind) {
|
||||||
case ChatUnitKind.line, ChatUnitKind.menu, ChatUnitKind.command, ChatUnitKind.pause: {
|
case DialogueUnitKind.line, DialogueUnitKind.menu, DialogueUnitKind.command, DialogueUnitKind.pause: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ChatUnitKind.comment, ChatUnitKind.point: {
|
case DialogueUnitKind.comment, DialogueUnitKind.point: {
|
||||||
update();
|
update();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ChatUnitKind.actor: {
|
case DialogueUnitKind.actor: {
|
||||||
actor = text;
|
actor = text;
|
||||||
update();
|
update();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ChatUnitKind.jump: {
|
case DialogueUnitKind.jump: {
|
||||||
jump(text);
|
jump(text);
|
||||||
update();
|
update();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ChatUnitKind.variable: {
|
case DialogueUnitKind.variable: {
|
||||||
auto variableIndex = -1;
|
auto variableIndex = -1;
|
||||||
auto view = text;
|
auto view = text;
|
||||||
auto name = trim(skipValue(view, '='));
|
auto name = trim(skipValue(view, '='));
|
||||||
|
@ -206,7 +208,7 @@ struct Chat {
|
||||||
}
|
}
|
||||||
// Create variable if it does not exist.
|
// Create variable if it does not exist.
|
||||||
if (variableIndex < 0) {
|
if (variableIndex < 0) {
|
||||||
auto variable = ChatValue();
|
auto variable = DialogueValue();
|
||||||
variable.name.append(name);
|
variable.name.append(name);
|
||||||
values.append(variable);
|
values.append(variable);
|
||||||
variableIndex = cast(int) values.length - 1;
|
variableIndex = cast(int) values.length - 1;
|
||||||
|
@ -236,7 +238,7 @@ struct Chat {
|
||||||
update();
|
update();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ChatUnitKind.plus, ChatUnitKind.minus: {
|
case DialogueUnitKind.plus, DialogueUnitKind.minus: {
|
||||||
auto variableIndex = -1;
|
auto variableIndex = -1;
|
||||||
auto name = text;
|
auto name = text;
|
||||||
// Find if variable exists.
|
// Find if variable exists.
|
||||||
|
@ -250,7 +252,7 @@ struct Chat {
|
||||||
if (variableIndex < 0) {
|
if (variableIndex < 0) {
|
||||||
assert(0, "TODO: A variable that does not exist it an error for now.");
|
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;
|
values[variableIndex].value += 1;
|
||||||
} else {
|
} else {
|
||||||
values[variableIndex].value -= 1;
|
values[variableIndex].value -= 1;
|
||||||
|
@ -268,7 +270,7 @@ struct Chat {
|
||||||
return Fault.invalid;
|
return Fault.invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
units.append(ChatUnit(LStr(), ChatUnitKind.pause));
|
units.append(DialogueUnit(LStr(), DialogueUnitKind.pause));
|
||||||
auto isFirstLine = true;
|
auto isFirstLine = true;
|
||||||
auto view = script;
|
auto view = script;
|
||||||
while (view.length != 0) {
|
while (view.length != 0) {
|
||||||
|
@ -280,20 +282,20 @@ struct Chat {
|
||||||
auto kind = line[0];
|
auto kind = line[0];
|
||||||
if (isFirstLine) {
|
if (isFirstLine) {
|
||||||
isFirstLine = false;
|
isFirstLine = false;
|
||||||
if (kind == ChatUnitKind.pause) {
|
if (kind == DialogueUnitKind.pause) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isValidChatUnitKind(kind)) {
|
if (isValidDialogueUnitKind(kind)) {
|
||||||
auto realKind = cast(ChatUnitKind) kind;
|
auto realKind = cast(DialogueUnitKind) kind;
|
||||||
units.append(ChatUnit(LStr(text), realKind));
|
units.append(DialogueUnit(LStr(text), realKind));
|
||||||
} else {
|
} else {
|
||||||
clear();
|
clear();
|
||||||
return Fault.invalid;
|
return Fault.invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (units.items[$ - 1].kind != ChatUnitKind.pause) {
|
if (units.items[$ - 1].kind != DialogueUnitKind.pause) {
|
||||||
units.append(ChatUnit(LStr(), ChatUnitKind.pause));
|
units.append(DialogueUnit(LStr(), DialogueUnitKind.pause));
|
||||||
}
|
}
|
||||||
return Fault.none;
|
return Fault.none;
|
||||||
}
|
}
|
||||||
|
@ -323,8 +325,8 @@ struct Chat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValidChatUnitKind(char c) {
|
bool isValidDialogueUnitKind(char c) {
|
||||||
foreach (kind; ChatUnitKindChars) {
|
foreach (kind; DialogueUnitKindChars) {
|
||||||
if (c == kind) {
|
if (c == kind) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -332,19 +334,19 @@ bool isValidChatUnitKind(char c) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result!Chat toChat(IStr script) {
|
Result!Dialogue toDialogue(IStr script) {
|
||||||
auto value = Chat();
|
auto value = Dialogue();
|
||||||
auto fault = value.parse(script);
|
auto fault = value.parse(script);
|
||||||
if (fault) {
|
if (fault) {
|
||||||
value.free();
|
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);
|
auto temp = loadTempText(path);
|
||||||
if (temp.isNone) {
|
if (temp.isNone) {
|
||||||
return Result!Chat(temp.fault);
|
return Result!Dialogue(temp.fault);
|
||||||
}
|
}
|
||||||
return toChat(temp.unwrap());
|
return toDialogue(temp.unwrap());
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Email: alexandroskapretsos@gmail.com
|
// Email: alexandroskapretsos@gmail.com
|
||||||
// Project: https://github.com/Kapendev/popka
|
// Project: https://github.com/Kapendev/popka
|
||||||
// Version: v0.0.14
|
// Version: v0.0.15
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
/// The `engine` module functions as a lightweight 2D game engine.
|
/// 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
|
@trusted
|
||||||
int randi() {
|
int randi() {
|
||||||
return ray.GetRandomValue(0, int.max);
|
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;
|
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
|
@trusted
|
||||||
void randomize(int seed) {
|
void randomize(int seed) {
|
||||||
ray.SetRandomSeed(seed);
|
ray.SetRandomSeed(seed);
|
||||||
|
@ -48,19 +48,19 @@ void randomize() {
|
||||||
randomize(randi);
|
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
|
@trusted
|
||||||
Vec2 toScreenPosition(Vec2 point, Camera camera) {
|
Vec2 toScreenPosition(Vec2 position, Camera camera) {
|
||||||
return toPopka(ray.GetWorldToScreen2D(point.toRay(), camera._toRay()));
|
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
|
@trusted
|
||||||
Vec2 toWorldPosition(Vec2 point, Camera camera) {
|
Vec2 toWorldPosition(Vec2 position, Camera camera) {
|
||||||
return toPopka(ray.GetScreenToWorld2D(point.toRay(), camera._toRay()));
|
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
|
@trusted
|
||||||
Font dfltFont() {
|
Font dfltFont() {
|
||||||
auto result = ray.GetFontDefault().toPopka();
|
auto result = ray.GetFontDefault().toPopka();
|
||||||
|
@ -69,6 +69,7 @@ Font dfltFont() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an absolute path to the assets folder.
|
||||||
IStr assetsPath() {
|
IStr assetsPath() {
|
||||||
return engineState.assetsPath.items;
|
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.
|
/// 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) {
|
Result!LStr loadText(IStr path) {
|
||||||
return readText(path.toAssetsPath());
|
return readText(path.toAssetsPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a text file from the assets folder and returns its contents as a slice.
|
/// 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.
|
/// 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) {
|
Result!IStr loadTempText(IStr path) {
|
||||||
auto fault = readTextIntoBuffer(path.toAssetsPath(), engineState.tempText);
|
auto fault = readTextIntoBuffer(path.toAssetsPath(), engineState.tempText);
|
||||||
return Result!IStr(engineState.tempText.items, fault);
|
return Result!IStr(engineState.tempText.items, fault);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads an image file from the assets folder.
|
/// Loads an image file (PNG) from 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.
|
||||||
@trusted
|
@trusted
|
||||||
Result!Texture loadTexture(IStr path) {
|
Result!Texture loadTexture(IStr path) {
|
||||||
auto value = ray.LoadTexture(path.toAssetsPath().toCStr().unwrapOr()).toPopka();
|
auto value = ray.LoadTexture(path.toAssetsPath().toCStr().unwrapOr()).toPopka();
|
||||||
|
@ -106,20 +107,21 @@ Result!Viewport loadViewport(int width, int height) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@trusted
|
@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 = []) {
|
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();
|
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));
|
return Result!Font(value, value.isEmpty.toFault(Fault.cantFind));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Saves a text file to the assets folder.
|
/// 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) {
|
Fault saveText(IStr path, IStr text) {
|
||||||
return writeText(path.toAssetsPath(), text);
|
return writeText(path.toAssetsPath(), text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opens the game window with the given size and title.
|
/// Opens a 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.
|
/// You should avoid calling this function manually.
|
||||||
/// Usually you should avoid calling this function manually.
|
|
||||||
@trusted
|
@trusted
|
||||||
void openWindow(int width, int height, IStr title = "Popka") {
|
void openWindow(int width, int height, IStr title = "Popka") {
|
||||||
if (ray.IsWindowReady) {
|
if (ray.IsWindowReady) {
|
||||||
|
@ -135,7 +137,7 @@ void openWindow(int width, int height, IStr title = "Popka") {
|
||||||
engineState.fullscreenState.lastWindowSize = Vec2(width, height);
|
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.
|
/// This function will return when the loop function returns true.
|
||||||
@trusted
|
@trusted
|
||||||
void updateWindow(alias loopFunc)() {
|
void updateWindow(alias loopFunc)() {
|
||||||
|
@ -229,52 +231,49 @@ void updateWindow(alias loopFunc)() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Closes the game window.
|
/// Closes the window.
|
||||||
/// Usually you should avoid calling this function manually.
|
/// You should avoid calling this function manually.
|
||||||
@trusted
|
@trusted
|
||||||
void closeWindow() {
|
void closeWindow() {
|
||||||
if (!ray.IsWindowReady) {
|
if (!ray.IsWindowReady) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
engineState.tempText.free();
|
engineState.free();
|
||||||
engineState.assetsPath.free();
|
|
||||||
engineState.viewport.free();
|
|
||||||
|
|
||||||
ray.CloseAudioDevice();
|
ray.CloseAudioDevice();
|
||||||
ray.CloseWindow();
|
ray.CloseWindow();
|
||||||
engineState = EngineState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the window background color to the given color.
|
||||||
void setBackgroundColor(Color color) {
|
void setBackgroundColor(Color color) {
|
||||||
engineState.backgroundColor = color;
|
engineState.backgroundColor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the FPS of the game is locked.
|
/// Returns true if the FPS is locked.
|
||||||
bool isFpsLocked() {
|
bool isFpsLocked() {
|
||||||
return engineState.flags.isFpsLocked;
|
return engineState.flags.isFpsLocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Locks the FPS of the game to a specific value.
|
/// Locks the FPS to the given value.
|
||||||
@trusted
|
@trusted
|
||||||
void lockFps(int target) {
|
void lockFps(int target) {
|
||||||
engineState.flags.isFpsLocked = true;
|
engineState.flags.isFpsLocked = true;
|
||||||
ray.SetTargetFPS(target);
|
ray.SetTargetFPS(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unlocks the FPS of the game.
|
/// Unlocks the FPS.
|
||||||
@trusted
|
@trusted
|
||||||
void unlockFps() {
|
void unlockFps() {
|
||||||
engineState.flags.isFpsLocked = false;
|
engineState.flags.isFpsLocked = false;
|
||||||
ray.SetTargetFPS(0);
|
ray.SetTargetFPS(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the resolution of the game is locked.
|
/// Returns true if the resolution is locked.
|
||||||
bool isResolutionLocked() {
|
bool isResolutionLocked() {
|
||||||
return !engineState.viewport.isEmpty;
|
return !engineState.viewport.isEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Locks the resolution of the game to a specific value.
|
/// Locks the resolution to the given value.
|
||||||
@trusted
|
@trusted
|
||||||
void lockResolution(int width, int height) {
|
void lockResolution(int width, int height) {
|
||||||
if (!engineState.flags.isUpdating) {
|
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() {
|
void unlockResolution() {
|
||||||
if (!engineState.flags.isUpdating) {
|
if (!engineState.flags.isUpdating) {
|
||||||
engineState.viewport.free();
|
engineState.viewport.free();
|
||||||
|
@ -311,7 +310,6 @@ bool isCursorHidden() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hides the system cursor.
|
/// Hides the system cursor.
|
||||||
/// This function works only on desktop.
|
|
||||||
@trusted
|
@trusted
|
||||||
void hideCursor() {
|
void hideCursor() {
|
||||||
engineState.flags.isCursorHidden = true;
|
engineState.flags.isCursorHidden = true;
|
||||||
|
@ -319,7 +317,6 @@ void hideCursor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shows the system cursor.
|
/// Shows the system cursor.
|
||||||
/// This function works only on desktop.
|
|
||||||
@trusted
|
@trusted
|
||||||
void showCursor() {
|
void showCursor() {
|
||||||
engineState.flags.isCursorHidden = false;
|
engineState.flags.isCursorHidden = false;
|
||||||
|
@ -327,14 +324,12 @@ void showCursor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the window is in fullscreen mode.
|
/// Returns true if the window is in fullscreen mode.
|
||||||
/// This function works only on desktop.
|
|
||||||
@trusted
|
@trusted
|
||||||
bool isFullscreen() {
|
bool isFullscreen() {
|
||||||
return ray.IsWindowFullscreen();
|
return ray.IsWindowFullscreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Changes the state of the fullscreen mode of the window.
|
/// Changes the state of the fullscreen mode of the window.
|
||||||
/// This function works only on desktop.
|
|
||||||
@trusted
|
@trusted
|
||||||
void toggleFullscreen() {
|
void toggleFullscreen() {
|
||||||
version(WebAssembly) {
|
version(WebAssembly) {
|
||||||
|
@ -355,6 +350,7 @@ bool isPixelPerfect() {
|
||||||
return engineState.flags.isPixelPerfect;
|
return engineState.flags.isPixelPerfect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Changes the state of the pixel perfect mode of the window.
|
||||||
void togglePixelPerfect() {
|
void togglePixelPerfect() {
|
||||||
engineState.flags.isPixelPerfect = !engineState.flags.isPixelPerfect;
|
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);
|
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) {
|
version (D_BetterC) {
|
||||||
pragma(msg, "Popka is using the C main function.");
|
pragma(msg, "Popka is using the C main function.");
|
||||||
extern(C)
|
extern(C)
|
||||||
|
|
|
@ -3,13 +3,12 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Email: alexandroskapretsos@gmail.com
|
// Email: alexandroskapretsos@gmail.com
|
||||||
// Project: https://github.com/Kapendev/popka
|
// Project: https://github.com/Kapendev/popka
|
||||||
// Version: v0.0.14
|
// Version: v0.0.15
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
// The `popka`` module imports all of its submodules.
|
|
||||||
module popka;
|
module popka;
|
||||||
|
|
||||||
public import popka.chat;
|
public import popka.dialogue;
|
||||||
public import popka.engine;
|
public import popka.engine;
|
||||||
public import popka.tilemap;
|
public import popka.tilemap;
|
||||||
public import popka.types;
|
public import popka.types;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Email: alexandroskapretsos@gmail.com
|
// Email: alexandroskapretsos@gmail.com
|
||||||
// Project: https://github.com/Kapendev/popka
|
// Project: https://github.com/Kapendev/popka
|
||||||
// Version: v0.0.14
|
// Version: v0.0.15
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
/// The `ray` module provides access to the raylib library.
|
/// The `ray` module provides access to the raylib library.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Email: alexandroskapretsos@gmail.com
|
// Email: alexandroskapretsos@gmail.com
|
||||||
// Project: https://github.com/Kapendev/popka
|
// Project: https://github.com/Kapendev/popka
|
||||||
// Version: v0.0.14
|
// Version: v0.0.15
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Email: alexandroskapretsos@gmail.com
|
// Email: alexandroskapretsos@gmail.com
|
||||||
// Project: https://github.com/Kapendev/popka
|
// Project: https://github.com/Kapendev/popka
|
||||||
// Version: v0.0.14
|
// Version: v0.0.15
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
/**********************************************************************************************
|
/**********************************************************************************************
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Email: alexandroskapretsos@gmail.com
|
// Email: alexandroskapretsos@gmail.com
|
||||||
// Project: https://github.com/Kapendev/popka
|
// Project: https://github.com/Kapendev/popka
|
||||||
// Version: v0.0.14
|
// Version: v0.0.15
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
/// The `tilemap` module provides a simple and fast tile map.
|
/// The `tilemap` module provides a simple and fast tile map.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Email: alexandroskapretsos@gmail.com
|
// Email: alexandroskapretsos@gmail.com
|
||||||
// Project: https://github.com/Kapendev/popka
|
// 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.
|
/// The `types` module defines all the types used within the `engine` module.
|
||||||
|
@ -170,6 +170,15 @@ struct EngineState {
|
||||||
Color backgroundColor;
|
Color backgroundColor;
|
||||||
LStr tempText;
|
LStr tempText;
|
||||||
LStr assetsPath;
|
LStr assetsPath;
|
||||||
|
|
||||||
|
@safe @nogc nothrow:
|
||||||
|
|
||||||
|
void free() {
|
||||||
|
viewport.free();
|
||||||
|
tempText.free();
|
||||||
|
assetsPath.free();
|
||||||
|
this = EngineState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DrawOptions {
|
struct DrawOptions {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue