3D+物理引擎

· · 个人记录

这里是我“最前沿”的模拟技术的上传地

放的是我最新整的活

22/9/15 闪屏问题已解决,帧率已获得过优化

#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
#define KeyDown(VK_NONAME) ((GetAsyncKeyState(VK_NONAME)&0x8000) ? 1:0) 
using namespace std;
double D=900,sen=0.2;
const double PI=acos(-1),g=9.8;
double cx,cy,cz;
double dirxz=0,diryz=0,mvdir;
double vy=0,ay=0,vx=0,ax=0;
bool ismove=false,isfly=false;
HANDLE Out=GetStdHandle(STD_OUTPUT_HANDLE),In=GetStdHandle(STD_INPUT_HANDLE);
HWND hWnd=GetConsoleWindow();
HDC hdc=GetDC(GetConsoleWindow()),Mem;
HBITMAP hBmp;HGDIOBJ hOldSel;
HPEN hpen0 = CreatePen( PS_SOLID, 1, RGB(255,255,255) );
HPEN hpen1 = CreatePen( PS_SOLID, 1, RGB(0,0,0) );
HPEN hpen2 = CreatePen( PS_SOLID, 1, RGB(0,50,255) );
HBRUSH blackbrush=CreateSolidBrush(RGB(200,200,200)),whitebrush=CreateSolidBrush(RGB(255,255,255));
struct line{
    double x1,y1,z1,x2,y2,z2;
};

double Hu(double dir){
    return dir*PI/180;
}
void Turn(double &x1,double &y1,double ox,double oy,double dir){
    double tmpx=x1-ox,tmpy=y1-oy;
    double cdir=cos(Hu(dir)),sdir=sin(Hu(dir));
    x1=tmpx*cdir-tmpy*sdir;
    y1=tmpx*sdir+tmpy*cdir;
}
vector<line> Linelist;
void CursorControl()
{
    while(1)
    {
        POINT p;
        GetCursorPos(&p);
        double dx=p.x-990,dy=p.y-540;
        dirxz+=dx*sen;
        diryz-=dy*sen;
        SetCursorPos(990,540);
        Sleep(10);
    }
}
POINT pts[25];
int cnt=0; 
void TurnAndPrint(double x1,double y1,double z1,double x2,double y2,double z2,bool issolid){
            Turn(x1,z1,cx,cz,dirxz); Turn(x2,z2,cx,cz,dirxz);
            z1+=cz,z2+=cz;
            Turn(z1,y1,cz,cy,-diryz); Turn(z2,y2,cz,cy,-diryz);
            if(z1<0&&z2<0){
                if(issolid){
                    pts[cnt]={pts[cnt-1].x,pts[cnt-1].y};       cnt++;
                    pts[cnt]={pts[cnt-2].x,pts[cnt-2].y};       cnt++;
                }
                return;
            } 
            if(z2<0){
                x2=x1-z1*((x1-x2)/(z1-z2));
                if(y1!=y2) y2=y2-z2*((y1-y2)/(z1-z2));
                z2=0;
            }
            else if(z1<0){
                x1=x1-z1*((x1-x2)/(z1-z2));
                if(y1!=y2) y1=y1-z1*((y1-y2)/(z1-z2));
                z1=0;
            } 
            double X1,Y1,X2,Y2;
            if(z1!=0)   X1=x1*(D/z1)+989,Y1=-y1*(D/z1)+540;
            else    X1=x1*D+989,Y1=-y1*D+540;
            if(z2!=0)   X2=x2*(D/z2)+989,Y2=-y2*(D/z2)+540;
            else    X2=x2*D+989,Y2=-y2*D+540;
            MoveToEx(Mem,X1,Y1,NULL);
            LineTo(Mem,X2,Y2);  
            if(issolid){
                pts[cnt]={int(X1),int(Y1)};     cnt++;
                pts[cnt]={int(X2),int(Y2)};     cnt++;
            }
}
struct cube{
    line l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12;
    //l1到l12,由上到下,从最左逆时针排列 
    bool ds[7];//要涂色的面,1为上,2345从最前逆时针排列,6为底 
    void print(){
        TurnAndPrint(l1.x1,l1.y1,l1.z1,l1.x2,l1.y2,l1.z2,1);
        TurnAndPrint(l2.x1,l2.y1,l2.z1,l2.x2,l2.y2,l2.z2,1);
        TurnAndPrint(l3.x1,l3.y1,l3.z1,l3.x2,l3.y2,l3.z2,1);
        TurnAndPrint(l4.x1,l4.y1,l4.z1,l4.x2,l4.y2,l4.z2,1);
        TurnAndPrint(l5.x1,l5.y1,l5.z1,l5.x2,l5.y2,l5.z2,1);
        TurnAndPrint(l6.x1,l6.y1,l6.z1,l6.x2,l6.y2,l6.z2,1);
        TurnAndPrint(l7.x1,l7.y1,l7.z1,l7.x2,l7.y2,l7.z2,1);
        TurnAndPrint(l8.x1,l8.y1,l8.z1,l8.x2,l8.y2,l8.z2,1);
        TurnAndPrint(l9.x1,l9.y1,l9.z1,l9.x2,l9.y2,l9.z2,1);
        TurnAndPrint(l10.x1,l10.y1,l10.z1,l10.x2,l10.y2,l10.z2,1);
        TurnAndPrint(l11.x1,l11.y1,l11.z1,l11.x2,l11.y2,l11.z2,1);
        TurnAndPrint(l12.x1,l12.y1,l12.z1,l12.x2,l12.y2,l12.z2,1);
        SelectObject(Mem,blackbrush);
        for(int d=1;d<=7;d++)
        if(ds[d])
        switch (d) {
            case 1:
                Polygon(Mem,pts,8);
                break;
            case 6:
                Polygon(Mem,pts+16,8);
                break;
            POINT nep[8];
            case 2:
                nep[0]=pts[2],nep[1]=pts[3],nep[2]=pts[10],nep[3]=pts[11],nep[4]=pts[19],nep[5]=pts[18],nep[6]=pts[8],nep[7]=pts[9];
                Polygon(Mem,nep,8);
                break;
            case 3:
                nep[0]=pts[4],nep[1]=pts[5],nep[2]=pts[13],nep[3]=pts[12],nep[4]=pts[21],nep[5]=pts[20],nep[6]=pts[10],nep[7]=pts[11];
                Polygon(Mem,nep,8);
                break;
            case 4:
                nep[0]=pts[6],nep[1]=pts[7],nep[2]=pts[15],nep[3]=pts[14],nep[4]=pts[23],nep[5]=pts[22],nep[6]=pts[12],nep[7]=pts[13];
                Polygon(Mem,nep,8);
                break;
            case 5:
                nep[0]=pts[0],nep[1]=pts[1],nep[2]=pts[9],nep[3]=pts[8],nep[4]=pts[17],nep[5]=pts[14],nep[6]=pts[14],nep[7]=pts[15];
                Polygon(Mem,nep,8);
                break;
            default:
                break;
        }
        SelectObject(Mem,whitebrush);
        cnt=0;
    }
};
vector<cube> Cubelist;
void print()
{
    while(1)
    {
        Mem=CreateCompatibleDC(hdc);
        hBmp=CreateCompatibleBitmap(hdc,1979,1079);
        hOldSel = SelectObject(Mem,hBmp);
        SelectObject(Mem,hpen0);
        Rectangle(Mem,0,0,1980,1080);
        SelectObject(Mem,hpen1);
        for(int o=0;o<int(Linelist.size());o++){
            SelectObject(Mem,hpen1);
            TurnAndPrint(Linelist[o].x1,Linelist[o].y1,Linelist[o].z1,Linelist[o].x2,Linelist[o].y2,Linelist[o].z2,0);
        }
        for(int o=0;o<int(Cubelist.size());o++){
            SelectObject(Mem,hpen1);
            Cubelist[o].print();
        }
        BitBlt(hdc,0,0,1979,1079,Mem,0,0,SRCCOPY);
        SelectObject(Mem,hOldSel);
        DeleteDC(Mem); 
        Sleep(33);
    }
}
void Move()
{
    while(1){
        if(ismove) ax=5;
        else ax=-5;
        if(vx<=30&&vx>=0) vx+=0.1*ax;
        if(vx<0) vx=0;
        if(vx>30) vx=30;
        cx+=0.1*vx*sin(Hu(mvdir));
        cz+=0.1*vx*cos(Hu(mvdir));
        Sleep(10);
    }

}
void fv(){
    while(1){
        if(!isfly){
        cy+=0.1*vy;
        Sleep(10);
        }
    }
}
void jump(){
    while(1){
        if(KeyDown(0x20)&&cy==0&&!isfly){
            vy=50,ay=0;
            Sleep(500);
        }       
        else if(KeyDown(0x20)&&isfly){
            cy+=5;
            Sleep(10);
        } 
        else if(KeyDown(0x10)&&isfly){
            cy-=5;
            Sleep(10);
        } 
    }
}
void Gravity(){
    while(1){
        if(!isfly){
        if(cy<0) vy=0,ay=0,cy=0;
        vy+=0.1*ay;
        ay-=g*0.1;
        Sleep(10);
        }
    }
}
int main()
{
//  cy=1000000;
    ShowWindow(hWnd,SW_SHOWMAXIMIZED);
    DWORD mode;
    GetConsoleMode(In,&mode);
    mode &= ~ENABLE_QUICK_EDIT_MODE;
    SetConsoleMode(In,mode);
    CONSOLE_CURSOR_INFO A;
    GetConsoleCursorInfo(Out,&A);
    A.bVisible=false;
    SetConsoleCursorInfo(Out,&A);
    thread t1(print);
    thread t2(CursorControl);
    thread t3(fv),t4(Gravity),t5(jump);
    thread t6(Move);
    for(double i=-1000;i<=1000;i+=100)
    for(double j=-1000;j<=1000;j+=100){     
    Cubelist.push_back({
        {j,50,i+100,j,50,i},{j,50,i,j+100,50,i},{j+100,50,i,j+100,50,i+100},{j+100,50,i+100,j,50,i+100},
        {j,-50,i,j,50,i},{j+100,-50,i,j+100,50,i},{j+100,-50,i+100,j+100,50,i+100},{j,-50,i+100,j,50,i+100},
        {j,-50,i+100,j,-50,i},{j,-50,i,j+100,-50,i},{j+100,-50,i,j+100,-50,i+100},{j+100,-50,i+100,j,-50,i+100}
    ,{0,1,0,0,0,0,1}});//上下两面保证首尾相连,中间从上至下 
    }
    while(1)
    {
        if(KeyDown(0x41)||KeyDown(0x44)||KeyDown(0x57)||KeyDown(0x53)) ismove=true;
        else ismove=false;
        if(KeyDown(0x41)) mvdir=dirxz-90.0;
        if(KeyDown(0x44)) mvdir=dirxz+90.0;
        if(KeyDown(0x57)) mvdir=dirxz;
        if(KeyDown(0x53)) mvdir=dirxz-180.0; 
        if(KeyDown(0x46)) isfly=!isfly,Sleep(100);
        if(KeyDown(0x4F))  sen+=0.01; 
        if(KeyDown(0x50))  sen-=0.01; 
        if(KeyDown(0xDD))  D+=10; 
        if(KeyDown(0xDB))  D-=10; 
        if(KeyDown(0x1B))  exit(0); 
        Sleep(40);
    }
    return 0;
}