Skip to main content

Step 1: Basic Setup

Let's create the foundation for our Worm game. We'll set up a grid system and draw the worm's initial position.

Understanding the Grid System

Unlike Cookie Clicker where things move smoothly, Worm uses a grid-based system. The worm moves in discrete steps, one cell at a time.

// Grid settings
let cellSize = 20; // Each cell is 20x20 pixels
let cols, rows; // Number of columns and rows

Why use a grid?

  • Makes movement predictable and game-like
  • Simplifies collision detection
  • Classic retro game feel
  • Easy to align food and worm segments

Setting Up the Worm

The worm is made of segments. We'll store each segment as an object with x and y coordinates:

let worm = [];  // Array to hold all worm segments

Global Variables

Start by declaring all the variables we'll need:

// Grid settings
let cellSize = 20;
let cols, rows;

// Worm
let worm = [];

Breaking it down:

  • cellSize = 20 - Each grid cell is 20×20 pixels
  • cols, rows - Will calculate how many cells fit on screen
  • worm = [] - Empty array that will hold worm segment positions

The setup() Function

function setup() {
createCanvas(400, 400);

// Calculate grid dimensions
cols = width / cellSize;
rows = height / cellSize;

// Initialize worm in the center
let startX = floor(cols / 2);
let startY = floor(rows / 2);
worm.push({x: startX, y: startY});
}

Breaking it down:

Grid Calculation

cols = width / cellSize;
rows = height / cellSize;
  • width is 400 (canvas width)
  • 400 / 20 = 20 columns
  • Same for rows: 20 rows
  • This creates a 20×20 grid

Starting Position

let startX = floor(cols / 2);
let startY = floor(rows / 2);
  • cols / 2 gives us the middle column (10)
  • floor() rounds down to ensure it's a whole number
  • Starting position: (10, 10) - dead center of grid

Creating the Worm

worm.push({x: startX, y: startY});
  • push() adds a segment to the worm array
  • {x: startX, y: startY} is an object storing the position
  • Worm starts as just one segment (the head)
tip

Using an array for the worm makes it easy to add more segments later when it grows!

The draw() Function

Now let's draw the worm on screen:

function draw() {
background(50); // Dark gray background

// Draw grid lines (optional - helps visualize)
stroke(80);
strokeWeight(1);
for (let i = 0; i < cols; i++) {
line(i * cellSize, 0, i * cellSize, height);
}
for (let i = 0; i < rows; i++) {
line(0, i * cellSize, width, i * cellSize);
}

// Draw the worm
noStroke();
fill(0, 255, 0); // Green color
for (let i = 0; i < worm.length; i++) {
let segment = worm[i];
rect(segment.x * cellSize, segment.y * cellSize, cellSize, cellSize);
}
}

Breaking it down:

Background

background(50);
  • Dark gray background (50 on a 0-255 scale)
  • Creates nice contrast with the green worm

Grid Lines (Optional)

stroke(80);
strokeWeight(1);
for (let i = 0; i < cols; i++) {
line(i * cellSize, 0, i * cellSize, height);
}
  • Draws vertical lines to visualize the grid
  • i * cellSize positions each line
  • You can remove this once you understand the grid

Drawing the Worm

noStroke();
fill(0, 255, 0);
for (let i = 0; i < worm.length; i++) {
let segment = worm[i];
rect(segment.x * cellSize, segment.y * cellSize, cellSize, cellSize);
}
  • Loops through each segment in the worm array
  • segment.x * cellSize converts grid position to pixel position
    • Example: segment at grid (10, 10) → pixel (200, 200)
  • Draws a green square for each segment
info

Grid position vs Pixel position

  • Grid: (10, 10) means 10th cell across, 10th cell down
  • Pixels: (200, 200) means 200 pixels from left, 200 from top
  • Multiply by cellSize to convert: 10 × 20 = 200

Complete Code

// Grid settings
let cellSize = 20;
let cols, rows;

// Worm
let worm = [];

function setup() {
createCanvas(400, 400);

// Calculate grid dimensions
cols = width / cellSize;
rows = height / cellSize;

// Initialize worm in the center
let startX = floor(cols / 2);
let startY = floor(rows / 2);
worm.push({x: startX, y: startY});
}

function draw() {
background(50);

// Draw grid lines (optional)
stroke(80);
strokeWeight(1);
for (let i = 0; i < cols; i++) {
line(i * cellSize, 0, i * cellSize, height);
}
for (let i = 0; i < rows; i++) {
line(0, i * cellSize, width, i * cellSize);
}

// Draw the worm
noStroke();
fill(0, 255, 0);
for (let i = 0; i < worm.length; i++) {
let segment = worm[i];
rect(segment.x * cellSize, segment.y * cellSize, cellSize, cellSize);
}
}

Test It Out!

Run this code. You should see:

  • ✅ A dark gray canvas with grid lines
  • ✅ A green square in the center
  • ✅ Grid is 20×20 cells

The worm isn't moving yet - that's coming in the next step!

What You Learned

  • How to create a grid-based game system
  • How to convert between grid coordinates and pixel coordinates
  • How to use arrays to store game object positions
  • How to use objects to store x,y coordinates
  • How to loop through arrays to draw multiple objects
  • How to use floor() to ensure integer values