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

#30
Jesus!of course!
Though testing it with this inI see still that some of the balls collisions are still missed sometimes, but not as much, maybe i am pushing its limits?? I dont know!
Try maxballs 15!
though i think it still showed bad at 9 or something..I dont know,I am really just testing its speed at the moment!
I thought it would be cool to show playbasics power to a few friends,and what better way than them seeing loads of generated balls destroying bricks!

RaverDave

#31
I have added a screenshot to show you,with just 5 balls
its deleted a brick from the middle of the cluster of 4,which should be impossible

RaverDave

#32
There is definately a problem, even with just 3 balls bouncing around! sometimes they go straight through a bunch of bricks, but they do eventually get destroyed?? weird eh?!
Seems happy as a lamb when its just the 2 of em!

RaverDave

#33
Okay,after abit of investigation,the problem seems to be with the PlayerWidth and PlayerHeight vars,if I keep these at 10 then it runs into problems, if I knock them down to 5 then its perfect (as it is now)?! Abit puzzling really,I have included all the source so far,if you press a during play it will put up a max of 25 balls and runs fine as is,changing the said vars to 10 or 15 even causes lots of problems!!


; PROJECT : Project1
; AUTHOR  : raverdave
; CREATED : 02/01/2006
; EDITED  : 03/01/2006

OpenScreen 640,480,32,2

;SetFPS 0
Mouse Off
ScreenVsync On

Global PlayerX=50
Global PlayerY=430
Global PlayerWidth =5
Global PlayerHeight =5
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
Global b
Global numofballs=1
Global maxballs=20
Type tBall
     Status
     Xpos,Ypos
   Width,Height
     SpeedX,SpeedY
     newx
     newy
 Image
 LifeTimer
 FlashToggle
EndType

; create an array to house our list of balls
Dim Balls(maxballs) As tBall



maketiles()


Repeat

; CReate the test Balls
testpos()

createnewlev()

Repeat
SetCursor 0,0
Cls 0
DrawMap MyMap,currlev,mapx,mapy


; loop through our list of balls
For b=0 To numofballs


; Call the MOve Ball function.

; This function steps the ball forward (along it's X+ Y speeds)
;and handles collision and rebound stuff all in one hit  

Move_Ball(b,MyMap,1)


; After it's Moved, we draw the ball  
Circle balls(b).xpos,balls(b).ypos,5,1


; check if balls is leaving the screen along the Y axis, if it does, just flip the Y speed
If balls(b).ypos<=0
 balls(b).speedy=4
EndIf

If balls(b).ypos>=480
balls(b).speedy=-4
EndIf


; check if balls is leaving the screen along the X axis, if it does, just flip the X speed
If balls(b).xpos<=0
 balls(b).speedx=4
EndIf

If balls(b).xpos>=640
balls(b).speedx=-4
EndIf

Next
If v=30 And numofballs<maxballs
newball()
EndIf


v=ScanCode()
If v=16
quit=1
EndIf


SetCursor 40,0
Ink RGB(255,255,255)
Print tilenum


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

Function Move_Ball(ThisBall,ThisMap,ThisLevel)


; Calc the New  X & Y positions of the ball....

NewX =Balls(ThisBall).Xpos  +  Balls(ThisBall).SpeedX
NewY =Balls(ThisBall).Ypos  +   Balls(ThisBall).SpeedY

; Get the WIDTH and HEIGHT OF our ball.  
; While At the moment this might be a bit of extra overkill, in the future
; you might decide that the balls can be different sizes.  
 Width = Balls(ThisBall).width
 Height= Balls(ThisBall).Height
 

; ==============================================================
; Collision -Check If this Movement will hit the Level
; ===========================================================
If CheckMapImpact(ThisMap,ThisLevel,balls(b).xpos,balls(b).ypos,NewX,NEwY,Width,Height)  

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

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

TileX=NewX/TileWidth  
TileY=NewY/Tileheight

If GetMapImpactLeft()
   Print "Impact occured on the LEFT side"  
If (TileX-1)>-1
  For  lp=TileY To (NewY+HEight-1)/TileHeight
   If PeekLevelTile(ThisMap,ThisLevel,TileX-1,lp)<>0
     PokeLevelTile ThisMap,ThisLevel,TileX-1,lp,0
      Dec tilenum
      balls(ThisBall).speedX=4
    EndIf
  Next
EndIf
EndIf


 
If GetMapImpactRight()
    Print "Impact occured on the RIGHT side"  
; 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 (NewY+HEight-1)/TileHeight
  If PeekLevelTile(ThisMap,ThisLevel,TileX+1,lp)<>0
   PokeLevelTile ThisMap,ThisLevel,TileX+1,lp,0
    Dec tilenum
    balls(ThisBall).speedX=-4
 EndIf
Next
EndIf

EndIf

If GetMapImpactTop()
 Print "Impact occured on the TOP side"  

; Kill Tile to the left of our position
If (TileY-1)>-1
For  Xlp=TileX To (NewX+Width-1)/TileWidth
If PeekLevelTile(ThisMap,ThisLevel,xlp,TileY-1)<>0
  PokeLevelTile ThisMap,ThisLevel,xlp,TileY-1,0
  Dec tilenum
  balls(ThisBall).speedy=4
 EndIf
Next
EndIf

EndIf


If GetMapImpactBot()
  Print "Impact occured on the Bottom side"

If (TileY+1)=<GetLevelHeight(ThisMap,ThisLevel)

  For  Xlp=TileX To (NewX+Width-1)/TileWidth
   If PeekLevelTile(ThisMap,ThisLevel,Xlp,TileY+1)<>0
     PokeLevelTile ThisMap,ThisLevel,Xlp,TileY+1,0
    Dec tilenum
    balls(ThisBall).speedy=-4
   EndIf
  Next
EndIf

EndIf
EndIf

;  Set the balls New Position

balls(ThisBall).xpos=NewX
balls(ThisBall).ypos=NewY


EndFunction

Function maketiles()
; Loop through and draw a series of randomly coloured Boxes to the screen
For lp=1 To Number_of_tiles
 xpos=lp*tileWidth
 r=Rnd(255)
 g=Rnd(255)
 b=Rnd(255)  
 BoxC Xpos,0,Xpos+TileWidth,TileHeight,1,RGB(r,g,b)
 col=RGB(r,g,b)
 c1=RGBFade(Col,100.0)
 ShadeBox xpos+1,ypos+1,Xpos+Tilewidth-1,Ypos+Tileheight-2,c1,c1,c2,c2  
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)

EndFunction

Function createnewlev()
tilenum=0
If currlev>1
reset()
Restore 0
currlev=1
PlayerX=50
PlayerY=430
EndIf

CreateLevel MyMap,currlev, 100,100
For Ylp=0 To 14
For Xlp=0 To 12
t=ReadData()
 If t>0
 tilenum=tilenum+1
PokeLevelTile MyMap,currlev,Xlp,ylp,t
EndIf
Next xlp
Next ylp
EndFunction

Function reset()
XVelo#=-4
Yvelo#=-4
yspeed#=-4
xspeed#=-4
PlayerX=50
PlayerY=430
EndFunction

Function testpos()
; Init Ball zero
balls(0).xpos=Rnd(320)
balls(0).ypos=400
balls(0).speedx=-4
balls(0).speedy=-4
balls(0).Width=PlayerWidth
balls(0).Height=PlayerHeight


; Init Ball 1
balls(1).xpos=Rnd(320)
balls(1).ypos=400
balls(1).speedx=4
balls(1).speedy=-4
balls(1).Width=PlayerWidth
balls(1).Height=PlayerHeight

EndFunction

Function dump()

EndFunction

Function newball()
Inc numofballs
balls(numofballs).xpos=320
balls(numofballs).ypos=400
balls(numofballs).speedx=-4
balls(numofballs).speedy=-4
balls(numofballs).Width=PlayerWidth
  balls(numofballs).Height=PlayerHeight
EndFunction



Rem levels data

Data 0,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,0
Data 0,1,2,0,0,0,0,0,0,0,0,0,0
Data 0,1,2,3,0,0,0,0,0,0,0,0,0
Data 0,1,2,3,0,0,0,0,0,0,0,0,0
Data 0,1,2,3,4,0,0,0,0,0,0,0,0
Data 0,1,2,3,4,0,0,0,0,0,0,0,0
Data 0,1,2,3,4,5,0,0,0,0,0,0,0
Data 0,1,2,3,4,5,6,0,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,8,8,8,8,8

Data 0,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,0
Data 0,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,0
Data 0,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,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0


kevin

Had a bit of a look, but this one seems to work as i'm expecting it too. So i dunno really.

I've change it to BOXES in this one which present the collision region better. The circles (you should really just images) are being centered around the X/Y location of the ball.  They really should be drawn from the Middle of the ball.  







; PROJECT : Project1
; AUTHOR  : raverdave
; CREATED : 02/01/2006
; EDITED  : 03/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
;Global b

Global numofballs=0

Global maxballs=20

Type tBall
    Status
    Xpos,Ypos
    Width,Height
    SpeedX,SpeedY
    newx
    newy
 Image
 LifeTimer
 FlashToggle
EndType

; create an array to house our list of balls
Dim Balls(maxballs) As tBall


maketiles()


; Create our default Ball #1
newball()


Repeat


createnewlev()

Repeat

; no need to clear the screen, when the map is being drawn full screen
;Cls 0
DrawMap MyMap,currlev,mapx,mapy

SetCursor 0,0



; loop through our FIRST ball to the max number of balls
For b=1 To numofballs


; Call the MOve Ball function.

; This function steps the ball forward (along it's X+ Y speeds)
;and handles collision and rebound stuff all in one hit  

Move_Ball(b,MyMap,1)


; After it's Moved, we draw the ball  

;Circle balls(b).xpos,balls(b).ypos,5,1
x1=balls(b).xpos
y1=balls(b).ypos
x2=x1+balls(b).Width
y2=y1+balls(b).Height

box x1,y1,x2,y2,1


; check if balls is leaving the screen along the Y axis, if it does, just flip the Y speed
If balls(b).ypos<=0 then  balls(b).speedy=4
If balls(b).ypos>=480 then balls(b).speedy=-4

; check if balls is leaving the screen along the X axis, if it does, just flip the X speed
If balls(b).xpos<=0 then  balls(b).speedx=4
If balls(b).xpos>=640 then balls(b).speedx=-4

Next

v=ScanCode()

If v=30 And numofballs<maxballs
newball()
EndIf


If v=16
quit=1
EndIf


SetCursor 40,0
Ink RGB(255,255,255)
Print tilenum


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

Function Move_Ball(ThisBall,ThisMap,ThisLevel)


; Calc the New  X & Y positions of the ball....
CurrentX =Balls(ThisBall).Xpos
CurrentY =Balls(ThisBall).Ypos

NewX =CurrentX  +  Balls(ThisBall).SpeedX
NewY =CurrentY  +   Balls(ThisBall).SpeedY

; Get the WIDTH and HEIGHT OF our ball.  
; While At the moment this might be a bit of extra overkill, in the future
; you might decide that the balls can be different sizes.  
  Width = Balls(ThisBall).width
  Height= Balls(ThisBall).Height


; ==============================================================
; Collision -Check If this Movement will hit the Level
; ===========================================================
If CheckMapImpact(ThisMap,ThisLevel,CurrentX,CurrentY,NewX,NEwY,Width,Height)  

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

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

TileX=NewX/TileWidth  
TileY=NewY/Tileheight

If GetMapImpactLeft()
;    Print "Impact occured on the LEFT side"  
 If (TileX-1)>-1
   For  lp=TileY To (NewY+HEight)/TileHeight
    If PeekLevelTile(ThisMap,ThisLevel,TileX-1,lp)<>0
      PokeLevelTile ThisMap,ThisLevel,TileX-1,lp,0
       Dec tilenum
        balls(ThisBall).speedX=4
     EndIf
   Next
 EndIf
EndIf



If GetMapImpactRight()
;     Print "Impact occured on the RIGHT side"  
; 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 (NewY+HEight)/TileHeight
    If PeekLevelTile(ThisMap,ThisLevel,TileX+1,lp)<>0
     PokeLevelTile ThisMap,ThisLevel,TileX+1,lp,0
      Dec tilenum
      balls(ThisBall).speedX=-4
   EndIf
  Next
 EndIf
EndIf


If GetMapImpactTop()
;   Print "Impact occured on the TOP side"  

; Kill Tile to the left of our position
 If (TileY-1)>-1
  For  Xlp=TileX To (NewX+Width)/TileWidth
   If PeekLevelTile(ThisMap,ThisLevel,xlp,TileY-1)<>0
      PokeLevelTile ThisMap,ThisLevel,xlp,TileY-1,0
      Dec tilenum
      balls(ThisBall).speedy=4
    EndIf
  Next
 EndIf

EndIf


If GetMapImpactBot()
;   Print "Impact occured on the Bottom side"

If (TileY+1)=<GetLevelHeight(ThisMap,ThisLevel)

  For  Xlp=TileX To (NewX+Width)/TileWidth
    If PeekLevelTile(ThisMap,ThisLevel,Xlp,TileY+1)<>0
       PokeLevelTile ThisMap,ThisLevel,Xlp,TileY+1,0
      Dec tilenum
      balls(ThisBall).speedy=-4
    EndIf
  Next
EndIf

EndIf
EndIf

;  Set the balls New Position

balls(ThisBall).xpos=NewX
balls(ThisBall).ypos=NewY


EndFunction

Function maketiles()
; Loop through and draw a series of randomly coloured Boxes to the screen
For lp=1 To Number_of_tiles
xpos=lp*tileWidth
r=Rnd(255)
g=Rnd(255)
b=Rnd(255)  
BoxC Xpos,0,Xpos+TileWidth,TileHeight,1,RGB(r,g,b)
col=RGB(r,g,b)
c1=RGBFade(Col,100.0)
ShadeBox xpos+1,ypos+1,Xpos+Tilewidth-1,Ypos+Tileheight-2,c1,c1,c2,c2  
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)

EndFunction

Function createnewlev()
tilenum=0
If currlev>1
reset()
Restore 0
currlev=1
PlayerX=50
PlayerY=430
EndIf

CreateLevel MyMap,currlev, 100,100
For Ylp=0 To 14
For Xlp=0 To 12
t=ReadData()
If t>0
tilenum=tilenum+1
PokeLevelTile MyMap,currlev,Xlp,ylp,t
EndIf
Next xlp
Next ylp
EndFunction

Function reset()
XVelo#=-4
Yvelo#=-4
yspeed#=-4
xspeed#=-4
PlayerX=50
PlayerY=430
EndFunction

Function testpos()
; Init Ball zero
balls(0).xpos=Rnd(320)
balls(0).ypos=400
balls(0).speedx=-4
balls(0).speedy=-4
balls(0).Width=PlayerWidth
balls(0).Height=PlayerHeight


; Init Ball 1
balls(1).xpos=Rnd(320)
balls(1).ypos=400
balls(1).speedx=4
balls(1).speedy=-4
balls(1).Width=PlayerWidth
balls(1).Height=PlayerHeight

EndFunction

Function dump()

EndFunction

Function newball()
Inc numofballs
balls(numofballs).xpos=320
balls(numofballs).ypos=400
balls(numofballs).speedx=-4
balls(numofballs).speedy=-4
  balls(numofballs).Width=PlayerWidth
  balls(numofballs).Height=PlayerHeight

EndFunction



Rem levels data

Data 0,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,0
Data 0,1,2,0,0,0,0,0,0,0,0,0,0
Data 0,1,2,3,0,0,0,0,0,0,0,0,0
Data 0,1,2,3,0,0,0,0,0,0,0,0,0
Data 0,1,2,3,4,0,0,0,0,0,0,0,0
Data 0,1,2,3,4,0,0,0,0,0,0,0,0
Data 0,1,2,3,4,5,0,0,0,0,0,0,0
Data 0,1,2,3,4,5,6,0,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,0,0,0,0,0
Data 0,1,2,3,4,5,6,7,8,8,8,8,8

Data 0,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,0
Data 0,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,0
Data 0,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,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0
Data 0,0,0,1,0,0,0,0,0,0,0,0,0







RaverDave

#35
Well thats odd,indeed it does work as expected, but why should it matter if it were a square or a circle?In fact remming out a shape so there is non atall would work, just that i wouldnt see it.hehehe....hmmmm

RaverDave

Well I am getting into the swing of things!
All the data statements have filnally gone and to load a new level its now a simple matter of reading from the level file! The function used is shown below..


Function createnewlev()
tilenum=0
thislevel=currlev
If currlev>1
 reset()
 currlev=1
 PlayerX=50
 PlayerY=430
EndIf
CreateLevel MyMap,currlev, 100,100
File$="arklev"
file$=file$+Str$(CURRLEV)
file$=FILE$+".dat"
ReadFile File$,1
For Ylp=0 To 15
 For Xlp=0 To 13
  t=Readint(1)
   If t>0
   tilenum=tilenum+1
   PokeLevelTile MyMap,currlev,Xlp,ylp,t
  EndIf
 Next xlp
Next ylp
closefile 1
waitkey
EndFunction

I wrote a small editor to achieve this which looks pretty nifty albeit primitive
Just hope the .dat extention is ok to use?! :D

kevin

You can use whatever extension you like.  

 It looks like it's coming  along fine, is there any reason why there's a "waitkey"  at the end of the routine ? :)

Also, will all levels be the same size ?

RaverDave

#38
yeh,the waitkey was put in there as a kindof "damn why doesnt it load god damnit" kind of test!! I didnt know if it was reading in the data correctly..Anyhow its removed now as I am confident things are ok!
And of course things start so quickly I needed it!
The size, Well the play area is reduced to try and emulate that of the arkanoid area,13*15 max.. I dont like brick games with too many bricks onscreen myself.
Take a look at the pic,although its abit beta-ish looking.
Now I need to introduce a system to make bricks having to be hit more than once, and having some bricks release powerups of course. Taking your advice then and only then will the various levels,maybe 50 or so, be introduced!