Advertisement
SforzandoCF

snerk

Oct 22nd, 2024 (edited)
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.12 KB | None | 0 0
  1. public class SnakeGame {
  2.     private Snake player = new Snake();
  3.     private JFrame window = new JFrame("Snake");
  4.     private Timer timer = new Timer("Snake Ticker");
  5.     private SnakeGameSettings settings = SnakeGameSettings.readOrNew();
  6.     private int moveTimer = 0;
  7.     private StoringKeyListener listener = new StoringKeyListener();
  8.     private SnakeBoard board = new SnakeBoard(this.window.getGraphics().getClipBounds());
  9.    
  10.     private boolean paused = false;
  11.     private boolean pauseScreenDisplayed = false;
  12.    
  13.     Logger logger = new Logger();
  14.    
  15.     public SnakeGame () {
  16.         this.board.setPlayer(player);
  17.         this.board.refresh();
  18.     }
  19.    
  20.     public void start () {
  21.         this.timer.schedule(this.new FrameTask(), 0L, 1000L / this.settings.framerate);
  22.     }
  23.    
  24.     public void setPaused (boolean paused) {
  25.         this.paused = paused;
  26.     }
  27.    
  28.     void runFrame () {
  29.         if (this.paused) this.runPausedFrame();
  30.         if (this.pauseScreenDisplayed) this.accessPauseScreen(false, false);
  31.         if (this.settings.getDifficulty().isSatisfied(this.moveTimer)) {
  32.             if (!this.player.move()) this.gameOver();
  33.             this.moveTimer = 0;
  34.         } else {
  35.             this.moveTimer++;
  36.         }
  37.         if (this.listener.up()) this.player.addBuffered(Snake.BUFFERED_INPUT_UP);
  38.         if (this.listener.down()) this.player.addBuffered(Snake.BUFFERED_INPUT_DOWN);
  39.         if (this.listener.left()) this.player.addBuffered(Snake.BUFFERED_INPUT_LEFT);
  40.         if (this.listener.right()) this.player.addBuffered(Snake.BUFFERED_INPUT_RIGHT);
  41.         if (this.listener.escape()) this.setPaused(true);
  42.         this.keyListener.reset();
  43.         if (this.window.isFocused()) this.renderFrame();
  44.     }
  45.    
  46.     void renderFrame () {
  47.         Graphics g = this.window.getGraphics();
  48.         g.setColor(Color.BLACK);
  49.         Rectangle clip = g.getClipBounds();
  50.         g.fillRect(clip.getX(), clip.getY(), clip.getWidth(), clip.getHeight());
  51.         g.setColor(Color.RED);
  52.         for (Point p : this.board.getApples())
  53.             g.fillRect((p.getX() * 8) + 1, (p.getY() * 8) + 1, 6, 6);
  54.         List<Snake.Segment> snake = Arrays.asList(this.player.getSegments());
  55.         g.setColor(Color.GREEN);
  56.         for (Snake.Segment s : snake) {
  57.             if (s.getFacingDirection() == Snake.Segment.DIRECTION_DOWN || s.getOriginDirection() == Snake.Segment.DIRECTION_DOWN)
  58.                 g.fillRect((s.getPos().getX() * 8) + 1, (s.getPos().getX() * 8) + 7, 6, 1);
  59.             if (s.getFacingDirection() == Snake.Segment.DIRECTION_UP || s.getOriginDirection() == Snake.Segment.DIRECTION_UP)
  60.                 g.fillRect((s.getPos().getX() * 8) + 1, (s.getPos().getX() * 8) + 0, 6, 1);
  61.             if (s.getFacingDirection() == Snake.Segment.DIRECTION_LEFT || s.getOriginDirection() == Snake.Segment.DIRECTION_LEFT)
  62.                 g.fillRect((s.getPos().getX() * 8) + 0, (s.getPos().getX() * 8) + 1, 1, 6);
  63.             if (s.getFacingDirection() == Snake.Segment.DIRECTION_RIGHT || s.getOriginDirection() == Snake.Segment.DIRECTION_RIGHT)
  64.                 g.fillRect((s.getPos().getX() * 8) + 7, (s.getPos().getX() * 8) + 1, 1, 6);
  65.             g.fillRect((s.getPos().getX() * 8) + 7, (s.getPos().getX() * 8) + 1, 1, 6);
  66.         }
  67.     }
  68.    
  69.     void closeGame () {
  70.         this.window.dispose();
  71.         this.timer.cancel();
  72.         this.settings.save();
  73.         this.board.dispose();
  74.     }
  75.    
  76.     void runPausedFrame () {
  77.         if (!this.paused) return;
  78.         if (!this.pauseScreenDisplayed) this.accessPauseScreen(true, false);
  79.         if (this.listener.escape()) this.setPaused(false);
  80.     }
  81.    
  82.     void accessPauseScreen (boolean show, boolean settings) {
  83.         if (show) {
  84.             if (settings)
  85.                 this.window.add(this.newPauseScreen(), PAUSE_SCREEN_INDEX);
  86.             else
  87.                 this.window.add(this.newSettingsScreen(), PAUSE_SCREEN_INDEX);
  88.         } else {
  89.             Component pauseScreen = this.window.get(PAUSE_SCREEN_INDEX);
  90.             this.window.remove(pauseScreen);
  91.             if (pauseScreen instanceof Container c) c.removeAll();
  92.         }
  93.         this.pauseScreenDisplayed = show;
  94.     }
  95.    
  96.     JPanel newPauseScreen () {
  97.         JPanel pauseScreen = new JPanel(new FlowLayout(FlowLayout.CENTER));
  98.         JButton settingsB = new JButton("Settings");
  99.         settingsB.setBackground(Color.GRAY);
  100.         settingsB.setForeground(Color.BLACK);
  101.         settingsB.addActionListener((e) -> { this.accessPauseScreen(true, true); });
  102.         pauseScreen.add(settingsB);
  103.         JButton exitB = new JButton("Exit game");
  104.         exitB.setBackground(Color.RED);
  105.         exitB.setForeground(Color.WHITE);
  106.         exitB.addActionListener((e) -> { this.closeGame(); });
  107.         pauseScreen.add(exitB);
  108.         return pauseScreen;
  109.     }
  110.    
  111.     JPanel newSettingsScreen () {
  112.         JPanel pauseScreen = new JPanel(new FlowLayout(FlowLayout.CENTER));
  113.         JLabel framerateL = new JLabel("Framerate");
  114.         framerateL.setBackground(new Color(0, 0, 0, 0));
  115.         framerateL.setForeground(Color.WHITE);
  116.         pauseScreen.add(framerateL);
  117.         JSlider framerateS = new JSlider(JSlider.HORIZONTAL, 60, 360, 60);
  118.         framerateS.addChangeListener((e) -> { this.settings.setFramerate(((JSlider)e.getSource()).getValue()); });
  119.         framerateS.setBackground(new Color(0, 0, 0, 0));
  120.         pauseScreen.add(framerateS);
  121.         JLabel difficultyL = new JLabel("Difficulty");
  122.         difficultyL.setBackground(new Color(0, 0, 0, 0));
  123.         difficultyL.setForeground(Color.WHITE);
  124.         pauseScreen.add(difficultyL);
  125.         JSlider difficultyS = new JSlider(JSlider.HORIZONTAL, 0, 1, 3);
  126.         difficultyS.addChangeListener((e) -> { this.settings.setDifficulty(((JSlider)e.getSource()).getValue()); });
  127.         difficultyS.setBackground(new Color(0, 0, 0, 0));
  128.         pauseScreen.add(difficultyS);
  129.         return pauseScreen;
  130.     }
  131.    
  132.     class FrameTask extends TimerTask {
  133.         private CompletableFuture<Void> lastFrame = CompletableFuture.runAsync(() -> { lastFrame.cancel(true); });
  134.        
  135.         public void run () {
  136.             if (this.lastFrame.isCompletedExceptionally()) {
  137.                 try {
  138.                     this.lastFrame.cancel(true);
  139.                     this.lastFrame.get();
  140.                 } catch (ExecutionException ee) {
  141.                     this.super.logger.error("Frame completion failed due to:\n");
  142.                     ee.printStackTrace(this.super.logger);
  143.                 } catch (CancellationException ce) {
  144.                     this.super.logger.warn("Frame completion was cancelled");
  145.                 } catch (InterruptedException ie) {
  146.                     throw new IllegalStateException("Thread timed out while waiting for last frame to complete");
  147.                 }
  148.                 return;
  149.             }
  150.             if (!this.lastFrame.isDone()) {
  151.                 this.super.logger.warn("Lag frame occured");
  152.                 return;
  153.             }
  154.             this.lastFrame = CompletableFuture.runAsync(this.super::runFrame);
  155.         }
  156.     }
  157. }
  158.  
  159. public class Logger extends PrintStream {
  160.     private final boolean debug;
  161.     private final PrintStream out;
  162.    
  163.     public Logger () {
  164.         this (false, System.out);
  165.     }
  166.    
  167.     public Logger (PrintStream out) {
  168.         this (false, out);
  169.     }
  170.    
  171.     public Logger (boolean debug) {
  172.         this (debug, System.out);
  173.     }
  174.    
  175.     public Logger (boolean debug, PrintStream out) {
  176.         super (out);
  177.         this.debug = debug;
  178.         this.out = out;
  179.     }
  180.    
  181.     public void log (String s) {
  182.         this.out.println("[ LOGGER: Log at " + Instant.now().toString() + " ]: " + s);
  183.     }
  184.    
  185.     public void warn (String s) {
  186.         this.out.println("[ LOGGER: Warning at " + Instant.now().toString() + " ]: " + s);
  187.     }
  188.    
  189.     public void error (String s) {
  190.         this.out.println("[ LOGGER: Fatal error occured at " + Instant.now().toString() + " ]: " + s);
  191.     }
  192. }
  193.  
  194. public class StoringKeyListener implements KeyListener {
  195.     private boolean up = false;
  196.    
  197.     public boolean up () {
  198.         boolean b = this.up;
  199.         this.up = false;
  200.         return b;
  201.     }
  202.    
  203.     private boolean down = false;
  204.    
  205.     public boolean down () {
  206.         boolean b = this.down;
  207.         this.down = false;
  208.         return b;
  209.     }
  210.    
  211.     private boolean left = false;
  212.    
  213.     public boolean left () {
  214.         boolean b = this.left;
  215.         this.left = false;
  216.         return b;
  217.     }
  218.    
  219.     private boolean right = false;
  220.    
  221.     public boolean right () {
  222.         boolean b = this.right;
  223.         this.right = false;
  224.         return b;
  225.     }
  226.    
  227.     private boolean escape = false;
  228.    
  229.     public boolean escape () {
  230.         boolean b = this.escape;
  231.         this.escape = false;
  232.         return b;
  233.     }
  234.    
  235.     public void keyPressed (KeyEvent evt) {
  236.         if (evt.getKeyCode() == KeyEvent.VK_W || evt.getKeyCode() == KeyEvent.VK_KP_UP) this.up = true;
  237.         if (evt.getKeyCode() == KeyEvent.VK_S || evt.getKeyCode() == KeyEvent.VK_KP_DOWN) this.down = true;
  238.         if (evt.getKeyCode() == KeyEvent.VK_A || evt.getKeyCode() == KeyEvent.VK_KP_LEFT) this.left = true;
  239.         if (evt.getKeyCode() == KeyEvent.VK_D || evt.getKeyCode() == KeyEvent.VK_KP_RIGHT) this.right = true;
  240.         if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) this.escape = true;
  241.     }
  242.    
  243.     public void keyReleased (KeyEvent evt) {
  244.         if (evt.getKeyCode() == KeyEvent.VK_W || evt.getKeyCode() == KeyEvent.VK_KP_UP) this.up = false;
  245.         if (evt.getKeyCode() == KeyEvent.VK_S || evt.getKeyCode() == KeyEvent.VK_KP_DOWN) this.down = false;
  246.         if (evt.getKeyCode() == KeyEvent.VK_A || evt.getKeyCode() == KeyEvent.VK_KP_LEFT) this.left = false;
  247.         if (evt.getKeyCode() == KeyEvent.VK_D || evt.getKeyCode() == KeyEvent.VK_KP_RIGHT) this.right = false;
  248.         if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) this.escape = false;
  249.     }
  250.    
  251.     public void keyTyped (KeyEvent evt) {}
  252. }
  253.  
  254. public class SnakeBoard {
  255.     private final Rectangle bounds;
  256.     private Snake player = null;
  257.     private Point[] apples;
  258.    
  259.     public SnakeBoard (Rectangle rect, int appleCount) {
  260.         this.bounds = new Rectangle(rect.getX() / 8, rect.getY() / 8, rect.getWidth() / 8, rect.getHeight() / 8);
  261.         this.apples = new Point[appleCount];
  262.     }
  263.    
  264.     public void setPlayer (Snake snake) {
  265.         this.player = snake;
  266.     }
  267.    
  268.     public void refresh () {
  269.         for (int i = 0; i <= this.apples.length; i++) {
  270.             boolean invalidApple = true;
  271.             while (invalidApple) {
  272.                 this.apples[i] = new Point(RandomGenerator.getDefault().nextInt(this.bounds.getWidth()) + this.bounds.getX(), RandomGenerator.getDefault().nextInt(this.bounds.getHeight()) + this.bounds.getY());
  273.                 for (Snake.Segment s : this.player.getSegments())
  274.                     if (s.getPos() != this.apples[i]) invalidApple = false;
  275.             }
  276.         }
  277.     }
  278.    
  279.     public Point[] getApples () {
  280.         return this.apples;
  281.     }
  282.    
  283.     public Rectangle getBounds () {
  284.         return this.bounds;
  285.     }
  286. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement