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. |