#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);
}