When making a level in kaboomJS with a large tile map collisions, things start to get slow... So I was wondering if there was an easy way to merge multiple tiles like maybe a whole row of blocks could be treated as one large block?
-
Alternatively, only render the tiles that are currently visible. – Ouroborus Nov 14 '21 at 01:48
-
Is there an easy way to do that? ( or a complex way) – Zachiah Nov 14 '21 at 02:06
-
2There's two things here. One is rendering, the other is physics. The rendering one is pretty easy. Check if the tile is within the view area and only draw it if it is. This is mainly checking to see if the tile is within the view area. The physics one is a little harder. You need a fast way to tell if things are near to each other, not necessarily colliding, but near enough that further calculations are needed. A common solution for both of these are quad trees. That's not the whole solution as you'll need to figure out the additional calculations that will be unique to your situation. – Ouroborus Nov 14 '21 at 02:19
1 Answers
1. Tiles don't have to fit in the grid
If you want to reduce the number of Game Objects in the Scene at a time you can have a single symbol in your level definition represent a Game Object that spans multiple grid tiles. So if you want a lot of platforms that are 3 grid squares wide, you don't need 3 objects per platform, you can just use a single character to represent a 3x1 rect:
import kaboom from "kaboom"
// initialize context
kaboom()
// load assets
loadSprite("bean", "sprites/bean.png")
addLevel(
// Note: the hyphens here hare just place holders to remind us that the
// game objects created by ➁ and ➂ are actually taking up 2 and 3 grid
// squares respectively.
[
" ⚥ ",
" ",
" ➂-- ",
" ",
" ➁- ",
" ",
" ",
"################################",
],
{
width: 32,
height: 32,
"⚥": () => [
sprite("bean"),
area(),
body(),
"player"
],
"#": () => [
rect(32, 32),
outline(2),
area(),
solid(),
],
"➁": () => [
rect(32 * 2, 32),
outline(2),
area(),
solid(),
],
"➂": () => [
rect(32 * 3, 32),
outline(2),
area(),
solid(),
],
}
);
const player = get("player")[0];
player.onUpdate(() => {
const left = isKeyDown('left') || isKeyDown('a');
const right = isKeyDown('right') || isKeyDown('d');
if (left && !right) {
player.move(-500, 0);
} else if (right && !left) {
player.move(500, 0);
}
camPos(player.pos);
});
onKeyPress("space", () => {
if (player.isGrounded()) {
player.jump();
}
});
Obviously if you had many different shapes and sizes this would be quite onerous.
2. Advanced: Quad Trees and Loading/Unloading Regions
I actually ran into this problem myself on a recent Kaboom project and decided to completely overhaul the built in addLevel()
with my own implementation that loaded from a bitmap instead of a bunch of strings, and then organized the level data into a quadtree so that I could quickly find chunks that overlapped the visible area, and load and unload game objects based on their visibility. The technique and code are a bit to complex it include here, so I'll just link to the Repl and the relevant source code: level-loader.ts and lib-quad-tree.ts and the usage in level-one.js .

- 18,988
- 3
- 28
- 41