diff --git a/Games/Mechanica/Mechanica.png b/Games/Mechanica/Mechanica.png new file mode 100644 index 0000000000..c13ab729f5 Binary files /dev/null and b/Games/Mechanica/Mechanica.png differ diff --git a/Games/Mechanica/README.md b/Games/Mechanica/README.md new file mode 100644 index 0000000000..5a4d43b851 --- /dev/null +++ b/Games/Mechanica/README.md @@ -0,0 +1,30 @@ +# **Mechanica** + +--- + +
+ +## **Description 📃** + +You are a mechanical seahorse trapped in a silicon-rich planet with hostile swarms of fishlike enemies on your tail. Can you survive the raid? +- + +## **functionalities 🎮** + +- 2d Shooter game with good graphical element. +
+ +## **How to play? 🕹ī¸** + +- Arrow Up / Arrow Down to control your player. +- Spacebar to shoot. +- D to toggle debug mode on/off. + +
+ +## **Screenshots 📸** + +
+ + + diff --git a/Games/Mechanica/angler1.png b/Games/Mechanica/angler1.png new file mode 100644 index 0000000000..859e611dbd Binary files /dev/null and b/Games/Mechanica/angler1.png differ diff --git a/Games/Mechanica/angler2.png b/Games/Mechanica/angler2.png new file mode 100644 index 0000000000..3054fbf86d Binary files /dev/null and b/Games/Mechanica/angler2.png differ diff --git a/Games/Mechanica/drone.png b/Games/Mechanica/drone.png new file mode 100644 index 0000000000..f202630d11 Binary files /dev/null and b/Games/Mechanica/drone.png differ diff --git a/Games/Mechanica/fireExplosion.png b/Games/Mechanica/fireExplosion.png new file mode 100644 index 0000000000..f3ccb00b32 Binary files /dev/null and b/Games/Mechanica/fireExplosion.png differ diff --git a/Games/Mechanica/gears.png b/Games/Mechanica/gears.png new file mode 100644 index 0000000000..2d9d3efe86 Binary files /dev/null and b/Games/Mechanica/gears.png differ diff --git a/Games/Mechanica/hivewhale.png b/Games/Mechanica/hivewhale.png new file mode 100644 index 0000000000..13b58fbd05 Binary files /dev/null and b/Games/Mechanica/hivewhale.png differ diff --git a/Games/Mechanica/index.html b/Games/Mechanica/index.html new file mode 100644 index 0000000000..de0b23b769 --- /dev/null +++ b/Games/Mechanica/index.html @@ -0,0 +1,29 @@ + + + + + + + + JavaScript Game + + + + + + + + + + + + + + + + + + + + + diff --git a/Games/Mechanica/layer1.png b/Games/Mechanica/layer1.png new file mode 100644 index 0000000000..fe582919ba Binary files /dev/null and b/Games/Mechanica/layer1.png differ diff --git a/Games/Mechanica/layer2.png b/Games/Mechanica/layer2.png new file mode 100644 index 0000000000..c2e9db6d54 Binary files /dev/null and b/Games/Mechanica/layer2.png differ diff --git a/Games/Mechanica/layer3.png b/Games/Mechanica/layer3.png new file mode 100644 index 0000000000..bfb5db9386 Binary files /dev/null and b/Games/Mechanica/layer3.png differ diff --git a/Games/Mechanica/layer4.png b/Games/Mechanica/layer4.png new file mode 100644 index 0000000000..a8591760a0 Binary files /dev/null and b/Games/Mechanica/layer4.png differ diff --git a/Games/Mechanica/lucky.png b/Games/Mechanica/lucky.png new file mode 100644 index 0000000000..38f25f1838 Binary files /dev/null and b/Games/Mechanica/lucky.png differ diff --git a/Games/Mechanica/player.png b/Games/Mechanica/player.png new file mode 100644 index 0000000000..e9799586ed Binary files /dev/null and b/Games/Mechanica/player.png differ diff --git a/Games/Mechanica/projectile.png b/Games/Mechanica/projectile.png new file mode 100644 index 0000000000..8621f995c7 Binary files /dev/null and b/Games/Mechanica/projectile.png differ diff --git a/Games/Mechanica/scripts.js b/Games/Mechanica/scripts.js new file mode 100644 index 0000000000..d62cbe10da --- /dev/null +++ b/Games/Mechanica/scripts.js @@ -0,0 +1,328 @@ +window.addEventListener('load', function() { + // canvas setup + const canvas = document.getElementById('canvas1'); + const ctx = canvas.getContext('2d'); + canvas.width = 700; + canvas.height = 500; + + class InputHandler { + constructor(game) { + this.game = game; + window.addEventListener('keydown', e => { + if (((e.key === 'ArrowUp') || (e.key === 'ArrowDown')) && this.game.keys.indexOf(e.key) === -1) { + this.game.keys.push(e.key); + } else if (e.key === ' ') { + this.game.player.shootTop(); + } else if (e.key === 'd') { + this.game.debug = !this.game.debug; + } + }); + window.addEventListener('keyup', e => { + if (this.game.keys.indexOf(e.key) > -1) { + this.game.keys.splice(this.game.keys.indexOf(e.key), 1); + } + }); + } + } + class Projectile { + constructor(game, x, y) { + this.game = game; + this.x = x; + this.y = y; + this.width = 10; + this.height = 3; + this.speed = 3; + this.markedForDeletion = false; + } + update() { + this.x += this.speed; + if (this.x > this.game.width * 0.8) this.markedForDeletion = true; + } + draw(context) { + context.fillStyle = 'yellow'; + context.fillRect(this.x, this.y, this.width, this.height); + } + } + class Particle { + + } + class Player { + constructor(game) { + this.game = game; + this.width = 120; + this.height = 190; + this.x = 20; + this.y = 100; + this.frameX = 0; + this.frameY = 0; + this.maxFrame = 37; + this.SpeedY = 0; + this.maxSpeed = 3; + this.projectiles = []; + this.image = document.getElementById('player'); + } + update() { + if (this.game.keys.includes('ArrowUp')) this.SpeedY = -this.maxSpeed; + else if (this.game.keys.includes('ArrowDown')) this.SpeedY = this.maxSpeed; + else this.SpeedY = 0; + this.y += this.SpeedY; + this.projectiles.forEach(projectile => { + projectile.update(); + }); + this.projectiles = this.projectiles.filter(projectile => !projectile.markedForDeletion); + if (this.frameX < this.maxFrame){ + this.frameX++; + }else{ + this.frameX = 0; + } + } + draw(context) { + if (this.game.debug) context.strokeRect(this.x, this.y, this.width, this.height); + context.drawImage(this.image, this.frameX * this.width, this.frameY * this.height, this.width, this.height, this.x, this.y, this.width, this.height); + this.projectiles.forEach(projectile => { + projectile.draw(context); + }); + } + shootTop() { + if (this.game.ammo > 0) { + this.projectiles.push(new Projectile(this.game, this.x + 80, this.y + 30)); + this.game.ammo--; + } + } + } + class Enemy { + constructor(game) { + this.game = game; + this.x = this.game.width; + this.SpeedX = Math.random() * -1.5 - 0.5; + this.markedForDeletion = false; + this.frameX = 0; + this.frameY = 0; + this.maxFrame = 37; + } + update() { + this.x += this.SpeedX - this.game.speed; + if (this.x + this.width < 0) this.markedForDeletion = true; + if (this.frameX < this.maxFrame){ + this.frameX++; + } else { + this.frameX = 0; + } + } + draw(context) { + if (this.game.debug) context.strokeRect(this.x, this.y, this.width, this.height); + context.drawImage(this.image, this.frameX * this.width, this.frameY * this.height, this.width, this.height, this.x, this.y, this.width, this.height, ); + context.font = '20px Helvetica'; + context.fillText(this.lives, this.x, this.y); + } + } + class Angler1 extends Enemy { + constructor(gane) { + super(game); + this.width = 228; + this.height = 169; + this.y = Math.random() * (this.game.height * 0.9 - this.height); + this.image = document.getElementById('angler1'); + this.frameY = Math.floor(Math.random() * 3); + this.lives = 2; + this.score = this.lives; + } + } + class Angler2 extends Enemy { + constructor(gane) { + super(game); + this.width = 213; + this.height = 165; + this.y = Math.random() * (this.game.height * 0.9 - this.height); + this.image = document.getElementById('angler2'); + this.frameY = Math.floor(Math.random() * 2); + this.lives = 3; + this.score = this.lives; + } + } + class LuckyFish extends Enemy { + constructor(gane) { + super(game); + this.width = 99; + this.height = 95; + this.y = Math.random() * (this.game.height * 0.9 - this.height); + this.image = document.getElementById('lucky'); + this.frameY = Math.floor(Math.random() * 2); + this.lives = 3; + this.score = 15 + this.type = 'lucky'; + } + } + class Layer { + constructor(game, image, speedModifier){ + this.game= game; + this.image= image; + this.speedModifier= speedModifier; + this.width= 1768; + this.height= 500; + this.x= 0; + this.y= 0; + } + update(){ + if (this.x <= -this.width) this.x = 0; + this.x -= this.game.speed * this.speedModifier; + } + draw(context){ + context.drawImage(this.image, this.x, this.y); + context.drawImage(this.image, this.x + this.width, this.y); + } + } + class Background { + constructor(game){ + this.game = game; + this.image1 = document.getElementById('layer1'); + this.image2 = document.getElementById('layer2'); + this.image3 = document.getElementById('layer3'); + this.image4 = document.getElementById('layer4'); + this.layer1 = new Layer(this.game, this.image1, 0.2); + this.layer2 = new Layer(this.game, this.image2, 0.4); + this.layer3 = new Layer(this.game, this.image3, 1); + this.layer4 = new Layer(this.game, this.image4, 1.5); + this.layers = [this.layer1, this.layer2, this.layer3]; + } + update(){ + this.layers.forEach(layer => layer.update()); + } + draw(context){ + this.layers.forEach(layer => layer.draw(context)); + } + } + class UI { + constructor(game) { + this.game = game; + this.fontSize = 25; + this.fontFamoily = 'Helvetica'; + this.color = 'white'; + } + draw(context) { + context.save(); + context.fillStyle = this.color; + context.shadowOffsetX = 2; + context.shadowOffsetY = 2; + context.shadowColor = 'black'; + context.font = this.fontSize + 'px ' + this.fontFamily; + context.fillText('Score: ' + this.game.score, 20, 40); + for (let i = 0; i < this.game.ammo; i++) { + context.fillRect(20 + 5 * i, 50, 3, 20); + } + const formattedTime = (this.game.gameTime * 0.001).toFixed(1); + context.fillText('Timer: ' + formattedTime, 20, 100); + if (this.game.gameOver) { + context.textAlign = 'center'; + let message1; + let message2; + if (this.game.score > this.game.winningScore) { + message1 = 'You Win!'; + message2 = 'Well Done!'; + } else { + message1 = 'You Lose!'; + message2 = 'Try Again Next Time!'; + } + context.font = '50px ' + this.fontFamily; + context.fillText(message1, this.game.width * 0.5, this.game.height * 0.5 - 40); + context.font = '25px ' + this.fontFamily; + context.fillText(message2, this.game.width * 0.5, this.game.height * 0.5 + 40); + } + context.restore(); + } + } + class Game { + constructor(width, height) { + this.width = width; + this.height = height; + this.background = new Background(this); + this.player = new Player(this); + this.input = new InputHandler(this); + this.ui = new UI(this); + this.keys = []; + this.enemies = []; + this.enemyTimer = 0; + this.enemyInterval = 1000; + this.ammo = 20; + this.maxAmmo = 50; + this.ammoTimer = 0; + this.ammoInterval = 500; + this.gameOver = false; + this.score = 0; + this.winningScore = 69; + this.gameTime = 0; + this.timeLimit = 15000; + this.speed = 1; + this.debug = true; + } + update(deltaTime) { + if (!this.gameOver) this.gameTime += deltaTime; + if (this.gameTime > this.timeLimit) this, this.gameOver = true; + this.background.update(); + this.background.layer4.update(); + this.player.update(); + if (this.ammoTimer > this.ammoInterval) { + if (this.ammo < this.maxAmmo) this.ammo++; + this.ammoTimer = 0; + } else { + this.ammoTimer += deltaTime; + } + this.enemies.forEach(enemy => { + enemy.update(); + if (this.checkCollision(this.player, enemy)) { + enemy.markedForDeletion = true; + } + this.player.projectiles.forEach(projectile => { + if (this.checkCollision(projectile, enemy)) { + enemy.lives--; + projectile.markedForDeletion = true; + if (enemy.lives <= 0) { + enemy.markedForDeletion = true; + if(!this.gameOver) this.score += enemy.score; + if (this.score > this.winningScore) this.gameOver = true; + } + } + }) + }); + this.enemies = this.enemies.filter(enemy => !enemy.markedForDeletion); + if (this.enemyTimer > this.enemyInterval && !this.gameOver) { + this.addEnemy(); + this.enemyTimer = 0; + } else { + this.enemyTimer += deltaTime; + } + } + draw(context) { + this.background.draw(context); + this.player.draw(context); + this.ui.draw(context); + this.enemies.forEach(enemy => { + enemy.draw(context); + }); + this.background.layer4.draw(context); + } + addEnemy() { + const randomize = Math.random(); + if (randomize < 0.3) this.enemies.push(new Angler1(this)); + else if (randomize < 0.6) this.enemies.push(new Angler2(this)); + else this.enemies.push(new LuckyFish(this)); + } + checkCollision(rect1, rect2) { + return (rect1.x < rect2.x + rect2.width && rect1.x + rect1.width > rect2.x && rect1.y < rect2.y + rect2.height && rect1.height + rect1.y > rect2.y) + } + } + + const game = new Game(canvas.width, canvas.height); + let lastTime = 0; + + function animate(timeStamp) { + const deltaTime = timeStamp - lastTime; + lastTime = timeStamp; + ctx.clearRect(0, 0, canvas.width, canvas.height); + game.update(deltaTime); + game.draw(ctx); + requestAnimationFrame(animate); + } + animate(0); + }); + diff --git a/Games/Mechanica/smokeExplosion.png b/Games/Mechanica/smokeExplosion.png new file mode 100644 index 0000000000..3d0574156f Binary files /dev/null and b/Games/Mechanica/smokeExplosion.png differ diff --git a/Games/Mechanica/styles.css b/Games/Mechanica/styles.css new file mode 100644 index 0000000000..14215632cd --- /dev/null +++ b/Games/Mechanica/styles.css @@ -0,0 +1,20 @@ +{ + margin: 0; + padding: 0; + box-sizing: border-box; +} + +#canvas1 { + border: 5px solid black; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background: #4d79bc; + max-width: 100%; + max-height: 100%; +} + +#layer1, #layer2, #layer3, #layer4, #player, #angler1, #angler2, #lucky { + display: none; +} diff --git a/README.md b/README.md index 8d90bdcb79..29637e229e 100644 --- a/README.md +++ b/README.md @@ -1605,13 +1605,10 @@ This repository also provides one such platforms where contributers come over an | [Tetris Game](https://github.com/kunjgit/GameZone/tree/main/Games/tetris_game)| |[Turn_on_the_light](https://github.com/kunjgit/GameZone/tree/main/Games/Turn_on_the_light) | | [Tic-Tac-Toe Game](https://github.com/kunjgit/GameZone/tree/main/Games/Tic-Tac-Toe) | - - +[Mechanica](https://github.com/kunjgit/GameZone/tree/main/Games/Mechanica) | | [Bounce_Ball](https://github.com/kunjgit/GameZone/tree/main/Games/Bounce_Ball) | [Bubble'z Popper](https://github.com/Chandu6702/GameZone/tree/main/Games/Bubble'z Popper)| - | [Rapid_click_frenzy](https://github.com/kunjgit/GameZone/tree/main/Games/Rapid_click_frenzy) - |[Elephant_ant_man](https://github.com/tanishkaa08/GameZone/tree/main/Games/Elephant_ant_man) | [Catch_The_Ball](https://github.com/kunjgit/GameZone/tree/main/Games/Catch_The_Ball) | | [Ball_in_Maze](https://github.com/kunjgit/GameZone/tree/main/Games/Ball_in_Maze) | @@ -1683,7 +1680,6 @@ This repository also provides one such platforms where contributers come over an |[Five_Nights_at_Freddys](https://github.com/kunjgit/GameZone/tree/main/Games/Five_Nights_at_Freddys)| |[Snake_Gun_Water](https://github.com/kunjgit/GameZone/tree/main/Games/Snake_Gun_Water)| |[Tether](https://github.com/kunjgit/GameZone/tree/main/Games/Tether)| - |[Rock Paper Scissors Lizard Spock Game](./Games/Rock_Paper_Scissors_Lizard_Spock_Game)| |[Hangman_Game](https://github.com/kunjgit/GameZone/tree/main/Games/Hangman_Game)| |[Conqueror_Quest](https://github.com/kunjgit/GameZone/tree/main/Games/Conqueror_Quest)| diff --git a/assets/images/Mechanica.png b/assets/images/Mechanica.png new file mode 100644 index 0000000000..c13ab729f5 Binary files /dev/null and b/assets/images/Mechanica.png differ