Jeux généré par ia
généré par gpt 5.2 puyis retouche via gemini , faudra encore en faire un peu , mais j'ai la flemme ... (foutez le code dans un bloc note , renommez le en machin.html , lancez le et enjoy (ou pas)) edit : corriged
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<title>Mini Kong Tower</title>
<style>
:root {
--bg1: #0a0b18;
--bg2: #130a1e;
--ink: #ffe9c7;
--panel: #00000055;
}
* { box-sizing: border-box; margin: 0; padding: 0; user-select: none; -webkit-user-select: none; }
html, body { height: 100%; overflow: hidden; }
body {
display: flex; align-items: center; justify-content: center;
background: radial-gradient(1200px 800px at 20% 10%, #1f2a6b33 0%, transparent 60%),
radial-gradient(900px 700px at 80% 20%, #b31b5a33 0%, transparent 55%),
linear-gradient(135deg, var(--bg1), var(--bg2));
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
color: var(--ink);
}
#wrap {
display: flex; flex-direction: column; gap: 10px; align-items: center;
width: 100%; max-width: 920px;
}
canvas {
width: 100%;
height: auto;
aspect-ratio: 4/3;
max-height: 80vh;
border-radius: 14px;
border: 2px solid #ffcc66;
background: linear-gradient(#070816, #04040a);
box-shadow: 0 20px 60px #000000aa;
image-rendering: pixelated;
}
#hud {
width: 100%;
display: flex; gap: 12px; flex-wrap: wrap; justify-content: space-between; align-items: center;
padding: 10px 16px; border-radius: 12px; background: var(--panel);
border: 1px solid #ffffff22;
font-size: 14px;
backdrop-filter: blur(4px);
}
kbd {
display: inline-block; min-width: 22px; text-align: center;
padding: 2px 7px; margin: 0 2px;
border-radius: 6px;
background: linear-gradient(#2a2a2a, #161616);
border: 1px solid #666;
color: #fff;
font-family: monospace; font-weight: 700;
box-shadow: inset 0 1px 0 #ffffff22;
font-size: 0.9em;
}
.pill {
padding: 4px 10px; border-radius: 999px; background: #ffffff12; border: 1px solid #ffffff1f;
}
@media (hover: none) and (pointer: coarse) {
#controls-hint { display: none; }
}
</style>
</head>
<body>
<div id="wrap">
<canvas id="c" width="640" height="480"></canvas>
<div id="hud">
<div class="pill" id="controls-hint">
<strong>Contrôles</strong> :
<kbd>←</kbd><kbd>→</kbd> bouger,
<kbd>↑</kbd><kbd>↓</kbd> échelles,
<kbd>Espace</kbd> sauter,
<kbd>Entrée</kbd> jouer
</div>
<div class="pill" id="stats">Score: 00000 · Vies: 3 · Niveau: 1</div>
</div>
</div>
<script>
(() => {
const canvas = document.getElementById("c" );
const ctx = canvas.getContext("2d", { alpha: false });
const W = 640;
const H = 480;
const COL = {
red: "#c43e5c", red2: "#ff8fa3",
cyan: "#62d7ff", cyan2: "#2aa7d3",
gold: "#ffd36b", gold2: "#ffb700",
ink: "#ffe9c7",
ladder: "#62d7ff", ladderRung: "#2aa7d3",
barrel: "#c2843a", barrelBorder: "#f5d19b",
barrelRed: "#e62e2e", barrelRedBorder: "#ff8888",
kong: "#ff5e3a", kongStroke: "#ffb199",
princess: "#ffc0f5",
hammerHead: "#ddd", hammerHandle: "#8b5a2b"
};
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
const aabb = (a, b) => (a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y);
const keys = Object.create(null);
window.addEventListener("keydown", (e) => {
if (["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", " "].includes(e.key)) {
e.preventDefault();
}
keys[e.key] = true;
if (e.key === "Enter" ) keys.__enterTap = true;
}, { passive: false });
window.addEventListener("keyup", (e) => keys[e.key] = false);
const touchState = { left: false, right: false, up: false, down: false, jump: false };
canvas.addEventListener("touchstart", handleTouch, { passive: false });
canvas.addEventListener("touchmove", handleTouch, { passive: false });
canvas.addEventListener("touchend", (e) => {
e.preventDefault();
if(e.touches.length === 0) {
touchState.left = touchState.right = touchState.up = touchState.down = touchState.jump = false;
}
});
function handleTouch(e) {
e.preventDefault();
const rect = canvas.getBoundingClientRect();
touchState.left = touchState.right = touchState.up = touchState.down = touchState.jump = false;
if(state !== "playing" ) {
if(e.type === "touchstart" ) keys.__enterTap = true;
return;
}
for (let i = 0; i < e.touches.length; i++) {
const t = e.touches[i];
const x = (t.clientX - rect.left) / rect.width * W;
const y = (t.clientY - rect.top) / rect.height * H;
if (x < W * 0.25) touchState.left = true;
else if (x < W * 0.5) touchState.right = true;
if (y < H * 0.3) touchState.up = true;
else if (y > H * 0.7 && x < W * 0.5) touchState.down = true;
if (x > W * 0.6) touchState.jump = true;
}
}
// --- Monde Zig-Zag ---
const platforms = [
{x: 0, y: H-44, w: W, h: 10, slope: 0.0},
{x: 0, y: H-120, w: W-80, h: 10, slope: 0.06},
{x: 80, y: H-196, w: W-80, h: 10, slope: -0.06},
{x: 0, y: H-272, w: W-80, h: 10, slope: 0.06},
{x: 80, y: H-350, w: W-80, h: 10, slope: -0.06},
];
// Ajustement des échelles : yTop ajusté pour dépasser ou coller au sol incliné
const ladders = [
{x: W-120, yTop: H-365, yBot: H-272, w: 22}, // Haut
{x: 120, yTop: H-285, yBot: H-196, w: 22},
{x: W-120, yTop: H-210, yBot: H-120, w: 22},
{x: 120, yTop: H-135, yBot: H-44, w: 22}, // Bas
{x: 320, yTop: H-365, yBot: H-272, w: 22},
];
const topPlat = {x: W/2 - 150, y: H-418, w: 300, h: 10, slope: 0};
ladders.push({x: W/2 - 80, yTop: H-418, yBot: H-350, w: 22});
function platformYAt(p, xMid) {
const t = clamp((xMid - p.x) / p.w, 0, 1);
return p.y + (t - 0.5) * p.slope * p.w;
}
const player = {
x: 40, y: H-90, w: 20, h: 28,
vx: 0, vy: 0,
onGround: false, climbing: false, facing: 1,
lives: 3, inv: 0, hasHammer: false, hammerTimer: 0
};
const hammer = { x: 0, y: 0, w: 20, h: 20, active: false };
const kong = { x: topPlat.x + 34, y: topPlat.y - 48, w: 52, h: 46 };
const princess = { x: topPlat.x + topPlat.w - 64, y: topPlat.y - 30, w: 18, h: 26 };
let barrels = [];
let particles = [];
let score = 0;
let level = 1;
let state = "title";
const GRAV = 1800;
const MOVE = 210;
const JUMP = 500;
const CLIMB = 160;
const MAXVX = 320;
let spawnT = 0;
function spawnInterval(){ return Math.max(0.6, 2.0 - level * 0.18); }
function spawnHammer() {
const pIdx = 1 + Math.floor(Math.random() * (platforms.length - 2));
const p = platforms[pIdx];
hammer.active = true;
hammer.w = 16; hammer.h = 16;
hammer.x = p.x + 40 + Math.random() * (p.w - 80);
hammer.y = platformYAt(p, hammer.x + 8) - 20;
}
function reset(full) {
barrels = [];
particles = [];
spawnT = 0;
player.x = 40; player.y = H-90;
player.vx = 0; player.vy = 0;
player.onGround = false; player.climbing = false;
player.inv = 2.0;
player.hasHammer = false;
player.hammerTimer = 0;
spawnHammer();
if (full) {
score = 0; level = 1; player.lives = 3;
}
}
function start() {
reset(true);
state = "playing";
}
function nextLevel() {
level++;
reset(false);
state = "playing";
}
function loseLife() {
player.lives--;
if (player.lives < 0) {
state = "gameover";
return;
}
reset(false);
}
function ladderAtPlayer() {
const cx = player.x + player.w / 2;
const cy = player.y + player.h / 2;
for (const L of ladders) {
// Zone de détection étendue verticalement
if (cx >= L.x - 8 && cx <= L.x + L.w + 8 && cy >= L.yTop - 18 && cy <= L.yBot + 8) return L;
}
return null;
}
function addParticles(x, y, color) {
for(let i=0; i<8; i++) {
particles.push({
x: x, y: y,
vx: (Math.random() - 0.5) * 300,
vy: (Math.random() - 1) * 300,
life: 1.0, color: color, size: 3 + Math.random()*3
});
}
}
function update(dt) {
if (keys.__enterTap) {
keys.__enterTap = false;
if (state === "title" ) start();
else if (state === "gameover" ) start();
else if (state === "win" ) nextLevel();
}
if (state !== "playing" ) return;
const left = keys["ArrowLeft"] || touchState.left;
const right = keys["ArrowRight"] || touchState.right;
const up = keys["ArrowUp"] || touchState.up;
const down = keys["ArrowDown"] || touchState.down;
const jump = keys[" "] || touchState.jump;
const L = ladderAtPlayer();
// Snap échelle
if (L && (up || down)) {
if (!player.climbing) {
player.x = L.x + (L.w - player.w) / 2;
player.climbing = true;
}
}
if (!L) player.climbing = false;
if (player.climbing && L) {
player.vx = 0;
player.vy = 0;
if (up) player.y -= CLIMB * dt;
if (down) player.y += CLIMB * dt;
player.x += ((L.x + L.w/2) - (player.x + player.w/2)) * 0.5;
// Clamp qui permet de dépasser un peu le haut (-4px) pour monter sur le sol
player.y = clamp(player.y, L.yTop - player.h - 4, L.yBot - player.h);
if (left || right) player.climbing = false;
} else {
let speed = MOVE;
if (player.hasHammer) speed = MOVE * 1.1;
// Contrôle "Sec" (Pas d'inertie)
if (left && !right) {
player.vx = -speed;
player.facing = -1;
}
else if (right && !left) {
player.vx = speed;
player.facing = 1;
}
else {
// Arrêt immédiat ! Fini le savon
player.vx = 0;
}
player.vx = clamp(player.vx, -MAXVX, MAXVX);
if (jump && player.onGround && !keys.__jumpHeld) {
player.vy = -JUMP;
player.onGround = false;
keys.__jumpHeld = true;
}
if (!jump) keys.__jumpHeld = false;
player.vy += GRAV * dt;
}
player.x += player.vx * dt;
player.y += player.vy * dt;
player.x = clamp(player.x, 8, W - 8 - player.w);
// Collisions Plateformes
player.onGround = false;
const allPlats = [...platforms, topPlat];
for (const p of allPlats) {
const xMid = player.x + player.w/2;
if (xMid < p.x || xMid > p.x + p.w) continue;
const py = platformYAt(p, xMid);
const feet = player.y + player.h;
const prevFeet = feet - player.vy * dt;
// Tolérance +4 pour attraper le sol après une échelle
if (prevFeet <= py + 4 && feet >= py && player.vy >= 0 && !player.climbing) {
player.y = py - player.h;
player.vy = 0;
player.onGround = true;
// NOTE: On ne rajoute plus la vélocité de la pente au joueur (ça glisse trop)
}
}
if (player.y > H + 60) loseLife();
if (player.hasHammer) {
player.hammerTimer -= dt;
if (player.hammerTimer <= 0) player.hasHammer = false;
} else if (hammer.active) {
if (aabb(player, hammer)) {
hammer.active = false;
player.hasHammer = true;
player.hammerTimer = 9.0;
score += 500;
addParticles(player.x, player.y, COL.gold);
}
}
if (player.inv > 0) player.inv -= dt;
// --- Barils ---
spawnT += dt;
if (spawnT >= spawnInterval()) {
spawnT = 0;
const dir = (Math.random() < 0.5) ? -1 : 1;
let type = "normal";
let bVx = 150 + level * 18;
if (level >= 2 && Math.random() < 0.25) {
type = "red";
bVx *= 1.5;
}
barrels.push({
x: kong.x + kong.w * 0.35, y: kong.y + kong.h * 0.7,
w: 18, h: 18,
vx: bVx * dir, vy: 0,
type: type
});
}
for (let i = barrels.length - 1; i >= 0; i--) {
const b = barrels[i];
b.vy += (GRAV * 0.9) * dt;
if (b.vy > 650) b.vy = 650;
b.x += b.vx * dt;
b.y += b.vy * dt;
if (b.x < 0) { b.x = 0; b.vx = Math.abs(b.vx); }
if (b.x + b.w > W) { b.x = W - b.w; b.vx = -Math.abs(b.vx); }
for (const p of allPlats) {
const xMid = b.x + b.w/2;
if (xMid < p.x || xMid > p.x + p.w) continue;
const py = platformYAt(p, xMid);
const feet = b.y + b.h;
const prevFeet = feet - b.vy * dt;
if (prevFeet <= py + 14 && feet >= py && b.vy >= 0) {
b.y = py - b.h;
if (b.type === "red" ) b.vy = -250; else b.vy = 0;
if (p.slope !== 0) b.vx += (p.slope * 280) * dt;
b.vx = clamp(b.vx, -450, 450);
}
}
if (b.y > H + 80) { barrels.splice(i, 1); score += 100; continue; }
const hit = {x: b.x + 2, y: b.y + 2, w: b.w - 4, h: b.h - 4};
if (aabb(player, hit)) {
if (player.hasHammer) {
addParticles(b.x, b.y, b.type === "red" ? COL.red : COL.barrel);
barrels.splice(i, 1);
score += 300;
} else if (player.inv <= 0) {
loseLife();
break;
}
}
}
for (let i = particles.length - 1; i >= 0; i--) {
let p = particles[i];
p.x += p.vx * dt;
p.y += p.vy * dt;
p.vy += GRAV * dt;
p.life -= dt * 2;
if(p.life <= 0) particles.splice(i, 1);
}
if (aabb(player, princess)) {
score += 1500 + level * 500;
state = "win";
}
}
function draw() {
const g = ctx.createLinearGradient(0, 0, 0, H);
g.addColorStop(0, "#07081a" );
g.addColorStop(1, "#03030a" );
ctx.fillStyle = g;
ctx.fillRect(0, 0, W, H);
ctx.fillStyle = "#ffffff18";
for (let i = 0; i < 90; i++) {
const x = (i * 97) % W;
const y = (i * 53) % Math.floor(H * 0.55);
ctx.fillRect(x, y, (i % 3 ? 1 : 2), (i % 3 ? 1 : 2));
}
function drawPlat(p) {
const yL = platformYAt(p, p.x);
const yR = platformYAt(p, p.x + p.w);
ctx.fillStyle = COL.red;
ctx.beginPath();
ctx.moveTo(p.x, yL);
ctx.lineTo(p.x + p.w, yR);
ctx.lineTo(p.x + p.w, yR + p.h);
ctx.lineTo(p.x, yL + p.h);
ctx.closePath();
ctx.fill();
ctx.strokeStyle = COL.red2;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(p.x, yL);
ctx.lineTo(p.x + p.w, yR);
ctx.stroke();
ctx.lineWidth = 1;
ctx.strokeStyle = "#00000055";
for (let x = p.x + 18; x < p.x + p.w; x += 28) {
const y = platformYAt(p, x);
ctx.beginPath();
ctx.moveTo(x, y + p.h);
ctx.lineTo(x, y + p.h + 10);
ctx.stroke();
}
}
for (const p of platforms) drawPlat(p);
drawPlat(topPlat);
for (const L of ladders) {
ctx.strokeStyle = COL.ladder;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(L.x, L.yTop);
ctx.lineTo(L.x, L.yBot);
ctx.moveTo(L.x + L.w, L.yTop);
ctx.lineTo(L.x + L.w, L.yBot);
ctx.stroke();
ctx.strokeStyle = COL.ladderRung;
ctx.lineWidth = 2;
for (let y = L.yTop + 10; y < L.yBot; y += 12) {
ctx.beginPath();
ctx.moveTo(L.x, y);
ctx.lineTo(L.x + L.w, y);
ctx.stroke();
}
}
if (hammer.active) {
ctx.save();
ctx.translate(hammer.x + hammer.w/2, hammer.y + hammer.h/2 + Math.sin(performance.now()/200)*3);
ctx.fillStyle = COL.hammerHandle;
ctx.fillRect(-2, 0, 4, 10);
ctx.fillStyle = COL.hammerHead;
ctx.fillRect(-6, -6, 12, 8);
ctx.strokeStyle = "#fff";
ctx.lineWidth = 1;
ctx.strokeRect(-6, -6, 12, 8);
ctx.restore();
}
ctx.lineWidth = 2;
ctx.fillStyle = COL.kong;
ctx.strokeStyle = COL.kongStroke;
ctx.beginPath();
roundRect(ctx, kong.x, kong.y, kong.w, kong.h, 8);
ctx.fill(); ctx.stroke();
ctx.fillStyle = COL.ink;
ctx.beginPath();
roundRect(ctx, kong.x + 12, kong.y + 14, kong.w - 24, kong.h - 26, 6);
ctx.fill();
ctx.fillStyle = "#222";
ctx.fillRect(kong.x + 18, kong.y + 22, 5, 5);
ctx.fillRect(kong.x + kong.w - 23, kong.y + 22, 5, 5);
ctx.fillStyle = COL.princess;
ctx.strokeStyle = "#fff0ff";
ctx.beginPath();
roundRect(ctx, princess.x, princess.y + 6, princess.w, princess.h - 6, 5);
ctx.fill(); ctx.stroke();
ctx.fillStyle = COL.ink;
ctx.beginPath();
roundRect(ctx, princess.x + 2, princess.y, princess.w - 4, 10, 4);
ctx.fill();
const t = performance.now() / 300;
const bob = Math.sin(t) * 3;
ctx.save();
ctx.translate(princess.x + princess.w / 2, princess.y - 10 + bob);
ctx.fillStyle = "#ff4f8b";
ctx.beginPath();
ctx.moveTo(0, 6);
ctx.bezierCurveTo(-6, 0, -5, -6, 0, -4);
ctx.bezierCurveTo(5, -6, 6, 0, 0, 6);
ctx.fill();
ctx.restore();
for (const b of barrels) {
ctx.lineWidth = 1.5;
const isRed = b.type === "red";
ctx.fillStyle = isRed ? COL.barrelRed : COL.barrel;
ctx.strokeStyle = isRed ? COL.barrelRedBorder : COL.barrelBorder;
const rot = ((performance.now() / (isRed?150:220)) + b.x / 60) % (Math.PI * 2);
ctx.save();
ctx.translate(b.x + b.w / 2, b.y + b.h / 2);
ctx.rotate(Math.sin(rot) * 0.35);
roundRect(ctx, -b.w / 2, -b.h / 2, b.w, b.h, 5);
ctx.fill(); ctx.stroke();
ctx.fillStyle = ctx.strokeStyle;
ctx.fillRect(-b.w / 2, -2, b.w, 4);
if(isRed) {
ctx.fillStyle = "#fff";
ctx.font = "bold 10px sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("!", 0, 1);
}
ctx.restore();
}
for(const p of particles) {
ctx.fillStyle = p.color;
ctx.globalAlpha = p.life;
ctx.fillRect(p.x, p.y, p.size, p.size);
ctx.globalAlpha = 1.0;
}
if (!(player.inv > 0 && Math.floor(performance.now() / 80) % 2 === 0)) {
if (player.hasHammer) {
ctx.save();
const swing = Math.sin(performance.now() / 50) * 1.5;
ctx.translate(player.x + player.w/2, player.y + player.h/2);
ctx.rotate(swing);
ctx.fillStyle = COL.hammerHandle;
ctx.fillRect(10, -10, 4, 14);
ctx.fillStyle = COL.hammerHead;
ctx.fillRect(6, -16, 12, 10);
ctx.restore();
}
const pg = ctx.createLinearGradient(player.x, player.y, player.x, player.y + player.h);
pg.addColorStop(0, COL.gold);
pg.addColorStop(1, COL.gold2);
ctx.fillStyle = pg;
ctx.strokeStyle = "#b38400";
ctx.lineWidth = 1.5;
roundRect(ctx, player.x, player.y + 8, player.w, player.h - 8, 5);
ctx.fill(); ctx.stroke();
ctx.fillStyle = COL.ink;
roundRect(ctx, player.x + 3, player.y, player.w - 6, 10, 4);
ctx.fill();
ctx.fillStyle = player.hasHammer ? "#fff" : "#ff6b6b";
roundRect(ctx, player.x + 2, player.y, player.w - 4, 6, 4);
ctx.fill();
ctx.fillStyle = "#222";
const eye = (player.facing >= 0) ? 3 : -3;
ctx.fillRect(player.x + player.w / 2 + eye - 2, player.y + 4, 2, 2);
}
ctx.lineWidth = 1;
if (state === "title" ) {
panel("Mini Kong Tower", "Nouveau: Marteau & Barils Rouges !", "Appuie sur ENTREE" );
} else if (state === "win" ) {
panel("Niveau terminé !", `Score +${1500 + level * 500}`, "ENTREE pour continuer" );
} else if (state === "gameover" ) {
panel("Game Over", `Score final: ${score}`, "ENTREE pour rejouer" );
}
const elStats = document.getElementById("stats" );
let txt = `Score: ${String(score).padStart(5, "0" )} · Vies: ${Math.max(0, player.lives)} · Niv: ${level}`;
if(player.hasHammer) txt += ` · Marteau: ${Math.ceil(player.hammerTimer)}s`;
if (elStats.textContent !== txt) elStats.textContent = txt;
}
function panel(title, line, hint) {
ctx.fillStyle = "rgba(0,0,0,0.65)";
ctx.fillRect(0, 0, W, H);
ctx.textAlign = "center";
ctx.fillStyle = "#ffe4b5";
ctx.font = "700 32px system-ui, Segoe UI";
ctx.textBaseline = "middle";
ctx.fillText(title, W / 2, H / 2 - 50);
ctx.fillStyle = "#ffeedd";
ctx.font = "18px system-ui, Segoe UI";
ctx.fillText(line, W / 2, H / 2 - 10);
const bw = 220, bh = 40;
const bx = W/2 - bw/2, by = H/2 + 25;
ctx.fillStyle = COL.red;
roundRect(ctx, bx, by, bw, bh, 20);
ctx.fill();
ctx.strokeStyle = "#fff"; ctx.lineWidth = 2; ctx.stroke();
ctx.fillStyle = "#fff";
ctx.font = "700 16px system-ui, Segoe UI";
ctx.fillText(hint, W / 2, by + bh/2);
ctx.textBaseline = "alphabetic";
}
function roundRect(ctx, x, y, w, h, r) {
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x + w, y, x + w, y + h, r);
ctx.arcTo(x + w, y + h, x, y + h, r);
ctx.arcTo(x, y + h, x, y, r);
ctx.arcTo(x, y, x + w, y, r);
ctx.closePath();
}
let last = performance.now();
function frame(now) {
const dt = Math.min(0.05, (now - last) / 1000);
last = now;
update(dt);
draw();
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
})();
</script>
</body>
</html>
---------------
...survivre à ses Medecins...