|
HOT TIP: you can freely browse the site while music plays

Loading...
Hypersausage

Estimated reading time: 5min 25s
Created: 6.3.2025, 17:41 - Updated: 6.3.2025, 20:04
6.2.2025, 17:51

2025-03-06_181554-area.png

Today I want to walk you through my implementation of Hypersausage, a Snake-like game using JavaScript, which I created for the Tunkki project. It's a worm game with a twist I invented. The game can be played on both your phone and computer. The game was implemented using artificial intelligence-assisted coding.

The Project Context

I developed Hypersausage as part of the Tunkki project for Entropy Ry. You can see it in action at entropy.fi/en/2025/e-x-h-lanit, where it serves as an interactive element on the E-X-H LAN event page.

Collaborating with AI

An interesting aspect of Hypersausage is that it's the result of coding with AI assistance. I wanted to test how AI could help with game development, and the process taught me some valuable lessons.

The main challenge I encountered was that the AI would sometimes forget the context and remove parts of the code that were already working correctly. To address this issue, I developed a strategy: whenever I had a section of code working properly, I would encapsulate it into a separate function. This made it easier for the AI to understand the context and avoid breaking functional code.

This modular approach not only helped in working with AI but also resulted in cleaner, more maintainable code overall.

Breaking Down My Implementation

Let me walk you through the key aspects of my code:

The Setup

export class SnakeGame {
  constructor() {
    this.canvas = document.getElementById("snake");
    this.ctx = this.canvas.getContext("2d");
    this.gameOn = true;
    this.highscore = 0;
    this.height = 600;
    this.width = 800;
    this.running = false;
    this.blockSize = 20;
    this.widthInBlocks = this.width / this.blockSize;
    this.heightInBlocks = this.height / this.blockSize;
    this.canvas.width = this.width;
    this.canvas.height = this.height;
    this.intervalId = 0;
    this.score = 0;
    this.speed = 90;
    this.colliding = false;
  }

The game uses a canvas-based approach. One important thing to note is that while I set default dimensions in the code, the actual canvas dimensions adapt to the user's screen size. Players can also adjust the play area by using browser zoom, which provides flexibility for different viewing environments.

The Snake Entity

this.snake = {
  body: [
    { x: 6, y: 4 },
    { x: 5, y: 4 },
    { x: 4, y: 4 },
  ],
  direction: "right",
  nextDirection: "right",
};

I decided to represent the snake as an array of coordinate objects. This approach makes it easy to:

  1. Add segments when the snake eats food
  2. Move the snake by adding a new head and removing the tail
  3. Check for collisions by comparing coordinates

Game Loop

For animation, I used a combination of requestAnimationFrame for smooth rendering and a custom interval for the game logic:

play() {
  let self = this;
  if (this.running === false) {
    this.intervalId = setInterval(function () {
      self.update();
    }, this.speed);
    this.running = true;
  }
}

Apple Generation

newApple() {
  const xCoordinate = Math.floor(Math.random() * (this.widthInBlocks - 2)) + 1;
  const yCoordinate = Math.floor(Math.random() * (this.heightInBlocks - 2)) + 1;

  this.apple = { x: xCoordinate, y: yCoordinate };

  if (this.checkCollision(this.apple.x, this.apple.y)) {
    this.newApple();
  }
}

This method generates a new apple at a random position. I used recursion to ensure that the apple doesn't appear on top of the snake - if a collision is detected, it simply tries again.

Movement Logic

I implemented direction changes with key listeners and added logic to prevent the snake from immediately reversing direction:

khangeDirection(newDirection) {
  if (this.snake.direction === "up" && newDirection === "down") {
    return;
  } else if (this.snake.direction === "right" && newDirection === "left") {
    return;
  } else if (this.snake.direction === "down" && newDirection === "up") {
    return;
  } else if (this.snake.direction === "left" && newDirection === "right") {
    return;
  }
  this.snake.nextDirection = newDirection;
}

Mobile version has totally different type of controls because there is no keyboard.

Collision Detection

The game checks for three types of collisions:

  1. With the wall boundaries
  2. With the snake's own body
  3. With the apple (for scoring)
checkCollision(x, y) {
  if (
    x < 0 ||
    x >= this.widthInBlocks ||
    y < 0 ||
    y >= this.heightInBlocks
  ) {
    return true;
  }

  for (let i = 0; i < this.snake.body.length; i++) {
    if (this.snake.body[i].x === x && this.snake.body[i].y === y) {
      return true;
    }
  }
  return false;
}

AI Collaboration Insights

Working with AI on this game taught me several valuable lessons about collaborative coding:

  1. Function Isolation: Breaking down code into smaller, well-defined functions helps AI understand the context better and prevents it from modifying critical, working code.

  2. Incremental Development: Getting small portions of the game working before moving to the next feature was essential when working with AI.

  3. Context Management: Consistently reminding the AI about the state of the application and what each function does helped maintain coherence.

  4. Review Process: Even with AI assistance, thorough code review was necessary to ensure everything worked as expected.

My Design Goals

When creating Hypersausage, I focused on several key aspects:

  1. Clean Code Organization: I structured the code as a class to make it easy to understand and maintain.

  2. Modern JavaScript: I used ES6+ features like classes and arrow functions to keep the code current.

  3. Separation of Concerns: I separated the rendering logic from the game logic for better maintainability, which also helped in working with AI.

  4. Responsive Design: I made the canvas dimensions adaptable to different screen sizes and zoom levels.

  5. Smart Collision Logic: I implemented a recursive approach to apple placement for fair gameplay.

See It in Action

You can play Hypersausage on the E-X-H LAN event page. I encourage you to try it out and see how the responsive canvas adapts to your screen and browser zoom settings.

Conclusion

Creating Hypersausage was not just about implementing a classic game concept but also exploring the potential of AI as a coding partner. The modularity that resulted from this collaboration has made the code more maintainable and easier to understand.

This project demonstrates that AI can be a valuable tool in game development when used with appropriate strategies. The key is understanding both the strengths and limitations of AI assistance and adapting your coding approach accordingly.