Facebook SDK

Game Initialization
In this section, we set up the initial game environment:
- We create a new JFrame, which represents the game window.
- We define the window's size, title, and close operation.
- The `snake` ArrayList is used to store the snake's segments, starting with the snake's initial position at the center of the window.
- We initialize the `food` Point to a fixed initial position.
- A `Timer` is used to create a game loop, which triggers the `actionPerformed` method at regular intervals to update the game state.
 


 

Game Loop
The game loop is responsible for the continuous execution of the game. It consists of the `actionPerformed` method:
- Inside the `actionPerformed` method, we check if the game is not over (`isGameOver` is `false`).
- If the game is not over, we call the `move` method to move the snake, followed by collision checks using the `checkCollision` method.
- Finally, we repaint the screen to reflect the updated game state.
 

Snake Movement
Snake movement is controlled based on player input:
- We have a `direction` variable (0: up, 1: right, 2: down, 3: left) to track the snake's current direction.
- In the `move` method, we determine the new head position based on the direction.
- The snake is represented as a list of `Point` objects, with the new head being inserted at the beginning and the tail removed to maintain the snake's length.
 

 Food Generation
Food generation ensures that food appears at random positions on the game board:
- We use a `Random` object to generate random coordinates for the food.
- We ensure that the food does not appear on the snake's body to prevent instant collision.

Collision Detection
Collision detection checks for collisions with walls and the snake's body:
- We check if the snake's head has hit the game board's boundaries, indicating a collision with the wall.
- We also check if the snake's head collides with any of its body segments, indicating a self-collision.
- If either collision occurs, we set `isGameOver` to `true`, indicating the end of the game.
 

 Double-Buffering
To eliminate screen flickering, we use double-buffering:
- We create an off-screen buffer (`buffer`) using the `createImage` method.
- The game elements (snake, food, and game over message) are drawn on the off-screen buffer.
- After drawing, we display the off-screen buffer on the screen using `g.drawImage`, preventing flickering during screen updates.
 

Running the Game
In the `main` method, we initialize the game and make it visible to the player:
- We create an instance of `SnakeGame` and set it as visible.
- Players can control the snake using arrow keys.
- The game loop runs continuously until the player loses by colliding with a wall or the snake's body.

 

Complete code Below

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Random;

public class SnakeGame extends JFrame implements ActionListener {
    private static final int WIDTH = 300;
    private static final int HEIGHT = 300;
    private static final int TILE_SIZE = 10;
    private static final int DELAY = 100;

    private ArrayList<Point> snake;
    private Point food;
    private int direction; // 0: up, 1: right, 2: down, 3: left
    private boolean isGameOver;

    public SnakeGame() {
        setTitle("Snake Game");
        setSize(WIDTH, HEIGHT);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setResizable(false);

        snake = new ArrayList<>();
        snake.add(new Point(WIDTH / 2, HEIGHT / 2)); // Initial position at the center
        food = new Point(100, 100); // Initial food position

        Timer timer = new Timer(DELAY, this);
        timer.start();

        addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                changeDirection(e.getKeyCode());
            }
        });

        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
    }

    public void actionPerformed(ActionEvent e) {
        if (!isGameOver) {
            move();
            checkCollision();
            repaint();
        }
    }

    private void move() {
        // Move the snake
        Point newHead = snake.get(0);
        switch (direction) {
            case 0: // Up
                newHead = new Point(newHead.x, newHead.y - TILE_SIZE);
                break;
            case 1: // Right
                newHead = new Point(newHead.x + TILE_SIZE, newHead.y);
                break;
            case 2: // Down
                newHead = new Point(newHead.x, newHead.y + TILE_SIZE);
                break;
            case 3: // Left
                newHead = new Point(newHead.x - TILE_SIZE, newHead.y);
                break;
        }

        snake.add(0, newHead);

        // Check if the snake ate the food
        if (newHead.equals(food)) {
            generateFood();
        } else {
            snake.remove(snake.size() - 1);
        }
    }

    private void generateFood() {
        Random rand = new Random();
        int maxX = WIDTH / TILE_SIZE;
        int maxY = HEIGHT / TILE_SIZE;

        int foodX = rand.nextInt(maxX) * TILE_SIZE;
        int foodY = rand.nextInt(maxY) * TILE_SIZE;

        food = new Point(foodX, foodY);
    }

    private void checkCollision() {
        Point head = snake.get(0);

        // Check if the snake collided with the walls
        if (head.x < 0 || head.x >= WIDTH || head.y < 0 || head.y >= HEIGHT) {
            isGameOver = true;
            return;
        }

        // Check if the snake collided with itself
        for (int i = 1; i < snake.size(); i++) {
            if (head.equals(snake.get(i))) {
                isGameOver = true;
                return;
            }
        }
    }

    private void changeDirection(int keyCode) {
        switch (keyCode) {
            case KeyEvent.VK_UP:
                if (direction != 2) // Avoid reversing direction
                    direction = 0;
                break;
            case KeyEvent.VK_RIGHT:
                if (direction != 3)
                    direction = 1;
                break;
            case KeyEvent.VK_DOWN:
                if (direction != 0)
                    direction = 2;
                break;
            case KeyEvent.VK_LEFT:
                if (direction != 1)
                    direction = 3;
                break;
        }
    }

    public void paint(Graphics g) {
        super.paint(g);

        // Double-buffering: Create an off-screen buffer to draw on
        Image buffer = createImage(getWidth(), getHeight());
        Graphics offscreen = buffer.getGraphics();

        if (isGameOver) {
            offscreen.setColor(Color.RED);
            offscreen.drawString("Game Over", WIDTH / 2 - 30, HEIGHT / 2);
        } else {
            // Draw the snake on the off-screen buffer
            offscreen.setColor(Color.GREEN);
            for (Point segment : snake) {
                offscreen.fillRect(segment.x, segment.y, TILE_SIZE, TILE_SIZE);
            }

            // Draw the food on the off-screen buffer
            offscreen.setColor(Color.RED);
            offscreen.fillRect(food.x, food.y, TILE_SIZE, TILE_SIZE);
        }

        // Draw the off-screen buffer on the screen
        g.drawImage(buffer, 0, 0, this);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            SnakeGame game = new SnakeGame();
            game.setVisible(true);
        });
    }

Conclusion
The tutorial concludes by suggesting ways to expand and enhance the game, such as adding scoring, levels, and more complex graphics. It encourages readers to use and modify the code for their own game development projects.

Post a Comment

Previous Post Next Post