set display mode 800, 600, 16
sync on
sync rate 0
set point light 0, 000, 3, -30
set light range 0, 500
set ambient light 10
color backdrop 0
 
autocam off
position camera 0, 3, -30
point camera 0, 2, 0
 
 
rem D3D_INIT
 
null = make vector3(1) :`Velocity
null = make vector3(2) :`Paddle Normal
null = make vector3(3) :`Used for collision
null = make vector3(4) :`Used for collision
 
 
#constant CURVE_RADIUS 12.0
#constant PADDLE_SPEED 0.135
 
 
 
Type Coord3D
   x as float
   y as float
   z as float
EndType
 
Type PlayerData
   angle as float
   targetAngle as float
   score as byte
EndType
 
Dim P(2) as PlayerData
 
P(1).angle = 225
P(2).angle = -45
P(1).targetAngle = 225
P(2).targetAngle = -45
P(1).score = 0
P(2).score = 0
 
`Make Paddles
make object box 2, 0.5, 6.0, 0.5 : color object 2, 0xff9999
make object box 3, 0.5, 6.0, 0.5 : color object 3, 0x99ff99
 
 
 
 
Type BallData
   p as Coord3D
   speed as float
EndType
Global Ball as BallData
resetPlay(-1)
 
`Make Ball
make object sphere 1, 0.5 : color object 1, 0x9999ff
position object 1, Ball.p.x, Ball.p.y, Ball.p.z
 
 
 
 
 
`Make floor
make object box 4, CURVE_RADIUS * 3.0, 4.0, 1.0
position object 4, 0, -CURVE_RADIUS - 1.5, 0
point object    4, 0, 0, 0
color object    4, 0x238F1D
`Make ceiling
make object box 5, CURVE_RADIUS * 5.0, 4.0, 1.0
position object 5, 0, CURVE_RADIUS +3.0, 0
point object    5, 0, 0, 0
color object    5, 0x238F1D
 
 
 
 
 
position mouse screen width() * 0.5, 0
hide mouse
 
 
 
 
 
 
global frameTime as float
frameTime = 1.0
startTime as integer
startTime = timer()
do
   frameTime = (frameTime * 0.8) + ((timer() - startTime) * 0.2)
   startTime = timer()
 
 
 
 
 
   `Handle Player 1
   if keystate(29)
      `Left Ctrl
      inc P(1).targetAngle, frameTime * PADDLE_SPEED
      if P(1).targetAngle > 280.0 then P(1).targetAngle = 280.0
   else
      if keystate(42)
         `Left Shift
         dec P(1).targetAngle, frameTime * PADDLE_SPEED
         if P(1).targetAngle < 90.0 then P(1).targetAngle = 90.0
      endif
   endif
   P(1).angle = curvevalue(P(1).targetAngle, P(1).angle, 200.0 / frameTime)
 
   `Handle Player 2
   if keystate(54)
      `right Shift
      inc P(2).targetAngle, frameTime * PADDLE_SPEED
      if P(2).targetAngle > 90.0 then P(2).targetAngle = 90.0
   else
      if keystate(157)
         `Right Ctrl
         dec P(2).targetAngle, frameTime * PADDLE_SPEED
         if P(2).targetAngle < -100 then P(2).targetAngle = -100
      endif
   endif
   P(2).angle = curvevalue(P(2).targetAngle, P(2).angle, 200.0 / frameTime)
 
   text 0, 10, "Speed: " + str$(Ball.speed)
   text 0, 0, "Player 1 Score: " + str$(P(1).score)
   p2score$ = "Player 2 Score: " + str$(P(2).score)
   text screen width() - text width(p2score$), 0, p2score$
 
 
 
   position object 2, -(CURVE_RADIUS*0.5) + (cos(P(1).angle) * CURVE_RADIUS), sin(P(1).angle) * CURVE_RADIUS, 0
   zrotate object  2, P(1).angle
 
   position object 3,  (CURVE_RADIUS*0.5) + (cos(P(2).angle) * CURVE_RADIUS), sin(P(2).angle) * CURVE_RADIUS, 0
   zrotate object  3, P(2).angle
 
 
   `handle gravity
   set vector3 1, x vector3(1), y vector3(1) - (frameTime * 0.0098), z vector3(1)
   inc Ball.p.x, x vector3(1) * frametime * 0.001
   inc Ball.p.y, y vector3(1) * frametime * 0.001
   inc Ball.p.z, z vector3(1) * frametime * 0.001
   position object 1, Ball.p.x, Ball.p.y, Ball.p.z
 
 
 
 
 
 
   handleCollision(2, object hit (2, 1))
   handleCollision(3, object hit (3, 1))
 
   if object hit (4, 1)
      `hit floor
      set vector3 1, x vector3(1), -y vector3(1), z vector3(1)
   endif
   if object hit (5, 1)
      `hit floor
      set vector3 1, x vector3(1), -y vector3(1), z vector3(1)
   endif
 
 
   objSx# = object screen x(1)
   objSy# = object screen y(1)
   if objSx# > screen width()
      resetPlay(-1)
      inc P(1).score
   else
      if objSx# < 0
         resetPlay(1)
         inc P(2).score
      endif
   endif
 
   sync
loop
end
 
 
 
 
function resetPlay(start as integer)
   Ball.p.x = 5.0 * start
   Ball.p.y = 5.0
   Ball.p.z = 0.0
   set vector3 1, 0, 0, 0 :`velocity of ball
   Ball.speed = length vector3(1)
 
   if object exist(1) then position object 1, Ball.p.x, Ball.p.y, Ball.p.z
endfunction
 
 
 
function handleCollision(paddle as integer, hit as boolean)
   if hit
      `Normal of paddle
      set vector3 2, cos(object angle z(paddle)), sin(object angle z(paddle)), 0
      normalize vector3 2, 2
      scale vector3 2, 2, 2.0
 
      `Get unit/normalized version of ball speed
      normalize vector3 3, 1
      `Temporarily invert
      multiply vector3 3, -1
      `Get scalar impulse
      I# = dot product vector3(2, 3) * 2.0
      `Multiply normal vector by it (and store in vector3(4))
      copy vector3 4, 2
      multiply vector3 4, I#
      `Un-invert
      multiply vector3 3, -1
      `Add to vector 4
      add vector3 4, 3, 4
      `Normlize
      normalize vector3 4, 4
      `Scale by speed magnitude
      Ball.speed = length vector3(1) * 1.05
      if Ball.speed > 30 then Ball.speed = 30
      multiply vector3 4, Ball.speed
 
 
      copy vector3 1, 4
   endif
endfunction