Thanks Caleb! I’ll try those.
Some of what’s happening sounds like you may have your player outside your map. Did you call map.layer[xyz]:insert(player)? The player has to be inserted into a layer for everything to work correctly.
And as for the objects not being drawn correctly, can you give me a little more information? You’re just creating the objects in a Tiled object layer, then loading them with dusk.buildMap(), and they appear off-center like that? Do they have any other properties other than physics:enabled?
-
Different tile sizes are not currently supported, but you can still make a background easily by just using smaller tiles. Alternatively, the most recent version of Dusk on the Dev branch also supports object culling, so you can use objects and draw/erase as needed.
-
Not currently. Dusk’s #1 weakness (and #1 requested feature) is lack of documentation and examples.
-
Dusk comes with built-in parallax scrolling. It’s in the docs. (Yay! I’ve always wanted to say that!)
-
Dusk comes with a camera system as well. It doesn’t have full documentation available, but it is touched upon in the Careening into Dusk guide.
- Caleb
I’m having the same problem with object layer. Object are not at the right position compared to my tile layer.
Object are offset buy about 16 - 24px depending on the scaling…
@Caleb P
Found something in the file /Dusk/dusk_core/layer/ objectlayer.lua
Around line 166, your setting the x and y position of the object based on the tileset size… I think it’s wrong since the object layer can be used for image that are not the same size as the tileset… At least, that’s what I’m doing
So instead of this line:
obj.x, obj.y = o.x + (mapData.stats.tileWidth \* 0.5), o.y - (mapData.stats.tileHeight \* 0.5)
I’ve changed the line to this:
obj.x, obj.y = o.x + (obj.width \* 0.5), o.y - (obj.height \* 0.5)
Correct me if I’m wrong.
P.
Ok. Didn’t know Tiled supports other-sized image objects. I need to check for other features I don’t know about
Right now I’m not able to “officially” fix this, but I’ll do it when I can.
- Caleb
In fact, I’m using image object for decoration in my map. I basically create a tileset per image (because they are at different size) where the tile width and height are the one of the image, so that turns into 1 tile and then add them as image object in the map. I don’t see another way for adding different sized images to Tiled, so maybe someone knows a better way
Hi Caleb,
I’m loading a map from tiled using your engine. All runs fine, what I don’t know is how to reload the map to start the player from the start position. I do a map.destroy() and recreate the map, but physics is not recreated. Do you know what could be happening?
Why does starting the player over require you to completely destroy the map and rebuild it? Couldn’t you just do this:
player.x, player.y = map.layer["tiles"].tilesToPixels(startPointX, startPointY) map.snapCamera() -- No camera movement back
If you can’t, what do you mean by “physics is not recreated”?
- Caleb
What options there is to detect if character is on tile (ground)?
Add a number property to your player to store the number of floor surfaces the player is currently touching. Each time you hit the floor, add one to the number, and when you stop hitting that floor element, subtract from it. You can then know if the player is grounded by checking if that number is over 0. (It has to be a number because if you use a Boolean and move horizontally from one floor to another, it registers as not grounded.)
As for the actual colliding itself…
With Box2D Physics
-
Add a separate body element to each floor tile via tile properties (physics2:), make it a sensor, and check the body element on collision - for this, best to offset the body by 1-2 px vertically so you can be sure of a collision
-
Add a separate body element to the player and check the body element of that
-
Check for if the tile is beneath the player on collision
Without Box2D Physics
-
Varies from system to system. It’s not very hard to do, though.
-
Caleb
Thanks Caleb!
Could you please give a basic example how this “ground thing” is done with custom physics.
If you’re not using Box2D, you won’t even need a ground counter, because you check for if the player’s grounded each frame. I went with the “Sonic approach” as detailed in the Sonic physics guide, so each frame, I cast a line (two, actually) down from the player and see if it collides with any tiles which have a top solid property. Here’s a pseudo-Lua example of how I handled it:
function player.onEachFrame() local leftTile, rightTile -- Store the left and right tiles we're colliding with -- Check for left side collision do local tiles = getTilesOverlappedByLine(player.leftSide, player.y, player.leftSide, player.bottomSide + 2) for i = 1, #tiles do if tiles[i].solid.top and player.bottomSide \<= tiles[i].topSide then leftTile = tiles[i] break end end end -- Check for right side collision do local tiles = getTilesOverlappedByLine(player.rightSide, player.y, player.rightSide, player.bottomSide + 2) for i = 1, #tiles do if tiles[i].solid.top and player.bottomSide \<= tiles[i].topSide then rightTile = tiles[i] break end end end -- Find the highest tile local collisionTile = leftTile or rightTile if leftTile and rightTile then if rightTile.y \< leftTile.y then collisionTile = rightTile end end -- Are we even colliding with a tile? if collisionTile then player.y = collisionTile.topSide - player.width \* 0.5 -- Position player on top of tile player.yVel = 0 -- Turn off player's Y-movement player.isGrounded = true -- Player is grounded else player.isGrounded = false end end
Of course, this example only does ground collision. To do the rest of collision, it’s not so hard to expand this in each direction the player’s going. Once you get that working, and you check for ‘solid.top’, ‘solid.left’, ‘solid.right’, and ‘solid.bottom’ on a tile, you can then just add a property ‘solid’ equal to ‘!tags! left, top, right, bottom’ in Tiled, and you’ll be able to solidify your tiles really easily. (Not sure if it’s documented, but Dusk’s ‘!tags!’ prefix creates a table with each comma-separated-value equal to ‘true’.)
The point is, with home-made physics, you have access to the player’s collision state every frame (in fact, you have to have access to it to make gravity work correctly), so you won’t need to keep a counter. You can just query the current state.
- Caleb
–======================================
–Open World / Multiplayer / Zombie survival game
–======================================
local YouAreHuman = true
If YouAreHuman == true then
print(“I will tell others of your game”)
end
Hey guys. I want to show you guys this for support and so that people can see one of the several ways Dusk can be used. It’s the open world/multiplayer/zombie survival game I’ve created. If you like it please feel free to share it with others so I can make it come true.
Hey Caleb!
Are you giving all of this support in your own spare time? Respect man!
@thomas6: Yep.
@Everyone Else:
I’m going to be out of town until April the 21st, so I won’t be able to answer any questions in that time. Sorry if you just came up against a wall or anything :).
- Caleb
Damn man… That’s insane. Supercool that you’re giving so much to the community. I’d love to help out more, but I’m so short on time working on my game (almost three years in the making now) that I need focus on finishing that project in this lifetime first…
Sorry; completely forgot about this topic. I’ll get an official fix for this right away.
- Caleb
I am trying to make a character to double jump and to be able to jump again when character touches to the ground.
So here is my attempt for double jump and noticed that collision doesn’t work properly. Is collision not easy to use when using dusk or something? Am I supposed to like compare character’s coordinates to my “ground” tilelayer where the physics are ?
[lua]
map.layer[“ground”]:insert(animation) – animation is the character
local playerInAir = false
local counter = 0
function jump(event)
if event.phase == “began” and (playerInAir == false or counter <= 1) then
playerInAir = true
animation:setLinearVelocity( 0, -300)
counter = counter + 1
end
return true
end
function onCollision( event )
if(event.object1.myName == “ground” and event.object2.myName == “animation”) then
playerInAir = false
counter = 0
end
end
Runtime:addEventListener( “collision”, onCollision )
[/lua]
So the jumping now is quite randomly happening when I keep clicking the jump button and the double jump doesn’t always work.
I added the ground layers name in Tiled by giving the preference tiles:myName “ground” (not sure if that is the right way) and for animation animation.myName = “animation” in main.lua
Also I would like to know how I could get the collision happen only in characters legs. So you can’t double jump if character jumps face to the wall.
The best way to do this when using a full-on physics engine (Box2D) is to use a counter for isGrounded instead of a Boolean. Also, you should use “isGrounded” instead of the inverse, “playerInAir”. They’ll amount to the same thing, it’s just usually done with a “grounded or not?” counter instead of a “not grounded?” counter. It’s a little more clear.
Anyhow, back to the question.
First of all, what you should do is add a collision listener that waits for “began” and “ended” phase, then sets isGrounded accordingly, instead of manually setting it when the player jumps. Also, to make sure the collision only happens with the player’s legs, you can either add a separate physics body and check for the element number during the collision, or check if the player’s position is sufficiently high above the object you collide with. Alternatively, only give the ground property to the ground tiles , instead of to every tile in the layer. Right click on the tile in the tileset, then add the property isGrounding = true or name = “ground” or something like that to the tile (stay away from “myXYZ” property names - they make your code feel “demo-y” in my opinion, and it’s just a bad practice for readability). If you’re using the same tile for the ground and the walls, this will be a problem and you’ll have to do one of the other options.
Finally, using a collision listener for only the player instead of for all of the scene and checking for if the collider is the player just makes things clearer. So I’d add the listener to the player instead of to Runtime.
Anyhoo, here’s all that information wrapped up:
local function onCollision(event) if "began" == event.phase then if event.other.isGrounding then player.isGrounded = player.isGrounded + 1 end elseif "ended" == event.phase then if event.other.isGrounding then player.isGrounded = player.isGrounded - 1 end end end player:addEventListener("collision", onCollision)
Then, in your enterFrame listener, you can reset the jump count if the player is grounded (jump count also needs a more meaningful name):
if player.isGrounded then jumpCount = 0 end
Finally, when you jump, apply a jump force and increment the jump count.
if player.isGrounded and jumpCount \<= 1 then player:applyLinearImpulse(0, -50) jumpCount = jumpCount + 1 end
- Caleb
Hi Caleb,
I am experimenting with your Dusk engine. Pretty sweet. I got a question though…
I have two Tiled json file maps where player starts from map1 and when enters a door, he goes to map2. Eventually he returns to map1 once he exits interior again.
How should I handle the switch between different map files? Each map is also its own lua file which has methods for loading json file, defining events on this map etc.
What would be the best way to handle switching between multiple levels\maps?
-T-