C语言EasyX详解(小球碰撞)

首先先来认识下EasyX
EasyX 是针对 C/C++ 的图形库,可以帮助使用C/C++语言的程序员快速上手图形和游戏编程。
比如,可以用 VC + EasyX 很快的用几何图形画一个房子,或者一辆移动的小车,可以编写俄罗斯方块、贪吃蛇、黑白棋等小游戏,可以练习图形学的各种算法,等等。

 

1.静止小球

#include <conio.h>
#include <graphics.h>
int main()
{
	initgraph(640,480);		//初始化画布大小
    setcolor(YELLOW);		//圆的线条颜色
    setfillcolor(GREEN);	//圆内部填充颜色
    fillcircle(100,100,20);	//圆位置以及半径
	getch();				//按任意键继续
	closegraph();			//关闭图形界面
	
	initgraph(640,256);		//初始化画布
	for(int y=0;y<256;y++)
	{
		setcolor(RGB(0,y,y));
		line(0,y,640,y);		//画线
	}
	getch();
	closegraph();
	return 0;
}

在这里插入图片描述

2.颜色渐变实现

#include <conio.h>
#include <graphics.h>
int main()
{
	initgraph(640,256);		//初始化画布
	for(int y=0;y<256;y++)
	{
		setcolor(RGB(0,y,y));
		line(0,y,640,y);		//画线
	}
	getch();
	closegraph();
	return 0;
}

在这里插入图片描述

3.围棋棋盘

#include <conio.h>
#include <graphics.h>
int main()
{
	initgraph(800,800);	
	setcolor(YELLOW);
	for(int i=0;i<801;i++)
	{
		line(0,i,841,i);
	}
	setcolor(BLACK);
	for(int j=40;j<761;j+=40)
	{
		line(40,j,760,j);
		line(j,40,j,760);		
	}
	setfillcolor(BLACK);
	fillcircle(160,160,4);		//在围棋的九个点上画圆
	fillcircle(160,400,4);
	fillcircle(160,640,4);
	fillcircle(400,160,4);
	fillcircle(400,400,4);
	fillcircle(400,640,4);
	fillcircle(640,160,4);
	fillcircle(640,400,4);
	fillcircle(640,640,4);
	getch();
	closegraph();
	return 0;
}

在这里插入图片描述

4.国际象棋棋盘

#include <conio.h>
#include <graphics.h>
int main()
{
	//国际象棋棋盘
	initgraph(640,640);	
	for(int i=0;i<640;i+=80)
	{
		for(int j=0;j<640;j+=80)
		{
			if(j/80%2==0)
			{
				if(i/80%2==0)
				{
					setfillcolor(BLACK);
					fillrectangle(j,i,j+80,i+80);
				}
				if(i/80%2==1)
				{
					setfillcolor(WHITE);
					fillrectangle(j,i,j+80,i+80);
				}
			}
			if(j/80%2==1)
			{
				if(i/80%2==1)
				{
					setfillcolor(BLACK);
					fillrectangle(j,i,j+80,i+80);
				}
				if(i/80%2==0)
				{
					setfillcolor(WHITE);
					fillrectangle(j,i,j+80,i+80);
				}
			}
		}
	}
	getch();
	closegraph();
	return 0;
}

在这里插入图片描述

5.小球运动

#include <conio.h>
#include <graphics.h>
#include <time.h>
int main()
{
	int ball_x,ball_y;		//小球位置坐标
	int ball_vx=1;			//小球X轴与Y轴的速度
	int ball_vy=1;
	//随机生成小球初始位置
	srand((unsigned)time(NULL));
	ball_x=rand()%600+20;
	ball_y=rand()%360+20;
	initgraph(640,400);
	BeginBatchDraw();			//这个函数用于开始批量绘图,执行后任何绘图操作都将暂时不输出到屏幕上。
	while(1)
	{
		setcolor(YELLOW);
		setfillcolor(GREEN);
		fillcircle(ball_x,ball_y,20);
		Sleep(2);
		FlushBatchDraw();		//将之前的绘图输出,这个函数用于执行未完成的绘图人物。
		setcolor(BLACK);
		setfillcolor(BLACK);
		fillcircle(ball_x,ball_y,20);
		ball_x=ball_x+ball_vx;
		ball_y=ball_y+ball_vy;
		//当小球表面接触墙壁时发生碰撞反弹
		if(ball_x<=20||ball_x>=620)
			ball_vx=-ball_vx;
		if(ball_y<=20||ball_y>=380)
			ball_vy=-ball_vy;
		
	}
	EndBatchDraw();		//结束批量绘制,并执行未完成的绘图任务
	closegraph();
	return 0;
}

在这里插入图片描述

6.多个小球移动

#include <conio.h>
#include <graphics.h>
#include <time.h>
#define number 10		//小球个数
struct Ball
{
	int ball_x;
	int ball_y;
	int ball_vx;
	int ball_vy;
};
Ball balls[number];
int main()
{
//初始化所有小球位置
	srand((unsigned)time(NULL));
	for(int i=0;i<number;i++)
	{
		balls[i].ball_x=rand()%600+20;
		balls[i].ball_y=rand()%360+20;
		balls[i].ball_vx=1;
		balls[i].ball_vy=1;
		//printf("[%d,%d]\n",balls[i].ball_x,balls[i].ball_y);
	}
	initgraph(640,400);
	BeginBatchDraw();
	while(1)
	{
		setcolor(YELLOW);
		setfillcolor(GREEN);
		//绘制所有小球
		for(int i=0;i<number;i++)
		{
			fillcircle(balls[i].ball_x,balls[i].ball_y,20);
		}
		Sleep(2);
		FlushBatchDraw();
		setcolor(BLACK);
		setfillcolor(BLACK);
		//改变所有小球坐标
		for(i=0;i<number;i++)
		{
			fillcircle(balls[i].ball_x,balls[i].ball_y,20);
			balls[i].ball_x=balls[i].ball_x+balls[i].ball_vx;
			balls[i].ball_y=balls[i].ball_y+balls[i].ball_vy;
			if(balls[i].ball_x<=20||balls[i].ball_x>=620)
				balls[i].ball_vx=-balls[i].ball_vx;
			if(balls[i].ball_y<=20||balls[i].ball_y>=380)
				balls[i].ball_vy=-balls[i].ball_vy;
		}
	}
	EndBatchDraw();
	closegraph();
}

在这里插入图片描述

7.多个小球碰撞

从上面可以看出,多个小球运动是有相互交错的部分,我们可以增加碰撞功能

#include <conio.h>
#include <graphics.h>
#include <time.h>
#define number 10		//小球个数
struct Ball
{
	int ball_x;
	int ball_y;
	int ball_vx;
	int ball_vy;
	int distance[2];		//记录某个小球,距离它最近的小球的距离,以及这个小球的下标
};
Ball balls[number];

int main()
{
	void get_distance(struct Ball balls[number]);
	void knock(struct Ball balls[number]);
	//初始化所有小球位置
	srand((unsigned)time(NULL));
	for(int i=0;i<number;i++)
	{
		balls[i].ball_x=rand()%600+20;
		balls[i].ball_y=rand()%360+20;
				for(int j=0;j<number;j++)
			if(i!=j)		//不用和自己比
			{
				//初始化让小球不会轻易重叠
				if((balls[i].ball_x>=balls[j].ball_x-20)&&(balls[i].ball_x<=balls[j].ball_x+20)&&
					(balls[i].ball_y>=balls[j].ball_y-20)&&(balls[i].ball_y<=balls[j].ball_y+20))
				{
					balls[i].ball_x=rand()%600+20;
					balls[i].ball_y=rand()%360+20;
				}
			}
		balls[i].ball_vx=1;
		balls[i].ball_vy=1;
		//printf("[%d,%d]\n",balls[i].ball_x,balls[i].ball_y);
	}
	for (i=0;i<number;i++)
    {
        balls[i].distance[0] = 99999999;
        balls[i].distance[1] = -1;
    }
	initgraph(640,400);
	BeginBatchDraw();
	while(1)
	{
		setcolor(YELLOW);
		setfillcolor(GREEN);
		//绘制所有小球
		for(int i=0;i<number;i++)
		{
			fillcircle(balls[i].ball_x,balls[i].ball_y,20);
		}
		get_distance(balls);
		knock(balls);
		Sleep(2);
		FlushBatchDraw();
		setcolor(BLACK);
		setfillcolor(BLACK);
		//改变所有小球坐标
		for(i=0;i<number;i++)
		{
			fillcircle(balls[i].ball_x,balls[i].ball_y,20);
			balls[i].ball_x=balls[i].ball_x+balls[i].ball_vx;
			balls[i].ball_y=balls[i].ball_y+balls[i].ball_vy;
			if(balls[i].ball_x<=20||balls[i].ball_x>=620)
				balls[i].ball_vx=-balls[i].ball_vx;
			if(balls[i].ball_y<=20||balls[i].ball_y>=380)
				balls[i].ball_vy=-balls[i].ball_vy;
		}
	}
	EndBatchDraw();
	closegraph();
	
	return 0;
}
int i,j;
void get_distance(struct Ball balls[number])
{
	// 求解所有小球两两之间的距离平方
	for (i=0;i<number;i++)
	{
		for (j=0;j<number;j++)
		{

			if (i!=j) // 自己和自己不需要比
			{
                int dist2;
                dist2 = (balls[i].ball_x - balls[j].ball_x)*(balls[i].ball_x - balls[j].ball_x)
						+(balls[i].ball_y - balls[j].ball_y)*(balls[i].ball_y - balls[j].ball_y);
                if (dist2<balls[i].distance[0])
                    {
                        balls[i].distance[0] = dist2;
                        balls[i].distance[1] = j;
                    }
             }
		}
	}
}

void knock(struct Ball balls[number])
{
	// 判断球之间是否碰撞
    for (i=0;i<number;i++)
    {
         if (balls[i].distance[0]<=4*(20*20)) // 最小距离小于阈值,发生碰撞
         {
              j = balls[i].distance[1];
              // 交换速度             
              int temp;
              temp = balls[i].ball_vx; balls[i].ball_vx = balls[j].ball_vx; balls[j].ball_vx = temp;
              temp = balls[i].ball_vy; balls[i].ball_vy = balls[j].ball_vy; balls[j].ball_vy = temp;

              balls[j].distance[0] = 99999999; // 避免交换两次速度,将两个小球重新赋值
              balls[j].distance[1] = -1;
			  
              balls[i].distance[0] = 99999999; 
              balls[i].distance[1] = -1;
          }
     }
}

在这里插入图片描述
在这里插入图片描述

posted @ 2023-03-13 11:45  h云淡风轻  阅读(121)  评论(0编辑  收藏  举报  来源