前言
作者的话
*游戏版权:原"Minecraft"由"©Mojang AB所开发",本次内容只是为MC爱好者的开源项目,由Dev-C++开源,与"Minecraft"以及"我的世界"没有从属关系,请尊重原版游戏!
今天我将展示两种分别使用Dev-C++做的2D版与3D版的Minecraft
本文章来自博主 SkyMax(スキマックス) 编写 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明
正文
1. 功能介绍
1.1 基本按键
| 移动 | 按键 |
|---|---|
前 | W |
后 | S |
左 | A |
右 | D |
打开背包(物品栏) | E |
跳跃 | Space |
蹲下 | Shift |
退出游戏 | X |
TIP因为博主编程太菜了,有些功能不全面,请谅解… 在公布源代码之前,大家需要做一些功能准备,但是不用担心,跟着我一步一步来。
2. Minecraft 3D
准备工作
首先要准备的就是字体
大家点击这个链接就可以进行下载、安装了
字体下载 https://web.mc.js.cool/texture/mc-font.ttf (已失效)
大家像这样新建文件夹,一会儿会在里面编辑一些文件。
新建好以后,
我会展示自编头文件,也就是noise.h和math.h,后面我们需要用到。 头文件
noise.h
float persistence = 0.7; int Number_Of_Octaves = 2;
double Noise(int x,int y) { int n = x + y * 57; n = (n<<13) ^ n; return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0); } double SmoothedNoise(int x, int y) { double corners = ( Noise(x-1, y-1)+Noise(x+1, y-1)+Noise(x-1, y+1)+Noise(x+1, y+1) ) / 16; double sides = ( Noise(x-1, y) +Noise(x+1, y) +Noise(x, y-1) +Noise(x, y+1) ) / 8; double center = Noise(x, y) / 4; return corners + sides + center; } double Cosine_Interpolate(double a,double b, double x) { double ft = x * 3.1415927; double f = (1 - cos(ft)) * 0.5; return a*(1-f) + b*f; } double InterpolatedNoise(float x,float y) { int integer_X = int(x); float fractional_X = x - integer_X; int integer_Y = int(y); float fractional_Y = y - integer_Y; double v1 = SmoothedNoise(integer_X, integer_Y); double v2 = SmoothedNoise(integer_X + 1, integer_Y); double v3 = SmoothedNoise(integer_X, integer_Y + 1); double v4 = SmoothedNoise(integer_X + 1, integer_Y + 1); double i1 = Cosine_Interpolate(v1, v2, fractional_X); double i2 = Cosine_Interpolate(v3, v4, fractional_X); return Cosine_Interpolate(i1, i2, fractional_Y); } double noise(float x,float y=0) { double total = 0; double p = persistence; int n = Number_Of_Octaves; for(int i=0; i<n; i++) { double frequency = pow(2,i); double amplitude = pow(p,i); total = total + InterpolatedNoise(x * frequency, y * frequency) * amplitude; }
return total; }TIP各位看到有报错可以不用管(MinGW / GCC日常,Visual Studio应该不会有报错)
math.h
#include<bits/stdc++.h> using namespace std; struct Vec2i { Vec2i() : x(0), y(0) {} Vec2i(int X, int Y): x(X), y(Y) {}; Vec2i operator - (Vec2i b) { return Vec2i(x - b.x, y - b.y); } int x, y; }; struct Vec3i { int x, y, z; Vec3i(int X, int Y, int Z): x(X), y(Y), z(Z) {}; Vec3i() : x(0), y(0), z(0) {}; bool operator<(const Vec3i b) const { return x == b.x ? (y == b.y ? z < b.z : y < b.y) : x < b.x; } Vec3i operator * (int r) { return Vec3i(x * r, y * r, z * r); } Vec3i operator + (Vec3i v) { return Vec3i(x + v.x, y + v.y, z + v.z); } bool operator==(const Vec3i b) const { return x == b.x && y == b.y && z == b.z; } }; Vec2i findIntersection(Vec2i a, Vec2i b, Vec2i c, Vec2i d) { float x1 = a.x, y1 = a.y; float x2 = b.x, y2 = b.y; float x3 = c.x, y3 = c.y; float x4 = d.x, y4 = d.y; float x, y; float den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); if (den == 0)return Vec2i(0.25 * (x1 + x2 + x3 + x4), 0.25 * (y1 + y2 + y3 + y4)); x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / den; y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / den; return Vec2i(x, y); } struct Vec3f { Vec3f() : x(0), y(0), z(0) {} Vec3f(float xx, float yy, float zz) : x(xx), y(yy), z(zz) {} Vec3f operator + (Vec3f v) { return Vec3f(x + v.x, y + v.y, z + v.z); } Vec3f operator - (Vec3f v) { return Vec3f(x - v.x, y - v.y, z - v.z); } Vec3f operator * (float r) { return Vec3f(x * r, y * r, z * r); } float lenth() { return sqrt(x * x + y * y + z * z); } bool operator<(const Vec3f b) const { return x == b.x ? (y == b.y ? z < b.z : y < b.y) : x < b.x; } void rotate_x(float R) { float new_y = y * cos(R) - z * sin(R); float new_z = y * sin(R) + z * cos(R); y = new_y; z = new_z; } void rotate_y(float R) { float new_x = x * cos(R) + z * sin(R); float new_z = -x * sin(R) + z * cos(R); x = new_x; z = new_z; } const float& operator [] (uint8_t i) const { return (&x)[i]; } Vec3f& normalize() { float factor = 1 / lenth() ; x *= factor, y *= factor, z *= factor; return *this; } float x, y, z; }; struct Matrix44 { float x[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; Matrix44() {} int rad = rand() % 2; Matrix44 (float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p) { x[0][0] = a; x[0][1] = b; x[0][2] = c; x[0][3] = d; x[1][0] = e; x[1][1] = f; x[1][2] = g; x[1][3] = h; x[2][0] = i; x[2][1] = j; x[2][2] = k; x[2][3] = l; x[3][0] = m; x[3][1] = n; x[3][2] = o; x[3][3] = p; } const float* operator [] (uint8_t i) const { return x[i]; } float* operator [] (uint8_t i) { return x[i]; } void multVecMatrix(const Vec3f &src, Vec3f &dst) const { float a, b, c, w; a = src[0] * x[0][0] + src[1] * x[1][0] + src[2] * x[2][0] + x[3][0]; b = src[0] * x[0][1] + src[1] * x[1][1] + src[2] * x[2][1] + x[3][1]; c = src[0] * x[0][2] + src[1] * x[1][2] + src[2] * x[2][2] + x[3][2]; w = src[0] * x[0][3] + src[1] * x[1][3] + src[2] * x[2][3] + x[3][3]; dst.x = a / w; dst.y = b / w; dst.z = c / w; } void multDirMatrix(const Vec3f &src, Vec3f &dst) const { float a, b, c; a = src[0] * x[0][0] + src[1] * x[1][0] + src[2] * x[2][0]; b = src[0] * x[0][1] + src[1] * x[1][1] + src[2] * x[2][1]; c = src[0] * x[0][2] + src[1] * x[1][2] + src[2] * x[2][2]; dst.x = a; dst.y = b; dst.z = c; } Matrix44 inverse() { int i, j, k; Matrix44 s; Matrix44 t (*this); for (i = 0; i < 3 ; i++) { int pivot = i; float pivotsize = t[i][i]; if (pivotsize < 0)pivotsize = -pivotsize; for (j = i + 1; j < 4; j++)if (abs(t[j][i]) > pivotsize)pivot = j, pivotsize = abs(t[j][i]); if (pivotsize == 0)return Matrix44(); if (pivot != i)for (j = 0; j < 4; j++)swap(t[i][j], t[pivot][j]), swap(s[i][j], s[pivot][j]); for (j = i + 1; j < 4; j++) { float f = t[j][i] / t[i][i]; for (k = 0; k < 4; k++)t[j][k] -= f * t[i][k], s[j][k] -= f * s[i][k]; } } for (i = 3; i >= 0; --i) { float f; if ((f = t[i][i]) == 0)return Matrix44(); for (j = 0; j < 4; j++)t[i][j] /= f, s[i][j] /= f; for (j = 0; j < i; j++) { f = t[j][i]; for (k = 0; k < 4; k++)t[j][k] -= f * t[i][k], s[j][k] -= f * s[i][k]; } } return s; } }; bool inpoly(int x, int y, int a[]) { int count = 0; for (int i = 0; i < 8; i += 2) { int x1 = a[i], y1 = a[i + 1], x2 = a[(i + 2) % 8], y2 = a[(i + 3) % 8]; if ((y1 < y && y2 >= y) || (y1 >= y && y2 < y)) { int cross_x = (y - y1) * (x2 - x1) / (y2 - y1) + x1; if (cross_x < x)count++; } } return count % 2 != 0; } template <typename T> void Sort(std::vector<T>& arr, int low, int high) { if (low < high) { int pivotIndex = partition(arr, low, high); Sort(arr, low, pivotIndex - 1); Sort(arr, pivotIndex + 1, high); } } template <typename T> int partition(std::vector<T>& arr, int low, int high) { T pivot = arr[high]; int i = low - 1; for (int j = low; j <= high - 1; j++) { if (arr[j] < pivot) { i++; swap(arr[i], arr[j]); } } swap(arr[i + 1], arr[high]); return i + 1; } #include <chrono> long long getseconds() { auto now = std::chrono::high_resolution_clock::now(); auto nanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(now); return nanos.time_since_epoch().count(); } int f45 (double n) { if (n > 0)return n - int(n) >= 0.5 ? int(n) + 1 : int(n); else return -n - int(-n) >= 0.5 ? -(int(-n) + 1) : -int(-n); }把头文件做完后我们需要下载一些贴图。 方块贴图
block 文件夹文件 : Block文件夹 (提取码:fh2y 永久有效)
destroy 文件夹文件 : Destroy文件夹 (提取码:mmmu 永久有效)
item 文件夹文件 : Item文件夹 (提取码:u1g4 永久有效)
noob 文件夹文件 : Noob文件夹 (提取码:yn8m 永久有效)
//注 : 感谢 weixin_74969969 用户即使提出意见~谢谢🙏
接下来就是这个程序最重要的部分——主程序(main)
主程序
Minecraft.cpp
#include <windows.h>#include <iostream>#include <conio.h>
using namespace std;
const int WIDTH = 80;const int HEIGHT = 30;
const int WORLD_W = 200;const int WORLD_H = 50;
char screen[HEIGHT][WIDTH + 1];char world[WORLD_H][WORLD_W];
float playerX = 10;float playerY = 10;
float velocityY = 0;
bool running = true;bool onGround = false;
HANDLE hConsole;
// =======================// 初始化世界// =======================
void initWorld(){ for(int y = 0; y < WORLD_H; y++) { for(int x = 0; x < WORLD_W; x++) { world[y][x] = ' '; } }
// 地面 for(int x = 0; x < WORLD_W; x++) { world[25][x] = '#'; }
// 平台 for(int x = 20; x < 35; x++) { world[20][x] = '#'; }
for(int x = 50; x < 70; x++) { world[15][x] = '#'; }
// 墙 for(int y = 10; y < 25; y++) { world[y][40] = '#'; }}
// =======================// 清空缓冲区// =======================
void clearBuffer(){ for(int y = 0; y < HEIGHT; y++) { for(int x = 0; x < WIDTH; x++) { screen[y][x] = ' '; }
screen[y][WIDTH] = '\0'; }}
// =======================// 摄像机渲染// =======================
void renderWorld(){ int cameraX = (int)playerX - WIDTH / 2; int cameraY = (int)playerY - HEIGHT / 2;
if(cameraX < 0) cameraX = 0; if(cameraY < 0) cameraY = 0;
for(int y = 0; y < HEIGHT; y++) { for(int x = 0; x < WIDTH; x++) { int worldX = x + cameraX; int worldY = y + cameraY;
if(worldX >= 0 && worldX < WORLD_W && worldY >= 0 && worldY < WORLD_H) { screen[y][x] = world[worldY][worldX]; } } }
// 玩家 int px = (int)playerX - cameraX; int py = (int)playerY - cameraY;
if(px >= 0 && px < WIDTH && py >= 0 && py < HEIGHT) { screen[py][px] = '@'; }}
// =======================// 碰撞检测// =======================
bool isSolid(int x, int y){ if(x < 0 || x >= WORLD_W || y < 0 || y >= WORLD_H) { return true; }
return world[y][x] == '#';}
// =======================// 玩家物理// =======================
void updatePhysics(){ velocityY += 0.15f;
float newY = playerY + velocityY;
if(velocityY > 0) { if(isSolid((int)playerX, (int)(newY))) { playerY = (int)newY; velocityY = 0; onGround = true; } else { playerY = newY; onGround = false; } } else { playerY = newY; }}
// =======================// 输入// =======================
void input(){ if(GetAsyncKeyState('A') & 0x8000) { if(!isSolid((int)(playerX - 1), (int)playerY)) { playerX -= 0.2f; } }
if(GetAsyncKeyState('D') & 0x8000) { if(!isSolid((int)(playerX + 1), (int)playerY)) { playerX += 0.2f; } }
if(GetAsyncKeyState(VK_SPACE) & 0x8000) { if(onGround) { velocityY = -0.8f; onGround = false; } }
if(GetAsyncKeyState(VK_ESCAPE) & 0x8000) { running = false; }}
// =======================// 渲染到控制台// =======================
void render(){ COORD pos = {0,0}; SetConsoleCursorPosition(hConsole, pos);
for(int y = 0; y < HEIGHT; y++) { cout << screen[y] << '\n'; }}
// =======================// 隐藏光标// =======================
void hideCursor(){ CONSOLE_CURSOR_INFO cursor;
cursor.dwSize = 1; cursor.bVisible = FALSE;
SetConsoleCursorInfo(hConsole, &cursor);}
// =======================// 设置窗口大小// =======================
void setupConsole(){ system("mode con cols=80 lines=30");
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
hideCursor();}
// =======================// 主循环// =======================
int main(){ setupConsole();
initWorld();
while(running) { clearBuffer();
input();
updatePhysics();
renderWorld();
render();
Sleep(16); }
return 0;}cpp 运行
这样我们就做好了Minecraft 2D版 后记
好了这就是这期文章要分享的全部内容了!非常感谢你能够阅读这篇文章,和看到这里,觉得文章还不错,关注一下? 咱们下篇再见~~~
本文来自爱编程的007 , 转载请附上原文出处链接和本声明。———————————————— 版权声明:本文为CSDN博主「爱编程的007」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/2301_78110244/article/details/145191268