The dialogue system works now and it is in core.

This commit is contained in:
Kapendev 2024-03-13 23:45:12 +02:00
parent 0dcc534b7a
commit 732f3b832d
6 changed files with 57 additions and 52 deletions

View file

@ -1,6 +1,5 @@
# NOW # NOW
* Working on menu for dialogue.
* Test engine on Windows. * Test engine on Windows.
# TODO # TODO

View file

@ -6,16 +6,20 @@
module popka.core.ascii; module popka.core.ascii;
enum { enum {
digitChars = "0123456789",
upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
lowerChars = "abcdefghijklmnopqrstuvwxyz",
alphaChars = upperChars ~ lowerChars,
spaceChars = " \t\v\r\n\f", spaceChars = " \t\v\r\n\f",
} }
bool isLower(char c) { bool isDigit(char c) {
return c >= 'a' && c <= 'z'; return c >= '0' && c <= '9';
} }
bool isLower(const(char)[] str) { bool isDigit(const(char)[] str) {
foreach (c; str) { foreach (c; str) {
if (!isLower(c)) return false; if (!isDigit(c)) return false;
} }
return true; return true;
} }
@ -31,6 +35,17 @@ bool isUpper(const(char)[] str) {
return true; return true;
} }
bool isLower(char c) {
return c >= 'a' && c <= 'z';
}
bool isLower(const(char)[] str) {
foreach (c; str) {
if (!isLower(c)) return false;
}
return true;
}
bool isAlpha(char c) { bool isAlpha(char c) {
return isLower(c) || isUpper(c); return isLower(c) || isUpper(c);
} }
@ -42,17 +57,6 @@ bool isAlpha(const(char)[] str) {
return true; return true;
} }
bool isDigit(char c) {
return c >= '0' && c <= '9';
}
bool isDigit(const(char)[] str) {
foreach (c; str) {
if (!isDigit(c)) return false;
}
return true;
}
bool isSpace(char c) { bool isSpace(char c) {
foreach (sc; spaceChars) { foreach (sc; spaceChars) {
if (c == sc) return true; if (c == sc) return true;
@ -67,13 +71,13 @@ bool isSpace(const(char)[] str) {
return true; return true;
} }
char toLower(char c) { char toDigit(char c) {
return isUpper(c) ? cast(char) (c + 32) : c; return isDigit(c) ? cast(char) (c - 48) : '0';
} }
void toLower(char[] str) { void toDigit(char[] str) {
foreach (ref c; str) { foreach (ref c; str) {
c = toLower(c); c = toDigit(c);
} }
} }
@ -87,13 +91,13 @@ void toUpper(char[] str) {
} }
} }
char toDigit(char c) { char toLower(char c) {
return isDigit(c) ? cast(char) (c - 48) : '0'; return isUpper(c) ? cast(char) (c + 32) : c;
} }
void toDigit(char[] str) { void toLower(char[] str) {
foreach (ref c; str) { foreach (ref c; str) {
c = toDigit(c); c = toLower(c);
} }
} }

View file

@ -9,6 +9,7 @@ module popka.core.basic;
public import popka.core.ascii; public import popka.core.ascii;
public import popka.core.color; public import popka.core.color;
public import popka.core.container; public import popka.core.container;
public import popka.core.dialogue;
public import popka.core.fmt; public import popka.core.fmt;
public import popka.core.io; public import popka.core.io;
public import popka.core.math; public import popka.core.math;

View file

@ -1,14 +1,14 @@
// Copyright 2024 Alexandros F. G. Kapretsos // Copyright 2024 Alexandros F. G. Kapretsos
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
/// The dialogue module is a versatile dialogue system for games, /// The dialogue module is a versatile dialogue system,
/// enabling the creation of interactive conversations and branching narratives. /// enabling the creation of interactive conversations and branching narratives.
// TODO: API might need some work. module popka.core.dialogue;
module popka.game.dialogue; import popka.core.container;
import popka.core.io;
import popka.core.basic; import popka.core.strutils;
enum dialogueUnitKindChars = "-#.@>|^"; enum dialogueUnitKindChars = "-#.@>|^";
@ -38,7 +38,7 @@ struct DialogueUnit {
struct Dialogue { struct Dialogue {
List!DialogueUnit units; List!DialogueUnit units;
List!(const(char)[]) options; List!(const(char)[]) menu;
size_t unitIndex; size_t unitIndex;
size_t pointCount; size_t pointCount;
const(char)[] text; const(char)[] text;
@ -48,16 +48,16 @@ struct Dialogue {
load(path); load(path);
} }
bool hasOptions() { bool hasMenu() {
return options.length != 0; return menu.length != 0;
} }
bool canUpdate() { bool canUpdate() {
return unitIndex < units.length && units[unitIndex].kind != DialogueUnitKind.pause; return unitIndex < units.length && units[unitIndex].kind != DialogueUnitKind.pause;
} }
DialogueUnit now() { const(char)[][] options() {
return units[unitIndex]; return menu.items;
} }
void reset() { void reset() {
@ -105,9 +105,10 @@ struct Dialogue {
} }
} }
void selectOption(size_t i) { void select(size_t i) {
menu.clear();
skip(i + 1); skip(i + 1);
options.clear(); update();
} }
void update() { void update() {
@ -124,11 +125,11 @@ struct Dialogue {
jump(unit.text.items); jump(unit.text.items);
update(); update();
} else if (unit.kind == DialogueUnitKind.menu) { } else if (unit.kind == DialogueUnitKind.menu) {
options.clear(); menu.clear();
const(char)[] view = unit.text.items; const(char)[] view = unit.text.items;
while (view.length != 0) { while (view.length != 0) {
auto option = trim(skipValue(view, DialogueUnitKind.menu)); auto option = trim(skipValue(view, DialogueUnitKind.menu));
options.append(option); menu.append(option);
} }
} }
} }

View file

@ -8,8 +8,8 @@ module popka.example.basic;
public import popka.example.camera; public import popka.example.camera;
public import popka.example.coins; public import popka.example.coins;
public import popka.example.hello;
public import popka.example.dialogue; public import popka.example.dialogue;
public import popka.example.hello;
void runEveryExample() { void runEveryExample() {
runHelloExample(); runHelloExample();

View file

@ -3,12 +3,9 @@
/// An example that shows how to use the dialogue system of Popka. /// An example that shows how to use the dialogue system of Popka.
// TODO: Example might need some work.
module popka.example.dialogue; module popka.example.dialogue;
import popka.basic; import popka.basic;
import popka.game.dialogue;
void runDialogueExample() { void runDialogueExample() {
openWindow(640, 480); openWindow(640, 480);
@ -28,6 +25,7 @@ void runDialogueExample() {
> Mia > Mia
| Hello! | Hello!
| Nice to meet you! | Nice to meet you!
| My name is Mia.
@ Point1 @ Point1
. Point2 . Point2
@ -50,11 +48,10 @@ void runDialogueExample() {
dialogue.update(); dialogue.update();
} }
if (dialogue.canUpdate) { if (dialogue.canUpdate) {
if (dialogue.hasOptions) { if (dialogue.hasMenu) {
foreach (i, key; "123456789"[0 .. dialogue.options.length]) { foreach (i, key; digitChars[1 .. 1 + dialogue.options.length]) {
if (isPressed(key)) { if (isPressed(key)) {
dialogue.selectOption(i); dialogue.select(i);
dialogue.update();
break; break;
} }
} }
@ -64,18 +61,21 @@ void runDialogueExample() {
} }
// Draw the game. // Draw the game.
if (dialogue.hasOptions) { if (dialogue.hasMenu) {
foreach (i, option; dialogue.options.items) { foreach (i, option; dialogue.options) {
drawDebugText("{}. {}".fmt(i + 1, option), Vec2(8, 8 + i * 14)); drawDebugText("{}. {}".fmt(i + 1, option), Vec2(8, 8 + i * 14));
} }
} else if (dialogue.canUpdate) { } else if (dialogue.canUpdate) {
drawDebugText("{}: {}".fmt(dialogue.actor, dialogue.text)); drawDebugText("{}: {}".fmt(dialogue.actor, dialogue.text));
} else { } else {
drawDebugText("No more dialogue."); drawDebugText("The dialogue has ended.");
} }
drawDebugText("Press R to restart.", Vec2(8, 140)); drawRect(Rect(0, resolution.y * 0.5, resolution.x, 1), lightGray);
drawDebugText(
"Press a number to pick an option.\nPress space to continue.\nPress R to restart.",
Vec2(8, resolution.y - 14 * 3 - 8)
);
} }
// Free all the game resources. // Free all the game resources.
dialogue.free(); dialogue.free();
freeWindow(); freeWindow();