第一个版本:静止小球的初始化和显示
#define WIDTH 1024 //屏幕的宽
#define HEIGHT 768 //屏幕的高
#define NUM_MOVERS 800 //小球的数量
//定义小球结构
struct Mover
{
COLORREF color; //颜色
float x, y; //坐标
float vx, vy; //速度
float radius; //半径
};
//定义全局变量
Mover movers[NUM_MOVERS]; //小球数组,每个数组元素都是一个结构体
void startup()
{
//设置随机种子
srand((unsigned int)time(NULL));
//初始化小球数组
for (int i = 0; i < NUM_MOVERS;i++)
{
movers[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
movers[i].x = rand() % WIDTH;
movers[i].y = rand() % HEIGHT;
movers[i].vx = float(cos(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦,重点!
movers[i].vy = float(sin(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦
movers[i].radius = (rand() % 34) / 15.0;
}
initgraph(WIDTH, HEIGHT);
BeginBatchDraw();
}
void show()
{
clearrectangle(0, 0, WIDTH - 1, HEIGHT - 1); //清空画面中的全部矩形区域
for (int i = 0; i < NUM_MOVERS;i++)
{
//画小球
setcolor(movers[i].color);
setfillstyle(movers[i].color);
fillcircle(int(movers[i].x + 0.5), int(movers[i].y + 0.5), int(movers[i].radius + 0.5));
}
FlushBatchDraw();
Sleep(2);
}
void updateWithoutInput()
{
}
void updateWithInput()
{
}
void gameover()
{
EndBatchDraw();
closegraph();
}
int main()
{
startup();
while (1)
{
show();
updateWithoutInput();
updateWithInput();
}
gameover();
return 0;
}
image.png
================================================================
第二版本:小球的运动与反弹
#include<stdio.h>
#include<string.h>
#include<stdlib.h> //清屏命令在这里。
#include <windows.h> //延时10毫秒-sleep,gotoxy函数
#include <iostream>
#include <conio.h> //getch()----不用按回车,就可以输入字符。
#include <graphics.h> //EasyX库,所使用的!
#include <math.h> //三角函数
#include <algorithm> //sort函数排序方法,https://blog.csdn.net/BIGKALA/article/details/81624691,这是方法适用的地址
#include <time.h>
using namespace std;
#define WIDTH 1024 //屏幕的宽
#define HEIGHT 768 //屏幕的高
#define NUM_MOVERS 800 //小球的数量
//定义小球结构
struct Mover
{
COLORREF color; //颜色
float x, y; //坐标
float vx, vy; //速度
float radius; //半径
};
//定义全局变量
Mover movers[NUM_MOVERS]; //小球数组,每个数组元素都是一个结构体
void startup()
{
//设置随机种子
srand((unsigned int)time(NULL));
//初始化小球数组
for (int i = 0; i < NUM_MOVERS;i++)
{
movers[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
movers[i].x = rand() % WIDTH;
movers[i].y = rand() % HEIGHT;
movers[i].vx = float(cos(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦,重点!
movers[i].vy = float(sin(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦
movers[i].radius = (rand() % 34) / 15.0;
}
initgraph(WIDTH, HEIGHT);
BeginBatchDraw();
}
void show()
{
clearrectangle(0, 0, WIDTH - 1, HEIGHT - 1); //清空画面中的全部矩形区域
for (int i = 0; i < NUM_MOVERS;i++)
{
//画小球
setcolor(movers[i].color);
setfillstyle(movers[i].color);
fillcircle(int(movers[i].x + 0.5), int(movers[i].y + 0.5), int(movers[i].radius + 0.5));
}
FlushBatchDraw();
Sleep(2);
}
void updateWithoutInput()
{
for (int i = 0; i < NUM_MOVERS;i++) //对所有小球进行遍历
{
float x = movers[i].x; //当前小球的坐标
float y = movers[i].y;
float vx = movers[i].vx; //当前小球的速度
float vy = movers[i].vy;
//根据 位置+速度,来更新小球的坐标
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;
}
//更新小球位置,速度的结构体数组
movers[i].vx = vx;
movers[i].vy = vy;
movers[i].x = nextX;
movers[i].y = nextY;
}
}
void updateWithInput()
{
}
void gameover()
{
EndBatchDraw();
closegraph();
}
int main()
{
startup();
while (1)
{
show();
updateWithoutInput();
updateWithInput();
}
gameover();
return 0;
}
效果图片。注意图片里的小球都是动态的
image.png
======================================================================
第三版本:小球运动的规范化
加入了阻尼运动
#define WIDTH 1024 //屏幕的宽
#define HEIGHT 768 //屏幕的高
#define NUM_MOVERS 800 //小球的数量
#define FRICTION 0.96f //摩擦力,阻力系数
//定义小球结构
struct Mover
{
COLORREF color; //颜色
float x, y; //坐标
float vx, vy; //速度
float radius; //半径
};
//定义全局变量
Mover movers[NUM_MOVERS]; //小球数组,每个数组元素都是一个结构体
void startup()
{
//设置随机种子
srand((unsigned int)time(NULL));
//初始化小球数组
for (int i = 0; i < NUM_MOVERS;i++)
{
movers[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
movers[i].x = rand() % WIDTH;
movers[i].y = rand() % HEIGHT;
movers[i].vx = float(cos(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦,重点!
movers[i].vy = float(sin(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦
movers[i].radius = (rand() % 34) / 15.0;
}
initgraph(WIDTH, HEIGHT);
BeginBatchDraw();
}
void show()
{
clearrectangle(0, 0, WIDTH - 1, HEIGHT - 1); //清空画面中的全部矩形区域
for (int i = 0; i < NUM_MOVERS;i++)
{
//画小球
setcolor(movers[i].color);
setfillstyle(movers[i].color);
fillcircle(int(movers[i].x + 0.5), int(movers[i].y + 0.5), int(movers[i].radius + 0.5));
}
FlushBatchDraw();
Sleep(2);
}
void updateWithoutInput()
{
for (int i = 0; i < NUM_MOVERS;i++) //对所有小球进行遍历
{
float x = movers[i].x; //当前小球的坐标
float y = movers[i].y;
float vx = movers[i].vx; //当前小球的速度
float vy = movers[i].vy;
//小球运动有一个阻尼,受到摩擦力限制,速度逐渐减小.每次循环,就减小一次
vx = vx*FRICTION;
vy = vy*FRICTION;
//速度的绝对值
float avgVX = abs(vx);
float avgVY = abs(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.4-3.5之间,速度越大,半径越大
float sc = avgV*0.45f;
sc = max(min(sc, 3.5f), 0.4f);
movers[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;
}
//更新小球位置,速度的结构体数组
movers[i].vx = vx;
movers[i].vy = vy;
movers[i].x = nextX;
movers[i].y = nextY;
}
}
void updateWithInput()
{
}
void gameover()
{
EndBatchDraw();
closegraph();
}
int main()
{
startup();
while (1)
{
show();
updateWithoutInput();
updateWithInput();
}
gameover();
return 0;
}
===============================================
第四版本:鼠标的吸引力
#define WIDTH 1024 //屏幕的宽
#define HEIGHT 768 //屏幕的高
#define NUM_MOVERS 800 //小球的数量
#define FRICTION 0.96f //摩擦力,阻力系数
//定义小球结构
struct Mover
{
COLORREF color; //颜色
float x, y; //坐标
float vx, vy; //速度
float radius; //半径
};
//定义全局变量
Mover movers[NUM_MOVERS]; //小球数组,每个数组元素都是一个结构体
int mouseX, mouseY; //当前鼠标坐标
void startup()
{
//设置随机种子
srand((unsigned int)time(NULL));
//初始化小球数组
for (int i = 0; i < NUM_MOVERS;i++)
{
movers[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
movers[i].x = rand() % WIDTH;
movers[i].y = rand() % HEIGHT;
movers[i].vx = float(cos(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦,重点!
movers[i].vy = float(sin(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦
movers[i].radius = (rand() % 34) / 15.0;
}
//初始化当前鼠标坐标在画布中心;
mouseX = WIDTH / 2;
mouseY = HEIGHT / 2;
initgraph(WIDTH, HEIGHT);
BeginBatchDraw();
}
void show()
{
clearrectangle(0, 0, WIDTH - 1, HEIGHT - 1); //清空画面中的全部矩形区域
for (int i = 0; i < NUM_MOVERS;i++)
{
//画小球
setcolor(movers[i].color);
setfillstyle(movers[i].color);
fillcircle(int(movers[i].x + 0.5), int(movers[i].y + 0.5), int(movers[i].radius + 0.5));
}
FlushBatchDraw();
Sleep(2);
}
void updateWithoutInput()
{
float toDist = WIDTH *0.86; //吸引距离,如果小球与鼠标的距离在此范围内,就会被吸引
for (int i = 0; i < NUM_MOVERS;i++) //对所有小球进行遍历
{
float x = movers[i].x; //当前小球的坐标
float y = movers[i].y;
float vx = movers[i].vx; //当前小球的速度
float vy = movers[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 )
{
//吸引力引起的加速度服务,小球距离鼠标越近引起的加速度越大 d越来越小--》toACC,越来越大。
float toAcc = (1 - (d / toDist))*WIDTH*0.0014f;
//由dx,dy归一化方向信息,加速度幅度值为toAcc,得到新的小球速度
vx = vx - dx*toAcc;
vy = vy - dy*toAcc;
}
//小球运动有一个阻尼,受到摩擦力限制,速度逐渐减小.每次循环,就减小一次
vx = vx*FRICTION;
vy = vy*FRICTION;
//速度的绝对值
float avgVX = abs(vx);
float avgVY = abs(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.4-3.5之间,速度越大,半径越大
float sc = avgV*0.45f;
sc = max(min(sc, 3.5f), 0.4f);
movers[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;
}
//更新小球位置,速度的结构体数组
movers[i].vx = vx;
movers[i].vy = vy;
movers[i].x = nextX;
movers[i].y = nextY;
}
}
void updateWithInput()
{
MOUSEMSG m; //定义鼠标消息
while (MouseHit()) //检测当前是否有鼠标消息
{
m = GetMouseMsg();
if (m.uMsg==WM_MOUSEMOVE ) //如果鼠标移动,更新当前鼠标坐标变量。
{
mouseX = m.x;
mouseY = m.y;
}
}
}
void gameover()
{
EndBatchDraw();
closegraph();
}
int main()
{
startup();
while (1)
{
show();
updateWithoutInput();
updateWithInput();
}
gameover();
return 0;
}
效果图:
image.png
===========================================================================
第五版本,鼠标的击打斥力
#define WIDTH 1024 //屏幕的宽
#define HEIGHT 768 //屏幕的高
#define NUM_MOVERS 800 //小球的数量
#define FRICTION 0.96f //摩擦力,阻力系数
//定义小球结构
struct Mover
{
COLORREF color; //颜色
float x, y; //坐标
float vx, vy; //速度
float radius; //半径
};
//定义全局变量
Mover movers[NUM_MOVERS]; //小球数组,每个数组元素都是一个结构体
int mouseX, mouseY; //当前鼠标坐标
int isMouseDown; //鼠标左键是否按下
void startup()
{
//设置随机种子
srand((unsigned int)time(NULL));
//初始化小球数组
for (int i = 0; i < NUM_MOVERS;i++)
{
movers[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
movers[i].x = rand() % WIDTH;
movers[i].y = rand() % HEIGHT;
movers[i].vx = float(cos(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦,重点!
movers[i].vy = float(sin(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦
movers[i].radius = (rand() % 34) / 15.0;
}
//初始化当前鼠标坐标在画布中心;
mouseX = WIDTH / 2;
mouseY = HEIGHT / 2;
isMouseDown = 0; //初始鼠标未按下
initgraph(WIDTH, HEIGHT);
BeginBatchDraw();
}
void show()
{
clearrectangle(0, 0, WIDTH - 1, HEIGHT - 1); //清空画面中的全部矩形区域
for (int i = 0; i < NUM_MOVERS;i++)
{
//画小球
setcolor(movers[i].color);
setfillstyle(movers[i].color);
fillcircle(int(movers[i].x + 0.5), int(movers[i].y + 0.5), int(movers[i].radius + 0.5));
}
FlushBatchDraw();
Sleep(2);
}
void updateWithoutInput()
{
float toDist = WIDTH *0.86; //吸引距离,如果小球与鼠标的距离在此范围内,就会被吸引
float blowDist = WIDTH*0.5; //击打距离,小球与鼠标的距离在此范围内,都会受到击打的斥力
for (int i = 0; i < NUM_MOVERS;i++) //对所有小球进行遍历
{
float x = movers[i].x; //当前小球的坐标
float y = movers[i].y;
float vx = movers[i].vx; //当前小球的速度
float vy = movers[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 )
{
//吸引力引起的加速度服务,小球距离鼠标越近引起的加速度越大 d越来越小--》toACC,越来越大。
float toAcc = (1 - (d / toDist))*WIDTH*0.0014f;
//由dx,dy归一化方向信息,加速度幅度值为toAcc,得到新的小球速度
vx = vx - dx*toAcc;
vy = vy - dy*toAcc;
}
//当鼠标左键按下,并且小球距离鼠标<blowDist,在击打范围内时会受到向外的力。
if (isMouseDown && d < blowDist)
{
//击打力引起的加速度幅度,这个公式表示小球距离鼠标越近击打斥力引起的加速度越大
float blowAcc = (1 - (d / blowDist)) * 6;
//0.5f - float(rand()) / RAND_MAX; --->产生-0.5到0.5的随机数,加入一些扰动
//float(rand()) / RAND_MAX --->产生0-1的随机数。
//得到最新的小球速度。
vx = vx + dx*blowAcc + 0.5f - float(rand()) / RAND_MAX;
vy = vy + dy*blowAcc + 0.5f - float(rand()) / RAND_MAX;
}
//小球运动有一个阻尼,受到摩擦力限制,速度逐渐减小.每次循环,就减小一次
vx = vx*FRICTION;
vy = vy*FRICTION;
//速度的绝对值
float avgVX = abs(vx);
float avgVY = abs(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.4-3.5之间,速度越大,半径越大
float sc = avgV*0.45f;
sc = max(min(sc, 3.5f), 0.4f);
movers[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;
}
//更新小球位置,速度的结构体数组
movers[i].vx = vx;
movers[i].vy = vy;
movers[i].x = nextX;
movers[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;
}
}
}
void gameover()
{
EndBatchDraw();
closegraph();
}
int main()
{
startup();
while (1)
{
show();
updateWithoutInput();
updateWithInput();
}
gameover();
return 0;
}
===================================================
第六版本:鼠标的干扰力。实现鼠标移动时对例子的扰动力,类似于在水面上拿树枝搅动,搅动的越快,扰动越大。
#define WIDTH 1024 //屏幕的宽
#define HEIGHT 768 //屏幕的高
#define NUM_MOVERS 800 //小球的数量
#define FRICTION 0.96f //摩擦力,阻力系数
//定义小球结构
struct Mover
{
COLORREF color; //颜色
float x, y; //坐标
float vx, vy; //速度
float radius; //半径
};
//定义全局变量
Mover movers[NUM_MOVERS]; //小球数组,每个数组元素都是一个结构体
int mouseX, mouseY; //当前鼠标坐标
int isMouseDown; //鼠标左键是否按下
int prevMouseX, prevMouseY; //上次鼠标位置
int mouseVX, mouseVY; //鼠标的速度,
void startup()
{
//设置随机种子
srand((unsigned int)time(NULL));
//初始化小球数组
for (int i = 0; i < NUM_MOVERS;i++)
{
movers[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
movers[i].x = rand() % WIDTH;
movers[i].y = rand() % HEIGHT;
movers[i].vx = float(cos(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦,重点!
movers[i].vy = float(sin(float(i)))*(rand() % 34); //这个速度变化不是线性变化哦
movers[i].radius = (rand() % 34) / 15.0;
}
//初始化当前鼠标坐标在画布中心;
mouseX = prevMouseX= WIDTH / 2;
mouseY = prevMouseY= HEIGHT / 2;
isMouseDown = 0; //初始鼠标未按下
initgraph(WIDTH, HEIGHT);
BeginBatchDraw();
}
void show()
{
clearrectangle(0, 0, WIDTH - 1, HEIGHT - 1); //清空画面中的全部矩形区域
for (int i = 0; i < NUM_MOVERS;i++)
{
//画小球
setcolor(movers[i].color);
setfillstyle(movers[i].color);
fillcircle(int(movers[i].x + 0.5), int(movers[i].y + 0.5), int(movers[i].radius + 0.5));
}
FlushBatchDraw();
Sleep(2);
}
void updateWithoutInput()
{
float toDist = WIDTH *0.86; //吸引距离,如果小球与鼠标的距离在此范围内,就会被吸引
float blowDist = WIDTH*0.5; //击打距离,小球与鼠标的距离在此范围内,都会受到击打的斥力
float stirDist = WIDTH*0.125; //扰动距离,小球与鼠标的距离在此范围内,都会受到鼠标的扰动
//前后两次运行间鼠标移动的距离,即为鼠标的速度
mouseVX = mouseX - prevMouseX;
mouseVY = mouseY - prevMouseY;
//为记录这次鼠标的坐标,更新上次鼠标坐标变量。
prevMouseX = mouseX;
prevMouseY = mouseY;
for (int i = 0; i < NUM_MOVERS;i++) //对所有小球进行遍历
{
float x = movers[i].x; //当前小球的坐标
float y = movers[i].y;
float vx = movers[i].vx; //当前小球的速度
float vy = movers[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 )
{
//吸引力引起的加速度服务,小球距离鼠标越近引起的加速度越大 d越来越小--》toACC,越来越大。
float toAcc = (1 - (d / toDist))*WIDTH*0.0014f;
//由dx,dy归一化方向信息,加速度幅度值为toAcc,得到新的小球速度
vx = vx - dx*toAcc;
vy = vy - dy*toAcc;
}
//当鼠标左键按下,并且小球距离鼠标<blowDist,在击打范围内时会受到向外的力。
if (isMouseDown && d < blowDist)
{
//击打力引起的加速度幅度,这个公式表示小球距离鼠标越近击打斥力引起的加速度越大
float blowAcc = (1 - (d / blowDist)) * 6;
//0.5f - float(rand()) / RAND_MAX; --->产生-0.5到0.5的随机数,加入一些扰动
//float(rand()) / RAND_MAX --->产生0-1的随机数。
//得到最新的小球速度。
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 = abs(vx);
float avgVY = abs(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.4-3.5之间,速度越大,半径越大
float sc = avgV*0.45f;
sc = max(min(sc, 3.5f), 0.4f);
movers[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;
}
//更新小球位置,速度的结构体数组
movers[i].vx = vx;
movers[i].vy = vy;
movers[i].x = nextX;
movers[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;
}
}
}
void gameover()
{
EndBatchDraw();
closegraph();
}
int main()
{
startup();
while (1)
{
show();
updateWithoutInput();
updateWithInput();
}
gameover();
return 0;
}
网友评论