Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Whac-A-Mole

A config-driven Whac-A-Mole game in vanilla JavaScript — no framework, no bundler, no build step.

▶ Play it

Whac-A-Mole gameplay: whacking moles on a 5x5 grass board, clearing the stage, then a larger 8x8 board

Moles pop out of holes one at a time. Whack one before it ducks and you score; swing at an empty hole and you lose points. Clear the target score before the timer runs out to advance — run out of time and it costs you a life.

Every stage is described in config.json: grid size, points, mole speed, target score and time limit. Change that file and the game changes. No code, no rebuild.

Play locally

git clone https://github.com/codeAesthetic/whac-a-mole.git
cd whac-a-mole
npm start

Then open http://localhost:8080.

There are no dependencies to installnpm start runs a ~50-line static server from scripts/serve.mjs. It exists only because ES modules and fetch are blocked on file://, so the page needs to come over http; opening index.html directly will not work.

Rules

  1. One hole is occupied at a time, and the mole moves on every highlightDuration tick.
  2. Whack the mole → +rewardPt.
  3. Swing at an empty hole → deductionPt. Score never drops below zero.
  4. Reach passingScore before duration expires → the stage clears.
  5. Timer hits zero first → lose a life and retry that stage. Earlier progress is kept.
  6. Out of lives → game over, back to stage one.
  7. Clear the final stage and you win.

Configuration

config.json drives everything:

{
  "lives": 3,
  "config": [
    {
      "name": "The Meadow",
      "row": 5,
      "col": 5,
      "rewardPt": 10,
      "deductionPt": 5,
      "highlightDuration": 800,
      "passingScore": 50,
      "duration": 30
    }
  ]
}
Key Type Meaning
lives number Retries for the whole run, shared across stages
config[] array One entry per stage, played in order
name string Stage name shown in the HUD
row / col number Grid size. The board scales to fit the screen — it is never truncated
rewardPt number Points for hitting the mole
deductionPt number Points lost for hitting an empty hole
highlightDuration number Milliseconds before the mole moves. Lower is harder
passingScore number Score needed to clear the stage
duration number Seconds allowed for the stage

The config is validated on load, and a mistake is reported up front rather than showing up later as a broken board. That includes catching stages nobody could clear — if duration and highlightDuration don't allow enough moles to reach passingScore, it says so and names the numbers.

How it is built

Plain ES modules, loaded straight from index.html with <script type="module">.

index.html            markup + the inline SVG sprite sheet
config.json           every stage, and the number of lives
src/js/
  main.js             bootstrap: load config, wire it up, show the intro
  core/               game rules — no DOM access at all
    game.js           stage flow, scoring, lives, win/lose
    board.js          grid model: dimensions and which hole is active
    countdown.js      pausable stage clock, driven by a wall-clock deadline
  ui/                 everything that touches the DOM
    board-view.js     renders holes, animates moles, reports whacks
    hud.js            score, target, lives, countdown bar
    modal.js          intro and every end-of-stage outcome
  utils/              dom helpers, randomness, config loading + validation
src/styles/           base / board / hud / modal
scripts/serve.mjs     dev server (the only tooling in the project)

The split that matters is core/ versus ui/: the rules never read the DOM, and the DOM layer never decides anything. Board size comes from the config and is fitted by CSS, so there is no layout measurement that can race with the game starting.

The original exercise

This started as a spec-driven exercise. The brief was:

Design a game which will be driven completely by a config. Each stage of the game will have an n × n matrix of boxes.

  1. One box in the matrix will be highlighted till the user clicks on it or the time gets over. Highlighted boxes will keep on changing randomly.
  2. If the user clicks on the highlighted matrix, he will be rewarded with some points given in the configuration.
  3. If the user clicks on a non-highlighted matrix, some points will be deducted from his total score.
  4. Every stage will have a passing score (given in the configuration).
  5. If the user reaches the passing score, the next stage of the game will be triggered.
  6. Once the user passes the last stage, we will have to congratulate him with some animation.

The 2.0 rewrite keeps all of that and adds the stage timer, lives, and the artwork — and drops the webpack build the original needed.

License

ISC © codeAesthetic

About

Game similar to punching target when pops out from hole

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages