hitbox fix

This commit is contained in:
Bluwww 2025-12-13 11:50:04 +07:00
parent d3640e0a32
commit 88cf60e096

104
Script.js
View File

@ -1,5 +1,7 @@
"use strict";
const DEBUG_HITBOX = true;
// ================== BGM SYSTEM ==================
const bgmList = [
{ normal: "music/Scary.mp3", gameover: "music/ScaryGO.mp3" },
@ -114,7 +116,6 @@ window.onload = function () {
init();
};
// Init
function init() {
c = document.getElementById("canvas");
@ -135,7 +136,6 @@ function init() {
requestAnimationFrame(gameLoop);
}
function gameLoop(timestamp) {
if (!gameStarted) return;
@ -269,7 +269,17 @@ function drawGame() {
t.draw();
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++;
abilityTokens.splice(i, 1);
createParticles(t.x, t.y, 15, "#00ffea");
@ -286,6 +296,8 @@ function drawGame() {
// Player
if (!player1.dead) {
player1.draw();
// DEBUG: Lihat Hitbox Player
if (DEBUG_HITBOX) drawDebugHitbox(player1.getHitbox(), "lime");
}
// Enemies
@ -294,6 +306,8 @@ function drawGame() {
s.draw();
s.update();
if (DEBUG_HITBOX) drawDebugHitbox(s.getHitbox(), "red");
if (s.x < -200) {
enemyShipArray.splice(i, 1);
i--;
@ -311,15 +325,8 @@ function drawGame() {
// Collision with player (hitbox vs hitbox)
if (!player1.dead && Tabrakan(player1.getHitbox(), s.getHitbox())) {
explosions.push(
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"
);
explosions.push(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");
enemyShipArray.splice(i, 1);
i--;
handlePlayerHit();
@ -333,11 +340,14 @@ function drawGame() {
m.draw();
m.update();
if (DEBUG_HITBOX) drawDebugHitbox(m.getHitbox(), "cyan");
let hit = false;
for (let j = 0; j < enemyShipArray.length; 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;
explosion_enemy.currentTime = 0;
explosion_enemy.play();
@ -374,7 +384,10 @@ function drawGame() {
b.draw();
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(
new Explosion(
player1.x + player1.width / 2,
@ -421,6 +434,14 @@ function drawGame() {
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() {
drawNewText(" " + player1.score, 1400, 760, "white");
@ -467,16 +488,18 @@ class PlayerObject {
};
}
getHitbox() {
const w = this.width * 0.45;
const h = this.height * 0.55;
const h = this.height * 0.05;
const w = this.width * 0.8;
const x = this.x + (this.width - w) / 2;
const y = this.y + (this.height - h) / 2;
return { x, y, width: w, height: h };
}
draw() {
// Invi frames
if (this.invincible > 0 && game.frames % 10 < 5) {
return;
}
@ -646,7 +669,7 @@ function updateCamera() {
cameraY += (clamped - cameraY) * 0.1;
}
//
//
class LaserBullet {
constructor(x, y) {
this.x = x;
@ -656,6 +679,10 @@ class LaserBullet {
this.speed = 16;
}
getHitbox() {
return { x: this.x, y: this.y, width: this.width, height: this.height };
}
draw() {
let g = ctx.createLinearGradient(
this.x,
@ -678,7 +705,7 @@ class LaserBullet {
}
}
//
//
class EnemyObj {
constructor(x, y, speed, img, pattern = "straight") {
this.x = x;
@ -693,9 +720,10 @@ class EnemyObj {
this.angle = 0;
}
getHitbox() {
const w = this.width * 0.65;
const h = this.height * 0.65;
const w = this.width * 0.55;
const h = this.height * 0.55;
const x = this.x + (this.width - w) / 2;
const y = this.y + (this.height - h) / 2;
return { x, y, width: w, height: h };
@ -732,6 +760,17 @@ class EnemyBullet {
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() {
let g = ctx.createLinearGradient(
this.x + this.width,
@ -910,12 +949,7 @@ function useAbility() {
// Explosions for all enemies
enemyShipArray.forEach((e) => {
explosions.push(new Explosion(e.x + e.width / 2, e.y + e.height / 2));
createParticles(
e.x + e.width / 2,
e.y + e.height / 2,
20,
"#ff9900"
);
createParticles(e.x + e.width / 2, e.y + e.height / 2, 20, "#ff9900");
});
enemyShipArray = [];
@ -1035,7 +1069,7 @@ class Explosion {
}
}
// GAME OVER / PAUSE
// GAME OVER / PAUSE
function drawGameOver() {
ctx.fillStyle = "rgba(53, 0, 0, 0.7)";
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
@ -1052,11 +1086,7 @@ function drawGameOver() {
canvasWidth / 2,
canvasHeight / 2 + 20
);
ctx.fillText(
"Refresh to Restart",
canvasWidth / 2,
canvasHeight / 2 + 70
);
ctx.fillText("Refresh to Restart", canvasWidth / 2, canvasHeight / 2 + 70);
ctx.textAlign = "left";
}
@ -1070,11 +1100,7 @@ function drawPauseOverlay() {
ctx.textAlign = "center";
ctx.fillText("PAUSED", canvasWidth / 2, canvasHeight / 2);
ctx.font = "24px Arial";
ctx.fillText(
"Press P to Resume",
canvasWidth / 2,
canvasHeight / 2 + 50
);
ctx.fillText("Press P to Resume", canvasWidth / 2, canvasHeight / 2 + 50);
ctx.textAlign = "left";
}