Trying to get vision cone working, it's not going well
This commit is contained in:
@@ -15,28 +15,32 @@ var mapGridHeight: int = null;
|
||||
|
||||
//entities
|
||||
var player: opaque = null;
|
||||
var renderer: opaque = null;
|
||||
|
||||
//lifetime functions
|
||||
fn onInit(node: opaque) {
|
||||
fn onLoad(node: opaque) {
|
||||
//init the rng with a seed (random)
|
||||
if (rng != null) {
|
||||
rng.freeRandomGenerator();
|
||||
}
|
||||
rng = createRandomGenerator(clock().hash());
|
||||
|
||||
|
||||
//generate the level, filling out the entity data
|
||||
node.generateLevel(rng);
|
||||
|
||||
//generate the child node to render the map
|
||||
var renderer: opaque = node.loadChildNode("scripts:/tilemap/renderer.toy");
|
||||
renderer.callNodeFn("setTilemap", tilemap);
|
||||
renderer = node.loadChildNode("scripts:/tilemap/renderer.toy");
|
||||
|
||||
//load the music
|
||||
loadMusic("music:/Music_Skylands_placeholder.ogg");
|
||||
playMusic();
|
||||
}
|
||||
|
||||
fn onInit(node: opaque) {
|
||||
//generate the level, filling out the entity data
|
||||
node.generateLevel(rng);
|
||||
|
||||
//update the visible area from the player's perspective
|
||||
updateVisible();
|
||||
}
|
||||
|
||||
fn onStep(node: opaque) {
|
||||
for (var i: int = 0; i < node.getChildNodeCount(); i++) {
|
||||
var child = node.getChildNode(i);
|
||||
@@ -162,6 +166,14 @@ fn runAI(node: opaque) {
|
||||
}
|
||||
}
|
||||
|
||||
//update the visible portions of the map
|
||||
fn updateVisible() {
|
||||
var playerX: int = player.callNodeFn("getGridPositionX");
|
||||
var playerY: int = player.callNodeFn("getGridPositionY");
|
||||
|
||||
renderer.callNodeFn("updateVisble", playerX, playerY, tilemap);
|
||||
}
|
||||
|
||||
|
||||
//for collisions
|
||||
fn getWalkableAt(node: opaque, x: int, y: int) {
|
||||
@@ -205,3 +217,4 @@ fn depthComparator(lhs: opaque, rhs: opaque) {
|
||||
|
||||
return lhsPositionY < rhsPositionY;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import standard;
|
||||
import engine;
|
||||
import node;
|
||||
import math;
|
||||
|
||||
|
||||
//constants for generating maps
|
||||
@@ -23,6 +24,9 @@ var MAP_GRID_WIDTH: int const = CELL_WIDTH * CELL_COUNT_X;
|
||||
var MAP_GRID_HEIGHT: int const = CELL_HEIGHT * CELL_COUNT_Y;
|
||||
|
||||
|
||||
var tilemapCache = [];
|
||||
|
||||
|
||||
//lifecycle functions
|
||||
fn onLoad(node: opaque) {
|
||||
//load the atlas into this node
|
||||
@@ -31,47 +35,171 @@ fn onLoad(node: opaque) {
|
||||
//create a child as a render target
|
||||
var child: opaque = node.loadChildNode("scripts:/tilemap/renderer-child.toy");
|
||||
child.createNodeTexture(MAP_GRID_WIDTH * TILE_PIXEL_WIDTH, MAP_GRID_HEIGHT * TILE_PIXEL_HEIGHT);
|
||||
|
||||
//generate a grid filled with only empty tiles, as a starting point
|
||||
for (var j: int = 0; j < MAP_GRID_HEIGHT; j++) {
|
||||
for (var i: int = 0; i < MAP_GRID_WIDTH; i++) {
|
||||
tilemapCache.push(-1); //x
|
||||
tilemapCache.push(-1); //y
|
||||
// tilemapCache.push(0); //collision
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: lazily render
|
||||
fn setTilemap(node: opaque, tilemap: [int]) {
|
||||
assert tilemap, "provided tilemap is null (in setTilemap)";
|
||||
|
||||
print clock() + " - begin rendering map";
|
||||
|
||||
//lazily render
|
||||
fn updateVisble(node: opaque, x: int, y: int, tilemap) {
|
||||
print clock() + " - start updateVisible()";
|
||||
var child: opaque = node.getChildNode(0);
|
||||
setRenderTarget(child);
|
||||
|
||||
//draw the tilemap to the child
|
||||
for (var j = 0; j < MAP_GRID_HEIGHT; j++) {
|
||||
for (var i = 0; i < MAP_GRID_WIDTH; i++) {
|
||||
//don't recalculate this every time
|
||||
var ITERATION: int const = j * MAP_GRID_WIDTH * 3 + i * 3;
|
||||
|
||||
//don't render empty tiles
|
||||
if (tilemap[ITERATION] < 0 || tilemap[ITERATION + 1] < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//set the rect of the node on the tilesheet - the "tilemap" var is a single blob of data
|
||||
node.setNodeRect(
|
||||
tilemap[ITERATION] * TILE_PIXEL_WIDTH,
|
||||
tilemap[ITERATION + 1] * TILE_PIXEL_HEIGHT,
|
||||
TILE_PIXEL_WIDTH, TILE_PIXEL_HEIGHT
|
||||
);
|
||||
|
||||
//draw to the screen
|
||||
node.drawNode(
|
||||
(i * TILE_PIXEL_WIDTH),
|
||||
(j * TILE_PIXEL_HEIGHT),
|
||||
TILE_PIXEL_WIDTH,
|
||||
TILE_PIXEL_HEIGHT
|
||||
);
|
||||
}
|
||||
}
|
||||
//divide the regions into octants & determine what is visible
|
||||
node.shadowCastOctant(x, y, 1, 1, 10, tilemap);
|
||||
node.shadowCastOctant(x, y, -1, 1, 10, tilemap);
|
||||
node.shadowCastOctant(x, y, 1, -1, 10, tilemap);
|
||||
node.shadowCastOctant(x, y, -1, -1, 10, tilemap);
|
||||
|
||||
//reset the render target to the screen
|
||||
setRenderTarget(null);
|
||||
|
||||
print clock() + " - end rendering map";
|
||||
print clock() + " - end updateVisible()";
|
||||
}
|
||||
|
||||
fn shadowCastOctant(node: opaque, x: int, y: int, dirX: int, dirY: int, depth: int, tilemap) {
|
||||
var shadows = [];
|
||||
|
||||
//for each tile, cast its shadow, and see if its already obscured
|
||||
for (var j: int = 0; abs(j) < depth; j += dirY) {
|
||||
for (var i: int = 0; abs(i) < depth; i += dirX) {
|
||||
//make sure this tile can actually cast a shadow
|
||||
var CACHE_ITERATION: int const = (y + j) * MAP_GRID_WIDTH * 2 + (x + i) * 2;
|
||||
var ITERATION: int const = (y + j) * MAP_GRID_WIDTH * 3 + (x + i) * 3;
|
||||
|
||||
//don't render empty tiles
|
||||
if (ITERATION < 0 || ITERATION >= MAP_GRID_WIDTH * MAP_GRID_HEIGHT * 3 || tilemap[ITERATION] < 0 || tilemap[ITERATION + 1] < 0) {
|
||||
continue; //break?
|
||||
}
|
||||
|
||||
//don't re-render already drawn tiles
|
||||
if (tilemapCache[CACHE_ITERATION] == tilemap[ITERATION] && tilemapCache[CACHE_ITERATION + 1] == tilemap[ITERATION + 1]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//cast the shadow
|
||||
var shadow = shadowCastTile(i + x, j + y, dirX, dirY, depth);
|
||||
|
||||
//merge shadows if needed
|
||||
var index: int = 0;
|
||||
|
||||
//find the insertion point
|
||||
for (; index < shadows.length(); index++) {
|
||||
if (shadows[index][0] >= shadow[0]) break;
|
||||
}
|
||||
|
||||
print shadows.toString() + " " + string index;
|
||||
|
||||
//check to see if the tile should be rendered (prev iterations would have merged shadows)
|
||||
if (shadows.length() == 0 || (shadows.length() > index && (index == 0 || shadows[index-1][1] <= shadow[1])) || (shadows.length() > index && (shadows.length() == index + 1 || shadows[index][0] >= shadow[0]) )) {
|
||||
print "first bracket";
|
||||
tilemapCache[CACHE_ITERATION] = tilemap[ITERATION];
|
||||
tilemapCache[CACHE_ITERATION + 1] = tilemap[ITERATION + 1];
|
||||
|
||||
//set the rect of the node on the tilesheet - the "tilemap" var is a single blob of data
|
||||
node.setNodeRect(
|
||||
tilemap[ITERATION] * TILE_PIXEL_WIDTH,
|
||||
tilemap[ITERATION + 1] * TILE_PIXEL_HEIGHT,
|
||||
TILE_PIXEL_WIDTH, TILE_PIXEL_HEIGHT
|
||||
);
|
||||
|
||||
print string((x + i) * TILE_PIXEL_WIDTH) + ", " + string((y + j) * TILE_PIXEL_HEIGHT);
|
||||
|
||||
//draw to the screen
|
||||
node.drawNode(
|
||||
((x + i) * TILE_PIXEL_WIDTH),
|
||||
((y + j) * TILE_PIXEL_HEIGHT),
|
||||
TILE_PIXEL_WIDTH,
|
||||
TILE_PIXEL_HEIGHT
|
||||
);
|
||||
}
|
||||
|
||||
var overlapping = false;
|
||||
|
||||
//see if the new shadow overlaps the previous
|
||||
if (index > 0 && shadows.length() > index && shadows[index -1][1] > shadow[0]) {
|
||||
print "second bracket";
|
||||
overlapping = true;
|
||||
shadows[index-1][1] = shadow[1]; //extend the prev shadow
|
||||
|
||||
//see if the newly extended prev overlaps the shadow at "index"
|
||||
if (shadows[index-1][1] >= shadows[index][0]) {
|
||||
//merge the two
|
||||
shadows[index-1][1] = shadows[index][1];
|
||||
shadows = shadows.remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
//see if the new shadow overlaps the one at "index"
|
||||
else if (shadows.length() > index && shadows[index][1] <= shadow[0]) {
|
||||
print "third bracket";
|
||||
overlapping = true;
|
||||
//extend the next shadow
|
||||
shadows[index][1] = shadow[0];
|
||||
}
|
||||
|
||||
if (!overlapping) {
|
||||
print "fourth bracket";
|
||||
//insert at this position
|
||||
shadows = shadows.insert(index, shadow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn shadowCastTile(x: int, y: int, dirX: int, dirY: int, depth: int) {
|
||||
//top-left corner & bottom-right corner forms a triangle with the player
|
||||
|
||||
//top-left = x & y
|
||||
//bottom-right = x + sign(dirX) & y + sign(dirY)
|
||||
|
||||
var start = abs(shadowCastPoint(x, y, depth));
|
||||
var end = abs(shadowCastPoint(x + sign(dirX), y + sign(dirY), depth));
|
||||
|
||||
return [start, end];
|
||||
}
|
||||
|
||||
fn shadowCastPoint(x: float, y: float, depth: int) {
|
||||
// if (y == 0) {
|
||||
// return sin(tan(INFINITY));
|
||||
// }
|
||||
return sin(tan(x/y)) * depth;
|
||||
}
|
||||
|
||||
//polyfill the insert function
|
||||
fn insert(self, k, v) {
|
||||
//eew
|
||||
var tmp1 = v;
|
||||
var tmp2;
|
||||
for (var i = k; i < self.length(); i++) {
|
||||
tmp2 = self[i];
|
||||
self[i] = tmp1;
|
||||
tmp1 = tmp2;
|
||||
}
|
||||
|
||||
self.push(tmp1);
|
||||
return self;
|
||||
}
|
||||
|
||||
//polyfill the remove function
|
||||
fn remove(self, k) {
|
||||
//double eew
|
||||
var result = [];
|
||||
|
||||
for (var i = 0; i <= k - 1; i++) {
|
||||
result.push( self[i] );
|
||||
}
|
||||
|
||||
for (var i = k + 1; i < self.length(); i++) {
|
||||
result.push( self[i] );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user