diff --git a/Games/Samurai_Fighting_Game/README.md b/Games/Samurai_Fighting_Game/README.md new file mode 100644 index 0000000000..12c9d114d6 --- /dev/null +++ b/Games/Samurai_Fighting_Game/README.md @@ -0,0 +1,22 @@ +# Samurai Fighting Game + +Samurai fighting games have carved out a unique niche in the gaming world, blending intense combat with rich cultural and historical themes. These games often feature stunning visuals, detailed characters, and engaging storylines that immerse players in the world of the samurai. + +## How to Play + +- PLAYER 1 can use the following keys: +A D and W to move +spacebar to hit + +- PLAYER 2 can use the following keys: +leftarrow rightarrow and uparrow to move +downarrow to hit + +## Installation + +No installation is required. Simply open the `index.html` file in your web browser to start playing the game. + +## Usage + +1. Clone the repository or download the files. +2. Open `index.html` in your preferred web browser. \ No newline at end of file diff --git a/Games/Samurai_Fighting_Game/img/background.png b/Games/Samurai_Fighting_Game/img/background.png new file mode 100644 index 0000000000..0fa288b90f Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/background.png differ diff --git a/Games/Samurai_Fighting_Game/img/kenji/Attack1.png b/Games/Samurai_Fighting_Game/img/kenji/Attack1.png new file mode 100644 index 0000000000..2d97fce405 Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/kenji/Attack1.png differ diff --git a/Games/Samurai_Fighting_Game/img/kenji/Attack2.png b/Games/Samurai_Fighting_Game/img/kenji/Attack2.png new file mode 100644 index 0000000000..b55303f7c7 Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/kenji/Attack2.png differ diff --git a/Games/Samurai_Fighting_Game/img/kenji/Death.png b/Games/Samurai_Fighting_Game/img/kenji/Death.png new file mode 100644 index 0000000000..0989c43330 Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/kenji/Death.png differ diff --git a/Games/Samurai_Fighting_Game/img/kenji/Fall.png b/Games/Samurai_Fighting_Game/img/kenji/Fall.png new file mode 100644 index 0000000000..22df71276b Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/kenji/Fall.png differ diff --git a/Games/Samurai_Fighting_Game/img/kenji/Idle.png b/Games/Samurai_Fighting_Game/img/kenji/Idle.png new file mode 100644 index 0000000000..7f877d7095 Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/kenji/Idle.png differ diff --git a/Games/Samurai_Fighting_Game/img/kenji/Jump.png b/Games/Samurai_Fighting_Game/img/kenji/Jump.png new file mode 100644 index 0000000000..01a6688fca Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/kenji/Jump.png differ diff --git a/Games/Samurai_Fighting_Game/img/kenji/Run.png b/Games/Samurai_Fighting_Game/img/kenji/Run.png new file mode 100644 index 0000000000..7e36b37275 Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/kenji/Run.png differ diff --git a/Games/Samurai_Fighting_Game/img/kenji/Take hit.png b/Games/Samurai_Fighting_Game/img/kenji/Take hit.png new file mode 100644 index 0000000000..48df0fbd43 Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/kenji/Take hit.png differ diff --git a/Games/Samurai_Fighting_Game/img/samuraiMack/Attack1.png b/Games/Samurai_Fighting_Game/img/samuraiMack/Attack1.png new file mode 100644 index 0000000000..92500f60ab Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/samuraiMack/Attack1.png differ diff --git a/Games/Samurai_Fighting_Game/img/samuraiMack/Attack2.png b/Games/Samurai_Fighting_Game/img/samuraiMack/Attack2.png new file mode 100644 index 0000000000..3e484d87dd Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/samuraiMack/Attack2.png differ diff --git a/Games/Samurai_Fighting_Game/img/samuraiMack/Death.png b/Games/Samurai_Fighting_Game/img/samuraiMack/Death.png new file mode 100644 index 0000000000..4754bd0cff Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/samuraiMack/Death.png differ diff --git a/Games/Samurai_Fighting_Game/img/samuraiMack/Fall.png b/Games/Samurai_Fighting_Game/img/samuraiMack/Fall.png new file mode 100644 index 0000000000..b9b4c29c53 Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/samuraiMack/Fall.png differ diff --git a/Games/Samurai_Fighting_Game/img/samuraiMack/Idle.png b/Games/Samurai_Fighting_Game/img/samuraiMack/Idle.png new file mode 100644 index 0000000000..bf9ca2ff09 Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/samuraiMack/Idle.png differ diff --git a/Games/Samurai_Fighting_Game/img/samuraiMack/Jump.png b/Games/Samurai_Fighting_Game/img/samuraiMack/Jump.png new file mode 100644 index 0000000000..c08a30b273 Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/samuraiMack/Jump.png differ diff --git a/Games/Samurai_Fighting_Game/img/samuraiMack/Run.png b/Games/Samurai_Fighting_Game/img/samuraiMack/Run.png new file mode 100644 index 0000000000..519ce09d1f Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/samuraiMack/Run.png differ diff --git a/Games/Samurai_Fighting_Game/img/samuraiMack/Take Hit - white silhouette.png b/Games/Samurai_Fighting_Game/img/samuraiMack/Take Hit - white silhouette.png new file mode 100644 index 0000000000..1f286d5a2a Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/samuraiMack/Take Hit - white silhouette.png differ diff --git a/Games/Samurai_Fighting_Game/img/samuraiMack/Take Hit.png b/Games/Samurai_Fighting_Game/img/samuraiMack/Take Hit.png new file mode 100644 index 0000000000..bda48d9770 Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/samuraiMack/Take Hit.png differ diff --git a/Games/Samurai_Fighting_Game/img/shop.png b/Games/Samurai_Fighting_Game/img/shop.png new file mode 100644 index 0000000000..d5ffabc4a2 Binary files /dev/null and b/Games/Samurai_Fighting_Game/img/shop.png differ diff --git a/Games/Samurai_Fighting_Game/index.html b/Games/Samurai_Fighting_Game/index.html new file mode 100644 index 0000000000..846ae69034 --- /dev/null +++ b/Games/Samurai_Fighting_Game/index.html @@ -0,0 +1,124 @@ + + + + + + + + +
+ +
+ +
+
+
+
+ + +
+ 10 +
+ +
+
+
+
+
+
+
+ Tie +
+ +
+ + + + + + diff --git a/Games/Samurai_Fighting_Game/index.js b/Games/Samurai_Fighting_Game/index.js new file mode 100644 index 0000000000..1fdc1033d2 --- /dev/null +++ b/Games/Samurai_Fighting_Game/index.js @@ -0,0 +1,332 @@ +const canvas = document.querySelector('canvas') +const c = canvas.getContext('2d') + +canvas.width = 1024 +canvas.height = 576 + +c.fillRect(0, 0, canvas.width, canvas.height) + +const gravity = 0.7 + +const background = new Sprite({ + position: { + x: 0, + y: 0 + }, + imageSrc: './img/background.png' +}) + +const shop = new Sprite({ + position: { + x: 600, + y: 128 + }, + imageSrc: './img/shop.png', + scale: 2.75, + framesMax: 6 +}) + +const player = new Fighter({ + position: { + x: 0, + y: 0 + }, + velocity: { + x: 0, + y: 0 + }, + offset: { + x: 0, + y: 0 + }, + imageSrc: './img/samuraiMack/Idle.png', + framesMax: 8, + scale: 2.5, + offset: { + x: 215, + y: 157 + }, + sprites: { + idle: { + imageSrc: './img/samuraiMack/Idle.png', + framesMax: 8 + }, + run: { + imageSrc: './img/samuraiMack/Run.png', + framesMax: 8 + }, + jump: { + imageSrc: './img/samuraiMack/Jump.png', + framesMax: 2 + }, + fall: { + imageSrc: './img/samuraiMack/Fall.png', + framesMax: 2 + }, + attack1: { + imageSrc: './img/samuraiMack/Attack1.png', + framesMax: 6 + }, + takeHit: { + imageSrc: './img/samuraiMack/Take Hit - white silhouette.png', + framesMax: 4 + }, + death: { + imageSrc: './img/samuraiMack/Death.png', + framesMax: 6 + } + }, + attackBox: { + offset: { + x: 100, + y: 50 + }, + width: 160, + height: 50 + } +}) + +const enemy = new Fighter({ + position: { + x: 400, + y: 100 + }, + velocity: { + x: 0, + y: 0 + }, + color: 'blue', + offset: { + x: -50, + y: 0 + }, + imageSrc: './img/kenji/Idle.png', + framesMax: 4, + scale: 2.5, + offset: { + x: 215, + y: 167 + }, + sprites: { + idle: { + imageSrc: './img/kenji/Idle.png', + framesMax: 4 + }, + run: { + imageSrc: './img/kenji/Run.png', + framesMax: 8 + }, + jump: { + imageSrc: './img/kenji/Jump.png', + framesMax: 2 + }, + fall: { + imageSrc: './img/kenji/Fall.png', + framesMax: 2 + }, + attack1: { + imageSrc: './img/kenji/Attack1.png', + framesMax: 4 + }, + takeHit: { + imageSrc: './img/kenji/Take hit.png', + framesMax: 3 + }, + death: { + imageSrc: './img/kenji/Death.png', + framesMax: 7 + } + }, + attackBox: { + offset: { + x: -170, + y: 50 + }, + width: 170, + height: 50 + } +}) + +console.log(player) + +const keys = { + a: { + pressed: false + }, + d: { + pressed: false + }, + ArrowRight: { + pressed: false + }, + ArrowLeft: { + pressed: false + } +} + +decreaseTimer() + +function animate() { + window.requestAnimationFrame(animate) + c.fillStyle = 'black' + c.fillRect(0, 0, canvas.width, canvas.height) + background.update() + shop.update() + c.fillStyle = 'rgba(255, 255, 255, 0.15)' + c.fillRect(0, 0, canvas.width, canvas.height) + player.update() + enemy.update() + + player.velocity.x = 0 + enemy.velocity.x = 0 + + // player movement + + if (keys.a.pressed && player.lastKey === 'a') { + player.velocity.x = -5 + player.switchSprite('run') + } else if (keys.d.pressed && player.lastKey === 'd') { + player.velocity.x = 5 + player.switchSprite('run') + } else { + player.switchSprite('idle') + } + + // jumping + if (player.velocity.y < 0) { + player.switchSprite('jump') + } else if (player.velocity.y > 0) { + player.switchSprite('fall') + } + + // Enemy movement + if (keys.ArrowLeft.pressed && enemy.lastKey === 'ArrowLeft') { + enemy.velocity.x = -5 + enemy.switchSprite('run') + } else if (keys.ArrowRight.pressed && enemy.lastKey === 'ArrowRight') { + enemy.velocity.x = 5 + enemy.switchSprite('run') + } else { + enemy.switchSprite('idle') + } + + // jumping + if (enemy.velocity.y < 0) { + enemy.switchSprite('jump') + } else if (enemy.velocity.y > 0) { + enemy.switchSprite('fall') + } + + // detect for collision & enemy gets hit + if ( + rectangularCollision({ + rectangle1: player, + rectangle2: enemy + }) && + player.isAttacking && + player.framesCurrent === 4 + ) { + enemy.takeHit() + player.isAttacking = false + + gsap.to('#enemyHealth', { + width: enemy.health + '%' + }) + } + + // if player misses + if (player.isAttacking && player.framesCurrent === 4) { + player.isAttacking = false + } + + // this is where our player gets hit + if ( + rectangularCollision({ + rectangle1: enemy, + rectangle2: player + }) && + enemy.isAttacking && + enemy.framesCurrent === 2 + ) { + player.takeHit() + enemy.isAttacking = false + + gsap.to('#playerHealth', { + width: player.health + '%' + }) + } + + // if player misses + if (enemy.isAttacking && enemy.framesCurrent === 2) { + enemy.isAttacking = false + } + + // end game based on health + if (enemy.health <= 0 || player.health <= 0) { + determineWinner({ player, enemy, timerId }) + } +} + +animate() + +window.addEventListener('keydown', (event) => { + if (!player.dead) { + switch (event.key) { + case 'd': + keys.d.pressed = true + player.lastKey = 'd' + break + case 'a': + keys.a.pressed = true + player.lastKey = 'a' + break + case 'w': + player.velocity.y = -20 + break + case ' ': + player.attack() + break + } + } + + if (!enemy.dead) { + switch (event.key) { + case 'ArrowRight': + keys.ArrowRight.pressed = true + enemy.lastKey = 'ArrowRight' + break + case 'ArrowLeft': + keys.ArrowLeft.pressed = true + enemy.lastKey = 'ArrowLeft' + break + case 'ArrowUp': + enemy.velocity.y = -20 + break + case 'ArrowDown': + enemy.attack() + + break + } + } +}) + +window.addEventListener('keyup', (event) => { + switch (event.key) { + case 'd': + keys.d.pressed = false + break + case 'a': + keys.a.pressed = false + break + } + + // enemy keys + switch (event.key) { + case 'ArrowRight': + keys.ArrowRight.pressed = false + break + case 'ArrowLeft': + keys.ArrowLeft.pressed = false + break + } +}) diff --git a/Games/Samurai_Fighting_Game/js/classes.js b/Games/Samurai_Fighting_Game/js/classes.js new file mode 100644 index 0000000000..679412b6a7 --- /dev/null +++ b/Games/Samurai_Fighting_Game/js/classes.js @@ -0,0 +1,218 @@ +class Sprite { + constructor({ + position, + imageSrc, + scale = 1, + framesMax = 1, + offset = { x: 0, y: 0 } + }) { + this.position = position + this.width = 50 + this.height = 150 + this.image = new Image() + this.image.src = imageSrc + this.scale = scale + this.framesMax = framesMax + this.framesCurrent = 0 + this.framesElapsed = 0 + this.framesHold = 5 + this.offset = offset + } + + draw() { + c.drawImage( + this.image, + this.framesCurrent * (this.image.width / this.framesMax), + 0, + this.image.width / this.framesMax, + this.image.height, + this.position.x - this.offset.x, + this.position.y - this.offset.y, + (this.image.width / this.framesMax) * this.scale, + this.image.height * this.scale + ) + } + + animateFrames() { + this.framesElapsed++ + + if (this.framesElapsed % this.framesHold === 0) { + if (this.framesCurrent < this.framesMax - 1) { + this.framesCurrent++ + } else { + this.framesCurrent = 0 + } + } + } + + update() { + this.draw() + this.animateFrames() + } +} + +class Fighter extends Sprite { + constructor({ + position, + velocity, + color = 'red', + imageSrc, + scale = 1, + framesMax = 1, + offset = { x: 0, y: 0 }, + sprites, + attackBox = { offset: {}, width: undefined, height: undefined } + }) { + super({ + position, + imageSrc, + scale, + framesMax, + offset + }) + + this.velocity = velocity + this.width = 50 + this.height = 150 + this.lastKey + this.attackBox = { + position: { + x: this.position.x, + y: this.position.y + }, + offset: attackBox.offset, + width: attackBox.width, + height: attackBox.height + } + this.color = color + this.isAttacking + this.health = 100 + this.framesCurrent = 0 + this.framesElapsed = 0 + this.framesHold = 5 + this.sprites = sprites + this.dead = false + + for (const sprite in this.sprites) { + sprites[sprite].image = new Image() + sprites[sprite].image.src = sprites[sprite].imageSrc + } + } + + update() { + this.draw() + if (!this.dead) this.animateFrames() + + // attack boxes + this.attackBox.position.x = this.position.x + this.attackBox.offset.x + this.attackBox.position.y = this.position.y + this.attackBox.offset.y + + // draw the attack box + // c.fillRect( + // this.attackBox.position.x, + // this.attackBox.position.y, + // this.attackBox.width, + // this.attackBox.height + // ) + + this.position.x += this.velocity.x + this.position.y += this.velocity.y + + // gravity function + if (this.position.y + this.height + this.velocity.y >= canvas.height - 96) { + this.velocity.y = 0 + this.position.y = 330 + } else this.velocity.y += gravity + } + + attack() { + this.switchSprite('attack1') + this.isAttacking = true + } + + takeHit() { + this.health -= 20 + + if (this.health <= 0) { + this.switchSprite('death') + } else this.switchSprite('takeHit') + } + + switchSprite(sprite) { + if (this.image === this.sprites.death.image) { + if (this.framesCurrent === this.sprites.death.framesMax - 1) + this.dead = true + return + } + + // overriding all other animations with the attack animation + if ( + this.image === this.sprites.attack1.image && + this.framesCurrent < this.sprites.attack1.framesMax - 1 + ) + return + + // override when fighter gets hit + if ( + this.image === this.sprites.takeHit.image && + this.framesCurrent < this.sprites.takeHit.framesMax - 1 + ) + return + + switch (sprite) { + case 'idle': + if (this.image !== this.sprites.idle.image) { + this.image = this.sprites.idle.image + this.framesMax = this.sprites.idle.framesMax + this.framesCurrent = 0 + } + break + case 'run': + if (this.image !== this.sprites.run.image) { + this.image = this.sprites.run.image + this.framesMax = this.sprites.run.framesMax + this.framesCurrent = 0 + } + break + case 'jump': + if (this.image !== this.sprites.jump.image) { + this.image = this.sprites.jump.image + this.framesMax = this.sprites.jump.framesMax + this.framesCurrent = 0 + } + break + + case 'fall': + if (this.image !== this.sprites.fall.image) { + this.image = this.sprites.fall.image + this.framesMax = this.sprites.fall.framesMax + this.framesCurrent = 0 + } + break + + case 'attack1': + if (this.image !== this.sprites.attack1.image) { + this.image = this.sprites.attack1.image + this.framesMax = this.sprites.attack1.framesMax + this.framesCurrent = 0 + } + break + + case 'takeHit': + if (this.image !== this.sprites.takeHit.image) { + this.image = this.sprites.takeHit.image + this.framesMax = this.sprites.takeHit.framesMax + this.framesCurrent = 0 + } + break + + case 'death': + if (this.image !== this.sprites.death.image) { + this.image = this.sprites.death.image + this.framesMax = this.sprites.death.framesMax + this.framesCurrent = 0 + } + break + } + } +} diff --git a/Games/Samurai_Fighting_Game/js/utils.js b/Games/Samurai_Fighting_Game/js/utils.js new file mode 100644 index 0000000000..042213f831 --- /dev/null +++ b/Games/Samurai_Fighting_Game/js/utils.js @@ -0,0 +1,37 @@ +function rectangularCollision({ rectangle1, rectangle2 }) { + return ( + rectangle1.attackBox.position.x + rectangle1.attackBox.width >= + rectangle2.position.x && + rectangle1.attackBox.position.x <= + rectangle2.position.x + rectangle2.width && + rectangle1.attackBox.position.y + rectangle1.attackBox.height >= + rectangle2.position.y && + rectangle1.attackBox.position.y <= rectangle2.position.y + rectangle2.height + ) +} + +function determineWinner({ player, enemy, timerId }) { + clearTimeout(timerId) + document.querySelector('#displayText').style.display = 'flex' + if (player.health === enemy.health) { + document.querySelector('#displayText').innerHTML = 'Tie' + } else if (player.health > enemy.health) { + document.querySelector('#displayText').innerHTML = 'Player 1 Wins' + } else if (player.health < enemy.health) { + document.querySelector('#displayText').innerHTML = 'Player 2 Wins' + } +} + +let timer = 60 +let timerId +function decreaseTimer() { + if (timer > 0) { + timerId = setTimeout(decreaseTimer, 1000) + timer-- + document.querySelector('#timer').innerHTML = timer + } + + if (timer === 0) { + determineWinner({ player, enemy, timerId }) + } +} diff --git a/README.md b/README.md index 6e5e1be251..615b55181d 100644 --- a/README.md +++ b/README.md @@ -837,8 +837,9 @@ This repository also provides one such platforms where contributers come over an |[Pottery-Game](https://github.com/kunjgit/GameZone/tree/main/Games/Pottery-Game)| |[Zombie_Shooter](https://github.com/kunjgit/GameZone/tree/main/Games/Zombie_Shooter)| | [Ganesh_QR_Maker](https://github.com/kunjgit/GameZone/tree/main/Games/Ganesh_QR_Maker) | -|[Wheel_of_Fortunes](https://github.com/Saipradyumnagoud/GameZone/tree/main/Games/Wheel_of_Fortunes)| -|[Tic-tac-toe](https://github.com/Saipradyumnagoud/GameZone/tree/main/Games/Tic-tac-toe)| +|[Wheel_of_Fortunes](https://github.com/kunjgit/GameZone/tree/main/Games/Wheel_of_Fortunes)| +|[Samurai_Fighting_Game](https://github.com/kunjgit/GameZone/tree/main/Games/Samurai_Fighting_Game)| +|[Tic-tac-toe](https://github.com/kunjgit/GameZone/tree/main/Games/Tic-tac-toe)| |[Quest_For_Riches](https://github.com/kunjgit/GameZone/tree/main/Games/Quest_For_Riches)| | [IKnowYou-Mind-Reading-Game](https://github.com/kunjgit/GameZone/tree/main/Games/IKnowYou-Mind-Reading-Game) | | [Tic_Tac_Toe_Neon](https://github.com/kunjgit/GameZone/tree/main/Games/Tic_Tac_Toe_Neon) | diff --git a/assets/images/Samurai Fighting Game.png b/assets/images/Samurai Fighting Game.png new file mode 100644 index 0000000000..308cfc6e2f Binary files /dev/null and b/assets/images/Samurai Fighting Game.png differ