News:

Building a 3D Ray Tracer  By stevmjon

Main Menu

collision help!

Started by RaverDave, January 01, 2006, 04:29:09 AM

Previous topic - Next topic

RaverDave

Sorry its been a while! I dug up some old code that kevin helped me with,added another loop to get the structure correct for more levels eventually, but it seems to not be counting,or minusing depending how you look at it!! the number of bricks hit!!I have tried allsorts and this last attempt i have used something like 4 variables to try and keep track of whats hit,putting em inside a loop,outside a loop,tried everything..Please help any1!!

PlayBASIC Code: [Select]
; PROJECT : mytest
; AUTHOR : raverdave
; CREATED : 01/01/2006
; EDITED : 01/01/2006

;

OpenScreen 640,480,32,2
;SetFPS 0
Mouse Off
ScreenVsync On

PlayerX=50
PlayerY=430
PlayerWidth =10
PlayerHeight =10
Speed=4
currlev=1
maxlev=99
Global tilenum=0
Global amm
Global amm2
Global amm3
Global amm4
Global hit
Global tot
MyMap = GetFreeMap()
CreateMap MyMap, 1
mapx=0
mapy=0
TileWidth=32
TileHeight=16
Number_of_tiles = 9

; Loop through and draw a series of randomly coloured Boxes to the screen
For lp=1 To Number_of_tiles
xpos=lp*tileWidth
BoxC Xpos,0,Xpos+TileWidth,TileHeight,1,RndRGB()
Line xpos,0,xpos+TileWidth,0
Line xpos,0,xpos,tileheight
Next

; Grab the box graphics that we've just drawn as image.
TempImage=GetFreeImage()
GetImage TempImage,0,0,xpos+TIleWidth,Tileheight
MakeMapGFX MyMAP,TempImage,TileWidth,TileHeight,Number_Of_Tiles,RGB(0,0,0)

Repeat
tilenum=0
tot=0
hit=0
amm=0
amm2=0
amm3=0
amm4=0
Restore 0
CreateLevel MyMap,1, 100,100
For Ylp=0 To 13
For Xlp=0 To 18
t=ReadData()
If t>0
tilenum=tilenum+1
PokeLevelTile MyMap,1,Xlp,ylp,t
EndIf
Next xlp
Next ylp

Repeat
SetCursor 0,0
Cls 0
DrawMap MyMap,1,mapx,mapy
PLayerX,PLayerY=Handle_player(PLayerX,PLayerY,PLayerWIdth,PlayerHeight,Speed,MyMap,1)
X2=playerX+PlayerWidth
Y2=playerY+PlayerHeight
Ink RGB(0,0,0)
Box playerX,playerY,x2,y2,1


fakex=playerX+5
fakey=playerY+5
Ink RGB(255,255,255)
Circle fakex,fakey,5,1
v=ScanCode()
If v=16
quit=1
EndIf

SetCursor 40,0
Print tilenum

Sync
Until quit=1 Or tilenum<=0

Until currlev>maxlev



Function Handle_player(PLayerX,PLayerY,WIdth,Height,Speed,ThisMap,ThisLevel)

; Store the players possible new position
NewX=PlayerX
NewY=PlayerY

; Handle the players Movement
If UpKey() Then NewY=PLayerY-Speed
If DownKey() Then NewY=PLayerY+Speed
If LeftKey() Then NewX=PLayerX-Speed
If RightKey() Then NewX=PLayerX+Speed

; ==========================
; Handle Collision
; ===========================
If CheckMapImpact(thisMap,ThisLevel,PlayerX,playerY,NewX,NewY,Width,Height)

; If there was impact with the map, then read our
; new position back.
PlayerX=GetMapImpactX()
PlayerY=GetMapImpactY()

TileWidth=GetMapBlockWidth(ThisMap)
TileHeight=GetMapBlockHeight(ThisMap)

TileX=PlayerX/TileWidth
TileY=PlayerY/Tileheight

; Check what side the impact occured upon
; and display a message

If GetMapImpactLeft()
Print "Impact occured on the LEFT side"
hit=1
; Kill Tile to the left of our position
If (TileX-1)>-1

For lp=TileY To (PlayerY+HEight-1)/TileHeight
PokeLevelTile ThisMap,ThisLevel,TileX-1,lp,0
amm=amm+1
Next

EndIf

EndIf



If GetMapImpactRight()
Print "Impact occured on the RIGHT side"
hit=1
; Kill Tile to the left of our position
Login required to view complete source code




kevin

#1
The problem is in the logic of how the blocks  clear tally is done.

 When an impact occurs of any side of the ball, theres a bit of clearing code to clear the tiles along this impacted edge.  This was required as In some cases the ball will bit one block, but in others it'll hit two or more perhaps.

 Here's the current code that does this task for impacts down the LEFT edge of the ball..

PlayBASIC Code: [Select]
  For  lp=TileY To (PlayerY+HEight-1)/TileHeight
PokeLevelTile ThisMap,ThisLevel,TileX-1,lp,0
amm=amm+1
Next



Notice how the code clears the block regardless of whether it needs clearing anyway ?  That is to say, the code doesn't check if the block is already clear before clearing it.  It just clears it...  There's the problem !

Because it doesn't check if a clear is needed or not (if there was a block in that position to be cleared), this is making your impact counter "amm" give inflated results...

The solution is easy, we check if the block requires clearing, if it does, we clear it and Bump our impact counter "amm", if it doesn't we do nothing..

So for the left side it'll look a bit like this

PlayBASIC Code: [Select]
   For  lp=TileY To (PlayerY+HEight-1)/TileHeight
; check if the tile is Not clear (not tile 0)
If PeekLevelTile(ThisMap,ThisLevel,TileX-1,lp)<>0
; if wasn't clear so we must have hit a block, so clear it
PokeLevelTile ThisMap,ThisLevel,TileX-1,lp,0
; bump the blocks killed/cleared counter for this update
amm=amm+1
endif
Next





The same problem  will occur for all side of the collision code.  But it's you job to fix those :)

RaverDave

Ah, now you might not believe me ;)
But I thought that might be the problem
Is the method I used for vars ok,can i just use 1 var now called amm and not amm2,amm3 and so forth?! Or am I right in having 4 different ones for each sides!

P.S..Happy New year and thanks for replying fast!

RaverDave

It works fine now anyhow,I wont change something that doesnt need fixing unless problems occur in the future. Ok time to finally get the ball bouncing,plus I need some cool better brick generator for their gfx(non random for instance) Yes i did manage to work out your code for right,top and bottom impacts! :D

kevin

For the block tally I'd prolly do it a bit differently.  I'd keep just one global variable that holds the Totaly_Active_tiles in the level.  Hence the number tiles that can be cleared (in your program you call this TotalTiles.   So when a collision occurs i'd simply decease this single counter, rather than having the separate counters.   But the result is about the same


i.e so a collision occurs on a edge it'd look like this now




For  lp=TileY To (PlayerY+HEight-1)/TileHeight
; check if the tile is Not clear (not tile 0)  
  If PeekLevelTile(ThisMap,ThisLevel,TileX-1,lp)<>0
   ; if wasn't clear so we must have hit a block, so clear it
   PokeLevelTile ThisMap,ThisLevel,TileX-1,lp,0
   
    ; decrease the total number of active tiles
      dec TotalTiles

 endif
 Next



RaverDave

#5
Yes! this is much neater,and I believe the dec command might just be a tad faster huh,of course I just created all them vars to trap out the bug that I ahd so I am gunna use these dec's right now!
The fun part is yet to come... Entering lines and lines of data to cater for 50 levels or so.. Thats gunna test my sanity somewhat
***Edit*** the var is actually tilenum,but its ok..I still understand! ;)

kevin

Ahh well, ya get that :)

 At this point though, I think i'd probably invest my time getting the mechanics of the game working as i wanted.  Before building lots of levels..

 I've found in the past that building the levels too early, often locks me into design that I end up butting heads with.  I.e. End up having to go back and makes changes to them for some change in my game.   Which is not only annoying but can be big of waste of time.

RaverDave

I am starting to realise this!! All the code works ok but its hard to modify already!without the levels in, I am realising I should have used types for the players ball for instance,that would allow easy implementation of multi-ball pickup

kevin

Quotehave used types for the players ball for instance,that would allow easy implementation of multi-ball pickup

Good idea !  You lucky though as it's a pretty short bit of code ATM, so it shouldn't take too long to convert the ball from variables over to a typed array.

RaverDave

#9
I had a crack at implementing type for ball yesterday,but it seemed to error indicating that the type didnt like being passed as a param to the handle player function..or something...

kevin

You shouldn't need to pass the entire "Ball Array" (assuming thats what your trying to do), just the index of the ball you wish to update within the array..


I'll write you an example in a minute

RaverDave

What would have been handy kevin,is a label before each data block, so you could restore <label> rather than having to deal with numbers!The problem I have is thati wanna use data statements to also create a colour index for the tiles,rather than them being random at the moment,i ripped out some code from the platform example withing pb to give the blocks that fade effect, but the colours are random at the moment..if i try to restore the data for a level at the moment it would take the data for the colour bricks into account also,making pretty undesirable results! I am gunna paste the code so far that I have... Its a pain coz I have had to backtrack alot to make room for more levels..

RaverDave

#12
PlayBASIC Code: [Select]
; PROJECT : mytest
; AUTHOR : raverdave
; CREATED : 01/01/2006
; EDITED : 01/01/2006

;

OpenScreen 640,480,32,2
;SetFPS 0
Mouse Off
ScreenVsync On

Global PlayerX=50
Global PlayerY=430
Global PlayerWidth =10
Global PlayerHeight =10
Global Speed=4
Global currlev=1
Global maxlev=99
Global tilenum=0
Global MyMap = GetFreeMap()
CreateMap MyMap,99
Global mapx=0
Global mapy=0
Global TileWidth=32
Global TileHeight=16
Global Number_of_tiles = 9
Global XVelo#=-4
Global Yvelo#=-4
Global yspeed#=-4
Global xspeed#=-4
maketiles()


Repeat
createnewlev()
Repeat
SetCursor 0,0
Cls 0
DrawMap MyMap,currlev,mapx,mapy
PLayerX,PLayerY=Handle_player(PLayerX,PLayerY,PLayerWIdth,PlayerHeight,Speed,MyMap,1)
X2=playerX+PlayerWidth
Y2=playerY+PlayerHeight
Ink RGB(0,0,0)
Box playerX,playerY,x2,y2,1
fakex=playerX+5
fakey=playerY+5
Ink RGB(255,255,255)
Circle fakex,fakey,5,1
v=ScanCode()
If v=16
quit=1
EndIf

SetCursor 40,0
Print tilenum

Sync
Until quit=1 Or tilenum<=0
Inc currlev
Until currlev>maxlev



Function Handle_player(PLayerX,PLayerY,WIdth,Height,Speed,ThisMap,ThisLevel)



; Store the players possible new position
NewX=PlayerX
NewY=PlayerY

; Handle the players Movement

NewY=PLayerY+yvelo#
NewX=PLayerX+XVelo#

If playerx<=0+playerwidth
xspeed#=4
xvelo#=xspeed#
EndIf
If playerx>=500
xspeed#=-4
xvelo#=xspeed#
EndIf
If playery<=0+playerheight
yspeed#=4
yvelo#=yspeed#
EndIf
If playery>=400
yspeed#=-4
yvelo#=yspeed#
EndIf

; ==========================
; Handle Collision
; ===========================
If CheckMapImpact(thisMap,currlev,PlayerX,playerY,NewX,NewY,Width,Height)

; If there was impact with the map, then read our
; new position back.
PlayerX=GetMapImpactX()
PlayerY=GetMapImpactY()

TileWidth=GetMapBlockWidth(ThisMap)
TileHeight=GetMapBlockHeight(ThisMap)

TileX=PlayerX/TileWidth
TileY=PlayerY/Tileheight

; Check what side the impact occured upon
; and display a message

If GetMapImpactLeft()
Print "Impact occured on the LEFT side"
hit=1
; Kill Tile to the left of our position
If (TileX-1)>-1

For lp=TileY To (PlayerY+HEight-1)/TileHeight
If PeekLevelTile(ThisMap,currlev,TileX-1,lp)<>0
PokeLevelTile ThisMap,currlev,TileX-1,lp,0
Dec tilenum
xspeed#=4
xvelo#=xspeed#
EndIf
Next

EndIf

EndIf



If GetMapImpactRight()
Print "Impact occured on the RIGHT side"
hit=1
; Kill Tile to the left of our position
If (TileX+1)=<GetLevelWidth(ThisMap,ThisLevel)

; Loop down the right edge of the players ball
For lp=TileY To (PlayerY+HEight-1)/TileHeight
If PeekLevelTile(ThisMap,currlev,TileX+1,lp)<>0
PokeLevelTile ThisMap,currlev,TileX+1,lp,0
Dec tilenum
xspeed#=-4
xvelo#=xspeed#
EndIf
Next
Login required to view complete source code



RaverDave

#13
As it stands there is just 1 level that gets cleared and loops back!This is done on purpose untill I figure out the rest. Some tidying up has been done,like functions to handle a new level and stuff

kevin

#14
Have a look see at this example/tutorial for a way to manage lots of ball objects..  

-> How To Handle More than One Object