2D MC,半成品😅(剩下的不会了)
2026-01-28 11:56:36
发布于:广东
2D Minecraft
#include <iostream>
#include <vector>
#include <string>
#include <conio.h>
#include <windows.h>
#include <ctime>
using namespace std;
// ==================== 游戏配置 ====================
const int BLOCK_SIZE = 4; // 每个方块占用的字符数
const int WORLD_WIDTH = 120; // 世界宽度
const int WORLD_HEIGHT = 50; // 世界高度
// 屏幕大小(字符单位)
const int SCREEN_WIDTH = 80;
const int SCREEN_HEIGHT = 24;
// ==================== 方块类型 ====================
enum BlockType {
AIR,
GRASS,
DIRT,
STONE,
WOOD,
LEAF,
PLAYER
};
// 方块属性
struct BlockInfo {
char symbol;
int color; // 0-15
};
// ==================== 玩家结构 ====================
struct Player {
float x, y; // 位置
float vx, vy; // 速度
int width; // 宽度(字符)
int height; // 高度(字符)
bool onGround; // 是否在地面上
BlockType selectedBlock; // 选中的方块
};
// ==================== 全局变量 ====================
vector<vector<BlockType>> world(WORLD_HEIGHT, vector<BlockType>(WORLD_WIDTH, AIR));
Player player;
// ==================== 控制台工具函数 ====================
void gotoxy(int x, int y) {
COORD coord = {x, y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void setColor(int color) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}
void hideCursor() {
CONSOLE_CURSOR_INFO info = {1, FALSE};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
}
void clearScreen() {
system("cls");
}
// ==================== 方块信息 ====================
BlockInfo GetBlockInfo(BlockType type) {
switch(type) {
case GRASS: return {'#', 10}; // 绿色
case DIRT: return {'#', 6}; // 棕色
case STONE: return {'#', 8}; // 灰色
case WOOD: return {'|', 14}; // 黄色
case LEAF: return {'*', 2}; // 深绿色
case PLAYER: return {'P', 12}; // 红色
default: return {' ', 7}; // 空格
}
}
// ==================== 世界生成 ====================
void InitWorld() {
srand((unsigned)time(0));
// 生成地形
for (int y = 0; y < WORLD_HEIGHT; y++) {
for (int x = 0; x < WORLD_WIDTH; x++) {
if (y < 20) {
world[y][x] = AIR;
} else if (y == 20) {
world[y][x] = GRASS;
} else if (y < 25) {
world[y][x] = DIRT;
} else {
world[y][x] = STONE;
}
}
}
// 生成树木
for (int i = 0; i < 15; i++) {
int treeX = rand() % (WORLD_WIDTH - 10) + 5;
int treeHeight = rand() % 3 + 4;
// 树干
for (int y = 20; y > 20 - treeHeight; y--) {
if (y >= 0 && y < WORLD_HEIGHT) {
world[y][treeX] = WOOD;
}
}
// 树叶
int leafY = 20 - treeHeight;
for (int dy = 0; dy < 3; dy++) {
for (int dx = -2; dx <= 2; dx++) {
int x = treeX + dx;
int y = leafY - dy - 1;
if (x >= 0 && x < WORLD_WIDTH && y >= 0 && y < WORLD_HEIGHT && world[y][x] != WOOD) {
world[y][x] = LEAF;
}
}
}
}
}
// ==================== 方块操作 ====================
BlockType GetBlock(int x, int y) {
if (x >= 0 && x < WORLD_WIDTH && y >= 0 && y < WORLD_HEIGHT) {
return world[y][x];
}
return STONE;
}
void SetBlock(int x, int y, BlockType type) {
if (x >= 0 && x < WORLD_WIDTH && y >= 0 && y < WORLD_HEIGHT) {
world[y][x] = type;
}
}
// ==================== 物理更新 ====================
void UpdatePlayer() {
// 输入处理
if (GetAsyncKeyState('A') & 0x8000) {
player.vx = -0.3f;
} else if (GetAsyncKeyState('D') & 0x8000) {
player.vx = 0.3f;
} else {
player.vx *= 0.8f;
}
if ((GetAsyncKeyState(VK_SPACE) & 0x8000) && player.onGround) {
player.vy = -0.8f;
player.onGround = false;
}
// 重力
player.vy += 0.05f;
if (player.vy > 1.0f) player.vy = 1.0f;
// 新位置
float newX = player.x + player.vx;
float newY = player.y + player.vy;
// 碰撞检测
player.onGround = false;
// 水平碰撞
int left = floor(newX / BLOCK_SIZE);
int right = floor((newX + player.width) / BLOCK_SIZE);
int top = floor(player.y / BLOCK_SIZE);
int bottom = floor((player.y + player.height - 1) / BLOCK_SIZE);
if (player.vx > 0) {
if (GetBlock(right, top) == AIR && GetBlock(right, bottom) == AIR) {
player.x = newX;
} else {
player.x = right * BLOCK_SIZE - player.width - 0.1f;
player.vx = 0;
}
} else if (player.vx < 0) {
if (GetBlock(left, top) == AIR && GetBlock(left, bottom) == AIR) {
player.x = newX;
} else {
player.x = (left + 1) * BLOCK_SIZE;
player.vx = 0;
}
}
// 垂直碰撞
top = floor(newY / BLOCK_SIZE);
bottom = floor((newY + player.height - 1) / BLOCK_SIZE);
left = floor(player.x / BLOCK_SIZE);
right = floor((player.x + player.width - 1) / BLOCK_SIZE);
if (player.vy > 0) {
if (GetBlock(left, bottom) == AIR && GetBlock(right, bottom) == AIR) {
player.y = newY;
} else {
player.y = bottom * BLOCK_SIZE - player.height - 0.1f;
player.vy = 0;
player.onGround = true;
}
} else if (player.vy < 0) {
if (GetBlock(left, top) == AIR && GetBlock(right, top) == AIR) {
player.y = newY;
} else {
player.y = (top + 1) * BLOCK_SIZE;
player.vy = 0;
}
}
}
// ==================== 输入处理 ====================
void HandleInput() {
// 数字键选择方块
if (GetAsyncKeyState('1') & 0x8000) player.selectedBlock = GRASS;
if (GetAsyncKeyState('2') & 0x8000) player.selectedBlock = DIRT;
if (GetAsyncKeyState('3') & 0x8000) player.selectedBlock = STONE;
if (GetAsyncKeyState('4') & 0x8000) player.selectedBlock = WOOD;
if (GetAsyncKeyState('5') & 0x8000) player.selectedBlock = LEAF;
// 光标控制 (IJKL) + 操作 (U/O)
static int cursorX = SCREEN_WIDTH / 2;
static int cursorY = SCREEN_HEIGHT / 2;
if (GetAsyncKeyState('I') & 0x8000) cursorY--;
if (GetAsyncKeyState('K') & 0x8000) cursorY++;
if (GetAsyncKeyState('J') & 0x8000) cursorX--;
if (GetAsyncKeyState('L') & 0x8000) cursorX++;
if (cursorX < 0) cursorX = 0;
if (cursorX >= SCREEN_WIDTH) cursorX = SCREEN_WIDTH - 1;
if (cursorY < 0) cursorY = 0;
if (cursorY >= SCREEN_HEIGHT) cursorY = SCREEN_HEIGHT - 1;
// 计算相机位置
int cameraX = floor(player.x) - SCREEN_WIDTH / 2;
int cameraY = floor(player.y) - SCREEN_HEIGHT / 2;
// 限制相机边界
if (cameraX < 0) cameraX = 0;
if (cameraY < 0) cameraY = 0;
if (cameraX > WORLD_WIDTH * BLOCK_SIZE - SCREEN_WIDTH)
cameraX = WORLD_WIDTH * BLOCK_SIZE - SCREEN_WIDTH;
if (cameraY > WORLD_HEIGHT * BLOCK_SIZE - SCREEN_HEIGHT)
cameraY = WORLD_HEIGHT * BLOCK_SIZE - SCREEN_HEIGHT;
// 破坏方块 (U键)
if (GetAsyncKeyState('U') & 0x8000) {
int blockX = (cursorX + cameraX) / BLOCK_SIZE;
int blockY = (cursorY + cameraY) / BLOCK_SIZE;
SetBlock(blockX, blockY, AIR);
}
// 放置方块 (O键)
if (GetAsyncKeyState('O') & 0x8000) {
int blockX = (cursorX + cameraX) / BLOCK_SIZE;
int blockY = (cursorY + cameraY) / BLOCK_SIZE;
// 检查不与玩家重叠
int playerBlockX = floor(player.x / BLOCK_SIZE);
int playerBlockY = floor(player.y / BLOCK_SIZE);
if (abs(blockX - playerBlockX) > 1 || abs(blockY - playerBlockY) > 1) {
SetBlock(blockX, blockY, player.selectedBlock);
}
}
}
// ==================== 渲染 ====================
void Render() {
// 计算相机位置
int cameraX = floor(player.x) - SCREEN_WIDTH / 2;
int cameraY = floor(player.y) - SCREEN_HEIGHT / 2;
// 限制相机边界
if (cameraX < 0) cameraX = 0;
if (cameraY < 0) cameraY = 0;
if (cameraX > WORLD_WIDTH * BLOCK_SIZE - SCREEN_WIDTH)
cameraX = WORLD_WIDTH * BLOCK_SIZE - SCREEN_WIDTH;
if (cameraY > WORLD_HEIGHT * BLOCK_SIZE - SCREEN_HEIGHT)
cameraY = WORLD_HEIGHT * BLOCK_SIZE - SCREEN_HEIGHT;
// 绘制世界
for (int y = 0; y < SCREEN_HEIGHT; y++) {
gotoxy(0, y);
for (int x = 0; x < SCREEN_WIDTH; x++) {
int worldX = (cameraX + x) / BLOCK_SIZE;
int worldY = (cameraY + y) / BLOCK_SIZE;
BlockType type = AIR;
if (worldX >= 0 && worldX < WORLD_WIDTH && worldY >= 0 && worldY < WORLD_HEIGHT) {
type = world[worldY][worldX];
}
// 检查玩家位置
int playerScreenX = player.x - cameraX;
int playerScreenY = player.y - cameraY;
if (x >= playerScreenX && x < playerScreenX + player.width &&
y >= playerScreenY && y < playerScreenY + player.height) {
type = PLAYER;
}
BlockInfo info = GetBlockInfo(type);
setColor(info.color);
cout << info.symbol;
}
}
// 绘制UI
gotoxy(0, 0);
setColor(15);
cout << "2D Minecraft | WASD:移动 Space:跳跃 | IJKL:光标 U:破坏 O:放置 | 1-5:选方块";
// 绘制光标
static int cursorX = SCREEN_WIDTH / 2;
static int cursorY = SCREEN_HEIGHT / 2;
gotoxy(cursorX, cursorY);
setColor(15);
cout << "+";
// 显示选中方块
gotoxy(0, SCREEN_HEIGHT - 1);
setColor(15);
BlockInfo info = GetBlockInfo(player.selectedBlock);
cout << "选中: " << info.symbol << " 坐标:( " << (cursorX + cameraX) / BLOCK_SIZE << ","
<< (cursorY + cameraY) / BLOCK_SIZE << " )";
}
// ==================== 主函数 ====================
int main() {
// 初始化
hideCursor();
clearScreen();
InitWorld();
// 初始化玩家
player = {
WORLD_WIDTH * BLOCK_SIZE / 2, 300.0f, // x, y
0.0f, 0.0f, // vx, vy
8, 12, // width, height
false, // onGround
GRASS // selectedBlock
};
// 游戏循环
while (true) {
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) break; // ESC退出
UpdatePlayer();
HandleInput();
Render();
Sleep(50); // 控制帧率
}
setColor(7);
clearScreen();
gotoxy(0, 0);
cout << "感谢游玩2D Minecraft!\n";
return 0;
}
全部评论 5
d
23小时前 来自 江西
0d
23小时前 来自 江西
0''
23小时前 来自 北京
0可以看一下 https://www.acgo.cn/discuss/study/68471,是 3D 的,但是 java
昨天 来自 北京
0按键 功能
W/A/S/D 移动角色
空格 跳跃
I/J/K/L 移动光标
U 破坏方块
O 放置方块
1-5 选择方块类型
ESC 退出游戏昨天 来自 广东
0第一次做,勿喷🙃
昨天 来自 广东
0虽然只有五种方块
昨天 来自 广东
0草方块(绿色 #)
泥土(棕色 #)
石头(灰色 #)
木头(黄色 |)
树叶(深绿色 *)昨天 来自 广东
0
































有帮助,赞一个