Try this. I know this works.
; Press space to initiate interactive mode!
Const GW = 320
Const GH = 240
Const TexSize = 256 ; Reduce this to 256 for extra FPS.
Const ScrollRate = 4 ; Number of pixels to scroll per frame.
Const MIN_BALL_SPEED = 4
Const MAX_BALL_SPEED = 8
; Init
Graphics GW, GH, 16, 1
SeedRnd MilliSecs()
BLx = GW/2
BLy = GH/2
BLvx = -1
BLvy = -1
BallWidth = GW/64
BallSpeed = MIN_BALL_SPEED
PaddleWidth = GW/64
PaddleHeight = GH/8
P1x = GW/32
P2x = GW-((GW/32)+PaddleWidth)
PaddleSpeed = MIN_BALL_SPEED
P1AI = True ; Enable to have P1 controlled by AI by default. Disable to have P1 controlled by mouse.
; Precalc
Dim TxL(GW, GH)
Dim TyL(GW, GH)
For By = 0 To GH-1
For Bx = 0 To GW-1
YLoc# = Float(By) / Float(GH)
XLoc# = Float(Bx) / Float(GW)
Radius# = YLoc# * Float(TexSize)
Angle# = XLoc# * 360.0
TxL(Bx, By) = Floor((TexSize/2.0) + (Radius# * Cos(Angle)))
TyL(Bx, By) = Floor((TexSize/2.0) + (Radius# * Sin(Angle)))
Next
Next
; Text
Dim Txt$(14)
Data "!", "?", ":)", ":(", "X", "O", "1", "0", "-", "+", "<", ">", "", "/"
For D = 0 To 13
Read Txt$(D)
Next
; Font
FONT_Arial1 = LoadFont("Arial Black", 30, False, False, False)
FONT_Arial2 = LoadFont("System", GH/6, False, False, False)
; Texture
Tex = CreateImage(TexSize, TexSize)
TexBuffer = ImageBuffer(Tex)
TexSize2 = TexSize / 2
; Timer init
Min_Frame_Time = Floor(1000.0/Float(MAX_FPS))
Frame_Period = Min_Frame_Time
Current_Time = MilliSecs()
Game_Start_Time = Current_Time
; Sounds.
Gosub MakeSounds
SND_Ping1 = LoadSound("ping1.wav")
SND_Ping2 = LoadSound("ping2.wav")
SND_Expl = LoadSound("expl.wav")
SetBuffer TexBuffer
Repeat
PaddleSpeed = BallSpeed - Rand(-1, 2)
; Distort.
LockBuffer BackBuffer()
LockBuffer TexBuffer
For By = 0 To (GH/2)-1
For Bx = 0 To GW-1
YLoc# = Float(By) / Float(GH) ; YLoc will never be greater than 0.5.
; Get pixel from texture and manipulate it.
Pixel = ReadPixelFast(TxL(Bx, By), TyL(Bx, By), TexBuffer)
Shade# = Yloc#*2.0 ; Dark edges
; Get green only.
Pixel = ((((Pixel Shr 8) And 255) * Shade#) Shl 8) ; Or ($ff000000)
; Full RGB copy.
;Pr = ((Pixel Shr 16) And 255) * Shade#
;Pg = ((Pixel Shr 8) And 255) * Shade#
;Pb = (Pixel And 255) * Shade#
;Pixel = Pb Or (Pg Shl 8) Or (Pr Shl 16) Or ($ff000000)
; Write top and mirror bottom pixels.
WritePixelFast Bx, By, Pixel, BackBuffer()
WritePixelFast Bx, (GH-1)-By, Pixel, BackBuffer()
Next
Next
UnlockBuffer BackBuffer()
UnlockBuffer TexBuffer
; Scroll, fill.
CopyRect 0, 0, TexSize, TexSize-ScrollRate, 0, ScrollRate, TexBuffer, TexBuffer
Color 0,0,0
Rect 0,0, TexSize, ScrollRate, 1
; Draw green text.
SetFont FONT_Arial1
Color 0, Rand(0, 196), 0
Text Rand(0, TexSize-1), 0, Txt$(Rand(0, 13))
; Draw paddles and ball.
SetBuffer BackBuffer()
Color 0, 255, 0
; P1 AI
If Not P1AI
; Player input.
; If mouse is so far down the screen that the paddle is partially off the screen, reposition it.
If MouseY() > (GH-PaddleHeight) Then MoveMouse MouseX(), (GH-PaddleHeight)
P1y = MouseY()
Else
; If ball is moving towards paddle...
If BLvx < 0
; If center of paddle is lower than ball, then move paddle up. Otherwise, move paddle down.
If ((P1y+(PaddleHeight/2)) > BLy)
P1y = P1y - PaddleSpeed
Else
P1y = P1y + PaddleSpeed
EndIf
EndIf
EndIf
; Keep paddle on screen.
If P1y < 0 Then P1y = 0
If P1y > (GH-PaddleHeight) Then P1y = GH-PaddleHeight
; P2 ai
; If ball is moving towards paddle...
If BLvx > 0
; If center of paddle is lower than ball, then move paddle up. Otherwise, move paddle down.
If ((P2y+(PaddleHeight/2)) > BLy)
P2y = P2y - PaddleSpeed
Else
P2y = P2y + PaddleSpeed
EndIf
EndIf
; Keep paddle on screen.
If P2y < 0 Then P2y = 0
If P2y > (GH-PaddleHeight) Then P2y = GH-PaddleHeight
; Ball Ai
; Ball collide with paddle.
; If ball moving towards paddle...
; (Prevents multiple collisions from occuring.)
If BLvx < 0
; If ball collides with paddle...
If RectsOverlap(P1x, P1y, PaddleWidth, PaddleHeight, BLx, BLy, BallWidth, BallWidth)
BLvx = -BLvx
PlaySound SND_Ping1
BallSpeed = BallSpeed + 1
EndIf
EndIf
If BLvx > 0
If RectsOverlap(P2x, P2y, PaddleWidth, PaddleHeight, BLx, BLy, BallWidth, BallWidth)
BLvx = -BLvx
PlaySound SND_Ping2
BallSpeed = BallSpeed + 1
EndIf
EndIf
; Keep ball from going so fast that it ignores paddle collisions.
If (BallSpeed > MAX_BALL_SPEED) Then BallSpeed = MAX_BALL_SPEED
; Left wall
If BLx < 0
P2Score = P2Score + 1
BLx = GW/2
BLy = GH/2
BLvx = -BLvx
BLvy = -BLvy
PlaySound SND_Expl
BallSpeed = MIN_BALL_SPEED
EndIf
; Right wall
If BLx > GW
P1Score = P1Score + 1
BLx = GW/2
BLy = GH/2
BLvx = -BLvx
BLvy = -BLvy
PlaySound SND_Expl
BallSpeed = MIN_BALL_SPEED
EndIf
; Top/Bottom wall
If (BLy < 0) Or (BLy > (GH-BallWidth)) Then BLvy = - BLvy
; Move ball
BLx = BLx + (BLvx * BallSpeed)
BLy = BLy + (BLvy * BallSpeed)
; Draw P1
Rect P1x, P1y, PaddleWidth, PaddleHeight, 1
; Draw P2
Rect P2x, P2y, PaddleWidth, PaddleHeight, 1
; Draw ball.
Rect BLx, BLy, BallWidth, BallWidth, 1
; Draw scores
SetFont FONT_Arial2
Text (GW/2)-(GW/8), GH/32, P1Score, True, False
Text (GW/2)+(GW/8), GH/32, P2Score, True, False
SetBuffer TexBuffer
; Flip!
Flip True
; Toggle interactive mode via space.
If KeyHit(57) Then P1AI = Not P1AI
Until KeyHit(1)
DeleteFile "expl.wav"
DeleteFile "ping1.wav"
DeleteFile "ping2.wav"
End
.MakeSounds
DeleteFile "expl.wav"
DeleteFile "ping1.wav"
DeleteFile "ping2.wav"
File = WriteFile("expl.wav")
WriteWavHeader(File, 1, 44000, 16, 44000)
For SampleLoop = 0 To 44000-1
Loc# = Float(SampleLoop) / 44000.0
If (SampleLoop Mod 4) = 0 Then Sample = Rand(-32767, 32767) * (1.0 - Loc#)
WriteShort File, Sample
Next
CloseFile File
File = WriteFile("ping1.wav")
Freq# = 440
WriteWavHeader(File, 1, 44000, 16, 20000)
For SampleLoop = 0 To 20000-1
Loc# = Float(SampleLoop) / 20000.0
Sample = (Sin(Loc#*Freq#*360.0)*32767.0) * (1.0-Loc#)
WriteShort File, Sample
Next
CloseFile File
File = WriteFile("ping2.wav")
Freq# = 220
WriteWavHeader(File, 1, 44000, 16, 20000)
For SampleLoop = 0 To 20000-1
Loc# = Float(SampleLoop) / 20000.0
Sample = (Sin(Loc#*Freq#*360.0)*32767.0) * (1.0-Loc#)
WriteShort File, Sample
Next
CloseFile File
Return
; This function writes a header to a wav file which you've already opened.
; File is the handle of the file.
Function WriteWavHeader(File, Channels, Frequency, Bits, Samples)
Local SampleSize = Channels * (Bits / 8)
Local WavSize = (Samples * SampleSize) + 52 ; Size of the wave file - include room for headers
; "RIFF"
WriteByte File, 82
WriteByte File, 73
WriteByte File, 70
WriteByte File, 70
; Size of the wav file not including the "RIFF" header and this 4-byte file size.
WriteInt File, WavSize - 8
; "WAVE"
WriteByte File, 87
WriteByte File, 65
WriteByte File, 86
WriteByte File, 69
; "fmt "
WriteByte File, 102
WriteByte File, 109
WriteByte File, 116
WriteByte File, 32
; Size of the format section.
WriteInt File, 18
; Format = PCM
WriteByte File, $01
WriteByte File, $00
; Channels
WriteByte File, Channels And $FF
WriteByte File, (Channels And $FF00) Shr 8
; Samples per second.
WriteInt File, Frequency
; Average bytes per second.
WriteInt File, Frequency * SampleSize
; Block align
WriteByte File, SampleSize And $FF
WriteByte File, (SampleSize And $FF00) Shr 8
; Bits per sample.
WriteByte File, Bits And $FF
WriteByte File, (Bits And $FF00) Shr 8
; Total extra information bytes.
WriteByte File, $00
WriteByte File, $00
; "data"
WriteByte File, 100
WriteByte File, 97
WriteByte File, 116
WriteByte File, 97
; Size of the data section.
WriteInt File, WavSize - 52
End Function