c语言入门好课分享

#include <graphics.h>

#include <math.h>

#include <time.h>


#define WIDTH		1000		// 屏幕宽度

#define HEIGHT		800			// 屏幕高度

#define NUM_BALLS	1024		// 小球数目

#define	FRICTION	0.95f		// 摩擦力/阻尼系数


// 定义小球结构

struct Ball

{

	COLORREF color;	// 颜色

	float x, y;		// 坐标

	float vx, vy;	// 速度

	float radius;	// 半径

};


// 定义全局变量

Ball balls[NUM_BALLS];		// 小球数组

int mouseX, mouseY;			// 当前鼠标坐标

int prevMouseX, prevMouseY;	// 上次鼠标坐标

int mouseVX, mouseVY;		// 鼠标移动速度

int isMouseDown;			// 鼠标左键是否按下


// 绝对延时

void delay(DWORD ms)

{

	static DWORD oldtime = GetTickCount();

	while (GetTickCount() - oldtime < ms)

		Sleep(1);

	oldtime = GetTickCount();

}


void startup() // 初始化函数

{

	// 初始化随机种子

	srand(time(0));  // 随机种子函数


	initgraph(WIDTH, HEIGHT); // 新建画布


	// 初始化小球数组

	for (int i = 0; i < NUM_BALLS; i++)

	{

		balls[i].color = RGB(rand() % 255, rand() % 255, rand() % 255);

		balls[i].x = rand() % WIDTH;

		balls[i].y = rand() % HEIGHT;

		balls[i].vx = float(cos(float(i))) * (rand() % 35);

		balls[i].vy = float(sin(float(i))) * (rand() % 35);

		balls[i].radius = (rand() % 35) / 18.0;

	}


	// 初始化鼠标变量,当前鼠标坐标、上次鼠标坐标都在画布中心

	mouseX = prevMouseX = WIDTH / 2;

	mouseY = prevMouseY = HEIGHT / 2;

	isMouseDown = 0; // 初始鼠标未按下


	BeginBatchDraw(); //  开始批量绘制 

}


void show() //  绘制函数

{

	cleardevice();	// 清屏


	for (int i = 0; i < NUM_BALLS; i++)

	{

		// 画小球

		setcolor(balls[i].color);

		setfillstyle(balls[i].color);

		fillcircle(int(balls[i].x + 0.5), int(balls[i].y + 0.5), int(balls[i].radius + 0.5));

	}


	FlushBatchDraw(); // 批量绘制

	delay(5); // 暂停

}


void updateWithoutInput() //  与输入无关的更新

{

	float toDist = WIDTH * 0.85;  // 吸引距离,小球距离鼠标在此范围内,会受到向内的吸力

	float blowDist = WIDTH * 0.4;   // 打击距离,小球距离鼠标在此范围内,会受到向外的斥力

	float stirDist = WIDTH * 0.15; // 扰动距离,小球距离鼠标在此范围内,会受到鼠标的扰动


	// 前后两次运行间鼠标移动的距离,即为鼠标的速度

	mouseVX = mouseX - prevMouseX;

	mouseVY = mouseY - prevMouseY;


	// 更新上次鼠标坐标变量,记录为当前鼠标的坐标

	prevMouseX = mouseX;

	prevMouseY = mouseY;


	for (int i = 0; i < NUM_BALLS; i++)  // 对所有小球遍历

	{

		float x = balls[i].x;  // 当前小球坐标

		float y = balls[i].y;

		float vx = balls[i].vx;  // 当前小球速度

		float vy = balls[i].vy;


		float dx = x - mouseX;    // 计算当前小球位置和鼠标位置的差

		float dy = y - mouseY;

		float d = sqrt(dx * dx + dy * dy);    // 当前小球和鼠标位置的距离


		// 下面将dx、dy归一化,仅反映方向,和距离大小无关

		if (d != 0)

		{

			dx = dx / d;

			dy = dy / d;

		}

		else

		{

			dx = 0;

			dy = 0;

		}


		// 小球距离鼠标 < toDist,在此范围内小球会受到鼠标的吸引

		if (d < toDist)

		{

			// 吸引力引起的加速度幅度,小球距离鼠标越近,引起的加速度越大

			float toAcc = (1 - (d / toDist)) * WIDTH * 0.0013f;

			// 由dx、dy归一化方向信息,加速度幅度值toAcc,得到新的小球速度

			vx = vx - dx * toAcc;

			vy = vy - dy * toAcc;

		}


		// 当鼠标左键按下,并且小球距离鼠标 < blowDist(在打击范围内,会受到向外的力)

		if (isMouseDown && d < blowDist)

		{

			// 打击力引起的加速度幅度(Acceleration),这个公式表示小球距离鼠标越近,打击斥力引起的加速度越大

			float blowAcc = (1 - (d / blowDist)) * 11;

			// 由上面得到的dx、dy归一化方向信息,上面的加速度幅度值blowAcc,得到新的小球速度

			// 0.5f - float(rand()) / RAND_MAX 产生[-0.5,0.5]之间的随机数,加入一些扰动

			vx = vx + dx * blowAcc + 0.5f - float(rand()) / RAND_MAX;

			vy = vy + dy * blowAcc + 0.5f - float(rand()) / RAND_MAX;

		}


		// 小球距离鼠标 < stirDist,在此范围内小球会受到鼠标的扰动

		if (d < stirDist)

		{

			// 扰动力引起的加速度幅度,小球距离鼠标越近,引起的加速度越大。扰动力的值更小

			float mAcc = (1 - (d / stirDist)) * WIDTH * 0.00026f;

			// 鼠标速度越快,引起的扰动力越大

			vx = vx + mouseVX * mAcc;

			vy = vy + mouseVY * mAcc;

		}


		// 小球运动有一个阻尼(摩擦力),速度逐渐减少

		vx = vx * FRICTION;

		vy = vy * FRICTION;


		// 速度的绝对值

		float avgVX = fabs(vx);

		float avgVY = fabs(vy);

		// 两个方向速度的平均

		float avgV = (avgVX + avgVY) * 0.5f;


		// 因为有上面阻尼的作用,如果速度过小的话,乘以一个[0,3]的随机数,会以比较大的概率让速度变大

		if (avgVX < 0.1)

			vx = vx * float(rand()) / RAND_MAX * 3;

		if (avgVY < 0.1)

			vy = vy * float(rand()) / RAND_MAX * 3;


		// 小球的半径在[0.5,2.0]之间,速度越大,半径越大

		float sc = avgV * 0.4f;

		sc = max(min(sc, 2.0f), 0.5f);

		balls[i].radius = sc;


		// 根据位置+速度,更新小球的坐标

		float nextX = x + vx;

		float nextY = y + vy;


		// 小球如果超过上下左右四个边界的话,位置设为边界处,速度反向

		if (nextX > WIDTH)

		{

			nextX = WIDTH;

			vx = -1 * vx;

		}

		else if (nextX < 0)

		{

			nextX = 0;

			vx = -1 * vx;

		}

		if (nextY > HEIGHT)

		{

			nextY = HEIGHT;

			vy = -1 * vy;

		}

		else if (nextY < 0)

		{

			nextY = 0;

			vy = -1 * vy;

		}


		// 更新小球位置、速度的结构体数组

		balls[i].vx = vx;

		balls[i].vy = vy;

		balls[i].x = nextX;

		balls[i].y = nextY;

	}

}


void updateWithInput()

{

	MOUSEMSG m;		// 定义鼠标消息

	while (MouseHit())  //检测当前是否有鼠标消息

	{

		m = GetMouseMsg();

		if (m.uMsg == WM_MOUSEMOVE) // 鼠标移动的话,更新当前鼠标坐标变量

		{

			mouseX = m.x;

			mouseY = m.y;

		}

		else if (m.uMsg == WM_LBUTTONDOWN)  // 鼠标左键按下

			isMouseDown = 1;

		else if (m.uMsg == WM_LBUTTONUP)    // 鼠标左键抬起

			isMouseDown = 0;

	}

}


int main()

{

	startup();  // 数据初始化	

	while (1)  //  游戏循环执行

	{

		show();  // 显示画面

		updateWithInput();     // 与用户输入有关的更新

		updateWithoutInput();  // 与用户输入无关的更新

	}

	return 0;

}


这是河海大学童晶老师主教的一门课:基于游戏开发的C语言程序设计入门与实践_河海大学_中国大学MOOC(慕课)

上面的代码也是课程中的

用游戏敲开c语言编程的大门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值