diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..222861c --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "tabWidth": 2, + "useTabs": false +} diff --git a/[i] ChangeLog 0.0.02 BETA.txt b/[i] ChangeLog 0.0.02 BETA.txt new file mode 100644 index 0000000..fca9a14 --- /dev/null +++ b/[i] ChangeLog 0.0.02 BETA.txt @@ -0,0 +1,6 @@ +[i] Patch version 0.0.02 BETA Version + +> [+] Lobby Screen +> [+] Movement player sama enemy +> [+] Namabahin asset, sound, background dll +> [+] Update progress bar timer untuk player dan enemy diff --git a/UpdatePatch.txt b/[i] ChangeLog 0.0.03 BETA.txt similarity index 55% rename from UpdatePatch.txt rename to [i] ChangeLog 0.0.03 BETA.txt index 2fc932a..4d0954a 100644 --- a/UpdatePatch.txt +++ b/[i] ChangeLog 0.0.03 BETA.txt @@ -1,10 +1,5 @@ -* New Update Xiiivpiexzo -^# [i] Patch version 0.0.02 BETA Version -> [+] Lobby Screen -> [+] Movement player sama enemy -> [+] Namabahin asset, sound, background dll -> [+] Update progress bar timer untuk player dan enemy -^# [i] Patch version 0.0.03 BETA Version +[i] Patch version 0.0.03 BETA Version + > [+] Update Player Movement > [+] Reverse Player > [FIXED] Player Jump 1x @@ -16,4 +11,4 @@ > [+] Add FrameWork kaboom.js Biar Lebih Enak > [+] Reponsive Player Movement > [+] Tampilan Game (canvas) sudah Full Screen -> [Optimasi Script Code] \ No newline at end of file +> [Optimasi Script Code] diff --git a/[i] ChangeLog 0.0.04 BETA.txt b/[i] ChangeLog 0.0.04 BETA.txt new file mode 100644 index 0000000..b66b76c --- /dev/null +++ b/[i] ChangeLog 0.0.04 BETA.txt @@ -0,0 +1,5 @@ +[i] Patch version 0.0.04 BETA Version + +> [+] Add New Character (2) +> [+] Fall (sprite jatuh) NOTED : BELUM SELESAI. +> [+] Animasi Take Hit diff --git a/asset/Player1/New/attack-player1.png b/asset/Player1/New/attack-player1.png new file mode 100644 index 0000000..670ca71 Binary files /dev/null and b/asset/Player1/New/attack-player1.png differ diff --git a/asset/Player1/New/death-player1.png b/asset/Player1/New/death-player1.png new file mode 100644 index 0000000..1616b52 Binary files /dev/null and b/asset/Player1/New/death-player1.png differ diff --git a/asset/Player1/New/idle-player1.png b/asset/Player1/New/idle-player1.png new file mode 100644 index 0000000..a8a93c3 Binary files /dev/null and b/asset/Player1/New/idle-player1.png differ diff --git a/asset/Player1/New/jump-player1.png b/asset/Player1/New/jump-player1.png new file mode 100644 index 0000000..bcff986 Binary files /dev/null and b/asset/Player1/New/jump-player1.png differ diff --git a/asset/Player1/New/run-player1.png b/asset/Player1/New/run-player1.png new file mode 100644 index 0000000..a4e3f49 Binary files /dev/null and b/asset/Player1/New/run-player1.png differ diff --git a/asset/Player1a/Attack1.png b/asset/Player1a/Attack1.png new file mode 100644 index 0000000..f159b98 Binary files /dev/null and b/asset/Player1a/Attack1.png differ diff --git a/asset/Player1a/Attack2.png b/asset/Player1a/Attack2.png new file mode 100644 index 0000000..d3fe455 Binary files /dev/null and b/asset/Player1a/Attack2.png differ diff --git a/asset/Player1a/Death.png b/asset/Player1a/Death.png new file mode 100644 index 0000000..34d159d Binary files /dev/null and b/asset/Player1a/Death.png differ diff --git a/asset/Player1a/Fall.png b/asset/Player1a/Fall.png new file mode 100644 index 0000000..82f1213 Binary files /dev/null and b/asset/Player1a/Fall.png differ diff --git a/asset/Player1a/Idle.png b/asset/Player1a/Idle.png new file mode 100644 index 0000000..c012d08 Binary files /dev/null and b/asset/Player1a/Idle.png differ diff --git a/asset/Player1a/Jump.png b/asset/Player1a/Jump.png new file mode 100644 index 0000000..86b3ca6 Binary files /dev/null and b/asset/Player1a/Jump.png differ diff --git a/asset/Player1a/Run.png b/asset/Player1a/Run.png new file mode 100644 index 0000000..5eef5da Binary files /dev/null and b/asset/Player1a/Run.png differ diff --git a/asset/Player1a/Takehit.png b/asset/Player1a/Takehit.png new file mode 100644 index 0000000..ed94e5b Binary files /dev/null and b/asset/Player1a/Takehit.png differ diff --git a/asset/Player1a/wizard.png b/asset/Player1a/wizard.png new file mode 100644 index 0000000..02af53b Binary files /dev/null and b/asset/Player1a/wizard.png differ diff --git a/asset/Player1a/wizard.xcf b/asset/Player1a/wizard.xcf new file mode 100644 index 0000000..c435df4 Binary files /dev/null and b/asset/Player1a/wizard.xcf differ diff --git a/asset/Player2a/Attack1.png b/asset/Player2a/Attack1.png new file mode 100644 index 0000000..793dcaa Binary files /dev/null and b/asset/Player2a/Attack1.png differ diff --git a/asset/Player2a/Attack2.png b/asset/Player2a/Attack2.png new file mode 100644 index 0000000..a37703b Binary files /dev/null and b/asset/Player2a/Attack2.png differ diff --git a/asset/Player2a/Attack3.png b/asset/Player2a/Attack3.png new file mode 100644 index 0000000..2a2a897 Binary files /dev/null and b/asset/Player2a/Attack3.png differ diff --git a/asset/Player2a/Death.png b/asset/Player2a/Death.png new file mode 100644 index 0000000..465f31a Binary files /dev/null and b/asset/Player2a/Death.png differ diff --git a/asset/Player2a/Fall.png b/asset/Player2a/Fall.png new file mode 100644 index 0000000..97b9b9f Binary files /dev/null and b/asset/Player2a/Fall.png differ diff --git a/asset/Player2a/Idle.png b/asset/Player2a/Idle.png new file mode 100644 index 0000000..8aeb3c6 Binary files /dev/null and b/asset/Player2a/Idle.png differ diff --git a/asset/Player2a/Jump.png b/asset/Player2a/Jump.png new file mode 100644 index 0000000..66354d9 Binary files /dev/null and b/asset/Player2a/Jump.png differ diff --git a/asset/Player2a/Run.png b/asset/Player2a/Run.png new file mode 100644 index 0000000..822079c Binary files /dev/null and b/asset/Player2a/Run.png differ diff --git a/asset/Player2a/Takehit.png b/asset/Player2a/Takehit.png new file mode 100644 index 0000000..93f980a Binary files /dev/null and b/asset/Player2a/Takehit.png differ diff --git a/asset/Player2a/warrior.png b/asset/Player2a/warrior.png new file mode 100644 index 0000000..7861832 Binary files /dev/null and b/asset/Player2a/warrior.png differ diff --git a/asset/Player2a/warrior.xcf b/asset/Player2a/warrior.xcf new file mode 100644 index 0000000..4776ef9 Binary files /dev/null and b/asset/Player2a/warrior.xcf differ diff --git a/asset/background/images_1.jpeg b/asset/background/images_1.jpeg new file mode 100644 index 0000000..24257d8 Binary files /dev/null and b/asset/background/images_1.jpeg differ diff --git a/asset/css/style.css b/asset/css/style.css index 8300d89..3f01346 100644 --- a/asset/css/style.css +++ b/asset/css/style.css @@ -1,5 +1,6 @@ -* { +*,html,body,div{ font-family: 'Press Start 2P', cursive; + font-size: 10px; } body { @@ -58,7 +59,6 @@ table .intruksiTableP2 tbody { border: 4px solid #4B5563; width: 10vw; height: 8vh; - ; border-radius: 8px; } diff --git a/asset/image/jump-player2.png b/asset/image/jump-player2.png deleted file mode 100644 index cec6b0c..0000000 Binary files a/asset/image/jump-player2.png and /dev/null differ diff --git a/asset/js/main.js b/asset/js/main.js index a8dd838..5bdd1e0 100644 --- a/asset/js/main.js +++ b/asset/js/main.js @@ -1,468 +1,599 @@ kaboom({ - width: 1280, - height: 720, - scale: 0.7, - debug: false -}) - -loadSprite("background", "asset/background/background_layer_1.png") -loadSprite("trees", "asset/background/background_layer_2.png") + width: 1280, + height: 720, + scale: 0.7, + debug: false, +}); + +const punchSound = new Audio("asset/sound/hit.wav"); + +loadSprite("background", "asset/background/background_layer_1.png"); +loadSprite("trees", "asset/background/background_layer_2.png"); loadSpriteAtlas("asset/image/shopUpdate.png", { - "ground-golden": { - "x": 16, - "y": 0, - "width": 16, - "height": 16, - }, - "deep-ground": { - "x": 16, - "y": 32, - "width": 16, - "height": 16 + "ground-golden": { + x: 16, + y: 0, + width: 16, + height: 16, + }, + "deep-ground": { + x: 16, + y: 32, + width: 16, + height: 16, + }, + "ground-silver": { + x: 150, + y: 0, + width: 16, + height: 16, + }, +}); + +loadSprite("shop", "asset/image/shop_anim.png", { + sliceX: 6, + sliceY: 1, + anims: { + default: { + from: 0, + to: 5, + speed: 12, + loop: true, }, - "ground-silver": { - "x": 150, - "y": 0, - "width": 16, - "height": 16 + }, +}); +loadSprite("fence", "asset/image/fence_1.png"); +loadSprite("sign", "asset/image/sign.png"); + +// loadSprite("idle-player1", "asset/Player1/idle-player1.png", { +// sliceX: 8, sliceY: 1, anims: { "idle": {from: 0, to: 7, speed: 12, loop: true}} +// }) +// loadSprite("jump-player1", "asset/Player1/jump-player1.png", { +// sliceX: 2, sliceY: 1, anims: { "jump": { from: 0, to: 1, speed: 2, loop: true}} +// }) +// loadSprite("attack-player1", "asset/Player1/attack-player1.png", { +// sliceX: 6, sliceY: 1, anims: { "attack": { from: 1, to: 5, speed: 18}} +// }) +// loadSprite("run-player1", "asset/Player1/run-player1.png", { +// sliceX: 8, sliceY: 1, anims: { "run": { from: 0, to: 7, speed: 18}} +// }) +// loadSprite("death-player1", "asset/Player1/death-player1.png", { +// sliceX: 6, sliceY: 1, anims: { "death": { from: 0, to: 5, speed: 10}} +// }) + +loadSprite("idle-player1", "asset/Player1a/idle.png", { + sliceX: 8, + sliceY: 1, + anims: { idle: { from: 0, to: 7, speed: 12, loop: true } }, +}); +loadSprite("fall-player1", "asset/Player1a/fall.png", { + sliceX: 2, + sliceY: 1, + anims: { fall: { from: 0, to: 2, speed: 2, loop: true } }, +}); +loadSprite("jump-player1", "asset/Player1a/jump.png", { + sliceX: 2, + sliceY: 1, + anims: { jump: { from: 0, to: 1, speed: 2, loop: true } }, +}); +loadSprite("attack-player1", "asset/Player1a/attack1.png", { + sliceX: 8, + sliceY: 1, + anims: { attack: { from: 0, to: 5, speed: 12 } }, +}); +loadSprite("take-hit-player1", "asset/Player1a/Takehit.png", { + sliceX: 3, + sliceY: 1, + anims: { takehit: { from: 0, to: 1, speed: 7 } }, +}); +loadSprite("run-player1", "asset/Player1a/run.png", { + sliceX: 8, + sliceY: 1, + anims: { run: { from: 0, to: 7, speed: 18 } }, +}); +loadSprite("death-player1", "asset/Player1a/death.png", { + sliceX: 7, + sliceY: 1, + anims: { death: { from: 0, to: 5, speed: 10 } }, +}); + +// loadSpSrite("idle-player2", "asset/Player2/idle-player2.png", { +// sliceX: 4, sliceY: 1, anims: { "idle": { from: 0, to: 3, speed: 8, loop: true}} +// }) +// loadSprite("jump-player2", "asset/Player2/jump-player2.png", { +// sliceX: 2, sliceY: 1, anims: {"jump": { from: 0, to: 1, speed: 2, loop: true}} +// }) +// loadSprite("attack-player2", "asset/Player2/attack-player2.png", { +// sliceX: 4, sliceY: 1, anims: { "attack": { from: 0, to: 3, speed: 18}} +// }) +// loadSprite("run-player2", "asset/Player2/run-player2.png", { +// sliceX: 8, sliceY: 1, anims: { "run": { from: 0, to: 7, speed: 18}} +// }) +// loadSprite("death-player2", "asset/Player2/death-player2.png", { +// sliceX: 7, sliceY: 1, anims: { "death": { from: 0, to: 6, speed: 10}} +// }) + +loadSprite("idle-player2", "asset/Player2a/idle.png", { + sliceX: 10, + sliceY: 1, + anims: { idle: { from: 0, to: 3, speed: 8, loop: true } }, +}); +loadSprite("fall-player2", "asset/Player2a/fall.png", { + sliceX: 3, + sliceY: 1, + anims: { fall: { from: 0, to: 2, speed: 4, loop: true } }, +}); +loadSprite("jump-player2", "asset/Player2a/jump.png", { + sliceX: 3, + sliceY: 1, + anims: { jump: { from: 0, to: 1, speed: 2, loop: true } }, +}); +loadSprite("attack-player2", "asset/Player2a/attack2.png", { + sliceX: 7, + sliceY: 1, + anims: { attack: { from: 0, to: 3, speed: 18 } }, +}); +loadSprite("take-hit-player2", "asset/Player2a/Takehit.png", { + sliceX: 3, + sliceY: 1, + anims: { takehit: { from: 0, to: 1, speed: 7 } }, +}); +loadSprite("run-player2", "asset/Player2a/run.png", { + sliceX: 8, + sliceY: 1, + anims: { run: { from: 0, to: 7, speed: 18 } }, +}); +loadSprite("death-player2", "asset/Player2a/death.png", { + sliceX: 7, + sliceY: 1, + anims: { death: { from: 0, to: 6, speed: 10 } }, +}); + +scene("fight", () => { + const background = add([sprite("background"), scale(4)]); + + background.add([sprite("trees")]); + + const groundTiles = addLevel( + [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "------#######-----------", + "dddddddddddddddddddddddd", + "dddddddddddddddddddddddd", + ], + { + tileWidth: 16, + tileHeight: 16, + tiles: { + "#": () => [sprite("ground-golden"), area(), body({ isStatic: true })], + "-": () => [sprite("ground-silver"), area(), body({ isStatic: true })], + d: () => [sprite("deep-ground"), area(), body({ isStatic: true })], + }, } -}) + ); -loadSprite("shop", "asset/image/shop_anim.png", { - sliceX: 6, - sliceY: 1, - anims: { - "default": { - from: 0, - to: 5, - speed: 12, - loop: true - } + groundTiles.use(scale(4)); + + const shop = background.add([sprite("shop"), pos(170, 15)]); + + shop.play("default"); + + // tembok kanan (gabisa keluar dari dunia) + add([rect(16, 720), area(), body({ isStatic: true }), pos(-20, 0)]); + + // tembok kiri (gabisa keluar dari dunia) + add([rect(16, 720), area(), body({ isStatic: true }), pos(1280, 0)]); + + background.add([sprite("fence"), pos(85, 125)]); + + background.add([sprite("fence"), pos(10, 125)]); + + background.add([sprite("sign"), pos(290, 115)]); + + function makePlayer(posX, posY, width, height, scaleFactor, id) { + return add([ + pos(posX, posY), + scale(scaleFactor), + area({ shape: new Rect(vec2(0), width, height) }), + anchor("center"), + body({ stickToPlatform: true }), + { + isCurrentlyJumping: false, + health: 500, + sprites: { + run: "run-" + id, + idle: "idle-" + id, + fall: "fall-" + id, + jump: "jump-" + id, + attack: "attack-" + id, + takehit: "takehit-" + id, + death: "death-" + id, + }, + }, + ]); + } + + setGravity(1200); + + // Player 1 + const player1 = makePlayer(200, 100, 16, 82, 4, "player1"); + player1.use(sprite(player1.sprites.idle)); + player1.play("idle"); + + // Run + function run(player, speed, flipPlayer) { + if (player.health === 0) { + return; } -}) -loadSprite("fence", "asset/image/fence_1.png") -loadSprite("sign", "asset/image/sign.png") - -loadSprite("idle-player1", "asset/Player1/idle-player1.png", { - sliceX: 8, sliceY: 1, anims: { "idle": {from: 0, to: 7, speed: 12, loop: true}} -}) -loadSprite("jump-player1", "asset/Player1/jump-player1.png", { - sliceX: 2, sliceY: 1, anims: { "jump": { from: 0, to: 1, speed: 2, loop: true}} -}) -loadSprite("attack-player1", "asset/Player1/attack-player1.png", { - sliceX: 6, sliceY: 1, anims: { "attack": { from: 1, to: 5, speed: 18}} -}) -loadSprite("run-player1", "asset/Player1/run-player1.png", { - sliceX: 8, sliceY: 1, anims: { "run": { from: 0, to: 7, speed: 18}} -}) -loadSprite("death-player1", "asset/Player1/death-player1.png", { - sliceX: 6, sliceY: 1, anims: { "death": { from: 0, to: 5, speed: 10}} -}) - -loadSprite("idle-player2", "asset/Player2/idle-player2.png", { - sliceX: 4, sliceY: 1, anims: { "idle": { from: 0, to: 3, speed: 8, loop: true}} -}) -loadSprite("jump-player2", "asset/Player2/jump-player2.png", { - sliceX: 2, sliceY: 1, anims: {"jump": { from: 0, to: 1, speed: 2, loop: true}} -}) -loadSprite("attack-player2", "asset/Player2/attack-player2.png", { - sliceX: 4, sliceY: 1, anims: { "attack": { from: 0, to: 3, speed: 18}} -}) -loadSprite("run-player2", "asset/Player2/run-player2.png", { - sliceX: 8, sliceY: 1, anims: { "run": { from: 0, to: 7, speed: 18}} -}) -loadSprite("death-player2", "asset/Player2/death-player2.png", { - sliceX: 7, sliceY: 1, anims: { "death": { from: 0, to: 6, speed: 10}} -}) -scene("fight", () => { - const background = add([ - sprite("background"), - scale(4) - ]) - - background.add([ - sprite("trees"), - ]) - - const groundTiles = addLevel([ - "","","","","","","","","", - "------#######-----------", - "dddddddddddddddddddddddd", - "dddddddddddddddddddddddd" - ], { - tileWidth: 16, - tileHeight: 16, - tiles: { - "#": () => [ - sprite("ground-golden"), - area(), - body({isStatic: true}) - ], - "-": () => [ - sprite("ground-silver"), - area(), - body({isStatic: true}), - ], - "d": () => [ - sprite("deep-ground"), - area(), - body({isStatic: true}) - ] - } - }) - - groundTiles.use(scale(4)) - - const shop = background.add([ - sprite("shop"), - pos(170, 15), - ]) - - shop.play("default") - - // tembok kanan (gabisa keluar dari dunia) - add([ - rect(16, 720), + if (player.curAnim() !== "run" && !player.isCurrentlyJumping) { + player.use(sprite(player.sprites.run)); + player.play("run"); + } + player.move(speed, 0); + player.flipX = flipPlayer; + } + + function resetPlayerToIdle(player) { + player.use(sprite(player.sprites.idle)); + player.play("idle"); + } + + onKeyDown("d", () => { + run(player1, 500, false); + }); + onKeyRelease("d", () => { + if (player1.health !== 0) { + resetPlayerToIdle(player1); + player1.flipX = false; + } + }); + + onKeyDown("a", () => { + run(player1, -500, true); + }); + onKeyRelease("a", () => { + if (player1.health !== 0) { + resetPlayerToIdle(player1); + player1.flipX = true; + } + }); + + // lompat + function makeJump(player) { + if (player.health === 0) { + return; + } + + if (player.isGrounded()) { + const currentFlip = player.flipX; + player.jump(); + player.use(sprite(player.sprites.jump)); + player.flipX = currentFlip; + player.play("jump"); + player.isCurrentlyJumping = true; + } + } + + // fixed lompat (1x) + function resetAfterJump(player) { + if (player.isGrounded() && player.isCurrentlyJumping) { + player.isCurrentlyJumping = false; + if (player.curAnim() !== "idle") { + resetPlayerToIdle(player); + } + } + // if (player.curAnim() === "fall") { + // resetPlayerToIdle(player); + // } + } + + function makeFall(player) { + if (player.health === 0) { + return; + } + + if (!player.isGrounded() && !player.isCurrentlyJumping) { + player.use(sprite(player.sprites.fall)); + player.play("fall"); + player.isCurrentlyJumping = true; + } else if (player.isGrounded()) { + player.isCurrentlyJumping = false; + } + } + + onKeyDown("w", () => { + makeJump(player1); + }); + + // player1.jumpForce = 800; // Menambahkan gaya lompat untuk player 1 + // player1.onUpdate(() => resetAfterJump(player1)); + // player1.onUpdate(() => { + // if (!player1.isGrounded() && !player1.isCurrentlyJumping) { + // player1.use(sprite(player1.sprites.fall)); + // player1.play("fall"); + // } else if (player1.curAnim() === "fall") { + // resetPlayerToIdle(player1); + // } + // resetAfterJump(player1); + // }); + player1.onUpdate(() => { + if (!player1.isGrounded() && !player1.isCurrentlyJumping) { + player1.use(sprite(player1.sprites.fall)); + player1.play("fall"); + } else if (player1.curAnim() === "fall") { + resetPlayerToIdle(player1); + } + resetAfterJump(player1); + }); + + // attack & attack box + function attack(player, excludedKeys) { + if (player.health === 0) { + return; + } + + for (const key of excludedKeys) { + if (isKeyDown(key)) { + return; + } + } + + const currentFlip = player.flipX; + if (player.curAnim() !== "attack") { + player.use(sprite(player.sprites.attack)); + player.flipX = currentFlip; + const slashX = player.pos.x + 30; + const slashXFlipped = player.pos.x - 350; + const slashY = player.pos.y - 200; + + add([ + rect(300, 300), + area(), + pos(currentFlip ? slashXFlipped : slashX, slashY), + opacity(0), + player.id + "attackHitbox", + ]); + + player.play("attack", { + onEnd: () => { + resetPlayerToIdle(player); + player.flipX = currentFlip; + punchSound.play(); + }, + }); + } + } + + onKeyPress("space", () => { + attack(player1, ["a", "d", "w"]); + }); + + onKeyRelease("space", () => { + destroyAll(player1.id + "attackHitbox"); + }); + + // player 2 + const player2 = makePlayer(1000, 200, 16, 42, 5, "player2"); + player2.use(sprite(player2.sprites.idle)); + player2.play("idle"); + player2.flipX = true; + + // run + onKeyDown("right", () => { + run(player2, 500, false); + }); + onKeyRelease("right", () => { + if (player2.health !== 0) { + resetPlayerToIdle(player2); + player2.flipX = false; + } + }); + + onKeyDown("left", () => { + run(player2, -500, true); + }); + onKeyRelease("left", () => { + if (player2.health !== 0) { + resetPlayerToIdle(player2); + player2.flipX = true; + } + }); + + // lompat + onKeyDown("up", () => { + makeJump(player2); + }); + + //player2.jumpForce = 800; // Menambahkan gaya lompat untuk player 2 + //player2.onUpdate(() => resetAfterJump(player2)); + player2.onUpdate(() => { + if (!player2.isGrounded() && !player2.isCurrentlyJumping) { + player2.use(sprite(player2.sprites.fall)); + player2.play("fall"); + } else if (player2.curAnim() === "fall") { + resetPlayerToIdle(player2); + } + // if (player2.isGrounded() && player2.isCurrentlyJumping) { + // player2.isCurrentlyJumping = false; + // resetPlayerToIdle(player2); + // } + resetAfterJump(player2); + }); + + // attack & attaack hit + onKeyPress("down", () => { + attack(player2, ["left", "right", "up"]); + }); + + onKeyRelease("down", () => { + destroyAll(player2.id + "attackHitbox"); + }); + + const counter = add([ + rect(100, 100), + pos(center().x, center().y - 300), + color(10, 10, 10), area(), - body({isStatic: true}), - pos(-20,0) - ]) + anchor("center"), + ]); - // tembok kiri (gabisa keluar dari dunia) - add([ - rect(16, 720), + // waktu permainan + const count = counter.add([ + text("60"), + area(), + anchor("center"), + { + timeLeft: 60, + }, + ]); + + // notifikasi atau player menang text muncul + const winningText = add([text(""), area(), anchor("center"), pos(center())]); + + let gameOver = false; + onKeyDown("enter", () => (gameOver ? go("fight") : null)); + + function declareWinner(winningText, player1, player2) { + if ( + (player1.health > 0 && player2.health > 0) || + (player1.health === 0 && player2.health === 0) + ) { + winningText.text = "Permainan Seri!"; + } else if (player1.health > 0 && player2.health === 0) { + winningText.text = "Player 1 Menang!"; + player2.use(sprite(player2.sprites.death)); + player2.play("death"); + } else { + winningText.text = "Player 2 Menang!"; + player1.use(sprite(player1.sprites.death)); + player1.play("death"); + } + } + + const countInterval = setInterval(() => { + if (count.timeLeft === 0) { + clearInterval(countInterval); + declareWinner(winningText, player1, player2); + gameOver = true; + + return; + } + count.timeLeft--; + count.text = count.timeLeft; + }, 1000); + + // progress bar + const player1HealthContainer = add([ + rect(500, 70), area(), - body({isStatic: true}), - pos(1280,0) - ]) - - background.add([ - sprite("fence"), - pos(85, 125) - ]) - - background.add([ - sprite("fence"), - pos(10, 125) - ]) - - background.add([ - sprite("sign"), - pos(290, 115) - ]) - - function makePlayer(posX, posY, width, height, scaleFactor, id) { - return add([ - pos(posX, posY), - scale(scaleFactor), - area({shape: new Rect(vec2(0), width, height)}), - anchor("center"), - body({stickToPlatform: true}), - { - isCurrentlyJumping: false, - health: 500, - sprites: { - run: "run-" + id, - idle: "idle-" + id, - jump: "jump-" + id, - attack: "attack-" + id, - death: "death-" + id - } - } - ]) + outline(5), + pos(90, 20), + color(200, 0, 0), + ]); + + const player1HealthBar = player1HealthContainer.add([ + rect(498, 65), + color(0, 180, 0), + pos(498, 70 - 2.5), + rotate(180), + ]); + + player1.onCollide(player2.id + "attackHitbox", () => { + if (gameOver) { + return; } - setGravity(1200) - - // Player 1 - const player1 = makePlayer(200, 100, 16, 42, 4, "player1") - player1.use(sprite(player1.sprites.idle)) - player1.play("idle") - - // Run - function run(player, speed, flipPlayer) { - if (player.health === 0) { - return - } - - if (player.curAnim() !== "run" - && !player.isCurrentlyJumping) { - player.use(sprite(player.sprites.run)) - player.play("run") - } - player.move(speed,0) - player.flipX = flipPlayer + if (player1.health !== 0) { + player1.health -= 50; + tween( + player1HealthBar.width, + player1.health, + 1, + (val) => { + player1HealthBar.width = val; + }, + easings.easeOutSine + ); } - function resetPlayerToIdle(player) { - player.use(sprite(player.sprites.idle)) - player.play("idle") + if (player1.health === 0) { + clearInterval(countInterval); + declareWinner(winningText, player1, player2); + gameOver = true; + //player1.jumpForce = 0; // Mencegah player 1 melompat setelah kalah } - onKeyDown("d", () => { - run(player1, 500, false) - }) - onKeyRelease("d", () => { - if (player1.health !== 0) { - resetPlayerToIdle(player1) - player1.flipX = false - } - }) - - onKeyDown("a", () => { - run(player1, -500, true) - }) - onKeyRelease("a", () => { - if (player1.health !== 0) { - resetPlayerToIdle(player1) - player1.flipX = true - } - }) - - // lompat - function makeJump(player) { - if (player.health === 0) { - return - } - - if (player.isGrounded()) { - const currentFlip = player.flipX - player.jump() - player.use(sprite(player.sprites.jump)) - player.flipX = currentFlip - player.play("jump") - player.isCurrentlyJumping = true - } + if (player1.health !== 0 && player1.curAnim() !== "takehit") { + player1.use(sprite("take-hit-player1")); + player1.play("takehit", { + onEnd: () => { + if (player1.health > 0) { + resetPlayerToIdle(player1); + } + }, + }); } + }); - // fixed lompat (1x) - function resetAfterJump(player) { - if (player.isGrounded() && player.isCurrentlyJumping) { - player.isCurrentlyJumping = false - if (player.curAnim() !== "idle") { - resetPlayerToIdle(player) - } - } + const player2HealthContainer = add([ + rect(500, 70), + area(), + outline(5), + pos(690, 20), + color(200, 0, 0), + ]); + + const player2HealthBar = player2HealthContainer.add([ + rect(498, 65), + color(0, 180, 0), + pos(2.5, 2.5), + ]); + + player2.onCollide(player1.id + "attackHitbox", () => { + if (gameOver) { + return; } - onKeyDown("w", () => { - makeJump(player1) - }) - - player1.onUpdate(() => resetAfterJump(player1)) - - // attack & attack box - function attack(player, excludedKeys) { - if (player.health === 0) { - return - } - - for (const key of excludedKeys) { - if (isKeyDown(key)) { - return - } - } - - const currentFlip = player.flipX - if (player.curAnim() !== "attack") { - player.use(sprite(player.sprites.attack)) - player.flipX = currentFlip - const slashX = player.pos.x + 30 - const slashXFlipped = player.pos.x - 350 - const slashY = player.pos.y - 200 - - add([ - rect(300,300), - area(), - pos(currentFlip ? slashXFlipped: slashX, slashY), - opacity(0), - player.id + "attackHitbox" - ]) - - player.play("attack", { - onEnd: () => { - resetPlayerToIdle(player) - player.flipX = currentFlip - } - }) - } + if (player2.health !== 0 && player2.curAnim() !== "takehit") { + player2.use(sprite("take-hit-player2")); + player2.play("takehit", { + onEnd: () => { + if (player2.health > 0) { + resetPlayerToIdle(player2); + } + }, + }); } - onKeyPress("space", () => { - attack(player1, ["a", "d", "w"]) - }) - - onKeyRelease("space", () => { - destroyAll(player1.id + "attackHitbox") - }) - - // player 2 - const player2 = makePlayer(1000, 200, 16, 52, 4, "player2") - player2.use(sprite(player2.sprites.idle)) - player2.play("idle") - player2.flipX = true - - // run - onKeyDown("right", () => { - run(player2, 500, false) - }) - onKeyRelease("right", () => { - if (player2.health !== 0) { - resetPlayerToIdle(player2) - player2.flipX = false - } - }) - - onKeyDown("left", () => { - run(player2, -500, true) - }) - onKeyRelease("left", () => { - if (player2.health !== 0) { - resetPlayerToIdle(player2) - player2.flipX = true - } - }) - - // lompat - onKeyDown("up", () => { - makeJump(player2) - }) - - player2.onUpdate(() => resetAfterJump(player2)) - - // attack & attaack hit - onKeyPress("down", () => { - attack(player2, ["left", "right", "up"]) - }) - - onKeyRelease("down", () => { - destroyAll(player2.id + "attackHitbox") - }) - - const counter = add([ - rect(100,100), - pos(center().x, center().y - 300), - color(10,10,10), - area(), - anchor("center") - ]) - - // waktu permainan - const count = counter.add([ - text("60"), - area(), - anchor("center"), - { - timeLeft: 60, - } - ]) - - // notifikasi atau player menang text muncul - const winningText = add([ - text(""), - area(), - anchor("center"), - pos(center()) - ]) - - let gameOver = false - onKeyDown("enter", () => gameOver ? go("fight") : null) - - function declareWinner(winningText, player1, player2) { - if (player1.health > 0 && player2.health > 0 - || player1.health === 0 && player2.health === 0) { - winningText.text = "Permainan Seri!" - } else if (player1.health > 0 && player2.health === 0) { - winningText.text = "Player 1 Menang!" - player2.use(sprite(player2.sprites.death)) - player2.play("death") - } else { - winningText.text = "Player 2 Menang!" - player1.use(sprite(player1.sprites.death)) - player1.play("death") - } + if (player2.health !== 0) { + player2.health -= 50; + tween( + player2HealthBar.width, + player2.health, + 1, + (val) => { + player2HealthBar.width = val; + }, + easings.easeOutSine + ); } - const countInterval = setInterval(() => { - if (count.timeLeft === 0) { - clearInterval(countInterval) - declareWinner(winningText, player1, player2) - gameOver = true - - return - } - count.timeLeft-- - count.text = count.timeLeft - }, 1000) - - // progress bar - const player1HealthContainer = add([ - rect(500, 70), - area(), - outline(5), - pos(90, 20), - color(200,0,0) - ]) - - const player1HealthBar = player1HealthContainer.add([ - rect(498, 65), - color(0,180,0), - pos(498, 70 - 2.5), - rotate(180) - ]) - - player1.onCollide(player2.id + "attackHitbox", () => { - if (gameOver) { - return - } - - if (player1.health !== 0) { - player1.health -= 50 - tween(player1HealthBar.width, player1.health, 1, (val) => { - player1HealthBar.width = val - }, easings.easeOutSine) - } - - if (player1.health === 0) { - clearInterval(countInterval) - declareWinner(winningText, player1, player2) - gameOver = true - } - }) - - const player2HealthContainer = add([ - rect(500, 70), - area(), - outline(5), - pos(690, 20), - color(200,0,0) - ]) - - const player2HealthBar = player2HealthContainer.add([ - rect(498, 65), - color(0,180,0), - pos(2.5, 2.5), - ]) - - player2.onCollide(player1.id + "attackHitbox", () => { - if (gameOver) { - return - } - - if (player2.health !== 0) { - player2.health -= 50 - tween(player2HealthBar.width, player2.health, 1, (val) => { - player2HealthBar.width = val - }, easings.easeOutSine) - } - - if (player2.health === 0) { - clearInterval(countInterval) - declareWinner(winningText, player1, player2) - gameOver = true - } - }) -}) - -go("fight") \ No newline at end of file + if (player2.health === 0) { + clearInterval(countInterval); + declareWinner(winningText, player1, player2); + gameOver = true; + //player2.jumpForce = 0; // Mencegah player 2 melompat setelah kalah + } + }); +}); + +go("fight"); diff --git a/asset/sound/effects.mp3 b/asset/sound/effects.mp3 deleted file mode 100644 index 0fc412c..0000000 Binary files a/asset/sound/effects.mp3 and /dev/null differ diff --git a/asset/sound/magic.wav b/asset/sound/magic.wav new file mode 100644 index 0000000..1e55ba4 Binary files /dev/null and b/asset/sound/magic.wav differ diff --git a/asset/sound/sword.wav b/asset/sound/sword.wav new file mode 100644 index 0000000..960457f Binary files /dev/null and b/asset/sound/sword.wav differ diff --git a/cara menjalankan game.txt b/cara menjalankan game.txt new file mode 100644 index 0000000..03ad140 --- /dev/null +++ b/cara menjalankan game.txt @@ -0,0 +1,4 @@ +Cara menjalanlan Game : + +- Run Menggunakan Extension Live Server +- Connect ke jaringan diff --git a/index.html b/index.html index 7f34070..eaaec80 100644 --- a/index.html +++ b/index.html @@ -1,19 +1,19 @@ -
- - - + + + +