News:

Building a 3D Ray Tracer  By stevmjon

Main Menu

Help with Pong / Arkanoid the source code

Started by RaverDave, January 11, 2006, 10:33:33 PM

Previous topic - Next topic

RaverDave

AAaaarrgghhh,I am so stuck! your code doesnt react all the time,it sometimes doesnt respond untill its wiped out a few without rebounding, so what i did was change back to the abs method,so for example:

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
 hitdat(tilex-1,lp)=hitdat(tilex-1,lp)-1

    balls(thisball).speedx#=Abs(balls(thisball).speedx#)
    Inc score
    s$="hit brick"
    checked=0
    SetCursor 320,10
    If hitdat(tilex-1,lp)<=0
    PokeLevelTile ThisMap,ThisLevel,TileX-1,lp,0
     Dec tilenum
    EndIf
  If powerdat(tilex-1,lp)<>0
   s$="Wooohoooo!!!"
EndIf
  EndIf
Next
EndIf
EndIf




Now this works 99.9% of the time, the 0.1% of the time, the ball stops dead on contact with a brick! I have the values of this impact,these are:


speedx#=0.487478
speedy#=3.97018
speed#=4.0
angle#=263.0

So I have no idea why the ball stops dead rarely!

RaverDave

#16
Oh my! I am getting sick of this code,been at it days,trying different ways, all I know is since using floats I have problems! The last 'hacked' code you sent kevin just doesnt work right,if you leave it running long enough,perhaps also press 'a' to add more balls,just so your not waiting too long! then you will see that for some odd reason they dont bounce off the bricks sometimes, yet the bricks get destroyed!
***edit**
I even went back to the Abs() way, and though they bounce ok this way, they just stop dead after apparently hitting a brick sometimes.

kevin

#17
This is logic problem.  I can give you the answer, but it's right there in front you.  I want you to understand why it occurs and how not to make it hapen in the future :)



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

    hitdat(tilex-1,lp)=hitdat(tilex-1,lp)-1

   balls(thisball).speedx#=balls(thisball).speedx#*-1      

   Inc score
   s$="hit brick"
   checked=0
   SetCursor 320,10
   If hitdat(tilex-1,lp)<=0
       PokeLevelTile ThisMap,ThisLevel,TileX-1,lp,0
        Dec tilenum
   EndIf
 If powerdat(tilex-1,lp)<>0
  s$="Wooohoooo!!!"
EndIf
 EndIf
Next
EndIf
EndIf







Hint,

 1) Is it possible for the ball ot Hit more than 1 block

 2) What happens to a number when it's multed by -1 MORE than ONCE ?

 a=10
 a=a*-1
 print a
 a=a*-1
 print a
sync
waitkey

 That is your problem !   Look through the logic of the rebound code (in each direction) and you'll hopefully see it.  




NOTE:  If you ABS() the sign of the speed on either axis, your rounding the balls path, which is not what you want.  And not the problem

RaverDave

#18
Nope,lol..I cant see it :(
looks fine to me..
You do know that hitdat() has only a value of 1 in at the start right(in this level anyhow)?so on the 1st hit it will be 0

kevin

Questions,

1) Is it possible for the ball to Hit more than 1 block    ????

2) What happens to a number when it's multed by -1 MORE than ONCE ???

RaverDave

Ah,i see now,yes, it can hit  2 bricks at once!, but how is this avoided?

RaverDave

Let me say that I never did like the fact that you can destroy 2 at once!
I have had this problem with blitz basic,dark basic..you name it,but never found a way to avoid this

kevin

Almost there, it's all about where the Balls speed is being flipped..

 Does the balls direction need to be changed for each block it hits, or just change when a collision occurs of a side ?

RaverDave

/me Scratches head and acts dumb (or am I acting!!) :D

RaverDave

#24
All I know is that this destroying 2 occurs for example as illustrated
I am not sure how to avoid this, afterall in reality it has the right quite frankly to do so!






|__|__|

   o
   ^


kevin

QuoteLet me say that I never did like the fact that you can destroy 2 at once!
I have had this problem with blitz basic,dark basic..you name it,but never found a way to avoid this

  The language is totally irrelevant, programming is always a question of  logic.

  If you want the ball to only clear one block, you'll have to work out what block on a side the of the ball,  that has been mainly impacted by it.    Once derived, clear that block.      

  One way of doing that is deciphering this is via counting the number of pixels along the balls collided position that it shares against it's blocks (down whatever edge)  The highest one, gets ripped.  If there's a draw, the both get ripped.  In tha case the ball has hit perfectly spread across the joining of two blocks.

  Anyway, The logic above is simply clearing any tiles on whatever side of the ball comes in contact with.

RaverDave

Well,as it stands they do both get ripped,thats the problem!

RaverDave

Right,taking into account the points, the function has now been modified!!

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()

NewX#=NewX
NewY#=NewY

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
 hitdat(tilex-1,lp)=hitdat(tilex-1,lp)-1
  Inc score
  ; balls(thisball).speedx=balls(thisball).speedx *-1
    hitside=1
bottom=1
    checked=0
    SetCursor 320,10
    If hitdat(tilex-1,lp)<=0
    PokeLevelTile ThisMap,ThisLevel,TileX-1,lp,0
     Dec tilenum
    EndIf
  If powerdat(tilex-1,lp)<>0
   s$="Wooohoooo!!!"
EndIf
  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
 hitdat(tilex+1,lp)=hitdat(tilex+1,lp)-1
  Inc score
;   balls(thisball).speedx=balls(thisball).speedx *-1
  checked=0
  hitside=1
  If hitdat(tilex+1,lp)<=0
    PokeLevelTile ThisMap,ThisLevel,TileX+1,lp,0
 
    Dec tilenum
  EndIf
  SetCursor 320,10
  If powerdat(tilex+1,lp)<>0
    s$="Wooohoooo!!!"
EndIf
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
hitdat(xlp,tiley-1)=hitdat(xlp,tiley-1)-1
; balls(thisball).speedy=balls(thisball).speedy * -1
checked=0
Inc score
hittop=1
  If powerdat(xlp,tiley-1)<>0
   s$="Wooohoooo!!!"
EndIf

If hitdat(xlp,tiley-1)<=0
 PokeLevelTile ThisMap,ThisLevel,xlp,TileY-1,0
  Dec tilenum
EndIf
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
  hitdat(xlp,tiley+1)=hitdat(xlp,tiley+1)-1
;     balls(thisball).speedy=balls(thisball).speedy * -1
  checked=0
   Inc score
hitbottom=1
If hitdat(xlp,tiley+1)<=0
  PokeLevelTile ThisMap,ThisLevel,Xlp,TileY+1,0
    Dec tilenum
  EndIf
  If powerdat(Xlp,tiley+1)<>0
    s$="Wooohoooo!!!"
EndIf
 
 EndIf
Next
EndIf

EndIf
EndIf

;  Set the balls New Position

balls(ThisBall).xpos=NewX#
balls(ThisBall).ypos=NewY#
If hittop=1
hittop=0
balls(thisball).speedy=balls(thisball).speedy * -1

EndIf
If hitbottom=1
hittbottom=0
balls(thisball).speedy=balls(thisball).speedy * -1

EndIf
If hitside=1
hitside=0
balls(thisball).speedx=balls(thisball).speedx *-1
EndIf
EndFunction



Can you see what i have done?
take note of this bit:

If hittop=1
hittop=0
balls(thisball).speedy=balls(thisball).speedy * -1

EndIf
If hitbottom=1
hittbottom=0
balls(thisball).speedy=balls(thisball).speedy * -1

EndIf
If hitside=1
hitside=0
balls(thisball).speedx=balls(thisball).speedx *-1
EndIf

RaverDave

This seems to work! but its hardly desirable,thoough it works! I am not sure how the reaction will be with various balls,maybe i should change the global vars to fileds within the ball type! yes this could be better..

RaverDave

actually scrap that,my balls just started to go sideways only..lol..hmm maybe the vars in the type idea might work?