Pong Game

        Pong merupakan permainan video generasi pertama yang dirilis sebagai permainan arkade yang dioperasikan dengan koin yang dikembangkan oleh Atari Inc. pada tanggal 29 November 1972. Pong didasari dari permainan tenis meja (PingPong), nama permainan ini berasal dari suara yang dihasilkan ketika memukul bola ping pong.

        Game ini terdiri dari empat class. Yang bisa dilihat pada gambar diagram class di bawah ini.




1. Class Pong
Class ini merupakan class utama dalam program game ini.

  1. /**
  2. * Class ini merupakan class utama dari PongGame.
  3. *
  4. * @author Sabrina Lydia S
  5. * @version 21/12/20
  6. */
  7.  
  8. import java.awt.BasicStroke;
  9. import java.awt.Color;
  10. import java.awt.Font;
  11. import java.awt.Graphics2D;
  12. import java.awt.RenderingHints;
  13. import java.awt.event.ActionEvent;
  14. import java.awt.event.ActionListener;
  15. import java.awt.event.KeyEvent;
  16. import java.awt.event.KeyListener;
  17. import java.util.Random;
  18. import javax.swing.JFrame;
  19. import javax.swing.Timer;
  20.  
  21. public class Pong implements ActionListener, KeyListener
  22. {
  23. public static Pong pong;
  24. public int width = 700, height = 700;
  25. public Renderer renderer;
  26. public Paddle player1;
  27. public Paddle player2;
  28. public Ball ball;
  29. public boolean bot = false, selectingDifficulty;
  30. public boolean w, s, up, down;
  31. public int gameStatus = 0, scoreLimit = 7, playerWon; //0 = Menu, 1 = Paused, 2 = Playing, 3 = Over
  32. public int botDifficulty, botMoves, botCooldown = 0;
  33. public Random random;
  34. public JFrame jframe;
  35.  
  36. public Pong()
  37. {
  38. Timer timer = new Timer(20, this);
  39. random = new Random();
  40. jframe = new JFrame("Pong");
  41. renderer = new Renderer();
  42. jframe.setSize(width + 15, height + 35);
  43. jframe.setVisible(true);
  44. jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  45. jframe.add(renderer);
  46. jframe.addKeyListener(this);
  47. timer.start();
  48. }
  49.  
  50. public void start()
  51. {
  52. gameStatus = 2;
  53. player1 = new Paddle(this, 1);
  54. player2 = new Paddle(this, 2);
  55. ball = new Ball(this);
  56. }
  57.  
  58. public void update()
  59. {
  60. if (player1.score >= scoreLimit)
  61. {
  62. playerWon = 1;
  63. gameStatus = 3;
  64. }
  65. if (player2.score >= scoreLimit)
  66. {
  67. gameStatus = 3;
  68. playerWon = 2;
  69. }
  70. if (w)
  71. {
  72. player1.move(true);
  73. }
  74. if (s)
  75. {
  76. player1.move(false);
  77. }
  78. if (!bot)
  79. {
  80. if (up)
  81. {
  82. player2.move(true);
  83. }
  84. if (down)
  85. {
  86. player2.move(false);
  87. }
  88. }
  89. else
  90. {
  91. if (botCooldown > 0)
  92. {
  93. botCooldown--;
  94. if (botCooldown == 0)
  95. {
  96. botMoves = 0;
  97. }
  98. }
  99. if (botMoves < 10)
  100. {
  101. if (player2.y + player2.height / 2 < ball.y)
  102. {
  103. player2.move(false);
  104. botMoves++;
  105. }
  106. if (player2.y + player2.height / 2 > ball.y)
  107. {
  108. player2.move(true);
  109. botMoves++;
  110. }
  111. if (botDifficulty == 0)
  112. {
  113. botCooldown = 20;
  114. }
  115. if (botDifficulty == 1)
  116. {
  117. botCooldown = 15;
  118. }
  119. if (botDifficulty == 2)
  120. {
  121. botCooldown = 10;
  122. }
  123. }
  124. }
  125. ball.update(player1, player2);
  126. }
  127.  
  128. public void render(Graphics2D g)
  129. {
  130. g.setColor(Color.WHITE);
  131. g.fillRect(0, 0, width, height);
  132. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  133. if (gameStatus == 0)
  134. {
  135. g.setColor(Color.BLACK);
  136. g.setFont(new Font("Arial", 1, 50));
  137. g.drawString("PONG", width / 2 - 75, 50);
  138. if (!selectingDifficulty)
  139. {
  140. g.setFont(new Font("Arial", 1, 30));
  141. g.drawString("Press Space to Play", width / 2 - 150, height / 2 - 25);
  142. g.drawString("Press Shift to Play with Bot", width / 2 - 200, height / 2 + 25);
  143. g.drawString("<< Score Limit: " + scoreLimit + " >>", width / 2 - 150, height / 2 + 75);
  144. }
  145. }
  146. if (selectingDifficulty)
  147. {
  148. String string = botDifficulty == 0 ? "Easy" : (botDifficulty == 1 ? "Medium" : "Hard");
  149. g.setFont(new Font("Arial", 1, 30));
  150. g.drawString("<< Bot Difficulty: " + string + " >>", width / 2 - 180, height / 2 - 25);
  151. g.drawString("Press Space to Play", width / 2 - 150, height / 2 + 25);
  152. }
  153. if (gameStatus == 1)
  154. {
  155. g.setColor(Color.BLACK);
  156. g.setFont(new Font("Arial", 1, 50));
  157. g.drawString("PAUSED", width / 2 - 103, height / 2 - 25);
  158. }
  159. if (gameStatus == 1 || gameStatus == 2)
  160. {
  161. g.setColor(Color.BLACK);
  162. g.setStroke(new BasicStroke(5f));
  163. g.drawLine(width / 2, 0, width / 2, height);
  164. g.setStroke(new BasicStroke(2f));
  165. g.drawOval(width / 2 - 150, height / 2 - 150, 300, 300);
  166. g.setFont(new Font("Arial", 1, 50));
  167. g.drawString(String.valueOf(player1.score), width / 2 - 90, 50);
  168. g.drawString(String.valueOf(player2.score), width / 2 + 65, 50);
  169. player1.render(g);
  170. player2.render(g);
  171. ball.render(g);
  172. }
  173. if (gameStatus == 3)
  174. {
  175. g.setColor(Color.BLACK);
  176. g.setFont(new Font("Arial", 1, 50));
  177. g.drawString("PONG", width / 2 - 75, 50);
  178. if (bot && playerWon == 2)
  179. {
  180. g.drawString("The Bot Wins!", width / 2 - 170, 200);
  181. }
  182. else
  183. {
  184. g.drawString("Player " + playerWon + " Wins!", width / 2 - 165, 200);
  185. }
  186. g.setFont(new Font("Arial", 1, 30));
  187. g.drawString("Press Space to Play Again", width / 2 - 185, height / 2 - 25);
  188. g.drawString("Press ESC for Menu", width / 2 - 140, height / 2 + 25);
  189. }
  190. }
  191.  
  192. @Override
  193. public void actionPerformed(ActionEvent e)
  194. {
  195. if (gameStatus == 2)
  196. {
  197. update();
  198. }
  199. renderer.repaint();
  200. }
  201.  
  202. public static void main(String[] args)
  203. {
  204. pong = new Pong();
  205. }
  206.  
  207. @Override
  208. public void keyPressed(KeyEvent e)
  209. {
  210. int id = e.getKeyCode();
  211. if (id == KeyEvent.VK_W)
  212. {
  213. w = true;
  214. }
  215. else if (id == KeyEvent.VK_S)
  216. {
  217. s = true;
  218. }
  219. else if (id == KeyEvent.VK_UP)
  220. {
  221. up = true;
  222. }
  223. else if (id == KeyEvent.VK_DOWN)
  224. {
  225. down = true;
  226. }
  227. else if (id == KeyEvent.VK_RIGHT)
  228. {
  229. if (selectingDifficulty)
  230. {
  231. if (botDifficulty < 2)
  232. {
  233. botDifficulty++;
  234. }
  235. else
  236. {
  237. botDifficulty = 0;
  238. }
  239. }
  240. else if (gameStatus == 0)
  241. {
  242. scoreLimit++;
  243. }
  244. }
  245. else if (id == KeyEvent.VK_LEFT)
  246. {
  247. if (selectingDifficulty)
  248. {
  249. if (botDifficulty > 0)
  250. {
  251. botDifficulty--;
  252. }
  253. else
  254. {
  255. botDifficulty = 2;
  256. }
  257. }
  258. else if (gameStatus == 0 && scoreLimit > 1)
  259. {
  260. scoreLimit--;
  261. }
  262. }
  263. else if (id == KeyEvent.VK_ESCAPE && (gameStatus == 2 || gameStatus == 3))
  264. {
  265. gameStatus = 0;
  266. }
  267. else if (id == KeyEvent.VK_SHIFT && gameStatus == 0)
  268. {
  269. bot = true;
  270. selectingDifficulty = true;
  271. }
  272. else if (id == KeyEvent.VK_SPACE)
  273. {
  274. if (gameStatus == 0 || gameStatus == 3)
  275. {
  276. if (!selectingDifficulty)
  277. {
  278. bot = false;
  279. }
  280. else
  281. {
  282. selectingDifficulty = false;
  283. }
  284. start();
  285. }
  286. else if (gameStatus == 1)
  287. {
  288. gameStatus = 2;
  289. }
  290. else if (gameStatus == 2)
  291. {
  292. gameStatus = 1;
  293. }
  294. }
  295. }
  296.  
  297. @Override
  298. public void keyReleased(KeyEvent e)
  299. {
  300. int id = e.getKeyCode();
  301. if (id == KeyEvent.VK_W)
  302. {
  303. w = false;
  304. }
  305. else if (id == KeyEvent.VK_S)
  306. {
  307. s = false;
  308. }
  309. else if (id == KeyEvent.VK_UP)
  310. {
  311. up = false;
  312. }
  313. else if (id == KeyEvent.VK_DOWN)
  314. {
  315. down = false;
  316. }
  317. }
  318.  
  319. @Override
  320. public void keyTyped(KeyEvent e)
  321. {
  322. }
  323. }

2. Class Ball
Class ball memiliki fungsi untuk mengatur semua yang berkaitan dengan bola, seperti warna, ukuran, bentuk bola.

  1. /**
  2. * Class Ball adalah class yang berfungsi untuk mengatur bola
  3. *
  4. * @author Sabrina Lydia S
  5. * @version 21/12/20
  6. */
  7.  
  8. import java.awt.Color;
  9. import java.awt.Graphics;
  10. import java.util.Random;
  11. public class Ball
  12. {
  13. public int x, y, width = 25, height = 25;
  14. public int motionX, motionY;
  15. public Random random;
  16. private Pong pong;
  17. public int amountOfHits;
  18. public Ball(Pong pong)
  19. {
  20. this.pong = pong;
  21. this.random = new Random();
  22. spawn();
  23. }
  24. public void update(Paddle paddle1, Paddle paddle2)
  25. {
  26. int speed = 5;
  27. this.x += motionX * speed;
  28. this.y += motionY * speed;
  29. if (this.y + height - motionY > pong.height || this.y + motionY < 0)
  30. {
  31. if (this.motionY < 0)
  32. {
  33. this.y = 0;
  34. this.motionY = random.nextInt(4);
  35. if (motionY == 0)
  36. {
  37. motionY = 1;
  38. }
  39. }
  40. else
  41. {
  42. this.motionY = -random.nextInt(4);
  43. this.y = pong.height - height;
  44. if (motionY == 0)
  45. {
  46. motionY = -1;
  47. }
  48. }
  49. }
  50. if (checkCollision(paddle1) == 1)
  51. {
  52. this.motionX = 1 + (amountOfHits / 5);
  53. this.motionY = -2 + random.nextInt(4);
  54. if (motionY == 0)
  55. {
  56. motionY = 1;
  57. }
  58. amountOfHits++;
  59. }
  60. else if (checkCollision(paddle2) == 1)
  61. {
  62. this.motionX = -1 - (amountOfHits / 5);
  63. this.motionY = -2 + random.nextInt(4);
  64. if (motionY == 0)
  65. {
  66. motionY = 1;
  67. }
  68. amountOfHits++;
  69. }
  70. if (checkCollision(paddle1) == 2)
  71. {
  72. paddle2.score++;
  73. spawn();
  74. }
  75. else if (checkCollision(paddle2) == 2)
  76. {
  77. paddle1.score++;
  78. spawn();
  79. }
  80. }
  81.  
  82. public void spawn()
  83. {
  84. this.amountOfHits = 0;
  85. this.x = pong.width / 2 - this.width / 2;
  86. this.y = pong.height / 2 - this.height / 2;
  87. this.motionY = -2 + random.nextInt(4);
  88. if (motionY == 0)
  89. {
  90. motionY = 1;
  91. }
  92. if (random.nextBoolean())
  93. {
  94. motionX = 1;
  95. }
  96. else
  97. {
  98. motionX = -1;
  99. }
  100. }
  101.  
  102. public int checkCollision(Paddle paddle)
  103. {
  104. if (this.x < paddle.x + paddle.width && this.x + width > paddle.x && this.y < paddle.y + paddle.height && this.y + height > paddle.y)
  105. {
  106. return 1; //bounce
  107. }
  108. else if ((paddle.x > x && paddle.paddleNumber == 1) || (paddle.x < x - width && paddle.paddleNumber == 2))
  109. {
  110. return 2; //score
  111. }
  112. return 0; //nothing
  113. }
  114.  
  115. public void render(Graphics g)
  116. {
  117. g.setColor(Color.RED);
  118. g.fillOval(x, y, width, height);
  119. }
  120. }

3. Class Paddle
Class paddle memiliki fungsi untuk mengatur semua yang berkaitan dengan paddle (stik pemukul), seperti bentuk, ukuran dan warna serta mengatur alas permainan.

  1. /**
  2. * Class Paddle adalah class untuk mengatur paddle (stik pemukul)
  3. *
  4. * @author Sabrina Lydia S
  5. * @version 21/12/20
  6. */
  7.  
  8.  
  9. import java.awt.Color;
  10. import java.awt.Graphics;
  11. public class Paddle
  12. {
  13. public int paddleNumber;
  14. public int x, y, width = 50, height = 250;
  15. public int score;
  16. public Paddle(Pong pong, int paddleNumber)
  17. {
  18. this.paddleNumber = paddleNumber;
  19. if (paddleNumber == 1)
  20. {
  21. this.x = 0;
  22. }
  23. if (paddleNumber == 2)
  24. {
  25. this.x = pong.width - width;
  26. }
  27. this.y = pong.height / 2 - this.height / 2;
  28. }
  29.  
  30. public void render(Graphics g)
  31. {
  32. g.setColor(Color.GREEN);
  33. g.fillRect(x, y, width, height);
  34. }
  35.  
  36. public void move(boolean up)
  37. {
  38. int speed = 15;
  39. if (up)
  40. {
  41. if (y - speed > 0)
  42. {
  43. y -= speed;
  44. }
  45. else
  46. {
  47. y = 0;
  48. }
  49. }
  50. else
  51. {
  52. if (y + height + speed < Pong.pong.height)
  53. {
  54. y += speed;
  55. }
  56. else
  57. {
  58. y = Pong.pong.height - height;
  59. }
  60. }
  61. }
  62. }

4. Class Renderer
Class ini memiliki fungsi untuk mengatur tampilan dasar grafik dari game.

  1. /**
  2. * Class Renderer adalah class yang berfungsi mengatur tampilan dasar.
  3. *
  4. * @author Sabrina Lydia S
  5. * @version 21/12/20
  6. */
  7.  
  8.  
  9. import java.awt.Graphics;
  10. import java.awt.Graphics2D;
  11. import javax.swing.JPanel;
  12. public class Renderer extends JPanel
  13. {
  14. private static final long serialVersionUID = 1L;
  15. @Override
  16. protected void paintComponent(Graphics g)
  17. {
  18. super.paintComponent(g);
  19. Pong.pong.render((Graphics2D) g);
  20. }
  21. }

Cara Menjalankan dan Memainkan

1. Klik kanan pada Class Pong => void main(String[] args) =>pada method call klik OK


2. Masuk ke tampilan awal game



        Di sini kita bisa bermain dengan dua player dengan cara menekan space ataupun menekan SHIFT jika kita ingin bermain bersama bot. Untuk mengatur score limit pada permainan, kita bisa menggunakan tombol panah pada keyboard.

3. Tampilan bermain dengan bot


        Saat bermain dengan bot, kita bisa memilih tingkat kesulitan mulai dari easy sampai difficult dengan menekan tanda panah.

4. Mode Permainan
Tekan ENTER untuk memulai permainan


Tekan ENTER lagi untuk pause


5. Tampilan Akhir Permainan

-Terima kasih-


Komentar

Postingan populer dari blog ini

Ticket Machine

ETS PWEB-A

Tugas 10 PBKK