diff --git a/Games/2D_Fighting_game/README.md b/Games/2D_Fighting_game/README.md
new file mode 100644
index 0000000000..199987a266
--- /dev/null
+++ b/Games/2D_Fighting_game/README.md
@@ -0,0 +1 @@
+# 2D Fighting Game
diff --git a/Games/2D_Fighting_game/img/background.png b/Games/2D_Fighting_game/img/background.png
new file mode 100644
index 0000000000..0fa288b90f
Binary files /dev/null and b/Games/2D_Fighting_game/img/background.png differ
diff --git a/Games/2D_Fighting_game/img/kenji/Attack1.png b/Games/2D_Fighting_game/img/kenji/Attack1.png
new file mode 100644
index 0000000000..2d97fce405
Binary files /dev/null and b/Games/2D_Fighting_game/img/kenji/Attack1.png differ
diff --git a/Games/2D_Fighting_game/img/kenji/Attack2.png b/Games/2D_Fighting_game/img/kenji/Attack2.png
new file mode 100644
index 0000000000..b55303f7c7
Binary files /dev/null and b/Games/2D_Fighting_game/img/kenji/Attack2.png differ
diff --git a/Games/2D_Fighting_game/img/kenji/Death.png b/Games/2D_Fighting_game/img/kenji/Death.png
new file mode 100644
index 0000000000..0989c43330
Binary files /dev/null and b/Games/2D_Fighting_game/img/kenji/Death.png differ
diff --git a/Games/2D_Fighting_game/img/kenji/Fall.png b/Games/2D_Fighting_game/img/kenji/Fall.png
new file mode 100644
index 0000000000..22df71276b
Binary files /dev/null and b/Games/2D_Fighting_game/img/kenji/Fall.png differ
diff --git a/Games/2D_Fighting_game/img/kenji/Idle.png b/Games/2D_Fighting_game/img/kenji/Idle.png
new file mode 100644
index 0000000000..7f877d7095
Binary files /dev/null and b/Games/2D_Fighting_game/img/kenji/Idle.png differ
diff --git a/Games/2D_Fighting_game/img/kenji/Jump.png b/Games/2D_Fighting_game/img/kenji/Jump.png
new file mode 100644
index 0000000000..01a6688fca
Binary files /dev/null and b/Games/2D_Fighting_game/img/kenji/Jump.png differ
diff --git a/Games/2D_Fighting_game/img/kenji/Run.png b/Games/2D_Fighting_game/img/kenji/Run.png
new file mode 100644
index 0000000000..7e36b37275
Binary files /dev/null and b/Games/2D_Fighting_game/img/kenji/Run.png differ
diff --git a/Games/2D_Fighting_game/img/kenji/Take hit.png b/Games/2D_Fighting_game/img/kenji/Take hit.png
new file mode 100644
index 0000000000..48df0fbd43
Binary files /dev/null and b/Games/2D_Fighting_game/img/kenji/Take hit.png differ
diff --git a/Games/2D_Fighting_game/img/samuraiMack/Attack1.png b/Games/2D_Fighting_game/img/samuraiMack/Attack1.png
new file mode 100644
index 0000000000..92500f60ab
Binary files /dev/null and b/Games/2D_Fighting_game/img/samuraiMack/Attack1.png differ
diff --git a/Games/2D_Fighting_game/img/samuraiMack/Attack2.png b/Games/2D_Fighting_game/img/samuraiMack/Attack2.png
new file mode 100644
index 0000000000..3e484d87dd
Binary files /dev/null and b/Games/2D_Fighting_game/img/samuraiMack/Attack2.png differ
diff --git a/Games/2D_Fighting_game/img/samuraiMack/Death.png b/Games/2D_Fighting_game/img/samuraiMack/Death.png
new file mode 100644
index 0000000000..4754bd0cff
Binary files /dev/null and b/Games/2D_Fighting_game/img/samuraiMack/Death.png differ
diff --git a/Games/2D_Fighting_game/img/samuraiMack/Fall.png b/Games/2D_Fighting_game/img/samuraiMack/Fall.png
new file mode 100644
index 0000000000..b9b4c29c53
Binary files /dev/null and b/Games/2D_Fighting_game/img/samuraiMack/Fall.png differ
diff --git a/Games/2D_Fighting_game/img/samuraiMack/Idle.png b/Games/2D_Fighting_game/img/samuraiMack/Idle.png
new file mode 100644
index 0000000000..bf9ca2ff09
Binary files /dev/null and b/Games/2D_Fighting_game/img/samuraiMack/Idle.png differ
diff --git a/Games/2D_Fighting_game/img/samuraiMack/Jump.png b/Games/2D_Fighting_game/img/samuraiMack/Jump.png
new file mode 100644
index 0000000000..c08a30b273
Binary files /dev/null and b/Games/2D_Fighting_game/img/samuraiMack/Jump.png differ
diff --git a/Games/2D_Fighting_game/img/samuraiMack/Run.png b/Games/2D_Fighting_game/img/samuraiMack/Run.png
new file mode 100644
index 0000000000..519ce09d1f
Binary files /dev/null and b/Games/2D_Fighting_game/img/samuraiMack/Run.png differ
diff --git a/Games/2D_Fighting_game/img/samuraiMack/Take Hit - white silhouette.png b/Games/2D_Fighting_game/img/samuraiMack/Take Hit - white silhouette.png
new file mode 100644
index 0000000000..1f286d5a2a
Binary files /dev/null and b/Games/2D_Fighting_game/img/samuraiMack/Take Hit - white silhouette.png differ
diff --git a/Games/2D_Fighting_game/img/samuraiMack/Take Hit.png b/Games/2D_Fighting_game/img/samuraiMack/Take Hit.png
new file mode 100644
index 0000000000..bda48d9770
Binary files /dev/null and b/Games/2D_Fighting_game/img/samuraiMack/Take Hit.png differ
diff --git a/Games/2D_Fighting_game/img/shop.png b/Games/2D_Fighting_game/img/shop.png
new file mode 100644
index 0000000000..d5ffabc4a2
Binary files /dev/null and b/Games/2D_Fighting_game/img/shop.png differ
diff --git a/Games/2D_Fighting_game/index.html b/Games/2D_Fighting_game/index.html
new file mode 100644
index 0000000000..846ae69034
--- /dev/null
+++ b/Games/2D_Fighting_game/index.html
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Games/2D_Fighting_game/index.js b/Games/2D_Fighting_game/index.js
new file mode 100644
index 0000000000..1fdc1033d2
--- /dev/null
+++ b/Games/2D_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/2D_Fighting_game/js/classes.js b/Games/2D_Fighting_game/js/classes.js
new file mode 100644
index 0000000000..679412b6a7
--- /dev/null
+++ b/Games/2D_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/2D_Fighting_game/js/utils.js b/Games/2D_Fighting_game/js/utils.js
new file mode 100644
index 0000000000..042213f831
--- /dev/null
+++ b/Games/2D_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 200f2735aa..89d5e10b5a 100644
--- a/README.md
+++ b/README.md
@@ -1677,6 +1677,7 @@ This repository also provides one such platforms where contributers come over an
|[Pokemon_Adventure_Game](https://github.com/kunjgit/GameZone/tree/main/Games/Pokemon_Adventure_Game)|
|[Garden-Builder-game](https://github.com/kunjgit/GameZone/tree/main/Games/Garden-Builder-game)|
+|[2D_Fighting_Game](https://github.com/kunjgit/GameZone/tree/main/Games/2D_Fighting_Game)|
| [Airhockey_game](https://github.com/kunjgit/GameZone/tree/main/Games/Airhockey_game)|
diff --git a/assets/images/2D_Fighting_Game.png b/assets/images/2D_Fighting_Game.png
new file mode 100644
index 0000000000..ac79adf704
Binary files /dev/null and b/assets/images/2D_Fighting_Game.png differ
diff --git a/assets/js/gamesData.json b/assets/js/gamesData.json
index 0b394cff3a..a1ad7cafbf 100644
--- a/assets/js/gamesData.json
+++ b/assets/js/gamesData.json
@@ -3375,11 +3375,16 @@
"thumbnailUrl": "Brain_Game.png"
},
"633":{
+ "gameTitle" : "2D Fighting Game",
+ "gameUrl": "2D_Fighting_Game",
+ "thumbnailUrl": "2D_Fighting_Game.png"
+ },
+ "634":{
"gameTitle" : "Cosmic_Blast",
"gameUrl": "Cosmic_Blast",
"thumbnailUrl": "Cosmic_Blast.png"
},
- "634":{
+ "635":{
"gameTitle" : "IKnowYou-Mind-Reading-Game",
"gameUrl": "IKnowYou-Mind-Reading-Game",
"thumbnailUrl": "IKnowYou-Mind-Reading-Game.png"