Collision problem
Blitz3D Forums/Blitz3D Beginners Area/Collision problem
| ||
So I'm trying to work out some code for collision detection, but there's something wrong with it. It seems to only detect a collision between the 'player' and the last "tile" type placed/loaded onto the map, rather than any tile on the map. I honestly can't see what's going wrong. Can anyone tell me why this is happening? Many thanks to anyone who can help me with this. ;tiles test ;Sean Tomlin ; ;Last updated 13th June 07 ;;;;;;;;;;;;;;;;;;;;; ; ;Space to save map ;Comma to load map ;Left mouseclick = place tile ;Delete + mouseclick = delete tiles ;Right mouseclick + move mouse = move around map ;Up/Down = change tile ; ;;;;;;;;;;;;;;;;;;;;; Global tnumber = 0 Global maprx Global mapry Global maprmode Global ox = 0 Global oy = 0 Global gravity# = 0.01 Graphics 640,480,16,1 SetBuffer BackBuffer() ClsColor 134,156,175 ;load tileset Global tiles1=LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage tiles1,255,0,255 Global px Global py Global pxspeed Global pyspeed Global pfalling=1 Global x Global y Global count Global tilecount ;;;;;;;;;;;;; While Not KeyHit(1) Cls Origin ox,oy UpdateMouse() If KeyHit(27) And tnumber<15 Then tnumber=tnumber+1 If KeyHit(26) And tnumber>0 Then tnumber=tnumber-1 If KeyHit(57) Then SaveMap() Text 10,290,"Save" EndIf If KeyHit(51) Then LoadMap() If KeyHit(14) Then ClearMap() UpdateTiles() UpdatePlayer() Text 10,10,x/16 Text 10,30,y/16 Text 10,180,maprx Text 10,200,mapry Text 10,220,maprmode Flip Wend ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Type tile ;position within grid Field xnum Field ynum ;type of tile: ground, water or danger Field mode End Type ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function UpdateMouse() ;infiinite mouse movement xs=MouseXSpeed() ys=MouseYSpeed() MoveMouse 320,240 ;right mouse button (click + drag): move around map If MouseDown(2) Then ox=ox+xs oy=oy+ys Else x=x+xs y=y+ys EndIf ;draw the currently selected tile at mouse cursor DrawImage tiles1,x,y,tnumber Color 45,200,75 Rect x,y,16,16,0 ;LMB: place tile If MouseDown(1) Then If Not KeyDown(58) Then t.tile = New tile t\xnum = x/16 t\ynum = y/16 t\mode = tnumber Else ;4x tile if CAPS pressed also t.tile = New tile t\xnum = x/16 t\ynum = y/16 t\mode = tnumber t.tile = New tile t\xnum = (x/16)+1 t\ynum = y/16 t\mode = tnumber t.tile = New tile t\xnum = x/16 t\ynum = (y/16)+1 t\mode = tnumber t.tile = New tile t\xnum = (x/16)+1 t\ynum = (y/16)+1 t\mode = tnumber EndIf EndIf End Function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function UpdateTiles() For t.tile = Each tile DrawImage tiles1,t\xnum*16,t\ynum*16,t\mode If ImageRectOverlap(tiles1,t\xnum*16,t\ynum*16,x,y,14,14) Then If KeyDown(211) Then Delete t Else EndIf If ImageRectOverlap(tiles1,t\xnum*16,t\ynum*16,px,py,16,26) Then pfalling = 0 Else pfalling = 1 EndIf Next End Function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function UpdatePlayer() If KeyDown(205) Then If pxspeed<1.8 Then pxspeed=pxspeed+0.1 ElseIf pxspeed>0 Then pxspeed=pxspeed-0.1 EndIf If KeyDown(203) Then If pxspeed>-1.8 Then pxspeed=pxspeed-0.1 Else If pxspeed<0 Then pxspeed=pxspeed+0.1 EndIf px = x py = y ;If pfalling = 1 Then ; If pyspeed<0.5 Then pyspeed = pyspeed + 0.01 ;Else ; pyspeed = 0 ;EndIf ;py = py + pyspeed Color 30,200,130 Rect px,py,16,24 Text px+30,py,pfalling End Function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function SaveMap() Color 20,20,75 mapname$="mapdata.txt" Count = 0 For t.tile = Each tile count = count + 1 Next mapout = WriteFile(mapname$) WriteInt(mapout,count) For t.tile = Each tile WriteInt(mapout,t\xnum) WriteInt(mapout,t\ynum) WriteInt(mapout,t\mode) Next CloseFile mapout End Function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function LoadMap() Color 20,20,75 whichmap$="mapdata.txt" For t.tile = Each tile Delete t Next mapin = ReadFile(whichmap$) count = ReadInt(mapin) For tile = 1 To count t.tile = New tile t\xnum=ReadInt(mapin) t\ynum=ReadInt(mapin) t\mode=ReadInt(mapin) Next CloseFile(mapin) End Function Function ClearMap() For t.tile = Each tile Delete t Next End Function Edit: should I have put that in a codebox? :S |
| ||
This doesn't work 'cause you haven't load a new image for each tile you create! Ex: If Not KeyDown(58) Then t.tile = New tile ;LOOK here t\img = LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage t\img,255,0,255 t\xnum = x/16 t\ynum = y/16 t\mode = tnumber Else ;4x tile if CAPS pressed also t.tile = New tile ;LOOK here t\img = LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage t\img,255,0,255 t\xnum = x/16 t\ynum = y/16 t\mode = tnumber t.tile = New tile ;LOOK here t\img = LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage t\img,255,0,255 t\xnum = (x/16)+1 t\ynum = y/16 t\mode = tnumber t.tile = New tile ;LOOK here t\img = LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage t\img,255,0,255 t\xnum = x/16 t\ynum = (y/16)+1 t\mode = tnumber t.tile = New tile ;LOOK here t\img = LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage t\img,255,0,255 t\xnum = (x/16)+1 t\ynum = (y/16)+1 t\mode = tnumber EndIf Then in the collision detection change to: DrawImage t\img,t\xnum*16,t\ynum*16,t\mode If ImageRectOverlap(t\img,t\xnum*16,t\ynum*16,x,y,14,14) Then Remember to change the type declaration! Type tile ;img!!! field img ;position within grid Field xnum Field ynum ;type of tile: ground, water or danger Field mode End Type P.s. Obviously you have to add those modifications to the whole code! Remember to change the Loadmap() function for example! |
| ||
Thanks Ingenium. I'll have a look. edit: Ok, I just tried that. Unfortunately, it makes loading the map so much slower. It actually just completely freezes for about 5 seconds before it loads :( I then tried to use RectsOverlap to see if that made things any easier regarding collision, but I still have the same problem; it only detects a collision with the last tile created. Any ideas? |
| ||
This code should work. Search for ">>>CORRECTED" to find any modifications! ;tiles test ;Sean Tomlin ; ;Last updated 13th June 07 ;;;;;;;;;;;;;;;;;;;;; ; ;Space to save map ;Comma to load map ;Left mouseclick = place tile ;Delete + mouseclick = delete tiles ;Right mouseclick + move mouse = move around map ;Up/Down = change tile ; ;;;;;;;;;;;;;;;;;;;;; Global tnumber = 0 Global maprx Global mapry Global maprmode Global ox = 0 Global oy = 0 Global gravity# = 0.01 Graphics 640,480,16,1 SetBuffer BackBuffer() ClsColor 134,156,175 ;load tileset Global tiles1=LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage tiles1,255,0,255 Global px Global py Global pxspeed Global pyspeed Global pfalling=1 Global x Global y Global count Global tilecount ;;;;;;;;;;;;; While Not KeyHit(1) Cls Origin ox,oy UpdateMouse() If KeyHit(27) And tnumber<15 Then tnumber=tnumber+1 If KeyHit(26) And tnumber>0 Then tnumber=tnumber-1 If KeyHit(57) Then SaveMap() Text 10,290,"Save" EndIf If KeyHit(51) Then LoadMap() If KeyHit(14) Then ClearMap() UpdateTiles() UpdatePlayer() Text 10,10,x/16 Text 10,30,y/16 Text 10,180,maprx Text 10,200,mapry Text 10,220,maprmode Flip Wend ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Type tile ;>>>CORRECTED Field img ;position within grid Field xnum Field ynum ;type of tile: ground, water or danger Field mode End Type ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function UpdateMouse() ;infiinite mouse movement xs=MouseXSpeed() ys=MouseYSpeed() MoveMouse 320,240 ;right mouse button (click + drag): move around map If MouseDown(2) Then ox=ox+xs oy=oy+ys Else x=x+xs y=y+ys EndIf ;draw the currently selected tile at mouse cursor DrawImage tiles1,x,y,tnumber Color 45,200,75 Rect x,y,16,16,0 ;LMB: place tile If MouseDown(1) Then If Not KeyDown(58) Then t.tile = New tile ;>>>CORRECTED t\img = LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage t\img,255,0,255 t\xnum = x/16 t\ynum = y/16 t\mode = tnumber Else ;4x tile if CAPS pressed also t.tile = New tile ;>>>CORRECTED t\img = LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage t\img,255,0,255 t\xnum = x/16 t\ynum = y/16 t\mode = tnumber t.tile = New tile ;>>>CORRECTED t\img = LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage t\img,255,0,255 t\xnum = (x/16)+1 t\ynum = y/16 t\mode = tnumber t.tile = New tile ;>>>CORRECTED t\img = LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage t\img,255,0,255 t\xnum = x/16 t\ynum = (y/16)+1 t\mode = tnumber t.tile = New tile ;>>>CORRECTED t\img = LoadAnimImage("C:/a/Co/Tiles/_A_TilesTest.bmp",16,16,0,16) MaskImage t\img,255,0,255 t\xnum = (x/16)+1 t\ynum = (y/16)+1 t\mode = tnumber EndIf EndIf End Function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function UpdateTiles() For t.tile = Each tile ;>>>CORRECTED DrawImage t\img,t\xnum*16,t\ynum*16,t\mode ;>>>CORRECTED If ImageRectOverlap(t\img,t\xnum*16,t\ynum*16,x,y,14,14) Then If KeyDown(211) Then Delete t Else EndIf ;>>>CORRECTED If ImageRectOverlap(t\img,t\xnum*16,t\ynum*16,px,py,16,26) Then pfalling = 0 Else pfalling = 1 EndIf ;>>>WHOA!!! YOU HAVE FORGOTTEN AN "EndIf"!!! EndIf Next End Function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function UpdatePlayer() If KeyDown(205) Then If pxspeed<1.8 Then pxspeed=pxspeed+0.1 ElseIf pxspeed>0 Then pxspeed=pxspeed-0.1 EndIf If KeyDown(203) Then If pxspeed>-1.8 Then pxspeed=pxspeed-0.1 Else If pxspeed<0 Then pxspeed=pxspeed+0.1 EndIf px = x py = y ;If pfalling = 1 Then ; If pyspeed<0.5 Then pyspeed = pyspeed + 0.01 ;Else ; pyspeed = 0 ;EndIf ;py = py + pyspeed Color 30,200,130 Rect px,py,16,24 Text px+30,py,pfalling End Function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function SaveMap() Color 20,20,75 mapname$="mapdata.txt" Count = 0 For t.tile = Each tile count = count + 1 Next mapout = WriteFile(mapname$) WriteInt(mapout,count) For t.tile = Each tile ;>>>CORRECTED writeInt(mapout,t\img) WriteInt(mapout,t\xnum) WriteInt(mapout,t\ynum) WriteInt(mapout,t\mode) Next CloseFile mapout End Function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Function LoadMap() Color 20,20,75 whichmap$="mapdata.txt" For t.tile = Each tile Delete t Next mapin = ReadFile(whichmap$) count = ReadInt(mapin) For tile = 1 To count t.tile = New tile ;>>>CORRECTED t\img=ReadInt(mapin) t\xnum=ReadInt(mapin) t\ynum=ReadInt(mapin) t\mode=ReadInt(mapin) Next CloseFile(mapin) End Function Function ClearMap() For t.tile = Each tile Delete t Next End Function |
| ||
Thanks for the help, but I'm actually fairly certain now that it's nothing to do with the image and how it's handled. I wrote this to check. There are no images or external files involved so you should be able to run it and see for yourself: it STILL only recognises the last tile created! I really don't understand why...any other ideas?Graphics 640,480,16,1 SetBuffer BackBuffer() ClsColor 43,135,200 ;;;;;;;;;;;;;;; Type tile ;position within grid Field xnum Field ynum ;type of tile: ground, water or danger Field mode End Type ;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;; Global px Global py Global pxspeed Global pyspeed Global pfalling=1 ;;;;;;;;;;;;;;;;;;; For i = 1 To 10 t.tile = New tile t\xnum = 5+i t\ynum = 8+i t\mode = 0 Next ;;;;;;;;;;;;;;;;;; While Not KeyHit(1) Cls UpdateTiles() Flip Wend End ;;;;;;;;;;;;;;;; Function UpdateTiles() For t.tile = Each tile ;DrawImage tiles1,t\xnum*16,t\ynum*16,t\mode Color 230,100,100 Rect t\xnum*16,t\ynum*16,16,16,True If RectsOverlap(t\xnum*16,t\ynum*16,16,16,MouseX(),MouseY(),14,14) Then pfalling = 0 Else pfalling = 1 Next Color 255,255,255 Rect MouseX(),MouseY(),14,14,False Text 10,10,pfalling If pfalling = 0 Then Color 255,0,0 Oval 10,30,10,10 EndIf End Function |
| ||
YES! Nevermind, I just figured it out. All that was needed was a "collided" true/false field in the "tile" type, which is set to true when there is a collision with the player, and false if not :) |
| ||
Make this change:pfalling = 1 For t.tile = Each tile ;DrawImage tiles1,t\xnum*16,t\ynum*16,t\mode Color 230,100,100 Rect t\xnum*16,t\ynum*16,16,16,True If RectsOverlap(t\xnum*16,t\ynum*16,16,16,MouseX(),MouseY(),14,14) Then pfalling = 0 Next P.S. Don't load the same animimage many times, as suggested by ingenium. |