Tutorial [Java]: Creating a Snake Game [Part 02] - Game Engine

Note: I have completely rewritten and improved this game. Most of my traffic comes from these posts, so I've not deleted them. Please use the new version which can be found here.

At the heart of every game is the engine. The engine is responsible for updating the game at fixed intervals, in response to events, or a combination of the two. In the case of the Snake Game, we need to update the game at regular intervals, and accept user input from the Keyboard. This part of the lesson will explain how to setup the basic game engine, which we will add functionality to as we develop the game.

To start, we're going to create a new class and name it Engine. This class will be responsible for handling most of the game's logic, the game loop, and window creation. We will return to this class throughout the tutorial as we add functionality to the game.

The first thing we must do is create the window to render on, so we'll start by creating the main method, and adding the gui code into it.

public static void main(String[] args) {
 /*
  * Create a new JFrame and set it's properties up.
  */
 JFrame frame = new JFrame("Snake Game");
 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 frame.setResizable(false);
 
 /*
  * Create a new canvas, and set it's properties up.
  */
 Canvas canvas = new Canvas();
 canvas.setBackground(Color.BLACK);
 canvas.setPreferredSize(new Dimension(500, 500));
 
 /*
  * Add the canvas to the frame.
  */
 frame.add(canvas);
 
 /*
  * Pack the frame, position it in the center of the screen, and then display
  * it.
  */
 frame.pack();
 frame.setLocationRelativeTo(null);
 frame.setVisible(true);
}

If we run the code now, we'll see a basic swing window appear on the screen. While this is nice and all, there's really no way of interacting with it yet. That's where the Engine class comes in. First, we'll create the constructor and pass our instance of the canvas to it, so that we may use it later for rendering.

/*
 * The canvas instance that we draw to.
 */
private Canvas canvas;

/*
 * Creates a new Engine instance.
 * @param canvas The canvas instance we're drawing onto.
 */
private Engine(Canvas canvas) {
 this.canvas = canvas;
}

While we're at it, let's also create the startGame method and add it to the class. This is the meat and potatoes of the class, as it will contain the game loop, and rendering context information. I'll post the entire method and explain what each part does in the comments.

/*
 * The number of times to update the game per second.
 */
private static final int UPDATES_PER_SECOND = 10;

/**
 * Responsible for setting up and retrieving the rendering context, then maintaining
 * the game loop.
 */
public void startGame() {
 /*
  * Create the buffers and get the graphics.
  */
 canvas.createBufferStrategy(2);
  
 /*
  * Grab a reference to the graphics object.
  */
 Graphics2D g = (Graphics2D)canvas.getBufferStrategy().getDrawGraphics();
  
 /*
  * Create the variables that keep the loop executing at a constant framerate.
  */
 long start = 0L;
 long sleepDuration = 0L;
 
 /*
  * The game loop will continue to click until the program ends.
  */
 while(true) {

  /*
   * Set the time that the loop started.
   */
  start = System.currentTimeMillis();
  
  /*
   * Update the game.
   */
  update();
   
  /*
   * Draw the game onto the graphics object.
   */
  render(g);
  
  /*
   * Display the graphics onto the screen.
   */
  canvas.getBufferStrategy().show();

  /*
   * Clear the screen so we draw a fresh frame next time.
   */
   g.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
   
  /*
   * Set the time that the loop finished.
   */
  sleepDuration = (1000L / UPDATES_PER_SECOND) - (System.currentTimeMillis() - start);
   
  /*
   * If the sleep duration is greater than 0 milliseconds, attempt to sleep.
   */
  if(sleepDuration > 0) {
   try {
    Thread.sleep(sleepDuration);
   } catch(Exception e) {
    e.printStackTrace();
   }
  }
 }
}

/*
 * Update the game's logic.
 */
private void update() {
 //Empty for now, we'll fill this in later.
}

/*
 * Draw the game onto the graphics object.
 */
private void render(Graphics2D g) {
 //Empty for now, we'll fill this in later.
}


The last thing we need to do now is create an instance of the engine in the main method.

//Window creation code...

 /*
  * Create the engine and start the game.
  */
 Engine engine = new Engine(canvas);
 engine.startGame();
}

If we run the game now, we'll have an empty game loop that we can play around with, which enables us to start implementing the game logic. Anyway, that's all for now, next time I'll cover how the game board works.

Posted in , , , , , , . Bookmark the permalink. RSS feed for this post.

15 Responses to Tutorial [Java]: Creating a Snake Game [Part 02] - Game Engine

  1. Hi I am a very beginner in programming.To learn programing we use a learning software "Greenfoot".Greenfoot uses Java language. Here is the link for the information about greenfoot http://www.greenfoot.org/home.
    okay, in greenfoot, we mainly have two classes- 1. World and 2. Actor. We just add subclusses with those two classes if we need. The perpose of world class is to give a nice background and placing the object according to our wish. Now my questions are:
    1. What is Jframe in your codes?
    2. Where I can write those codes in my greenfoot? In World class?
    3. Is it okay if we don't create any engine class?

    ReplyDelete
    Replies
    1. 1. A JFrame is just a window that the GUI will be displayed on, and is part of the Swing API. You can learn more about them here (http://docs.oracle.com/javase/tutorial/uiswing/components/frame.html)

      2. I've never heard of Greenfoot until now, so I'm not entirely sure how it works. However, it seems as though it's just a simple engine that handles most of the low-level stuff for you, so you really only need to worry about the game logic itself.

      3. If you're using Greenfoot, it looks as though you'd create a new class that extends the "World" class rather than writing an Engine class as I did.

      Delete
  2. Im getting an an error with the engine creation? any thoughts

    ReplyDelete
    Replies
    1. I am having the same issue.
      Without the JFrame added(), it can't init the methods.
      When I add the dang thing, it spits out the usual, you need another dozen ";;;;;;"

      Delete
    2. I got the solution here

      when copy the code of engine creation
      don't copy the curly brace "}"
      that's it

      hope it helps :D

      Delete
  3. Where Could I Place the Engine Constructor?

    ReplyDelete
  4. Where Could I Place the Engine Constructor?

    ReplyDelete
  5. Hi, why is frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    giving me the error
    - Syntax error on token ".", ... expected
    - Syntax error on token "setDefaultCloseOperation", Identifier expected after this token


    and
    frame.setResizable(false);

    giving me the error
    - Syntax error on token(s), misplaced construct(s)
    - Syntax error on token "false", delete this token

    ?

    Thanks!

    ReplyDelete
  6. hey, so what we got here? 2 class, a GUI Class which has the Windows and Canvas and Another Engine Class?

    ReplyDelete
  7. g.clearRect(canvas.getWidth(), canvas.getHeight());
    this line is an error. i dont know how to fix it. it says it requires 4 ints, but only two are found..reason: actual and formal argument lists differ in length... i tried g.clearRect(canvas.getWidth(), canvas.getHeight(), 0, 0); it run but the window didn't appear because of so many bugs.. can u please help me ??

    i'm using Netbeans BTW :D
    thank you so much ..

    ReplyDelete
    Replies
    1. I'm not sure why my code is missing the first two parameters, it should be g.clearRect(x, y, width, height); so the call should be g.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); Sorry about that!

      Also, I should note that this series was very poorly thought out, so it's kind of an ugly mess. I've created a newer version that improves on a lot of things here: http://psnbtech.blogspot.com/2012/10/tutorial-java-snake-game-remake.html

      If you still want to use this version, you can skip to the last part (part 7) and check out the source code.

      Delete
  8. When I try to run it it shows an error (in Eclipse):
    Exception in thread "main" java.lang.Error: Unresolved compilation problem:

    at Engine.main(Engine.java:11)
    It redirects to: public static void main(String[] args) {

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. Can I have a PDF file of this?

    ReplyDelete

Search

Swedish Greys - a WordPress theme from Nordic Themepark. Converted by LiteThemes.com.