diff --git a/.gitignore b/.gitignore index 4bdbcec..2ffa4c3 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,11 @@ modules.order Module.symvers Mkfile.old dkms.conf + +#mdbook files +book +mdbook + +#repl tools +source/*inspector* +source/*library* \ No newline at end of file diff --git a/Toy b/Toy index bbb1e38..b312c0d 160000 --- a/Toy +++ b/Toy @@ -1 +1 @@ -Subproject commit bbb1e3864987de13f70bf212dc4915f1107bca20 +Subproject commit b312c0d8a3fde62635a1f9116d1f06ab67b5d47e diff --git a/assets/main.toy b/assets/main.toy index 47f536d..8c7f388 100644 --- a/assets/main.toy +++ b/assets/main.toy @@ -1,10 +1,11 @@ -//debug testing -var counter = 0; +//quick and dirty RNG var randi: Int = 69420; 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) { actor.setX(actor.x + rand() % 5); actor.setY(actor.y + rand() % 5); @@ -12,43 +13,36 @@ fn wander(actor: Opaque) { counter++; } -//TODO: general purpose math functions -//TODO: optimize away single-line blocks in the AST - //player controlled character var playerMaxMotion: Int = 5; var playerMotionX: Int = 0; var playerMotionY: Int = 0; fn playerOnFrame(player: Opaque) { - //accept input - if (Keyboard.UP) { - playerMotionY -= 5; - } - if (Keyboard.DOWN) { - playerMotionY += 5; - } - if (Keyboard.LEFT) { - playerMotionX -= 5; - } - if (Keyboard.RIGHT) { - playerMotionX += 5; - } + //handle keyboard input + if (KeyPressed.UP) playerMotionY -= 5; + if (KeyPressed.DOWN) playerMotionY += 5; + if (KeyPressed.LEFT) playerMotionX -= 5; + if (KeyPressed.RIGHT) playerMotionX += 5; -// print playerMotionX; -// print playerMotionY; -// print playerMaxMotion; -// print -playerMaxMotion; + if (KeyReleased.UP) playerMotionY = min(playerMotionY + 5, 0); + if (KeyReleased.DOWN) playerMotionY = max(playerMotionY - 5, 0); + if (KeyReleased.LEFT) playerMotionX = min(playerMotionX + 5, 0); + if (KeyReleased.RIGHT) playerMotionX = max(playerMotionX - 5, 0); - //cap the speed - if (playerMotionX > playerMaxMotion) playerMotionX = playerMaxMotion; - if (playerMotionX < -playerMaxMotion) playerMotionX = -playerMaxMotion; - if (playerMotionY > playerMaxMotion) playerMotionY = playerMaxMotion; - if (playerMotionY < -playerMaxMotion) playerMotionY = -playerMaxMotion; + //cap the max speed + playerMotionX = min(max(playerMotionX, -playerMaxMotion), playerMaxMotion); + playerMotionY = min(max(playerMotionY, -playerMaxMotion), playerMaxMotion); + + //shortcut for normalized diagonal movement + var mod = 1; + if (playerMotionX != 0 && playerMotionY != 0) { + mod = 0.707; + } //move the player - player.setX(player.x + playerMotionX); - player.setY(player.y + playerMotionY); + player.setX(player.x + floor(playerMotionX * mod)); + player.setY(player.y + floor(playerMotionY * mod)); } //when the game is ready, load the "zombie" sprite @@ -68,9 +62,12 @@ fn onReady() { fn onFrame() { //debug -// print Keyboard.A; } //example API for the game initScreen(1280, 720, "Oh no, Zombies!"); initLoop(onReady, onFrame, null); + + + +//TODO: optimize away single-line blocks in the AST \ No newline at end of file diff --git a/makefile b/makefile index 7d096a7..b831e93 100644 --- a/makefile +++ b/makefile @@ -17,7 +17,7 @@ export TOY_OUTDIR=../$(VAMP_OUTDIR) export TOY_OBJDIR=$(VAMP_OBJDIR) #targets -all: $(VAMP_OUTDIR) Toy source +all: $(VAMP_OUTDIR) Toy tools source .PHONY: source source: @@ -27,6 +27,11 @@ source: Toy: $(MAKE) -C $(TOY_SOURCEDIR) +.PHONY: tools +tools: + cp Toy/repl/*library* $(VAMP_SOURCEDIR) + cp Toy/repl/*inspector* $(VAMP_SOURCEDIR) + #util targets $(VAMP_OUTDIR): mkdir $(VAMP_OUTDIR) diff --git a/source/keyboard.c b/source/keyboard.c index b1fd3e7..1203e22 100644 --- a/source/keyboard.c +++ b/source/keyboard.c @@ -116,13 +116,25 @@ KeyboardMap keyboardMap[] = { {0, NULL}, }; -KeyboardData keyboardData = { //NOTE: it is just a dummy struct right now so the API looks nice +KeyboardData keyboardData = { .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) { (void)vm; - (void)compound; + + KeyboardData* kd = (KeyboardData*)TOY_VALUE_AS_OPAQUE(compound); Toy_String* string = TOY_VALUE_AS_STRING(attribute); 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 for (KeyboardMap* ptr = keyboardMap; ptr->cstr != NULL; ptr++) { 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); } } diff --git a/source/keyboard.h b/source/keyboard.h index 036b668..88a8346 100644 --- a/source/keyboard.h +++ b/source/keyboard.h @@ -4,6 +4,9 @@ #include "toy_vm.h" #include "raylib.h" +//fn pointers +typedef bool (*raykey_callback)(int); + //wraps raylib's 'KeyboardKey' enum to a c-string typedef struct KeyboardMap { int raykey; @@ -15,8 +18,11 @@ extern KeyboardMap keyboardMap[]; //keyboard opaque typedef struct KeyboardData { OpaqueType type; + raykey_callback callback; } KeyboardData; extern KeyboardData keyboardData; +extern KeyboardData keyPressedData; +extern KeyboardData keyReleasedData; Toy_Value handleKeyboardAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute); \ No newline at end of file diff --git a/source/main.c b/source/main.c index b6a4acd..520a1bc 100644 --- a/source/main.c +++ b/source/main.c @@ -11,11 +11,14 @@ #include "keyboard.h" #include "actor.h" +#include "standard_library.h" + #include #include #include // #include "bytecode_inspector.h" +// #include "bucket_inspector.h" //utils 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) { case OPAQUE_KEYBOARD: + case OPAQUE_KEY_PRESSED: + case OPAQUE_KEY_RELEASED: return handleKeyboardAttributes(vm, compound, attribute); case OPAQUE_ACTOR: @@ -197,10 +202,22 @@ void initGameAPI(Toy_VM* vm) { Toy_freeString(key); } - //declare keyboard opaque - Toy_String* keyboardString = Toy_toString(&vm->memoryBucket, "Keyboard"); - Toy_declareScope(vm->scope, keyboardString, TOY_VALUE_OPAQUE, TOY_OPAQUE_FROM_POINTER(&keyboardData), true); - Toy_freeString(keyboardString); + //declare input opaques + { + Toy_String* name = Toy_toString(&vm->memoryBucket, "Keyboard"); + 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 @@ -221,6 +238,7 @@ int main() { Toy_initVM(&vm); Toy_bindVM(&vm, entryCode, NULL); + initStandardLibrary(&vm); initGameAPI(&vm); initActorAPI(&vm); Toy_setOpaqueAttributeHandler(dispatchOpaqueAttributes); @@ -271,6 +289,8 @@ int main() { freeActorAPI(&vm); + // inspect_bucket(&vm.memoryBucket); + Toy_freeVM(&vm); free(entryCode); diff --git a/source/opaque_type.h b/source/opaque_type.h index 08a777d..203ea1d 100644 --- a/source/opaque_type.h +++ b/source/opaque_type.h @@ -3,9 +3,7 @@ //always first member of any opaques typedef enum OpaqueType { OPAQUE_KEYBOARD, + OPAQUE_KEY_PRESSED, + OPAQUE_KEY_RELEASED, OPAQUE_ACTOR, } OpaqueType; - -typedef struct DummyOpaque { - OpaqueType type; -} DummyOpaque; \ No newline at end of file