2.5D implementation
2.5D implementation
Hi, i'm looking for ideas & suggestions on what would be the best way to implement something like this in LUA:
..mainly how to do sprite ordering & collisions in a situation as depicted above
..mainly how to do sprite ordering & collisions in a situation as depicted above
- Jasoco
- Inner party member
- Posts: 3727
- Joined: Mon Jun 22, 2009 9:35 am
- Location: Pennsylvania, USA
- Contact:
Re: 2.5D implementation
Sprite Z ordering is easy. You just sort the objects table by its Y value.
If I made the game, and believe me, I've wanted to make something like the old Konami side-scrolling TMNT/Simpsons arcade games, every character and object on screen would be an actor or scenery. In my Adventure game project I use this method. All enemies, scenery, dropped items and the player, etc, are dumped into a table each frame, and that table is then sorted by its Y value using code like this:
table.sort(T) where T is the table name of the table you put all your objects in. This will sort them in ascending order so they get drawn in the correct order. a.y < b.y is the key part here as it sorts the first one before the second one. If you reversed them you'd draw the objects in the wrong order.
Can't help you with the collisions. Well, I can. But it might be different in every game. There's an active thread with a collision function out there somewhere. This is the code I use for finding if two rectangles collide:
Yes, there might be a more compact way to do it, if so, let me know. As long as it takes the same parameters and returns the same values, I don't care what the function looks like.
Where x, y, w and h are the location and size of each rectangle. Where a rectangle would be a fist and an enemy. 1 would be the fist, 2 would be the enemy. And you would check against each enemy to see if your fist (Or foot) collided. Then take the appropriate action.
This function would also be used for picking up items by checking against every dropped item on screen to see if you walked over it.
If I made the game, and believe me, I've wanted to make something like the old Konami side-scrolling TMNT/Simpsons arcade games, every character and object on screen would be an actor or scenery. In my Adventure game project I use this method. All enemies, scenery, dropped items and the player, etc, are dumped into a table each frame, and that table is then sorted by its Y value using code like this:
Code: Select all
function sort(T) table.sort(T, function(a, b) return a.y < b.y end ) end
Can't help you with the collisions. Well, I can. But it might be different in every game. There's an active thread with a collision function out there somewhere. This is the code I use for finding if two rectangles collide:
Code: Select all
function overlap(x1,y1,w1,h1,x2,y2,w2,h2)
local tl, bl, tr, br = false, false, false, false
if (x2 >= x1 and x2 <= (x1 + w1)) and (y2 >= y1 and y2 <= (y1 + h1)) then tl = true end
if (x2+w2 >= x1 and x2+w2 <= (x1 + w1)) and (y2 >= y1 and y2 <= (y1 + h1)) then tr = true end
if (x2 >= x1 and x2 <= (x1 + w1)) and (y2+h2 >= y1 and y2+h2 <= (y1 + h1)) then bl = true end
if (x2+w2 >= x1 and x2+w2 <= (x1 + w1)) and (y2+h2 >= y1 and y2+h2 <= (y1 + h1)) then br = true end
if (x1 >= x2 and x1 <= (x2 + w2)) and (y1 >= y2 and y1 <= (y2 + h2)) then tl = true end
if (x1+w1 >= x2 and x1+w1 <= (x2 + w2)) and (y1 >= y2 and y1 <= (y2 + h2)) then tr = true end
if (x1 >= x2 and x1 <= (x2 + w2)) and (y1+h1 >= y2 and y1+h1 <= (y2 + h2)) then bl = true end
if (x1+w1 >= x2 and x1+w1 <= (x2 + w2)) and (y1+h1 >= y2 and y1+h1 <= (y2 + h2)) then br = true end
if tl or tr or bl or br then return true else return false end
end
Where x, y, w and h are the location and size of each rectangle. Where a rectangle would be a fist and an enemy. 1 would be the fist, 2 would be the enemy. And you would check against each enemy to see if your fist (Or foot) collided. Then take the appropriate action.
This function would also be used for picking up items by checking against every dropped item on screen to see if you walked over it.
Re: 2.5D implementation
I've done this before in c++ in various ways (also with methods you described) but I'm completely new to LUA and LÖVE .. so I thought maybe there's a different angle on this that one can leverage using LUA .. while this approach works (and can be optimised) I never really liked it. I wonder how the old arcades did it, surely they didn't just sort everything and BB-check a lot every frame?
BUT in this particular case the "perspective" was/is giving me a little trouble, (XY plane representing the ground it appears like a skewed rectangle) mainly with the !$!=# STAIRS .. how would I sort and collide the player against the rail/stairs?
BUT in this particular case the "perspective" was/is giving me a little trouble, (XY plane representing the ground it appears like a skewed rectangle) mainly with the !$!=# STAIRS .. how would I sort and collide the player against the rail/stairs?
- Jasoco
- Inner party member
- Posts: 3727
- Joined: Mon Jun 22, 2009 9:35 am
- Location: Pennsylvania, USA
- Contact:
Re: 2.5D implementation
Stairs are a bit harder. I would say it's basically just an extra Y offset depending on where along the stairs you are.
Is this a game you made or someone made? Is this a real game? Are you sure the stairs are accessible by the player? It might just be scenery. As that wouldn't require actual interaction.
Is this a game you made or someone made? Is this a real game? Are you sure the stairs are accessible by the player? It might just be scenery. As that wouldn't require actual interaction.
- Robin
- The Omniscient
- Posts: 6506
- Joined: Fri Feb 20, 2009 4:29 pm
- Location: The Netherlands
- Contact:
Re: 2.5D implementation
Hm. Lemme try.Jasoco wrote:Yes, there might be a more compact way to do it, if so, let me know. As long as it takes the same parameters and returns the same values, I don't care what the function looks like.Code: Select all
function overlap(x1,y1,w1,h1,x2,y2,w2,h2) local tl, bl, tr, br = false, false, false, false if (x2 >= x1 and x2 <= (x1 + w1)) and (y2 >= y1 and y2 <= (y1 + h1)) then tl = true end if (x2+w2 >= x1 and x2+w2 <= (x1 + w1)) and (y2 >= y1 and y2 <= (y1 + h1)) then tr = true end if (x2 >= x1 and x2 <= (x1 + w1)) and (y2+h2 >= y1 and y2+h2 <= (y1 + h1)) then bl = true end if (x2+w2 >= x1 and x2+w2 <= (x1 + w1)) and (y2+h2 >= y1 and y2+h2 <= (y1 + h1)) then br = true end if (x1 >= x2 and x1 <= (x2 + w2)) and (y1 >= y2 and y1 <= (y2 + h2)) then tl = true end if (x1+w1 >= x2 and x1+w1 <= (x2 + w2)) and (y1 >= y2 and y1 <= (y2 + h2)) then tr = true end if (x1 >= x2 and x1 <= (x2 + w2)) and (y1+h1 >= y2 and y1+h1 <= (y2 + h2)) then bl = true end if (x1+w1 >= x2 and x1+w1 <= (x2 + w2)) and (y1+h1 >= y2 and y1+h1 <= (y2 + h2)) then br = true end if tl or tr or bl or br then return true else return false end end
Code: Select all
function overlap(x1,y1,w1,h1,x2,y2,w2,h2)
return (((x2+w2 >= x1 and x2+w2 <= (x1 + w1)) or (x2 >= x1 and x2 <= (x1 + w1)))
and ((y2 >= y1 and y2 <= (y1 + h1)) or (y2+h2 >= y1 and y2+h2 <= (y1 + h1)))
end
Help us help you: attach a .love.
- Jasoco
- Inner party member
- Posts: 3727
- Joined: Mon Jun 22, 2009 9:35 am
- Location: Pennsylvania, USA
- Contact:
Re: 2.5D implementation
Amazing. Aside from a missing closing parenthesis at the end, (Which I added above in the quote just in case someone wants to use the code it'll work right.) it works just as well. Thanks! I can't see how it could get any shorter without taking out all the spaces, replacing the two digit variables with single digit ones, removing unneeded parenthesis and putting it all on one line. Like this...Robin wrote:Hm. Lemme try.Warning: untested, and it can probably be made shorter.Code: Select all
function overlap(x1,y1,w1,h1,x2,y2,w2,h2) return (((x2+w2 >= x1 and x2+w2 <= (x1 + w1)) or (x2 >= x1 and x2 <= (x1 + w1))) and ((y2 >= y1 and y2 <= (y1 + h1)) or (y2+h2 >= y1 and y2+h2 <= (y1 + h1)))) end
Code: Select all
function o(x,y,w,h,a,b,c,d) return (((a+c>=x and a+c<=x+w) or (a>=x and a<=x+w)) and ((b>=y and b<=y+h) or (b+d>=y and b+d<=y+h))) end
Edit: Wait, I spoke too soon. Yours doesn't always detect collisions. I had this same problem when I first wrote mine. I implemented yours and suddenly a lot of my collisions were being ignored. Enemy hits missing, item pickups un-picked-up. Hmm... Still, there must be a way. For now, mine works fine and dandy.
Edit more:
This works though. I wrote my original function when I was a n00b at Lua and didn't know all the cool tricks. I improved my own method to utilize the method you use:
Code: Select all
function overlap(x1,y1,w1,h1, x2,y2,w2,h2)
return (x2 >= x1 and x2 <= x1+w1) and (y2 >= y1 and y2 <= y1+h1) or
(x2+w2 >= x1 and x2+w2 <= x1+w1) and (y2 >= y1 and y2 <= y1+h1) or
(x2 >= x1 and x2 <= x1+w1) and (y2+h2 >= y1 and y2+h2 <= y1+h1) or
(x2+w2 >= x1 and x2+w2 <= x1+w1) and (y2+h2 >= y1 and y2+h2 <= y1+h1) or
(x1 >= x2 and x1 <= x2+w2) and (y1 >= y2 and y1 <= y2+h2) or
(x1+w1 >= x2 and x1+w1 <= x2+w2) and (y1 >= y2 and y1 <= y2+h2) or
(x1 >= x2 and x1 <= x2+w2) and (y1+h1 >= y2 and y1+h1 <= y2+h2) or
(x1+w1 >= x2 and x1+w1 <= x2+w2) and (y1+h1 >= y2 and y1+h1 <= y2+h2)
end
- ghostwriter
- Prole
- Posts: 38
- Joined: Sat Dec 11, 2010 11:08 pm
Re: 2.5D implementation
At the risk of hijacking paramecij's thread, i'll share my rectangle collision code:Jasoco wrote:Yes, there might be a more compact way to do it, if so, let me know. As long as it takes the same parameters and returns the same values, I don't care what the function looks like.
Code: Select all
function overlap(x1,y1,w1,h1,x2,y2,w2,h2)
if x1+w1 < x2
or x2+w2 < x1
or y1+h1 < y2
or y2+h2 < y1 then
return false
end
return true
end
- Attachments
-
- collide.love
- (441 Bytes) Downloaded 186 times
- ghostwriter
- Prole
- Posts: 38
- Joined: Sat Dec 11, 2010 11:08 pm
Re: 2.5D implementation
To reply to paramecij's original question, I would recommend storing the full three dimensional x-y-z coordinates of each sprite. That way you can still use the sorting method suggested by Jasoco, as well as have things like stairs. For example, moving left and right would change the x position, moving towards or away from the screen would change the z position and moving vertically changes the Y position.
This way you could still simply sort by Z position for drawing, no matter how high something is on the Y axis. You'd just have to figure out how to draw everything in the correct position. You can see in the image below, even though the two characters are on the stairs, their z-position is closer than the z-position of the guy on the ground beside them.
This way you could still simply sort by Z position for drawing, no matter how high something is on the Y axis. You'd just have to figure out how to draw everything in the correct position. You can see in the image below, even though the two characters are on the stairs, their z-position is closer than the z-position of the guy on the ground beside them.
- Robin
- The Omniscient
- Posts: 6506
- Joined: Fri Feb 20, 2009 4:29 pm
- Location: The Netherlands
- Contact:
Re: 2.5D implementation
Oops.ghostwriter wrote:At the risk of hijacking paramecij's thread,
Your version was exactly what I meant, I just couldn't remember what it was exactly, probably because of the Eldritch abomination that was the original (sorry, Jasoco).ghostwriter wrote:i'll share my rectangle collision code:
Anyway, to make it even shorter:
Code: Select all
function overlap(x1,y1,w1,h1,x2,y2,w2,h2)
return not (x1+w1 < x2 or x2+w2 < x1
or y1+h1 < y2 or y2+h2 < y1)
end
Help us help you: attach a .love.
- Jasoco
- Inner party member
- Posts: 3727
- Joined: Mon Jun 22, 2009 9:35 am
- Location: Pennsylvania, USA
- Contact:
Re: 2.5D implementation
At the risk of being stupid and an idiot because it goes against every 3d game ever made, but I always prefer to refer to X and Y as being the floor and Z being the height of the room. It always seemed weird to have Z be north and south and Y being above and below. Just seems stupid and I blame iD Software even though they probably didn't come up with it, but I need a scapegoat to blame and they were the first to come to mind. i.e., the ground in that game would be X and Y and the Z would be the characters jumping or on stairs position above the ground level.ghostwriter wrote:To reply to paramecij's original question, I would recommend storing the full three dimensional x-y-z coordinates of each sprite. That way you can still use the sorting method suggested by Jasoco, as well as have things like stairs. For example, moving left and right would change the x position, moving towards or away from the screen would change the z position and moving vertically changes the Y position.
This way you could still simply sort by Z position for drawing, no matter how high something is on the Y axis. You'd just have to figure out how to draw everything in the correct position. You can see in the image below, even though the two characters are on the stairs, their z-position is closer than the z-position of the guy on the ground beside them.
So basically, in my adventure game engine, X and Y are the left, right, up and down of my map and "elevation" is the Z coordinate for when placing scenery or having a flying enemy. Makes much more sense this way to me and doesn't require me to edit my project to replace all the Y's with Z's.
But other than that, I agree. That picture is exactly how it should be handled. I would like to make a game like this one day and this is the method I would use too. Though I'd also like to make an isometric adventure game one day too. I have abandoned projects for so many game types including an almost arcade perfect Pac-Man that I never got around to finishing because I ran out of ideas or hit a wall or got bored. My Adventure engine remains the one major project I've started and stuck with.
Also, Robin, your new code seems to work just as well too. Using it for now unless I hit the same bug I had before. Hopefully it works perfect because I like how much less space it takes.
Who is online
Users browsing this forum: No registered users and 14 guests