Play now! Duck Hunt
Duck Hunt is an 80's retro game where the player takes Dog to go duck hunting. In this project to create a clone of the game, the player will "hunt" the flying ducks using their mouse or trackpad. Points are given for successful hunts and the player has limited ammo. The game is over when time runs out, the user runs out of ammo or all ducks are hunted.
In Duck Hunt, users will be able to:
- Use a trackpad or mouse click to hunt a duck
- Gain points when successfully hunting
- Lose ammo per hunt attempt
- Lose the game if the time limit runs out
In addition, this project will include:
- Sound effects
- Mute and unmute sound effects
- Canvas API
- Animations
- Javascript
- HTML5 with CSS3
Plan the project timeline, tasks, and search for assets. The assets will include sprites for the birds and the Dog. Research how to animate using sprite sheets and how to add sound effects.
- General HTML Canvas research
Continue any remaining research from Day 0 and begin the project setup.
- Complete skeleton setup
- Animating with sprite sheets
- Adding sound
- Collision detection on click event
Create classes for the UI, the Dog, bird objects, the timer, the life count and the score.
- Render canvas and background
- Render navigation bar and control buttons
- Render the duck objects (w/o event handling)
- Render dog object (w/o event handling)
- Render the timer, life count and score count
- Graphics only, not operational at this time
// Ducks have a randomized starting position behind the bushes
randomPosition() {
let pos = [];
pos[0] = Math.floor(Math.random() * DIMX);
pos[1] = DIMY - (2.5 * this.frameSize);
return pos;
}
// When a duck hits the bounds of the canvas, it will flip it's direction
bounce(pos) {
if(pos[0] < 0 || pos[0] > DIMX) {
this.vel[0] = -this.vel[0];
}
if(pos[1] < 0 || pos[1] > DIMY - (2.5 * this.frameSize)) {
this.vel[1] = -this.vel[1];
}
}
// Natural flight movement required a slower change in sprite position than frame rate
flap(time, sound) {
this.timeElapsed += time;
if(this.timeElapsed > 90) {
this.timeElapsed = 0;
this.spriteCol++;
this.spriteCol = this.spriteCol % this.maxFrame;
if(this.spriteCol > this.maxFrame) this.spriteCol = 0;
}
this.flapTime += time;
if(this.flapTime > 360) {
sound.duckFlap.pause();
sound.duckFlap.currentTime = 0;
sound.duckFlap.play();
this.flapTime = 0;
}
}
Work on all the game logic.
- Bird movement logic
- Event handling logic
- Game play logic
- Points for successful hunt
- Game-over logic
- Missed hunts
- Timer reaches zero
- Sound effects
// The basic game loop: animate a frame until a game over condition has been reached
// Each frame will animate the duck, counters, and dog accordingly
gameLoop(timestamp) {
let timeElapsed = (timestamp - this.prevTime);
this.prevTime = timestamp;
this.timer += timeElapsed;
if(timeElapsed > 16) {
this.gameboard.clear();
if(!this.dogIntro) {
this.updateCounters();
this.animateDuck(timeElapsed);
} else if(this.dogIntro) {
this.animateDog(timeElapsed);
}
// Game over conditions
if((this.ammo < 1 || this.duckArray.length === 0 || this.roundTime < 0) && this.animating) {
this.animating = false;
this.stop();
}
}
if(this.duckArray.length && this.animating) {
window.requestAnimationFrame(this.gameLoop.bind(this));
}
}
// The play button and splash page listeners only run once. The restart button will set a new single use play button listener
playButtonListener() {
this.playButton.addEventListener("click", () => {
this.sound.introSound.play();
this.game.start();
this.playButton.style.display = "none";
this.huntEventListener();
this.pauseButtonListener();
this.restartButtonListener();
}, { once: true });
}
// Some listeners need to be removed at the end of each game
soundToggleListener() {
let toggle = document.getElementById("sound-effects");
let soundOn = document.getElementById("sound-on");
let soundOff = document.getElementById("sound-off");
let sound = this.sound;
toggle.addEventListener("click", toggleSound)
if(soundOn.style.display === "none") {
sound.mute();
} else {
sound.unmute();
}
function toggleSound() {
if(soundOn.style.display !== "none") {
soundOn.style.display = "none";
soundOff.style.display = "block";
sound.mute();
} else {
soundOn.style.display = "block";
soundOff.style.display = "none";
sound.unmute();
}
}
function removeListener() {
toggle.removeEventListener("click", toggleSound);
}
this.soundToggleListener.removeListener = removeListener;
}
- Complete any lingering tasks
- Add bonus features if time allows
- Deploy website
Make it pretty, make it glow.
- Clean up code
- Clean up UI
- Crossover with other game characters
- Lose points if they are hunted
- Power-ups to regain ammo/time
- Add top 3 score board
The live project:
- Link to portfolio website, Github account, LinkedIn account
- Landing page/modal with clear instructions
- Interactive
- Styled, clean frontend
- Ability to mute any sound effects
Production README:
- Link to live project
- Instructions to play or interact with the project
- List of technologies, libraries, APIs used
- Technical implementation details with clean code snippets
- To-dos and future features
- No .DS_store files, debugger, console.logs
- Organized file structure with /src and /dist directories