Adjusted API to a more explicit layout
This commit is contained in:
+6
-8
@@ -1,16 +1,11 @@
|
||||
var screenWidth = 1280;
|
||||
var screenHeight = 720;
|
||||
var screenCaption = "Hello raylib from Toy!";
|
||||
|
||||
//"global" variables
|
||||
var frameCounter: Int = 0;
|
||||
var posCounter: Int = 0;
|
||||
|
||||
//this runs before the game starts
|
||||
fn onReady() {
|
||||
loadMonsterSprite("parvati", "assets/parvati.png", 32, 32);
|
||||
}
|
||||
|
||||
//this runs each frame
|
||||
fn onStep() {
|
||||
frameCounter++;
|
||||
|
||||
@@ -20,7 +15,10 @@ fn onStep() {
|
||||
}
|
||||
}
|
||||
|
||||
//this runs as the game is closing down
|
||||
fn onFinished() {
|
||||
fn onClose() {
|
||||
//
|
||||
}
|
||||
|
||||
//example API for the game
|
||||
initScreen(1280, 720, "Hello raylib from Toy!");
|
||||
initLoop(onReady, onStep, onClose);
|
||||
+124
-37
@@ -66,6 +66,101 @@ unsigned char* makeCodeFromSource(const char* source) {
|
||||
return code;
|
||||
}
|
||||
|
||||
//static pointers
|
||||
static Toy_Function* onReady = NULL;
|
||||
static Toy_Function* onStep = NULL;
|
||||
static Toy_Function* onClose = NULL;
|
||||
|
||||
//game API definitions
|
||||
void initScreen(Toy_VM* vm) {
|
||||
Toy_Value caption = Toy_popStack(&vm->stack);
|
||||
Toy_Value height = Toy_popStack(&vm->stack);
|
||||
Toy_Value width = Toy_popStack(&vm->stack);
|
||||
|
||||
if (!TOY_VALUE_IS_STRING(caption) || TOY_VALUE_AS_STRING(caption)->info.type != TOY_STRING_LEAF || !TOY_VALUE_IS_INTEGER(height) || !TOY_VALUE_IS_INTEGER(width)) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Bad types found in 'initScreen', exiting" TOY_CC_RESET "\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//setup raylib
|
||||
InitWindow(TOY_VALUE_AS_INTEGER(width), TOY_VALUE_AS_INTEGER(height), TOY_VALUE_AS_STRING(caption)->leaf.data);
|
||||
SetTargetFPS(60);
|
||||
|
||||
Toy_freeValue(width);
|
||||
Toy_freeValue(height);
|
||||
Toy_freeValue(caption);
|
||||
}
|
||||
|
||||
void initLoop(Toy_VM* vm) {
|
||||
Toy_Value valueOnClose = Toy_popStack(&vm->stack);
|
||||
Toy_Value valueOnStep = Toy_popStack(&vm->stack);
|
||||
Toy_Value valueOnReady = Toy_popStack(&vm->stack);
|
||||
|
||||
if (!TOY_VALUE_IS_FUNCTION(valueOnClose) && !TOY_VALUE_IS_NULL(valueOnClose)) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Bad types found in 'initLoop', exiting" TOY_CC_RESET "\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!TOY_VALUE_IS_FUNCTION(valueOnStep) && !TOY_VALUE_IS_NULL(valueOnStep)) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Bad types found in 'initLoop', exiting" TOY_CC_RESET "\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!TOY_VALUE_IS_FUNCTION(valueOnReady) && !TOY_VALUE_IS_NULL(valueOnReady)) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Bad types found in 'initLoop', exiting" TOY_CC_RESET "\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (TOY_VALUE_IS_FUNCTION(valueOnReady)) {
|
||||
if (TOY_VALUE_AS_FUNCTION(valueOnReady)->type != TOY_FUNCTION_CUSTOM) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Bad function found in 'initLoop', exiting (only allows custom functions or null)" TOY_CC_RESET "\n");
|
||||
exit(-1);
|
||||
}
|
||||
onReady = TOY_VALUE_AS_FUNCTION(valueOnReady);
|
||||
}
|
||||
if (TOY_VALUE_IS_FUNCTION(valueOnStep)) {
|
||||
if (TOY_VALUE_AS_FUNCTION(valueOnStep)->type != TOY_FUNCTION_CUSTOM) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Bad function found in 'initLoop', exiting (only allows custom functions or null)" TOY_CC_RESET "\n");
|
||||
exit(-1);
|
||||
}
|
||||
onStep = TOY_VALUE_AS_FUNCTION(valueOnStep);
|
||||
}
|
||||
if (TOY_VALUE_IS_FUNCTION(valueOnClose)) {
|
||||
if (TOY_VALUE_AS_FUNCTION(valueOnClose)->type != TOY_FUNCTION_CUSTOM) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Bad function found in 'initLoop', exiting (only allows custom functions or null)" TOY_CC_RESET "\n");
|
||||
exit(-1);
|
||||
}
|
||||
onClose = TOY_VALUE_AS_FUNCTION(valueOnClose);
|
||||
}
|
||||
}
|
||||
|
||||
//game API tools
|
||||
typedef struct CallbackPairs {
|
||||
const char* name;
|
||||
Toy_nativeCallback callback;
|
||||
} CallbackPairs;
|
||||
|
||||
static CallbackPairs callbackPairs[] = {
|
||||
{"initScreen", initScreen},
|
||||
{"initLoop", initLoop},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
void initGameAPI(Toy_VM* vm) {
|
||||
if (vm == NULL || vm->scope == NULL || vm->memoryBucket == NULL) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't initialize game API, exiting\n" TOY_CC_RESET);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//declare each function in the global scope
|
||||
for (int i = 0; callbackPairs[i].name; i++) {
|
||||
Toy_String* key = Toy_toString(&(vm->memoryBucket), callbackPairs[i].name);
|
||||
Toy_Function* fn = Toy_createFunctionFromCallback(&(vm->memoryBucket), callbackPairs[i].callback);
|
||||
Toy_declareScope(vm->scope, key, TOY_VALUE_FUNCTION, TOY_VALUE_FROM_FUNCTION(fn), true);
|
||||
Toy_freeString(key);
|
||||
}
|
||||
}
|
||||
|
||||
//player data
|
||||
typedef struct PlayerData {
|
||||
Texture2D texture;
|
||||
@@ -76,8 +171,10 @@ typedef struct PlayerData {
|
||||
|
||||
PlayerData loadPlayerData(const char* fileName, Rectangle rect) {
|
||||
PlayerData player = {0};
|
||||
if (IsWindowReady()) {
|
||||
player.texture = LoadTexture(fileName);
|
||||
player.rect = rect;
|
||||
}
|
||||
return player;
|
||||
}
|
||||
|
||||
@@ -87,7 +184,7 @@ void unloadPlayerData(PlayerData player) {
|
||||
|
||||
//main file
|
||||
int main() {
|
||||
//example Toy controlling the window stuff
|
||||
//load the entry point
|
||||
int size = 0;
|
||||
const char* source = (char*)readFile("assets/main.toy", &size);
|
||||
|
||||
@@ -96,44 +193,31 @@ int main() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char* configCode = makeCodeFromSource(source);
|
||||
unsigned char* invokeOnReady = makeCodeFromSource("onReady();");
|
||||
unsigned char* invokeOnStep = makeCodeFromSource("onStep();");
|
||||
unsigned char* invokeOnFinished = makeCodeFromSource("onFinished();");
|
||||
unsigned char* entryCode = makeCodeFromSource(source);
|
||||
|
||||
//build and run the VM
|
||||
//build and run the VM with APIs
|
||||
Toy_VM vm;
|
||||
Toy_initVM(&vm);
|
||||
Toy_bindVM(&vm, configCode, NULL);
|
||||
Toy_bindVM(&vm, entryCode, NULL);
|
||||
initGameAPI(&vm);
|
||||
initMonsterAPI(&vm);
|
||||
Toy_runVM(&vm);
|
||||
Toy_resetVM(&vm, true, false); //leave it in a valid, but unset state
|
||||
|
||||
//extract the settings
|
||||
Toy_Value* screenWidthPtr = Toy_accessScopeAsPointer(vm.scope, Toy_toString(&vm.memoryBucket, "screenWidth") );
|
||||
Toy_Value* screenHeightPtr = Toy_accessScopeAsPointer(vm.scope, Toy_toString(&vm.memoryBucket, "screenHeight") );
|
||||
Toy_Value* screenCaptionPtr = Toy_accessScopeAsPointer(vm.scope, Toy_toString(&vm.memoryBucket, "screenCaption") );
|
||||
|
||||
int screenWidth = screenWidthPtr != NULL && TOY_VALUE_IS_INTEGER(*screenWidthPtr) ? TOY_VALUE_AS_INTEGER(*screenWidthPtr) : 640;
|
||||
int screenHeight = screenHeightPtr != NULL && TOY_VALUE_IS_INTEGER(*screenHeightPtr) ? TOY_VALUE_AS_INTEGER(*screenHeightPtr) : 480;
|
||||
const char* screenCaption = screenCaptionPtr != NULL && TOY_VALUE_IS_STRING(*screenCaptionPtr) ? TOY_VALUE_AS_STRING(*screenCaptionPtr)->leaf.data : "";
|
||||
|
||||
//setup raylib
|
||||
InitWindow(screenWidth, screenHeight, screenCaption);
|
||||
SetTargetFPS(60);
|
||||
Toy_resetVM(&vm, false, false); //leave in a valid, but unset state
|
||||
|
||||
//load a sprite
|
||||
PlayerData player = loadPlayerData("assets/parvati.png", (Rectangle){0,0,32,32});
|
||||
|
||||
//initialize the monster object pool and run the setup function
|
||||
initMonsterObjectPool(&vm);
|
||||
|
||||
//setup
|
||||
Toy_bindVM(&vm, invokeOnReady, NULL);
|
||||
//setup and run the given loop functions
|
||||
if (onReady != NULL) {
|
||||
Toy_bindVM(&vm, onReady->bytecode.code, onReady->bytecode.parentScope);
|
||||
Toy_runVM(&vm);
|
||||
Toy_resetVM(&vm, true, false);
|
||||
Toy_resetVM(&vm, false, false);
|
||||
}
|
||||
|
||||
//onStep is called each frame
|
||||
Toy_bindVM(&vm, invokeOnStep, NULL);
|
||||
if (onStep != NULL) {
|
||||
Toy_bindVM(&vm, onStep->bytecode.code, onStep->bytecode.parentScope);
|
||||
}
|
||||
|
||||
while (!WindowShouldClose()) {
|
||||
//input
|
||||
@@ -143,7 +227,7 @@ int main() {
|
||||
if (IsKeyDown(KEY_RIGHT)) player.position.x += 5.0f;
|
||||
|
||||
//run the onStep function
|
||||
Toy_runVM(&vm);
|
||||
Toy_runVM(&vm); //no check needed, empty VMs are skipped
|
||||
|
||||
//drawing
|
||||
BeginDrawing();
|
||||
@@ -159,23 +243,26 @@ int main() {
|
||||
}
|
||||
|
||||
//clear onStep
|
||||
Toy_resetVM(&vm, true, false);
|
||||
if (onStep != NULL) {
|
||||
Toy_resetVM(&vm, false, false);
|
||||
}
|
||||
|
||||
//cleanup
|
||||
Toy_bindVM(&vm, invokeOnFinished, NULL);
|
||||
if (onClose != NULL) {
|
||||
Toy_bindVM(&vm, onClose->bytecode.code, onClose->bytecode.parentScope);
|
||||
Toy_runVM(&vm);
|
||||
Toy_resetVM(&vm, true, false);
|
||||
Toy_resetVM(&vm, false, false);
|
||||
}
|
||||
|
||||
freeMonsterObjectPool(&vm);
|
||||
freeMonsterAPI(&vm);
|
||||
unloadPlayerData(player);
|
||||
|
||||
if (IsWindowReady()) {
|
||||
CloseWindow();
|
||||
}
|
||||
|
||||
Toy_freeVM(&vm);
|
||||
free(invokeOnReady);
|
||||
free(invokeOnStep);
|
||||
free(invokeOnFinished);
|
||||
free(configCode);
|
||||
free(entryCode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+13
-4
@@ -31,6 +31,11 @@ static Toy_Array* monsterArray = NULL;
|
||||
static void loadMonsterSprite(Toy_VM* vm) {
|
||||
//key, file, width, height -> null
|
||||
|
||||
if (!IsWindowReady()) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't load monster sprites before the window has been initialized" TOY_CC_RESET "\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//check for initialization
|
||||
if (spriteTable == NULL || monsterArray == NULL) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Object pool for monster system hasn't been initialized" TOY_CC_RESET "\n");
|
||||
@@ -114,7 +119,11 @@ static void spawnMonsterAt(Toy_VM* vm) {
|
||||
//get the sprite
|
||||
Toy_Value spriteValue = Toy_lookupTable(&spriteTable, key);
|
||||
if (TOY_VALUE_IS_NULL(spriteValue)) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't spawn a monster with a non-existant sprite" TOY_CC_RESET "\n");
|
||||
Toy_String* string = Toy_stringifyValue(&(vm->memoryBucket), key);
|
||||
char* cstr = Toy_getStringRaw(string);
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't spawn a monster with a non-existant sprite '%s'" TOY_CC_RESET "\n", cstr);
|
||||
free(cstr);
|
||||
Toy_freeString(string);
|
||||
Toy_freeValue(key);
|
||||
Toy_freeValue(xpos);
|
||||
Toy_freeValue(ypos);
|
||||
@@ -160,7 +169,7 @@ typedef struct CallbackPairs {
|
||||
Toy_nativeCallback callback;
|
||||
} CallbackPairs;
|
||||
|
||||
CallbackPairs callbackPairs[] = {
|
||||
static CallbackPairs callbackPairs[] = {
|
||||
{"loadMonsterSprite", loadMonsterSprite},
|
||||
{"spawnMonsterAt", spawnMonsterAt},
|
||||
|
||||
@@ -168,7 +177,7 @@ CallbackPairs callbackPairs[] = {
|
||||
};
|
||||
|
||||
//exposed
|
||||
void initMonsterObjectPool(Toy_VM* vm) {
|
||||
void initMonsterAPI(Toy_VM* vm) {
|
||||
if (vm == NULL || vm->scope == NULL || vm->memoryBucket == NULL) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Can't initialize standard library, exiting\n" TOY_CC_RESET);
|
||||
exit(-1);
|
||||
@@ -189,7 +198,7 @@ void initMonsterObjectPool(Toy_VM* vm) {
|
||||
monsterArray = Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY);
|
||||
}
|
||||
|
||||
void freeMonsterObjectPool(Toy_VM* vm) {
|
||||
void freeMonsterAPI(Toy_VM* vm) {
|
||||
(void)vm;
|
||||
|
||||
//free the GL textures
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
#include "toy_vm.h"
|
||||
|
||||
//object pool system
|
||||
void initMonsterObjectPool(Toy_VM* vm);
|
||||
void freeMonsterObjectPool(Toy_VM* vm);
|
||||
void initMonsterAPI(Toy_VM* vm);
|
||||
void freeMonsterAPI(Toy_VM* vm);
|
||||
|
||||
void drawMonsters(Toy_VM* vm);
|
||||
|
||||
Reference in New Issue
Block a user