-
Notifications
You must be signed in to change notification settings - Fork 88
Open
Description
<title>Minecraft 2D v2.0 - Bro Edition</title>
<style>
body { margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background: #87CEEB; font-family: 'Courier New', monospace; overflow: hidden; color: #333; }
#game-view { position: relative; width: 800px; height: 500px; background: #87CEEB; border: 6px solid #333; box-shadow: 0 10px 20px rgba(0,0,0,0.3); overflow: hidden; }
.block { position: absolute; width: 40px; height: 40px; box-sizing: border-box; cursor: pointer; transition: background 0.1s; }
.block:hover { border: 2px solid white; }
.grass { background: #5da130; border-bottom: 4px solid #4a8226; }
.dirt { background: #8b5a2b; }
.stone { background: #808080; border: 1px solid #666; }
.wood { background: #614126; border: 2px solid #4a311d; }
.leaf { background: #2d5a27; opacity: 0.9; }
#player { position: absolute; width: 32px; height: 48px; background: #e0ac69; border: 3px solid #333; z-index: 10; border-radius: 4px; transition: left 0.05s linear, top 0.05s linear; box-shadow: 0 4px 6px rgba(0,0,0,0.3); }
#player::after { content: "👕"; position: absolute; top: 10px; left: 4px; font-size: 24px; }
#ui-container { position: absolute; bottom: 10px; left: 10px; display: flex; gap: 10px; z-index: 20; pointer-events: none; }
.ui-box { background: rgba(0,0,0,0.6); color: white; padding: 10px; border-radius: 6px; pointer-events: auto; }
.hotbar { display: flex; gap: 5px; }
.hotbar-slot { width: 40px; height: 40px; border: 2px solid #999; display: flex; justify-content: center; align-items: center; cursor: pointer; background: rgba(255,255,255,0.1); }
.hotbar-slot.active { border-color: #ffeb3b; box-shadow: 0 0 10px #ffeb3b; }
.hotbar-slot:hover { background: rgba(255,255,255,0.2); }
</style>
<script>
const view = document.getElementById('game-view');
const player = document.getElementById('player');
const woodCountEl = document.getElementById('wood-count');
// Game State
let state = {
player: { x: 380, y: 192, vx: 0, vy: 0, onGround: false },
inventory: { wood: 0 },
selectedBlockType: 'dirt',
blocks: []
};
const CONFIG = { grid: 40, gravity: 0.8, jump: -15, speed: 6, width: 800, height: 500 };
function initWorld() {
// Tạo mặt đất
for (let x = 0; x < CONFIG.width; x += CONFIG.grid) {
for (let y = 320; y < CONFIG.height; y += CONFIG.grid) {
createBlock(x, y, y === 320 ? 'grass' : (y < 440 ? 'dirt' : 'stone'));
}
}
// Tạo cây
createTree(160, 160);
createTree(600, 160);
}
function createBlock(x, y, type) {
const block = document.createElement('div');
block.className = `block ${type}`;
block.style.left = x + 'px';
block.style.top = y + 'px';
// Đào khối (Click)
block.onmousedown = (e) => {
if (e.button === 0) { // Chuột trái
if (type === 'wood') {
state.inventory.wood++;
woodCountEl.innerText = state.inventory.wood;
}
block.remove();
state.blocks = state.blocks.filter(b => b.el !== block);
}
};
view.appendChild(block);
state.blocks.push({ x, y, type, el: block });
}
function createTree(x, yStart) {
for (let i = 0; i < 4; i++) createBlock(x, 320 - (i+1)*CONFIG.grid, 'wood');
for (let ix = -1; ix <= 1; ix++) {
for (let iy = -2; iy <= 0; iy++) {
if (ix === 0 && iy === 0) continue;
createBlock(x + ix*CONFIG.grid, 320 - 4*CONFIG.grid + iy*CONFIG.grid, 'leaf');
}
}
}
// Đặt Block (Chuột phải)
view.oncontextmenu = (e) => {
e.preventDefault();
const rect = view.getBoundingClientRect();
const x = Math.floor((e.clientX - rect.left) / CONFIG.grid) * CONFIG.grid;
const y = Math.floor((e.clientY - rect.top) / CONFIG.grid) * CONFIG.grid;
// Kiểm tra xem có khối nào ở đó chưa
if (!state.blocks.some(b => b.x === x && b.y === y)) {
createBlock(x, y, state.selectedBlockType);
}
};
function selectBlock(type, el) {
state.selectedBlockType = type;
document.querySelectorAll('.hotbar-slot').forEach(s => s.classList.remove('active'));
el.classList.add('active');
}
// Vòng lặp Game (Physics & Input)
function gameLoop() {
// Trọng lực
state.player.vy += CONFIG.gravity;
state.player.y += state.player.vy;
state.player.x += state.player.vx;
state.player.onGround = false;
// Xử lý va chạm
state.blocks.forEach(block => {
// Va chạm trục Y (rơi xuống)
if (state.player.x < block.x + CONFIG.grid && state.player.x + 32 > block.x &&
state.player.y < block.y + CONFIG.grid && state.player.y + 48 > block.y) {
if (state.player.vy > 0) { // Đang rơi xuống
state.player.y = block.y - 48;
state.player.vy = 0;
state.player.onGround = true;
} else if (state.player.vy < 0) { // Đang nhảy đụng đầu
state.player.y = block.y + CONFIG.grid;
state.player.vy = 0;
}
}
});
// Giới hạn biên
if (state.player.y > CONFIG.height - 48) { state.player.y = CONFIG.height - 48; state.player.vy = 0; state.player.onGround = true; }
if (state.player.x < 0) state.player.x = 0;
if (state.player.x > CONFIG.width - 32) state.player.x = CONFIG.width - 32;
// Cập nhật vị trí nhân vật
player.style.left = state.player.x + 'px';
player.style.top = state.player.y + 'px';
requestAnimationFrame(gameLoop);
}
// Điều khiển
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft' || e.key === 'a') state.player.vx = -CONFIG.speed;
if (e.key === 'ArrowRight' || e.key === 'd') state.player.vx = CONFIG.speed;
if ((e.key === 'ArrowUp' || e.key === 'w' || e.key === ' ') && state.player.onGround) {
state.player.vy = CONFIG.jump;
state.player.onGround = false;
}
});
document.addEventListener('keyup', (e) => {
if (e.key === 'ArrowLeft' || e.key === 'a' || e.key === 'ArrowRight' || e.key === 'd') state.player.vx = 0;
});
initWorld();
gameLoop();
</script>
Gỗ: 0
🟫
🪨
🪵
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels