hitbox fix
This commit is contained in:
parent
d3640e0a32
commit
88cf60e096
104
Script.js
104
Script.js
@ -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";
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user