Skip to main content

The Game Map

After selecting your Mokepon, you’ll enter a 2D map rendered using the HTML5 Canvas API. The map is where you navigate to find and engage opponents - both CPU-controlled and human players.
The map uses a percentage-based coordinate system that adapts to different screen sizes, ensuring consistent gameplay across desktop and mobile devices.

Movement Controls

Control your Mokepon’s movement across the map using different input methods depending on your device.

Keyboard Controls

Use the arrow keys on your keyboard to move your Mokepon:
  • ↑ Up Arrow: Move up
  • ↓ Down Arrow: Move down
  • ← Left Arrow: Move left
  • → Right Arrow: Move right
You can press multiple arrow keys simultaneously for diagonal movement.

Map Mechanics

Canvas Rendering

The map is rendered at 30 FPS (frames per second) using a continuous render loop:
// From mokepon.js - Render loop runs every 30ms
renderMapInterval = setInterval(renderCanvas, 30);

function renderCanvas() {
  // Update the pet's position based on speed
  selectedPlayerPet.x += selectedPlayerPet.speedX;
  selectedPlayerPet.y += selectedPlayerPet.speedY;
  
  // Clear canvas and redraw
  canvas.clearRect(0, 0, map.width, map.height);
  canvas.drawImage(mapBackground, 0, 0, map.width, map.height);
  
  selectedPlayerPet.renderPet();
  enemyPets.forEach(enemy => enemy.renderPet());
}

Movement Speed

Each Mokepon has a base movement speed that scales with the canvas size:
// Base speed constant
static get BASE_SPEED() {
  return 7;
}

// Speed adjusts based on canvas scale factor
function adjustPetSpeed(scaleFactor) {
  selectedPlayerPet.adjustedSpeedX = Mokepon.BASE_SPEED * scaleFactor;
  selectedPlayerPet.adjustedSpeedY = Mokepon.BASE_SPEED * scaleFactor;
}
Movement speed automatically adjusts when you resize the browser window to maintain consistent gameplay feel.

Responsive Map System

The map adapts to different screen sizes while maintaining the same gameplay experience.

Percentage-Based Positioning

All Mokepon positions are stored as percentages (0-100%) of the map dimensions, not absolute pixels:
// Convert pixel position to percentage
function pixelToPercent(x, y, mapWidth, mapHeight) {
  return {
    xPercent: (x / mapWidth) * 100,
    yPercent: (y / mapHeight) * 100
  };
}

// Convert percentage back to pixels
function percentToPixel(xPercent, yPercent, mapWidth, mapHeight) {
  return {
    x: (xPercent / 100) * mapWidth,
    y: (yPercent / 100) * mapHeight
  };
}
This ensures that:
  • Your position remains consistent across screen resizes
  • Other players see you at the correct location regardless of their screen size
  • The game works seamlessly on both mobile and desktop

Canvas Sizing

The canvas dynamically sizes based on your viewport:
function resizeCanvas() {
  const aspectRatio = mapBackground.width / mapBackground.height;
  const maxWidth = 700; // Maximum canvas width
  map.width = Math.min(window.innerWidth * 0.8, maxWidth);
  map.height = map.width / aspectRatio;
}

Finding Opponents

Spawn System

When you join the map, the server calculates a safe spawn position that isn’t too close to existing players:
1

Request Safe Position

Your client requests a spawn location from GET /mokepon/:playerId/safePosition
2

Server Calculates Safety

Server tries up to 20 times to find a position at least 20% away from other players
3

Spawn Confirmation

You spawn at the safe position, converted from percentage to your canvas pixels
// Safe position request from client
const response = await fetch(
  `${SERVER_URL}mokepon/${playerId}/safePosition`
);
const data = await response.json();

if (data.safe) {
  const pixelCoords = percentToPixel(
    data.xPercent,
    data.yPercent,
    map.width,
    map.height
  );
  selectedPlayerPet.x = pixelCoords.x;
  selectedPlayerPet.y = pixelCoords.y;
}

Identifying Opponents

As you navigate the map, you’ll encounter different types of opponents:

CPU Opponents

Labeled with “CPU” text above their Mokepon. These are computer-controlled enemies that spawn automatically.

Human Players

No label - these are real players navigating the map just like you. They move in real-time.
// CPU Mokepons are marked with isCPU flag
if (this.isCPU) {
  // Draw "CPU" label above the Mokepon
  canvas.fillStyle = "rgba(0, 0, 0, 0.6)";
  canvas.fillRect(/* background for label */);
  canvas.fillStyle = "white";
  canvas.fillText("CPU", this.x + this.width / 2, this.y - 5);
}

Real-Time Updates

Your position is broadcast to other players in real-time:
1

Position Update

Every frame, your client sends your current position to the server via POST /mokepon/:playerId/position
2

Enemy Positions Received

Server responds with the positions of all other players currently on the map
3

Enemies Rendered

Your client renders other players’ Mokepons at their reported positions

Collision Detection

When you move close enough to another Mokepon, the game detects a collision and initiates combat.

How Collisions Work

The game checks for overlapping bounding boxes between your Mokepon and enemies:
function isTooClose(enemy) {
  const dx = Math.abs(selectedPlayerPet.x - enemy.x);
  const dy = Math.abs(selectedPlayerPet.y - enemy.y);
  
  return dx < selectedPlayerPet.width && dy < selectedPlayerPet.height;
}
Once collision is detected, you automatically enter combat with that opponent. Position yourself carefully!

Explore Thoroughly

The map has multiple areas - don’t stay in one spot. CPU opponents are distributed across different zones.

Watch Movement Patterns

Human players move unpredictably, while CPU opponents remain stationary. Plan your approach accordingly.

Corner Strategy

Avoid getting trapped in corners where escape is difficult if you need to evade opponents.

Type Advantage Scouting

Try to identify opponent types before engaging. Each Mokepon’s appearance indicates its element.

Map Boundaries

Your Mokepon is constrained within the canvas boundaries:
// Boundary checking prevents moving off-screen
if (selectedPlayerPet.x < 0) {
  selectedPlayerPet.x = 0;
}
if (selectedPlayerPet.x > map.width - selectedPlayerPet.width) {
  selectedPlayerPet.x = map.width - selectedPlayerPet.width;
}
// Similar checks for Y axis
Use the map edges strategically - they can help you control engagement timing by limiting your movement options deliberately.

Performance Considerations

The map rendering system is optimized for smooth gameplay:
  • Canvas clearing: Each frame clears and redraws to prevent visual artifacts
  • Sprite scaling: Mokepon sizes scale with canvas for consistent appearance
  • Update throttling: Position updates are sent on movement, not every frame
  • Responsive design: Canvas resizes trigger recalculations for all positions

Next Steps

Combat System

Learn what happens when you collide with an opponent

Choose Your Mokepon

Review the 6 available Mokepons and their types

Build docs developers (and LLMs) love