StarFight

#include <windows.h>
#include <gl/gl.h>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>

long double t,ti=0.00005,shotI=0.24,shotV=6,st1=0,st2=0,initr=0.016,
              bt=0.12,bt2=1.08,bombI=3.6,shotr=0.004,ac=2,AIv=2;
bool s1=0,s2=0,b1=0,b2=0;
double starsize=0.016,szsq2=starsize*sqrt(0.5),PId16=3.14159/16;
const int Player1=0,Player2=1,Star=16,Shot=32,Bomb=33,dead=-1;
typedef long double ldouble;
int move1=5,move2=5;

#define AdP2(a,b) ((a)*(a)+(b)*(b))

int p1id=0,p2id=1,l1=10,l2=10;

#define Rand_ld (((long double) (rand()&0x1ffff)-0x10000)/0x20000)

double* makexf() {
    double *Xf=new double[32];
    for(int i=0; i<32; Xf[i]=cos(PId16*i),++i);
    return Xf;
}
double* makeyf() {
    double *Xf=new double[32];
    for(int i=0; i<32; Xf[i]=sin(PId16*i),++i);
    return Xf;
}

double *xf=makexf(),*yf=makeyf();

typedef struct {
    double red,green,blue;
    long double m,x,y,vx,vy,r,I;
    int type,l;
} star;

void move(star &s) {
    s.x+=s.vx*ti;
    s.y+=s.vy*ti;
    bool gg=0;
    if(s.x<-1&&s.vx<0) {
        s.vx=-s.vx;
        gg=1;
    }
    if(s.y<-1&&s.vy<0) {
        s.vy=-s.vy;
        gg=1;
    }
    if(s.x>1&&s.vx>0) {
        s.vx=-s.vx;
        gg=1;
    }
    if(s.y>1&&s.vy>0) {
        s.vy=-s.vy;
        gg=1;
    }
    if(gg) {
        s.l--;
        if(s.type==Shot) s.x+=2333+Rand_ld*233;
    }
}


void attract(star &a,star &b) {
    long double d=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
    if(d<=(a.r+b.r)*(a.r+b.r)) {
        ldouble x=b.x-a.x,y=b.y-a.y,I;
        if(a.type==Shot||b.type==Shot) {
            I=(a.I+b.I)/(sqrt(x*x+y*y)*a.m*b.m);
            if(I<=0) return;
            a.vx-=I*x*b.m;
            a.vy-=I*y*b.m;
            b.vx+=I*x*a.m;
            b.vy+=I*y*a.m;
            if(a.type&32) a.x+=2333;
            if(b.type&32) b.x+=2333;
            return;
        }
        I=(x*(a.vx-b.vx)+y*(a.vy-b.vy))*2/((x*x+y*y)*(a.m+b.m));
        if(I<0) return;
        a.vx-=I*x*b.m;
        a.vy-=I*y*b.m;
        b.vx+=I*x*a.m;
        b.vy+=I*y*a.m;
    } else {
        d*=sqrt(d);
        d=ti*0.02/d;
        a.vx+=b.m*(b.x-a.x)*d;
        b.vx+=a.m*(a.x-b.x)*d;
        a.vy+=b.m*(b.y-a.y)*d;
        b.vy+=a.m*(a.y-b.y)*d;
    }
}

void randstar(star& s,int i) {
    s.red=s.green=s.blue=0.0;
    if(i==p1id) {
        s.red=s.blue=1.0;
        s.m=0.5;
    } else if(i==p2id) {
        s.blue=s.green=1.0;
        s.m=0.5;
    } else {
        if(rand()%3==0) s.red=1.0;
        else if(rand()&1) s.green=1.0;
        else s.blue=1.0;
        s.m=Rand_ld+0.5;
    }
    s.x=Rand_ld*4;
    s.y=Rand_ld*4;
    s.vx=Rand_ld;
    s.vy=Rand_ld;
    s.r=initr;
    s.type=s.l=s.I=0;
}

class cosmos {
public:
    void set(int star_amount) {
        if(star_amount<1||star_amount>256) {
            return;
        }
        amount=star_amount;
        random_get();
    }

    void random_get() {
        for(int i=0; i<amount; ++i) {
            randstar(s[i],i);
        }
        set_mid();
        s2=true;
        s[3].m=5;
        s[3].r=initr*5;
        //s[2].blue=s[2].green=s[2].red=0.2;
        //s[2].m=100;
        s[2].r=initr/4;
        s[4].m=6;
        s[4].r=initr*7;
    }
    void set_mid() {
        long double sx=0.0,sy=0.0,svx=0.0,svy=0.0,sm=0.0;
        for(int i=0; i<amount; ++i) {
            sx+=s[i].x*s[i].m;
            sy+=s[i].y*s[i].m;
            svx+=s[i].vx*s[i].m;
            svy+=s[i].vy*s[i].m;
            sm+=s[i].m;
        }
        sx/=sm;
        sy/=sm;
        svx/=sm;
        svy/=sm;
        for(int i=0; i<amount; ++i) {
            s[i].x-=sx;
            s[i].y-=sy;
            s[i].vx-=svx;
            s[i].vy-=svy;
        }
    }

    void process(long double time) {
        for(; time>0; time-=ti) {
#if !TWOPLAYER
            if(s[1].vx<0&&s[1].x<0||s[1].x<-0.64||s[1].vx<-sqrt(AIv))
                s[1].vx+=ti*AIv;
            else if(s[1].vx>0&&s[1].x>0||s[1].x>.64||s[1].vx>sqrt(AIv))
                s[1].vx-=ti*AIv;
            if(s[1].y<0&&s[1].vy<0||s[1].y<-0.64||s[1].vy<-sqrt(AIv))
                s[1].vy+=ti*AIv;
            else if(s[1].y>0&&s[1].vy>0||s[1].y>0.64||s[1].vy>sqrt(AIv))
                s[1].vy-=ti*AIv;
            /*long double d=sqrt(s[1].x*s[1].x+s[1].y*s[1].y),v;
            v=sqrt(s[1].vx*s[1].vx+s[1].vy*s[1].vy);
            s[1].vx-=s[1].x/d*ti*AIv+s[1].vx/v*AIv;
            s[1].vy-=s[1].y/d*ti*AIv+s[1].vy/v*AIv;*/
#else
            switch(move2) {
            case 0:
                s[1].vy+=ti*ac;
                break;
            case 1:
                s[1].vy-=ti*ac;
                break;
            case 2:
                s[1].vx-=ti*ac;
                break;
            case 3:
                s[1].vx+=ti*ac;
                break;
            }
#endif
            switch(move1) {
            case 0:
                s[0].vy+=ti*ac;
                break;
            case 1:
                s[0].vy-=ti*ac;
                break;
            case 2:
                s[0].vx-=ti*ac;
                break;
            case 3:
                s[0].vx+=ti*ac;
                break;
            }
            t+=ti;
            if(s1&&t>st1+bt) {
                st1=t;
                if(b1) {
                    st1+=bt2;
                    b1=0;
                    shot(p1id,p2id,bombI);
                } else shot(p1id,p2id,shotI);
            }
            if(s2&&t>st2+bt) {
                st2=t;
                if(b2) {
                    b2=0;
                    st2+=bt2;
                    shot(p2id,p1id,bombI);
                } else shot(p2id,p1id,shotI);
            }
            for(int i=0; i<amount; ++i) {
                for(int j=i+1; j<amount; ++j) {
                    attract(s[i],s[j]);
                }
            }
            for(int i=0; i<amount; ++i) {
                if(s[i].x>233) {
                    amount--;
                    s[i].red=s[amount].red;
                    s[i].green=s[amount].green;
                    s[i].blue=s[amount].blue;
                    s[i].m=s[amount].m;
                    s[i].x=s[amount].x;
                    s[i].vx=s[amount].vx;
                    s[i].y=s[amount].y;
                    s[i].vy=s[amount].vy;
                    s[i].r=s[amount].r;
                }
                move(s[i]);
            }
        }
    }
    void output(HDC &hDC) {
        glClearColor (0.0, 0.0, 0.0, 0.0);
        glClear (GL_COLOR_BUFFER_BIT);
        double x,y,r;
        for(int i=0; i<amount; ++i) {
            glPushMatrix();

            glColor3d(s[i].red,s[i].green,s[i].blue);
            glBegin(GL_TRIANGLE_FAN);
            x=s[i].x;
            y=s[i].y;
            r=s[i].r;
            glVertex2d(x, y);
            for(int i=0; i<32; ++i) {
                glVertex2d(x+r*xf[i], y+r*yf[i]);
            }
            glVertex2d(x+r*xf[0], y+r*yf[0]);
            glEnd();
            glPopMatrix ();
        }
        SwapBuffers (hDC);
    }
    void shot(int i1,int i2,long double I) {
        s[amount].blue = s[amount].green = s[amount].red = 1.0;
        long double x=s[i2].x-s[i1].x,y=s[i2].y-s[i1].y,d;
        long double dt=(x*s[i2].vx+y*s[i2].vy);
dt+=sqrt(dt*dt+(x*x+y*y)*(shotV*shotV-s[i2].vx*s[i2].vx-s[i2].vy*s[i2].vy))
dt/=(shotV*shotV-s[i2].vx*s[i2].vx-s[i2].vy*s[i2].vy);
        x+=s[i2].vx*dt;
y+=s[i2].vy*dt;
d=sqrt(x*x+y*y);
        s[amount].x=s[i1].x+s[i1].r*x/d*1.9;
        s[amount].y=s[i1].y+s[i1].r*y/d*1.9;
        s[amount].vx=shotV*x/d;
        s[amount].vy=shotV*y/d;
        s[amount].m=0.00001;
        s[amount].I=I;
        s[amount].type=Shot;
        s[amount].r=I==shotI?shotr:shotr*2;
        s[amount].l=0;
        amount++;
    }
    star s[256];
    int amount;
};
#define TWOPLAYER 1
#include "starfight.h"

LRESULT CALLBACK WndProc (HWND hWnd, UINT message,
                          WPARAM wParam, LPARAM lParam);
void EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC);
void DisableOpenGL (HWND hWnd, HDC hDC, HGLRC hRC);

cosmos MyUniv;

#define p1 (MyUniv.s[0])
#define p2 (MyUniv.s[1])

const ldouble playera=0.05;

long double process_time=0.01;
/**************************
 * WinMain
 *
 **************************/

int WINAPI WinMain (HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine,
                    int iCmdShow) {
    srand(GetTickCount());
    WNDCLASS wc;
    HWND hWnd;
    HDC hDC;
    HGLRC hRC;
    MSG msg;
    BOOL bQuit = FALSE;

    /* register window class */
    wc.style = CS_OWNDC;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "Star";
    RegisterClass (&wc);

    /* create main window */
    hWnd = CreateWindow (
              "Star", "Star",
              WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,
              0, 0, 768, 768,
              NULL, NULL, hInstance, NULL);

    /* enable OpenGL for the window */
    EnableOpenGL (hWnd, &hDC, &hRC);
    MyUniv.set(3);
    /* program main loop */
    while (!bQuit) {
        /* check for messages */
        if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
            /* handle or dispatch messages */
            if (msg.message == WM_QUIT) {
                bQuit = TRUE;
            } else {
                TranslateMessage (&msg);
                DispatchMessage (&msg);
            }
        } else {
            /* OpenGL animation code goes here */
            if(process_time>0) {
                MyUniv.process(process_time);
                MyUniv.output(hDC);
                if(p1.l<-10) {
                    MyUniv.random_get();
                    process_time = 0.0001;
                    MessageBox(NULL,"","P2 WIN!",0);
                }
                if(p2.l<-10) {
                    MyUniv.random_get();
                    process_time = 0.0001;
                    MessageBox(NULL,"","P1 WIN!",0);
                }
            }
            Sleep (3);
        }
    }

    /* shutdown OpenGL */
    DisableOpenGL (hWnd, hDC, hRC);

    /* destroy the window explicitly */
    DestroyWindow (hWnd);

    return msg.wParam;
}


/********************
 * Window Procedure
 *
 ********************/

LRESULT CALLBACK WndProc (HWND hWnd, UINT message,
                          WPARAM wParam, LPARAM lParam) {
    
    switch (message) {
    case WM_CREATE:
        return 0;
    case WM_CLOSE:
        PostQuitMessage (0);
        return 0;

    case WM_DESTROY:
        return 0;

    case WM_KEYDOWN:
        switch (wParam) {
        case VK_ESCAPE:
            PostQuitMessage(0);
            return 0;
        case ' ':
            MyUniv.random_get();
            process_time = 0.0001;
            return 0;
        case VK_UP:
            process_time += 0.001;
            return 0;
        case VK_DOWN:
            if((process_time -= 0.001)<0.0) process_time=0.0;
            return 0;
        case 'Z':
            process_time += 0.0001;
            return 0;
        case 'X':
            if((process_time -= 0.0001)<0.0) process_time=0.0;
            return 0;
        case 'C':
            process_time= 0.0;
            return 0;
        case 'W':
            move1=0;
            return 0;
        case 'S':
            move1=1;
            return 0;
        case 'A':
            move1=2;
            return 0;
        case 'D':
            move1=3;
            return 0;
        case 'E':
            s1=!s1;
            return 0;
        case 'Q':
            b1=1;
            return 0;
#if TWOPLAYER
        case 'I':
            move2=0;
            return 0;
        case 'K':
            move2=1;
            return 0;
        case 'J':
            move2=2;
            return 0;
        case 'L':
            move2=3;
            return 0;
        case 'O':
            s2=!s2;
            return 0;
        case 'U':
            b2=1;
            return 0;
#endif
        case VK_LEFT:
            MyUniv.set(MyUniv.amount-1);
            return 0;
        case VK_RIGHT:
            MyUniv.set(MyUniv.amount+1);
            return 0;
        }
        return 0;

    default:
        return DefWindowProc (hWnd, message, wParam, lParam);
    }
}


/*******************
 * Enable OpenGL
 *
 *******************/

void EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC) {
    PIXELFORMATDESCRIPTOR pfd;
    int iFormat;

    /* get the device context (DC) */
    *hDC = GetDC (hWnd);

    /* set the pixel format for the DC */
    ZeroMemory (&pfd, sizeof (pfd));
    pfd.nSize = sizeof (pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW |
                  PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cDepthBits = 8;
    pfd.iLayerType = PFD_MAIN_PLANE;
    iFormat = ChoosePixelFormat (*hDC, &pfd);
    SetPixelFormat (*hDC, iFormat, &pfd);

    /* create and enable the render context (RC) */
    *hRC = wglCreateContext( *hDC );
    wglMakeCurrent( *hDC, *hRC );

}


/******************
 * Disable OpenGL
 *
 ******************/

void DisableOpenGL (HWND hWnd, HDC hDC, HGLRC hRC) {
    wglMakeCurrent (NULL, NULL);
    wglDeleteContext (hRC);
    ReleaseDC (hWnd, hDC);
}

 

posted @ 2017-04-03 11:47  141421356  阅读(1187)  评论(0)    收藏  举报