{
   "description" : "A basic implementation of pong.",
   "ancestor_list" : [],
   "name" : "Pong",
   "author" : "dilots",
   "code" : "(\r\nvar paddlePositions = [0.5,0.5]; // Paddle position from 0 (left) to 1 (right)\r\nvar paddleWidths = [100, 100];\r\nvar paddleSpeed = 0.005;\r\nvar paddleMaxSpeed = 0.02;\r\nvar paddleMovements = [0,0];\r\nvar friction = 1.15;\r\nvar width = 600, height = 700;\r\nvar ballPosition = Point(width/2, height/2);\r\nvar ballSize = 10;\r\nvar ballXMovement = rand2(1.5);\r\nvar ballYMovement = 3.0*((rand(2)*2)-1);\r\nvar ballMaxSpeed = 30;\r\nvar scores = [0,0];\r\nvar notes = Scale.phrygian.degrees+60;\r\n\r\nk = Set[]; // keep track of held keys\r\n\r\n// SynthDef\r\nSynthDef(\\bounce, {\r\n\t|out=0, gain=0.5, length=1, freq=200, depth=20|\r\n\tvar bounce, freqenv, ampenv;\r\n\tfreqenv = EnvGen.kr(Env.perc(0.01,length,depth));\r\n\tampenv = EnvGen.kr(Env.perc(0.01,length,1.0),doneAction:2);\r\n\tbounce = SinOsc.ar(freq+freqenv)!2 * ampenv * gain;\r\n\tbounce = Limiter.ar(bounce, gain, 0.001);\r\n\tOut.ar(out,bounce);\r\n}).add;\r\n\r\n// GUI\r\nw = Window(\"Pong\", Rect((Window.screenBounds.width/2)-(width/2), (Window.screenBounds.height/2)-(height/2), width, height), false).front;\r\nu = UserView(w, Rect(0, 0, width, height));\r\nu.background = Color.white;\r\nu.animate = true;\r\nu.frameRate = 60;\r\nu.drawFunc = {\r\n\t// update paddle position\r\n\t2.do{|i|\r\n\t\tif(paddleMovements[i]<0,{\r\n\t\t\t//  left bounds\r\n\t\t\t// if holding left, increase left speed\r\n\t\t\tif(  (paddleMovements[i].abs < paddleMaxSpeed)\r\n\t\t\t\t&& (k.includes((i*(16777234-65))+65)),{\r\n\t\t\t\t\tpaddleMovements[i] = paddleMovements[i]-0.001;\r\n\t\t\t});\r\n\t\t\tif((paddlePositions[i]*width - paddleWidths[i]) >= 40,\r\n\t\t\t\t{\r\n\t\t\t\t\tpaddlePositions[i] = paddlePositions[i] + paddleMovements[i];\r\n\t\t\t\t}\r\n\t\t\t);\r\n\t\t},{\r\n\t\t\t// right bounds\r\n\t\t\t// if holding right, increase right speed\r\n\t\t\tif(  (paddleMovements[i].abs < paddleMaxSpeed)\r\n\t\t\t\t&& (k.includes(i*(16777236-68)+68)),{\r\n\t\t\t\t\tpaddleMovements[i] = paddleMovements[i]+0.001;\r\n\t\t\t});\r\n\t\t\tif((paddlePositions[i]*width + paddleWidths[i]) <= (width-40),\r\n\t\t\t\t{\r\n\t\t\t\t\tpaddlePositions[i] = paddlePositions[i] + paddleMovements[i];\r\n\t\t\t\t}\r\n\t\t\t);\r\n\t\t});\r\n\t};\r\n\tif((k.includes(65) || (k.includes(68))).not,\r\n\t\t{\r\n\t\t\tpaddleMovements[0] = paddleMovements[0] / friction;\r\n\t});\r\n\tif((k.includes(16777234) || (k.includes(16777236))).not,\r\n\t\t{\r\n\t\t\tpaddleMovements[1] = paddleMovements[1] / friction;\r\n\t});\r\n\t// update ball position\r\n\tballPosition.x = ballPosition.x + ballXMovement;\r\n\tballPosition.y = ballPosition.y + ballYMovement;\r\n\t// collision detection\r\n\t// top\r\n\tif ((ballPosition.y < 45) && (ballPosition.y > (35-(ballYMovement.abs))),\r\n\t\t{\r\n\t\t\tif(  (ballPosition.x > (paddlePositions[0]*width-paddleWidths[0]))\r\n\t\t\t\t&& (ballPosition.x < (paddlePositions[0]*width+paddleWidths[0])),\r\n\t\t\t\t{\r\n\t\t\t\t\tvar ballRelPos = ((ballPosition.x-(paddlePositions[0]*width)) / (paddleWidths[0]*2));\r\n\t\t\t\t\tSynth(\\bounce, [\\freq, notes.choose.midicps]);\r\n\t\t\t\t\tballYMovement = ballYMovement.abs;\r\n\t\t\t\t\tif (ballYMovement <= ballMaxSpeed,\r\n\t\t\t\t\t\t{ballYMovement = ballYMovement * (1.1);}\r\n\t\t\t\t\t);\r\n\t\t\t\t\tballXMovement = ballRelPos*16;\r\n\t\t\t\t}\r\n\t\t\t);\r\n\t\t}\r\n\t);\r\n\t// bottom\r\n\tif ((ballPosition.y > (height-45)) && (ballPosition.y < (height-35+ballYMovement.abs)),\r\n\t\t{\r\n\t\t\tif(  (ballPosition.x > (paddlePositions[1]*width-paddleWidths[1]))\r\n\t\t\t\t&& (ballPosition.x < (paddlePositions[1]*width+paddleWidths[1])),\r\n\t\t\t\t{\r\n\t\t\t\t\t// change angle based on distance from center of paddle\r\n\t\t\t\t\tvar ballRelPos = ((ballPosition.x-(paddlePositions[1]*width)) / (paddleWidths[1]*2));\r\n\t\t\t\t\tSynth(\\bounce, [\\freq, notes.choose.midicps]);\r\n\t\t\t\t\tballYMovement = ballYMovement.abs * (-1);\r\n\t\t\t\t\tif (ballYMovement.abs <= ballMaxSpeed,\r\n\t\t\t\t\t\t{ballYMovement = ballYMovement * (1.1);}\r\n\t\t\t\t\t);\r\n\t\t\t\t\tballXMovement = ballRelPos*16;\r\n\t\t\t\t}\r\n\t\t\t);\r\n\t\t}\r\n\t);\r\n\r\n\t// wall bounce\r\n\tif (ballPosition.x > (width-40),\r\n\t\t{\r\n\t\t\tSynth(\\bounce, [\\freq, (notes.choose-12).midicps]);\r\n\t\t\tballXMovement = ballXMovement.abs * (-1);\r\n\t\t}\r\n\t);\r\n\tif (ballPosition.x < 40,\r\n\t\t{\r\n\t\t\tSynth(\\bounce, [\\freq, (notes.choose-12).midicps]);\r\n\t\t\tballXMovement = ballXMovement.abs;\r\n\t\t}\r\n\t);\r\n\r\n\t// out detection\r\n\t// out top\r\n\tif (ballPosition.y < (0-ballYMovement.abs),\r\n\t\t{\r\n\t\t\tscores[1] = scores[1]+1;\r\n\t\t\tSynth(\\bounce, [\\freq, 10, \\length, (4), \\depth, 100]);\r\n\t\t\tballPosition = Point(width/2, height/2);\r\n\t\t\tballXMovement = rand2(1.5);\r\n\t\t\tballYMovement = 3.0;\r\n\t\t}\r\n\t);\r\n\t// out bottom\r\n\tif (ballPosition.y > (height+(ballYMovement.abs)),\r\n\t\t{\r\n\t\t\tscores[0] = scores[0]+1;\r\n\t\t\tSynth(\\bounce, [\\freq, 10, \\length, (4), \\depth, 100]);\r\n\t\t\tballPosition = Point(width/2, height/2);\r\n\t\t\tballXMovement = rand2(1.5);\r\n\t\t\tballYMovement = -3.0;\r\n\t\t}\r\n\t);\r\n\tPen.use {\r\n\t\t// draw bounds\r\n\t\tPen.line(Point(40,40),Point(40,height-40));\r\n\t\tPen.line(Point(width-40,40),Point(width-40,height-40));\r\n\t\tPen.strokeColor = Color.green;\r\n\t\tPen.width = 3;\r\n\t\tPen.stroke;\r\n\t\t// draw paddles\r\n\t\tPen.line(\r\n\t\t\tPoint(paddlePositions[0]*width-paddleWidths[0], 40),\r\n\t\t\tPoint(paddlePositions[0]*width+paddleWidths[0], 40)\r\n\t\t);\r\n\t\tPen.line(\r\n\t\t\tPoint(paddlePositions[1]*width-paddleWidths[1], (height-40)),\r\n\t\t\tPoint(paddlePositions[1]*width+paddleWidths[1], (height-40))\r\n\t\t);\r\n\t\tPen.strokeColor = Color.black;\r\n\t\tPen.width = 5;\r\n\t\tPen.stroke;\r\n\t\t// draw ball\r\n\t\tPen.fillOval(Rect(ballPosition.x-(ballSize/2),ballPosition.y-(ballSize/2),ballSize,ballSize));\r\n\t\t// Draw score\r\n\t\t(scores[0]+\"\").drawAtPoint(\r\n\t\t\tPoint(width/2,height/2-100),\r\n\t\t\tFont(\"Courier\", 30),\r\n\t\t\tColor.blue(0.3, 0.5));\r\n\t\t(scores[1]+\"\").drawAtPoint(\r\n\t\t\tPoint(width/2,height/2+100),\r\n\t\t\tFont(\"Courier\", 30),\r\n\t\t\tColor.blue(0.3, 0.5));\r\n\t};\r\n};\r\n\r\nw.view.keyDownAction = {\r\n\targ view, char, modifiers, unicode, keycode, key;\r\n\tif(k.includes(key).not,{\r\n\t\tk.add(key); // add keystroke to list of keys being held\r\n\t\tswitch(key,\r\n\t\t\t65, {paddleMovements[0] = paddleSpeed*(-1)},  // left player 0\r\n\t\t\t68, {paddleMovements[0] = paddleSpeed},  // right player 0\r\n\t\t\t16777234, {paddleMovements[1] = paddleSpeed*(-1)},  // left player 1\r\n\t\t\t16777236, {paddleMovements[1] = paddleSpeed}  // right player 1\r\n\t\t);\r\n\t});\r\n};\r\nw.view.keyUpAction_({\r\n\targ view, char, mod, uni, keycode, key;\r\n\tswitch(key,\r\n\t\t65, {if(k.includes(68),{paddleMovements[0] = paddleSpeed})},  // left\r\n\t\t68, {if(k.includes(65),{paddleMovements[0] = paddleSpeed*(-1)})},  // right\r\n\t\t16777234, {if(k.includes(16777236),{paddleMovements[1] = paddleSpeed})},  // left\r\n\t\t16777236, {if(k.includes(16777234),{paddleMovements[1] = paddleSpeed*(-1)})},  // right\r\n\t);\r\n\tk.remove(key); // remove keystroke from list of keys being held\r\n});\r\n)",
   "id" : "1-50g",
   "is_private" : null,
   "labels" : [
      "games",
      "game",
      "pong",
      "phrygian"
   ]
}
