<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple Minecraft Clone</title>
<style>
body {
margin: 0;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
#gameCanvas {
display: none;
}
.menu {
text-align: center;
}
.menu button {
margin: 10px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="menu" id="mainMenu">
<h1>Simple Minecraft Clone</h1>
<button οnclick="startGame()">开始游戏</button>
<button οnclick="openSettings()">设置</button>
<button οnclick="exitGame()">退出</button>
</div>
<canvas id="gameCanvas"></canvas>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const blockSize = 20;
let playerX = canvas.width / 2;
let playerY = canvas.height - blockSize * 2;
let inGame = false;
const terrain = [];
class Player {
constructor(x, y) {
this.x = x;
this.y = y;
this.width = blockSize;
this.height = blockSize;
this.inventory = [];
this.health = 100;
this.hunger = 100;
}
draw() {
ctx.fillStyle = 'green';
ctx.fillRect(this.x, this.y, this.width, this.height);
}
move(dx, dy) {
this.x += dx * blockSize;
this.y += dy * blockSize;
}
addItem(item) {
this.inventory.push(item);
}
removeItem(index) {
this.inventory.splice(index, 1);
}
updateHUD() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(10, 10, canvas.width - 20, 100);
ctx.fillStyle = 'white';
ctx.font = '16px Arial';
ctx.fillText('生命值: ' + this.health, 20, 30);
ctx.fillText('饥饿度: ' + this.hunger, 20, 50);
}
}
class Enemy {
constructor(x, y) {
this.x = x;
this.y = y;
this.width = blockSize;
this.height = blockSize;
this.speed = 1;
}
draw() {
ctx.fillStyle = 'red';
ctx.fillRect(this.x, this.y, this.width, this.height);
}
move(player) {
const dx = this.x - player.x;
const dy = this.y - player.y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance > this.speed) {
const angle = Math.atan2(dy, dx);
this.x -= this.speed * Math.cos(angle);
this.y -= this.speed * Math.sin(angle);
}
if (terrain[Math.floor(this.x / blockSize)][Math.floor(this.y / blockSize)] === 1) {
this.x += this.speed;
}
}
}
const player = new Player(playerX, playerY);
const enemy = new Enemy(Math.random() * canvas.width, Math.random() * canvas.height);
function generateTerrain() {
for (let x = 0; x < canvas.width; x += blockSize) {
terrain[x] = [];
for (let y = 0; y < canvas.height; y += blockSize) {
const noiseValue = Math.random();
if (noiseValue > 0.8) {
terrain[x][y] = 1;
} else if (noiseValue > 0.6) {
terrain[x][y] = 2;
} else {
terrain[x][y] = 0;
}
}
}
}
function drawBlocks() {
for (let x = 0; x < canvas.width; x += blockSize) {
for (let y = 0; y < canvas.height; y += blockSize) {
if (terrain[x][y] === 1) {
ctx.fillStyle = 'gray';
ctx.fillRect(x, y, blockSize, blockSize);
} else if (terrain[x][y] === 2) {
ctx.fillStyle = 'brown';
ctx.fillRect(x, y, blockSize, blockSize);
}
}
}
}
function collectResource(x, y) {
if (terrain[x][y] === 2) {
terrain[x][y] = 0;
player.addItem('resource');
}
}
function buildStructure(x, y, type) {
if (player.inventory.includes(type)) {
terrain[x][y] = type;
player.removeItem(player.inventory.indexOf(type));
}
}
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBlocks();
player.draw();
enemy.draw();
enemy.move(player);
player.updateHUD();
requestAnimationFrame(gameLoop);
}
document.addEventListener('keydown', (event) => {
if (!inGame) return;
switch (event.key) {
case 'ArrowUp':
if (terrain[Math.floor(player.x / blockSize)][Math.floor((player.y - blockSize) / blockSize)] !== 1) {
player.move(0, -1);
}
break;
case 'ArrowDown':
if (terrain[Math.floor(player.x / blockSize)][Math.floor((player.y + blockSize * 2) / blockSize)] !== 1) {
player.move(0, 1);
}
break;
case 'ArrowLeft':
if (terrain[Math.floor((player.x - blockSize) / blockSize)][Math.floor(player.y / blockSize)] !== 1) {
player.move(-1, 0);
}
break;
case 'ArrowRight':
if (terrain[Math.floor((player.x + blockSize * 2) / blockSize)][Math.floor(player.y / blockSize)] !== 1) {
player.move(1, 0);
}
break;
case ' ': // 空格键拾取物品或采集资源
if (terrain[Math.floor(player.x / blockSize)][Math.floor(player.y / blockSize)] === 1) {
terrain[Math.floor(player.x / blockSize)][Math.floor(player.y / blockSize)] = 0;
player.addItem('block');
} else if (terrain[Math.floor(player.x / blockSize)][Math.floor(player.y / blockSize)] === 2) {
collectResource(Math.floor(player.x / blockSize), Math.floor(player.y / blockSize));
}
break;
case 'b': // B键建造
buildStructure(Math.floor(player.x / blockSize), Math.floor(player.y / blockSize), 'wall');
break;
}
});
function startGame() {
inGame = true;
document.getElementById('mainMenu').style.display = 'none';
canvas.style.display = 'block';
generateTerrain();
gameLoop();
}
function openSettings() {
alert('设置');
}
function exitGame() {
inGame = false;
document.getElementById('mainMenu').style.display = 'flex';
canvas.style.display = 'none';
}
function showInventory() {
alert('背包内容: ' + player.inventory.join(', '));
}
function updateGameInterface() {
player.health -= 0.1;
player.hunger -= 0.1;
if (player.health <= 0) {
alert('游戏结束');
exitGame();
}
}
// 默认显示主菜单
document.getElementById('mainMenu').style.display = 'flex';
document.getElementById('mainMenu').innerHTML += '<button οnclick="showInventory()">查看背包</button>';
document.getElementById('mainMenu').innerHTML += '<button οnclick="updateGameInterface()">更新游戏界面</button>';
</script>
</body>
</html>