hitbox fix
This commit is contained in:
parent
d3640e0a32
commit
88cf60e096
104
Script.js
104
Script.js
@ -1,5 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const DEBUG_HITBOX = true;
|
||||||
|
|
||||||
// ================== BGM SYSTEM ==================
|
// ================== BGM SYSTEM ==================
|
||||||
const bgmList = [
|
const bgmList = [
|
||||||
{ normal: "music/Scary.mp3", gameover: "music/ScaryGO.mp3" },
|
{ normal: "music/Scary.mp3", gameover: "music/ScaryGO.mp3" },
|
||||||
@ -114,7 +116,6 @@ window.onload = function () {
|
|||||||
init();
|
init();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
function init() {
|
function init() {
|
||||||
c = document.getElementById("canvas");
|
c = document.getElementById("canvas");
|
||||||
@ -135,7 +136,6 @@ function init() {
|
|||||||
requestAnimationFrame(gameLoop);
|
requestAnimationFrame(gameLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function gameLoop(timestamp) {
|
function gameLoop(timestamp) {
|
||||||
if (!gameStarted) return;
|
if (!gameStarted) return;
|
||||||
|
|
||||||
@ -269,7 +269,17 @@ function drawGame() {
|
|||||||
t.draw();
|
t.draw();
|
||||||
t.update();
|
t.update();
|
||||||
|
|
||||||
if (!player1.dead && Tabrakan(player1.getHitbox(), t)) {
|
// Hitbox token sederhana (tidak perlu .getHitbox karena bentuknya simple)
|
||||||
|
// Tapi kita pakai logika bounding box manual di sini
|
||||||
|
if (
|
||||||
|
!player1.dead &&
|
||||||
|
Tabrakan(player1.getHitbox(), {
|
||||||
|
x: t.x,
|
||||||
|
y: t.y,
|
||||||
|
width: t.width,
|
||||||
|
height: t.height,
|
||||||
|
})
|
||||||
|
) {
|
||||||
abilityCharges++;
|
abilityCharges++;
|
||||||
abilityTokens.splice(i, 1);
|
abilityTokens.splice(i, 1);
|
||||||
createParticles(t.x, t.y, 15, "#00ffea");
|
createParticles(t.x, t.y, 15, "#00ffea");
|
||||||
@ -286,6 +296,8 @@ function drawGame() {
|
|||||||
// Player
|
// Player
|
||||||
if (!player1.dead) {
|
if (!player1.dead) {
|
||||||
player1.draw();
|
player1.draw();
|
||||||
|
// DEBUG: Lihat Hitbox Player
|
||||||
|
if (DEBUG_HITBOX) drawDebugHitbox(player1.getHitbox(), "lime");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enemies
|
// Enemies
|
||||||
@ -294,6 +306,8 @@ function drawGame() {
|
|||||||
s.draw();
|
s.draw();
|
||||||
s.update();
|
s.update();
|
||||||
|
|
||||||
|
if (DEBUG_HITBOX) drawDebugHitbox(s.getHitbox(), "red");
|
||||||
|
|
||||||
if (s.x < -200) {
|
if (s.x < -200) {
|
||||||
enemyShipArray.splice(i, 1);
|
enemyShipArray.splice(i, 1);
|
||||||
i--;
|
i--;
|
||||||
@ -311,15 +325,8 @@ function drawGame() {
|
|||||||
|
|
||||||
// Collision with player (hitbox vs hitbox)
|
// Collision with player (hitbox vs hitbox)
|
||||||
if (!player1.dead && Tabrakan(player1.getHitbox(), s.getHitbox())) {
|
if (!player1.dead && Tabrakan(player1.getHitbox(), s.getHitbox())) {
|
||||||
explosions.push(
|
explosions.push(new Explosion(s.x + s.width / 2, s.y + s.height / 2));
|
||||||
new Explosion(s.x + s.width / 2, s.y + s.height / 2)
|
createParticles(s.x + s.width / 2, s.y + s.height / 2, 20, "#ff6600");
|
||||||
);
|
|
||||||
createParticles(
|
|
||||||
s.x + s.width / 2,
|
|
||||||
s.y + s.height / 2,
|
|
||||||
20,
|
|
||||||
"#ff6600"
|
|
||||||
);
|
|
||||||
enemyShipArray.splice(i, 1);
|
enemyShipArray.splice(i, 1);
|
||||||
i--;
|
i--;
|
||||||
handlePlayerHit();
|
handlePlayerHit();
|
||||||
@ -333,11 +340,14 @@ function drawGame() {
|
|||||||
m.draw();
|
m.draw();
|
||||||
m.update();
|
m.update();
|
||||||
|
|
||||||
|
if (DEBUG_HITBOX) drawDebugHitbox(m.getHitbox(), "cyan");
|
||||||
|
|
||||||
let hit = false;
|
let hit = false;
|
||||||
for (let j = 0; j < enemyShipArray.length; j++) {
|
for (let j = 0; j < enemyShipArray.length; j++) {
|
||||||
let en = enemyShipArray[j];
|
let en = enemyShipArray[j];
|
||||||
|
|
||||||
if (Tabrakan(m, en.getHitbox())) {
|
// PERBAIKAN: Gunakan .getHitbox() untuk kedua objek
|
||||||
|
if (Tabrakan(m.getHitbox(), en.getHitbox())) {
|
||||||
player1.score += 100;
|
player1.score += 100;
|
||||||
explosion_enemy.currentTime = 0;
|
explosion_enemy.currentTime = 0;
|
||||||
explosion_enemy.play();
|
explosion_enemy.play();
|
||||||
@ -374,7 +384,10 @@ function drawGame() {
|
|||||||
b.draw();
|
b.draw();
|
||||||
b.update();
|
b.update();
|
||||||
|
|
||||||
if (!player1.dead && Tabrakan(b, player1.getHitbox())) {
|
if (DEBUG_HITBOX) drawDebugHitbox(b.getHitbox(), "orange");
|
||||||
|
|
||||||
|
// PERBAIKAN: Gunakan b.getHitbox() agar collision lebih akurat (tidak kena glow)
|
||||||
|
if (!player1.dead && Tabrakan(b.getHitbox(), player1.getHitbox())) {
|
||||||
explosions.push(
|
explosions.push(
|
||||||
new Explosion(
|
new Explosion(
|
||||||
player1.x + player1.width / 2,
|
player1.x + player1.width / 2,
|
||||||
@ -421,6 +434,14 @@ function drawGame() {
|
|||||||
drawUI();
|
drawUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function drawDebugHitbox(rect, color) {
|
||||||
|
ctx.save();
|
||||||
|
ctx.strokeStyle = color;
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.strokeRect(rect.x, rect.y, rect.width, rect.height);
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
function drawUI() {
|
function drawUI() {
|
||||||
drawNewText(" " + player1.score, 1400, 760, "white");
|
drawNewText(" " + player1.score, 1400, 760, "white");
|
||||||
|
|
||||||
@ -467,16 +488,18 @@ class PlayerObject {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getHitbox() {
|
getHitbox() {
|
||||||
const w = this.width * 0.45;
|
const h = this.height * 0.05;
|
||||||
const h = this.height * 0.55;
|
|
||||||
|
const w = this.width * 0.8;
|
||||||
|
|
||||||
const x = this.x + (this.width - w) / 2;
|
const x = this.x + (this.width - w) / 2;
|
||||||
const y = this.y + (this.height - h) / 2;
|
const y = this.y + (this.height - h) / 2;
|
||||||
|
|
||||||
return { x, y, width: w, height: h };
|
return { x, y, width: w, height: h };
|
||||||
}
|
}
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
// Invi frames
|
|
||||||
if (this.invincible > 0 && game.frames % 10 < 5) {
|
if (this.invincible > 0 && game.frames % 10 < 5) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -646,7 +669,7 @@ function updateCamera() {
|
|||||||
cameraY += (clamped - cameraY) * 0.1;
|
cameraY += (clamped - cameraY) * 0.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
class LaserBullet {
|
class LaserBullet {
|
||||||
constructor(x, y) {
|
constructor(x, y) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
@ -656,6 +679,10 @@ class LaserBullet {
|
|||||||
this.speed = 16;
|
this.speed = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getHitbox() {
|
||||||
|
return { x: this.x, y: this.y, width: this.width, height: this.height };
|
||||||
|
}
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
let g = ctx.createLinearGradient(
|
let g = ctx.createLinearGradient(
|
||||||
this.x,
|
this.x,
|
||||||
@ -678,7 +705,7 @@ class LaserBullet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
class EnemyObj {
|
class EnemyObj {
|
||||||
constructor(x, y, speed, img, pattern = "straight") {
|
constructor(x, y, speed, img, pattern = "straight") {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
@ -693,9 +720,10 @@ class EnemyObj {
|
|||||||
this.angle = 0;
|
this.angle = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getHitbox() {
|
getHitbox() {
|
||||||
const w = this.width * 0.65;
|
const w = this.width * 0.55;
|
||||||
const h = this.height * 0.65;
|
const h = this.height * 0.55;
|
||||||
const x = this.x + (this.width - w) / 2;
|
const x = this.x + (this.width - w) / 2;
|
||||||
const y = this.y + (this.height - h) / 2;
|
const y = this.y + (this.height - h) / 2;
|
||||||
return { x, y, width: w, height: h };
|
return { x, y, width: w, height: h };
|
||||||
@ -732,6 +760,17 @@ class EnemyBullet {
|
|||||||
this.vy = (dy / len) * speed;
|
this.vy = (dy / len) * speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getHitbox() {
|
||||||
|
const padding = 1;
|
||||||
|
return {
|
||||||
|
x: this.x + padding,
|
||||||
|
y: this.y + padding,
|
||||||
|
width: this.width - padding * 2,
|
||||||
|
height: this.height - padding * 2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
let g = ctx.createLinearGradient(
|
let g = ctx.createLinearGradient(
|
||||||
this.x + this.width,
|
this.x + this.width,
|
||||||
@ -910,12 +949,7 @@ function useAbility() {
|
|||||||
// Explosions for all enemies
|
// Explosions for all enemies
|
||||||
enemyShipArray.forEach((e) => {
|
enemyShipArray.forEach((e) => {
|
||||||
explosions.push(new Explosion(e.x + e.width / 2, e.y + e.height / 2));
|
explosions.push(new Explosion(e.x + e.width / 2, e.y + e.height / 2));
|
||||||
createParticles(
|
createParticles(e.x + e.width / 2, e.y + e.height / 2, 20, "#ff9900");
|
||||||
e.x + e.width / 2,
|
|
||||||
e.y + e.height / 2,
|
|
||||||
20,
|
|
||||||
"#ff9900"
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
enemyShipArray = [];
|
enemyShipArray = [];
|
||||||
@ -1035,7 +1069,7 @@ class Explosion {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GAME OVER / PAUSE
|
// GAME OVER / PAUSE
|
||||||
function drawGameOver() {
|
function drawGameOver() {
|
||||||
ctx.fillStyle = "rgba(53, 0, 0, 0.7)";
|
ctx.fillStyle = "rgba(53, 0, 0, 0.7)";
|
||||||
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
|
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
|
||||||
@ -1052,11 +1086,7 @@ function drawGameOver() {
|
|||||||
canvasWidth / 2,
|
canvasWidth / 2,
|
||||||
canvasHeight / 2 + 20
|
canvasHeight / 2 + 20
|
||||||
);
|
);
|
||||||
ctx.fillText(
|
ctx.fillText("Refresh to Restart", canvasWidth / 2, canvasHeight / 2 + 70);
|
||||||
"Refresh to Restart",
|
|
||||||
canvasWidth / 2,
|
|
||||||
canvasHeight / 2 + 70
|
|
||||||
);
|
|
||||||
|
|
||||||
ctx.textAlign = "left";
|
ctx.textAlign = "left";
|
||||||
}
|
}
|
||||||
@ -1070,11 +1100,7 @@ function drawPauseOverlay() {
|
|||||||
ctx.textAlign = "center";
|
ctx.textAlign = "center";
|
||||||
ctx.fillText("PAUSED", canvasWidth / 2, canvasHeight / 2);
|
ctx.fillText("PAUSED", canvasWidth / 2, canvasHeight / 2);
|
||||||
ctx.font = "24px Arial";
|
ctx.font = "24px Arial";
|
||||||
ctx.fillText(
|
ctx.fillText("Press P to Resume", canvasWidth / 2, canvasHeight / 2 + 50);
|
||||||
"Press P to Resume",
|
|
||||||
canvasWidth / 2,
|
|
||||||
canvasHeight / 2 + 50
|
|
||||||
);
|
|
||||||
ctx.textAlign = "left";
|
ctx.textAlign = "left";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user