Advertisement
Guest User

Untitled

a guest
Jul 27th, 2018
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 7.49 KB | None | 0 0
  1. open Reprocessing;
  2.  
  3. type winner =
  4.   | Computer
  5.   | Player;
  6.  
  7. type playing =
  8.   | Menu
  9.   | Playing
  10.   | Restart(winner);
  11.  
  12. type state = {
  13.   playing,
  14.   computerCoords: (float, float),
  15.   playerCoords: (float, float),
  16.   ballCoords: (float, float),
  17.   ballVelocity: (float, float),
  18.   font: fontT,
  19.   playerScore: int,
  20.   computerScore: int,
  21. };
  22.  
  23. /* Measurements */
  24. let windowWidth = 600.;
  25. let windowHeight = 400.;
  26.  
  27. let paddleHeight = 100.;
  28. let paddleWidth = 10.;
  29. let paddleVelocity = 250.;
  30.  
  31. let ballRadius = 10.;
  32.  
  33. /* Colors */
  34. let background = Utils.color(~r=40, ~g=42, ~b=54, ~a=255);
  35. let foreground = Utils.color(~r=80, ~g=250, ~b=123, ~a=255);
  36.  
  37. /* Helpers */
  38. let paddleCenter = (~paddleY) => paddleY +. paddleHeight /. 2.;
  39.  
  40. let constrainPaddle = (~amt) => Utils.constrain(~amt, ~low=0., ~high=windowHeight -. paddleHeight);
  41.  
  42. let playerScoredPoint = ({ballCoords}) => {
  43.   let (ballX, _) = ballCoords;
  44.   ballX < -. ballRadius;
  45. };
  46.  
  47. let computerScoredPoint = ({ballCoords}) => {
  48.   let (ballX, _) = ballCoords;
  49.   ballX > +. windowWidth +. ballRadius;
  50. };
  51.  
  52. module PlayerPaddle = {
  53.   /* Default Settings */
  54.   let defaultCoords = (windowWidth -. paddleWidth, windowHeight /. 2.);
  55.  
  56.   /* Functions */
  57.   let draw = (state, env) => {
  58.     Draw.fill(foreground, env);
  59.     Draw.rectf(~pos=state.playerCoords, ~width=paddleWidth, ~height=paddleHeight, env);
  60.   };
  61.  
  62.   let update = ({playerCoords}, env) => {
  63.     let deltaTime = Env.deltaTime(env);
  64.  
  65.     let (playerPaddleX, playerPaddleY) = playerCoords;
  66.  
  67.     if (Env.key(Up, env)) {
  68.       (playerPaddleX, constrainPaddle(~amt=playerPaddleY -. paddleVelocity *. deltaTime));
  69.     } else if (Env.key(Down, env)) {
  70.       (playerPaddleX, constrainPaddle(~amt=playerPaddleY +. paddleVelocity *. deltaTime));
  71.     } else {
  72.       playerCoords;
  73.     };
  74.   };
  75. };
  76.  
  77. module ComputerPaddle = {
  78.   /* Default Settings */
  79.   let defaultCoords = (0., windowHeight /. 2.);
  80.   let deadzoneTresshold = 30.;
  81.  
  82.   /* Helpers */
  83.   let underDeadzone = (~ballY, ~paddleY) => ballY < paddleCenter(~paddleY) -. deadzoneTresshold;
  84.   let aboveDeadzone = (~ballY, ~paddleY) => ballY > paddleCenter(~paddleY) +. deadzoneTresshold;
  85.  
  86.   /* Functions */
  87.   let draw = (state, env) => {
  88.     Draw.fill(foreground, env);
  89.     Draw.rectf(~pos=state.computerCoords, ~width=paddleWidth, ~height=paddleHeight, env);
  90.   };
  91.  
  92.   let update = ({computerCoords, ballCoords}, env) => {
  93.     let deltaTime = Env.deltaTime(env);
  94.  
  95.     let (_, ballY) = ballCoords;
  96.     let (computerPaddleX, computerPaddleY) = computerCoords;
  97.  
  98.     if (underDeadzone(~ballY, ~paddleY=computerPaddleY)) {
  99.       (computerPaddleX, constrainPaddle(~amt=computerPaddleY -. paddleVelocity *. deltaTime));
  100.     } else if (aboveDeadzone(~ballY, ~paddleY=computerPaddleY)) {
  101.       (computerPaddleX, constrainPaddle(~amt=computerPaddleY +. paddleVelocity *. deltaTime));
  102.     } else {
  103.       computerCoords;
  104.     };
  105.   };
  106. };
  107.  
  108. module Ball = {
  109.   /* Default setting */
  110.   let acceleration = 10.;
  111.   let defaultVelocity = (Utils.randomf(~min=-250., ~max=250.), Utils.randomf(~min=-250., ~max=250.));
  112.   let defaultCoords = (windowWidth /. 2., windowHeight /. 2.);
  113.  
  114.   /* Helpers */
  115.   let collidesWithWalls = (~ballY) => ballY < 0. +. ballRadius || ballY > windowHeight -. ballRadius;
  116.  
  117.   let collisionVelocity = (ballY, paddleY) => {
  118.     let paddleCenter = paddleY +. paddleHeight /. 2.;
  119.     let ballCenter = ballY +. ballRadius /. 2.;
  120.  
  121.     let distanceToMiddle = abs_float(ballCenter -. paddleCenter);
  122.  
  123.     ballCenter <= paddleCenter ? -. distanceToMiddle *. acceleration : distanceToMiddle *. acceleration;
  124.   };
  125.  
  126.   let collidesWithPaddle = (~ballCoords, ~paddleCoords) =>
  127.     Utils.intersectRectCircle(
  128.       ~rectPos=paddleCoords,
  129.       ~rectH=paddleHeight,
  130.       ~rectW=paddleWidth,
  131.       ~circlePos=ballCoords,
  132.       ~circleRad=ballRadius,
  133.     );
  134.  
  135.   let calculateVelocity = ({ballCoords, playerCoords, computerCoords, ballVelocity}, _env) => {
  136.     let (_, ballY) = ballCoords;
  137.     let (_, playerPaddleY) = playerCoords;
  138.     let (_, computerPaddleY) = computerCoords;
  139.     let (velocityX, velocityY) = ballVelocity;
  140.  
  141.     if (collidesWithPaddle(~ballCoords, ~paddleCoords=playerCoords)) {
  142.       (velocityX *. (-1.), collisionVelocity(ballY, playerPaddleY));
  143.     } else if (collidesWithPaddle(~ballCoords, ~paddleCoords=computerCoords)) {
  144.       (velocityX *. (-1.), collisionVelocity(ballY, computerPaddleY));
  145.     } else if (collidesWithWalls(~ballY)) {
  146.       (velocityX, velocityY *. (-1.));
  147.     } else {
  148.       (velocityX, velocityY);
  149.     };
  150.   };
  151.  
  152.   /* Functions */
  153.   let draw = ({ballCoords}, env) => {
  154.     Draw.fill(foreground, env);
  155.     Draw.ellipsef(~center=ballCoords, ~radx=ballRadius, ~rady=ballRadius, env);
  156.   };
  157.  
  158.   let update = (state, env) => {
  159.     let deltaTime = Env.deltaTime(env);
  160.     let (ballX, ballY) = state.ballCoords;
  161.  
  162.     let (velocityX, velocityY) = calculateVelocity(state, env);
  163.  
  164.     ((ballX +. velocityX *. deltaTime, ballY +. velocityY *. deltaTime), (velocityX, velocityY));
  165.   };
  166. };
  167.  
  168. module Arena = {
  169.   let draw = ({font, playerScore, computerScore}, env) => {
  170.     Draw.background(background, env);
  171.  
  172.     Draw.text(~font, ~body=string_of_int(computerScore), ~pos=(200, 50), env);
  173.     Draw.text(~font, ~body=string_of_int(playerScore), ~pos=(400, 50), env);
  174.   };
  175. };
  176.  
  177. let setup = env => {
  178.   Env.size(~width=int_of_float(windowWidth), ~height=int_of_float(windowHeight), env);
  179.  
  180.   {
  181.     playing: Menu,
  182.     computerCoords: ComputerPaddle.defaultCoords,
  183.     playerCoords: PlayerPaddle.defaultCoords,
  184.     ballCoords: Ball.defaultCoords,
  185.     ballVelocity: Ball.defaultVelocity,
  186.     font: Draw.loadFont(~filename="assets/fonts/font.fnt", ~isPixel=true, env),
  187.     playerScore: 0,
  188.     computerScore: 0,
  189.   };
  190. };
  191.  
  192. let draw = (state, env) => {
  193.   Arena.draw(state, env);
  194.  
  195.   Ball.draw(state, env);
  196.  
  197.   PlayerPaddle.draw(state, env);
  198.   ComputerPaddle.draw(state, env);
  199.  
  200.   switch (state.playing) {
  201.   | Menu =>
  202.     Draw.text(~font=state.font, ~body="Press Space to Play", ~pos=(175, 300), env);
  203.  
  204.     Env.key(Space, env) ? {...state, playing: Playing} : state;
  205.   | Playing =>
  206.     let playerCoords = PlayerPaddle.update(state, env);
  207.     let computerCoords = ComputerPaddle.update(state, env);
  208.  
  209.     if (playerScoredPoint(state)) {
  210.       let ballCoords = Ball.defaultCoords;
  211.       let ballVelocity = Ball.defaultVelocity;
  212.       let playerScore = state.playerScore + 1;
  213.       let playing = playerScore == 3 ? Restart(Player) : Playing;
  214.  
  215.       {...state, playing, playerScore, computerCoords, playerCoords, ballCoords, ballVelocity};
  216.     } else if (computerScoredPoint(state)) {
  217.       let ballCoords = Ball.defaultCoords;
  218.       let ballVelocity = Ball.defaultVelocity;
  219.       let computerScore = state.computerScore + 1;
  220.       let playing = computerScore == 3 ? Restart(Computer) : Playing;
  221.  
  222.       {...state, playing, computerScore, computerCoords, playerCoords, ballCoords, ballVelocity};
  223.     } else {
  224.       let (ballCoords, ballVelocity) = Ball.update(state, env);
  225.       {...state, computerCoords, playerCoords, ballCoords, ballVelocity};
  226.     };
  227.  
  228.   | Restart(winner) =>
  229.     let text =
  230.       switch (winner) {
  231.       | Player => "You won!"
  232.       | Computer => "You Lost!"
  233.       };
  234.  
  235.     Draw.text(~font=state.font, ~body=text, ~pos=(240, 300), env);
  236.     Draw.text(~font=state.font, ~body="Press Space to play again", ~pos=(140, 340), env);
  237.  
  238.     if (Env.key(Space, env)) {
  239.       {...state, playing: Playing, computerScore: 0, playerScore: 0};
  240.     } else {
  241.       state;
  242.     };
  243.   };
  244. };
  245.  
  246. run(~setup, ~draw, ());
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement