I recently wrote a guide teaching how to use Tiled with Kaboom in a more performant way. Read it here : jslegenddev.substack.com/p/how-to-use-tiled-with-kaboomjs Kaboom.js has a discord server where people using Kaboom ask questions, share their projects, share plugins they made and even contribute code to the Kaboom github repo. I really recommend joining if you can. Here's the invite link : discord.com/invite/aQ6RuQm3TF
It was incredible! I learned a lot from your classes. A fantastic idea would be to create a class on making a game set underwater, similar to the stages in the Mario game. I believe it could benefit many people who share the same interest. Thank you very much for sharing this amazing content!
at 5:43:42, I decided to use a simpler approach and just rewrite the if statements for every key and use the "areAnyOfTheseKeysDown" function to exclude every other key and it works the same.
Regarding the movement issue at 5:18:03 I just replaced the if statements like this: ((key === "left" || key === "a" && !areAnyOfTheseKeysDown(k, ["left"])) && !areAnyOfTheseKeysDown(k, ["up", "down", "w", "s"])) worked perfectly BTW: awesome tutorial! thanks
At 3:01:53, how do you go behind the trees? It doesn't seem to work for me. The player keeps on going above the trees. In Tiled, the layers are in correct order, but it doesn't work.
Compare your code with this specific for loop. Do you have the same thing? github.com/JSLegendDev/Zelda-like-Kaboomjs/blob/2b27121996ca913852665fbed772bd5aa0407c6e/src/scenes/world.js#L30
when i got to this point 1:43:48 my screen was still just blue and i checked everything too, could it be because my map is big or that has nothing to do with it?
Hard to tell without seeing your code. It could be possible that the issue is that the positioning is wrong for your map (I'm assuming that you decided to use your own map). You could try downloading the source code and comparing with yours. The link is in the description.
@@JSLegendDev in chrome it says the error is about drawtiles not being defined but i followed your steps so i hope i fix whatever's going on with the drawtiles
At 2:06:45, when u run it, it works but when I run it it says "error: only support polygons and rect shapes for now" how do i fix it? pls help me i cant figure it out
In the code for creating the player, did you set the shape of the body correctly like this : k.area({ shape: new k.Rect(k.vec2(3, 4), 10, 12) })? One thing you could do is compare your code with what I provided on github. github.com/JSLegendDev/Zelda-like-Kaboomjs/blob/master/src/entities/player.js By comparing your code with mine, it will be easier to detect the error.
@@RealDroid7 Can you look at the console in your browser's dev tools? Any error messages? Also you could try downloading the source code and running it on your machine along your own project. That way you can more easily compare.
on your substack, I found a way to make diagonal movement not buggy, and it works! but the problem is that whenever I use the diagonal movement, the animation doesn't play. (I'm still using the four cardinal animations shown in the video)
You can add a second tileset in Tiled for a same level and use it. You need to be careful with tile indexes. The index of the first tile of the second tileset will be the number of tiles in the first tileset + 0. (Indexes starts at 0 if you remember) Example : tileset #1 has 40 tiles. So the first tile of tileset #2 is going to have index = 40 (Since it's nb of tiles in tileset #1 + 0) The second tile of tileset #2 is going to have index = 41 (Since it's nb of tiles in tileset #1 + 1) etc...
@@RealDroid7 Look at the resulting .json, your tiles will have numbers that are bigger than the last tile number of the first tileset. It's a bit hard to explain through text. I think you'll understand better by just trying it out.
Hello friend, I have a question, I would like to use as a player a sprite of 2 16x16 blocks, in the first one is the head and in the second the body to give you an idea. How could I do it with Kaboom?
Hi! You can achieve this by creating a parent game object and adding two game objects as children. Example code : const player = k.add([]) //parent player.add([ k.sprite("head"), k.pos(0, 10) // specify the position you want ]) // first child will display the head part player.add([ k.sprite("body"), k.pos(0, -10) ]) // second child will display the body part Is there a reason you want to display the head and the body separately instead of displaying the whole character at once?
If the game camera is centered on my player, is there a way for the top edge of my camera to clamp to the top edge of my map? I don't want the camera to go beyond the top edge of my game map when my player moves up k.onUpdate(() => { if (entities?.player?.pos.dist(k.camPos())) { const playerPos = entities?.player?.worldPos(); k.tween( k.camPos(), playerPos, // needs to be clamped to map somehow 0.1, (newPos) => { k.camPos(newPos); }, k.easings.linear ); } });
Some time ago, I came across this tutorial that covered how to do this in Love2D with the lua programming language. I think it's worth looking into as the logic is transferable since it's just math. You should be able to take the concepts in that video and apply it Kaboom.js Here's the link with the specific time stamp : ruclips.net/video/F3zKl70RJlk/видео.htmlfeature=shared&t=330 Hope this helps!
Thanks for the link. Seems like there is no easy way to clamp the map at a specific point in kaboom, for instance before a signpost at the upper map limit, consistently for different viewport heights. Phaser has a setBounds method for this but seems like I'm gonna have to figure out something else.. @@JSLegendDev
I figured it out, the math will be slightly different for everyone depending on camScale, tileset and how they drew their map on tiled, but this code below clamps the map consistently to the map's y upper and lower limit regardless of viewport height const isMobile = window.innerWidth < 768; k.camScale(k.vec2(isMobile ? 1 : 1.5)); k.camPos(entities?.player?.worldPos()) const tileMapHeight = 1600; // 32 x 32 tiles and 50 rows and columns const tileHeight = isMobile ? 32 : 48; // 32 is when camScale is 1, 48 is when camScale is 1.5 const halfOfGameHeight = k.height() / 2; const tilesFromYBoundary = halfOfGameHeight / tileHeight; const playerPosFromTopBoundary = 32 * tilesFromYBoundary + 64; const playerPosFromBottomBoundary = tileMapHeight - (32 * tilesFromTopBoundary - 32); k.onUpdate(() => { if (entities?.player?.pos.dist(k.camPos())) { const playerPos = entities?.player?.worldPos(); k.tween( k.camPos(), k.vec2( playerPos.x, k.clamp(playerPos.y, playerPosFromTopBoundary, playerPosFromBottomBoundary ), 0.1, (newPos) => { k.camPos(newPos); }, k.easings.linear ); } }); For const playerPosFromTopBoundary = 32 * tilesFromYBoundary + 64; 32 is from my 32 x 32 tileset and + 64 is because the kaboom debugger says that the first visual y row (which is my second row from the top) in my map has a pos: (0, 64). My first actual y row is filled with Boundaries objects.
I recently wrote a guide teaching how to use Tiled with Kaboom in a more performant way. Read it here : jslegenddev.substack.com/p/how-to-use-tiled-with-kaboomjs
Kaboom.js has a discord server where people using Kaboom ask questions, share their projects, share plugins they made and even contribute code to the Kaboom github repo.
I really recommend joining if you can. Here's the invite link : discord.com/invite/aQ6RuQm3TF
I really appreciate you for going into details things like file paths and stuff the beginners will really like it too.☺
Bro, you are helping me so much with my little game, i have watched a lot of your vids. Thank you!
Same with me. Thanks, JSLegendDev!
oohh yess been waiting for this!
you're the best Sir!
i just finished making the game! thank you so much for this tutorial I'm looking forward to your videos
It was incredible! I learned a lot from your classes. A fantastic idea would be to create a class on making a game set underwater, similar to the stages in the Mario game. I believe it could benefit many people who share the same interest.
Thank you very much for sharing this amazing content!
Legend fr, you need more recognition
such a beautiful tutorial , thank you❤❤
No problem! Glad you liked it :)
at 5:43:42, I decided to use a simpler approach and just rewrite the if statements for every key and use the "areAnyOfTheseKeysDown" function to exclude every other key and it works the same.
Holy crap that was a ride! Great tutorial!:)
Thanks for watching :)
Regarding the movement issue at 5:18:03 I just replaced the if statements like this:
((key === "left" || key === "a" && !areAnyOfTheseKeysDown(k, ["left"])) && !areAnyOfTheseKeysDown(k, ["up", "down", "w", "s"]))
worked perfectly
BTW: awesome tutorial! thanks
At 3:01:53, how do you go behind the trees? It doesn't seem to work for me. The player keeps on going above the trees. In Tiled, the layers are in correct order, but it doesn't work.
Compare your code with this specific for loop. Do you have the same thing? github.com/JSLegendDev/Zelda-like-Kaboomjs/blob/2b27121996ca913852665fbed772bd5aa0407c6e/src/scenes/world.js#L30
@@JSLegendDev it works now. Thanks! I just had to do map.add instead of k.add.
when i got to this point 1:43:48 my screen was still just blue and i checked everything too, could it be because my map is big or that has nothing to do with it?
Hard to tell without seeing your code. It could be possible that the issue is that the positioning is wrong for your map (I'm assuming that you decided to use your own map). You could try downloading the source code and comparing with yours. The link is in the description.
@@JSLegendDev in chrome it says the error is about drawtiles not being defined but i followed your steps so i hope i fix whatever's going on with the drawtiles
At 2:06:45, when u run it, it works but when I run it it says "error: only support polygons and rect shapes for now" how do i fix it? pls help me i cant figure it out
In the code for creating the player, did you set the shape of the body correctly like this : k.area({ shape: new k.Rect(k.vec2(3, 4), 10, 12) })?
One thing you could do is compare your code with what I provided on github. github.com/JSLegendDev/Zelda-like-Kaboomjs/blob/master/src/entities/player.js
By comparing your code with mine, it will be easier to detect the error.
@@JSLegendDev now it just gives me a white screen...
@@RealDroid7 Can you look at the console in your browser's dev tools? Any error messages?
Also you could try downloading the source code and running it on your machine along your own project. That way you can more easily compare.
@@JSLegendDev nvm i just needed to delete something in the kaboom.mjs file.
now it works. Thanks!
on your substack, I found a way to make diagonal movement not buggy, and it works! but the problem is that whenever I use the diagonal movement, the animation doesn't play. (I'm still using the four cardinal animations shown in the video)
Can you show your code?
@@JSLegendDev export function setPlayerMovment(k, player) {
player.onUpdate(() => {
const directionVector = k.vec2(0, 0)
if (k.isKeyDown("left")) {
player.flipX = true;
player.direction = "left"
directionVector.x = -1
playAnimIfNotPlaying(player, "player-side")
}
if (k.isKeyDown("right")) {
player.flipX = false;
player.direction = "right"
directionVector.x = 1
playAnimIfNotPlaying(player, "player-side")
}
if (k.isKeyDown("up")) {
directionVector.y = -1
player.direction = "up"
playAnimIfNotPlaying(player, "player-up")
}
if (k.isKeyDown("down")) {
directionVector.y = 1
player.direction = "down"
playAnimIfNotPlaying(player, "player-down")
}
const unitVector = directionVector.unit(); // make sure that the vector has a magnitude of 1
player.move(unitVector.scale(player.speed));
})
k.onKeyRelease(() => {
player.stop();
});
}
the above message is my movement code.
@@RealDroid7 I can't see your code.
@@JSLegendDev export function setPlayerMovment(k, player) {
player.onUpdate(() => {
const directionVector = k.vec2(0, 0)
if (k.isKeyDown("left")) {
player.flipX = true;
player.direction = "left"
directionVector.x = -1
playAnimIfNotPlaying(player, "player-side")
}
if (k.isKeyDown("right")) {
player.flipX = false;
player.direction = "right"
directionVector.x = 1
playAnimIfNotPlaying(player, "player-side")
}
if (k.isKeyDown("up")) {
directionVector.y = -1
player.direction = "up"
playAnimIfNotPlaying(player, "player-up")
}
if (k.isKeyDown("down")) {
directionVector.y = 1
player.direction = "down"
playAnimIfNotPlaying(player, "player-down")
}
const unitVector = directionVector.unit(); // make sure that the vector has a magnitude of 1
player.move(unitVector.scale(player.speed));
})
k.onKeyRelease(() => {
player.stop();
});
}
13:00
How would I use multiple tilesets? like a different tileset for each scene?
You can add a second tileset in Tiled for a same level and use it. You need to be careful with tile indexes. The index of the first tile of the second tileset will be the number of tiles in the first tileset + 0. (Indexes starts at 0 if you remember)
Example :
tileset #1 has 40 tiles.
So the first tile of tileset #2 is going to have index = 40 (Since it's nb of tiles in tileset #1 + 0)
The second tile of tileset #2 is going to have index = 41 (Since it's nb of tiles in tileset #1 + 1)
etc...
@@JSLegendDev and how would I source it in the code to make sure it's the correct one?
@@RealDroid7 Look at the resulting .json, your tiles will have numbers that are bigger than the last tile number of the first tileset.
It's a bit hard to explain through text. I think you'll understand better by just trying it out.
@@JSLegendDev ok
Thank you for posting such a good video.
I'm going to make a city map by referring to the video. Can you tell me the site where I can buy an asset?
You can go on itch.io here : itch.io/game-assets/tag-city-builder
Hello friend, I have a question, I would like to use as a player a sprite of 2 16x16 blocks, in the first one is the head and in the second the body to give you an idea. How could I do it with Kaboom?
Hi!
You can achieve this by creating a parent game object and adding two game objects as children.
Example code :
const player = k.add([]) //parent
player.add([
k.sprite("head"),
k.pos(0, 10) // specify the position you want
]) // first child will display the head part
player.add([
k.sprite("body"),
k.pos(0, -10)
]) // second child will display the body part
Is there a reason you want to display the head and the body separately instead of displaying the whole character at once?
@@JSLegendDev Thanks for responding, fortunately I found another way to solve my problem, great video friend
@@jhonnysuarez4215 No problem! Glad you found a solution.
19:10
best video
good video
can you make a typescript tutorial please ..?
If the game camera is centered on my player, is there a way for the top edge of my camera to clamp to the top edge of my map? I don't want the camera to go beyond the top edge of my game map when my player moves up
k.onUpdate(() => {
if (entities?.player?.pos.dist(k.camPos())) {
const playerPos = entities?.player?.worldPos();
k.tween(
k.camPos(),
playerPos, // needs to be clamped to map somehow
0.1,
(newPos) => {
k.camPos(newPos);
},
k.easings.linear
);
}
});
Some time ago, I came across this tutorial that covered how to do this in Love2D with the lua programming language.
I think it's worth looking into as the logic is transferable since it's just math. You should be able to take the concepts in that video and apply it Kaboom.js
Here's the link with the specific time stamp : ruclips.net/video/F3zKl70RJlk/видео.htmlfeature=shared&t=330
Hope this helps!
Thanks for the link. Seems like there is no easy way to clamp the map at a specific point in kaboom, for instance before a signpost at the upper map limit, consistently for different viewport heights. Phaser has a setBounds method for this but seems like I'm gonna have to figure out something else.. @@JSLegendDev
I figured it out, the math will be slightly different for everyone depending on camScale, tileset and how they drew their map on tiled, but this code below clamps the map consistently to the map's y upper and lower limit regardless of viewport height
const isMobile = window.innerWidth < 768;
k.camScale(k.vec2(isMobile ? 1 : 1.5));
k.camPos(entities?.player?.worldPos())
const tileMapHeight = 1600; // 32 x 32 tiles and 50 rows and columns
const tileHeight = isMobile ? 32 : 48; // 32 is when camScale is 1, 48 is when camScale is 1.5
const halfOfGameHeight = k.height() / 2;
const tilesFromYBoundary = halfOfGameHeight / tileHeight;
const playerPosFromTopBoundary = 32 * tilesFromYBoundary + 64;
const playerPosFromBottomBoundary =
tileMapHeight - (32 * tilesFromTopBoundary - 32);
k.onUpdate(() => {
if (entities?.player?.pos.dist(k.camPos())) {
const playerPos = entities?.player?.worldPos();
k.tween(
k.camPos(),
k.vec2(
playerPos.x,
k.clamp(playerPos.y, playerPosFromTopBoundary, playerPosFromBottomBoundary
),
0.1,
(newPos) => {
k.camPos(newPos);
},
k.easings.linear
);
}
});
For const playerPosFromTopBoundary = 32 * tilesFromYBoundary + 64;
32 is from my 32 x 32 tileset and + 64 is because the kaboom debugger says that the first visual y row (which is my second row from the top) in my map has a pos: (0, 64). My first actual y row is filled with Boundaries objects.
@@hideinbush0 Glad you were able to solve the issue! Thanks for sharing your solution as well.
No problem thanks for the tutorial, I would not have gotten this far without it.@@JSLegendDev