[pbcode]
; PROJECT : Project1
; AUTHOR : raverdave
; CREATED : 02/01/2006
; EDITED : 11/01/2006
OpenScreen 640,480,32,2
SetFPS 60
ScreenVsync On
Mouse Off
Type TPaddles
X#,Y#,SizeX#,SizeY#
EndType
Dim Paddles(2) As Tpaddles
Paddles(1).SizeX#=64: Paddles(1).SizeY#=10
paddles(1).y#=400
Dim map(64,64)
Dim powerdat(64,64)
Dim hitdat(64,64)
Global checked=0
Global currvel=-4
Global PlayerX=50
Global PlayerY=430
Global PlayerWidth =10
Global PlayerHeight =10
Global s$
Global Speed=4
Global currlev=1
Global maxlev=99
Global tilenum=0
Global MyMap = GetFreeMap()
Global bottplay=400
CreateMap MyMap,99
Global currvel=-4
Global mapx=0
Global mapy=0
Global TileWidth=32
Global TileHeight=16
Global Number_of_tiles = 9
Global schange=0
Global thislevel
Global b
Global numofballs=0
Global maxballs=25
Global gamemode=1
Type tBall
Status
Xpos#,Ypos#
Width,Height
SpeedX#,SpeedY#
newx#
newy#
ballspeed#
ballangle#
Image
LifeTimer
FlashToggle
EndType
; create an array to house our list of balls
Dim Balls(maxballs) As tBall
maketiles()
; CReate the test Balls
testpos()
createfx1()
Global width=GetImageWidth(40)
Repeat
loadlev()
gamemode=1
Repeat
LockBuffer
Cls 0
SetCursor 0,0
DrawMap MyMap,currlev,mapx,mapy
Text 300,450,FPS()
showdecors()
If gamemode=1
balls(0).speedy=0
balls(0).xpos=paddles(1).x#+paddles(1).sizex#/2
balls(0).ypos=paddles(1).y#-10
EndIf
; loop through our list of balls
For b=0 To numofballs
If gamemode=0
Move_Ball(b,MyMap,currlev)
EndIf
;drawball
DrawImage 40,balls(b).xpos,balls(b).ypos,1
;Circle balls(b).xpos,balls(b).ypos,5,1
;draw paddle
X#=Paddles(1).X#: Y#=Paddles(1).Y#
Box X#,Y#,X#+Paddles(1).SizeX#,Y#+Paddles(1).SizeY#,1
If balls(b).ypos<=0
balls(b).speedy=-balls(b).speedy
checked=0
EndIf
If balls(b).ypos>=bottplay+64
balls(b).speedy=-balls(b).speedy
checked=0
EndIf
If balls(b).xpos<=0+tilewidth
balls(b).speedx=-balls(b).speedx
checked=0
EndIf
If balls(b).xpos>=tilewidth*14-width
balls(b).speedx=-balls(b).speedx
checked=0
EndIf
If gamemode=0
If PointInBox(balls(b).xpos,balls(b).ypos+10,paddles(1).x#,paddles(1).y#,paddles(1).x#+paddles(1).sizex#,paddles(1).y#+paddles(1).sizey#)
currvel=Rnd(1)+1
If currvel=0 Then currvel=1
balls(b).speedy=-Abs(currvel)
checked=1
Inc schange
SetCursor 350,460
Print "changed= "+Str$(schange)
EndIf
EndIf
Next
control()
SetCursor 500,400
Print balls(b).speedy
SetCursor 450,440
Print currvel
Text 300,400,s$
UnLockBuffer
Sync
Until quit=1 Or tilenum<=0
Until currlev>maxlev
Function control()
v=ScanCode()
If v=30 And numofballs<maxballs
newball()
EndIf
If LeftKey()=1
Paddles(1).x#=Paddles(1).x#-4
EndIf
If RightKey()=1
Paddles(1).x#=Paddles(1).x#+4
EndIf
If v=16
quit=1
EndIf
If v=57 And gamemode=1
gamemode=0
currvel=Rnd(5)+1
s$="Hit bat"
print"nigga"
If currvel=0 Then currvel=1
balls(b).speedy=-Abs(currvel)
checked=1
EndIf
EndFunction
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
hitdat(tilex-1,lp)=hitdat(tilex-1,lp)-1
balls(thisball).speedx=4
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
balls(thisball).speedx=-4
checked=0
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=Abs(balls(thisball).speedy)
checked=0
SetCursor 320,10
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=-Abs(balls(thisball).speedy)
checked=0
SetCursor 320,10
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
EndFunction
Function maketiles()
; Loop through and draw a series of randomly coloured Boxes to the screen
Data RGB(255,255,255) ` White Block
Data RGB(255,20,25) ` RED/Block
Data RGB(255,255,25) ` Yellow Block
Data RGB(25,255,25) ` GREEN
Data RGB(255,25,255) ` PURPLE
Data RGB(55,95,155) ` PURPLE
Data -1
For lp=1 To Number_of_tiles
xpos=lp*tileWidth
Col=ReadData()
BoxC xpos+0,ypos+0,Xpos+tilewidth,Ypos+tileheight,1,RGBFade(Col,50.0)
c1=RGBFade(Col,100.0)
;BoxC xpos,ypos,tilewidth,tileheight,RGB(col)
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()
thislevel=currlev
tilenum=0
If currlev>2
reset()
Restore 0
currlev=1
thislevel=currlev
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 loadlev()
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)
p=ReadInt(1)
d=ReadInt(1)
map(xlp,ylp)=t
powerdat(xlp,ylp)=p
hitdat(xlp,ylp)=d
If t>0
tilenum=tilenum+1
PokeLevelTile MyMap,currlev,Xlp,ylp,t
EndIf
Next xlp
Next ylp
CloseFile 1
EndFunction
Function reset()
XVelo#=-4
Yvelo#=-4
yspeed#=-4
xspeed#=-4
PlayerX=50
PlayerY=430
EndFunction
Function showdecors()
DrawImage 1,16,0,0
DrawImage 2,(14*32),0,0
DrawImage 3,(14*32+16),0,0
EndFunction
Function createfx1()
CreateImage 1,16,bottplay
CreateImage 2,16,bottplay
CreateImage 40,playerwidth,playerheight
; Tell PB to erdirect all drawing command to draw upon this image and now the screen..
RenderToImage 1
For lp =0 To bottplay
GouraudStripH 0,RGB(10,10,10),16,RGB(91,90,94),0+lp
Next
CopyImage 1,2
CreateImage 3,228,bottplay
RenderToImage 3
For lp =0 To 228
GouraudStripV 0,RGB(0,0,200),bottplay,RGB(0,0,10),0+lp
Next
RenderToImage 40
CircleC playerwidth/2,playerheight/2,playerwidth/2,1,RGB(255,255,255)
RenderToScreen
EndFunction
Function testpos()
; Init Ball zero
balls(0).xpos=320
balls(0).ypos=1
balls(0).speedx=-4
balls(0).speedy=-1
balls(0).Width=PlayerWidth
balls(0).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
[/pbcode]
I did get further but a crash with the gui put an end to that
Just mess around with it when you have some real spare time! There's no rush as I am working hard on the editor, if the editor becomes user friendly enough it might just be intergrated into the game to allow for user created levels!
Hi!
Great work!
runs with 120
Greetings
stef
Dave,
Just had a quickr glance, and it's looking good... Keep at it !
if you want to balls to travel any speed you'll have to modify the collision code a little. That's about it. Currently, when an impact occurs. The code inverts the balls speed along either the X or Y axis. depending upon what side the impact occured. The problem is, it sets the inverted direction using an absolute value. Which is not what we want. It needs to flip the direction.
; For example when the ball has a right hand impact, it then set it's new speed on the X axis to -4
i.e
balls(thisball).speedx=-4
It also does the same for the Y axis
This is fine if you want the balls to only ever move at either -4 (left) or 4 (right) along either axis.. But what would happen if we set the ball a custom speed of say 1.5 on the X axis and -2 on y (when we launching a ball that is).
ie.
balls(thisball).speedx=1.5
balls(thisball).speedy=-2
So the ball would travel along this path, UNTIL it hits a tile (or the screen edge). Where our rebound code, changes thhe Speed to either -4 or 4. Depending on what side it hit..
To fix it... Simple
All we do is reflect the speed when and impact occurs.. like this
balls(thisball).speedx=balls(thisball).speedx * -1
What this does is takes the current Speed valule and negates it. Which will will us the rebounded speed. No matter how fast it's moving.
Have a play !
huh?! I havent done much! :D
Well I will mess around anyhow, thanks for your help so far coz I wouldnt have got even this far without it! ;) I sometimes feel like just jacking it in and accepting that I just aint good enough though
Hmmm, I am having some odd results with that method,sometime it will destroy quite a few before it bothers rebounding from the side of a brick
[pbcode]
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
hitdat(tilex-1,lp)=hitdat(tilex-1,lp)-1
balls(thisball).speedx=balls(thisball).speedx *-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
balls(thisball).speedx=balls(thisball).speedx *-1
checked=0
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
SetCursor 320,10
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
SetCursor 320,10
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
EndFunction
[/pbcode]
This is what I have in the function, at 1st glance it looks ok, but after abit you realise that its not desirable!
Next hint...
Why are these "NewX" and "NewY" still INTEGERS ? :)
balls(ThisBall).xpos=NewX
balls(ThisBall).ypos=NewY
I dunno :D
but adding a # to all of them,like i just did, causes the collisions not to occur atall!!lol
Hmmmm..actually why not,I mean they aint floats coz I aint using floats yet?right?? So actually they should still be integers..Why would that be the problem??
Looking at the declaration of your type.. Yep their FLOATS..
[pbcode]
Type tBall
Status
Xpos#,Ypos#
Width,Height
SpeedX#,SpeedY#
newx#
newy#
ballspeed#
ballangle#
Image
LifeTimer
FlashToggle
EndType
[/pbcode]
damnit!I 4got about that, they were put in just before a crash!Anyhow I took them out now, but still the same problem! hehe
Just curious,what time is it where you are? Its 5:09AM here,I been awake all night working on the editor mostly! :D:D
Life's too short
Just had a look see. The drama you mention (if you swap them all to floats) is cause due to rounding rounds when dealing with floats. The solution was to Store the moved balls position in a floats NEWX# & NEwY#, but perform the collision on integer versions of NEWX + NEWY. This Avoids avoid any possible roungin errors. And basic keep the code much the same
Bellow is a patched/hacked version that alllows balls to move at any angle + speed.
OpenScreen 640,480,32,2
SetFPS 60
ScreenVsync On
Mouse Off
Type TPaddles
X#,Y#,SizeX#,SizeY#
EndType
Dim Paddles(2) As Tpaddles
Paddles(1).SizeX#=64: Paddles(1).SizeY#=10
paddles(1).y#=400
Dim map(64,64)
Dim powerdat(64,64)
Dim hitdat(64,64)
Global checked=0
Global currvel=-4
Global PlayerX=50
Global PlayerY=430
Global PlayerWidth =10
Global PlayerHeight =10
Global s$
Global Speed=4
Global currlev=1
Global maxlev=99
Global tilenum=0
Global MyMap = GetFreeMap()
Global bottplay=400
CreateMap MyMap,99
Global currvel=-4
Global mapx=0
Global mapy=0
Global TileWidth=32
Global TileHeight=16
Global Number_of_tiles = 9
Global schange=0
Global thislevel
Global b
Global numofballs=0
Global maxballs=25
Global gamemode=1
Type tBall
Status
Xpos#,Ypos#
Width,Height
SpeedX#,SpeedY#
newx#
newy#
speed#
angle#
Image
LifeTimer
FlashToggle
EndType
; create an array to house our list of balls
Dim Balls(maxballs) As tBall
maketiles()
; CReate the test Balls
testpos()
createfx1()
Global width=GetImageWidth(40)
Repeat
loadlev()
gamemode=1
Repeat
LockBuffer
Cls 0
SetCursor 0,0
DrawMap MyMap,currlev,mapx,mapy
Text 300,450,FPS()
showdecors()
If gamemode=1
balls(0).speedy=0
balls(0).xpos=paddles(1).x#+paddles(1).sizex#/2
balls(0).ypos=paddles(1).y#-10
EndIf
; loop through our list of balls
For b=0 To numofballs
If gamemode=0
Move_Ball(b,MyMap,currlev)
EndIf
;drawball
DrawImage 40,balls(b).xpos,balls(b).ypos,1
;Circle balls(b).xpos,balls(b).ypos,5,1
;draw paddle
X#=Paddles(1).X#: Y#=Paddles(1).Y#
Box X#,Y#,X#+Paddles(1).SizeX#,Y#+Paddles(1).SizeY#,1
If balls(b).ypos<=0
balls(b).speedy=-balls(b).speedy
checked=0
EndIf
If balls(b).ypos>=bottplay+64
balls(b).speedy=-balls(b).speedy
checked=0
EndIf
If balls(b).xpos<=0+tilewidth
balls(b).speedx=-balls(b).speedx
checked=0
EndIf
If balls(b).xpos>=tilewidth*14-width
balls(b).speedx=-balls(b).speedx
checked=0
EndIf
If gamemode=0
If PointInBox(balls(b).xpos,balls(b).ypos+10,paddles(1).x#,paddles(1).y#,paddles(1).x#+paddles(1).sizex#,paddles(1).y#+paddles(1).sizey#)
currvel=Rnd(1)+1
If currvel=0 Then currvel=1
balls(b).speedy=-Abs(currvel)
checked=1
Inc schange
SetCursor 350,460
Print "changed= "+Str$(schange)
EndIf
EndIf
Next
control()
SetCursor 500,400
Print balls(b).speedy
SetCursor 450,440
Print currvel
Text 300,400,s$
UnLockBuffer
Sync
Until quit=1 Or tilenum<=0
Until currlev>maxlev
Function control()
v=ScanCode()
If v=30 And numofballs<maxballs
newball()
EndIf
If LeftKey()=1
Paddles(1).x#=Paddles(1).x#-4
EndIf
If RightKey()=1
Paddles(1).x#=Paddles(1).x#+4
EndIf
If v=16
quit=1
EndIf
If v=57 And gamemode=1
gamemode=0
currvel=Rnd(5)+1
s$="Hit bat"
print"nigga"
If currvel=0 Then currvel=1
balls(b).speedy=-Abs(currvel)
checked=1
EndIf
EndFunction
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
balls(thisball).speedx=balls(thisball).speedx *-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
balls(thisball).speedx=balls(thisball).speedx *-1
checked=0
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
SetCursor 320,10
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
SetCursor 320,10
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#
EndFunction
Function maketiles()
; Loop through and draw a series of randomly coloured Boxes to the screen
Data RGB(255,255,255) ` White Block
Data RGB(255,20,25) ` RED/Block
Data RGB(255,255,25) ` Yellow Block
Data RGB(25,255,25) ` GREEN
Data RGB(255,25,255) ` PURPLE
Data RGB(55,95,155) ` PURPLE
Data -1
For lp=1 To Number_of_tiles
xpos=lp*tileWidth
Col=ReadData()
BoxC xpos+0,ypos+0,Xpos+tilewidth,Ypos+tileheight,1,RGBFade(Col,50.0)
c1=RGBFade(Col,100.0)
;BoxC xpos,ypos,tilewidth,tileheight,RGB(col)
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()
thislevel=currlev
tilenum=0
If currlev>2
reset()
Restore 0
currlev=1
thislevel=currlev
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 loadlev()
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)
p=ReadInt(1)
d=ReadInt(1)
map(xlp,ylp)=t
powerdat(xlp,ylp)=p
hitdat(xlp,ylp)=d
If t>0
tilenum=tilenum+1
PokeLevelTile MyMap,currlev,Xlp,ylp,t
EndIf
Next xlp
Next ylp
CloseFile 1
EndFunction
Function reset()
XVelo#=-4
Yvelo#=-4
yspeed#=-4
xspeed#=-4
PlayerX=50
PlayerY=430
EndFunction
Function showdecors()
DrawImage 1,16,0,0
DrawImage 2,(14*32),0,0
DrawImage 3,(14*32+16),0,0
EndFunction
Function createfx1()
CreateImage 1,16,bottplay
CreateImage 2,16,bottplay
CreateImage 40,playerwidth,playerheight
; Tell PB to erdirect all drawing command to draw upon this image and now the screen..
RenderToImage 1
For lp =0 To bottplay
GouraudStripH 0,RGB(10,10,10),16,RGB(91,90,94),0+lp
Next
CopyImage 1,2
CreateImage 3,228,bottplay
RenderToImage 3
For lp =0 To 228
GouraudStripV 0,RGB(0,0,200),bottplay,RGB(0,0,10),0+lp
Next
RenderToImage 40
CircleC playerwidth/2,playerheight/2,playerwidth/2,1,RGB(255,255,255)
RenderToScreen
EndFunction
Function testpos()
; Init Ball zero
balls(0).xpos=320
balls(0).ypos=1
balls(0).speedx=-4
balls(0).speedy=-1
balls(0).Width=PlayerWidth
balls(0).Height=PlayerHeight
EndFunction
Function dump()
If (balls(b).ypos+balls(b).height)>Paddles(1).Y#
If (balls(b).ypos-balls(b).height)<Paddles(1).Y#+Paddles(1).SizeY#
If balls(b).xpos-balls(b).width<Paddles(1).X#+paddles(1).sizex#
If balls(b).xpos>Paddles(1).X#
currvel=Rnd(5)+1
s$="Hit bat"
print"nigga"
If currvel=0 Then currvel=1
balls(b).speedy=-Abs(currvel)
checked=1
Inc schange
SetCursor 350,460
Print "changed= "+Str$(schange)
EndIf
EndIf
EndIf
EndIf
EndFunction
Function newball()
Inc numofballs
balls(numofballs).xpos=320
balls(numofballs).ypos=400
; Calc a rondom angle facing upwards
Balls(numOfBalls).Angle#=rndrange(180+45,360-45)
Speed#=rndrange(2,5)
balls(numofballs).speed =Speed#
balls(numofballs).speedx =Cos(Balls(numOfBalls).Angle#)*Speed#
balls(numofballs).speedY =Sin(Balls(numOfBalls).Angle#)*Speed#
;balls(numofballs).speedx=
;balls(numofballs).speedy=-4
balls(numofballs).Width=PlayerWidth
balls(numofballs).Height=PlayerHeight
EndFunction
well,this still has the same problem,sometimes a few are destroyed before it bothers to rebound, I saw this problem without floats also! The "a" key still works,best to have to or 3 onscreen so your not waiting about to realise this! But eventually you would see the problem with just 1 ball!
Also I can tell you its only occured since using the:
balls(thisball).speedx=balls(thisball).speedx *-1
methods
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!
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.
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
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
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 ???
Ah,i see now,yes, it can hit 2 bricks at once!, but how is this avoided?
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
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 ?
/me Scratches head and acts dumb (or am I acting!!) :D
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
^
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.
Well,as it stands they do both get ripped,thats the problem!
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
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..
actually scrap that,my balls just started to go sideways only..lol..hmm maybe the vars in the type idea might work?
Examine this. Try playing with the for next loop end counter.. try values from 1 to 3 - it's set to 2 at the moment
a=10
print "Starting A="+Str$(a)
For lp=1 to 2
a=a*-1
print "The state of A Inside the loop ="+Str$(a)
next
print "Final A="+Str$(a)
sync
waitkey
Notice how the number of loops affects the ultimate sign of the A variable.
Now relate this back the ball collision fragments of code...
If the ball hits two blocks on the Right hand side say.
Then the loop runs down this right edge clearing each block.
Within the clear loop it flips the SIGN the speedX each loop...
Obviously, if it clears two blocks, then the Xspeed sign will be flipped
and then flipped back.. Hence the logic error..
So, the balls speed only needs to be flipped when a collision registers, not during the block clearing loop itself.
Finally!! I might have fixed it!!
ok i put for example the type looks like this:
ype tBall
Status
Xpos#,Ypos#
Width,Height
SpeedX#,SpeedY#
newx#
newy#
speed#
angle#
hittop
hitbottom
hitside
Image
LifeTimer
FlashToggle
EndType
[QUOTE]
Now then when a impact occurs i set whatever to 1 like so:
[CODE]
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
balls(thisball).hitside=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
Ok then I check if its equal to 1 outside the for next loop of that functioon,near the bottom, like so:
If balls(thisball).hitside=1
balls(thisball).hitside=0
balls(thisball).speedx=balls(thisball).speedx *-1
EndIf
EndFunction
And then the speed is changed!
I do this for the tophit and bottomhit fileds aswell!
Maybe this works,it seems to work!
Bingo... in a round about kind of way..
or you could do this way
if GetMapImpactLeft()
; Print "Impact occured on the LEFT side"
; Do the Balls Rebound
balls(thisball).speedx=balls(thisball).speedx *-1
; Now do the loop to clear the tiles
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
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
Oh my,thats cruelly shorter!
I feel inadequate!
maybe mine has the advantage of being more modular..lol
Oh NO!! It worked, then as I was admiring the balls rebounding,one of them stopped dead!lol,on a brick, it only moved again when another ball destroyed that brick..
I have implemented your way,cleaned the code up,now then very rarely it tends to bounce off a brick but not destroy the brick,I sometimes have to watch it for ages before this happens,to be sure! But yep its definately hapenning! Is this another simple logic over-sight?
Well, been working away at the code and the editor on and off all day, I implemented non destructable bricks, now this has shown a major snag in all this sytem, the ball on a given angle can get stuck in a rebound! But I think only if there is a 1 brick gap between the columns! So its gunna need careful planning or some hack to stop this
Nah! It gets stuck in a rebound no matter what! I have presented a snapshot of an example of where it would get cought in a rebound loop! Its the area I have put a dimaond shape in black, not necessarily in this way does it loop but its typical example!
So the aim of the level would be to get to the top and destroy the only destructible bricks on that level (red and yellow) the white ones are not destructable
If it gets stuck at the screen edges, that's most probably caused by the edge flip not bothering to reposition the ball inside the egde, instead it just flips the speed.
When the balls hits the edge (any of them) it should be re position the bal inside the edge along the axis.
Ie.
If BallX > RightEdge
; POsition ball so it can't cause a collision next frame
BallX = RightEdge-BallWidth
; flip the speed
BallSpeedX=BallSpeedX * -1
endif
well i tried it,eventually it got stuck again, after clearing the level 14 times though.. :/
I didnt mean it gets stuck stuck, it goes in a continues rebound loop! if you look at the snapshot closely you will see i have shown this with black lines(sorta middle left hand side) So I am saying the ball hits the side, then the bottom of a brick, rebounds to hit the side of the brick below that, rebounds to hit the top of the brick below that, then back to the side! In a diamond shape