以上是设想,无需刻意的用近大远小的原理去伪3D,算法到位效果自然就实现了,原理可参考眼珠子。视轴z轴搞半天才弄明白。
可以试着cube几个方块玩玩,有能力还可以添加n个随机位置的方块,再创建个线程自动向前走。
#include<iostream>
#include<conio.h>//windows:#include<windows.h>
#include<math.h>
using namespace std;
#define PI 3.1415926
#define RW 200//房间宽度
#define FOV 40.0//视野
char room[RW][RW][RW];//房间
int render_d=100,anglex=-5,angley=30;//渲染距离,纵、横视轴方向
struct point {
int x;
int y;
int z;
int v;
};//3D位置结构(v为创建方块时用到的体积变量)
point i= {RW/2-5,RW/2,RW/2,0};//自身坐标
class screen
{
#define SCRN_W 49//屏幕宽度
#define SCRN_L 98//屏幕长度
public:
char s[SCRN_W][SCRN_L];//屏幕
screen(char mc=' ',char fc='#')//初始化屏幕
{
int x,y;
for(x=0; x<SCRN_W; x++)
for(y=0; y<SCRN_L; y++)
s[x][y]=mc;
for(x=0; x<SCRN_W; x++)
s[x][0]=s[x][SCRN_L-1]=fc;
for(y=0; y<SCRN_L; y++)
s[0][y]=s[SCRN_W-1][y]=fc;
}
void refresh()//刷新屏幕
{
cout<<"\033[H\033[2J\033[?25l";
for(int x=0; x<SCRN_W; x++)
{
for(int y=0; y<SCRN_L; y++)
putchar(s[x][y]);
cout<<endl;
}
}
} scrn;
void cube(point cube)//创建方块
{
for(int x=cube.x-cube.v; x<=cube.x+cube.v; x++)
for(int z=cube.z-cube.v; z<=cube.z+cube.v; z++)
room[x][cube.y-cube.v][z]=room[x][cube.y+cube.v][z]='-';
for(int x=cube.x-cube.v; x<=cube.x+cube.v; x++)
for(int y=cube.y-cube.v; y<=cube.y+cube.v; y++)
room[x][y][cube.z-cube.v]=room[x][y][cube.z+cube.v]='#';
for(int y=cube.y-cube.v; y<=cube.y+cube.v; y++)
for(int z=cube.z-cube.v; z<=cube.z+cube.v; z++)
room[cube.x-cube.v][y][z]=room[cube.x+cube.v][y][z]='+';
}
void init()//初始化房间,画出坐标轴和方块
{
for(int x=0; x<RW; x++)
for(int y=0; y<RW; y++)
for(int z=0; z<RW; z++)
room[x][y][z]=0;
for(int n=0; n<RW; n++)
room[n][RW/2][RW/2]=room[RW/2][RW/2][n]=room[RW/2][n][RW/2]='#';
}
void display()//投射到屏幕并显示
{
float nx,ny,nz,xs,ys,zs,fax,fay;
int n;
for(int x=0; x<=SCRN_W; x++)
for(int y=0; y<=SCRN_L; y++)
{
fax=(anglex-FOV/2+FOV/SCRN_W*x)*PI/180;
fay=(angley-FOV/2+FOV/SCRN_L*y)*PI/180;
xs=sin(fax);
ys=sin(fay);
zs=cos(fax)*cos(fay);
nx=i.x,ny=i.y,nz=i.z;
for(n=0; n<render_d; n++)
{
nx+=xs;
ny+=ys;
nz+=zs;
if(nx>=RW||ny>=RW||nz>=RW||nx<=0||ny<=0||nz<=0)
{
scrn.s[x][y]=' ';
break;
}
if(room[(int)nx][(int)ny][(int)nz])
{
scrn.s[x][y]=room[(int)nx][(int)ny][(int)nz];
break;
}
}
if(n>=render_d)
scrn.s[x][y]=' ';
}
scrn.refresh();
}
int main()
{
init();
cube({RW/2-10,RW/2+15,RW/2+15,10});//创建方块
for(int n=-150; n<=210; n++)
{
display();
i.y=RW/2+50*sin(n*PI/180);
i.z=RW/2+50*cos(n*PI/180);
angley++;
usleep(1000000/180);//windows:Sleep(1000/180);
}
}
Windows系统运行需要改的地方都有注释,如果屏幕抖动严重的话可以把屏幕长宽改小一点。
运行效果