Expanded keyboard API, added repl tools to make process

This commit is contained in:
2026-05-27 12:25:32 +10:00
parent 1c1473339f
commit 82d43ae813
8 changed files with 90 additions and 44 deletions
+8
View File
@@ -51,3 +51,11 @@ modules.order
Module.symvers Module.symvers
Mkfile.old Mkfile.old
dkms.conf dkms.conf
#mdbook files
book
mdbook
#repl tools
source/*inspector*
source/*library*
+1 -1
Submodule Toy updated: bbb1e38649...b312c0d8a3
+28 -31
View File
@@ -1,10 +1,11 @@
//debug testing //quick and dirty RNG
var counter = 0;
var randi: Int = 69420; var randi: Int = 69420;
fn rand() { fn rand() {
return randi = randi * 1664525 + 1013904223; //can be negative return randi = randi * 1664525 + 1013904223; //overflows to a negative, which is fine
} }
//wander like a zombie
var counter = 0;
fn wander(actor: Opaque) { fn wander(actor: Opaque) {
actor.setX(actor.x + rand() % 5); actor.setX(actor.x + rand() % 5);
actor.setY(actor.y + rand() % 5); actor.setY(actor.y + rand() % 5);
@@ -12,43 +13,36 @@ fn wander(actor: Opaque) {
counter++; counter++;
} }
//TODO: general purpose math functions
//TODO: optimize away single-line blocks in the AST
//player controlled character //player controlled character
var playerMaxMotion: Int = 5; var playerMaxMotion: Int = 5;
var playerMotionX: Int = 0; var playerMotionX: Int = 0;
var playerMotionY: Int = 0; var playerMotionY: Int = 0;
fn playerOnFrame(player: Opaque) { fn playerOnFrame(player: Opaque) {
//accept input //handle keyboard input
if (Keyboard.UP) { if (KeyPressed.UP) playerMotionY -= 5;
playerMotionY -= 5; if (KeyPressed.DOWN) playerMotionY += 5;
} if (KeyPressed.LEFT) playerMotionX -= 5;
if (Keyboard.DOWN) { if (KeyPressed.RIGHT) playerMotionX += 5;
playerMotionY += 5;
}
if (Keyboard.LEFT) {
playerMotionX -= 5;
}
if (Keyboard.RIGHT) {
playerMotionX += 5;
}
// print playerMotionX; if (KeyReleased.UP) playerMotionY = min(playerMotionY + 5, 0);
// print playerMotionY; if (KeyReleased.DOWN) playerMotionY = max(playerMotionY - 5, 0);
// print playerMaxMotion; if (KeyReleased.LEFT) playerMotionX = min(playerMotionX + 5, 0);
// print -playerMaxMotion; if (KeyReleased.RIGHT) playerMotionX = max(playerMotionX - 5, 0);
//cap the speed //cap the max speed
if (playerMotionX > playerMaxMotion) playerMotionX = playerMaxMotion; playerMotionX = min(max(playerMotionX, -playerMaxMotion), playerMaxMotion);
if (playerMotionX < -playerMaxMotion) playerMotionX = -playerMaxMotion; playerMotionY = min(max(playerMotionY, -playerMaxMotion), playerMaxMotion);
if (playerMotionY > playerMaxMotion) playerMotionY = playerMaxMotion;
if (playerMotionY < -playerMaxMotion) playerMotionY = -playerMaxMotion; //shortcut for normalized diagonal movement
var mod = 1;
if (playerMotionX != 0 && playerMotionY != 0) {
mod = 0.707;
}
//move the player //move the player
player.setX(player.x + playerMotionX); player.setX(player.x + floor(playerMotionX * mod));
player.setY(player.y + playerMotionY); player.setY(player.y + floor(playerMotionY * mod));
} }
//when the game is ready, load the "zombie" sprite //when the game is ready, load the "zombie" sprite
@@ -68,9 +62,12 @@ fn onReady() {
fn onFrame() { fn onFrame() {
//debug //debug
// print Keyboard.A;
} }
//example API for the game //example API for the game
initScreen(1280, 720, "Oh no, Zombies!"); initScreen(1280, 720, "Oh no, Zombies!");
initLoop(onReady, onFrame, null); initLoop(onReady, onFrame, null);
//TODO: optimize away single-line blocks in the AST
+6 -1
View File
@@ -17,7 +17,7 @@ export TOY_OUTDIR=../$(VAMP_OUTDIR)
export TOY_OBJDIR=$(VAMP_OBJDIR) export TOY_OBJDIR=$(VAMP_OBJDIR)
#targets #targets
all: $(VAMP_OUTDIR) Toy source all: $(VAMP_OUTDIR) Toy tools source
.PHONY: source .PHONY: source
source: source:
@@ -27,6 +27,11 @@ source:
Toy: Toy:
$(MAKE) -C $(TOY_SOURCEDIR) $(MAKE) -C $(TOY_SOURCEDIR)
.PHONY: tools
tools:
cp Toy/repl/*library* $(VAMP_SOURCEDIR)
cp Toy/repl/*inspector* $(VAMP_SOURCEDIR)
#util targets #util targets
$(VAMP_OUTDIR): $(VAMP_OUTDIR):
mkdir $(VAMP_OUTDIR) mkdir $(VAMP_OUTDIR)
+15 -3
View File
@@ -116,13 +116,25 @@ KeyboardMap keyboardMap[] = {
{0, NULL}, {0, NULL},
}; };
KeyboardData keyboardData = { //NOTE: it is just a dummy struct right now so the API looks nice KeyboardData keyboardData = {
.type = OPAQUE_KEYBOARD, .type = OPAQUE_KEYBOARD,
.callback = &IsKeyDown,
};
KeyboardData keyPressedData = {
.type = OPAQUE_KEY_PRESSED,
.callback = &IsKeyPressed,
};
KeyboardData keyReleasedData = {
.type = OPAQUE_KEY_RELEASED,
.callback = &IsKeyReleased,
}; };
Toy_Value handleKeyboardAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) { Toy_Value handleKeyboardAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
(void)vm; (void)vm;
(void)compound;
KeyboardData* kd = (KeyboardData*)TOY_VALUE_AS_OPAQUE(compound);
Toy_String* string = TOY_VALUE_AS_STRING(attribute); Toy_String* string = TOY_VALUE_AS_STRING(attribute);
const char* cstr = string->leaf.data; const char* cstr = string->leaf.data;
@@ -130,7 +142,7 @@ Toy_Value handleKeyboardAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value att
//find the mapped value, if available //find the mapped value, if available
for (KeyboardMap* ptr = keyboardMap; ptr->cstr != NULL; ptr++) { for (KeyboardMap* ptr = keyboardMap; ptr->cstr != NULL; ptr++) {
if (strlen(ptr->cstr) == strlen(cstr) && strncmp(cstr, ptr->cstr, strlen(ptr->cstr)) == 0) { if (strlen(ptr->cstr) == strlen(cstr) && strncmp(cstr, ptr->cstr, strlen(ptr->cstr)) == 0) {
bool result = IsKeyPressed(ptr->raykey); bool result = kd->callback(ptr->raykey);
return TOY_VALUE_FROM_BOOLEAN(result); return TOY_VALUE_FROM_BOOLEAN(result);
} }
} }
+6
View File
@@ -4,6 +4,9 @@
#include "toy_vm.h" #include "toy_vm.h"
#include "raylib.h" #include "raylib.h"
//fn pointers
typedef bool (*raykey_callback)(int);
//wraps raylib's 'KeyboardKey' enum to a c-string //wraps raylib's 'KeyboardKey' enum to a c-string
typedef struct KeyboardMap { typedef struct KeyboardMap {
int raykey; int raykey;
@@ -15,8 +18,11 @@ extern KeyboardMap keyboardMap[];
//keyboard opaque //keyboard opaque
typedef struct KeyboardData { typedef struct KeyboardData {
OpaqueType type; OpaqueType type;
raykey_callback callback;
} KeyboardData; } KeyboardData;
extern KeyboardData keyboardData; extern KeyboardData keyboardData;
extern KeyboardData keyPressedData;
extern KeyboardData keyReleasedData;
Toy_Value handleKeyboardAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute); Toy_Value handleKeyboardAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute);
+24 -4
View File
@@ -11,11 +11,14 @@
#include "keyboard.h" #include "keyboard.h"
#include "actor.h" #include "actor.h"
#include "standard_library.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
// #include "bytecode_inspector.h" // #include "bytecode_inspector.h"
// #include "bucket_inspector.h"
//utils //utils
unsigned char* readFile(char* path, int* size) { unsigned char* readFile(char* path, int* size) {
@@ -160,6 +163,8 @@ Toy_Value dispatchOpaqueAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value att
switch(*type) { switch(*type) {
case OPAQUE_KEYBOARD: case OPAQUE_KEYBOARD:
case OPAQUE_KEY_PRESSED:
case OPAQUE_KEY_RELEASED:
return handleKeyboardAttributes(vm, compound, attribute); return handleKeyboardAttributes(vm, compound, attribute);
case OPAQUE_ACTOR: case OPAQUE_ACTOR:
@@ -197,10 +202,22 @@ void initGameAPI(Toy_VM* vm) {
Toy_freeString(key); Toy_freeString(key);
} }
//declare keyboard opaque //declare input opaques
Toy_String* keyboardString = Toy_toString(&vm->memoryBucket, "Keyboard"); {
Toy_declareScope(vm->scope, keyboardString, TOY_VALUE_OPAQUE, TOY_OPAQUE_FROM_POINTER(&keyboardData), true); Toy_String* name = Toy_toString(&vm->memoryBucket, "Keyboard");
Toy_freeString(keyboardString); Toy_declareScope(vm->scope, name, TOY_VALUE_OPAQUE, TOY_OPAQUE_FROM_POINTER(&keyboardData), true);
Toy_freeString(name);
}
{
Toy_String* name = Toy_toString(&vm->memoryBucket, "KeyPressed");
Toy_declareScope(vm->scope, name, TOY_VALUE_OPAQUE, TOY_OPAQUE_FROM_POINTER(&keyPressedData), true);
Toy_freeString(name);
}
{
Toy_String* name = Toy_toString(&vm->memoryBucket, "KeyReleased");
Toy_declareScope(vm->scope, name, TOY_VALUE_OPAQUE, TOY_OPAQUE_FROM_POINTER(&keyReleasedData), true);
Toy_freeString(name);
}
} }
//main file //main file
@@ -221,6 +238,7 @@ int main() {
Toy_initVM(&vm); Toy_initVM(&vm);
Toy_bindVM(&vm, entryCode, NULL); Toy_bindVM(&vm, entryCode, NULL);
initStandardLibrary(&vm);
initGameAPI(&vm); initGameAPI(&vm);
initActorAPI(&vm); initActorAPI(&vm);
Toy_setOpaqueAttributeHandler(dispatchOpaqueAttributes); Toy_setOpaqueAttributeHandler(dispatchOpaqueAttributes);
@@ -271,6 +289,8 @@ int main() {
freeActorAPI(&vm); freeActorAPI(&vm);
// inspect_bucket(&vm.memoryBucket);
Toy_freeVM(&vm); Toy_freeVM(&vm);
free(entryCode); free(entryCode);
+2 -4
View File
@@ -3,9 +3,7 @@
//always first member of any opaques //always first member of any opaques
typedef enum OpaqueType { typedef enum OpaqueType {
OPAQUE_KEYBOARD, OPAQUE_KEYBOARD,
OPAQUE_KEY_PRESSED,
OPAQUE_KEY_RELEASED,
OPAQUE_ACTOR, OPAQUE_ACTOR,
} OpaqueType; } OpaqueType;
typedef struct DummyOpaque {
OpaqueType type;
} DummyOpaque;