Playing around with scripts
This commit is contained in:
@@ -21,6 +21,15 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="source\main.c" />
|
<ClCompile Include="source\main.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="assets\scripts\entity.toy" />
|
||||||
|
<None Include="assets\scripts\init.toy" />
|
||||||
|
<None Include="assets\scripts\scene.toy" />
|
||||||
|
<None Include="assets\scripts\tilemap\layer-background.toy" />
|
||||||
|
<None Include="assets\scripts\tilemap\layer-walls.toy" />
|
||||||
|
<None Include="assets\scripts\tilemap\tile.toy" />
|
||||||
|
<None Include="assets\scripts\tilemap\tilemap.toy" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>17.0</VCProjectVersion>
|
<VCProjectVersion>17.0</VCProjectVersion>
|
||||||
<ProjectGuid>{97F823E5-3AB8-47EF-B142-C15DD7CADF76}</ProjectGuid>
|
<ProjectGuid>{97F823E5-3AB8-47EF-B142-C15DD7CADF76}</ProjectGuid>
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ xcopy "$(SolutionDir)Toy\repl\repl_tools.*" "$(SolutionDir)box" /Y /I /E</Comman
|
|||||||
<ClCompile Include="box\lib_engine.c" />
|
<ClCompile Include="box\lib_engine.c" />
|
||||||
<ClCompile Include="box\lib_input.c" />
|
<ClCompile Include="box\lib_input.c" />
|
||||||
<ClCompile Include="box\lib_node.c" />
|
<ClCompile Include="box\lib_node.c" />
|
||||||
|
<ClCompile Include="box\lib_random.c" />
|
||||||
<ClCompile Include="box\lib_runner.c" />
|
<ClCompile Include="box\lib_runner.c" />
|
||||||
<ClCompile Include="box\lib_standard.c" />
|
<ClCompile Include="box\lib_standard.c" />
|
||||||
<ClCompile Include="box\repl_tools.c" />
|
<ClCompile Include="box\repl_tools.c" />
|
||||||
@@ -156,6 +157,7 @@ xcopy "$(SolutionDir)Toy\repl\repl_tools.*" "$(SolutionDir)box" /Y /I /E</Comman
|
|||||||
<ClInclude Include="box\lib_engine.h" />
|
<ClInclude Include="box\lib_engine.h" />
|
||||||
<ClInclude Include="box\lib_input.h" />
|
<ClInclude Include="box\lib_input.h" />
|
||||||
<ClInclude Include="box\lib_node.h" />
|
<ClInclude Include="box\lib_node.h" />
|
||||||
|
<ClInclude Include="box\lib_random.h" />
|
||||||
<ClInclude Include="box\lib_runner.h" />
|
<ClInclude Include="box\lib_runner.h" />
|
||||||
<ClInclude Include="box\lib_standard.h" />
|
<ClInclude Include="box\lib_standard.h" />
|
||||||
<ClInclude Include="box\repl_tools.h" />
|
<ClInclude Include="box\repl_tools.h" />
|
||||||
|
|||||||
2
Toy
2
Toy
Submodule Toy updated: d3df01c1c4...3aeddff736
@@ -25,7 +25,7 @@ mapInputEventToKeyUp("character_right", "right"); //event, keysym
|
|||||||
|
|
||||||
|
|
||||||
//this function must always be called, or the engine won't run
|
//this function must always be called, or the engine won't run
|
||||||
initWindow("Airport Game", 800, 600, false);
|
initWindow("Airport Game", 1080, 720, false);
|
||||||
|
|
||||||
//kick off the logic of the scene graph
|
//kick off the logic of the scene graph
|
||||||
loadRootNode("scripts:/root.toy");
|
loadRootNode("scripts:/scene.toy");
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
//import standard;
|
|
||||||
import engine;
|
|
||||||
import node;
|
|
||||||
|
|
||||||
//util to generate and init a child node of a parent
|
|
||||||
fn makeChild(parent: opaque, fname: string) {
|
|
||||||
var child: opaque = loadNode(fname);
|
|
||||||
parent.pushNode(child);
|
|
||||||
child.initNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
//NOTE: root node can load the whole scene, and essentially act as the scene object
|
|
||||||
fn onInit(node: opaque) {
|
|
||||||
print "root.toy:onInit() called";
|
|
||||||
|
|
||||||
//make a child
|
|
||||||
node.makeChild("scripts:/entity.toy");
|
|
||||||
|
|
||||||
//give the child a child
|
|
||||||
// node.getNodeChild(0).makeChild("scripts:/entity.toy");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onStep(node: opaque) {
|
|
||||||
//print clock();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onFree(node: opaque) {
|
|
||||||
print "root.toy:onFree() called";
|
|
||||||
}
|
|
||||||
23
assets/scripts/scene.toy
Normal file
23
assets/scripts/scene.toy
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
//the overarching scene
|
||||||
|
import node;
|
||||||
|
|
||||||
|
|
||||||
|
//util to generate and init a child node of a given parent
|
||||||
|
fn makeChild(parent: opaque, fname: string) {
|
||||||
|
var child: opaque = loadNode(fname);
|
||||||
|
parent.pushNode(child);
|
||||||
|
child.initNode();
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn onInit(node: opaque) {
|
||||||
|
//load the tile map node
|
||||||
|
var tilemapNode = node.makeChild("scripts:/tilemap/tilemap.toy");
|
||||||
|
|
||||||
|
tilemapNode.callNodeFn("loadLayer", "layer-background.toy");
|
||||||
|
tilemapNode.callNodeFn("loadLayer", "layer-walls.toy");
|
||||||
|
tilemapNode.callNodeFn("loadLayer", "layer-walls.toy");
|
||||||
|
//tilemapNode.callNodeFn("loadLayer", "layer-walls.toy"); //TODO: remove this
|
||||||
|
//tilemapNode.callNodeFn("loadLayer", "layer-maze.toy");
|
||||||
|
}
|
||||||
70
assets/scripts/tilemap/layer-background.toy
Normal file
70
assets/scripts/tilemap/layer-background.toy
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
//this is one layer
|
||||||
|
import node;
|
||||||
|
|
||||||
|
var childCounter: int = 0;
|
||||||
|
|
||||||
|
//TODO: reference these from a global source (root?)
|
||||||
|
var tileWidth: float const = 100;
|
||||||
|
var tileHeight: float const = 100;
|
||||||
|
|
||||||
|
var roomWidth: float const = 10;
|
||||||
|
var roomHeight: float const = 10;
|
||||||
|
|
||||||
|
|
||||||
|
//util to generate and init a child node of a given parent
|
||||||
|
fn makeChildSprite(parent: opaque, spriteName: string) {
|
||||||
|
var child: opaque = loadNode("scripts:/tilemap/tile.toy");
|
||||||
|
parent.pushNode(child);
|
||||||
|
child.initNode();
|
||||||
|
|
||||||
|
child.loadTexture("sprites:/" + spriteName);
|
||||||
|
|
||||||
|
//BUGFIX
|
||||||
|
childCounter++;
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn onInit(node: opaque) {
|
||||||
|
//load the child node, with the tiling back image
|
||||||
|
node.makeChildSprite("tile-background.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drawRoom(node: opaque, x, y, depth, camX, camY, camW, camH) {
|
||||||
|
//the modifier ratio to move things
|
||||||
|
var mod: float = float tileWidth / (tileWidth - depth);
|
||||||
|
|
||||||
|
var tileWidth_mod = tileWidth * mod;
|
||||||
|
var tileHeight_mod = tileHeight * mod;
|
||||||
|
var camX_mod = (camX - camW) * mod + camW / 2;
|
||||||
|
var camY_mod = (camY - camH) * mod + camH / 2;
|
||||||
|
|
||||||
|
for (var j: int = 0; j < roomHeight; j++) {
|
||||||
|
for (var i: int = 0; i < roomWidth; i++) {
|
||||||
|
node.getNodeChild(0).drawNode(round( (x * roomWidth + i) * tileWidth_mod + camX_mod ),round( (y * roomHeight + j) * tileHeight_mod + camY_mod ), round( tileWidth_mod ), round( tileHeight_mod ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn round(x): int {
|
||||||
|
var f = floor(x);
|
||||||
|
return x - f >= 0.5 ? f + 1 : f;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn floor(x): int {
|
||||||
|
return int x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ceil(x): int {
|
||||||
|
var f = floor(x);
|
||||||
|
return x - f != 0 ? f + 1 : f;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn min(a, b) {
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max(a, b) {
|
||||||
|
return a > b ? a : b;
|
||||||
|
}
|
||||||
84
assets/scripts/tilemap/layer-walls.toy
Normal file
84
assets/scripts/tilemap/layer-walls.toy
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
//this is one layer
|
||||||
|
import node;
|
||||||
|
|
||||||
|
var childCounter: int = 0;
|
||||||
|
|
||||||
|
//TODO: reference these from a global source (root?)
|
||||||
|
var tileWidth: float const = 100;
|
||||||
|
var tileHeight: float const = 100;
|
||||||
|
|
||||||
|
var roomWidth: float const = 10;
|
||||||
|
var roomHeight: float const = 10;
|
||||||
|
|
||||||
|
|
||||||
|
//util to generate and init a child node of a given parent
|
||||||
|
fn makeChildSprite(parent: opaque, spriteName: string) {
|
||||||
|
var child: opaque = loadNode("scripts:/tilemap/tile.toy");
|
||||||
|
parent.pushNode(child);
|
||||||
|
child.initNode();
|
||||||
|
|
||||||
|
child.loadTexture("sprites:/" + spriteName);
|
||||||
|
|
||||||
|
//BUGFIX
|
||||||
|
childCounter++;
|
||||||
|
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn onInit(node: opaque) {
|
||||||
|
//load the child node, with the tiling back image
|
||||||
|
node.makeChildSprite("tile-wall.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw the parallax-style walls
|
||||||
|
fn drawRoom(node: opaque, x, y, depth, camX, camY, camW, camH) {
|
||||||
|
var mod: float = float tileWidth / (tileWidth - depth);
|
||||||
|
|
||||||
|
var tileWidth_mod = tileWidth * mod;
|
||||||
|
var tileHeight_mod = tileHeight * mod;
|
||||||
|
var camX_mod = (camX - camW) * mod + camW / 2;
|
||||||
|
var camY_mod = (camY - camH) * mod + camH / 2;
|
||||||
|
|
||||||
|
//top
|
||||||
|
for (var i = x * roomWidth; i < (x * roomWidth) + roomWidth; i++) {
|
||||||
|
node.getNodeChild(0).drawNode(round( i * tileWidth_mod + camX_mod ), round(y * roomHeight * tileHeight_mod + camY_mod ), round( tileWidth_mod), round( tileHeight_mod ));
|
||||||
|
}
|
||||||
|
|
||||||
|
//left
|
||||||
|
for (var j = y * roomHeight; j < (y * roomHeight) + roomHeight; j++) {
|
||||||
|
node.getNodeChild(0).drawNode(round( x * roomWidth * tileWidth_mod + camX_mod ), round( j * tileHeight_mod + camY_mod ), round( tileWidth_mod), round( tileHeight_mod ));
|
||||||
|
}
|
||||||
|
|
||||||
|
//bottom
|
||||||
|
for (var i = x * roomWidth; i < (x * roomWidth) + roomWidth; i++) {
|
||||||
|
node.getNodeChild(0).drawNode(round( i * tileWidth_mod + camX_mod), round( ((y+1) * roomHeight -1) * tileHeight_mod + camY_mod), round( tileWidth_mod), round( tileHeight_mod));
|
||||||
|
}
|
||||||
|
|
||||||
|
//right
|
||||||
|
for (var j = y * roomHeight; j < (y * roomHeight) + roomHeight; j++) {
|
||||||
|
node.getNodeChild(0).drawNode(round( ((x + 1) * roomWidth -1) * tileWidth_mod + camX_mod ), round( j * tileHeight_mod + camY_mod ), round( tileWidth_mod ), round( tileHeight_mod ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn round(x): int {
|
||||||
|
var f = floor(x);
|
||||||
|
return x - f >= 0.5 ? f + 1 : f;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn floor(x): int {
|
||||||
|
return int x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ceil(x): int {
|
||||||
|
var f = floor(x);
|
||||||
|
return x - f != 0 ? f + 1 : f;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn min(a, b) {
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max(a, b) {
|
||||||
|
return a > b ? a : b;
|
||||||
|
}
|
||||||
2
assets/scripts/tilemap/tile.toy
Normal file
2
assets/scripts/tilemap/tile.toy
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
//EMPTY
|
||||||
|
|
||||||
95
assets/scripts/tilemap/tilemap.toy
Normal file
95
assets/scripts/tilemap/tilemap.toy
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
//this file manages the tilemap-related utilities
|
||||||
|
import standard;
|
||||||
|
import node;
|
||||||
|
|
||||||
|
var childCounter: int = 0;
|
||||||
|
|
||||||
|
var levelXCount: int const = 4;
|
||||||
|
var levelYCount: int const = 4;
|
||||||
|
|
||||||
|
var camX: float = 0;
|
||||||
|
var camY: float = 0;
|
||||||
|
|
||||||
|
//TODO: reference these from a global source (root?)
|
||||||
|
var tileWidth: float const = 100;
|
||||||
|
var tileHeight: float const = 100;
|
||||||
|
|
||||||
|
var roomWidth: float const = 10;
|
||||||
|
var roomHeight: float const = 10;
|
||||||
|
|
||||||
|
var screenWidth: float = 1080;
|
||||||
|
var screenHeight: float = 720;
|
||||||
|
|
||||||
|
|
||||||
|
//util to generate and init a child node of a given parent
|
||||||
|
fn makeChild(parent: opaque, fname: string) {
|
||||||
|
var child: opaque = loadNode(fname);
|
||||||
|
parent.pushNode(child);
|
||||||
|
child.initNode();
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn loadLayer(node: opaque, layerName: string) {
|
||||||
|
//load the given layer as a child
|
||||||
|
var layerNode = node.makeChild("scripts:/tilemap/" + layerName);
|
||||||
|
childCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var stepCounter = 0;
|
||||||
|
fn onStep(node: opaque) {
|
||||||
|
stepCounter++;
|
||||||
|
|
||||||
|
camX--;
|
||||||
|
camY--;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn onDraw(node: opaque) {
|
||||||
|
print stepCounter;
|
||||||
|
stepCounter = 0;
|
||||||
|
|
||||||
|
//TODO: reference the camera width & height
|
||||||
|
//TODO: render parallax
|
||||||
|
|
||||||
|
//cull out-of-bounds regions
|
||||||
|
var lowerX = abs(floor(floor((camX-screenWidth/2) / tileWidth) / float roomWidth));
|
||||||
|
var upperX = abs(ceil(floor((camX-screenWidth*1.5) / float tileWidth) / float roomWidth));
|
||||||
|
|
||||||
|
var lowerY = abs(floor(floor((camY-screenHeight/2) / tileHeight) / float roomHeight));
|
||||||
|
var upperY = abs(ceil(floor((camY-screenHeight*1.5) / float tileHeight) / float roomHeight));
|
||||||
|
|
||||||
|
//bounds check
|
||||||
|
lowerX = max(lowerX, 0);
|
||||||
|
upperX = min(upperX + 1, levelXCount);
|
||||||
|
lowerY = max(lowerY, 0);
|
||||||
|
upperY = min(upperY + 1, levelYCount);
|
||||||
|
|
||||||
|
for (var c = 0; c < childCounter; c++) {
|
||||||
|
for (var j = lowerY; j <= upperY; j++) {
|
||||||
|
for (var i = lowerX; i <= upperX; i++) {
|
||||||
|
node.getNodeChild(c).callNodeFn("drawRoom", i, j, c * 4.0, camX, camY, screenWidth, screenHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn round(x): int {
|
||||||
|
var f = floor(x);
|
||||||
|
return x - f >= 0.5 ? f + 1 : f;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn floor(x): int {
|
||||||
|
return int x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ceil(x): int {
|
||||||
|
var f = floor(x);
|
||||||
|
return x - f != 0 ? f + 1 : f;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn min(a, b) {
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max(a, b) {
|
||||||
|
return a > b ? a : b;
|
||||||
|
}
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 700 B |
BIN
assets/sprites/tile-background.png
Normal file
BIN
assets/sprites/tile-background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 179 B |
BIN
assets/sprites/tile-wall.png
Normal file
BIN
assets/sprites/tile-wall.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 179 B |
@@ -4,6 +4,7 @@
|
|||||||
#include "lib_input.h"
|
#include "lib_input.h"
|
||||||
#include "lib_node.h"
|
#include "lib_node.h"
|
||||||
#include "lib_standard.h"
|
#include "lib_standard.h"
|
||||||
|
#include "lib_random.h"
|
||||||
#include "lib_runner.h"
|
#include "lib_runner.h"
|
||||||
#include "repl_tools.h"
|
#include "repl_tools.h"
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ void Box_initEngine() {
|
|||||||
//init Toy
|
//init Toy
|
||||||
Toy_initInterpreter(&engine.interpreter);
|
Toy_initInterpreter(&engine.interpreter);
|
||||||
Toy_injectNativeHook(&engine.interpreter, "standard", Toy_hookStandard);
|
Toy_injectNativeHook(&engine.interpreter, "standard", Toy_hookStandard);
|
||||||
|
Toy_injectNativeHook(&engine.interpreter, "random", Toy_hookRandom);
|
||||||
Toy_injectNativeHook(&engine.interpreter, "runner", Toy_hookRunner);
|
Toy_injectNativeHook(&engine.interpreter, "runner", Toy_hookRunner);
|
||||||
Toy_injectNativeHook(&engine.interpreter, "engine", Box_hookEngine);
|
Toy_injectNativeHook(&engine.interpreter, "engine", Box_hookEngine);
|
||||||
Toy_injectNativeHook(&engine.interpreter, "node", Box_hookNode);
|
Toy_injectNativeHook(&engine.interpreter, "node", Box_hookNode);
|
||||||
@@ -338,7 +340,7 @@ void Box_execEngine() {
|
|||||||
//set up time
|
//set up time
|
||||||
engine.realTime = clock();
|
engine.realTime = clock();
|
||||||
engine.simTime = engine.realTime;
|
engine.simTime = engine.realTime;
|
||||||
clock_t delta = (double) CLOCKS_PER_SEC / 240.0;
|
clock_t delta = (double) CLOCKS_PER_SEC / 60.0;
|
||||||
|
|
||||||
while (engine.running) {
|
while (engine.running) {
|
||||||
execEvents();
|
execEvents();
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ static int nativeLoadNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
|
|||||||
|
|
||||||
//init the inner interpreter manually
|
//init the inner interpreter manually
|
||||||
Toy_initLiteralArray(&inner.literalCache);
|
Toy_initLiteralArray(&inner.literalCache);
|
||||||
|
Toy_initLiteralArray(&inner.stack);
|
||||||
|
inner.hooks = interpreter->hooks;
|
||||||
inner.scope = Toy_pushScope(NULL);
|
inner.scope = Toy_pushScope(NULL);
|
||||||
inner.bytecode = tb;
|
inner.bytecode = tb;
|
||||||
inner.length = size;
|
inner.length = size;
|
||||||
@@ -62,8 +64,6 @@ static int nativeLoadNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
|
|||||||
inner.codeStart = -1;
|
inner.codeStart = -1;
|
||||||
inner.depth = interpreter->depth + 1;
|
inner.depth = interpreter->depth + 1;
|
||||||
inner.panic = false;
|
inner.panic = false;
|
||||||
Toy_initLiteralArray(&inner.stack);
|
|
||||||
inner.hooks = interpreter->hooks;
|
|
||||||
Toy_setInterpreterPrint(&inner, interpreter->printOutput);
|
Toy_setInterpreterPrint(&inner, interpreter->printOutput);
|
||||||
Toy_setInterpreterAssert(&inner, interpreter->assertOutput);
|
Toy_setInterpreterAssert(&inner, interpreter->assertOutput);
|
||||||
Toy_setInterpreterError(&inner, interpreter->errorOutput);
|
Toy_setInterpreterError(&inner, interpreter->errorOutput);
|
||||||
@@ -74,11 +74,7 @@ static int nativeLoadNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
|
|||||||
Toy_Literal nodeLiteral = TOY_TO_OPAQUE_LITERAL(node, node->tag);
|
Toy_Literal nodeLiteral = TOY_TO_OPAQUE_LITERAL(node, node->tag);
|
||||||
Toy_pushLiteralArray(&interpreter->stack, nodeLiteral);
|
Toy_pushLiteralArray(&interpreter->stack, nodeLiteral);
|
||||||
|
|
||||||
//cleanup
|
//cleanup (NOT the scope - that needs to hang around)
|
||||||
while (inner.scope) {
|
|
||||||
inner.scope = Toy_popScope(inner.scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
Toy_freeLiteralArray(&inner.stack);
|
Toy_freeLiteralArray(&inner.stack);
|
||||||
Toy_freeLiteralArray(&inner.literalCache);
|
Toy_freeLiteralArray(&inner.literalCache);
|
||||||
Toy_freeLiteral(filePathLiteral);
|
Toy_freeLiteral(filePathLiteral);
|
||||||
@@ -221,6 +217,11 @@ static int nativeGetNodeChild(Toy_Interpreter* interpreter, Toy_LiteralArray* ar
|
|||||||
Toy_freeLiteral(parentIdn);
|
Toy_freeLiteral(parentIdn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Toy_Literal indexIdn = index;
|
||||||
|
if (TOY_IS_IDENTIFIER(index) && Toy_parseIdentifierToValue(interpreter, &index)) {
|
||||||
|
Toy_freeLiteral(indexIdn);
|
||||||
|
}
|
||||||
|
|
||||||
if (!TOY_IS_OPAQUE(parent) || !TOY_IS_INTEGER(index)) {
|
if (!TOY_IS_OPAQUE(parent) || !TOY_IS_INTEGER(index)) {
|
||||||
interpreter->errorOutput("Incorrect argument type passed to getNodeChild\n");
|
interpreter->errorOutput("Incorrect argument type passed to getNodeChild\n");
|
||||||
Toy_freeLiteral(parent);
|
Toy_freeLiteral(parent);
|
||||||
@@ -528,15 +529,15 @@ static int nativeDrawNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nativeCallNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
static int nativeCallNodeFn(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
//checks
|
//checks
|
||||||
if (arguments->count < 2) {
|
if (arguments->count < 2) {
|
||||||
interpreter->errorOutput("Too few arguments passed to callNode\n");
|
interpreter->errorOutput("Too few arguments passed to callNode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_LiteralArray extraArgs;
|
Toy_LiteralArray extraArgsBackwards;
|
||||||
Toy_initLiteralArray(&extraArgs);
|
Toy_initLiteralArray(&extraArgsBackwards);
|
||||||
|
|
||||||
//extract the extra arg values
|
//extract the extra arg values
|
||||||
while (arguments->count > 2) {
|
while (arguments->count > 2) {
|
||||||
@@ -547,10 +548,22 @@ static int nativeCallNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
|
|||||||
Toy_freeLiteral(idn);
|
Toy_freeLiteral(idn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(&extraArgsBackwards, tmp);
|
||||||
|
Toy_freeLiteral(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//reverse the extra args
|
||||||
|
Toy_LiteralArray extraArgs;
|
||||||
|
Toy_initLiteralArray(&extraArgs);
|
||||||
|
|
||||||
|
while (extraArgsBackwards.count > 0) {
|
||||||
|
Toy_Literal tmp = Toy_popLiteralArray(&extraArgsBackwards);
|
||||||
Toy_pushLiteralArray(&extraArgs, tmp);
|
Toy_pushLiteralArray(&extraArgs, tmp);
|
||||||
Toy_freeLiteral(tmp);
|
Toy_freeLiteral(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Toy_freeLiteralArray(&extraArgsBackwards);
|
||||||
|
|
||||||
//back on track
|
//back on track
|
||||||
Toy_Literal fnName = Toy_popLiteralArray(arguments);
|
Toy_Literal fnName = Toy_popLiteralArray(arguments);
|
||||||
Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments);
|
Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments);
|
||||||
@@ -609,7 +622,9 @@ int Box_hookNode(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Liter
|
|||||||
{"freeTexture", nativeFreeTexture},
|
{"freeTexture", nativeFreeTexture},
|
||||||
{"setRect", nativeSetRect},
|
{"setRect", nativeSetRect},
|
||||||
{"drawNode", nativeDrawNode},
|
{"drawNode", nativeDrawNode},
|
||||||
{"callNode", nativeCallNode},
|
{"callNodeFn", nativeCallNodeFn},
|
||||||
|
|
||||||
|
//get rect, get node var, create empty node, get child count, get root node
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
196
box/lib_random.c
Normal file
196
box/lib_random.c
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
#include "lib_random.h"
|
||||||
|
|
||||||
|
#include "toy_memory.h"
|
||||||
|
|
||||||
|
static int hashInt(int x) {
|
||||||
|
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||||
|
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||||
|
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
||||||
|
x = (x >> 16) ^ x;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct Toy_RandomGenerator {
|
||||||
|
int seed; //mutated with each call
|
||||||
|
} Toy_RandomGenerator;
|
||||||
|
|
||||||
|
//Toy native functions
|
||||||
|
static int nativeCreateRandomGenerator(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to createRandomGenerator\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the seed argument
|
||||||
|
Toy_Literal seedLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal seedLiteralIdn = seedLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(seedLiteral) && Toy_parseIdentifierToValue(interpreter, &seedLiteral)) {
|
||||||
|
Toy_freeLiteral(seedLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_IS_IDENTIFIER(seedLiteral)) {
|
||||||
|
Toy_freeLiteral(seedLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TOY_IS_INTEGER(seedLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect literal type passed to createRandomGenerator");
|
||||||
|
Toy_freeLiteral(seedLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate the generator object
|
||||||
|
Toy_RandomGenerator* generator = TOY_ALLOCATE(Toy_RandomGenerator, 1);
|
||||||
|
generator->seed = TOY_AS_INTEGER(seedLiteral);
|
||||||
|
Toy_Literal generatorLiteral = TOY_TO_OPAQUE_LITERAL(generator, TOY_OPAQUE_TAG_RANDOM);
|
||||||
|
|
||||||
|
//return and cleanup
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, generatorLiteral);
|
||||||
|
|
||||||
|
Toy_freeLiteral(seedLiteral);
|
||||||
|
Toy_freeLiteral(generatorLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeGenerateRandomNumber(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to generateRandomNumber\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the runner object
|
||||||
|
Toy_Literal generatorLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal generatorLiteralIdn = generatorLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(generatorLiteral) && Toy_parseIdentifierToValue(interpreter, &generatorLiteral)) {
|
||||||
|
Toy_freeLiteral(generatorLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_IS_IDENTIFIER(generatorLiteral)) {
|
||||||
|
Toy_freeLiteral(generatorLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_GET_OPAQUE_TAG(generatorLiteral) != TOY_OPAQUE_TAG_RANDOM) {
|
||||||
|
interpreter->errorOutput("Unrecognized opaque literal in generateRandomNumber\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_RandomGenerator* generator = TOY_AS_OPAQUE(generatorLiteral);
|
||||||
|
|
||||||
|
//generate the new value and package up the return
|
||||||
|
generator->seed = hashInt(generator->seed);
|
||||||
|
|
||||||
|
Toy_Literal resultLiteral = TOY_TO_INTEGER_LITERAL(generator->seed);
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(generatorLiteral);
|
||||||
|
Toy_freeLiteral(resultLiteral);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nativeFreeRandomGenerator(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
//no arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to freeRandomGenerator\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the runner object
|
||||||
|
Toy_Literal generatorLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
Toy_Literal generatorLiteralIdn = generatorLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(generatorLiteral) && Toy_parseIdentifierToValue(interpreter, &generatorLiteral)) {
|
||||||
|
Toy_freeLiteral(generatorLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_IS_IDENTIFIER(generatorLiteral)) {
|
||||||
|
Toy_freeLiteral(generatorLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_GET_OPAQUE_TAG(generatorLiteral) != TOY_OPAQUE_TAG_RANDOM) {
|
||||||
|
interpreter->errorOutput("Unrecognized opaque literal in freeRandomGenerator\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_RandomGenerator* generator = TOY_AS_OPAQUE(generatorLiteral);
|
||||||
|
|
||||||
|
//clear out the runner object
|
||||||
|
TOY_FREE(Toy_RandomGenerator, generator);
|
||||||
|
Toy_freeLiteral(generatorLiteral);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//call the hook
|
||||||
|
typedef struct Natives {
|
||||||
|
const char* name;
|
||||||
|
Toy_NativeFn fn;
|
||||||
|
} Natives;
|
||||||
|
|
||||||
|
int Toy_hookRandom(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
||||||
|
//build the natives list
|
||||||
|
Natives natives[] = {
|
||||||
|
{"createRandomGenerator", nativeCreateRandomGenerator},
|
||||||
|
{"generateRandomNumber", nativeGenerateRandomNumber},
|
||||||
|
{"freeRandomGenerator", nativeFreeRandomGenerator},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
//store the library in an aliased dictionary
|
||||||
|
if (!TOY_IS_NULL(alias)) {
|
||||||
|
//make sure the name isn't taken
|
||||||
|
if (Toy_isDelcaredScopeVariable(interpreter->scope, alias)) {
|
||||||
|
interpreter->errorOutput("Can't override an existing variable\n");
|
||||||
|
Toy_freeLiteral(alias);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//create the dictionary to load up with functions
|
||||||
|
Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
||||||
|
Toy_initLiteralDictionary(dictionary);
|
||||||
|
|
||||||
|
//load the dict with functions
|
||||||
|
for (int i = 0; natives[i].name; i++) {
|
||||||
|
Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString(natives[i].name));
|
||||||
|
Toy_Literal func = TOY_TO_FUNCTION_NATIVE_LITERAL(natives[i].fn);
|
||||||
|
|
||||||
|
Toy_setLiteralDictionary(dictionary, name, func);
|
||||||
|
|
||||||
|
Toy_freeLiteral(name);
|
||||||
|
Toy_freeLiteral(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
//build the type
|
||||||
|
Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true);
|
||||||
|
Toy_Literal strType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true);
|
||||||
|
Toy_Literal fnType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_FUNCTION_NATIVE, true);
|
||||||
|
TOY_TYPE_PUSH_SUBTYPE(&type, strType);
|
||||||
|
TOY_TYPE_PUSH_SUBTYPE(&type, fnType);
|
||||||
|
|
||||||
|
//set scope
|
||||||
|
Toy_Literal dict = TOY_TO_DICTIONARY_LITERAL(dictionary);
|
||||||
|
Toy_declareScopeVariable(interpreter->scope, alias, type);
|
||||||
|
Toy_setScopeVariable(interpreter->scope, alias, dict, false);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(dict);
|
||||||
|
Toy_freeLiteral(type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//default
|
||||||
|
for (int i = 0; natives[i].name; i++) {
|
||||||
|
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
7
box/lib_random.h
Normal file
7
box/lib_random.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "toy_interpreter.h"
|
||||||
|
|
||||||
|
int Toy_hookRandom(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias);
|
||||||
|
|
||||||
|
#define TOY_OPAQUE_TAG_RANDOM 200
|
||||||
@@ -7,6 +7,49 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
static int nativeAbs(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to abs\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the self
|
||||||
|
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
//parse to value if needed
|
||||||
|
Toy_Literal selfLiteralIdn = selfLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
|
||||||
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_IS_IDENTIFIER(selfLiteral)) {
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(TOY_IS_INTEGER(selfLiteral) || TOY_IS_FLOAT(selfLiteral))) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to abs\n");
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal result;
|
||||||
|
|
||||||
|
if (TOY_IS_INTEGER(selfLiteral)) {
|
||||||
|
result = TOY_TO_INTEGER_LITERAL( TOY_AS_INTEGER(selfLiteral) > 0 ? TOY_AS_INTEGER(selfLiteral) : -TOY_AS_INTEGER(selfLiteral) );
|
||||||
|
}
|
||||||
|
if (TOY_IS_FLOAT(selfLiteral)) {
|
||||||
|
result = TOY_TO_FLOAT_LITERAL( TOY_AS_FLOAT(selfLiteral) > 0 ? TOY_AS_FLOAT(selfLiteral) : -TOY_AS_FLOAT(selfLiteral) );
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
|
|
||||||
|
Toy_freeLiteral(result);
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
static int nativeClock(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
//no arguments
|
//no arguments
|
||||||
if (arguments->count != 0) {
|
if (arguments->count != 0) {
|
||||||
@@ -702,6 +745,36 @@ static int nativeGetValues(Toy_Interpreter* interpreter, Toy_LiteralArray* argum
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nativeHash(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to hash\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the self
|
||||||
|
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
//parse to value if needed
|
||||||
|
Toy_Literal selfLiteralIdn = selfLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
|
||||||
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TOY_IS_IDENTIFIER(selfLiteral)) {
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal result = TOY_TO_INTEGER_LITERAL(Toy_hashLiteral(selfLiteral));
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, result);
|
||||||
|
|
||||||
|
Toy_freeLiteral(result);
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int nativeIndexOf(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
static int nativeIndexOf(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
//no arguments
|
//no arguments
|
||||||
if (arguments->count != 2) {
|
if (arguments->count != 2) {
|
||||||
@@ -1667,6 +1740,7 @@ typedef struct Natives {
|
|||||||
int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias) {
|
||||||
//build the natives list
|
//build the natives list
|
||||||
Natives natives[] = {
|
Natives natives[] = {
|
||||||
|
{"abs", nativeAbs},
|
||||||
{"clock", nativeClock},
|
{"clock", nativeClock},
|
||||||
{"concat", nativeConcat}, //array, dictionary, string
|
{"concat", nativeConcat}, //array, dictionary, string
|
||||||
{"containsKey", nativeContainsKey}, //dictionary
|
{"containsKey", nativeContainsKey}, //dictionary
|
||||||
@@ -1676,6 +1750,7 @@ int Toy_hookStandard(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L
|
|||||||
{"forEach", nativeForEach}, //array, dictionary
|
{"forEach", nativeForEach}, //array, dictionary
|
||||||
{"getKeys", nativeGetKeys}, //dictionary
|
{"getKeys", nativeGetKeys}, //dictionary
|
||||||
{"getValues", nativeGetValues}, //dictionary
|
{"getValues", nativeGetValues}, //dictionary
|
||||||
|
{"hash", nativeHash},
|
||||||
{"indexOf", nativeIndexOf}, //array
|
{"indexOf", nativeIndexOf}, //array
|
||||||
{"map", nativeMap}, //array, dictionary
|
{"map", nativeMap}, //array, dictionary
|
||||||
{"reduce", nativeReduce}, //array, dictionary
|
{"reduce", nativeReduce}, //array, dictionary
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "repl_tools.h"
|
#include "repl_tools.h"
|
||||||
#include "lib_about.h"
|
#include "lib_about.h"
|
||||||
#include "lib_standard.h"
|
#include "lib_standard.h"
|
||||||
|
#include "lib_random.h"
|
||||||
#include "lib_runner.h"
|
#include "lib_runner.h"
|
||||||
|
|
||||||
#include "toy_console_colors.h"
|
#include "toy_console_colors.h"
|
||||||
@@ -112,6 +113,7 @@ void Toy_runBinary(const unsigned char* tb, size_t size) {
|
|||||||
//inject the libs
|
//inject the libs
|
||||||
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
|
Toy_injectNativeHook(&interpreter, "about", Toy_hookAbout);
|
||||||
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
|
Toy_injectNativeHook(&interpreter, "standard", Toy_hookStandard);
|
||||||
|
Toy_injectNativeHook(&interpreter, "random", Toy_hookRandom);
|
||||||
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
|
Toy_injectNativeHook(&interpreter, "runner", Toy_hookRunner);
|
||||||
|
|
||||||
Toy_runInterpreter(&interpreter, tb, (int)size);
|
Toy_runInterpreter(&interpreter, tb, (int)size);
|
||||||
|
|||||||
Reference in New Issue
Block a user