I think everything works now.

This commit is contained in:
Kapendev 2024-08-13 13:28:23 +03:00
parent d2d269b658
commit 4ccf2f9c89
29 changed files with 214 additions and 183 deletions

View file

@ -35,12 +35,12 @@ mixin addGameStart!(gameStart, 640, 360);
## Dependencies ## Dependencies
To use Popka, you'll need the raylib library (version 5.0) installed on your system. * [Joka](https://github.com/Kapendev/joka)
The [official raylib instructions](https://github.com/raysan5/raylib/wiki) will guide you through the process. * [raylib](https://github.com/raysan5/raylib)
## Installation ## Installation
This guide shows how to install Popka and its dependency, raylib, using DUB. This guide shows how to install Popka and its dependencies using DUB.
While DUB simplifies the process, Popka itself doesn't require DUB. While DUB simplifies the process, Popka itself doesn't require DUB.
Create a new folder and run inside the following commands: Create a new folder and run inside the following commands:
@ -50,12 +50,11 @@ dub init -n
dub run popka:setup dub run popka:setup
``` ```
The last line will download raylib and create some folders necessary for Popka to function properly. The folders: The final line modifies the default app.d and dub.json files, downloads raylib, and creates the necessary folders for Popka to function properly. The following folders will be created:
* assets: This folder is used to store game assets such as images, sounds and fonts. * 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.
The last line also changes the default app.d and dub.json files.
Once the installation is complete, you should be able to compile/run with: Once the installation is complete, you should be able to compile/run with:
```bash ```bash
@ -68,15 +67,16 @@ For more info about exporting to web, read [this](#web-support).
## 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 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 of the engine's functionalities. You can also read the [TOUR.md](TOUR.md) file for a more in-depth overview.
## Attributes and BetterC Support ## Attributes and BetterC Support
This project offers support for some attributes (`@safe`, `@nogc`, `nothrow`) and aims for good compatibility with BetterC. This project offers support for some attributes (`@safe`, `@nogc`, `nothrow`) and aims for good compatibility with BetterC.
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 and it has to avoid some imports from the standard library. For exporting to web, your project needs to 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: If you use DUB, you can run the script with:
@ -87,27 +87,24 @@ dub run popka:web
## raylib Bindings ## raylib Bindings
Popka provides bindings for raylib that are compatible with BetterC and the web. Popka provides bindings for raylib that are compatible with BetterC and the web.
Additionally, it provides helper functions to reduce some boilerplate code.
All the helper functions are inside the [raylibpp.d](source/popka/vendor/ray/raylibpp.d) file.
```d ```d
import popka.ray; import popka.ray;
bool rayLoop() { int main() {
BeginDrawing(); const int screenWidth = 800;
ClearBackground(RAYWHITE); const int screenHeight = 450;
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
EndDrawing(); SetTargetFPS(60);
return false; while (!WindowShouldClose()) {
} BeginDrawing();
ClearBackground(RAYWHITE);
void rayStart(string path) { DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
InitWindow(800, 450, "raylib"); EndDrawing();
updateWindow!rayLoop(); }
CloseWindow(); CloseWindow();
return 0;
} }
mixin addRayStart!rayStart;
``` ```
## Note ## Note

94
TOUR.md
View file

@ -3,15 +3,16 @@
> [!WARNING] > [!WARNING]
> I am still working on this. > I am still working on this.
## Your First Popka Game ## 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: 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:
```d ```d
import popka; import popka;
bool gameLoop() { bool gameLoop() {
draw("Hello world!"); drawDebugText("Hello world!");
return false; return false;
} }
@ -23,38 +24,23 @@ void gameStart() {
mixin addGameStart!(gameStart, 640, 360); mixin addGameStart!(gameStart, 640, 360);
``` ```
Once you've saved the code, you should be able to compile/run with: Let's see how everything works:
```bash 1. Game Loop
dub run
```
You should see a window with the text "Hello world!" displayed.
Congratulations, you've created your first Popka game!
### Understanding the Code
1. Import
```d
import popka;
```
This line imports some basic Popka modules that are needed to make your game.
2. Game Loop
```d ```d
bool gameLoop() { bool gameLoop() {
draw("Hello world!"); drawDebugText("Hello world!");
return false; return false;
} }
``` ```
This function is the main loop of your game. It runs every frame, and on each frame in this example, it draws the message "Hello world!" on the game window. This function is the main loop of the game.
The `return false` statement tells the game to keep running. If true is returned, then the game will stop running. 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.
3. Game Start and Mixin 2. Game Start
```d ```d
void gameStart() { void gameStart() {
@ -65,8 +51,18 @@ Congratulations, you've created your first Popka game!
mixin addGameStart!(gameStart, 640, 360); mixin addGameStart!(gameStart, 640, 360);
``` ```
This function is the starting point of your game. It runs only one time, and in this example, it locks the game resolution to 320 pixels wide and 180 pixels tall, and the `updateWindow!gameLoop()` call starts the game loop. This function is the starting point of the game.
The `mixin addGameStart!(gameStart, 640, 360)` line might seem a bit complex right now, but it makes sure the `gameStart` function runs when your game starts and creates a game window that is 640 pixels wide and 360 pixels tall. 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.
3. Mixin
```d
mixin addGameStart!(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.
In essence, a Popka game typically relies on two key functions: In essence, a Popka game typically relies on two key functions:
@ -75,34 +71,24 @@ In essence, a Popka game typically relies on two key functions:
## Drawing ## Drawing
Popka provides a set of drawing functions for creating various graphical elements. 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
// Rectangle Drawing // Basic Drawing Functions
void draw(Rect area, Color color = white); 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());
// Circle Drawing // Tile Map Drawing Functions
void draw(Circ area, Color color = white); 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());
// Line Drawing
void draw(Line area, float size, Color color = white);
// Point Drawing
void draw(Vec2 point, float size, Color color = white);
// Sprite Drawing
void draw(Sprite sprite, Rect area, Vec2 position, DrawOptions options = DrawOptions());
void draw(Sprite sprite, Vec2 position, DrawOptions options = DrawOptions());
void draw(Sprite sprite, Vec2 tileSize, int tileID, Vec2 position, DrawOptions options = DrawOptions());
void draw(Sprite sprite, TileMap tileMap, Camera camera, Vec2 position, DrawOptions options = DrawOptions());
// Font Drawing
void draw(Font font, dchar rune, Vec2 position, DrawOptions options = DrawOptions());
void draw(Font font, const(char)[] text, Vec2 position, DrawOptions options = DrawOptions());
// Debug Drawing
void draw(const(char)[] text, Vec2 position = Vec2(8.0f), DrawOptions options = DrawOptions());
``` ```
## Loading and Saving ## Loading and Saving
@ -110,4 +96,4 @@ void draw(const(char)[] text, Vec2 position = Vec2(8.0f), DrawOptions options =
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. 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(const(char)[] path)` function. Also, if you need text data for just a single frame, consider using the `loadTempText` function.

View file

@ -7,7 +7,7 @@
"license": "MIT", "license": "MIT",
"name": "popka", "name": "popka",
"dependencies": { "dependencies": {
"joka": "~main" "joka": "*"
}, },
"subPackages" : [ "subPackages" : [
"setup", "setup",

View file

@ -7,40 +7,26 @@
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.
![image](hello.png)
## [Coins](coins.d) ## [Coins](coins.d)
This example shows how to create a simple game with Popka. This example shows how to create a simple game with Popka.
![image](coins.png)
## [Pong](pong.d) ## [Pong](pong.d)
This example shows how to create a pong-like game with Popka. This example shows how to create a pong-like game with Popka.
![image](pong.png)
## [Camera](camera.d) ## [Camera](camera.d)
This example shows how to use the camera structure of Popka. This example shows how to use the camera structure of Popka.
![image](camera.png)
## [Dialogue](dialogue.d) ## [Dialogue](dialogue.d)
This example shows how to use the Popka dialogue system. This example shows how to use the Popka dialogue system.
![image](dialogue.png)
## [Follower](follower.d) ## [Follower](follower.d)
This example shows how to create an animated character that follows the mouse. This example shows how to create an animated character that follows the mouse.
![image](follower.png)
## [Map](map.d) ## [Map](map.d)
This example shows how to use the tile map structure of Popka. This example shows how to use the tile map structure of Popka.
![image](map.png)

View file

@ -1,6 +1,3 @@
// Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT
/// This example shows how to use the camera structure of Popka. /// This example shows how to use the camera structure of Popka.
import popka; import popka;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -1,6 +1,3 @@
// Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT
/// This example shows how to create a simple game with Popka. /// This example shows how to create a simple game with Popka.
import popka; import popka;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -1,6 +1,3 @@
// Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT
/// This example shows how to use the Popka chat system. /// This example shows how to use the Popka chat system.
import popka; import popka;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -1,3 +1,4 @@
/// This example shows how to create an animated character that follows the mouse.
import popka; import popka;
// The game variables. // The game variables.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -1,6 +1,3 @@
// Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT
/// 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;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -1,6 +1,3 @@
// Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT
/// This example shows how to use the tile map structure of Popka. /// This example shows how to use the tile map structure of Popka.
import popka; import popka;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -1,6 +1,3 @@
// Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT
/// This example shows how to create a pong-like game with Popka. /// This example shows how to create a pong-like game with Popka.
import popka; import popka;
@ -41,7 +38,6 @@ bool gameLoop() {
// Move paddle1. // Move paddle1.
paddle1.position.y = clamp(paddle1.position.y + wasd.y * ballSpeed.y * deltaTime, paddle1.size.y * 0.5, resolution.y - paddle1.size.y * 0.5); paddle1.position.y = clamp(paddle1.position.y + wasd.y * ballSpeed.y * deltaTime, paddle1.size.y * 0.5, resolution.y - paddle1.size.y * 0.5);
// Move paddle2. // Move paddle2.
auto paddle2Target = ball.position.y; auto paddle2Target = ball.position.y;
if (ballDirection.x < 1) { if (ballDirection.x < 1) {
@ -65,7 +61,6 @@ bool gameLoop() {
drawRect(ball.centerArea); drawRect(ball.centerArea);
drawRect(paddle1.centerArea); drawRect(paddle1.centerArea);
drawRect(paddle2.centerArea); drawRect(paddle2.centerArea);
// Draw the counter. // Draw the counter.
auto textOptions = DrawOptions(); auto textOptions = DrawOptions();
textOptions.scale = Vec2(2); textOptions.scale = Vec2(2);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

59
scripts/header.d Executable file
View file

@ -0,0 +1,59 @@
#!/bin/env rdmd
/// A helper script that adds a header to every file in a directory.
import std;
enum fileExt = ".d";
enum header = "// ---
// Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// ---";
int main(string[] args) {
if (args.length == 1) {
writeln("Provide a directory containing `%s` files.".format(fileExt));
return 0;
}
// Basic error checking.
auto targetDir = args[1];
if (!targetDir.exists) {
writeln("Path `%s` does not exist.".format(targetDir));
return 1;
}
auto tempIndex = header.countUntil("\n");
if (tempIndex == -1) {
writeln("Header separator does not exist.");
writeln("The first line of the header is the header separator.");
return 1;
}
auto headerSep = header[0 .. tempIndex];
// Add the header to the files.
foreach (file; dirEntries(targetDir, SpanMode.breadth).parallel) {
if (!file.name.endsWith(fileExt)) continue;
auto text = readText(file.name);
if (text.startsWith(headerSep)) {
foreach (i, c; text) {
if (i <= headerSep.length) continue;
if (i == text.length - headerSep.length) {
writeln("File `%s` does not have a second header separator.".format(file.name));
writeln("A header separator looks like this: `%s`".format(headerSep));
break;
}
if (text[i .. i + headerSep.length] == headerSep) {
std.file.write(file.name, header ~ text[i + headerSep.length .. $]);
break;
}
}
} else {
std.file.write(file.name, header ~ "\n\n" ~ text);
}
}
return 0;
}

View file

@ -1,29 +1,26 @@
#!/bin/env rdmd #!/bin/env rdmd
// TODO: Needs some cleaning, but it works for now and I don't care.
/// A helper script that automates the project setup. /// A helper script that automates the project setup.
/// This script is designed with the idea that you use DUB, but it can work without DUB too. /// This script is designed with the idea that you use DUB, but it can work without DUB too.
import std.format; import std.format;
import std.path; import std.path;
import std.stdio; import std.stdio;
import std.file; import std.file;
import std.process; import std.process;
// The config. // The config.
// ---------- // ----------
enum noLibsArg = "offline"; enum noLibsArg = "offline";
enum dubFile = buildPath(".", "dub.json"); enum dubFile = buildPath(".", "dub.json");
enum dubyFile = buildPath(".", "dub.selections.json"); enum dubyFile = buildPath(".", "dub.selections.json");
enum appFile = buildPath(".", "source", "app.d"); enum appFile = buildPath(".", "source", "app.d");
enum gitignoreFile = buildPath(".", ".gitignore"); enum gitignoreFile = buildPath(".", ".gitignore");
enum assetsDir = buildPath(".", "assets"); enum assetsDir = buildPath(".", "assets");
enum webDir = buildPath(".", "web"); enum webDir = buildPath(".", "web");
// ---------- // ----------
enum defaultDUBContent = `{ enum defaultDUBContent = `{
"name" : "game", "name" : "game",
"description" : "A game made with Popka.", "description" : "A game made with Popka.",
@ -31,6 +28,7 @@ enum defaultDUBContent = `{
"copyright" : "Copyright © 2024, Name", "copyright" : "Copyright © 2024, Name",
"license" : "proprietary", "license" : "proprietary",
"dependencies": { "dependencies": {
"joka": "*",
"popka": "*" "popka": "*"
}, },
"configurations": [ "configurations": [
@ -73,7 +71,7 @@ enum defaultDUBContent = `{
"name": "web", "name": "web",
"targetType": "staticLibrary", "targetType": "staticLibrary",
"targetName": "webgame", "targetName": "webgame",
"dflags": ["-mtriple=wasm32-unknown-unknown-wasm", "-checkaction=halt", "-betterC", "--release", "-i"] "dflags": ["-mtriple=wasm32-unknown-unknown-wasm", "-checkaction=halt", "-betterC", "-i", "--release"]
} }
] ]
} }

View file

@ -1,5 +1,10 @@
// ---
// Copyright 2024 Alexandros F. G. Kapretsos // Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// ---
/// The `chat` module provides a simple and versatile dialogue system. /// The `chat` module provides a simple and versatile dialogue system.
module popka.chat; module popka.chat;
@ -28,11 +33,23 @@ enum ChatUnitKind {
struct ChatUnit { struct ChatUnit {
LStr text; LStr text;
ChatUnitKind kind; ChatUnitKind kind;
@safe @nogc nothrow:
void free() {
text.free();
}
} }
struct ChatValue { struct ChatValue {
LStr name; LStr name;
long value; long value;
@safe @nogc nothrow:
void free() {
name.free();
}
} }
alias ChatCommandRunner = void function(IStr[] args); alias ChatCommandRunner = void function(IStr[] args);
@ -73,27 +90,10 @@ struct Chat {
IStr[] choices() { IStr[] choices() {
static IStr[16] buffer; static IStr[16] buffer;
struct Range {
IStr menu;
bool empty() {
return menu.length == 0;
}
IStr front() {
auto temp = menu;
return temp.skipValue(ChatUnitKind.menu).trim();
}
void popFront() {
menu.skipValue(ChatUnitKind.menu);
}
}
auto length = 0; auto length = 0;
auto range = hasChoices ? Range(units[unitIndex].text.items) : Range(""); auto temp = hasChoices ? units[unitIndex].text.items : "";
foreach (item; range) { while (temp.length != 0) {
buffer[length] = item; buffer[length] = temp.skipValue(ChatUnitKind.menu).trim();
length += 1; length += 1;
} }
return buffer[0 .. length]; return buffer[0 .. length];
@ -102,27 +102,10 @@ struct Chat {
IStr[] args() { IStr[] args() {
static IStr[16] buffer; static IStr[16] buffer;
struct Range {
IStr command;
bool empty() {
return command.length == 0;
}
IStr front() {
auto temp = command;
return temp.skipValue(' ').trim();
}
void popFront() {
command.skipValue(' ');
}
}
auto length = 0; auto length = 0;
auto range = hasArgs ? Range(units[unitIndex].text.items) : Range(""); auto temp = hasArgs ? units[unitIndex].text.items : "";
foreach (item; range) { while (temp.length != 0) {
buffer[length] = item; buffer[length] = temp.skipValue(' ').trim();
length += 1; length += 1;
} }
return buffer[0 .. length]; return buffer[0 .. length];
@ -134,7 +117,6 @@ struct Chat {
unitIndex = 0; unitIndex = 0;
} }
// TODO: Make it faster.
void jump(IStr point) { void jump(IStr point) {
if (point.length == 0) { if (point.length == 0) {
foreach (i; unitIndex + 1 .. units.length) { foreach (i; unitIndex + 1 .. units.length) {
@ -155,7 +137,6 @@ struct Chat {
} }
} }
// TODO: Make it faster.
void jump(Sz i) { void jump(Sz i) {
auto currPoint = 0; auto currPoint = 0;
foreach (j, unit; units.items) { foreach (j, unit; units.items) {
@ -214,7 +195,7 @@ struct Chat {
auto name = trim(skipValue(view, '=')); auto name = trim(skipValue(view, '='));
auto value = trim(skipValue(view, '=')); auto value = trim(skipValue(view, '='));
if (name.length == 0) { if (name.length == 0) {
assert(0, "TODO: An variable without a name is an error for now."); assert(0, "TODO: A variable without a name is an error for now.");
} }
// Find if variable exists. // Find if variable exists.
foreach (i, variable; values.items) { foreach (i, variable; values.items) {
@ -244,7 +225,7 @@ struct Chat {
} }
} }
if (valueVariableIndex < 0) { if (valueVariableIndex < 0) {
assert(0, "TODO: A variable that doesn't exist it an error for now."); assert(0, "TODO: A variable that does not exist it an error for now.");
} else { } else {
values[variableIndex].value = values[valueVariableIndex].value; values[variableIndex].value = values[valueVariableIndex].value;
} }
@ -267,7 +248,7 @@ struct Chat {
} }
// Add/Remove from variable. // Add/Remove from variable.
if (variableIndex < 0) { if (variableIndex < 0) {
assert(0, "TODO: A variable that doesn't 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 == ChatUnitKind.plus) {
values[variableIndex].value += 1; values[variableIndex].value += 1;
@ -319,11 +300,11 @@ struct Chat {
void clear() { void clear() {
foreach (ref unit; units) { foreach (ref unit; units) {
unit.text.free(); unit.free();
} }
units.clear(); units.clear();
foreach (ref variable; values) { foreach (ref variable; values) {
variable.name.free(); variable.free();
} }
values.clear(); values.clear();
reset(); reset();
@ -331,11 +312,11 @@ struct Chat {
void free() { void free() {
foreach (ref unit; units) { foreach (ref unit; units) {
unit.text.free(); unit.free();
} }
units.free(); units.free();
foreach (ref variable; values) { foreach (ref variable; values) {
variable.name.free(); variable.free();
} }
values.free(); values.free();
reset(); reset();

View file

@ -1,5 +1,10 @@
// ---
// Copyright 2024 Alexandros F. G. Kapretsos // Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// ---
/// The `engine` module functions as a lightweight 2D game engine. /// The `engine` module functions as a lightweight 2D game engine.
module popka.engine; module popka.engine;
@ -676,18 +681,6 @@ void drawTexture(Texture texture, Vec2 position, DrawOptions options = DrawOptio
drawTexture(texture, position, Rect(texture.size), options); drawTexture(texture, position, Rect(texture.size), options);
} }
void drawTile(Texture texture, Vec2 position, int tileID, Vec2 tileSize, DrawOptions options = DrawOptions()) {
auto gridWidth = cast(int) (texture.size.x / tileSize.x);
auto gridHeight = cast(int) (texture.size.y / tileSize.y);
if (gridWidth == 0 || gridHeight == 0) {
return;
}
auto row = tileID / gridWidth;
auto col = tileID % gridWidth;
auto area = Rect(col * tileSize.x, row * tileSize.y, tileSize.x, tileSize.y);
drawTexture(texture, position, area, options);
}
@trusted @trusted
void drawRune(Font font, Vec2 position, dchar rune, DrawOptions options = DrawOptions()) { void drawRune(Font font, Vec2 position, dchar rune, DrawOptions options = DrawOptions()) {
if (font.isEmpty) { if (font.isEmpty) {

View file

@ -1,6 +1,12 @@
// ---
// Copyright 2024 Alexandros F. G. Kapretsos // Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// ---
// The `popka`` module imports all of its submodules.
module popka; module popka;
public import popka.chat; public import popka.chat;

View file

@ -1,6 +1,12 @@
// ---
// Copyright 2024 Alexandros F. G. Kapretsos // Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// ---
/// The `ray` module provides access to the raylib library.
module popka.ray; module popka.ray;
public import popka.ray.raylib; public import popka.ray.raylib;

View file

@ -1,3 +1,11 @@
// ---
// Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// ---
/********************************************************************************************** /**********************************************************************************************
* *
* raylib v5.0 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) * raylib v5.0 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
@ -76,6 +84,7 @@
* *
**********************************************************************************************/ **********************************************************************************************/
/// The `rayib` module provides access to the raylib.h functions.
module popka.ray.raylib; module popka.ray.raylib;
// import core.stdc.config; // import core.stdc.config;

View file

@ -1,3 +1,11 @@
// ---
// Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// ---
/********************************************************************************************** /**********************************************************************************************
* *
* rlgl v4.5 - A multi-OpenGL abstraction layer with an immediate-mode style API * rlgl v4.5 - A multi-OpenGL abstraction layer with an immediate-mode style API
@ -104,6 +112,7 @@
* *
**********************************************************************************************/ **********************************************************************************************/
/// The `rlgl` module provides access to the rlgl.h functions.
module popka.ray.rlgl; module popka.ray.rlgl;
@nogc nothrow extern(C): @nogc nothrow extern(C):

View file

@ -1,5 +1,10 @@
// ---
// Copyright 2024 Alexandros F. G. Kapretsos // Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// ---
/// The `tilemap` module provides a simple and fast tile map. /// The `tilemap` module provides a simple and fast tile map.
module popka.tilemap; module popka.tilemap;
@ -86,6 +91,18 @@ Result!TileMap loadTileMap(IStr path) {
return toTileMap(temp.unwrap()); return toTileMap(temp.unwrap());
} }
void drawTile(Texture texture, Vec2 position, int tileID, Vec2 tileSize, DrawOptions options = DrawOptions()) {
auto gridWidth = cast(int) (texture.size.x / tileSize.x);
auto gridHeight = cast(int) (texture.size.y / tileSize.y);
if (gridWidth == 0 || gridHeight == 0) {
return;
}
auto row = tileID / gridWidth;
auto col = tileID % gridWidth;
auto area = Rect(col * tileSize.x, row * tileSize.y, tileSize.x, tileSize.y);
drawTexture(texture, position, area, options);
}
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()) {
enum extraTileCount = 1; enum extraTileCount = 1;

View file

@ -1,5 +1,10 @@
// ---
// Copyright 2024 Alexandros F. G. Kapretsos // Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/popka
// Version: v0.0.14
// ---
/// The `types` module defines all the types used within the `engine` module. /// The `types` module defines all the types used within the `engine` module.
module popka.types; module popka.types;

View file

@ -1,9 +1,10 @@
#!/bin/env rdmd #!/bin/env rdmd
// TODO: Needs some cleaning, but it works for now and I don't care.
/// A helper script to assist with the web export process. /// A helper script to assist with the web export process.
/// This script is designed with the idea that Popka is included inside your source folder, but it can work without Popka too. /// This script is designed with the idea that Popka is included inside your source folder, but it can work without Popka too.
/// Just copy-paste the web folder into your project and run the script from your project folder. /// Just copy-paste the web folder into your project and run the script from your project folder.
import std.string; import std.string;
import std.format; import std.format;
import std.path; import std.path;
@ -11,7 +12,6 @@ import std.stdio;
import std.file; import std.file;
import std.process; import std.process;
// The config. // The config.
// ---------- // ----------
enum dflags = "-betterC -O --release"; // The compiler flags passed to ldc. Local dependencies can be added here. enum dflags = "-betterC -O --release"; // The compiler flags passed to ldc. Local dependencies can be added here.
@ -33,7 +33,6 @@ enum dubWebConfig = "web"; // The config
enum dubLibName = "webgame"; // The library name that DUB will output with the web config. enum dubLibName = "webgame"; // The library name that DUB will output with the web config.
// ---------- // ----------
// This is used if a shell file does not exist. // This is used if a shell file does not exist.
enum defaultShellContent = `<!doctype html> enum defaultShellContent = `<!doctype html>
<html lang="EN-us"> <html lang="EN-us">
@ -116,7 +115,6 @@ enum defaultShellContent = `<!doctype html>
</html> </html>
`; `;
/// Check if path exists and print an error message if needed. /// Check if path exists and print an error message if needed.
bool check(const(char)[] path, bool isLoud = true) { bool check(const(char)[] path, bool isLoud = true) {
if (!exists(path)) { if (!exists(path)) {