refisi update
This commit is contained in:
parent
d260dee6c7
commit
8e49077466
1
about.md
1
about.md
@ -1 +0,0 @@
|
|||||||
Permainan dengan nama HarGame adalah game sederhana berbasis HTML,CSS, dan JavaScript dimana pemain menggerakan kotak biru ke kiri atau kanan untuk menghindari blok merah yang jatuh.Skor akan bertambah setiap detik, dan level akan meningkat otomatis sehingga kecepatan musuh semakin cepat.Jika terkena blok, game berakhir dan skor tertinggi disimpan dengan LocalStorage.Game ini menampilkan mekanik dasar seperti gerakan pemain, spawn musuh deteksi tabrakan,dan sistem level
|
|
||||||
BIN
assets/BG.jpg
Normal file
BIN
assets/BG.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
65
assets/game.js
Normal file
65
assets/game.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
const player = document.getElementById("player");
|
||||||
|
const block = document.getElementById("block");
|
||||||
|
const scoreText = document.getElementById("scoreText");
|
||||||
|
|
||||||
|
let score = 0;
|
||||||
|
let playerX = 180;
|
||||||
|
|
||||||
|
// KECEPATAN (DIUBAH)
|
||||||
|
let speed = 1;
|
||||||
|
let speedIncrease = 0.6;
|
||||||
|
let maxSpeed = 12;
|
||||||
|
|
||||||
|
document.addEventListener("keydown", (e) => {
|
||||||
|
if (e.key === "ArrowLeft" && playerX > 0) {
|
||||||
|
playerX -= 20;
|
||||||
|
}
|
||||||
|
if (e.key === "ArrowRight" && playerX < 360) {
|
||||||
|
playerX += 20;
|
||||||
|
}
|
||||||
|
player.style.left = playerX + "px";
|
||||||
|
});
|
||||||
|
|
||||||
|
function moveBlock() {
|
||||||
|
let blockY = -40;
|
||||||
|
let blockX = Math.floor(Math.random() * 360);
|
||||||
|
block.style.left = blockX + "px";
|
||||||
|
|
||||||
|
let fall = setInterval(() => {
|
||||||
|
blockY += speed;
|
||||||
|
block.style.top = blockY + "px";
|
||||||
|
|
||||||
|
// TABRAKAN
|
||||||
|
if (
|
||||||
|
blockY > 450 &&
|
||||||
|
blockX < playerX + 40 &&
|
||||||
|
blockX + 40 > playerX
|
||||||
|
) {
|
||||||
|
alert("Game Over! Score: " + score);
|
||||||
|
score = 0;
|
||||||
|
speed = 1; // reset ke pelan (DIUBAH)
|
||||||
|
scoreText.textContent = "Score: 0";
|
||||||
|
clearInterval(fall);
|
||||||
|
moveBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// BLOCK LOLOS
|
||||||
|
if (blockY > 500) {
|
||||||
|
score++;
|
||||||
|
scoreText.textContent = "Score: " + score;
|
||||||
|
|
||||||
|
// NAIK BERTAHAP (TERASA)
|
||||||
|
if (speed < maxSpeed) {
|
||||||
|
speed += speedIncrease;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockY = -40;
|
||||||
|
block.style.top = "-40px";
|
||||||
|
clearInterval(fall);
|
||||||
|
moveBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 16); // DIUBAH: lebih smooth (60 FPS)
|
||||||
|
}
|
||||||
|
|
||||||
|
moveBlock();
|
||||||
BIN
assets/sound/gameover.wav
Normal file
BIN
assets/sound/gameover.wav
Normal file
Binary file not shown.
BIN
assets/sound/move.wav
Normal file
BIN
assets/sound/move.wav
Normal file
Binary file not shown.
BIN
assets/sound/score.wav
Normal file
BIN
assets/sound/score.wav
Normal file
Binary file not shown.
196
assets/style.css
Normal file
196
assets/style.css
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
/* ============================
|
||||||
|
GLOBAL STYLE
|
||||||
|
============================ */
|
||||||
|
body {
|
||||||
|
font-family: 'Poppins', sans-serif;
|
||||||
|
background: linear-gradient(135deg, #1b1b1b, #2a2a2a);
|
||||||
|
color: #f5f5f5;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
AUTH BOX (Login / Register)
|
||||||
|
============================ */
|
||||||
|
.box {
|
||||||
|
background: #1f1f1f;
|
||||||
|
margin: 100px auto;
|
||||||
|
width: 350px;
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0px 0px 20px rgba(0, 150, 255, 0.2);
|
||||||
|
animation: fadeIn 0.6s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box h2 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #00aaff;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, button {
|
||||||
|
padding: 12px;
|
||||||
|
margin: 8px 0;
|
||||||
|
width: 90%;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
background: #2e2e2e;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: #007bff;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background: #005fcc;
|
||||||
|
transform: scale(1.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
GAME AREA
|
||||||
|
============================ */
|
||||||
|
#gameArea {
|
||||||
|
width: 400px;
|
||||||
|
height: 500px;
|
||||||
|
background: #111;
|
||||||
|
border-radius: 15px;
|
||||||
|
margin: 30px auto;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 2px solid #00aaff;
|
||||||
|
box-shadow: 0px 0px 25px rgba(0, 170, 255, 0.4);
|
||||||
|
animation: fadeIn 0.8s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Player */
|
||||||
|
#player {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: cyan;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 180px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Falling Block */
|
||||||
|
#block {
|
||||||
|
width: 45px;
|
||||||
|
height: 45px;
|
||||||
|
background: linear-gradient(135deg, #ff4d4d, #ff0000);
|
||||||
|
border-radius: 10px;
|
||||||
|
position: absolute;
|
||||||
|
top: -50px;
|
||||||
|
left: 180px;
|
||||||
|
box-shadow: 0 0 12px rgba(255, 50, 50, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
TOP BAR (Game Page)
|
||||||
|
============================ */
|
||||||
|
.top-bar {
|
||||||
|
margin-top: 20px;
|
||||||
|
background: #1f1f1f;
|
||||||
|
width: 100%;
|
||||||
|
padding: 15px 0;
|
||||||
|
color: #00d0ff;
|
||||||
|
font-size: 18px;
|
||||||
|
box-shadow: 0 3px 15px rgba(0, 150, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar a {
|
||||||
|
color: #ff5252;
|
||||||
|
margin-left: 15px;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar a:hover {
|
||||||
|
color: #ff7777;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================= POPUP GAME OVER ================= */
|
||||||
|
#gameOverPopup {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.85);
|
||||||
|
display: none;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-box {
|
||||||
|
background: #1e1e1e;
|
||||||
|
padding: 30px;
|
||||||
|
width: 300px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 0 15px rgba(0,0,0,0.5);
|
||||||
|
animation: popIn 0.25s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-box h2 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-box button {
|
||||||
|
width: 130px;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#btnRestart {
|
||||||
|
background: #0aa4ff;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#btnMenu {
|
||||||
|
background: #00d37e;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
#btnMenu:hover {
|
||||||
|
background: #00b86b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes popIn {
|
||||||
|
from { transform: scale(0.6); opacity: 0; }
|
||||||
|
to { transform: scale(1); opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
SCORE TEXT
|
||||||
|
============================ */
|
||||||
|
#scoreText {
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 10px;
|
||||||
|
color: #00eaff;
|
||||||
|
text-shadow: 0px 0px 10px rgba(0, 200, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
ANIMATIONS
|
||||||
|
============================ */
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; transform: translateY(20px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
12
db.php
Normal file
12
db.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
$host = "localhost";
|
||||||
|
$user = "root";
|
||||||
|
$pass = "";
|
||||||
|
$db = "dodge_game";
|
||||||
|
|
||||||
|
$conn = new mysqli($host, $user, $pass, $db);
|
||||||
|
|
||||||
|
if ($conn->connect_error) {
|
||||||
|
die("Koneksi gagal: " . $conn->connect_error);
|
||||||
|
}
|
||||||
|
?>
|
||||||
8
db.sql
Normal file
8
db.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
USE dodge_game;
|
||||||
|
|
||||||
|
CREATE TABLE users (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
username VARCHAR(50) UNIQUE,
|
||||||
|
password VARCHAR(255)
|
||||||
|
);
|
||||||
14
events.md
14
events.md
@ -1,14 +0,0 @@
|
|||||||
## EVENTS
|
|
||||||
|
|
||||||
## Mulai Pembuatan HarGame (menghindari blok merah)
|
|
||||||
Diskusi Dan Membuat Judul Game Pada Tanggal 12 November 2025
|
|
||||||
|
|
||||||
## Memulai Pembuatan Html Dan Php
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Memulai Pembuatan Css
|
|
||||||
|
|
||||||
|
|
||||||
## memulai Pembuatan javascript
|
|
||||||
|
|
||||||
295
game.php
Normal file
295
game.php
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
if (!isset($_SESSION['user'])) {
|
||||||
|
header("Location: index.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$username = $_SESSION['user'];
|
||||||
|
|
||||||
|
// koneksi db
|
||||||
|
$conn = new mysqli("localhost", "root", "", "dodge_game");
|
||||||
|
// Ambil skin user dari database
|
||||||
|
$q = $conn->query("SELECT skin FROM users WHERE username='$username'");
|
||||||
|
$skinColor = $q->fetch_assoc()["skin"];
|
||||||
|
|
||||||
|
// Daftar warna skin
|
||||||
|
$skinList = [
|
||||||
|
"cyan" => "#00ffff",
|
||||||
|
"blue" => "#0066ff",
|
||||||
|
"yellow" => "#ffee00",
|
||||||
|
"purple" => "#ff55ff",
|
||||||
|
"green" => "#33ff55"
|
||||||
|
];
|
||||||
|
|
||||||
|
// Warna player yang dipakai
|
||||||
|
$playerColor = $skinList[$skinColor];
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Hindari Block</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial;
|
||||||
|
background: url('assets/bg.jpg') no-repeat center center fixed;
|
||||||
|
background-size: cover;
|
||||||
|
color: white;
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gameWrapper {
|
||||||
|
width: 75%;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gameArea {
|
||||||
|
width: 400px;
|
||||||
|
height: 500px;
|
||||||
|
background: #222;
|
||||||
|
margin: 0 auto;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 0 10px #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#player {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: <?= $playerColor ?>;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
left: 180px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#block {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: red;
|
||||||
|
position: absolute;
|
||||||
|
top: -40px;
|
||||||
|
left: 180px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#leaderboard {
|
||||||
|
width: 25%;
|
||||||
|
padding: 20px;
|
||||||
|
background: #111;
|
||||||
|
border-left: 2px solid #333;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
padding: 8px;
|
||||||
|
border-bottom: 1px solid #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== POPUP GAME OVER ===== */
|
||||||
|
#gameOverPopup {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0,0,0,0.7);
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-box {
|
||||||
|
background: #222;
|
||||||
|
padding: 25px;
|
||||||
|
border-radius: 10px;
|
||||||
|
text-align: center;
|
||||||
|
width: 300px;
|
||||||
|
box-shadow: 0 0 10px #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-box button {
|
||||||
|
margin-top: 15px;
|
||||||
|
padding: 10px;
|
||||||
|
width: 120px;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#btnRestart {
|
||||||
|
background: #00d37e;
|
||||||
|
}
|
||||||
|
|
||||||
|
#btnLmenu {
|
||||||
|
background: #00d37e;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="gameWrapper">
|
||||||
|
<h1>Hindari Block</h1>
|
||||||
|
<p>Player: <b><?= $username ?></b></p>
|
||||||
|
<div class="score-box">Score: <span id="score">0</span></div>
|
||||||
|
|
||||||
|
<div id="gameArea">
|
||||||
|
<div id="player"></div>
|
||||||
|
<div id="block"></div>
|
||||||
|
</div>
|
||||||
|
<p>Credits: Haekal Adi Rendra & Gerrad</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="leaderboard">
|
||||||
|
<h2>Leaderboard</h2>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>User</th>
|
||||||
|
<th>Score</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$result = $conn->query("SELECT username, score FROM leaderboard ORDER BY score DESC LIMIT 20");
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
echo "<tr><td>{$row['username']}</td><td>{$row['score']}</td></tr>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ========= POPUP GAME OVER ========= -->
|
||||||
|
<div id="gameOverPopup">
|
||||||
|
<div class="popup-box">
|
||||||
|
<h2>Game Over</h2>
|
||||||
|
<p>Score Kamu: <span id="finalScore"></span></p>
|
||||||
|
|
||||||
|
<button id="btnRestart">New Game</button>
|
||||||
|
<button id="btnmenu">Menu</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<audio id="soundMove" src="assets/sound/move.wav"></audio>
|
||||||
|
<audio id="soundScore" src="assets/sound/score.wav"></audio>
|
||||||
|
<audio id="soundGameOver" src="assets/sound/gameover.wav"></audio>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let currentUser = "<?= $username ?>";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// ========= GAME SCRIPT ==========
|
||||||
|
const player = document.getElementById("player");
|
||||||
|
const block = document.getElementById("block");
|
||||||
|
let score = 0;
|
||||||
|
let gameRunning = true;
|
||||||
|
|
||||||
|
document.addEventListener("keydown", e => {
|
||||||
|
if (!gameRunning) return;
|
||||||
|
|
||||||
|
let left = parseInt(window.getComputedStyle(player).getPropertyValue("left"));
|
||||||
|
|
||||||
|
if (e.key === "ArrowLeft" && left > 0) {
|
||||||
|
player.style.left = (left - 20) + "px";
|
||||||
|
soundMove.currentTime = 0;
|
||||||
|
soundMove.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.key === "ArrowRight" && left < 360) {
|
||||||
|
player.style.left = (left + 20) + "px";
|
||||||
|
soundMove.currentTime = 0;
|
||||||
|
soundMove.play();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
let blockSpeed = 5; // kecepatan awal block
|
||||||
|
|
||||||
|
function fall() {
|
||||||
|
if (!gameRunning) return;
|
||||||
|
|
||||||
|
let blockTop = parseInt(window.getComputedStyle(block).getPropertyValue("top"));
|
||||||
|
let blockLeft = parseInt(window.getComputedStyle(block).getPropertyValue("left"));
|
||||||
|
let playerLeft = parseInt(window.getComputedStyle(player).getPropertyValue("left"));
|
||||||
|
|
||||||
|
// TABRAKAN
|
||||||
|
if (blockTop > 450 && Math.abs(blockLeft - playerLeft) < 40) {
|
||||||
|
gameRunning = false;
|
||||||
|
soundGameOver.play();
|
||||||
|
saveScore(score);
|
||||||
|
showGameOver(score);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika block sudah jatuh ke bawah
|
||||||
|
if (blockTop > 500) {
|
||||||
|
block.style.top = "-40px";
|
||||||
|
block.style.left = Math.floor(Math.random() * 360) + "px";
|
||||||
|
score++;
|
||||||
|
document.getElementById("score").innerText = score;
|
||||||
|
|
||||||
|
// ======== TINGKATKAN KECEPATAN BLOCK BERDASARKAN SCORE ========
|
||||||
|
if (score === 15) blockSpeed = 7;
|
||||||
|
if (score === 25) blockSpeed = 8;
|
||||||
|
if (score === 35) blockSpeed = 10;
|
||||||
|
if (score === 45) blockSpeed = 12;
|
||||||
|
if (score === 60) blockSpeed = 14;
|
||||||
|
if (score === 80) blockSpeed = 16;
|
||||||
|
if (score === 100) blockSpeed = 18;
|
||||||
|
|
||||||
|
soundScore.currentTime = 0;
|
||||||
|
soundScore.play();
|
||||||
|
} else {
|
||||||
|
block.style.top = (blockTop + blockSpeed) + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(fall);
|
||||||
|
}
|
||||||
|
fall();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ================== SIMPAN SKOR KE SERVER ==================
|
||||||
|
function saveScore(finalScore) {
|
||||||
|
fetch("save_score.php", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||||
|
body: "username=" + currentUser + "&score=" + finalScore
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ================== POPUP GAME OVER ==================
|
||||||
|
const popup = document.getElementById("gameOverPopup");
|
||||||
|
const finalScoreText = document.getElementById("finalScore");
|
||||||
|
const btnRestart = document.getElementById("btnRestart");
|
||||||
|
const btnmenu = document.getElementById("btnmenu");
|
||||||
|
|
||||||
|
function showGameOver(finalScore) {
|
||||||
|
finalScoreText.textContent = finalScore;
|
||||||
|
popup.style.display = "flex";
|
||||||
|
}
|
||||||
|
|
||||||
|
btnRestart.onclick = () => {
|
||||||
|
window.location.reload();
|
||||||
|
};
|
||||||
|
|
||||||
|
btnmenu.onclick = () => {
|
||||||
|
window.location.href = "menu.php";
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
45
index.php
Normal file
45
index.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require 'db.php';
|
||||||
|
|
||||||
|
$message = "";
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||||
|
$username = $_POST['username'];
|
||||||
|
$password = $_POST['password'];
|
||||||
|
|
||||||
|
$query = $conn->query("SELECT * FROM users WHERE username='$username'");
|
||||||
|
|
||||||
|
if ($query->num_rows > 0) {
|
||||||
|
$row = $query->fetch_assoc();
|
||||||
|
if (password_verify($password, $row['password'])) {
|
||||||
|
$_SESSION['user'] = $row['username'];
|
||||||
|
header("Location: menu.php"); // ⬅ KE MENU BUKAN GAME
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$message = "Password salah!";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$message = "Username tidak ditemukan!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Login</title>
|
||||||
|
<link rel="stylesheet" href="assets/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="box">
|
||||||
|
<h2>Login</h2>
|
||||||
|
<form method="POST">
|
||||||
|
<input type="text" name="username" placeholder="Username" required><br>
|
||||||
|
<input type="password" name="password" placeholder="Password" required><br>
|
||||||
|
<button type="submit">Masuk</button>
|
||||||
|
</form>
|
||||||
|
<p><?= $message ?></p>
|
||||||
|
<a href="register.php">Register</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4
logout.php
Normal file
4
logout.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
session_destroy();
|
||||||
|
header("Location: index.php");
|
||||||
97
menu.php
Normal file
97
menu.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
if (!isset($_SESSION['user'])) {
|
||||||
|
header("Location: index.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Menu Utama</title>
|
||||||
|
<link rel="stylesheet" href="assets/style.css">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Popup background */
|
||||||
|
#settingsPopup {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0,0,0,0.7);
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Popup box */
|
||||||
|
.popup-box {
|
||||||
|
background: #1e1e1e;
|
||||||
|
width: 350px;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 12px;
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 0 20px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-option {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
margin-top: 8px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="box" style="width: 350px;">
|
||||||
|
<h2>Menu Utama</h2>
|
||||||
|
<p>Halo, <b><?= $_SESSION['user'] ?></b></p>
|
||||||
|
|
||||||
|
<a href="game.php">
|
||||||
|
<button style="width: 100%;">Mulai Game</button>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Tombol Settings membuka popup -->
|
||||||
|
<button onclick="openSettings()" style="width: 100%; background:#00d37e;">Pengaturan</button>
|
||||||
|
|
||||||
|
<a href="logout.php">
|
||||||
|
<button style="width: 100%; background: #ff4d4d;">Keluar</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ================= SETTINGS POPUP ================== -->
|
||||||
|
<div id="settingsPopup">
|
||||||
|
<div class="popup-box">
|
||||||
|
<h2>Pengaturan</h2>
|
||||||
|
|
||||||
|
<a href="skins.php">
|
||||||
|
<button class="popup-option" style="background:#ffaa00;">Pilih Skin</button>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<button class="popup-option" onclick="closeSettings()" style="background:#555;">Kembali</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function openSettings() {
|
||||||
|
document.getElementById("settingsPopup").style.display = "flex";
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeSettings() {
|
||||||
|
document.getElementById("settingsPopup").style.display = "none";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -1,7 +0,0 @@
|
|||||||
Kelompok 1
|
|
||||||
|
|
||||||
Nama Anggota:
|
|
||||||
|
|
||||||
Haekal - ( Mengcoding css )
|
|
||||||
Adi - (mengcoding javascript )
|
|
||||||
Rendra & Gerrad - ( mengcoding html dan php )
|
|
||||||
43
register.php
Normal file
43
register.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
require 'db.php';
|
||||||
|
|
||||||
|
$message = "";
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||||
|
$username = $_POST['username'];
|
||||||
|
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
|
||||||
|
|
||||||
|
$check = $conn->query("SELECT * FROM users WHERE username='$username'");
|
||||||
|
if ($check->num_rows > 0) {
|
||||||
|
$message = "Username sudah digunakan!";
|
||||||
|
} else {
|
||||||
|
$sql = "INSERT INTO users(username, password) VALUES('$username', '$password')";
|
||||||
|
if ($conn->query($sql)) {
|
||||||
|
header("Location: index.php");
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$message = "Gagal registrasi!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Register</title>
|
||||||
|
<link rel="stylesheet" href="assets/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="box">
|
||||||
|
<h2>Register</h2>
|
||||||
|
<form method="POST">
|
||||||
|
<input type="text" name="username" placeholder="Username" required><br>
|
||||||
|
<input type="password" name="password" placeholder="Password" required><br>
|
||||||
|
<button type="submit">Daftar</button>
|
||||||
|
</form>
|
||||||
|
<p><?= $message ?></p>
|
||||||
|
<a href="index.php">Login</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
24
save_score.php
Normal file
24
save_score.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
$conn = new mysqli("localhost", "root", "", "dodge_game");
|
||||||
|
|
||||||
|
if ($conn->connect_error) {
|
||||||
|
die("DB Error: " . $conn->connect_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
$username = $_POST['username'];
|
||||||
|
$score = intval($_POST['score']);
|
||||||
|
|
||||||
|
// cek jika user sudah punya skor sebelumnya
|
||||||
|
$check = $conn->query("SELECT * FROM leaderboard WHERE username='$username'");
|
||||||
|
|
||||||
|
if ($check->num_rows > 0) {
|
||||||
|
// update jika score baru lebih tinggi
|
||||||
|
$conn->query("UPDATE leaderboard SET score=GREATEST(score, $score) WHERE username='$username'");
|
||||||
|
} else {
|
||||||
|
// insert jika belum ada
|
||||||
|
$conn->query("INSERT INTO leaderboard (username, score) VALUES ('$username', $score)");
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "OK";
|
||||||
|
?>
|
||||||
0
settings.php
Normal file
0
settings.php
Normal file
134
skins.php
Normal file
134
skins.php
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
if (!isset($_SESSION['user'])) {
|
||||||
|
header("Location: index.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$conn = new mysqli("localhost", "root", "", "dodge_game");
|
||||||
|
$user = $_SESSION['user'];
|
||||||
|
|
||||||
|
// AMBIL SKIN USER SEKARANG
|
||||||
|
$qSkin = $conn->query("SELECT skin FROM users WHERE username='$user'");
|
||||||
|
$currentSkin = $qSkin->fetch_assoc()['skin'];
|
||||||
|
|
||||||
|
// LIST SKIN
|
||||||
|
$skins = [
|
||||||
|
"cyan" => "#00ffff",
|
||||||
|
"blue" => "#0066ff",
|
||||||
|
"yellow" => "#ffee00",
|
||||||
|
"purple" => "#ff55ff",
|
||||||
|
"green" => "#33ff55"
|
||||||
|
];
|
||||||
|
|
||||||
|
// AMBIL SKIN USER
|
||||||
|
$qSkin = $conn->query("SELECT skin FROM users WHERE username='$user'");
|
||||||
|
$data = $qSkin->fetch_assoc();
|
||||||
|
|
||||||
|
// PROSES SIMPAN SKIN
|
||||||
|
if (isset($_POST['chooseSkin'])) {
|
||||||
|
$selectedSkin = $_POST['skin'];
|
||||||
|
$conn->query("UPDATE users SET skin='$selectedSkin' WHERE username='$user'");
|
||||||
|
$currentSkin = $selectedSkin;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Pilih Skin</title>
|
||||||
|
<link rel="stylesheet" href="assets/style.css">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 40px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-box {
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.2s;
|
||||||
|
border: 4px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-box:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-selected {
|
||||||
|
border: 4px solid #fff;
|
||||||
|
box-shadow: 0 0 15px white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden-radio {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h2>Pilih Skin Pemain</h2>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
|
||||||
|
<div class="skin-container">
|
||||||
|
|
||||||
|
<?php foreach ($skins as $name => $color): ?>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="skin"
|
||||||
|
class="hidden-radio"
|
||||||
|
value="<?= $name ?>"
|
||||||
|
<?= $currentSkin == $name ? "checked" : "" ?>
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="skin-box <?= $currentSkin == $name ? "skin-selected" : "" ?>"
|
||||||
|
style="background: <?= $color ?>"
|
||||||
|
></div>
|
||||||
|
</label>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
<button type="submit" name="chooseSkin" style="width:250px;">Simpan Skin</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<a href="menu.php">
|
||||||
|
<button style="width:250px; background:#555; margin-top:20px;">Kembali</button>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// AUTO HIGHLIGHT SKIN KETIKA DIPILIH
|
||||||
|
const radios = document.querySelectorAll("input[name='skin']");
|
||||||
|
const boxes = document.querySelectorAll(".skin-box");
|
||||||
|
|
||||||
|
boxes.forEach((box, index) => {
|
||||||
|
box.addEventListener("click", () => {
|
||||||
|
// pilih radio
|
||||||
|
radios[index].checked = true;
|
||||||
|
|
||||||
|
// remove highlight
|
||||||
|
boxes.forEach(b => b.classList.remove("skin-selected"));
|
||||||
|
|
||||||
|
// add highlight ke yang dipilih
|
||||||
|
box.classList.add("skin-selected");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user