Earning Website Demo with Withdraw
💰 Earning Website Demo with Withdraw
Login
<div class="register-box">
<h2>Register</h2>
<form action="register.php" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Register</button>
</form>
</div>d<h2>Register</h2>
<div class="register-box">
<h2>Register</h2>
<form action="register.php" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Register</button>
</form>
</div>d<h2>Register</h2> <form action="register.php" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Register</button>
</form>
</div>
<form action="register.php" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Register</button>
</form>
</div>
<h2>Register</h2>
<form action="register.php" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Register</button>
</form>
</div>
<h2>Register</h2>
<form action="register.php" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Register</button>
</form>
</div>
<h2>Register</h2>
<form action="register.php" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Register</button>
</form>
</div><!DOCTYPE html>
<html>
<head>
<title>Red or Blue Background</title>
<style>
body {
background-color: red; /* change to blue */
height: 100vh;
margin: 0;
}
</style>
</head>
<body>
</body>
</html><!DOCTYPE html>
<html>
<head>
<title>Background Toggle</title>
<style>
body {
margin: 0;
height: 100vh;
background-color: red;
display: flex;
justify-content: center;
align-items: center;
}
button {
padding: 10px 20px;
font-size: 18px;
}
</style>
</head>
<body>
<button onclick="toggleColor()">Toggle Background</button>
<script>
function toggleColor() {
document.body.style.backgroundColor =
document.body.style.backgroundColor === 'red' ? 'blue' : 'red';
}
</script>
</body>
<h2>Register</h2>
<form action="register.php" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="email" name="email" placeholder="Email" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Register</button>
</form>
</div><!DOCTYPE html>
<html>
<head>
<title>Red or Blue Background</title>
<style>
body {
background-color: red; /* change to blue */
height: 100vh;
margin: 0;
}
</style>
</head>
<body>
</body>
</html><!DOCTYPE html>
<html>
<head>
<title>Background Toggle</title>
<style>
body {
margin: 0;
height: 100vh;
background-color: red;
display: flex;
justify-content: center;
align-items: center;
}
button {
padding: 10px 20px;
font-size: 18px;
}
</style>
</head>
<body>
<button onclick="toggleColor()">Toggle Background</button>
<script>
function toggleColor() {
document.body.style.backgroundColor =
document.body.style.backgroundColor === 'red' ? 'blue' : 'red';
}
</script>
</body>Avatar CustomizerSkin
Score: 0High: 0Change avatar colors then press Start. The avatar is drawn from shapes — easy to replace with image sprites later.
</html><!-- Save as index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Avatar Dodge — Upgraded</title>
<style>
:root{--bg:#061124;--panel:#071226;--muted:#9aa4b2}
*{box-sizing:border-box}
body{margin:0;font-family:Inter,system-ui,Arial;background:var(--bg);color:#e6eef6;display:flex;gap:18px;padding:20px;align-items:flex-start}
.sidebar{width:320px;background:linear-gradient(180deg,#071022,#0b1220);padding:16px;border-radius:12px;box-shadow:0 6px 24px rgba(0,0,0,.6)}
h2{margin:6px 0 14px;font-size:18px}
label{display:block;font-size:13px;color:var(--muted);margin-top:8px}
.swatches{display:flex;gap:8px;margin-top:8px;flex-wrap:wrap}
.swatch{width:36px;height:36px;border-radius:6px;cursor:pointer;border:2px solid transparent}
.swatch.selected{outline:3px solid rgba(255,255,255,0.06)}
.controls{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}
button{background:#112033;border:0;color:#e6eef6;padding:8px 10px;border-radius:8px;cursor:pointer}
.play-area{flex:1;display:flex;flex-direction:column;align-items:center}
canvas{background:linear-gradient(180deg,#071022,#0b1630);border-radius:12px;box-shadow:0 10px 40px rgba(2,6,23,0.7)}
.info{margin-top:12px;color:var(--muted);font-size:13px;display:flex;gap:12px}
.row{display:flex;gap:8px;align-items:center}
input, select{width:100%;padding:8px;margin:8px 0;border-radius:6px;border:1px solid rgba(255,255,255,0.06);background:rgba(255,255,255,0.02);color:#e6eef6}
.muted{color:var(--muted)}
.small{font-size:12px}
.power{display:flex;gap:8px;margin-top:8px}
.leaderboard{margin-top:14px;background:rgba(255,255,255,0.02);padding:8px;border-radius:8px;max-height:180px;overflow:auto}
</style>
</head>
<body>
<div class="sidebar">
<h2>Avatar Customizer</h2>
<label>Skin</label>
<div class="swatches" id="skin-swatches"></div>
<label>Hair</label>
<div class="swatches" id="hair-swatches"></div>
<label>Shirt</label>
<div class="swatches" id="shirt-swatches"></div>
<h2 style="margin-top:16px">Levels</h2>
<div class="controls">
<button data-level="city" class="lvl">City</button>
<button data-level="forest" class="lvl">Forest</button>
<button data-level="space" class="lvl">Space</button>
</div>
<h2 style="margin-top:12px">Game Settings</h2>
<label>Difficulty</label>
<div class="controls">
<button id="easy">Easy</button>
<button id="medium">Medium</button>
<button id="hard">Hard</button>
</div>
<h2 style="margin-top:12px">Power-ups</h2>
<div class="power">
<button id="useShield">Use Shield</button>
<button id="useSlow">Use Slow</button>
<button id="useBonus">Use +Points</button>
</div>
<h2 style="margin-top:12px">Controls</h2>
<div class="info small">
<div>Move: ← → or A D</div>
<div>Jump: W / ↑</div>
<div>Pause: P / Space</div>
</div>
<div style="margin-top:12px" class="row">
<button id="startBtn">Start</button>
<button id="restartBtn">Restart</button>
</div>
<h2 style="margin-top:12px">Leaderboard (Online)</h2>
<div style="display:flex;gap:8px;">
<input id="playerName" placeholder="Your name (for leaderboard)" />
<button id="submitScoreBtn">Submit</button>
</div>
<div class="leaderboard" id="leaderboard">Loading...</div>
<div style="margin-top:12px" class="small muted">Server endpoints expected: submit_score.php, fetch_scores.php (see server files). Save them into same folder on PHP-capable server.</div>
</div>
<div class="play-area">
<canvas id="game" width="880" height="520"></canvas>
<div class="row info">
<div>Score: <b id="score">0</b></div>
<div>High: <b id="high">0</b></div>
<div>Lives: <b id="lives">3</b></div>
<div>Shield: <b id="shieldCount">1</b></div>
<div>Slow: <b id="slowCount">1</b></div>
</div>
<div class="info muted small">Sound effects: on by default. Toggle in console if needed.</div>
</div>
<script>
/*
Upgraded Avatar Dodge
- Avatar animations (walk/jump) drawn procedurally (no external images)
- Background level switching
- Power-ups: shield (skip hit), slow (slows enemies), bonus (instant points)
- WebAudio for SFX + simple music loop
- Online leaderboard calls (submit & fetch) via fetch API to PHP endpoints
- Server endpoints are included separately (PHP + SQL)
*/
// ---------------- Config ----------------
const skinOptions = ["#f8d7b7","#f0c19a","#d6a06a","#b07a4a","#7b4b2e"];
const hairOptions = ["#0b0b0b","#5a3714","#d9c08a","#6b2e8a","#f2f2f2"];
const shirtOptions = ["#3b82f6","#10b981","#ef4444","#f59e0b","#6366f1"];
let avatar = {skin: skinOptions[1], hair: hairOptions[0], shirt: shirtOptions[0]};
let difficulty = 'medium';
let level = 'city';
// UI: make swatches
function makeSwatches(containerId, options, key){
const container = document.getElementById(containerId);
container.innerHTML = '';
options.forEach((c,i)=>{
const s = document.createElement('div');
s.className='swatch'+(i===0?' selected':'');
s.style.background = c;
s.addEventListener('click',()=>{
avatar[key]=c;
container.querySelectorAll('.swatch').forEach(x=>x.classList.remove('selected'));
s.classList.add('selected');
drawPreview();
});
container.appendChild(s);
});
}
makeSwatches('skin-swatches', skinOptions, 'skin');
makeSwatches('hair-swatches', hairOptions, 'hair');
makeSwatches('shirt-sw
<?php
// Save as submit_score.php
// Simple JSON API: expects POST JSON {name, score}
// Stores into MySQL table `leaderboard`
// NOTE: adjust DB credentials below.
header('Content-Type: application/json');
$raw = file_get_contents("php://input");
$data = json_decode($raw, true);
if(!$data || !isset($data['name']) || !isset($data['score'])) {
http_response_code(400);
echo json_encode(['error'=>'Invalid payload']);
exit;
}
$name = substr(trim($data['name']),0,64);
$score = (int)$data['score'];
$host = 'localhost';
$user = 'root';
$pass = '';
$db = 'earning_db'; // or your chosen DB
$conn = new mysqli($host,$user,$pass,$db);
if($conn->connect_error){ http_response_code(500); echo json_encode(['error'=>'DB connection']); exit; }
$stmt = $conn->prepare("INSERT INTO leaderboard (name, score) VALUES (?, ?)");
$stmt->bind_param('si', $name, $score);
if($stmt->execute()){
echo json_encode(['ok'=>true]);
} else {
http_response_code(500);
echo json_encode(['error'=>'insert failed']);
}
$stmt->close();
$conn->close();
<?php
// Save as fetch_scores.php
// Returns top 20 scores as JSON
header('Content-Type: application/json');
$host = 'localhost';
$user = 'root';
$pass = '';
$db = 'earning_db';
$conn = new mysqli($host,$user,$pass,$db);
if($conn->connect_error){ http_response_code(500); echo json_encode([]); exit; }
$res = $conn->query("SELECT name, score FROM leaderboard ORDER BY score DESC, id ASC LIMIT 20");
$out = [];
while($row = $res->fetch_assoc()){
$out[] = ['name'=>htmlspecialchars($row['name']), 'score'=>(int)$row['score']];
}
echo json_encode($out);
$conn->close();-- Run in your MySQL:
CREATE DATABASE IF NOT EXISTS earning_db;
USE earning_db;
-- leaderboard table
CREATE TABLE IF NOT EXISTS leaderboard (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(64) NOT NULL,
score INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- (Optional) existing users table from earlier (if you saved it)
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100),
password VARCHAR(255),
points INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);<!-- Save this as index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Avatar Dodge — Frontend</title>
<style>
:root{--bg:#061124;--panel:#071226;--muted:#9aa4b2}
*{box-sizing:border-box}
body{margin:0;font-family:Inter,system-ui,Arial;background:var(--bg);color:#e6eef6;display:flex;gap:18px;padding:20px;align-items:flex-start}
.sidebar{width:320px;background:linear-gradient(180deg,#071022,#0b1220);padding:16px;border-radius:12px;box-shadow:0 6px 24px rgba(0,0,0,.6)}
h2{margin:6px 0 14px;font-size:18px}
label{display:block;font-size:13px;color:var(--muted);margin-top:8px}
.swatches{display:flex;gap:8px;margin-top:8px;flex-wrap:wrap}
.swatch{width:36px;height:36px;border-radius:6px;cursor:pointer;border:2px solid transparent}
.swatch.selected{outline:3px solid rgba(255,255,255,0.06)}
.controls{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}
button{background:#112033;border:0;color:#e6eef6;padding:8px 10px;border-radius:8px;cursor:pointer}
.play-area{flex:1;display:flex;flex-direction:column;align-items:center}
canvas{background:linear-gradient(180deg,#071022,#0b1630);border-radius:12px;box-shadow:0 10px 40px rgba(2,6,23,0.7)}
.info{margin-top:12px;color:var(--muted);font-size:13px;display:flex;gap:12px;flex-wrap:wrap}
.row{display:flex;gap:8px;align-items:center}
input, select{width:100%;padding:8px;margin:8px 0;border-radius:6px;border:1px solid rgba(255,255,255,0.06);background:rgba(255,255,255,0.02);color:#e6eef6}
.muted{color:var(--muted)}
.small{font-size:12px}
.power{display:flex;gap:8px;margin-top:8px}
.leaderboard{margin-top:14px;background:rgba(255,255,255,0.02);padding:8px;border-radius:8px;max-height:180px;overflow:auto}
</style>
</head>
<body>
<div class="sidebar">
<h2>Avatar Customizer</h2>
<label>Skin</label>
<div class="swatches" id="skin-swatches"></div>
<label>Hair</label>
<div class="swatches" id="hair-swatches"></div>
<label>Shirt</label>
<div class="swatches" id="shirt-swatches"></div>
<h2 style="margin-top:16px">Levels</h2>
<div class="controls">
<button data-level="city" class="lvl">City</button>
<button data-level="forest" class="lvl">Forest</button>
<button data-level="space" class="lvl">Space</button>
</div>
<h2 style="margin-top:12px">Game Settings</h2>
<label>Difficulty</label>
<div class="controls">
<button id="easy">Easy</button>
<button id="medium">Medium</button>
<button id="hard">Hard</button>
</div>
<h2 style="margin-top:12px">Power-ups</h2>
<div class="power">
<button id="useShield">Use Shield</button>
<button id="useSlow">Use Slow</button>
<button id="useBonus">Use +Points</button>
</div>
<h2 style="margin-top:12px">Controls</h2>
<div class="info small">
<div>Move: ← → or A D</div>
<div>Jump: W / ↑</div>
<div>Pause: P / Space</div>
</div>
<div style="margin-top:12px" class="row">
<button id="startBtn">Start</button>
<button id="restartBtn">Restart</button>
</div>
<h2 style="margin-top:12px">Leaderboard (placeholder)</h2>
<div class="leaderboard" id="leaderboard">Local demo — server leaderboard not active yet</div>
</div>
<div class="play-area">
<canvas id="game" width="880" height="520"></canvas>
<div class="row info">
<div>Score: <b id="score">0</b></div>
<div>High: <b id="high">0</b></div>
<div>Lives: <b id="lives">3</b></div>
<div>Shield: <b id="shieldCount">1</b></div>
<div>Slow: <b id="slowCount">1</b></div>
</div>
<div class="info muted small">Sound effects included (WebAudio). To mute, open dev console and set AudioCtx.suspend() if needed.</div>
</div>
<script>
/* Front-end Avatar Dodge (full client-side)
- Avatar customization
- Levels (city/forest/space)
- Difficulty
- Power-ups (shield, slow, bonus)
- Procedural avatar drawing & simple animations
- WebAudio SFX (no external files)
*/
const skinOptions = ["#f8d7b7","#f0c19a","#d6a06a","#b07a4a","#7b4b2e"];
const hairOptions = ["#0b0b0b","#5a3714","#d9c08a","#6b2e8a","#f2f2f2"];
const shirtOptions = ["#3b82f6","#10b981","#ef4444","#f59e0b","#6366f1"];
let avatar = {skin: skinOptions[1], hair: hairOptions[0], shirt: shirtOptions[0]};
let difficulty = 'medium';
let level = 'city';
function makeSwatches(containerId, options, key){
const container = document.getElementById(containerId);
container.innerHTML = '';
options.forEach((c,i)=>{
const s = document.createElement('div');
s.className='swatch'+(i===0?' selected':'');
s.style.background = c;
s.addEventListener('click',()=>{
avatar[key]=c;
container.querySelectorAll('.swatch').forEach(x=>x.classList.remove('selected'));
s.classList.add('selected');
drawPreview();
});
container.appendChild(s);
});
}
makeSwatches('skin-swatches', skinOptions, 'skin');
makeSwatches('hair-swatches', hairOptions, 'hair');
makeSwatches('shirt-swatches', shirtOptions, 'shirt');
['easy','medium','hard'].forEach(id=>document.getElementById(id).addEventListener('click',()=>{difficulty=id; flashButton(id);}));
function flashButton(id){document.querySelectorAll('.controls button').forEach(b=>b.style.opacity=0.6); const btn=document.getElementById(id); if(btn) btn.style.opacity=1}
flashButton('medium');
document.querySelectorAll('.lvl').forEach(b=>{
b.addEventListener('click', ()=>{ level = b.dataset.level; document.querySelectorAll('.lvl').forEach(x=>x.style.opacity=0.6); b.style.opacity=1; })
});
document.querySelectorAll('.lvl')[0].style.opacity = 1;
// Canvas & state
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const W = canvas.width, H = canvas.height;
let running=false, paused=false;
let player = {x: W/2, y: H-90, w:44, h:64, vx:0, vy:0, speed:4, onGround:true};
let enemies = [], powerups = [];
let spawnTimer=0, score=0, high=Number(localStorage.getItem('avatarHigh')||0);
let lives=3;
let shieldCount=1, slowCount=1;
let slowActive=false, shieldActive=false;
document.getElementById('high').innerText = high;
document.getElementById('lives').innerText = lives;
document.getElementById('shieldCount').innerText = shieldCount;
document.getElementById('slowCount').innerText = slowCount;
function paramsForDifficulty(d){
if(d==='easy') return {spawnRate:100, speedMin:1.2, speedMax:2.5};
if(d==='medium') return {spawnRate:70, speedMin:2.0, speedMax:3.6};
return {spawnRate:45, speedMin:2.6, speedMax:4.6};
}
// Input
const keys = {};
window.addEventListener('keydown', e=>{ keys[e.key.toLowerCase()]=true; if(e.key===' '||e.key==='Spacebar') e.preventDefault(); if(e.key==='p'||e.key==='P') paused=!paused; });
window.addEventListener('keyup', e=>{ keys[e.key.toLowerCase()]=false; });
document.getElementById('startBtn').addEventListener('click', ()=>startGame());
document.getElementById('restartBtn').addEventListener('click', ()=>resetAll());
document.getElementById('useShield').addEventListener('click', ()=>{
if(shieldCount>0){ shieldActive=true; shieldCount--; document.getElementById('shieldCount').innerText=shieldCount; sfx('shield'); setTimeout(()=>{shieldActive=false}, 8000); }
});
document.getElementById('useSlow').addEventListener('click', ()=>{
if(slowCount>0){ slowActive=true; slowCount--; document.getElementById('slowCount').innerText=slowCount; sfx('slow'); setTimeout(()=>{slowActive=false}, 8000); }
});
document.getElementById('useBonus').addEventListener('click', ()=>{
score += 25; document.getElementById('score').innerText = score; sfx('bonus');
});
// Audio (WebAudio)
const AudioCtx = new (window.AudioContext || window.webkitAudioContext)();
function sfx(type){
const t = AudioCtx.currentTime;
const o = AudioCtx.createOscillator();
const g = AudioCtx.createGain();
o.connect(g); g.connect(AudioCtx.destination);
o.type = 'sine';
if(type==='hit'){ o.frequency.setValueAtTime(120, t); g.gain.setValueAtTime(0.15,t); o.frequency.exponentialRampToValueAtTime(60,t+0.2); }
else if(type==='bonus'){ o.frequency.setValueAtTime(900,t); g.gain.setValueAtTime(0.09,t); o.frequency.exponentialRampToValueAtTime(1200,t+0.12); }
else if(type==='shield'){ o.frequency.setValueAtTime(300,t); g.gain.setValueAtTime(0.08,t); }
else if(type==='slow'){ o.frequency.setValueAtTime(240,t); g.gain.setValueAtTime(0.07,t); }
else { o.frequency.setValueAtTime(520,t); g.gain.setValueAtTime(0.04,t); }
o.start(t); o.stop(t+0.18);
}
// Avatar drawing
function drawAvatar(ctx,x,y,w,h, avatar, frame=0, state='idle'){
const headW = w*0.58, headH = h*0.34;
ctx.fillStyle = avatar.skin; ctx.beginPath(); ctx.ellipse(x, y - h*0.36, headW/2, headH/2, 0, 0, Math.PI*2); ctx.fill();
ctx.fillStyle = avatar.hair;
ctx.beginPath();
ctx.ellipse(x, y - h*0.45 - (state==='jump'?6:0), headW/1.05, headH*0.45, 0, 0, Math.PI*2);
ctx.fill();
ctx.fillStyle = avatar.shirt;
const bodyY = y - h*0.15 + (state==='walk'? Math.sin(frame*0.2)*2:0);
ctx.fillRect(x - w/2, bodyY, w, h*0.5);
ctx.fillStyle = '#111'; ctx.fillRect(x - 8, y - h*0.38, 4,4); ctx.fillRect(x +4, y - h*0.38,4,4);
ctx.fillStyle = '#0b0b0b';
const legOffset = (state==='walk')? Math.sin(frame*0.3)*6 : 0;
ctx.fillRect(x - w/2 + 6, y + h*0.18 + Math.max(0, legOffset), 8, 18);
ctx.fillRect(x + w/2 - 14, y + h*0.18 - Math.max(0, legOffset), 8, 18);
}
function drawPreview(){
ctx.save();
ctx.clearRect(0,0,160,120);
ctx.fillStyle='rgba(255,255,255,0.02)';
ctx.fillRect(0,0,160,120);
drawAvatar(ctx,70,70,80,100,avatar,0,'idle');
ctx.restore();
}
// Enemies & powerups
function spawnEnemy(){
const w = 28 + Math.random()*42;
const x = Math.random()*(W - w - 20) + 10;
const p = paramsForDifficulty(difficulty);
let speed = p.speedMin + Math.random()*(p.speedMax - p.speedMin);
if(slowActive) speed *= 0.45;
enemies.push({x, y:-w, w:w, h:w, vy:speed, rot:Math.random()*0.5});
}
function spawnPowerup(){
const types = ['shield','slow','bonus'];
const t = types[Math.floor(Math.random()*types.length)];
const x = Math.random()*(W-40)+20;
powerups.push({type:t,x,y:-30,w:28,h:28,vy:1.4});
}
// Update & draw
let frame=0;
function update(){
if(!running || paused) return;
frame++;
player.vx = 0;
if(keys['arrowleft']||keys['a']) player.vx = -player.speed;
if(keys['arrowright']||keys['d']) player.vx = player.speed;
if((keys['w']||keys['arrowup']) && player.onGround){ player.vy = -8; player.onGround=false; sfx('bonus'); }
player.x += player.vx;
player.y += player.vy;
if(!player.onGround) player.vy += 0.35;
if(player.y >= H - 50){ player.y = H - 50; player.vy=0; player.onGround=true; }
if(player.x < player.w/2) player.x = player.w/2;
if(player.x > W - player.w/2) player.x = W - player.w/2;
spawnTimer++;
const pr = paramsForDifficulty(difficulty).spawnRate;
if(spawnTimer > pr){ spawnEnemy(); spawnTimer=0; if(Math.random()<0.05) spawnPowerup(); }
for(let i=enemies.length-1;i>=0;i--){
const e = enemies[i];
e.y += e.vy;
e.vy += 0.01;
if(rectIntersect(e.x,e.y,e.w,e.h, player.x - player.w/2, player.y - player.h/2, player.w, player.h)){
if(shieldActive){ sfx('shield'); enemies.splice(i,1); score+=2; document.getElementById('score').innerText = score; }
else { sfx('hit'); enemies.splice(i,1); lives--; document.getElementById('lives').innerText = lives; if(lives<=0) endGame(); }
}
if(e.y > H + 100){ enemies.splice(i,1); score+=1; document.getElementById('score').innerText = score; }
}
for(let i=powerups.length-1;i>=0;i--){
const p = powerups[i]; p.y += p.vy;
if(rectIntersect(p.x,p.y,p.w,p.h, player.x - player.w/2, player.y - player.h/2, player.w, player.h)){
if(p.type==='shield'){ shieldCount++; document.getElementById('shieldCount').innerText = shieldCount;}
if(p.type==='slow'){ slowCount++; document.getElementById('slowCount').innerText = slowCount;}
if(p.type==='bonus'){ score+=10; document.getElementById('score').innerText = score;}
sfx('bonus'); powerups.splice(i,1);
} else if(p.y > H+50) powerups.splice(i,1);
}
}
function drawBackground(){
if(level==='city'){
ctx.fillStyle='#071826'; ctx.fillRect(0,0,W,H);
for(let i=0;i<14;i++){
ctx.fillStyle = `rgba(10,20,30,${0.05 + (i%3)*0.02})`;
const bw = 60 + (i%5)*30;
ctx.fillRect(i*70, H - 200 - (i%4)*20, bw, 200 + (i%4)*20);
}
ctx.fillStyle='#0b1b2b'; ctx.fillRect(0,H-30,W,30);
} else if(level==='forest'){
ctx.fillStyle='#042018'; ctx.fillRect(0,0,W,H);
for(let i=0;i<20;i++){
const tx = (i*80 + (frame%80));
ctx.fillStyle = '#0d331f';
ctx.fillRect(tx%W, H-140, 20, 140);
ctx.fillStyle = '#114d2b';
ctx.beginPath(); ctx.ellipse((tx%W)+10, H-150, 50,70,0,0,Math.PI*2); ctx.fill();
}
ctx.fillStyle='#062417'; ctx.fillRect(0,H-30,W,30);
} else {
ctx.fillStyle = '#00021a'; ctx.fillRect(0,0,W,H);
for(let i=0;i<120;i++){
ctx.fillStyle = i%7===0 ? '#fff' : '#7fb7ff';
ctx.fillRect((i*47 + frame)%W, (i*23 + frame)%H, 2,2);
}
ctx.fillStyle='rgba(10,10,30,0.4)'; ctx.fillRect(0,H-30,W,30);
}
}
function draw(){
ctx.clearRect(0,0,W,H);
drawBackground();
powerups.forEach(p=>{
ctx.fillStyle = p.type==='shield' ? '#7dd3fc' : p.type==='slow' ? '#fbbf24' : '#34d399';
ctx.beginPath(); ctx.arc(p.x+14, p.y+14, 12, 0, Math.PI*2); ctx.fill();
});
enemies.forEach(e=>{
ctx.save();
ctx.translate(e.x + e.w/2, e.y + e.h/2);
ctx.rotate(Math.sin(frame*0.02 + e.rot)*0.3);
ctx.fillStyle = '#eb515a'; ctx.fillRect(-e.w/2, -e.h/2, e.w, e.h);
ctx.restore();
});
const state = (!player.onGround) ? 'jump' : (Math.abs(player.vx)>0 ? 'walk' : 'idle');
drawAvatar(ctx, player.x, player.y, player.w, player.h, avatar, frame, state);
drawPreview();
if(paused){ ctx.fillStyle='rgba(0,0,0,0.45)'; ctx.fillRect(0,0,W,H); ctx.fillStyle='#fff'; ctx.font='28px sans-serif'; ctx.fillText('Paused', W/2-40, H/2); }
}
function loop(){ update(); draw(); if(running) requestAnimationFrame(loop); }
function rectIntersect(x1,y1,w1,h1,x2,y2,w2,h2){ return !(x2 > x1 + w1 || x2 + w2 < x1 || y2 > y1 + h1 || y2 + h2 < y1); }
function startGame(){
running = true; paused=false;
enemies = []; powerups = []; spawnTimer=0; score=0; lives=3; shieldCount=1; slowCount=1;
player.x = W/2; player.y = H-90; player.vx=0; player.vy=0; player.onGround=true;
document.getElementById('score').innerText = score;
document.getElementById('lives').innerText = lives;
document.getElementById('shieldCount').innerText = shieldCount;
document.getElementById('slowCount').innerText = slowCount;
loop();
}
function endGame(){
running=false;
if(score>high){ high=score; localStorage.setItem('avatarHigh', high); document.getElementById('high').innerText = high; }
ctx.fillStyle='rgba(0,0,0,0.6)'; ctx.fillRect(0,0,W,H);
ctx.fillStyle='#fff'; ctx.font='28px sans-serif'; ctx.fillText('Game Over', W/2-80, H/2-10);
ctx.font='18px sans-serif'; ctx.fillText('Score: '+score, W/2-40, H/2+20);
sfx('hit');
}
function resetAll(){ startGame(); }
drawPreview();
setInterval(()=>{ if(running && Math.random()<0.06) spawnPowerup(); }, 1200);
setInterval(()=>{ if(!running) drawPreview(); }, 800);
</script>
</body>
</html>-- create_db.sql
CREATE DATABASE IF NOT EXISTS earning_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE earning_db;
-- users table (for login)
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(150) DEFAULT NULL,
password VARCHAR(255) NOT NULL,
points INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- leaderboard table
CREATE TABLE IF NOT EXISTS leaderboard (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT DEFAULT NULL, -- nullable: allow guest scores
name VARCHAR(64) NOT NULL,
score INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
);<?php
// config.php
// Update these with your real DB credentials
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'earning_db');
function db_connect(){
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if($mysqli->connect_error) {
http_response_code(500);
die(json_encode(['error'=>'DB connection failed']));
}
$mysqli->set_charset('utf8mb4');
return $mysqli;
}
?><?php
// register.php
header('Content-Type: application/json');
require_once 'config.php';
$data = $_POST;
if(!isset($data['username']) || !isset($data['password'])){
http_response_code(400);
echo json_encode(['error'=>'Missing fields']);
exit;
}
$username = trim($data['username']);
$email = isset($data['email']) ? trim($data['email']) : null;
$password = $data['password'];
if(strlen($username) < 3 || strlen($password) < 6){
http_response_code(400);
echo json_encode(['error'=>'Username or password too short']);
exit;
}
$hash = password_hash($password, PASSWORD_DEFAULT);
$mysqli = db_connect();
$stmt = $mysqli->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
$stmt->bind_param('sss', $username, $email, $hash);
if($stmt->execute()){
echo json_encode(['ok'=>true, 'user_id'=>$stmt->insert_id]);
} else {
http_response_code(400);
echo json_encode(['error'=>'Insert failed: '.$mysqli->error]);
}
$stmt->close();
$mysqli->close();
?><?php
// login.php
session_start();
header('Content-Type: application/json');
require_once 'config.php';
$data = $_POST;
if(!isset($data['username']) || !isset($data['password'])){
http_response_code(400);
echo json_encode(['error'=>'Missing fields']);
exit;
}
$username = trim($data['username']);
$password = $data['password'];
$mysqli = db_connect();
$stmt = $mysqli->prepare("SELECT id, password FROM users WHERE username = ?");
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows === 0){
http_response_code(401);
echo json_encode(['error'=>'Invalid credentials']);
exit;
}
$stmt->bind_result($id, $hash);
$stmt->fetch();
if(password_verify($password, $hash)){
// login success
$_SESSION['user_id'] = $id;
echo json_encode(['ok'=>true, 'user_id'=>$id]);
} else {
http_response_code(401);
echo json_encode(['error'=>'Invalid credentials']);
}
$stmt->close();
$mysqli->close();
?><?php
// admin.php (dangerous: protect this)
require_once 'config.php';
$secret = 'REPLACE_WITH_STRONG_PASSWORD';
if(!isset($_GET['key']) || $_GET['key'] !== $secret){ die('Forbidden'); }
$mysqli = db_connect();
$mysqli->query("TRUNCATE TABLE leaderboard");
echo "Leaderboard cleared.";
?><?php
// submit_score.php
// Accepts JSON { name, score }
// If user logged in (session), it links score to user_id.
header('Content-Type: application/json');
require_once 'config.php';
session_start();
$raw = file_get_contents("php://input");
$data = json_decode($raw, true);
if(!$data || !isset($data['name']) || !isset($data['score'])){
http_response_code(400);
echo json_encode(['error'=>'Invalid payload']);
exit;
}
$name = substr(trim($data['name']),0,64);
$score = (int)$data['score'];
$user_id = isset($_SESSION['user_id']) ? intval($_SESSION['user_id']) : null;
$mysqli = db_connect();
$stmt = $mysqli->prepare("INSERT INTO leaderboard (user_id, name, score) VALUES (?, ?, ?)");
$stmt->bind_param('isi', $user_id, $name, $score);
if($stmt->execute()){
echo json_encode(['ok'=>true, 'id'=>$stmt->insert_id]);
} else {
http_response_code(500);
echo json_encode(['error'=>'insert failed']);
}
$stmt->close();
$mysqli->close();
?><?php
// fetch_scores.php
header('Content-Type: application/json');
require_once 'config.php';
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 20;
if($limit < 1) $limit = 20;
if($limit > 100) $limit = 100;
$mysqli = db_connect();
$stmt = $mysqli->prepare("SELECT name, score, created_at FROM leaderboard ORDER BY score DESC, created_at ASC LIMIT ?");
$stmt->bind_param('i', $limit);
$stmt->execute();
$res = $stmt->get_result();
$out = [];
while($row = $res->fetch_assoc()){
$out[] = ['name'=>htmlspecialchars($row['name']), 'score'=>(int)$row['score'], 'ts'=>$row['created_at']];
}
echo json_encode($out);
$stmt->close();
$mysqli->close();
?><?php
// admin.php (dangerous: protect this)
require_once 'config.php';
$secret = 'REPLACE_WITH_STRONG_PASSWORD';
if(!isset($_GET['key']) || $_GET['key'] !== $secret){ die('Forbidden'); }
$mysqli = db_connect();
$mysqli->query("TRUNCATE TABLE leaderboard");
echo "Leaderboard cleared.";
?>fetch('submit_score.php', {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify({name: playerName, score: score})
});<?php
// =============================
// Avatar Game - Database Config
// =============================
// Database settings
$host = "localhost"; // اگر XAMPP/WAMP استعمال کر رہے ہیں تو localhost رہنے دیں
$user = "root"; // default XAMPP user
$password = ""; // default XAMPP میں خالی ہوتا ہے
$dbname = "avatar_game"; // database name
// Create connection
$conn = new mysqli($host, $user, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("❌ Database Connection failed: " . $conn->connect_error);
}
// Character set UTF-8
$conn->set_charset("utf8");
?>-- ===========================
-- Avatar Game - Database SQL
-- ===========================
-- Database بنائیں
CREATE DATABASE IF NOT EXISTS avatar_game;
USE avatar_game;
-- Users table (login/register کے لیے)
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Scores table (leaderboard کے لیے)
CREATE TABLE IF NOT EXISTS scores (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
score INT NOT NULL,
level VARCHAR(50) DEFAULT 'default',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);<?php
include 'config.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = trim($_POST["username"]);
$email = trim($_POST["email"]);
$password = trim($_POST["password"]);
if (!empty($username) && !empty($email) && !empty($password)) {
// Password Hash
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Prepare SQL
$stmt = $conn-><?php
include 'config.php';
session_start();
if (!isset($_SESSION['user_id'])) {
echo "❌ User not logged in";
exit;
}
if (isset($_POST['score'])) {
$user_id = $_SESSION['user_id'];
$score = intval($_POST['score']);
$sql = "INSERT INTO scores (user_id, score) VALUES (?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ii", $user_id, $score);
if ($stmt->execute()) {
echo "✅ Score saved successfully!";
} else {
echo "❌ Error: " . $conn->error;
}
} else {
echo "❌ Score not received";
}
?><?php
include 'config.php';
$sql = "SELECT users.username, MAX(scores.score) AS best_score
FROM scores
JOIN users ON scores.user_id = users.id
GROUP BY users.id
ORDER BY best_score DESC
LIMIT 10";
$result = $conn->query($sql);
echo "<h2>🏆 Leaderboard</h2>";
echo "<table border='1' cellpadding='8'>";
echo "<tr><th>Rank</th><th>Username</th><th>Best Score</th></tr>";
$rank = 1;
while ($row = $result->fetch_assoc()) {
echo "<tr>
<td>{$rank}</td>
<td>{$row['username']}</td>
<td>{$row['best_score']}</td>
</tr>";
$rank++;
}
echo "</table>";
?>CREATE TABLE scores (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
score INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);<!DOCTYPE html>
<html>
<head>
<title>Mini Shooting Game</title>
<style>
body { margin:0; background:#222; overflow:hidden; }
#player {
width:40px; height:40px;
background:lime; position:absolute;
bottom:20px; left:50%;
}
.bullet {
width:5px; height:10px;
background:yellow; position:absolute;
}
.enemy {
width:40px; height:40px;
background:red; position:absolute;
top:0;
}
</style>
</head>
<body>
<div id="player"></div>
<script>
const player = document.getElementById("player");
let bullets = [];
let enemies = [];
// Player movement
document.addEventListener("keydown", e => {
let left = parseInt(player.style.left);
if(e.key === "ArrowLeft") player.style.left = (left-20) + "px";
if(e.key === "ArrowRight") player.style.left = (left+20) + "px";
if(e.key === " ") shoot();
});
function shoot(){
let bullet = document.createElement("div");
bullet.className = "bullet";
bullet.style.left = (player.offsetLeft+18) + "px";
bullet.style.top = (player.offsetTop-10) + "px";
document.body.appendChild(bullet);
bullets.push(bullet);
}
function spawnEnemy(){
let enemy = document.createElement("div");
enemy.className = "enemy";
enemy.style.left = Math.random() * (window.innerWidth-40) + "px";
document.body.appendChild(enemy);
enemies.push(enemy);
}
function gameLoop(){
// move bullets
bullets.forEach((b,i)=>{
b.style.top = (b.offsetTop-10) + "px";
if(b.offsetTop < 0) { b.remove(); bullets.splice(i,1); }
});
// move enemies
enemies.forEach((e,i)=>{
e.style.top = (e.offsetTop+3) + "px";
if(e.offsetTop > window.innerHeight) { e.remove(); enemies.splice(i,1); }
});
// collision check
bullets.forEach((b,bi)=>{
enemies.forEach((e,ei)=>{
if(b.offsetLeft < e.offsetLeft+40 &&
b.offsetLeft+5 > e.offsetLeft &&
b.offsetTop < e.offsetTop+40 &&
b.offsetTop+10 > e.offsetTop){
e.remove(); enemies.splice(ei,1);
b.remove(); bullets.splice(bi,1);
}
});
});
requestAnimationFrame(gameLoop);
}
setInterval(spawnEnemy, 2000);
gameLoop();
</script>
</body>
</html>
Score: 0High: 0Change avatar colors then press Start. The avatar is drawn from shapes — easy to replace with image sprites later.
</html><!-- Save as index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Avatar Dodge — Upgraded</title>
<style>
:root{--bg:#061124;--panel:#071226;--muted:#9aa4b2}
*{box-sizing:border-box}
body{margin:0;font-family:Inter,system-ui,Arial;background:var(--bg);color:#e6eef6;display:flex;gap:18px;padding:20px;align-items:flex-start}
.sidebar{width:320px;background:linear-gradient(180deg,#071022,#0b1220);padding:16px;border-radius:12px;box-shadow:0 6px 24px rgba(0,0,0,.6)}
h2{margin:6px 0 14px;font-size:18px}
label{display:block;font-size:13px;color:var(--muted);margin-top:8px}
.swatches{display:flex;gap:8px;margin-top:8px;flex-wrap:wrap}
.swatch{width:36px;height:36px;border-radius:6px;cursor:pointer;border:2px solid transparent}
.swatch.selected{outline:3px solid rgba(255,255,255,0.06)}
.controls{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}
button{background:#112033;border:0;color:#e6eef6;padding:8px 10px;border-radius:8px;cursor:pointer}
.play-area{flex:1;display:flex;flex-direction:column;align-items:center}
canvas{background:linear-gradient(180deg,#071022,#0b1630);border-radius:12px;box-shadow:0 10px 40px rgba(2,6,23,0.7)}
.info{margin-top:12px;color:var(--muted);font-size:13px;display:flex;gap:12px}
.row{display:flex;gap:8px;align-items:center}
input, select{width:100%;padding:8px;margin:8px 0;border-radius:6px;border:1px solid rgba(255,255,255,0.06);background:rgba(255,255,255,0.02);color:#e6eef6}
.muted{color:var(--muted)}
.small{font-size:12px}
.power{display:flex;gap:8px;margin-top:8px}
.leaderboard{margin-top:14px;background:rgba(255,255,255,0.02);padding:8px;border-radius:8px;max-height:180px;overflow:auto}
</style>
</head>
<body>
<div class="sidebar">
<h2>Avatar Customizer</h2>
<label>Skin</label>
<div class="swatches" id="skin-swatches"></div>
<label>Hair</label>
<div class="swatches" id="hair-swatches"></div>
<label>Shirt</label>
<div class="swatches" id="shirt-swatches"></div>
<h2 style="margin-top:16px">Levels</h2>
<div class="controls">
<button data-level="city" class="lvl">City</button>
<button data-level="forest" class="lvl">Forest</button>
<button data-level="space" class="lvl">Space</button>
</div>
<h2 style="margin-top:12px">Game Settings</h2>
<label>Difficulty</label>
<div class="controls">
<button id="easy">Easy</button>
<button id="medium">Medium</button>
<button id="hard">Hard</button>
</div>
<h2 style="margin-top:12px">Power-ups</h2>
<div class="power">
<button id="useShield">Use Shield</button>
<button id="useSlow">Use Slow</button>
<button id="useBonus">Use +Points</button>
</div>
<h2 style="margin-top:12px">Controls</h2>
<div class="info small">
<div>Move: ← → or A D</div>
<div>Jump: W / ↑</div>
<div>Pause: P / Space</div>
</div>
<div style="margin-top:12px" class="row">
<button id="startBtn">Start</button>
<button id="restartBtn">Restart</button>
</div>
<h2 style="margin-top:12px">Leaderboard (Online)</h2>
<div style="display:flex;gap:8px;">
<input id="playerName" placeholder="Your name (for leaderboard)" />
<button id="submitScoreBtn">Submit</button>
</div>
<div class="leaderboard" id="leaderboard">Loading...</div>
<div style="margin-top:12px" class="small muted">Server endpoints expected: submit_score.php, fetch_scores.php (see server files). Save them into same folder on PHP-capable server.</div>
</div>
<div class="play-area">
<canvas id="game" width="880" height="520"></canvas>
<div class="row info">
<div>Score: <b id="score">0</b></div>
<div>High: <b id="high">0</b></div>
<div>Lives: <b id="lives">3</b></div>
<div>Shield: <b id="shieldCount">1</b></div>
<div>Slow: <b id="slowCount">1</b></div>
</div>
<div class="info muted small">Sound effects: on by default. Toggle in console if needed.</div>
</div>
<script>
/*
Upgraded Avatar Dodge
- Avatar animations (walk/jump) drawn procedurally (no external images)
- Background level switching
- Power-ups: shield (skip hit), slow (slows enemies), bonus (instant points)
- WebAudio for SFX + simple music loop
- Online leaderboard calls (submit & fetch) via fetch API to PHP endpoints
- Server endpoints are included separately (PHP + SQL)
*/
// ---------------- Config ----------------
const skinOptions = ["#f8d7b7","#f0c19a","#d6a06a","#b07a4a","#7b4b2e"];
const hairOptions = ["#0b0b0b","#5a3714","#d9c08a","#6b2e8a","#f2f2f2"];
const shirtOptions = ["#3b82f6","#10b981","#ef4444","#f59e0b","#6366f1"];
let avatar = {skin: skinOptions[1], hair: hairOptions[0], shirt: shirtOptions[0]};
let difficulty = 'medium';
let level = 'city';
// UI: make swatches
function makeSwatches(containerId, options, key){
const container = document.getElementById(containerId);
container.innerHTML = '';
options.forEach((c,i)=>{
const s = document.createElement('div');
s.className='swatch'+(i===0?' selected':'');
s.style.background = c;
s.addEventListener('click',()=>{
avatar[key]=c;
container.querySelectorAll('.swatch').forEach(x=>x.classList.remove('selected'));
s.classList.add('selected');
drawPreview();
});
container.appendChild(s);
});
}
makeSwatches('skin-swatches', skinOptions, 'skin');
makeSwatches('hair-swatches', hairOptions, 'hair');
makeSwatches('shirt-sw
<?php
// Save as submit_score.php
// Simple JSON API: expects POST JSON {name, score}
// Stores into MySQL table `leaderboard`
// NOTE: adjust DB credentials below.
header('Content-Type: application/json');
$raw = file_get_contents("php://input");
$data = json_decode($raw, true);
if(!$data || !isset($data['name']) || !isset($data['score'])) {
http_response_code(400);
echo json_encode(['error'=>'Invalid payload']);
exit;
}
$name = substr(trim($data['name']),0,64);
$score = (int)$data['score'];
$host = 'localhost';
$user = 'root';
$pass = '';
$db = 'earning_db'; // or your chosen DB
$conn = new mysqli($host,$user,$pass,$db);
if($conn->connect_error){ http_response_code(500); echo json_encode(['error'=>'DB connection']); exit; }
$stmt = $conn->prepare("INSERT INTO leaderboard (name, score) VALUES (?, ?)");
$stmt->bind_param('si', $name, $score);
if($stmt->execute()){
echo json_encode(['ok'=>true]);
} else {
http_response_code(500);
echo json_encode(['error'=>'insert failed']);
}
$stmt->close();
$conn->close();<?php
// Save as fetch_scores.php
// Returns top 20 scores as JSON
header('Content-Type: application/json');
$host = 'localhost';
$user = 'root';
$pass = '';
$db = 'earning_db';
$conn = new mysqli($host,$user,$pass,$db);
if($conn->connect_error){ http_response_code(500); echo json_encode([]); exit; }
$res = $conn->query("SELECT name, score FROM leaderboard ORDER BY score DESC, id ASC LIMIT 20");
$out = [];
while($row = $res->fetch_assoc()){
$out[] = ['name'=>htmlspecialchars($row['name']), 'score'=>(int)$row['score']];
}
echo json_encode($out);
$conn->close();-- Run in your MySQL:
CREATE DATABASE IF NOT EXISTS earning_db;
USE earning_db;
-- leaderboard table
CREATE TABLE IF NOT EXISTS leaderboard (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(64) NOT NULL,
score INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- (Optional) existing users table from earlier (if you saved it)
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100),
password VARCHAR(255),
points INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);<!-- Save this as index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Avatar Dodge — Frontend</title>
<style>
:root{--bg:#061124;--panel:#071226;--muted:#9aa4b2}
*{box-sizing:border-box}
body{margin:0;font-family:Inter,system-ui,Arial;background:var(--bg);color:#e6eef6;display:flex;gap:18px;padding:20px;align-items:flex-start}
.sidebar{width:320px;background:linear-gradient(180deg,#071022,#0b1220);padding:16px;border-radius:12px;box-shadow:0 6px 24px rgba(0,0,0,.6)}
h2{margin:6px 0 14px;font-size:18px}
label{display:block;font-size:13px;color:var(--muted);margin-top:8px}
.swatches{display:flex;gap:8px;margin-top:8px;flex-wrap:wrap}
.swatch{width:36px;height:36px;border-radius:6px;cursor:pointer;border:2px solid transparent}
.swatch.selected{outline:3px solid rgba(255,255,255,0.06)}
.controls{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}
button{background:#112033;border:0;color:#e6eef6;padding:8px 10px;border-radius:8px;cursor:pointer}
.play-area{flex:1;display:flex;flex-direction:column;align-items:center}
canvas{background:linear-gradient(180deg,#071022,#0b1630);border-radius:12px;box-shadow:0 10px 40px rgba(2,6,23,0.7)}
.info{margin-top:12px;color:var(--muted);font-size:13px;display:flex;gap:12px;flex-wrap:wrap}
.row{display:flex;gap:8px;align-items:center}
input, select{width:100%;padding:8px;margin:8px 0;border-radius:6px;border:1px solid rgba(255,255,255,0.06);background:rgba(255,255,255,0.02);color:#e6eef6}
.muted{color:var(--muted)}
.small{font-size:12px}
.power{display:flex;gap:8px;margin-top:8px}
.leaderboard{margin-top:14px;background:rgba(255,255,255,0.02);padding:8px;border-radius:8px;max-height:180px;overflow:auto}
</style>
</head>
<body>
<div class="sidebar">
<h2>Avatar Customizer</h2>
<label>Skin</label>
<div class="swatches" id="skin-swatches"></div>
<label>Hair</label>
<div class="swatches" id="hair-swatches"></div>
<label>Shirt</label>
<div class="swatches" id="shirt-swatches"></div>
<h2 style="margin-top:16px">Levels</h2>
<div class="controls">
<button data-level="city" class="lvl">City</button>
<button data-level="forest" class="lvl">Forest</button>
<button data-level="space" class="lvl">Space</button>
</div>
<h2 style="margin-top:12px">Game Settings</h2>
<label>Difficulty</label>
<div class="controls">
<button id="easy">Easy</button>
<button id="medium">Medium</button>
<button id="hard">Hard</button>
</div>
<h2 style="margin-top:12px">Power-ups</h2>
<div class="power">
<button id="useShield">Use Shield</button>
<button id="useSlow">Use Slow</button>
<button id="useBonus">Use +Points</button>
</div>
<h2 style="margin-top:12px">Controls</h2>
<div class="info small">
<div>Move: ← → or A D</div>
<div>Jump: W / ↑</div>
<div>Pause: P / Space</div>
</div>
<div style="margin-top:12px" class="row">
<button id="startBtn">Start</button>
<button id="restartBtn">Restart</button>
</div>
<h2 style="margin-top:12px">Leaderboard (placeholder)</h2>
<div class="leaderboard" id="leaderboard">Local demo — server leaderboard not active yet</div>
</div>
<div class="play-area">
<canvas id="game" width="880" height="520"></canvas>
<div class="row info">
<div>Score: <b id="score">0</b></div>
<div>High: <b id="high">0</b></div>
<div>Lives: <b id="lives">3</b></div>
<div>Shield: <b id="shieldCount">1</b></div>
<div>Slow: <b id="slowCount">1</b></div>
</div>
<div class="info muted small">Sound effects included (WebAudio). To mute, open dev console and set AudioCtx.suspend() if needed.</div>
</div>
<script>
/* Front-end Avatar Dodge (full client-side)
- Avatar customization
- Levels (city/forest/space)
- Difficulty
- Power-ups (shield, slow, bonus)
- Procedural avatar drawing & simple animations
- WebAudio SFX (no external files)
*/
const skinOptions = ["#f8d7b7","#f0c19a","#d6a06a","#b07a4a","#7b4b2e"];
const hairOptions = ["#0b0b0b","#5a3714","#d9c08a","#6b2e8a","#f2f2f2"];
const shirtOptions = ["#3b82f6","#10b981","#ef4444","#f59e0b","#6366f1"];
let avatar = {skin: skinOptions[1], hair: hairOptions[0], shirt: shirtOptions[0]};
let difficulty = 'medium';
let level = 'city';
function makeSwatches(containerId, options, key){
const container = document.getElementById(containerId);
container.innerHTML = '';
options.forEach((c,i)=>{
const s = document.createElement('div');
s.className='swatch'+(i===0?' selected':'');
s.style.background = c;
s.addEventListener('click',()=>{
avatar[key]=c;
container.querySelectorAll('.swatch').forEach(x=>x.classList.remove('selected'));
s.classList.add('selected');
drawPreview();
});
container.appendChild(s);
});
}
makeSwatches('skin-swatches', skinOptions, 'skin');
makeSwatches('hair-swatches', hairOptions, 'hair');
makeSwatches('shirt-swatches', shirtOptions, 'shirt');
['easy','medium','hard'].forEach(id=>document.getElementById(id).addEventListener('click',()=>{difficulty=id; flashButton(id);}));
function flashButton(id){document.querySelectorAll('.controls button').forEach(b=>b.style.opacity=0.6); const btn=document.getElementById(id); if(btn) btn.style.opacity=1}
flashButton('medium');
document.querySelectorAll('.lvl').forEach(b=>{
b.addEventListener('click', ()=>{ level = b.dataset.level; document.querySelectorAll('.lvl').forEach(x=>x.style.opacity=0.6); b.style.opacity=1; })
});
document.querySelectorAll('.lvl')[0].style.opacity = 1;
// Canvas & state
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const W = canvas.width, H = canvas.height;
let running=false, paused=false;
let player = {x: W/2, y: H-90, w:44, h:64, vx:0, vy:0, speed:4, onGround:true};
let enemies = [], powerups = [];
let spawnTimer=0, score=0, high=Number(localStorage.getItem('avatarHigh')||0);
let lives=3;
let shieldCount=1, slowCount=1;
let slowActive=false, shieldActive=false;
document.getElementById('high').innerText = high;
document.getElementById('lives').innerText = lives;
document.getElementById('shieldCount').innerText = shieldCount;
document.getElementById('slowCount').innerText = slowCount;
function paramsForDifficulty(d){
if(d==='easy') return {spawnRate:100, speedMin:1.2, speedMax:2.5};
if(d==='medium') return {spawnRate:70, speedMin:2.0, speedMax:3.6};
return {spawnRate:45, speedMin:2.6, speedMax:4.6};
}
// Input
const keys = {};
window.addEventListener('keydown', e=>{ keys[e.key.toLowerCase()]=true; if(e.key===' '||e.key==='Spacebar') e.preventDefault(); if(e.key==='p'||e.key==='P') paused=!paused; });
window.addEventListener('keyup', e=>{ keys[e.key.toLowerCase()]=false; });
document.getElementById('startBtn').addEventListener('click', ()=>startGame());
document.getElementById('restartBtn').addEventListener('click', ()=>resetAll());
document.getElementById('useShield').addEventListener('click', ()=>{
if(shieldCount>0){ shieldActive=true; shieldCount--; document.getElementById('shieldCount').innerText=shieldCount; sfx('shield'); setTimeout(()=>{shieldActive=false}, 8000); }
});
document.getElementById('useSlow').addEventListener('click', ()=>{
if(slowCount>0){ slowActive=true; slowCount--; document.getElementById('slowCount').innerText=slowCount; sfx('slow'); setTimeout(()=>{slowActive=false}, 8000); }
});
document.getElementById('useBonus').addEventListener('click', ()=>{
score += 25; document.getElementById('score').innerText = score; sfx('bonus');
});
// Audio (WebAudio)
const AudioCtx = new (window.AudioContext || window.webkitAudioContext)();
function sfx(type){
const t = AudioCtx.currentTime;
const o = AudioCtx.createOscillator();
const g = AudioCtx.createGain();
o.connect(g); g.connect(AudioCtx.destination);
o.type = 'sine';
if(type==='hit'){ o.frequency.setValueAtTime(120, t); g.gain.setValueAtTime(0.15,t); o.frequency.exponentialRampToValueAtTime(60,t+0.2); }
else if(type==='bonus'){ o.frequency.setValueAtTime(900,t); g.gain.setValueAtTime(0.09,t); o.frequency.exponentialRampToValueAtTime(1200,t+0.12); }
else if(type==='shield'){ o.frequency.setValueAtTime(300,t); g.gain.setValueAtTime(0.08,t); }
else if(type==='slow'){ o.frequency.setValueAtTime(240,t); g.gain.setValueAtTime(0.07,t); }
else { o.frequency.setValueAtTime(520,t); g.gain.setValueAtTime(0.04,t); }
o.start(t); o.stop(t+0.18);
}
// Avatar drawing
function drawAvatar(ctx,x,y,w,h, avatar, frame=0, state='idle'){
const headW = w*0.58, headH = h*0.34;
ctx.fillStyle = avatar.skin; ctx.beginPath(); ctx.ellipse(x, y - h*0.36, headW/2, headH/2, 0, 0, Math.PI*2); ctx.fill();
ctx.fillStyle = avatar.hair;
ctx.beginPath();
ctx.ellipse(x, y - h*0.45 - (state==='jump'?6:0), headW/1.05, headH*0.45, 0, 0, Math.PI*2);
ctx.fill();
ctx.fillStyle = avatar.shirt;
const bodyY = y - h*0.15 + (state==='walk'? Math.sin(frame*0.2)*2:0);
ctx.fillRect(x - w/2, bodyY, w, h*0.5);
ctx.fillStyle = '#111'; ctx.fillRect(x - 8, y - h*0.38, 4,4); ctx.fillRect(x +4, y - h*0.38,4,4);
ctx.fillStyle = '#0b0b0b';
const legOffset = (state==='walk')? Math.sin(frame*0.3)*6 : 0;
ctx.fillRect(x - w/2 + 6, y + h*0.18 + Math.max(0, legOffset), 8, 18);
ctx.fillRect(x + w/2 - 14, y + h*0.18 - Math.max(0, legOffset), 8, 18);
}
function drawPreview(){
ctx.save();
ctx.clearRect(0,0,160,120);
ctx.fillStyle='rgba(255,255,255,0.02)';
ctx.fillRect(0,0,160,120);
drawAvatar(ctx,70,70,80,100,avatar,0,'idle');
ctx.restore();
}
// Enemies & powerups
function spawnEnemy(){
const w = 28 + Math.random()*42;
const x = Math.random()*(W - w - 20) + 10;
const p = paramsForDifficulty(difficulty);
let speed = p.speedMin + Math.random()*(p.speedMax - p.speedMin);
if(slowActive) speed *= 0.45;
enemies.push({x, y:-w, w:w, h:w, vy:speed, rot:Math.random()*0.5});
}
function spawnPowerup(){
const types = ['shield','slow','bonus'];
const t = types[Math.floor(Math.random()*types.length)];
const x = Math.random()*(W-40)+20;
powerups.push({type:t,x,y:-30,w:28,h:28,vy:1.4});
}
// Update & draw
let frame=0;
function update(){
if(!running || paused) return;
frame++;
player.vx = 0;
if(keys['arrowleft']||keys['a']) player.vx = -player.speed;
if(keys['arrowright']||keys['d']) player.vx = player.speed;
if((keys['w']||keys['arrowup']) && player.onGround){ player.vy = -8; player.onGround=false; sfx('bonus'); }
player.x += player.vx;
player.y += player.vy;
if(!player.onGround) player.vy += 0.35;
if(player.y >= H - 50){ player.y = H - 50; player.vy=0; player.onGround=true; }
if(player.x < player.w/2) player.x = player.w/2;
if(player.x > W - player.w/2) player.x = W - player.w/2;
spawnTimer++;
const pr = paramsForDifficulty(difficulty).spawnRate;
if(spawnTimer > pr){ spawnEnemy(); spawnTimer=0; if(Math.random()<0.05) spawnPowerup(); }
for(let i=enemies.length-1;i>=0;i--){
const e = enemies[i];
e.y += e.vy;
e.vy += 0.01;
if(rectIntersect(e.x,e.y,e.w,e.h, player.x - player.w/2, player.y - player.h/2, player.w, player.h)){
if(shieldActive){ sfx('shield'); enemies.splice(i,1); score+=2; document.getElementById('score').innerText = score; }
else { sfx('hit'); enemies.splice(i,1); lives--; document.getElementById('lives').innerText = lives; if(lives<=0) endGame(); }
}
if(e.y > H + 100){ enemies.splice(i,1); score+=1; document.getElementById('score').innerText = score; }
}
for(let i=powerups.length-1;i>=0;i--){
const p = powerups[i]; p.y += p.vy;
if(rectIntersect(p.x,p.y,p.w,p.h, player.x - player.w/2, player.y - player.h/2, player.w, player.h)){
if(p.type==='shield'){ shieldCount++; document.getElementById('shieldCount').innerText = shieldCount;}
if(p.type==='slow'){ slowCount++; document.getElementById('slowCount').innerText = slowCount;}
if(p.type==='bonus'){ score+=10; document.getElementById('score').innerText = score;}
sfx('bonus'); powerups.splice(i,1);
} else if(p.y > H+50) powerups.splice(i,1);
}
}
function drawBackground(){
if(level==='city'){
ctx.fillStyle='#071826'; ctx.fillRect(0,0,W,H);
for(let i=0;i<14;i++){
ctx.fillStyle = `rgba(10,20,30,${0.05 + (i%3)*0.02})`;
const bw = 60 + (i%5)*30;
ctx.fillRect(i*70, H - 200 - (i%4)*20, bw, 200 + (i%4)*20);
}
ctx.fillStyle='#0b1b2b'; ctx.fillRect(0,H-30,W,30);
} else if(level==='forest'){
ctx.fillStyle='#042018'; ctx.fillRect(0,0,W,H);
for(let i=0;i<20;i++){
const tx = (i*80 + (frame%80));
ctx.fillStyle = '#0d331f';
ctx.fillRect(tx%W, H-140, 20, 140);
ctx.fillStyle = '#114d2b';
ctx.beginPath(); ctx.ellipse((tx%W)+10, H-150, 50,70,0,0,Math.PI*2); ctx.fill();
}
ctx.fillStyle='#062417'; ctx.fillRect(0,H-30,W,30);
} else {
ctx.fillStyle = '#00021a'; ctx.fillRect(0,0,W,H);
for(let i=0;i<120;i++){
ctx.fillStyle = i%7===0 ? '#fff' : '#7fb7ff';
ctx.fillRect((i*47 + frame)%W, (i*23 + frame)%H, 2,2);
}
ctx.fillStyle='rgba(10,10,30,0.4)'; ctx.fillRect(0,H-30,W,30);
}
}
function draw(){
ctx.clearRect(0,0,W,H);
drawBackground();
powerups.forEach(p=>{
ctx.fillStyle = p.type==='shield' ? '#7dd3fc' : p.type==='slow' ? '#fbbf24' : '#34d399';
ctx.beginPath(); ctx.arc(p.x+14, p.y+14, 12, 0, Math.PI*2); ctx.fill();
});
enemies.forEach(e=>{
ctx.save();
ctx.translate(e.x + e.w/2, e.y + e.h/2);
ctx.rotate(Math.sin(frame*0.02 + e.rot)*0.3);
ctx.fillStyle = '#eb515a'; ctx.fillRect(-e.w/2, -e.h/2, e.w, e.h);
ctx.restore();
});
const state = (!player.onGround) ? 'jump' : (Math.abs(player.vx)>0 ? 'walk' : 'idle');
drawAvatar(ctx, player.x, player.y, player.w, player.h, avatar, frame, state);
drawPreview();
if(paused){ ctx.fillStyle='rgba(0,0,0,0.45)'; ctx.fillRect(0,0,W,H); ctx.fillStyle='#fff'; ctx.font='28px sans-serif'; ctx.fillText('Paused', W/2-40, H/2); }
}
function loop(){ update(); draw(); if(running) requestAnimationFrame(loop); }
function rectIntersect(x1,y1,w1,h1,x2,y2,w2,h2){ return !(x2 > x1 + w1 || x2 + w2 < x1 || y2 > y1 + h1 || y2 + h2 < y1); }
function startGame(){
running = true; paused=false;
enemies = []; powerups = []; spawnTimer=0; score=0; lives=3; shieldCount=1; slowCount=1;
player.x = W/2; player.y = H-90; player.vx=0; player.vy=0; player.onGround=true;
document.getElementById('score').innerText = score;
document.getElementById('lives').innerText = lives;
document.getElementById('shieldCount').innerText = shieldCount;
document.getElementById('slowCount').innerText = slowCount;
loop();
}
function endGame(){
running=false;
if(score>high){ high=score; localStorage.setItem('avatarHigh', high); document.getElementById('high').innerText = high; }
ctx.fillStyle='rgba(0,0,0,0.6)'; ctx.fillRect(0,0,W,H);
ctx.fillStyle='#fff'; ctx.font='28px sans-serif'; ctx.fillText('Game Over', W/2-80, H/2-10);
ctx.font='18px sans-serif'; ctx.fillText('Score: '+score, W/2-40, H/2+20);
sfx('hit');
}
function resetAll(){ startGame(); }
drawPreview();
setInterval(()=>{ if(running && Math.random()<0.06) spawnPowerup(); }, 1200);
setInterval(()=>{ if(!running) drawPreview(); }, 800);
</script>
</body>
</html>-- create_db.sql
CREATE DATABASE IF NOT EXISTS earning_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE earning_db;
-- users table (for login)
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(150) DEFAULT NULL,
password VARCHAR(255) NOT NULL,
points INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- leaderboard table
CREATE TABLE IF NOT EXISTS leaderboard (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT DEFAULT NULL, -- nullable: allow guest scores
name VARCHAR(64) NOT NULL,
score INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
);<?php
// config.php
// Update these with your real DB credentials
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'earning_db');
function db_connect(){
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if($mysqli->connect_error) {
http_response_code(500);
die(json_encode(['error'=>'DB connection failed']));
}
$mysqli->set_charset('utf8mb4');
return $mysqli;
}
?><?php
// register.php
header('Content-Type: application/json');
require_once 'config.php';
$data = $_POST;
if(!isset($data['username']) || !isset($data['password'])){
http_response_code(400);
echo json_encode(['error'=>'Missing fields']);
exit;
}
$username = trim($data['username']);
$email = isset($data['email']) ? trim($data['email']) : null;
$password = $data['password'];
if(strlen($username) < 3 || strlen($password) < 6){
http_response_code(400);
echo json_encode(['error'=>'Username or password too short']);
exit;
}
$hash = password_hash($password, PASSWORD_DEFAULT);
$mysqli = db_connect();
$stmt = $mysqli->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
$stmt->bind_param('sss', $username, $email, $hash);
if($stmt->execute()){
echo json_encode(['ok'=>true, 'user_id'=>$stmt->insert_id]);
} else {
http_response_code(400);
echo json_encode(['error'=>'Insert failed: '.$mysqli->error]);
}
$stmt->close();
$mysqli->close();
?><?php
// login.php
session_start();
header('Content-Type: application/json');
require_once 'config.php';
$data = $_POST;
if(!isset($data['username']) || !isset($data['password'])){
http_response_code(400);
echo json_encode(['error'=>'Missing fields']);
exit;
}
$username = trim($data['username']);
$password = $data['password'];
$mysqli = db_connect();
$stmt = $mysqli->prepare("SELECT id, password FROM users WHERE username = ?");
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->store_result();
if($stmt->num_rows === 0){
http_response_code(401);
echo json_encode(['error'=>'Invalid credentials']);
exit;
}
$stmt->bind_result($id, $hash);
$stmt->fetch();
if(password_verify($password, $hash)){
// login success
$_SESSION['user_id'] = $id;
echo json_encode(['ok'=>true, 'user_id'=>$id]);
} else {
http_response_code(401);
echo json_encode(['error'=>'Invalid credentials']);
}
$stmt->close();
$mysqli->close();
?><?php
// admin.php (dangerous: protect this)
require_once 'config.php';
$secret = 'REPLACE_WITH_STRONG_PASSWORD';
if(!isset($_GET['key']) || $_GET['key'] !== $secret){ die('Forbidden'); }
$mysqli = db_connect();
$mysqli->query("TRUNCATE TABLE leaderboard");
echo "Leaderboard cleared.";
?><?php
// submit_score.php
// Accepts JSON { name, score }
// If user logged in (session), it links score to user_id.
header('Content-Type: application/json');
require_once 'config.php';
session_start();
$raw = file_get_contents("php://input");
$data = json_decode($raw, true);
if(!$data || !isset($data['name']) || !isset($data['score'])){
http_response_code(400);
echo json_encode(['error'=>'Invalid payload']);
exit;
}
$name = substr(trim($data['name']),0,64);
$score = (int)$data['score'];
$user_id = isset($_SESSION['user_id']) ? intval($_SESSION['user_id']) : null;
$mysqli = db_connect();
$stmt = $mysqli->prepare("INSERT INTO leaderboard (user_id, name, score) VALUES (?, ?, ?)");
$stmt->bind_param('isi', $user_id, $name, $score);
if($stmt->execute()){
echo json_encode(['ok'=>true, 'id'=>$stmt->insert_id]);
} else {
http_response_code(500);
echo json_encode(['error'=>'insert failed']);
}
$stmt->close();
$mysqli->close();
?><?php
// fetch_scores.php
header('Content-Type: application/json');
require_once 'config.php';
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 20;
if($limit < 1) $limit = 20;
if($limit > 100) $limit = 100;
$mysqli = db_connect();
$stmt = $mysqli->prepare("SELECT name, score, created_at FROM leaderboard ORDER BY score DESC, created_at ASC LIMIT ?");
$stmt->bind_param('i', $limit);
$stmt->execute();
$res = $stmt->get_result();
$out = [];
while($row = $res->fetch_assoc()){
$out[] = ['name'=>htmlspecialchars($row['name']), 'score'=>(int)$row['score'], 'ts'=>$row['created_at']];
}
echo json_encode($out);
$stmt->close();
$mysqli->close();
?><?php
// admin.php (dangerous: protect this)
require_once 'config.php';
$secret = 'REPLACE_WITH_STRONG_PASSWORD';
if(!isset($_GET['key']) || $_GET['key'] !== $secret){ die('Forbidden'); }
$mysqli = db_connect();
$mysqli->query("TRUNCATE TABLE leaderboard");
echo "Leaderboard cleared.";
?>fetch('submit_score.php', {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify({name: playerName, score: score})
});<?php
// =============================
// Avatar Game - Database Config
// =============================
// Database settings
$host = "localhost"; // اگر XAMPP/WAMP استعمال کر رہے ہیں تو localhost رہنے دیں
$user = "root"; // default XAMPP user
$password = ""; // default XAMPP میں خالی ہوتا ہے
$dbname = "avatar_game"; // database name
// Create connection
$conn = new mysqli($host, $user, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("❌ Database Connection failed: " . $conn->connect_error);
}
// Character set UTF-8
$conn->set_charset("utf8");
?>-- ===========================
-- Avatar Game - Database SQL
-- ===========================
-- Database بنائیں
CREATE DATABASE IF NOT EXISTS avatar_game;
USE avatar_game;
-- Users table (login/register کے لیے)
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Scores table (leaderboard کے لیے)
CREATE TABLE IF NOT EXISTS scores (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
score INT NOT NULL,
level VARCHAR(50) DEFAULT 'default',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);<?php
include 'config.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = trim($_POST["username"]);
$email = trim($_POST["email"]);
$password = trim($_POST["password"]);
if (!empty($username) && !empty($email) && !empty($password)) {
// Password Hash
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Prepare SQL
$stmt = $conn-><?php
include 'config.php';
session_start();
if (!isset($_SESSION['user_id'])) {
echo "❌ User not logged in";
exit;
}
if (isset($_POST['score'])) {
$user_id = $_SESSION['user_id'];
$score = intval($_POST['score']);
$sql = "INSERT INTO scores (user_id, score) VALUES (?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ii", $user_id, $score);
if ($stmt->execute()) {
echo "✅ Score saved successfully!";
} else {
echo "❌ Error: " . $conn->error;
}
} else {
echo "❌ Score not received";
}
?><?php
include 'config.php';
$sql = "SELECT users.username, MAX(scores.score) AS best_score
FROM scores
JOIN users ON scores.user_id = users.id
GROUP BY users.id
ORDER BY best_score DESC
LIMIT 10";
$result = $conn->query($sql);
echo "<h2>🏆 Leaderboard</h2>";
echo "<table border='1' cellpadding='8'>";
echo "<tr><th>Rank</th><th>Username</th><th>Best Score</th></tr>";
$rank = 1;
while ($row = $result->fetch_assoc()) {
echo "<tr>
<td>{$rank}</td>
<td>{$row['username']}</td>
<td>{$row['best_score']}</td>
</tr>";
$rank++;
}
echo "</table>";
?>CREATE TABLE scores (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
score INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);<!DOCTYPE html>
<html>
<head>
<title>Mini Shooting Game</title>
<style>
body { margin:0; background:#222; overflow:hidden; }
#player {
width:40px; height:40px;
background:lime; position:absolute;
bottom:20px; left:50%;
}
.bullet {
width:5px; height:10px;
background:yellow; position:absolute;
}
.enemy {
width:40px; height:40px;
background:red; position:absolute;
top:0;
}
</style>
</head>
<body>
<div id="player"></div>
<script>
const player = document.getElementById("player");
let bullets = [];
let enemies = [];
// Player movement
document.addEventListener("keydown", e => {
let left = parseInt(player.style.left);
if(e.key === "ArrowLeft") player.style.left = (left-20) + "px";
if(e.key === "ArrowRight") player.style.left = (left+20) + "px";
if(e.key === " ") shoot();
});
function shoot(){
let bullet = document.createElement("div");
bullet.className = "bullet";
bullet.style.left = (player.offsetLeft+18) + "px";
bullet.style.top = (player.offsetTop-10) + "px";
document.body.appendChild(bullet);
bullets.push(bullet);
}
function spawnEnemy(){
let enemy = document.createElement("div");
enemy.className = "enemy";
enemy.style.left = Math.random() * (window.innerWidth-40) + "px";
document.body.appendChild(enemy);
enemies.push(enemy);
}
function gameLoop(){
// move bullets
bullets.forEach((b,i)=>{
b.style.top = (b.offsetTop-10) + "px";
if(b.offsetTop < 0) { b.remove(); bullets.splice(i,1); }
});
// move enemies
enemies.forEach((e,i)=>{
e.style.top = (e.offsetTop+3) + "px";
if(e.offsetTop > window.innerHeight) { e.remove(); enemies.splice(i,1); }
});
// collision check
bullets.forEach((b,bi)=>{
enemies.forEach((e,ei)=>{
if(b.offsetLeft < e.offsetLeft+40 &&
b.offsetLeft+5 > e.offsetLeft &&
b.offsetTop < e.offsetTop+40 &&
b.offsetTop+10 > e.offsetTop){
e.remove(); enemies.splice(ei,1);
b.remove(); bullets.splice(bi,1);
}
});
});
requestAnimationFrame(gameLoop);
}
setInterval(spawnEnemy, 2000);
gameLoop();
</script>
</body>
</html>
Gmail
ReplyDelete