<!
DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mincraft 2D</title>
<style>
body { margin: 0; overflow: hidden; user-select: none; }
canvas { display: block; }
#controls {
position: absolute;
bottom: 10px;
left: 10px;
display: grid;
grid-template-areas:
". up ."
"left down right";
gap: 10px;
}
.control-btn {
width: 50px;
height: 50px;
background: rgba(0, 0, 0, 0.7);
border: 2px solid #fff;
color: white;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
font-size: 20px;
cursor: pointer;
}
#up { grid-area: up; }
#left { grid-area: left; }
#down { grid-area: down; }
#right { grid-area: right; }
#inventory {
position: absolute;
bottom: 10px;
left: 200px;
display: flex;
background: rgba(0, 0, 0, 0.7);
padding: 5px;
border-radius: 5px;
}
.inventory-slot {
width: 30px;
height: 30px;
margin: 3px;
background: rgba(255, 255, 255, 0.2);
border: 2px solid #fff;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 12px;
}
#stats {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: Arial, sans-serif;
display: flex;
align-items: center;
gap: 10px;
}
.heart {
width: 20px;
height: 20px;
background: red;
clip-path: polygon(
50% 0%,
70% 20%,
100% 30%,
80% 60%,
90% 100%,
50% 80%,
10% 100%,
20% 60%,
0% 30%,
30% 20%
);
}
</style>
</head>
<body>
<canvas id="gameCanvas"></canvas>
<div id="controls">
<button id="up" class="control-btn">↑</button>
<button id="left" class="control-btn">←</button>
<button id="down" class="control-btn">↓</button>
<button id="right" class="control-btn">→</button>
</div>
<div id="inventory">
<div class="inventory-slot">0</div>
<div class="inventory-slot">0</div>
<div class="inventory-slot">0</div>
<div class="inventory-slot">0</div>
<div class="inventory-slot">0</div>
</div>
<div id="stats">
<p>Vie: <span id="health">3</span></p>
<p>Nourriture: <span id="food">100</span></p>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Joueur
const player = {
x: canvas.width / 2,
y: canvas.height / 2,
width: 40,
height: 60,
speed: 5,
velocityY: 0,
gravity: 0.5,
onGround: false,
health: 3,
food: 100,
inventory: [0, 0, 0, 0, 0],
frame: 0,
direction: 'right'
};
// Sprite du joueur (lien direct vers une image)
const playerSprite = new Image();
playerSprite.src = 'https://raw.githubusercontent.com/your-repo/your-
image.png'; // Remplace par ton sprite sheet
// Blocs
const blocks = [];
const blockSize = 40;
// Types de blocs
const blockTypes = {
grass: '#2E8B57',
dirt: '#8B4513',
stone: '#808080',
sand: '#F4A460',
water: '#1E90FF',
tree: '#006400',
wood: '#8B4513',
leaf: '#228B22'
};
// Génération aléatoire du relief (montagnes, lacs, arbres)
function generateTerrain() {
const groundLevel = 400;
const amplitude = 100; // Variation du relief
const frequency = 0.02; // Fréquence du relief
for (let x = 0; x <= canvas.width * 2; x += blockSize) {
const y = groundLevel + Math.sin(x * frequency) * amplitude +
Math.cos(x * frequency * 0.5) * 50;
blocks.push({ x, y: Math.floor(y / blockSize) * blockSize, width:
blockSize, height: blockSize, type: 'grass' });
// Ajouter de la terre et de la pierre en dessous
for (let dy = y + blockSize; dy <= canvas.height; dy += blockSize)
{
const depth = (dy - y) / blockSize;
if (depth < 3) {
blocks.push({ x, y: dy, width: blockSize, height:
blockSize, type: 'dirt' });
} else {
blocks.push({ x, y: dy, width: blockSize, height:
blockSize, type: 'stone' });
}
}
// Ajouter des lacs
if (Math.random() < 0.1) {
for (let dx = x; dx < x + blockSize * 5; dx += blockSize) {
blocks.push({ x: dx, y: y + blockSize, width: blockSize,
height: blockSize, type: 'water' });
}
}
// Ajouter des arbres
if (Math.random() < 0.2) {
const treeX = x;
const treeY = y - blockSize * 2;
blocks.push({ x: treeX, y: treeY, width: blockSize, height:
blockSize * 3, type: 'tree' });
blocks.push({ x: treeX, y: treeY - blockSize, width: blockSize,
height: blockSize, type: 'leaf' });
}
}
}
generateTerrain();
// Dessiner le joueur
function drawPlayer() {
ctx.save();
if (player.direction === 'left') {
ctx.scale(-1, 1);
ctx.drawImage(playerSprite, player.x - player.width, player.y,
player.width, player.height);
} else {
ctx.drawImage(playerSprite, player.x, player.y, player.width,
player.height);
}
ctx.restore();
}
// Dessiner les blocs
function drawBlocks() {
blocks.forEach(block => {
ctx.fillStyle = blockTypes[block.type];
ctx.fillRect(block.x, block.y, block.width, block.height);
});
}
// Appliquer la gravité
function applyGravity() {
player.velocityY += player.gravity;
player.y += player.velocityY;
// Collision avec les blocs
blocks.forEach(block => {
if (player.x < block.x + block.width &&
player.x + player.width > block.x &&
player.y < block.y + block.height &&
player.y + player.height > block.y) {
player.velocityY = 0;
player.y = block.y - player.height;
player.onGround = true;
}
});
// Collision avec le sol
if (player.y + player.height > canvas.height) {
player.y = canvas.height - player.height;
player.velocityY = 0;
player.onGround = true;
}
}
// Mettre à jour l'inventaire
function updateInventoryUI() {
const inventorySlots = document.querySelectorAll('.inventory-slot');
inventorySlots.forEach((slot, index) => {
slot.textContent = player.inventory[index] || 0;
});
}
// Mettre à jour les stats
function updateStats() {
document.getElementById('health').textContent = player.health;
document.getElementById('food').textContent = player.food;
}
// Boucle de jeu
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
applyGravity();
drawBlocks();
drawPlayer();
updateStats();
requestAnimationFrame(gameLoop);
}
// Contrôles
let moveLeft = false;
let moveRight = false;
document.getElementById('up').addEventListener('click', () => {
if (player.onGround) {
player.velocityY = -10;
player.onGround = false;
}
});
document.getElementById('left').addEventListener('mousedown', () => {
moveLeft = true;
player.direction = 'left';
});
document.getElementById('left').addEventListener('mouseup', () => {
moveLeft = false;
});
document.getElementById('right').addEventListener('mousedown', () => {
moveRight = true;
player.direction = 'right';
});
document.getElementById('right').addEventListener('mouseup', () => {
moveRight = false;
});
// Déplacement continu
function handleMovement() {
if (moveLeft) {
player.x -= player.speed;
}
if (moveRight) {
player.x += player.speed;
}
}
// Casser des blocs au clic
canvas.addEventListener('click', (e) => {
const mouseX = e.clientX;
const mouseY = e.clientY;
blocks.forEach((block, index) => {
if (mouseX > block.x && mouseX < block.x + block.width &&
mouseY > block.y && mouseY < block.y + block.height) {
blocks.splice(index, 1); // Casser le bloc
addToInventory(block.type); // Ajouter à l'inventaire
}
});
});
// Ajouter un bloc à l'inventaire
function addToInventory(item) {
const index = player.inventory.findIndex(slot => slot === 0);
if (index !== -1) {
player.inventory[index] = item;
updateInventoryUI();
}
}
// Placer un bloc
canvas.addEventListener('contextmenu', (e) => {
e.preventDefault();
const mouseX = e.clientX;
const mouseY = e.clientY;
const blockX = Math.floor(mouseX / blockSize) * blockSize;
const blockY = Math.floor(mouseY / blockSize) * blockSize;
const index = player.inventory.findIndex(slot => slot !== 0);
if (index !== -1) {
const blockType = player.inventory[index];
blocks.push({ x: blockX, y: blockY, width: blockSize, height:
blockSize, type: blockType });
player.inventory[index] = 0;
updateInventoryUI();
}
});
// Démarrer la boucle de jeu
gameLoop();
setInterval(handleMovement, 16); // 60 FPS
</script>
</body>
</html>