Wednesday, 23 April 2025

Star Collection Game in Kaplay: Catching Stars While Beating the Clock!

This is a fun and engaging star collection game built with Kaplay. The player controls a character using left and right keys to catch falling stars while avoiding letting too many fall to the ground. Every time a star is collected, the score increases, and the timer keeps running to challenge players to beat their own time and score. With gravity and player movement physics in place, this game offers a good mix of action and timing. The game ends when too many stars are missed, and players are rewarded with a final score based on how many stars they caught. Plus, there’s a fun audio element with a collect sound when stars are gathered and a game over sound at the end.

 

Following step-by-step procedure helps you to build the game.

 

1: Set Up Your Game Environment

Before you start coding, ensure that you have Kaplay installed and your development environment is ready. The game uses assets like images, sounds, and the Kaplay library itself.

 

1.1 Import Kaplay: The first step is importing the Kaplay library.

import kaplay from "kaplay";

 

1.2 Initialize the Kaplay Game Engine: You create an instance of the Kaplay game engine (k) where you define the game configuration like background color and button mappings.

const k = kaplay({
  background: [250, 250, 250], // Light blue background (sky-like)
  buttons: {
    left: { keyboard: ["left"], gamepad: ["west"] },
    right: { keyboard: ["right"], gamepad: ["east"] },
  },
});

2. Define Game Constants and Variables

To control the game’s difficulty and behavior, define a few constants and variables:

 

2.1 Player Speed and Gravity: The speed at which the player moves and the gravity that affects falling stars.

const PLAYER_SPEED = 2000;
const GRAVITY = 500;
let score = 0;
let missedStars = 0;
const MAX_MISSED_STARS = 10;
let secondsElapsed = 0;

2.2 Set Gravity: The game world’s gravity pulls objects down, simulating a natural environment.

k.setGravity(GRAVITY);

 

3. Load Game Assets

Next, we load the necessary game assets like sprites for the player and stars, and sounds for collecting stars and game over.

 

k.loadSprite("bean", "sprites/bean.png");
k.loadSprite("star", "sprites/star.svg");
k.loadSound("collect", "sounds/collect.mp3");
k.loadSound("gameOver", "sounds/game_over.mp3");

4. Create UI Elements

For a better gaming experience, display the score, missed stars, and timer on the screen.

const scoreLabel = k.add([k.text(`Score: ${score}`, 10), k.pos(20, 20), k.fixed(), k.color(0, 0, 0)]);
const missedLabel = k.add([k.text(`Missed: ${missedStars}/${MAX_MISSED_STARS}`, 20), k.pos(20, 50), k.fixed(), k.color(0, 0, 0)]);
const timerLabel = k.add([k.text(`Time: 0s`, 24), k.pos(k.width() - 400, 20), k.fixed(), k.color(0, 0, 0)]);

5. Create the Player Character

You need a player character that can move and interact with stars.

 

5.1 Add Player: The player is a "bean" sprite that can move left and right, and jump to avoid missing stars.

const player = k.add([k.sprite("bean"), k.pos(k.width() / 2, k.height() - 100), k.body(), k.area()]);

 5.2 Player Movement: Define how the player moves with the left and right arrow keys.

 

k.onKeyDown("left", () => {
  if (player.pos.x > 0) {
    player.move(-PLAYER_SPEED, 0);
  }
});

k.onKeyDown("right", () => {
  if (player.pos.x < k.width() - player.width) {
    player.move(PLAYER_SPEED, 0);
  }
});

6. Score and Missed Stars Logic

The core of the gameplay revolves around collecting stars and avoiding missed ones.

 

6.1 Update Score: Each time the player collects a star, the score increases and a sound plays.

const updateScore = () => {
  score += 1;
  scoreLabel.text = `Score: ${score}`;
  k.play("collect", { volume: 1 }); // Play collect sound
};

6.2 Update Missed Stars: If a star falls off the screen, the player misses it, and the game updates the missed stars count. If the player misses too many stars, the game ends.

 

const updateMissedStars = () => {
  missedStars += 1;
  missedLabel.text = `Missed: ${missedStars}/${MAX_MISSED_STARS}`;
  if (missedStars >= MAX_MISSED_STARS) {
    endGame();
  }
};

 

7. Star Spawning

Stars fall from the top of the screen, and the player must catch them.

 

7.1 Spawn Stars: A function that spawns stars randomly across the screen. Stars have random colors and a fall animation.

const spawnStar = () => {
  const x = k.rand(20, k.width() - 20); // Random x position
  const star = k.add([k.sprite("star"), k.pos(x, -20), k.area(), k.body(), k.scale(3), k.color(...getRandomColor()), "star"]);
  star.onCollide("ground", () => {
    updateMissedStars();
    k.destroy(star);
  });
};

 

Loop to Spawn Stars: Every 1.5 seconds, a new star is created and falls.

 

let starSpawnner = k.loop(1.5, spawnStar);

 

8. Game Over Condition

The game ends when the player misses too many stars.

 

8.1 End Game: If the player misses enough stars, the game stops, and a "Game Over" message appears.

 

const endGame = () => {
  gameEnded = true;
  starSpawnner.cancel();
  k.play("gameOver", { volume: 1 }); // Play game over sound
  k.add([k.text("Game Over", 48), k.pos(k.width() / 2 - 150, k.height() / 2), k.color(255, 0, 0)]);
};

 

9. Timer Function

A timer keeps track of how long the player has been playing.

 

9.1 Update Timer: The timer updates every second and is displayed on the screen.

 

const updateTimer = () => {
  if (!gameEnded) {
    secondsElapsed += 1;
    timerLabel.text = `Time: ${secondsElapsed}s`;
  } else {
    timerController.cancel();
  }
};

 

Loop to Update Timer: This loop updates the timer at regular intervals.

let timerController = k.loop(1, updateTimer);

 

Project Setup and make the Application run in your system.

 

Step 1: Create a KAPLAY project star-collection by executing below command.

npx create-kaplay star-collection

 

Upon successful execution of above command, you can see a project structure looks like below.


 

 

Step 2: Update src/main.js with below content.

 

main.js

import kaplay from "kaplay";

function getInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function getRandomColor() {
  return [getInt(0, 255), getInt(0, 255), getInt(0, 255)];
}

// Initialize Kaplay
const k = kaplay({
  background: [250, 250, 250], // Light blue background (sky-like),
  buttons: {
    left: { keyboard: ["left"], gamepad: ["west"] },
    right: { keyboard: ["right"], gamepad: ["east"] },
  },
});

// Game Configuration
const PLAYER_SPEED = 2000;
const GRAVITY = 500;
let score = 0;
let missedStars = 0;
const MAX_MISSED_STARS = 10;
let secondsElapsed = 0; // Timer variable

// Set gravity for the game world
k.setGravity(GRAVITY);

// Load assets
k.loadRoot("./");
k.loadSprite("bean", "sprites/bean.png");
k.loadSprite("star", "sprites/star.svg");
k.loadSound("collect", "sounds/collect.mp3");
k.loadSound("gameOver", "sounds/game_over.mp3");

// Display the score, missed stars, and timer
const scoreLabel = k.add([
  k.text(`Score: ${score}`, 10),
  k.pos(20, 20),
  k.fixed(),
  k.color(0, 0, 0),
]);

const missedLabel = k.add([
  k.text(`Missed: ${missedStars}/${MAX_MISSED_STARS}`, 20),
  k.pos(20, 50),
  k.fixed(),
  k.color(0, 0, 0),
]);

const timerLabel = k.add([
  k.text(`Time: 0s`, 24),
  k.pos(k.width() - 400, 20),
  k.fixed(),
  k.color(0, 0, 0),
]);

// Create the player
const player = k.add([
  k.sprite("bean"),
  k.pos(k.width() / 2, k.height() - 100),
  k.body(),
  k.area(),
]);

// Function to update the score
const updateScore = () => {
  score += 1;
  scoreLabel.text = `Score: ${score}`;
  k.play("collect", { volume: 1 }); // Play collect sound
};

// Function to update missed stars count
const updateMissedStars = () => {
  missedStars += 1;
  missedLabel.text = `Missed: ${missedStars}/${MAX_MISSED_STARS}`;

  // End the game if missed stars exceed the limit
  if (missedStars >= MAX_MISSED_STARS) {
    endGame();
  }
};

let gameEnded = false;

// Function to end the game
const endGame = () => {
  gameEnded = true;
  starSpawnner.cancel();
  k.play("gameOver", { volume: 1 }); // Play game over sound
  k.add([
    k.text("Game Over", 48),
    k.pos(k.width() / 2 - 150, k.height() / 2),
    k.color(255, 0, 0),
  ]);
};

// Function to spawn stars
const spawnStar = () => {
  const x = k.rand(20, k.width() - 20); // Random x position
  const star = k.add([
    k.sprite("star"),
    k.pos(x, -20), // Spawn above the screen
    k.area(),
    k.body(),
    k.scale(3),
    k.color(...getRandomColor()),
    "star",
  ]);

  // Remove star if it collides with the ground
  star.onCollide("ground", () => {
    updateMissedStars();
    k.destroy(star);
  });
};

// Spawn stars every 1.5 seconds
let starSpawnner = k.loop(1, spawnStar);

// Handle player movement
k.onKeyDown("left", () => {
  if (player.pos.x > 0) {
    player.move(-PLAYER_SPEED, 0);
  }
});

k.onKeyDown("right", () => {
  if (player.pos.x < k.width() - player.width) {
    player.move(PLAYER_SPEED, 0);
  }
});

k.onKeyPress("space", () => {
  player.jump();
});

// Handle star collection
player.onCollide("star", (star) => {
  updateScore(); // Increase score
  k.destroy(star); // Remove the star
});

// Add the ground
k.add([
  k.rect(k.width(), 50),
  k.pos(0, k.height() - 50),
  k.area(),
  k.color(109, 99, 19),
  k.body({ isStatic: true }),
  "ground", // Tag for collision detection
]);

// Timer function that updates every second
const updateTimer = () => {
  if (!gameEnded) {
    secondsElapsed += 1;
    timerLabel.text = `Time: ${secondsElapsed}s`;
  } else {
    timerController.cancel();
  }
};

// Update the timer every second
let timerController = k.loop(1, updateTimer);

 

Step 3: Place collect.mp3 and game_over.mp3 files in public/sounds folder. You can download these files from below link.

https://github.com/harikrishna553/frontend/tree/main/gaming/kaplay/games/star-collection/public/sounds

 

Step 4: Execute below commands from project root folder to run the Application.

 

npm install
npm run dev

Launch the url ‘http://localhost:3001/’ in a browser to play with the Application.

 

You can see a demo recording here (https://www.youtube.com/watch?v=ewroGaX-Nr4)

 

You can download the Application from this link.



References

Sounds to download: https://mixkit.co/free-sound-effects/game/

 

Previous                                                    Next                                                    Home

No comments:

Post a Comment