Mobile Mario Game
by PrismCobra26285 lines8.1 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Mobile Mario Game</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; touch-action: manipulation; }
body {
background: #87CEEB;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
overflow: hidden;
font-family: Arial;
}
canvas {
display: block;
width: 100vw;
height: 60vh;
background: linear-gradient(#87CEEB, #E0F7FF);
}
.controls {
display: flex;
justify-content: space-between;
align-items: center;
width: 100vw;
height: 40vh;
padding: 10px 20px;
background: #333;
}
.btn {
width: 80px;
height: 80px;
border-radius: 50%;
border: none;
font-size: 30px;
font-weight: bold;
color: white;
display: flex;
justify-content: center;
align-items: center;
user-select: none;
-webkit-user-select: none;
touch-action: none;
box-shadow: 0 4px 0 rgba(0,0,0,0.3);
}
.btn:active { transform: translateY(4px); box-shadow: none; }
.left { background: #E74C3C; }
.right { background: #E74C3C; }
.jump { background: #27AE60; width: 100px; height: 100px; font-size: 20px; }
.btn-group { display: flex; gap: 15px; }
</style>
</head>
<body>
<canvas id="game"></canvas>
<div class="controls">
<div class="btn-group">
<button class="btn left" id="leftBtn">◀</button>
<button class="btn right" id="rightBtn">▶</button>
</div>
<button class="btn jump" id="jumpBtn">JUMP</button>
</div>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight * 0.6;
}
resize();
window.addEventListener('resize', resize);
const keys = { left: false, right: false, up: false };
document.getElementById('leftBtn').addEventListener('touchstart', e => { e.preventDefault(); keys.left = true; });
document.getElementById('leftBtn').addEventListener('touchend', e => { e.preventDefault(); keys.left = false; });
document.getElementById('rightBtn').addEventListener('touchstart', e => { e.preventDefault(); keys.right = true; });
document.getElementById('rightBtn').addEventListener('touchend', e => { e.preventDefault(); keys.right = false; });
document.getElementById('jumpBtn').addEventListener('touchstart', e => { e.preventDefault(); keys.up = true; });
document.getElementById('jumpBtn').addEventListener('touchend', e => { e.preventDefault(); keys.up = false; });
// Also support mouse for testing
document.getElementById('leftBtn').addEventListener('mousedown', () => keys.left = true);
document.getElementById('leftBtn').addEventListener('mouseup', () => keys.left = false);
document.getElementById('rightBtn').addEventListener('mousedown', () => keys.right = true);
document.getElementById('rightBtn').addEventListener('mouseup', () => keys.right = false);
document.getElementById('jumpBtn').addEventListener('mousedown', () => keys.up = true);
document.getElementById('jumpBtn').addEventListener('mouseup', () => keys.up = false);
const player = {
x: 50, y: 300, w: 30, h: 40,
vx: 0, vy: 0,
speed: 4, jumpPower: -12,
onGround: false
};
const gravity = 0.6;
const platforms = [
{x: 0, y: 420, w: 900, h: 40},
{x: 150, y: 340, w: 100, h: 20},
{x: 300, y: 280, w: 120, h: 20},
{x: 500, y: 220, w: 100, h: 20},
{x: 680, y: 160, w: 120, h: 20},
{x: 400, y: 360, w: 80, h: 20}
];
const coins = [
{x: 180, y: 300, r: 8, collected: false},
{x: 340, y: 240, r: 8, collected: false},
{x: 540, y: 180, r: 8, collected: false},
{x: 720, y: 120, r: 8, collected: false}
];
const enemies = [
{x: 600, y: 390, w: 30, h: 30, vx: -1.5, minX: 550, maxX: 750, alive: true},
{x: 250, y: 310, w: 30, h: 30, vx: 1.2, minX: 150, maxX: 280, alive: true}
];
let score = 0;
let gameOver = false;
let win = false;
function rectCollide(a, b) {
return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
}
function update() {
if (gameOver || win) return;
if (keys.left) player.vx = -player.speed;
else if (keys.right) player.vx = player.speed;
else { player.vx *= 0.8; if (Math.abs(player.vx) < 0.1) player.vx = 0; }
if (keys.up && player.onGround) {
player.vy = player.jumpPower;
player.onGround = false;
}
player.vy += gravity;
player.x += player.vx;
for (let p of platforms) {
if (rectCollide(player, p)) {
if (player.vx > 0) player.x = p.x - player.w;
else if (player.vx < 0) player.x = p.x + p.w;
player.vx = 0;
}
}
player.y += player.vy;
player.onGround = false;
for (let p of platforms) {
if (rectCollide(player, p)) {
if (player.vy > 0) {
player.y = p.y - player.h;
player.vy = 0;
player.onGround = true;
} else if (player.vy < 0) {
player.y = p.y + p.h;
player.vy = 0;
}
}
}
if (player.x < 0) player.x = 0;
if (player.x + player.w > canvas.width) player.x = canvas.width - player.w;
if (player.y > canvas.height) gameOver = true;
for (let c of coins) {
if (!c.collected) {
const coinRect = {x: c.x - c.r, y: c.y - c.r, w: c.r * 2, h: c.r * 2};
if (rectCollide(player, coinRect)) { c.collected = true; score += 10; }
}
}
for (let e of enemies) {
if (!e.alive) continue;
e.x += e.vx;
if (e.x < e.minX || e.x + e.w > e.maxX) e.vx *= -1;
if (rectCollide(player, e)) {
if (player.vy > 0 && player.y + player.h - player.vy <= e.y + 10) {
e.alive = false;
player.vy = -8;
score += 50;
} else gameOver = true;
}
}
if (player.x + player.w > canvas.width - 40) win = true;
}
function draw() {
ctx.fillStyle = '#87CEEB';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(canvas.width * 0.2, 60, 25, 0, Math.PI * 2);
ctx.arc(canvas.width * 0.25, 50, 35, 0, Math.PI * 2);
ctx.arc(canvas.width * 0.3, 60, 25, 0, Math.PI * 2);
ctx.fill();
for (let p of platforms) {
ctx.fillStyle = '#8B4513';
ctx.fillRect(p.x, p.y, p.w, p.h);
ctx.fillStyle = '#228B22';
ctx.fillRect(p.x, p.y, p.w, 5);
}
for (let c of coins) {
if (!c.collected) {
ctx.beginPath();
ctx.arc(c.x, c.y, c.r, 0, Math.PI * 2);
ctx.fillStyle = '#FFD700';
ctx.fill();
ctx.strokeStyle = '#B8860B';
ctx.lineWidth = 2;
ctx.stroke();
}
}
for (let e of enemies) {
if (e.alive) {
ctx.fillStyle = '#8B0000';
ctx.fillRect(e.x, e.y, e.w, e.h);
ctx.fillStyle = 'white';
ctx.fillRect(e.x + 5, e.y + 8, 6, 6);
ctx.fillRect(e.x + 19, e.y + 8, 6, 6);
ctx.fillStyle = 'black';
ctx.fillRect(e.x + 7, e.y + 10, 3, 3);
ctx.fillRect(e.x + 21, e.y + 10, 3, 3);
}
}
ctx.fillStyle = '#E52521';
ctx.fillRect(player.x, player.y, player.w, player.h);
ctx.fillStyle = '#1E90FF';
ctx.fillRect(player.x + 4, player.y + 20, player.w - 8, player.h - 20);
ctx.fillStyle = '#FFDAB9';
ctx.fillRect(player.x + 5, player.y + 5, 20, 12);
ctx.fillStyle = 'black';
ctx.fillRect(player.x + 10, player.y + 8, 3, 4);
ctx.fillRect(player.x + 18, player.y + 8, 3, 4);
ctx.fillStyle = 'black';
ctx.font = '20px Arial';
ctx.fillText('Score: ' + score, 20, 30);
if (gameOver) {
ctx.fillStyle = 'rgba(0,0,0,0.6)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.font = '40px Arial';
ctx.fillText('Game Over!', canvas.width/2 - 110, canvas.height/2);
ctx.font = '24px Arial';
ctx.fillText('Score: ' + score, canvas.width/2 - 60, canvas.height/2 + 50);
}
if (win) {
ctx.fillStyle = 'rgba(0,0,0,0.6)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.font = '40px Arial';
ctx.fillText('You Win!', canvas.width/2 - 90, canvas.height/2);
ctx.font = '24px Arial';
ctx.fillText('Score: ' + score, canvas.width/2 - 60, canvas.height/2 + 50);
}
}
function gameLoop() {
update();
draw();
requestAnimationFrame(gameLoop);
}
gameLoop();
</script>
</body>
</html>Game Source: Mobile Mario Game
Creator: PrismCobra26
Libraries: none
Complexity: complex (285 lines, 8.1 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: mobile-mario-game-prismcobra26" to link back to the original. Then publish at arcadelab.ai/publish.