Mario Landscape Game
by PrismCobra26469 lines11.9 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<meta name="screen-orientation" content="landscape">
<meta name="x5-orientation" content="landscape">
<title>Mario Landscape Game</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
touch-action: none;
-webkit-user-select: none;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
background: #000;
font-family: Arial, sans-serif;
}
#gameContainer {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #87CEEB;
}
canvas {
display: block;
background: linear-gradient(#87CEEB, #E0F7FF);
image-rendering: pixelated;
}
/* Portrait warning */
#rotateMsg {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: #222;
color: white;
justify-content: center;
align-items: center;
flex-direction: column;
z-index: 9999;
text-align: center;
padding: 20px;
}
#rotateMsg .icon {
font-size: 80px;
margin-bottom: 20px;
animation: rotate 2s infinite;
}
@keyframes rotate {
0%, 100% { transform: rotate(0deg); }
50% { transform: rotate(90deg); }
}
#rotateMsg h2 {
font-size: 24px;
margin-bottom: 10px;
}
#rotateMsg p {
font-size: 16px;
opacity: 0.8;
direction: rtl;
}
@media (orientation: portrait) {
#rotateMsg { display: flex; }
#gameContainer { display: none; }
}
/* Touch buttons */
.btn {
position: fixed;
bottom: 15px;
width: 70px;
height: 70px;
border-radius: 50%;
border: 3px solid rgba(255,255,255,0.5);
font-size: 26px;
font-weight: bold;
color: white;
display: flex;
justify-content: center;
align-items: center;
z-index: 100;
background: rgba(0,0,0,0.35);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
box-shadow: 0 4px 10px rgba(0,0,0,0.4);
transition: transform 0.05s;
}
.btn:active, .btn.pressed {
transform: scale(0.9);
background: rgba(255,255,255,0.4);
}
#leftBtn { left: 15px; }
#rightBtn { left: 100px; }
#jumpBtn {
right: 20px;
width: 85px;
height: 85px;
bottom: 20px;
font-size: 16px;
background: rgba(39,174,96,0.6);
}
</style>
</head>
<body>
<!-- Portrait Warning -->
<div id="rotateMsg">
<div class="icon">📱</div>
<h2>فون کو گھمائیں</h2>
<p>گیم کھیلنے کے لیے فون کو سیدھا (افقی) کریں</p>
</div>
<!-- Game -->
<div id="gameContainer">
<canvas id="game"></canvas>
</div>
<!-- Touch Controls -->
<button class="btn" id="leftBtn">◀</button>
<button class="btn" id="rightBtn">▶</button>
<button class="btn" id="jumpBtn">JUMP</button>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
// فکسڈ گیم کی چوڑائی/اونچائی
const CW = 800;
const CH = 400;
canvas.width = CW;
canvas.height = CH;
// Canvas کو سکرین پر فٹ کریں (لینڈ اسکیپ میں)
function resizeCanvas() {
const winW = window.innerWidth;
const winH = window.innerHeight;
const scale = Math.min(winW / CW, winH / CH);
canvas.style.width = (CW * scale) + 'px';
canvas.style.height = (CH * scale) + 'px';
}
window.addEventListener('resize', resizeCanvas);
window.addEventListener('orientationchange', () => {
setTimeout(resizeCanvas, 300);
});
resizeCanvas();
// کی پریس حالت
const keys = { left: false, right: false, up: false };
// Touch buttons - بہتر handling
function bindButton(id, key) {
const el = document.getElementById(id);
const press = (e) => { e.preventDefault(); keys[key] = true; el.classList.add('pressed'); };
const release = (e) => { e.preventDefault(); keys[key] = false; el.classList.remove('pressed'); };
el.addEventListener('touchstart', press, { passive: false });
el.addEventListener('touchend', release, { passive: false });
el.addEventListener('touchcancel', release, { passive: false });
el.addEventListener('mousedown', press);
el.addEventListener('mouseup', release);
el.addEventListener('mouseleave', release);
}
bindButton('leftBtn', 'left');
bindButton('rightBtn', 'right');
bindButton('jumpBtn', 'up');
// کیبورڈ سپورٹ (PC پر ٹیسٹ کے لیے)
document.addEventListener('keydown', e => {
if (e.key === 'ArrowLeft' || e.key === 'a' || e.key === 'A') keys.left = true;
if (e.key === 'ArrowRight' || e.key === 'd' || e.key === 'D') keys.right = true;
if (e.key === 'ArrowUp' || e.key === 'w' || e.key === 'W' || e.key === ' ') {
keys.up = true;
e.preventDefault();
}
});
document.addEventListener('keyup', e => {
if (e.key === 'ArrowLeft' || e.key === 'a' || e.key === 'A') keys.left = false;
if (e.key === 'ArrowRight' || e.key === 'd' || e.key === 'D') keys.right = false;
if (e.key === 'ArrowUp' || e.key === 'w' || e.key === 'W' || e.key === ' ') keys.up = false;
});
// پلیئر
const player = {
x: 50, y: 280, w: 28, h: 36,
vx: 0, vy: 0,
speed: 4, jumpPower: -11.5,
onGround: false,
facing: 1
};
const gravity = 0.6;
// پلیٹ فارم
const platforms = [
{x: 0, y: 380, w: 800, h: 20},
{x: 130, y: 310, w: 90, h: 15},
{x: 270, y: 260, w: 100, h: 15},
{x: 430, y: 210, w: 90, h: 15},
{x: 590, y: 260, w: 100, h: 15},
{x: 350, y: 330, w: 70, h: 15}
];
// سکے
const coins = [
{x: 160, y: 275, r: 7, collected: false},
{x: 310, y: 225, r: 7, collected: false},
{x: 470, y: 175, r: 7, collected: false},
{x: 630, y: 225, r: 7, collected: false},
{x: 380, y: 295, r: 7, collected: false}
];
// دشمن
const enemies = [
{x: 550, y: 350, w: 28, h: 28, vx: -1.4, minX: 480, maxX: 720, alive: true},
{x: 200, y: 350, w: 28, h: 28, vx: 1.2, minX: 120, maxX: 320, 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 resetGame() {
player.x = 50; player.y = 280;
player.vx = 0; player.vy = 0;
player.onGround = false;
score = 0;
gameOver = false;
win = false;
coins.forEach(c => c.collected = false);
enemies[0].alive = true; enemies[0].x = 550; enemies[0].vx = -1.4;
enemies[1].alive = true; enemies[1].x = 200; enemies[1].vx = 1.2;
}
function update() {
if (gameOver || win) {
// Tap to restart
if (keys.up || keys.left || keys.right) {
if (gameOver || win) {
setTimeout(() => {
if (gameOver || win) resetGame();
}, 100);
}
}
return;
}
// Horizontal movement
if (keys.left) { player.vx = -player.speed; player.facing = -1; }
else if (keys.right) { player.vx = player.speed; player.facing = 1; }
else { player.vx *= 0.75; if (Math.abs(player.vx) < 0.1) player.vx = 0; }
// Jump
if (keys.up && player.onGround) {
player.vy = player.jumpPower;
player.onGround = false;
}
player.vy += gravity;
if (player.vy > 15) player.vy = 15;
// Horizontal collision
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;
}
}
// Vertical collision
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;
}
}
}
// Boundaries
if (player.x < 0) player.x = 0;
if (player.x + player.w > CW) player.x = CW - player.w;
if (player.y > CH + 100) gameOver = true;
// Coins
for (let c of coins) {
if (!c.collected) {
const cr = {x: c.x - c.r, y: c.y - c.r, w: c.r * 2, h: c.r * 2};
if (rectCollide(player, cr)) { c.collected = true; score += 10; }
}
}
// Enemies
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 + 12) {
e.alive = false;
player.vy = -8;
score += 50;
} else {
gameOver = true;
}
}
}
// Win
if (player.x + player.w > CW - 40) win = true;
}
function draw() {
// Sky
const skyGrad = ctx.createLinearGradient(0, 0, 0, CH);
skyGrad.addColorStop(0, '#87CEEB');
skyGrad.addColorStop(1, '#E0F7FF');
ctx.fillStyle = skyGrad;
ctx.fillRect(0, 0, CW, CH);
// Clouds
ctx.fillStyle = 'white';
ctx.beginPath();
ctx.arc(120, 60, 22, 0, Math.PI * 2);
ctx.arc(150, 50, 30, 0, Math.PI * 2);
ctx.arc(180, 60, 22, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.arc(600, 90, 18, 0, Math.PI * 2);
ctx.arc(630, 80, 26, 0, Math.PI * 2);
ctx.arc(660, 90, 18, 0, Math.PI * 2);
ctx.fill();
// Platforms
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);
}
// Coins
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();
}
}
// Enemies
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 + 7, 6, 6);
ctx.fillRect(e.x + 17, e.y + 7, 6, 6);
ctx.fillStyle = 'black';
ctx.fillRect(e.x + 7, e.y + 9, 3, 3);
ctx.fillRect(e.x + 19, e.y + 9, 3, 3);
}
}
// Flag (win point)
ctx.fillStyle = '#654321';
ctx.fillRect(CW - 35, 130, 5, 250);
ctx.fillStyle = '#00AA00';
ctx.beginPath();
ctx.moveTo(CW - 30, 130);
ctx.lineTo(CW - 5, 145);
ctx.lineTo(CW - 30, 160);
ctx.fill();
// Player
ctx.fillStyle = '#E52521';
ctx.fillRect(player.x, player.y, player.w, player.h);
ctx.fillStyle = '#1E90FF';
ctx.fillRect(player.x + 3, player.y + 18, player.w - 6, player.h - 18);
ctx.fillStyle = '#FFDAB9';
ctx.fillRect(player.x + 4, player.y + 4, 20, 11);
ctx.fillStyle = 'black';
ctx.fillRect(player.x + 8, player.y + 7, 3, 4);
ctx.fillRect(player.x + 16, player.y + 7, 3, 4);
// Score
ctx.fillStyle = 'rgba(0,0,0,0.7)';
ctx.fillRect(8, 8, 130, 32);
ctx.fillStyle = 'white';
ctx.font = 'bold 18px Arial';
ctx.fillText('Score: ' + score, 18, 30);
// Game Over
if (gameOver) {
ctx.fillStyle = 'rgba(0,0,0,0.75)';
ctx.fillRect(0, 0, CW, CH);
ctx.fillStyle = 'white';
ctx.font = 'bold 48px Arial';
ctx.textAlign = 'center';
ctx.fillText('Game Over!', CW/2, CH/2 - 20);
ctx.fillStyle = '#FFD700';
ctx.font = 'bold 26px Arial';
ctx.fillText('Score: ' + score, CW/2, CH/2 + 25);
ctx.fillStyle = 'white';
ctx.font = '16px Arial';
ctx.fillText('Tap JUMP to restart', CW/2, CH/2 + 65);
ctx.textAlign = 'left';
}
// Win
if (win) {
ctx.fillStyle = 'rgba(0,0,0,0.75)';
ctx.fillRect(0, 0, CW, CH);
ctx.fillStyle = '#FFD700';
ctx.font = 'bold 48px Arial';
ctx.textAlign = 'center';
ctx.fillText('🏆 You Win! 🏆', CW/2, CH/2 - 20);
ctx.fillStyle = 'white';
ctx.font = 'bold 26px Arial';
ctx.fillText('Score: ' + score, CW/2, CH/2 + 25);
ctx.font = '16px Arial';
ctx.fillText('Tap JUMP to play again', CW/2, CH/2 + 65);
ctx.textAlign = 'left';
}
}
function gameLoop() {
update();
draw();
requestAnimationFrame(gameLoop);
}
gameLoop();
</script>
</body>
</html>Game Source: Mario Landscape Game
Creator: PrismCobra26
Libraries: none
Complexity: complex (469 lines, 11.9 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: mario-landscape-game-prismcobra26" to link back to the original. Then publish at arcadelab.ai/publish.