Meta Description" name="description" />
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Mini Mario HP</title>
<style>
* {
box-sizing: border-box;
touch-action: manipulation;
}
body {
margin: 0;
padding: 10px;
background-color: #222;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
font-family: sans-serif;
color: white;
}
canvas {
border: 3px solid #fff;
background-color: #5c94fc;
width: 100%;
max-width: 400px;
height: auto;
border-radius: 8px;
}
/* Tombol Kontrol Layar Sentuh HP */
.controls {
display: flex;
justify-content: space-between;
width: 100%;
max-width: 400px;
margin-top: 15px;
}
.d-pad {
display: flex;
gap: 10px;
}
.btn {
width: 60px;
height: 60px;
background-color: #444;
border: 2px solid #fff;
border-radius: 50%;
color: white;
font-size: 22px;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
user-select: none;
-webkit-user-select: none;
}
.btn:active {
background-color: #888;
transform: scale(0.95);
}
.btn-jump {
background-color: #e74c3c;
width: 70px;
height: 70px;
border-radius: 50%;
}
</style>
</head>
<body>
<h2>Mini Mario 2D</h2>
<canvas id="gameCanvas" width="400" height="300"></canvas>
<!-- Tombol Sentuh HP -->
<div class="controls">
<div class="d-pad">
<div class="btn" id="btnLeft">◀</div>
<div class="btn" id="btnRight">▶</div>
</div>
<div class="btn btn-jump" id="btnJump">⬆</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const player = {
x: 30,
y: 150,
width: 20,
height: 30,
color: '#ff2222',
velocityX: 0,
velocityY: 0,
speed: 3.5,
jumpForce: -9,
grounded: false
};
const gravity = 0.5;
let score = 0;
const platforms = [
{ x: 0, y: 270, width: 400, height: 30, color: '#c84c0c' },
{ x: 80, y: 200, width: 80, height: 15, color: '#fc9838' },
{ x: 200, y: 150, width: 80, height: 15, color: '#fc9838' },
{ x: 300, y: 100, width: 70, height: 15, color: '#fc9838' }
];
const coins = [
{ x: 120, y: 170, radius: 6, collected: false },
{ x: 240, y: 120, radius: 6, collected: false },
{ x: 335, y: 70, radius: 6, collected: false }
];
const keys = { right: false, left: false };
// Event Listener Tombol HP
const btnLeft = document.getElementById('btnLeft');
const btnRight = document.getElementById('btnRight');
const btnJump = document.getElementById('btnJump');
// Sentuh Kiri
btnLeft.addEventListener('touchstart', (e) => { e.preventDefault(); keys.left = true; });
btnLeft.addEventListener('touchend', (e) => { e.preventDefault(); keys.left = false; });
btnLeft.addEventListener('mousedown', () => keys.left = true);
btnLeft.addEventListener('mouseup', () => keys.left = false);
// Sentuh Kanan
btnRight.addEventListener('touchstart', (e) => { e.preventDefault(); keys.right = true; });
btnRight.addEventListener('touchend', (e) => { e.preventDefault(); keys.right = false; });
btnRight.addEventListener('mousedown', () => keys.right = true);
btnRight.addEventListener('mouseup', () => keys.right = false);
// Sentuh Lompat
const doJump = () => {
if (player.grounded) {
player.velocityY = player.jumpForce;
player.grounded = false;
}
};
btnJump.addEventListener('touchstart', (e) => { e.preventDefault(); doJump(); });
btnJump.addEventListener('mousedown', doJump);
function update() {
if (keys.right) player.velocityX = player.speed;
else if (keys.left) player.velocityX = -player.speed;
else player.velocityX = 0;
player.velocityY += gravity;
player.x += player.velocityX;
player.y += player.velocityY;
if (player.x < 0) player.x = 0;
if (player.x + player.width > canvas.width) player.x = canvas.width - player.width;
player.grounded = false;
platforms.forEach(plat => {
if (
player.x < plat.x + plat.width &&
player.x + player.width > plat.x &&
player.y + player.height >= plat.y &&
player.y + player.height <= plat.y + plat.height &&
player.velocityY >= 0
) {
player.grounded = true;
player.velocityY = 0;
player.y = plat.y - player.height;
}
});
coins.forEach(coin => {
if (!coin.collected) {
let distX = (player.x + player.width / 2) - coin.x;
let distY = (player.y + player.height / 2) - coin.y;
let distance = Math.sqrt(distX * distX + distY * distY);
if (distance < coin.radius + player.width / 2) {
coin.collected = true;
score += 10;
}
}
});
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
platforms.forEach(plat => {
ctx.fillStyle = plat.color;
ctx.fillRect(plat.x, plat.y, plat.width, plat.height);
});
coins.forEach(coin => {
if (!coin.collected) {
ctx.beginPath();
ctx.arc(coin.x, coin.y, coin.radius, 0, Math.PI * 2);
ctx.fillStyle = '#f8d800';
ctx.fill();
ctx.closePath();
}
});
// Mario
ctx.fillStyle = player.color;
ctx.fillRect(player.x, player.y, player.width, player.height);
// Topi
ctx.fillStyle = '#990000';
ctx.fillRect(player.x, player.y, player.width + 2, 5);
// Skor
ctx.fillStyle = '#fff';
ctx.font = '14px sans-serif';
ctx.fillText(`Skor: ${score}`, 15, 25);
}
function gameLoop() {
update();
draw();
requestAnimationFrame(gameLoop);
}
gameLoop();
</script>
</body>
</html>
1
1
7KB
7KB
95.0ms
120.0ms
95.0ms