C语言基于控制台110行代码实现3D空间效果

以上是设想,无需刻意的用近大远小的原理去伪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系统运行需要改的地方都有注释,如果屏幕抖动严重的话可以把屏幕长宽改小一点。

运行效果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值