A simple Game of Life implementation in Java
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 lines
6.6 KiB

  1. package edu.stuy.goldfish;
  2. import java.awt.*;
  3. import java.awt.event.*;
  4. import java.awt.image.*;
  5. import javax.swing.*;
  6. public class Render extends Canvas implements Runnable, MouseListener,
  7. MouseMotionListener, ActionListener, ItemListener {
  8. private static final long serialVersionUID = 1L;
  9. public static String title = "Goldfish";
  10. public static int width;
  11. public static int height;
  12. public static int scale;
  13. public static int max_fps = 15;
  14. public boolean paused;
  15. public String rule;
  16. public boolean reset;
  17. private Grid _grid;
  18. private int[] _pixels;
  19. private BufferedImage _image;
  20. private long _lastTick;
  21. private String[] _rules;
  22. private JFrame _frame;
  23. private JButton pauseButton;
  24. public Render(int width, int height, Grid g, String[] rules) {
  25. addMouseListener(this);
  26. addMouseMotionListener(this);
  27. Render.width = width;
  28. Render.height = height;
  29. setScale();
  30. paused = false;
  31. reset = false;
  32. rule = rules[0];
  33. _grid = g;
  34. _image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  35. _pixels = ((DataBufferInt) _image.getRaster().getDataBuffer()).getData();
  36. _lastTick = 0;
  37. _rules = rules;
  38. Dimension size = new Dimension(width * scale, height * scale);
  39. setPreferredSize(size);
  40. setFrame();
  41. }
  42. public Render(int width, int height, Grid g) {
  43. this(width, height, g, new String[0]);
  44. }
  45. public Render(int width, int height) {
  46. this(width, height, new Grid(width, height));
  47. }
  48. public Render() {
  49. this(256, 256);
  50. }
  51. private void setScale() {
  52. if (height <= 128 || width <= 128) {
  53. Render.scale = 4;
  54. } else if (height <= 256 || width <= 256) {
  55. Render.scale = 2;
  56. } else {
  57. Render.scale = 1;
  58. }
  59. }
  60. private void setFrame() {
  61. JMenuBar menuBar = new JMenuBar();
  62. JMenu menuMain = new JMenu("Menu");
  63. JMenu menuAlgo = new JMenu("Algorithms");
  64. for (String rule : _rules) {
  65. JMenuItem menuAlgoItem = new JMenuItem(rule);
  66. menuAlgo.add(menuAlgoItem);
  67. menuAlgoItem.addActionListener(this);
  68. }
  69. menuMain.add(menuAlgo);
  70. menuBar.add(menuMain);
  71. pauseButton = new JButton("Pause");
  72. pauseButton.setActionCommand("pause");
  73. menuBar.add(pauseButton);
  74. pauseButton.addActionListener(this);
  75. JButton resetButton = new JButton("Reset");
  76. resetButton.setActionCommand("reset");
  77. menuBar.add(resetButton);
  78. resetButton.addActionListener(this);
  79. JButton clearButton = new JButton("Clear");
  80. clearButton.setActionCommand("clear");
  81. menuBar.add(clearButton);
  82. clearButton.addActionListener(this);
  83. _frame = new JFrame();
  84. _frame.setJMenuBar(menuBar);
  85. _frame.setResizable(false);
  86. _frame.setTitle(title);
  87. _frame.add(this);
  88. _frame.pack();
  89. _frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  90. _frame.setLocationRelativeTo(null);
  91. _frame.setVisible(true);
  92. }
  93. private void update() {
  94. int state;
  95. int states = Goldfish.getMaxStates(rule);
  96. for (int i = 0; i < width; i++) {
  97. for (int j = 0; j < height; j++) {
  98. state = _grid.getPatch(i, j).getState();
  99. if (_pixels[i + j * width] == state) {
  100. } else {
  101. draw(i, j, (int) ((state / ((double) states - 1)) * 0xffffff));
  102. }
  103. }
  104. }
  105. }
  106. public void run() {
  107. BufferStrategy bs;
  108. Graphics g;
  109. bs = getBufferStrategy();
  110. if (bs == null) {
  111. createBufferStrategy(1);
  112. return;
  113. }
  114. update();
  115. g = bs.getDrawGraphics();
  116. g.drawImage(_image, 0, 0, getWidth(), getHeight(), null);
  117. g.dispose();
  118. bs.show();
  119. }
  120. public void sleep() {
  121. long since = System.currentTimeMillis() - _lastTick;
  122. if (since < 1000 / max_fps) {
  123. try {
  124. Thread.sleep(1000 / max_fps - since);
  125. } catch (InterruptedException e) {
  126. return;
  127. }
  128. }
  129. _lastTick = System.currentTimeMillis();
  130. }
  131. public void setGrid(Grid g) {
  132. _grid = g;
  133. }
  134. public void draw(int x, int y, int color) {
  135. _pixels[x + y * width] = color;
  136. }
  137. public void clear() {
  138. for (int i = 0; i < _grid.getHeight(); i++) {
  139. for (int j = 0; j < _grid.getWidth(); j++) {
  140. _grid.getPatch(i, j).setState(0);
  141. }
  142. }
  143. }
  144. @Override
  145. public void mouseDragged(MouseEvent e) {
  146. int states = Goldfish.getMaxStates(rule) - 1;
  147. if (e.getX() < 0 || e.getY() < 0 || e.getX() / scale > width || e.getY() / scale > height)
  148. return;
  149. _grid.getPatch(e.getX() / scale, e.getY() / scale).setState(states);
  150. e.consume();
  151. }
  152. @Override
  153. public void mouseClicked(MouseEvent e) {
  154. int states = Goldfish.getMaxStates(rule) - 1;
  155. _grid.getPatch(e.getX() / scale, e.getY() / scale).setState(states);
  156. e.consume();
  157. }
  158. @Override
  159. public void mouseEntered(MouseEvent e) {
  160. }
  161. @Override
  162. public void mouseExited(MouseEvent e) {
  163. }
  164. @Override
  165. public void mousePressed(MouseEvent e) {
  166. int states = Goldfish.getMaxStates(rule) - 1;
  167. _grid.getPatch(e.getX() / scale, e.getY() / scale).setState(states);
  168. e.consume();
  169. }
  170. @Override
  171. public void mouseReleased(MouseEvent e) {
  172. }
  173. @Override
  174. public void mouseMoved(MouseEvent e) {
  175. }
  176. // Affects the algorithms menu
  177. @Override
  178. public void actionPerformed(ActionEvent event) {
  179. if ("pause".equals(event.getActionCommand())) {
  180. if (paused) {
  181. paused = false;
  182. pauseButton.setText("Pause");
  183. } else {
  184. paused = true;
  185. pauseButton.setText("Unpause");
  186. }
  187. } else if ("reset".equals(event.getActionCommand())) {
  188. clear();
  189. reset = true;
  190. } else if ("clear".equals(event.getActionCommand())) {
  191. clear();
  192. } else {
  193. rule = event.getActionCommand();
  194. }
  195. }
  196. @Override
  197. public void itemStateChanged(ItemEvent event) {
  198. }
  199. }