iCon
Newish
Posts: 20
|
Post by iCon on Feb 18, 2012 1:44:57 GMT -5
I'm struggling to get tile map collision detection in a basic platformer I'm attempting. I'm using sprvel.
|
|
|
Post by Darkjester on Feb 18, 2012 22:55:46 GMT -5
use the sprleft() sprright() sprtop() sprbottom() functions to return the position of the sprite..
|
|
iCon
Newish
Posts: 20
|
Post by iCon on Feb 19, 2012 0:00:49 GMT -5
I can do basic collision detection, I just need a way to find each tile and check for collision without slowing down the program from lots of tiles.
|
|
|
Post by matthew on Feb 19, 2012 16:55:42 GMT -5
Davy wrote a Program here some time ago which uses Tilemap Collision in a game like Zelda. I've put the code & textures in a Zip file that you can download here.
|
|
iCon
Newish
Posts: 20
|
Post by iCon on Feb 20, 2012 3:54:44 GMT -5
Can't see how I would apply this to individual tile collision, that program uses a constant to check the collision with the side of the game. My aim is for the sprite(s) to collide with each specified tile. I need a way to find each tiles x and y values and use this to collide the sprite with them by cycling through each tile.
e.g. for j = 0 to 3 for i = 0 to 11 if tiles (i) (j) = 1 then collide endif next next
|
|
|
Post by matthew on Feb 20, 2012 6:23:50 GMT -5
Try taking a look at the example here by DJLinux.
|
|
iCon
Newish
Posts: 20
|
Post by iCon on Feb 22, 2012 2:02:02 GMT -5
Excellent, but I'm having a some trouble trying to apply to my program. I understand how it works but I can't seem to get it to work. I don't know what is wrong. Use your own sprite atm. textmode (TEXT_BUFFERED)
data 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 data 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 data 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 data 1, 1, 1, 1, 2, 2, 2, 1, 1, 0, 1, 1 data 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 1, 1 data 0, 1, 1, 1, 1, 2, 1, 1, 0, 0, 1, 1 data 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1 data 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0 data 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0
dim xtiles = 11, ytiles = 8 dim x, y, tiles (xtiles) (ytiles), tilemap
for y = 0 to ytiles for x = 0 to xtiles read tiles (x) (y) next next
tilemap = newtilemap (loadtexstrip ("tiles\tiletest.png", 64, 64)) sprsetsolid (false) sprsetxrepeat (false) sprsetyrepeat (false) sprsetpos (128, 192)'both variables are divisible by the tiles height and width sprsettiles (tiles)
'tilemap variables dim tloop 'tile map loop dim i, j, m
'constants const widthhalf = 20 const heighthalf = 60
'variables dim character (texstripframes ("characterfile")- 1)
dim walk (9), stand dim score = 0 dim a = 1 dim ploop 'platform loop dim cl 'collision loop dim notonplat = 1 dim onground = false dim newplatform = true
'player variables dim xplayer = 175 dim yplayer = 200
'collision variables dim xmap, ymap
character = loadtexstrip ("character")
stand = character (0)
walk (0) = character (8) walk (1) = character (1) walk (2) = character (2) walk (3) = character (3) walk (4) = character (4) walk (5) = character (0) walk (6) = character (5) walk (7) = character (6) walk (8) = character (7) walk (9) = character (0)
dim sprite sprite = newsprite (stand) sprsetpos (xplayer, yplayer)
'collision function function notcollision (xloc, yloc)'x location, y location 'left and right ymap = yloc/64 xmap = (xloc - widthhalf)/64 'right side of sprite if tiles (xmap, ymap) = 1 then return false endif xmap = (xloc + widthhalf)/64 'left side of sprite if tiles (xmap, ymap) = 1 then return false endif 'top and bottom xmap = xloc/64 ymap = (yloc - heighthalf)/64 'top of sprite if tiles (xmap, ymap) = 1 then return false endif ymap = (yloc + heighthalf)/64 'bottom of sprite if tiles (xmap, ymap) = 1 then return false endif return true end function
while true 'Player Control bindsprite (2) if scankeydown (VK_RIGHT) then sprsettextures (walk) sprsetanimspeed (0.2) sprsetxflip (false) xplayer = xplayer + 1 elseif scankeydown (VK_LEFT) then sprsettextures (walk) sprsetanimspeed (0.2) sprsetxflip (true) xplayer = xplayer - 1 else sprsettexture (stand) xplayer = xplayer endif 'Stops the player going off screen if sprleft (2) <= -10 and scankeydown (VK_LEFT) then xplayer = xplayer + 1 endif if sprright (2) >= spriteareawidth () + 10 and scankeydown (VK_RIGHT) then xplayer = xplayer - 1 endif 'Tilemap Collision Detection if notcollision (xplayer, yplayer) = true then print "gravity" endif yplayer = yplayer + 1 'temporary, just to check for collision
bindsprite (2): sprsetpos (xplayer, yplayer) drawtext () animatesprites () waittimer (10) wend
Attachments:
|
|
|
Post by matthew on Feb 23, 2012 8:59:28 GMT -5
You can download a ZIP file here with my corrections. There is still something wrong with the game which I haven't got around to fixing which is the Tiles on the the Screen don't appear to match their DATA value. So the Character falls through tiles which he shouldn't. If I had more time I'd have been able to correct it completely but you should be able to finish it off.
|
|
|
Post by shadow008 on Feb 23, 2012 14:54:33 GMT -5
Ya know, I would post the thread that references my 2D ninja demo (which I'm sure some members here may remember), but I cant find the thread anywhere on these forums. Musta gotten deleted. So anyways, this is a 2D platform style game I never gotten around to finishing (I would probably rewrite it before going off that code >.>), but it still works for demonstration purposes. Going down to line 495 theres this thing labled "physics" (again, sloppy code (also note improper use of the term "acceleration)) - This is where my collision detection starts. First off, since it is a static tile based game, you will always know the boundary's of the box's(tiles). Since your image has a static width and a static height, if you know the position of your image(sprite,animation,ect.), you have the boundary of your image. If those two boundary's EVER collide, make them NOT collide (simple, right?) Heres the example from my code: 'test for "on ground" status if tiles(((player(i).y+16)/32),(player(i).x+3)/32) = 1 or tiles(((player(i).y+16)/32),(player(i).x-3)/32) = 1 then player(i).onground = true sprsetpos(sprx(),player(i).heightlevel*32+16) player(i).yhit = true
Now whats happening here? Well, my tiles are set up in an array... HOW CONVENIENT! By knowing that all tiles are 32 pixles by 32 pixles, I now have relative 2D location, and boundary box. So i have a say 640x480 screen, that means i can fit 20x15 tiles in the window (and more if i wanted a larger SPRITE AREA SIZE; which is absolutely _*NOT*_ the same as screen resolution, and is changed by the function ResizeSpriteArea(real,real) ) So cool, I know the tile positions easily, for example tile 2,4 will have location _TileCount*TileSize-HalfTileSize_ or 2*32-16,4*32-16 = 48,112 to the CENTER of the tile. Finding its top most part is as simple as negating the -16 on the y axis and the bottom most part it would be changed to -32. And the same for the x axis (oh yeah, the sprites are set from the top LEFT corner so + on the Y axis is DOWN) Now for the character collision... So I have the Box boundary, well, the character is quite simply, the EXACT same process, with a different center point. Your character boundary is simple as taking the position of your character, dividing it by however big your tile size is, and casting it into an integer rounded DOWN(if it isnt already one). So a character at position 478,133 would be at int(478/32),int(133/32) or 14,4. Well, now you know which tiles to check(all this assuming your character isnt bigger than any tiles). Only the ones corresponding to +/-1 on each axis. So only tiles 15,4 13,4 14,5 and 14,3 must be checked. However, its even simpler if your tiles are in an array like mine are in the demo(and as are yours). Here, you only have to take your character position, and add +HALF_CHARACTER_HEIGHT(in pixles) on each axis, and then cast that into an integer. So lets say we have a character thats 8x32 pixles (like mine are in the demo), At position 478,133 we only need one more step then described above. Instead of simply dividing by tile size and casting into an int, we do something like int(478 +4/32) (adding half the character width size) - which equates to 15. Well, now its really as simple as checking IN YOUR ARRAY, the tile at position 15,4. So it boils down to something really as simple as: If tiles(15)(4) <> 0 then... Also note, im using 0 because its what u have in ur code for "nothing". Thats it, thats really a simple concept once you get use to it. I have no more time to continue, so if you have further questions, just post Good luck with your project! Attachments:
|
|
|
Post by matthew on Feb 23, 2012 16:32:23 GMT -5
Thanks for uploading the file, I knew that someone had created a Platformer before but I couldn't find it on the forum.
|
|
|
Post by shadow008 on Feb 23, 2012 17:27:28 GMT -5
Thanks for uploading the file, I knew that someone had created a Platformer before but I couldn't find it on the forum. No problem But seriously, that entire thread like... disappeared... magically...
|
|
|
Post by matthew on Feb 23, 2012 20:01:59 GMT -5
Well I know when DJLinux became a Mod he deleted several years worth of threads. So sad to say but it was probably one of those.
|
|
iCon
Newish
Posts: 20
|
Post by iCon on Feb 24, 2012 5:10:07 GMT -5
I've got it working, kinda. Whenever I try to add/subtract half the sprites width/height for the collision detection, it doesn't work. If I leave widthhalf and heighthalf at 0, it works just with the centre of the sprite. I've removed left/right collision until I get the down collision working. Sprite is included below. textmode (TEXT_BUFFERED)
' 0 1 2 3 4 5 6 7 8 9 10 11 12 data 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 '0 data 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 '1 data 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 '2 data 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 '3 data 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 '4 data 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 '5 data 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 '6 data 1, 1, 1, 1, 2, 2, 2, 1, 1, 0, 1, 1, 1 '7 data 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 1, 1, 1 '8 data 0, 1, 1, 1, 1, 2, 1, 1, 0, 0, 1, 1, 1 '9 data 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 '10 data 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0 '11 data 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0 '12 data 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 '13 data 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 '14
dim xtiles = 12, ytiles = 14 dim x, y, tiles (xtiles) (ytiles), tilemap
for y = 0 to ytiles for x = 0 to xtiles read tiles (x) (y) next next
tilemap = newtilemap (loadtexstrip ("tiles\tiletest.png", 64, 64)) sprsetsolid (false) sprsetxrepeat (false) sprsetyrepeat (false) sprsetpos (0, 0) sprsettiles (tiles)
'tilemap variables dim tloop 'tile map loop dim i, j, m
'constants const widthhalf = 0 const heighthalf = 0
'variables dim cyanman (texstripframes ("tiles\cyanman.png")- 1)
dim walk (9), stand dim score = 0 dim a = 1 dim ploop 'platform loop dim cl 'collision loop dim notonplat = 1 dim onground = false dim newplatform = true
'player variables dim xplayer# = 175 dim yplayer# = 100
'collision variables dim xmap, ymap
cyanman = loadtexstrip ("tiles\cyanman.png")
stand = cyanman (0)
walk (0) = cyanman (8) walk (1) = cyanman (1) walk (2) = cyanman (2) walk (3) = cyanman (3) walk (4) = cyanman (4) walk (5) = cyanman (0) walk (6) = cyanman (5) walk (7) = cyanman (6) walk (8) = cyanman (7) walk (9) = cyanman (0)
dim sprite sprite = newsprite (stand) sprsetpos (xplayer#, yplayer#)
'collision function function notcollision (xloc, yloc)'x location, y location 'top and bottom xmap = (xloc/32) ymap = ((yloc - heighthalf)/32) 'top of sprite if tiles (xmap, ymap) = 1 then return false endif ymap = ((yloc + heighthalf)/32) 'bottom of sprite if tiles (xmap, ymap) = 1 then return false endif return true end function
while true cls 'Player Control bindsprite (2) if scankeydown (VK_RIGHT) then sprsettextures (walk) sprsetanimspeed (0.2) sprsetxflip (false) xplayer# = xplayer# + 1 elseif scankeydown (VK_LEFT) then sprsettextures (walk) sprsetanimspeed (0.2) sprsetxflip (true) xplayer# = xplayer# - 1 else sprsettexture (stand) xplayer# = xplayer# endif 'Stops the player going off screen if sprleft (2) <= -10 and scankeydown (VK_LEFT) then xplayer# = xplayer# + 1 endif if sprright (2) >= spriteareawidth () + 10 and scankeydown (VK_RIGHT) then xplayer# = xplayer# - 1 endif 'Tilemap Collision Detection if notcollision (xplayer#, yplayer#) = true then yplayer# = yplayer# + 1 endif locate 0, 1: print xmap locate 0, 3: print ymap bindsprite (2): sprsetpos (xplayer#, yplayer#) drawtext () animatesprites () waittimer (10) wend
Attachments:
|
|
|
Post by matthew on Feb 24, 2012 5:32:42 GMT -5
Try using SprSetXCentre & SprSetYCentre to adjust the centre of the Sprite. You'll find the commands described in the Sprite Library Guide.
|
|
|
Post by shadow008 on Feb 24, 2012 15:04:33 GMT -5
Your problems atm:
Change line "tilemap = newtilemap (loadtexstrip ("tiles\tiletest.png", 64, 64))"
to
tilemap = newtilemap (loadtexstrip ("tiles\tiletest.png", 32, 32))
OR change the half height to 32. I'd make a constant for your tile size.
ALSO: Add some changes like this to your code:
-Make a definite tile size like CONST TileSize = 32 ... tilemap = newtilemap (loadtexstrip ("tiles\tiletest.png", TILE_SIZE, TILE_SIZE))
-Make a definite screen size using: ResizeSpriteArea(640,480) OR ResizeSpriteArea(xtiles*TILE_SIZE,ytiles*TILE_SIZE)
-Make xtiles and ytiles either EQUAL or in proportion to the screen size
So something like 20x15 tiles for 640x480 sprite size.
-Change the zorder of your tiles to be behind your character:
tilemap = newtilemap (loadtexstrip ("tiles\tiletest.png", 64, 64)) sprsetsolid (false) sprsetxrepeat (false) sprsetyrepeat (false) sprsetpos (0, 0) sprsettiles (tiles) SprSetZOrder(-1)
....
tilemap = newtilemap (loadtexstrip ("tiles\tiletest.png", 64, 64)) SprSetZOrder(1) sprsetsolid (false) ....
Then you should have no problems fixing the side to side collision, and moving further on.
Hope this helps ^_^
|
|