Room generation looks good
This commit is contained in:
@@ -1,163 +0,0 @@
|
|||||||
import standard;
|
|
||||||
import node;
|
|
||||||
import random;
|
|
||||||
|
|
||||||
//variables
|
|
||||||
var gridPositionX: int = 1;
|
|
||||||
var gridPositionY: int = 1;
|
|
||||||
|
|
||||||
var direction: int = null; //BUGFIX: animation not looping properly
|
|
||||||
|
|
||||||
var stepAI: int = 0;
|
|
||||||
|
|
||||||
//polyfills - animating different cycles on one image
|
|
||||||
var walkAnimationCounter: int = 0;
|
|
||||||
|
|
||||||
fn faceDown(node: opaque) {
|
|
||||||
if (direction == 0) return;
|
|
||||||
direction = 0;
|
|
||||||
node.setNodeRect(0, 0, 32, 32);
|
|
||||||
node.setNodeFrames(2);
|
|
||||||
walkAnimationCounter = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn faceUp(node: opaque) {
|
|
||||||
if (direction == 1) return;
|
|
||||||
direction = 1;
|
|
||||||
node.setNodeRect(32 * 2, 0, 32, 32);
|
|
||||||
node.setNodeFrames(2);
|
|
||||||
walkAnimationCounter = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn faceRight(node: opaque) {
|
|
||||||
if (direction == 2) return;
|
|
||||||
direction = 2;
|
|
||||||
node.setNodeRect(32 * 4, 0, 32, 32);
|
|
||||||
node.setNodeFrames(2);
|
|
||||||
walkAnimationCounter = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn faceLeft(node: opaque) {
|
|
||||||
if (direction == 3) return;
|
|
||||||
direction = 3;
|
|
||||||
node.setNodeRect(32 * 6, 0, 32, 32);
|
|
||||||
node.setNodeFrames(2);
|
|
||||||
walkAnimationCounter = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//accessors & mutators
|
|
||||||
fn setGridPosition(node: opaque, x: int, y: int) {
|
|
||||||
gridPositionX = x;
|
|
||||||
gridPositionY = y;
|
|
||||||
|
|
||||||
node.setNodePositionX(floor( gridPositionX * node.getNodeRectW() / node.getNodeScaleX() ));
|
|
||||||
node.setNodePositionY(floor( gridPositionY * node.getNodeRectH() / node.getNodeScaleY() ));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getGridPositionX(node: opaque) {
|
|
||||||
return gridPositionX;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getGridPositionY(node: opaque) {
|
|
||||||
return gridPositionY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//lifecycle functions
|
|
||||||
fn onLoad(node: opaque) {
|
|
||||||
node.loadNodeTexture("sprites:/drone.png");
|
|
||||||
node.faceDown();
|
|
||||||
|
|
||||||
node.setNodeScaleX(CAMERA_SCALE_X);
|
|
||||||
node.setNodeScaleY(CAMERA_SCALE_Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
//fn onUpdate(node: opaque, delta: int) {
|
|
||||||
// //
|
|
||||||
//}
|
|
||||||
|
|
||||||
fn onStep(node: opaque) {
|
|
||||||
if (++walkAnimationCounter >= 12) {
|
|
||||||
node.incrementCurrentNodeFrame();
|
|
||||||
walkAnimationCounter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//move in realspace
|
|
||||||
var distX = gridPositionX * TILE_PIXEL_WIDTH - node.getNodePositionX();
|
|
||||||
var distY = gridPositionY * TILE_PIXEL_HEIGHT - node.getNodePositionY();
|
|
||||||
|
|
||||||
node.setNodeMotionX( normalize(distX) );
|
|
||||||
node.setNodeMotionY( normalize(distY) );
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onFree(node: opaque) {
|
|
||||||
node.freeNodeTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onDraw(node: opaque) {
|
|
||||||
var posX: int = node.getNodeWorldPositionX();
|
|
||||||
var posY: int = node.getNodeWorldPositionY();
|
|
||||||
|
|
||||||
var scaleX: float = node.getNodeWorldScaleX();
|
|
||||||
var scaleY: float = node.getNodeWorldScaleY();
|
|
||||||
|
|
||||||
//this offset is because the sprite cell for lejana is twice as big as the sprite cell for the floor tiles
|
|
||||||
var originOffsetX: int = node.getNodeRectW() * int scaleX / 4;
|
|
||||||
var originOffsetY: int = node.getNodeRectH() * int scaleY / 2;
|
|
||||||
|
|
||||||
node.drawNode(
|
|
||||||
floor(posX * scaleX) - originOffsetX + globalCameraX,
|
|
||||||
floor(posY * scaleY) - originOffsetY + globalCameraY,
|
|
||||||
floor(node.getNodeRectW() * scaleX),
|
|
||||||
floor(node.getNodeRectH() * scaleY)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//gameplay functions
|
|
||||||
fn runAI(node: opaque, rng: opaque) {
|
|
||||||
if (stepAI++ >= 1) {
|
|
||||||
stepAI = 0;
|
|
||||||
|
|
||||||
var dir = rng.generateRandomNumber() % 4;
|
|
||||||
var moveX = 0;
|
|
||||||
var moveY = 0;
|
|
||||||
|
|
||||||
if (dir == 0) {
|
|
||||||
moveY += 1;
|
|
||||||
node.faceDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir == 1) {
|
|
||||||
moveY -= 1;
|
|
||||||
node.faceUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir == 2) {
|
|
||||||
moveX += 1;
|
|
||||||
node.faceRight();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir == 3) {
|
|
||||||
moveX -= 1;
|
|
||||||
node.faceLeft();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.getParentNode().callNodeFn("getWalkableAt", gridPositionX + moveX, gridPositionY + moveY)) {
|
|
||||||
gridPositionX += moveX;
|
|
||||||
gridPositionY += moveY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//polyfills - move these to standard
|
|
||||||
fn normalize(x): int {
|
|
||||||
if (x > 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (x < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,258 +0,0 @@
|
|||||||
import standard;
|
|
||||||
import node;
|
|
||||||
|
|
||||||
var gridPositionX: int = 1; //position on the game grid
|
|
||||||
var gridPositionY: int = 1;
|
|
||||||
|
|
||||||
var inputX: int = 0; //cache the keyboard input
|
|
||||||
var inputY: int = 0;
|
|
||||||
|
|
||||||
var direction: int = null; //BUGFIX: animation not looping properly
|
|
||||||
var enableMovementCounter: int = 60 * 3; //BUGFIX: freeze while drones reach their starting spot
|
|
||||||
|
|
||||||
//polyfills - animating different cycles on one image
|
|
||||||
var walkAnimationCounter: int = 0;
|
|
||||||
var attackAnimationCounter: int = 0;
|
|
||||||
|
|
||||||
//utils for facing different directions (idling)
|
|
||||||
fn faceDown(node: opaque) {
|
|
||||||
if (direction == 0) return;
|
|
||||||
direction = 0;
|
|
||||||
node.setNodeRect(0, 0, 32, 32);
|
|
||||||
node.setNodeFrames(4);
|
|
||||||
walkAnimationCounter = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn faceUp(node: opaque) {
|
|
||||||
if (direction == 1) return;
|
|
||||||
direction = 1;
|
|
||||||
node.setNodeRect(32 * 4, 0, 32, 32);
|
|
||||||
node.setNodeFrames(4);
|
|
||||||
walkAnimationCounter = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn faceRight(node: opaque) {
|
|
||||||
if (direction == 2) return;
|
|
||||||
direction = 2;
|
|
||||||
node.setNodeRect(32 * 8, 0, 32, 32);
|
|
||||||
node.setNodeFrames(4);
|
|
||||||
walkAnimationCounter = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn faceLeft(node: opaque) {
|
|
||||||
if (direction == 3) return;
|
|
||||||
direction = 3;
|
|
||||||
node.setNodeRect(32 * 12, 0, 32, 32);
|
|
||||||
node.setNodeFrames(4);
|
|
||||||
walkAnimationCounter = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
//accessors & mutators
|
|
||||||
fn setGridPosition(node: opaque, x: int, y: int) {
|
|
||||||
gridPositionX = x;
|
|
||||||
gridPositionY = y;
|
|
||||||
|
|
||||||
node.setNodePositionX(floor( gridPositionX * node.getNodeRectW() / node.getNodeScaleX() ));
|
|
||||||
node.setNodePositionY(floor( gridPositionY * node.getNodeRectH() / node.getNodeScaleY() ));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getGridPositionX(node: opaque) {
|
|
||||||
return gridPositionX;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getGridPositionY(node: opaque) {
|
|
||||||
return gridPositionY;
|
|
||||||
}
|
|
||||||
|
|
||||||
//lifecycle functions
|
|
||||||
fn onLoad(node: opaque) {
|
|
||||||
node.loadNodeTexture("sprites:/lejana.png"); //NOTE: all of this script is mapped to this sprite sheet
|
|
||||||
node.faceDown();
|
|
||||||
|
|
||||||
node.setNodeScaleX(CAMERA_SCALE_X);
|
|
||||||
node.setNodeScaleY(CAMERA_SCALE_Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
//fn onUpdate(node: opaque, delta: int) {
|
|
||||||
// //
|
|
||||||
//}
|
|
||||||
|
|
||||||
fn onStep(node: opaque) {
|
|
||||||
//initial freeze
|
|
||||||
if (enableMovementCounter > 0) {
|
|
||||||
enableMovementCounter--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//animation - start idling
|
|
||||||
if (attackAnimationCounter == 0) {
|
|
||||||
//move to standing state
|
|
||||||
if (node.getNodeRectY() != 0) {
|
|
||||||
node.setNodeRect(direction * 32 * 4, 0, 32, 32);
|
|
||||||
node.setNodeFrames(4);
|
|
||||||
walkAnimationCounter = 12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//animation - start attacking
|
|
||||||
if (--attackAnimationCounter >= 0) {
|
|
||||||
//move to attacking state
|
|
||||||
if (node.getNodeRectY() != 32) {
|
|
||||||
node.setNodeRect(direction * 32 * 4, 32, 32, 32);
|
|
||||||
node.setNodeFrames(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((attackAnimationCounter+1) % 4 == 0) { //+1 for a bugfix
|
|
||||||
node.incrementCurrentNodeFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
//skip out
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//facing
|
|
||||||
if (inputY > 0) {
|
|
||||||
node.faceDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (inputY < 0) {
|
|
||||||
node.faceUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (inputX > 0) {
|
|
||||||
node.faceRight();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (inputX < 0) {
|
|
||||||
node.faceLeft();
|
|
||||||
}
|
|
||||||
|
|
||||||
//BUGFIX for smooth animation fo
|
|
||||||
var lesser = 0;
|
|
||||||
if ((inputX != 0 || inputY != 0) && attackAnimationCounter == 0) {
|
|
||||||
lesser = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
//actually animate
|
|
||||||
if (--walkAnimationCounter <= lesser) {
|
|
||||||
node.incrementCurrentNodeFrame();
|
|
||||||
walkAnimationCounter = 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
var parent = node.getParentNode(); //check for collisions from the parent
|
|
||||||
|
|
||||||
if (parent.callNodeFn("getWalkableAt", gridPositionX + inputX, gridPositionY + inputY) && abs(inputX) != abs(inputY)) {
|
|
||||||
//calc movement
|
|
||||||
gridPositionX += inputX;
|
|
||||||
gridPositionY += inputY;
|
|
||||||
|
|
||||||
parent.callNodeFn("runAI");
|
|
||||||
}
|
|
||||||
|
|
||||||
//move in realspace
|
|
||||||
var distX = gridPositionX * TILE_PIXEL_WIDTH - node.getNodePositionX();
|
|
||||||
var distY = gridPositionY * TILE_PIXEL_HEIGHT - node.getNodePositionY();
|
|
||||||
|
|
||||||
node.setNodeMotionX( normalize(distX) );
|
|
||||||
node.setNodeMotionY( normalize(distY) );
|
|
||||||
|
|
||||||
//reset input
|
|
||||||
inputX = 0;
|
|
||||||
inputY = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onFree(node: opaque) {
|
|
||||||
node.freeNodeTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onDraw(node: opaque) {
|
|
||||||
var posX: int = node.getNodeWorldPositionX();
|
|
||||||
var posY: int = node.getNodeWorldPositionY();
|
|
||||||
|
|
||||||
var scaleX: float = node.getNodeWorldScaleX();
|
|
||||||
var scaleY: float = node.getNodeWorldScaleY();
|
|
||||||
|
|
||||||
//this offset is because the sprite cell for lejana is twice as big as the sprite cell for the floor tiles
|
|
||||||
var originOffsetX: int = player.getNodeRectW() / 2;
|
|
||||||
var originOffsetY: int = player.getNodeRectH();
|
|
||||||
|
|
||||||
node.drawNode(
|
|
||||||
floor(posX * scaleX) - originOffsetX + globalCameraX,
|
|
||||||
floor(posY * scaleY) - originOffsetY + globalCameraY,
|
|
||||||
floor(node.getNodeRectW() * scaleX),
|
|
||||||
floor(node.getNodeRectH() * scaleY)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//event functions
|
|
||||||
fn onKeyDown(node: opaque, event: string) {
|
|
||||||
//initial freeze
|
|
||||||
if (enableMovementCounter > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//enable attack
|
|
||||||
if (event == "character_attack" && inputX == 0 && inputY == 0) {
|
|
||||||
attackAnimationCounter = 12;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if moving, don't take any more input
|
|
||||||
if (node.getNodeMotionX() != 0 || node.getNodeMotionY() != 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event == "character_up") {
|
|
||||||
inputY -= 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event == "character_down") {
|
|
||||||
inputY += 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event == "character_left") {
|
|
||||||
inputX -= 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event == "character_right") {
|
|
||||||
inputX += 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onKeyUp(node: opaque, event: string) {
|
|
||||||
if (event == "character_up" && inputY < 0) {
|
|
||||||
inputY = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event == "character_down" && inputY > 0) {
|
|
||||||
inputY = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event == "character_left" && inputX < 0) {
|
|
||||||
inputX = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event == "character_right" && inputX > 0) {
|
|
||||||
inputX = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//polyfills - move these to standard
|
|
||||||
fn normalize(x): int {
|
|
||||||
if (x > 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (x < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
import standard;
|
|
||||||
import node;
|
|
||||||
import random;
|
|
||||||
|
|
||||||
|
|
||||||
//persistent members
|
|
||||||
var tilemap: opaque = null;
|
|
||||||
var stepCounter: opaque = null;
|
|
||||||
var player: opaque = null;
|
|
||||||
var enemies: [opaque] = null;
|
|
||||||
|
|
||||||
var collisionDataCache: [bool] = null;
|
|
||||||
|
|
||||||
var rng: opaque = null; //TODO: does this have an opaque tag?
|
|
||||||
|
|
||||||
//lifecycle functions
|
|
||||||
fn onInit(node: opaque) {
|
|
||||||
//load the map stuff
|
|
||||||
tilemap = node.loadChild("scripts:/gameplay/tilemap.toy");
|
|
||||||
node.generateScene(clock().hash(), MAP_GRID_WIDTH, MAP_GRID_HEIGHT);
|
|
||||||
|
|
||||||
//load and initialize the UI (depends on map stuff)
|
|
||||||
stepCounter = node.loadChild("scripts:/gameplay/step-counter.toy");
|
|
||||||
stepCounter.setNodeRect(0, 0, CAMERA_SCREEN_W, 32);
|
|
||||||
stepCounter.callNodeFn("setMaxSteps", 100);
|
|
||||||
stepCounter.setNodeLayer(100);
|
|
||||||
|
|
||||||
//offset the scene node, so it shows the map outside separate from the UI
|
|
||||||
node.setNodePositionY(16);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onFree(node: opaque) {
|
|
||||||
//cleanup
|
|
||||||
if (rng != null) {
|
|
||||||
rng.freeRandomGenerator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fn onUpdate(node: opaque, delta: int) {
|
|
||||||
// print "delta: " + string delta;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//fn onStep(node: opaque) {
|
|
||||||
// //
|
|
||||||
//}
|
|
||||||
|
|
||||||
fn onDraw(node: opaque) {
|
|
||||||
//use the onDraw to sort - skip too many steps
|
|
||||||
node.sortChildrenNode(depthComparator);
|
|
||||||
|
|
||||||
var scaleX: float = player.getNodeWorldScaleX();
|
|
||||||
var scaleY: float = player.getNodeWorldScaleY();
|
|
||||||
|
|
||||||
//this offset is because the sprite cell for lejana is twice as big as the sprite cell for the floor tiles
|
|
||||||
var originOffsetX: int = player.getNodeRectW() / 2;
|
|
||||||
var originOffsetY: int = player.getNodeRectH() / 2;
|
|
||||||
|
|
||||||
//use the room scene's onDraw to set the global camera position
|
|
||||||
globalCameraX = floor((CAMERA_SCREEN_W / 2) - (player.getNodeWorldPositionX() * scaleX)) - originOffsetX;
|
|
||||||
globalCameraY = floor((CAMERA_SCREEN_H / 2) - (player.getNodeWorldPositionY() * scaleY)) - originOffsetY;
|
|
||||||
}
|
|
||||||
|
|
||||||
//gameplay functions
|
|
||||||
fn generateScene(node: opaque, seed: int, width: int, height: int) {
|
|
||||||
//reset the array
|
|
||||||
enemies = [];
|
|
||||||
|
|
||||||
if (rng != null) {
|
|
||||||
rng.freeRandomGenerator();
|
|
||||||
}
|
|
||||||
rng = createRandomGenerator(seed);
|
|
||||||
|
|
||||||
//generate map
|
|
||||||
tilemap.callNodeFn("generateFromRng", rng, width, height);
|
|
||||||
collisionDataCache = tilemap.callNodeFn("getCollisionData");
|
|
||||||
|
|
||||||
//place player here, so drop dropping can avoid the player
|
|
||||||
player = node.loadChild("scripts:/gameplay/lejana.toy");
|
|
||||||
player.callNodeFn("setGridPosition", 1, 1);
|
|
||||||
|
|
||||||
//generate drones
|
|
||||||
var droneCount: int const = rng.generateRandomNumber() % 2 + 20;
|
|
||||||
for (var i = 0; i < droneCount; i++) {
|
|
||||||
var d: opaque = node.loadChild("scripts:/gameplay/drone.toy");
|
|
||||||
d.initNode();
|
|
||||||
|
|
||||||
enemies.push(d);
|
|
||||||
|
|
||||||
var x = 0;
|
|
||||||
var y = 0;
|
|
||||||
|
|
||||||
//while generated spot is a collision, or too close to the player
|
|
||||||
while (x == 0 && y == 0 || node.getWalkableAt(x, y) == false || x < width / 6 * 2 && y < height / 6 * 2) {
|
|
||||||
x = rng.generateRandomNumber() % width;
|
|
||||||
y = rng.generateRandomNumber() % height;
|
|
||||||
}
|
|
||||||
|
|
||||||
d.callNodeFn("setGridPosition", x, y);
|
|
||||||
d.setNodePositionX(MAP_GRID_WIDTH * TILE_PIXEL_WIDTH);
|
|
||||||
d.setNodePositionY(MAP_GRID_HEIGHT * TILE_PIXEL_HEIGHT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getWalkableAt(node: opaque, x: int, y: int) {
|
|
||||||
if (collisionDataCache == null || x == null || y == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//entities
|
|
||||||
if (x == player.callNodeFn("getGridPositionX") && y == player.callNodeFn("getGridPositionY")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < enemies.length(); i++) {
|
|
||||||
if (x == enemies[i].callNodeFn("getGridPositionX") && y == enemies[i].callNodeFn("getGridPositionY")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//outside the grid
|
|
||||||
if (y * MAP_GRID_WIDTH + x < 0 || y * MAP_GRID_WIDTH + x >= collisionDataCache.length()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//default
|
|
||||||
return collisionDataCache[y * MAP_GRID_WIDTH + x];
|
|
||||||
}
|
|
||||||
|
|
||||||
fn runAI(node: opaque) {
|
|
||||||
for (var i = 0; i < enemies.length(); i++) {
|
|
||||||
enemies[i].callNodeFn("runAI", rng);
|
|
||||||
}
|
|
||||||
|
|
||||||
stepCounter.callNodeFn("alterRemainingSteps", -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//utils - polyfills
|
|
||||||
fn loadChild(parent: opaque, fname: string) {
|
|
||||||
//TODO: add this to the API proper
|
|
||||||
var child: opaque = loadNode(fname);
|
|
||||||
parent.pushNode(child);
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn depthComparator(lhs: opaque, rhs: opaque) { //for sorting by depth
|
|
||||||
var lhsPositionY = lhs.getNodeWorldPositionY();
|
|
||||||
var rhsPositionY = rhs.getNodeWorldPositionY();
|
|
||||||
|
|
||||||
if (lhsPositionY == null || rhsPositionY == null) { //BUGFIX: children without that function
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lhsPositionY == rhsPositionY) { //BUGFIX: prevent z-fighting
|
|
||||||
var lhsPositionX = lhs.getNodeWorldPositionX();
|
|
||||||
var rhsPositionX = rhs.getNodeWorldPositionX();
|
|
||||||
|
|
||||||
return lhsPositionX < rhsPositionX;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lhsPositionY < rhsPositionY;
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
import node;
|
|
||||||
|
|
||||||
//members
|
|
||||||
var maxSteps: int = 0;
|
|
||||||
var remainingSteps: int = 0;
|
|
||||||
|
|
||||||
//accessors
|
|
||||||
fn getMaxSteps(node: opaque) {
|
|
||||||
return maxSteps;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getRemainingSteps(node: opaque) {
|
|
||||||
return remainingSteps;
|
|
||||||
}
|
|
||||||
|
|
||||||
//mutators
|
|
||||||
fn setMaxSteps(node: opaque, steps: int) {
|
|
||||||
maxSteps = steps;
|
|
||||||
remainingSteps = steps;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setRemainingSteps(node: opaque, steps: int) {
|
|
||||||
remainingSteps = steps;
|
|
||||||
}
|
|
||||||
|
|
||||||
//utility mutators
|
|
||||||
fn alterRemainingSteps(node: opaque, increment: int) {
|
|
||||||
remainingSteps += increment;
|
|
||||||
if (remainingSteps > maxSteps) {
|
|
||||||
remainingSteps = maxSteps;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remainingSteps < 0) {
|
|
||||||
remainingSteps = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return remainingSteps;
|
|
||||||
}
|
|
||||||
|
|
||||||
//utils - polyfills
|
|
||||||
fn loadChild(parent: opaque, fname: string) {
|
|
||||||
var child: opaque = loadNode(fname);
|
|
||||||
parent.pushNode(child);
|
|
||||||
child.setNodeLayer(parent.getNodeLayer());
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
|
|
||||||
//lifecycle functions
|
|
||||||
fn onLoad(node: opaque) {
|
|
||||||
node.loadNodeTexture("sprites:/stepcounter.png");
|
|
||||||
|
|
||||||
node
|
|
||||||
.loadChild("scripts:/gameplay/text.toy")
|
|
||||||
.setNodeText("fonts:/alphbeta.ttf", 32, "Water", 0, 60, 240, 255); //rgba
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onFree(node: opaque) {
|
|
||||||
node.freeNodeTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onDraw(node: opaque) {
|
|
||||||
if (remainingSteps > 0 && maxSteps > 0) {
|
|
||||||
var tmp = float remainingSteps / maxSteps * node.getNodeRectW();
|
|
||||||
var h = node.getNodeRectH();
|
|
||||||
|
|
||||||
node.drawNode(node.getNodePositionX(), node.getNodePositionY(), int tmp, h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import node;
|
|
||||||
|
|
||||||
//this is a child of the step counter, which simply renders text
|
|
||||||
|
|
||||||
fn onDraw(node: opaque) {
|
|
||||||
var posX: int = node.getNodePositionX();
|
|
||||||
var posY: int = node.getNodePositionY();
|
|
||||||
var scaleX: float = node.getNodeScaleX();
|
|
||||||
var scaleY: float = node.getNodeScaleY();
|
|
||||||
|
|
||||||
node.drawNode(floor(posX * scaleX), floor(posY * scaleY));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onFree(node: opaque) {
|
|
||||||
node.freeNodeTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: polyfill?
|
|
||||||
@@ -1,187 +0,0 @@
|
|||||||
import standard;
|
|
||||||
import node;
|
|
||||||
|
|
||||||
//constants mapped to the given file "tileset.png"
|
|
||||||
var tileset: [string : [int]] const = [
|
|
||||||
"empty": [-1. -1, -1],
|
|
||||||
|
|
||||||
"pillar": [0, 0, 0],
|
|
||||||
|
|
||||||
"floor-0": [0, 1, 1],
|
|
||||||
"floor-1": [1, 1, 1],
|
|
||||||
"floor-2": [2, 1, 1],
|
|
||||||
"floor-3": [3, 1, 1],
|
|
||||||
|
|
||||||
"wall-t": [0, 2, 0],
|
|
||||||
"wall-b": [1, 2, 0],
|
|
||||||
"wall-l": [2, 2, 0],
|
|
||||||
"wall-r": [3, 2, 0],
|
|
||||||
|
|
||||||
"corner-tl": [0, 3, 0],
|
|
||||||
"corner-tr": [1, 3, 0],
|
|
||||||
"corner-bl": [2, 3, 0],
|
|
||||||
"corner-br": [3, 3, 0],
|
|
||||||
|
|
||||||
"edge-tl": [0, 4, 0],
|
|
||||||
"edge-tr": [1, 4, 0],
|
|
||||||
"edge-bl": [2, 4, 0],
|
|
||||||
"edge-br": [3, 4, 0]
|
|
||||||
];
|
|
||||||
|
|
||||||
//raw string data
|
|
||||||
var rawmap: [[string]] = null;
|
|
||||||
|
|
||||||
//baked and usable blobs of data
|
|
||||||
var tilemap: [int] = null; // [x0, y0, x1, y1, ...]
|
|
||||||
var collisions: [bool] = null;
|
|
||||||
|
|
||||||
//metadata about the above blobs
|
|
||||||
var tilemapGridWidth: int = 0;
|
|
||||||
var tilemapGridHeight: int = 0;
|
|
||||||
|
|
||||||
//fast accessors
|
|
||||||
fn getTilemapData(node: opaque) {
|
|
||||||
return tilemap;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getCollisionData(node: opaque) {
|
|
||||||
return collisions;
|
|
||||||
}
|
|
||||||
|
|
||||||
//lifecycle functions
|
|
||||||
fn onLoad(node: opaque) {
|
|
||||||
node.loadNodeTexture("sprites:/tileset.png");
|
|
||||||
|
|
||||||
node.setNodeScaleX(CAMERA_SCALE_X);
|
|
||||||
node.setNodeScaleY(CAMERA_SCALE_Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn onDraw(node: opaque) {
|
|
||||||
assert tilemap, "tilemap is null";
|
|
||||||
|
|
||||||
var posX: int const = node.getNodeWorldPositionX();
|
|
||||||
var posY: int const = node.getNodeWorldPositionY();
|
|
||||||
|
|
||||||
//draw everything at twice the original size
|
|
||||||
var scaleX: float const = node.getNodeWorldScaleX();
|
|
||||||
var scaleY: float const = node.getNodeWorldScaleY();
|
|
||||||
|
|
||||||
//draw the tilemap
|
|
||||||
for (var j = 0; j < tilemapGridHeight; j++) {
|
|
||||||
for (var i = 0; i < tilemapGridWidth; i++) {
|
|
||||||
//set the rect of the node on the tilesheet - the "tilemap" var is a single blob of data
|
|
||||||
node.setNodeRect(
|
|
||||||
tilemap[j * tilemapGridWidth * 2 + i * 2] * TILE_PIXEL_WIDTH,
|
|
||||||
tilemap[j * tilemapGridWidth * 2 + i * 2 + 1] * TILE_PIXEL_HEIGHT,
|
|
||||||
TILE_PIXEL_WIDTH, TILE_PIXEL_HEIGHT
|
|
||||||
);
|
|
||||||
|
|
||||||
//draw to the screen
|
|
||||||
node.drawNode(
|
|
||||||
floor((i * TILE_PIXEL_WIDTH + posX) * scaleX) + globalCameraX,
|
|
||||||
floor((j * TILE_PIXEL_HEIGHT + posY) * scaleY) + globalCameraY,
|
|
||||||
floor(TILE_PIXEL_WIDTH * scaleX),
|
|
||||||
floor(TILE_PIXEL_HEIGHT * scaleY)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//utils functions for map generation
|
|
||||||
fn generateFromRng(node: opaque, rng: opaque, width: int, height: int) {
|
|
||||||
//use debug room for now
|
|
||||||
rawmap = generateRawTilemapDebugRoom(rng, width, height);
|
|
||||||
|
|
||||||
tilemap = bakeTilemap(rawmap, width, height);
|
|
||||||
collisions = bakeCollisionMap(rawmap, width, height);
|
|
||||||
|
|
||||||
tilemapGridWidth = width;
|
|
||||||
tilemapGridHeight = height;
|
|
||||||
|
|
||||||
//debugging
|
|
||||||
print tilemap;
|
|
||||||
print collisions;
|
|
||||||
}
|
|
||||||
|
|
||||||
//"raw" tilemaps are not usable, they are just a 2d array of strings
|
|
||||||
fn generateRawTilemapDebugRoom(rng: opaque, width: int, height: int): [[string]] const {
|
|
||||||
import random;
|
|
||||||
|
|
||||||
//generate a grid filled with only pillar tiles, as a starting point
|
|
||||||
var result: [[string]] = [];
|
|
||||||
var row: [string] = [];
|
|
||||||
for (var j: int = 0; j < height; j++) {
|
|
||||||
row.push("pillar");
|
|
||||||
}
|
|
||||||
for (var i: int = 0; i < width; i++) {
|
|
||||||
result.push(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
//generate the walkable tiles of the grid - floor tiles
|
|
||||||
for (var j: int = 1; j < height - 1; j++) {
|
|
||||||
for (var i: int = 1; i < width - 1; i++) {
|
|
||||||
//select a random floor tile (graphical effect only)
|
|
||||||
var x: int = rng.generateRandomNumber() % 4;
|
|
||||||
var t: string = "floor-" + string x;
|
|
||||||
|
|
||||||
result[i][j] = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//draw top and bottom walls
|
|
||||||
for (var i: int = 1; i < width - 1; i++) {
|
|
||||||
result[i][0] = "wall-t";
|
|
||||||
result[i][height - 1] = "wall-b";
|
|
||||||
}
|
|
||||||
|
|
||||||
//draw the left and right walls
|
|
||||||
for (var j: int = 1; j < height - 1; j++) {
|
|
||||||
result[0][j] = "wall-l";
|
|
||||||
result[width-1][j] = "wall-r";
|
|
||||||
}
|
|
||||||
|
|
||||||
//draw the corners
|
|
||||||
result[0][0] = "corner-tl";
|
|
||||||
result[width - 1][0] = "corner-tr";
|
|
||||||
result[0][height - 1] = "corner-bl";
|
|
||||||
result[width - 1][height - 1] = "corner-br";
|
|
||||||
|
|
||||||
//debugging
|
|
||||||
result[4][4] = "pillar";
|
|
||||||
result[width - 5][4] = "pillar";
|
|
||||||
result[4][height - 5] = "pillar";
|
|
||||||
result[width - 5][height - 5] = "pillar";
|
|
||||||
|
|
||||||
//return the raw result of strings
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//"baking" converts raw tilemaps into usable blobs of data
|
|
||||||
fn bakeTilemap(tilemap: [[string]] const, width: int, height: int): [int] const {
|
|
||||||
var result: [int] = [];
|
|
||||||
|
|
||||||
//extract the positions from the tileset
|
|
||||||
for (var j: int = 0; j < height; j++) {
|
|
||||||
for (var i: int = 0; i < width; i++) {
|
|
||||||
result.push(tileset[ tilemap[i][j] ][0]);
|
|
||||||
result.push(tileset[ tilemap[i][j] ][1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//this bakes the collision map as a separate object
|
|
||||||
fn bakeCollisionMap(tilemap: [[string]] const, width: int, height: int): [bool] const {
|
|
||||||
var result: [bool] = [];
|
|
||||||
|
|
||||||
//extract the walkable state
|
|
||||||
for (var j: int = 0; j < height; j++) {
|
|
||||||
for (var i: int = 0; i < width; i++) {
|
|
||||||
result.push(tileset[ tilemap[i][j] ][2] != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@@ -24,8 +24,8 @@ var tileset: [string : [int]] const = [
|
|||||||
|
|
||||||
"temple-edge-tl": [0, 4, 0],
|
"temple-edge-tl": [0, 4, 0],
|
||||||
"temple-edge-tr": [1, 4, 0],
|
"temple-edge-tr": [1, 4, 0],
|
||||||
"temple-edge-bl": [2, 4, 0],
|
"temple-edge-bl": [3, 4, 0], //would be great if these were the right way around...
|
||||||
"temple-edge-br": [3, 4, 0]
|
"temple-edge-br": [2, 4, 0]
|
||||||
];
|
];
|
||||||
|
|
||||||
var themes: [string] const = [
|
var themes: [string] const = [
|
||||||
@@ -104,7 +104,8 @@ fn generateTilemapData(rng: opaque) {
|
|||||||
//etch the corridors
|
//etch the corridors
|
||||||
etchCorridors(roomData, corridorData, rng);
|
etchCorridors(roomData, corridorData, rng);
|
||||||
|
|
||||||
//TODO: etch the walls with a filter, based on the room's themes
|
//etch the walls with marching squares, based on the room's themes
|
||||||
|
etchWalls(roomData);
|
||||||
|
|
||||||
//save the metadata for later retrieval
|
//save the metadata for later retrieval
|
||||||
metadata = roomData;
|
metadata = roomData;
|
||||||
@@ -153,52 +154,6 @@ fn etchRoom(rng: opaque, metadata: [string: any]) {
|
|||||||
tilemap[j * CELL_WIDTH * CELL_COUNT_X * 3 + i * 3 + 2] = tileset[theme + "-floor-" + string floorIndex][2];
|
tilemap[j * CELL_WIDTH * CELL_COUNT_X * 3 + i * 3 + 2] = tileset[theme + "-floor-" + string floorIndex][2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// //create the string constants here, so refstring can do it's job
|
|
||||||
// var T_WALL: [int] const = tileset[ theme + "-wall-t" ];
|
|
||||||
// var B_WALL: [int] const = tileset[ theme + "-wall-b" ];
|
|
||||||
// var L_WALL: [int] const = tileset[ theme + "-wall-l" ];
|
|
||||||
// var R_WALL: [int] const = tileset[ theme + "-wall-r" ];
|
|
||||||
|
|
||||||
// //etch the walls of each room
|
|
||||||
// for (var i: int = x; i < x + w; i++) {
|
|
||||||
// tilemap[y * CELL_WIDTH * CELL_COUNT_X * 3 + i * 3 + 0] = T_WALL[0];
|
|
||||||
// tilemap[y * CELL_WIDTH * CELL_COUNT_X * 3 + i * 3 + 1] = T_WALL[1];
|
|
||||||
// tilemap[y * CELL_WIDTH * CELL_COUNT_X * 3 + i * 3 + 2] = T_WALL[2];
|
|
||||||
|
|
||||||
// tilemap[(h + y - 1) * CELL_WIDTH * CELL_COUNT_X * 3 + i * 3 + 0] = B_WALL[0];
|
|
||||||
// tilemap[(h + y - 1) * CELL_WIDTH * CELL_COUNT_X * 3 + i * 3 + 1] = B_WALL[1];
|
|
||||||
// tilemap[(h + y - 1) * CELL_WIDTH * CELL_COUNT_X * 3 + i * 3 + 2] = B_WALL[2];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for (var j: int = y; j < y + h; j++) {
|
|
||||||
// tilemap[j * CELL_WIDTH * CELL_COUNT_X * 3 + x * 3 + 0] = L_WALL[0];
|
|
||||||
// tilemap[j * CELL_WIDTH * CELL_COUNT_X * 3 + x * 3 + 1] = L_WALL[1];
|
|
||||||
// tilemap[j * CELL_WIDTH * CELL_COUNT_X * 3 + x * 3 + 2] = L_WALL[2];
|
|
||||||
|
|
||||||
// tilemap[j * CELL_WIDTH * CELL_COUNT_X * 3 + (x + w - 1) * 3 + 0] = R_WALL[0];
|
|
||||||
// tilemap[j * CELL_WIDTH * CELL_COUNT_X * 3 + (x + w - 1) * 3 + 1] = R_WALL[1];
|
|
||||||
// tilemap[j * CELL_WIDTH * CELL_COUNT_X * 3 + (x + w - 1) * 3 + 2] = R_WALL[2];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //etch the corners
|
|
||||||
// tilemap[y * CELL_WIDTH * CELL_COUNT_X * 3 + x * 3 + 0] = tileset[ theme + "-corner-tl" ][0];
|
|
||||||
// tilemap[y * CELL_WIDTH * CELL_COUNT_X * 3 + x * 3 + 1] = tileset[ theme + "-corner-tl" ][1];
|
|
||||||
// tilemap[y * CELL_WIDTH * CELL_COUNT_X * 3 + x * 3 + 2] = tileset[ theme + "-corner-tl" ][2];
|
|
||||||
|
|
||||||
// tilemap[(h + y - 1) * CELL_WIDTH * CELL_COUNT_X * 3 + x * 3 + 0] = tileset[ theme + "-corner-bl" ][0];
|
|
||||||
// tilemap[(h + y - 1) * CELL_WIDTH * CELL_COUNT_X * 3 + x * 3 + 1] = tileset[ theme + "-corner-bl" ][1];
|
|
||||||
// tilemap[(h + y - 1) * CELL_WIDTH * CELL_COUNT_X * 3 + x * 3 + 2] = tileset[ theme + "-corner-bl" ][2];
|
|
||||||
|
|
||||||
|
|
||||||
// tilemap[y * CELL_WIDTH * CELL_COUNT_X * 3 + (x + w - 1) * 3 + 0] = tileset[ theme + "-corner-tr" ][0];
|
|
||||||
// tilemap[y * CELL_WIDTH * CELL_COUNT_X * 3 + (x + w - 1) * 3 + 1] = tileset[ theme + "-corner-tr" ][1];
|
|
||||||
// tilemap[y * CELL_WIDTH * CELL_COUNT_X * 3 + (x + w - 1) * 3 + 2] = tileset[ theme + "-corner-tr" ][2];
|
|
||||||
|
|
||||||
|
|
||||||
// tilemap[(h + y - 1) * CELL_WIDTH * CELL_COUNT_X * 3 + (x + w - 1) * 3 + 0] = tileset[ theme + "-corner-br" ][0];
|
|
||||||
// tilemap[(h + y - 1) * CELL_WIDTH * CELL_COUNT_X * 3 + (x + w - 1) * 3 + 1] = tileset[ theme + "-corner-br" ][1];
|
|
||||||
// tilemap[(h + y - 1) * CELL_WIDTH * CELL_COUNT_X * 3 + (x + w - 1) * 3 + 2] = tileset[ theme + "-corner-br" ][2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generateCorridorData(rng: opaque) {
|
fn generateCorridorData(rng: opaque) {
|
||||||
@@ -419,6 +374,189 @@ fn etchLine(x: int, y: int, xLength: int, yLength: int, theme: string, rng: opaq
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn etchWalls(roomData) {
|
||||||
|
//zero'd signals
|
||||||
|
var signals: [string] = [];
|
||||||
|
|
||||||
|
for (var j: int = 0; j < CELL_COUNT_Y * CELL_HEIGHT; j++) {
|
||||||
|
for (var i: int = 0; i < CELL_COUNT_X * CELL_WIDTH; i++) {
|
||||||
|
signals.push(""); //empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//determine the walls' layout from the tilemap
|
||||||
|
for (var i: int = 0; i < MAP_GRID_WIDTH; i++) {
|
||||||
|
for (var j: int = 0; j < MAP_GRID_HEIGHT; j++) {
|
||||||
|
signals[j * MAP_GRID_WIDTH + i] = parseTilemapAt(i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//etch the walls into the tilemap, based on the room theme
|
||||||
|
for (var i: int = 0; i < MAP_GRID_WIDTH; i++) {
|
||||||
|
for (var j: int = 0; j < MAP_GRID_HEIGHT; j++) {
|
||||||
|
if (signals[j * MAP_GRID_WIDTH + i] == "") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var theme = roomData[floor(i / CELL_WIDTH)][floor(j / CELL_HEIGHT)]["theme"];
|
||||||
|
tilemap[j * CELL_WIDTH * CELL_COUNT_X * 3 + i * 3 + 0] = tileset[theme + "-" + signals[j * MAP_GRID_WIDTH + i]][0];
|
||||||
|
tilemap[j * CELL_WIDTH * CELL_COUNT_X * 3 + i * 3 + 1] = tileset[theme + "-" + signals[j * MAP_GRID_WIDTH + i]][1];
|
||||||
|
tilemap[j * CELL_WIDTH * CELL_COUNT_X * 3 + i * 3 + 2] = tileset[theme + "-" + signals[j * MAP_GRID_WIDTH + i]][2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
//lets say snapshot looks like this
|
||||||
|
snapshot:
|
||||||
|
|
||||||
|
0, 0, 1
|
||||||
|
0, 0, 1
|
||||||
|
0, 0, 1
|
||||||
|
|
||||||
|
result should be "wall-l",
|
||||||
|
|
||||||
|
//lets say filter looks like this
|
||||||
|
filter:
|
||||||
|
|
||||||
|
1 1 1 1 1
|
||||||
|
1 0 0 0 1
|
||||||
|
1 0 0 0 1
|
||||||
|
1 0 0 0 1
|
||||||
|
1 1 1 1 1
|
||||||
|
|
||||||
|
find the position within the filter, that gives the result "wall-l"
|
||||||
|
|
||||||
|
//lets say result looks like this
|
||||||
|
|
||||||
|
"edge-br" "wall-b" "edge-bl"
|
||||||
|
"wall-r" "pillar" "wall-l"
|
||||||
|
"edge-tr" "wall-t" "edge-tl"
|
||||||
|
|
||||||
|
let's try this...
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 9x9
|
||||||
|
var marchingFilter: [int] const = [
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 1, 1, 1, 0, 0, 1,
|
||||||
|
1, 0, 0, 1, 1, 1, 0, 0, 1,
|
||||||
|
1, 0, 0, 1, 1, 1, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1
|
||||||
|
];
|
||||||
|
|
||||||
|
var marchingFilterResult: [string] const = [
|
||||||
|
"", "", "", "", "", "", "", "", "",
|
||||||
|
"", "edge-tr", "wall-b", "wall-b", "wall-b", "wall-b", "wall-b", "edge-tl", "",
|
||||||
|
"", "wall-r", "corner-tl", "wall-t", "wall-t", "wall-t", "corner-tr", "wall-l", "",
|
||||||
|
"", "wall-r", "wall-l", "", "", "", "wall-r", "wall-l", "",
|
||||||
|
"", "wall-r", "wall-l", "", "", "", "wall-r", "wall-l", "",
|
||||||
|
"", "wall-r", "wall-l", "", "", "", "wall-r", "wall-l", "",
|
||||||
|
"", "wall-r", "corner-bl", "wall-b", "wall-b", "wall-b", "corner-br", "wall-l", "",
|
||||||
|
"", "edge-br", "wall-t", "wall-t", "wall-t", "wall-t", "wall-t", "edge-bl", "",
|
||||||
|
"", "", "", "", "", "", "", "", ""
|
||||||
|
];
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//this is a nightmare
|
||||||
|
var marchingFilter: [int] const = [
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1,
|
||||||
|
1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||||
|
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
||||||
|
];
|
||||||
|
|
||||||
|
var marchingFilterResult: [string] const = [
|
||||||
|
"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,
|
||||||
|
"" ,"" ,"edge-tl" ,"wall-b" ,"wall-b" ,"wall-b" ,"wall-b" ,"wall-b" ,"wall-b" ,"edge-tr" ,"" ,"" ,
|
||||||
|
"" ,"edge-tl" ,"corner-br" ,"" ,"corner-tl" ,"wall-t" ,"wall-t" ,"corner-tr" ,"" ,"corner-bl" ,"edge-tr" ,"" ,
|
||||||
|
"" ,"wall-r" ,"" ,"" ,"wall-l" ,"" ,"" ,"wall-r" ,"" ,"" ,"wall-l" ,"" ,
|
||||||
|
"" ,"wall-r" ,"corner-tl" ,"wall-t" ,"edge-br" ,"" ,"" ,"edge-bl" ,"wall-t" ,"corner-tr" ,"wall-l" ,"" ,
|
||||||
|
"" ,"wall-r" ,"wall-l" ,"" ,"" ,"" ,"" ,"" ,"" ,"wall-r" ,"wall-l" ,"" ,
|
||||||
|
"" ,"wall-r" ,"wall-l" ,"" ,"" ,"" ,"" ,"" ,"" ,"wall-r" ,"wall-l" ,"" ,
|
||||||
|
"" ,"wall-r" ,"corner-bl" ,"wall-b" ,"edge-tr" ,"" ,"" ,"edge-tl" ,"wall-b" ,"corner-br" ,"wall-l" ,"" ,
|
||||||
|
"" ,"wall-r" ,"" ,"" ,"wall-l" ,"" ,"" ,"wall-r" ,"" ,"" ,"wall-l" ,"" ,
|
||||||
|
"" ,"edge-bl" ,"corner-tr" ,"" ,"corner-bl" ,"wall-b" ,"wall-b" ,"corner-br" ,"" ,"corner-tl" ,"edge-br" ,"" ,
|
||||||
|
"" ,"" ,"edge-bl" ,"wall-t" ,"wall-t" ,"wall-t" ,"wall-t" ,"wall-t" ,"wall-t" ,"edge-br" ,"" ,"" ,
|
||||||
|
"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,""
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
//if walkable is below, then return top, etc.
|
||||||
|
fn parseTilemapAt(x: int, y: int) {
|
||||||
|
//parse based on walkability, for now
|
||||||
|
if (tilemap[y * CELL_WIDTH * CELL_COUNT_X * 3 + x * 3 + 2] != 0) {
|
||||||
|
return ""; //empty
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate the snapshot of the current position
|
||||||
|
var snapshot = generateSnapshotAt(x, y);
|
||||||
|
|
||||||
|
//find the snapshot's position within the filter
|
||||||
|
for (var i: int = 0; i < 12 -2; i++) {
|
||||||
|
for (var j: int = 0; j < 12 -2; j++) {
|
||||||
|
if (
|
||||||
|
marchingFilter[(j + 0) * 12 + (i + 0)] == snapshot[0 * 3 + 0] &&
|
||||||
|
marchingFilter[(j + 0) * 12 + (i + 1)] == snapshot[0 * 3 + 1] &&
|
||||||
|
marchingFilter[(j + 0) * 12 + (i + 2)] == snapshot[0 * 3 + 2] &&
|
||||||
|
|
||||||
|
marchingFilter[(j + 1) * 12 + (i + 0)] == snapshot[1 * 3 + 0] &&
|
||||||
|
marchingFilter[(j + 1) * 12 + (i + 1)] == snapshot[1 * 3 + 1] &&
|
||||||
|
marchingFilter[(j + 1) * 12 + (i + 2)] == snapshot[1 * 3 + 2] &&
|
||||||
|
|
||||||
|
marchingFilter[(j + 2) * 12 + (i + 0)] == snapshot[2 * 3 + 0] &&
|
||||||
|
marchingFilter[(j + 2) * 12 + (i + 1)] == snapshot[2 * 3 + 1] &&
|
||||||
|
marchingFilter[(j + 2) * 12 + (i + 2)] == snapshot[2 * 3 + 2]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return marchingFilterResult[(j+1) * 12 + (i+1)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//anything else, just plop down a pillar
|
||||||
|
fn nonZero(key: int, value: int) {
|
||||||
|
return value != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshot.some(nonZero)) {
|
||||||
|
return "pillar";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generateSnapshotAt(x: int, y: int) {
|
||||||
|
var result: [int] = [];
|
||||||
|
|
||||||
|
for (var j: int = -1; j < 2; j++) {
|
||||||
|
for (var i: int = -1; i < 2; i++) {
|
||||||
|
if (x + i < 0 || y + j < 0 || x + i >= MAP_GRID_WIDTH || y + j >= MAP_GRID_HEIGHT) {
|
||||||
|
result.push(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.push(tilemap[(y+j) * CELL_WIDTH * CELL_COUNT_X * 3 + (x+i) * 3 + 2] != 0 ? 1 : 0); //walkable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
//polyfill
|
//polyfill
|
||||||
fn sign(x) {
|
fn sign(x) {
|
||||||
if (x > 0) return 1;
|
if (x > 0) return 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user