#include<easyx.h>
#include <conio.h>
#include <graphics.h>
#include <math.h>
#include "ball.h"
//重载acos
float acos(const float cost,const float y)
{
if(y>0)return acos(cost);
if(y<0)return 2*pi-acos(cost);
if(y==0&&cost>=0)return 0;
if(y==0&&cost<0)return pi;
}
//重载atan
float atan(const float y,const float x)
{
if(x>0&&y>=0)return atan(y/x);
if(x>0&&y<0)return 2*pi+atan(y/x);
if(x==0&&y==0)return 0;
if(x==0&&y>0)return pi/2;
if(x==0&&y<0)return 3*pi/2;
if(x<0)return pi+atan(y/x);
}
//ball类成员实现***********************************************************************************
//构造函数
ball::ball(float xput=200,float yput=200,COLORREF colorset=RGB(255,255,255))
{
x=xput;
y=yput;
v=0;
r=15;
t=0;
color=colorset;
acc=0.0006;
check=false;
}
//重设变量
void ball::setagain(float v0,float t0)
{
v=v0;
t=t0;
}
//画小球
void ball::draw()
{
setlinecolor(color);
setfillcolor(color);
fillcircle(x,y,r);
}
//小球移动并判断边界
void ball::move(float l,float w)
{
if((fabs(x-r)<50&&fabs(y-r)<50)|| //check判断是否进洞
(fabs(x-r)<50&&y+r+50>w)||
(x+r+50>l&&fabs(y-r)<50)||
(x+r+50>l&&y+r+50>w))
{
v=0;
check=true;
}
if(fabs(x-l/2)<20&&fabs(y-r)<50)
{
v=0;
check=true;
}
if(fabs(x-l/2)<20&&y+r+50>w)
{
v=0;
check=true;
}
x=x+v*cos(t); //和桌边相撞
y=y+v*sin(t);
if(x+r+40>l||x-r<40)t=pi-t;
if(y+r+40>w||y-r<40)t=-t;
v=v-acc;
if(v<0)v=0;
}
//ballarm类成员实现***********************************************************************************
//构造函数
ballarm::ballarm()
{
mouse1=GetMouseMsg();
pointx2=mouse1.x;
pointy2=mouse1.y;
}
//重设参数
void ballarm::reset(ball &ball10)
{
mouse1=GetMouseMsg();
pointx1=ball10.getx();
pointy1=ball10.gety();
pointx2=mouse1.x;
pointy2=mouse1.y;
}
//获得鼠标信息并计算力的大小
bool ballarm::hit(ball &ball10)
{
for(int k=0;;k++)
{
mouse1=GetMouseMsg();
pointx1=ball10.getx();
pointy1=ball10.gety();
pointx2=mouse1.x;
pointy2=mouse1.y;
if(mouse1.uMsg==WM_LBUTTONDOWN)
{
vset=sqrt((pointx2-pointx1)*(pointx2-pointx1)+(pointy2-pointy1)*(pointy2-pointy1))/400;
tset=atan(pointy2-pointy1,pointx2-pointx1);
return true;
}
else return false;
}
}
//画杆
void ballarm::draw()
{
setlinecolor(WHITE);
setlinestyle(PS_DASH);
line(pointx1,pointy1,pointx2,pointy2);
}
//background类成员实现***********************************************************************************
//画背景
void background::drawbackground()
{
putimage(0,0,&img);
}
//开始界面
int background::initial()
{
putimage(0,0,&img2);
MOUSEMSG m;
while(true)
{
m=GetMouseMsg();
if(m.uMsg==WM_LBUTTONDOWN)return 1;
}
}
//show函数实现******************************************************************************************
void show(ball *balls,ballarm &arm,background &back1)
{
float distance=30; //小球恰好相碰时间距
float dis[11][2]; //数组存放距离和小球的标号
int k1,k2;
while(1)
{
BeginBatchDraw(); //开始画图
cleardevice();
back1.drawbackground();
for(int i1=0;i1<11;i1++)
{ //小球开始运动
balls[i1].move(back1.Getl(),back1.Getw());
}
for(int i=0;i<11;i++)
{
dis[i][0]=10000;
dis[i][1]=-1;
}
//记录最近的小球的标号和距离
for(k1=0;k1<11;k1++)
for(k2=0;k2<11;k2++)
{
if(k1!=k2)
{
float dist;
dist=(balls[k2].getx()-balls[k1].getx())*(balls[k2].getx()-balls[k1].getx())+(balls[k2].gety()-balls[k1].gety())*(balls[k2].gety()-balls[k1].gety());
if(dist<dis[k1][0])
{
dis[k1][0]=dist;
dis[k1][1]=k2;
}
}
}
//和最近的小球碰撞
for(k1=0;k1<11;k1++)
{
if(dis[k1][0]<distance*distance)
{
/*设球k1,球k2,以球k1为原点,k1k2方向建立平面直角坐标系,
k1k2方向交换速度,法向速度不变*/
k2=dis[k1][1];
if(balls[k1].numcheck()==false&&balls[k2].numcheck()==false)
{
float a=acos((balls[k2].getx()-balls[k1].getx())/distance,balls[k2].gety()-balls[k1].gety());
float a_t1=balls[k1].gett()-a;
float a_t2=balls[k2].gett()-a;
float a_vx1=balls[k1].getv()*cos(a_t1);
float a_vx2=balls[k2].getv()*cos(a_t2);
float a_vy1=balls[k1].getv()*sin(a_t1);
float a_vy2=balls[k2].getv()*sin(a_t2);
setfillcolor(BLACK);
fillcircle(balls[k2].getx(),balls[k2].gety(),15);
float ballsk1_v=sqrt(a_vx2*a_vx2+a_vy1*a_vy1); //碰撞之后坐标系转回原坐标系
float ballsk2_v=sqrt(a_vx1*a_vx1+a_vy2*a_vy2);
float ballsk1_t=atan(a_vy1,a_vx2)+a;
float ballsk2_t=atan(a_vy2,a_vx1)+a;
float ballsk2_x=balls[k1].getx()+(distance)*cos(a);
float ballsk2_y=balls[k1].gety()+(distance)*sin(a);
balls[k1].setagain(ballsk1_v,ballsk1_t);
balls[k2].setagain(ballsk2_v,ballsk2_t);
balls[k2].setxy(ballsk2_x,ballsk2_y);
dis[k2][0]=10000; //重设数组避免二次交换速度
dis[k2][1]=-1;
balls[k2].draw();
}
}
}
bool checkmove=true;
for(int j=0;j<11;j++) //小球全停止才能实施打击
if(balls[j].getv()!=0)
{
checkmove=false;
break;
}
if(checkmove==true)
{
if(arm.hit(balls[10])==true)
{
balls[10].setagain(arm.getvset(),arm.gettset());
}
arm.draw();
}
int numcal=0; //小球个数清零
for(i=0;i<11;i++)
{
if(balls[i].numcheck()==false) //画没有进洞的小球
{
numcal++;
balls[i].draw();
}
}
if(balls[10].numcheck()==false)numcal--;
char s[5]; //输出得分
settextstyle(25,0,_T("黑体"));
outtext("Your Score: ");
sprintf(s, "%d", 10-numcal);
outtext(s);
if(balls[10].numcheck()==true) //检测输赢
{
RECT r = {0, 0, 1000, 500};
drawtext(_T("You Lose"), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
if(numcal==0&&balls[10].numcheck()==false)
{
RECT r = {0, 0, 1000, 500};
drawtext(_T("You Win"), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
FlushBatchDraw();
EndBatchDraw();
}
}