Dev-C++使用EGE绘图库实现燃放灿烂烟花的编写和发布

Dev-C++使用EGE绘图库实现燃放灿烂烟花的编写和发布


前提是为Dev-C++配置EGE绘图库,详见
Dev-C++ 使用EGE绘图库编程入门  https://blog.csdn.net/cnds123/article/details/109982100

灿烂烟花程序的编写

灿烂烟花程序的目录结构:

Dev-C++使用EGE绘图库实现燃放灿烂烟花的编写和发布_第1张图片

背景图片:

Dev-C++使用EGE绘图库实现燃放灿烂烟花的编写和发布_第2张图片

 背景音乐自己找个吧,文件名 背景音乐.mp3

燃放烟花.cpp 文件内容如下:

#include 
#include 
#include "fireworks.cpp"
#include "fireworks.h"
#define NUM_FIREWORKS 12	//烟花数量,12左右比较好,多了太密集

int main()
{
	initgraph(860, 660, INIT_RENDERMANUAL);

	srand((unsigned)time(NULL));

	//烟花
	Fireworks* fireworks = new Fireworks[NUM_FIREWORKS];

	//背景图(860 x 660)
	PIMAGE bgPimg = newimage();
	getimage(bgPimg, "背景图片.jpg");
	//先绘制一下,不然前面有空白期
	putimage(0, 0, bgPimg);
	delay_ms(0);

	//背景音乐
	MUSIC bgMusic;
	bgMusic.OpenFile("背景音乐.mp3");
	bgMusic.SetVolume(1.0f);
	if (bgMusic.IsOpen()) {
		bgMusic.Play(0);
	}

	
	//图像缓存, 因为要加背景图,直接加模糊滤镜会把背景图模糊掉
	//所以另设一个图像缓存来绘制烟花并加模糊滤镜,再绘制到窗口
	PIMAGE cachePimg = newimage(860, 660);
	
	//计时用,主要用来定时检查音乐播放
	int timeCount = 0;

	for (; is_run(); delay_fps(60))
	{
		//隔1秒检查一下,如果播放完了,重新播放
		if ((++timeCount % 60 == 0) && (bgMusic.GetPlayStatus() == MUSIC_MODE_STOP)) {
			bgMusic.Play(0);
		}
		//更新位置
		for (int i = 0; i < NUM_FIREWORKS; i++) {
			fireworks[i].update();
		}

		//绘制背景
		putimage(0, 0, bgPimg);

		//绘制烟花到图像缓存中
		for (int i = 0; i < NUM_FIREWORKS; i++) {
			fireworks[i].draw(cachePimg);
		}

		//模糊滤镜,拖尾效果
		//第二个参数,模糊度,越大越模糊,粒子也就越粗
		//第三个参数,亮度,越大拖尾越长
		//可以试试一下其它参数搭配,例如以下几组:
		//0x03, 0xff
		//0x0b, 0xe0
		//0xff, 0xff
		imagefilter_blurring(cachePimg, 0x0a, 0xff);

		//缓存绘制到窗口,模式为(最终颜色 = 窗口像素颜色 Or 图像像素颜色), 这样颜色会叠加起来
		putimage(0, 0, cachePimg, SRCPAINT);

	}

	delete[] fireworks;

	delimage(bgPimg);
	delimage(cachePimg);

	bgMusic.Close();

	closegraph();

	return 0;
}

fireworks.cpp 文件内容如下:

#include 
#define SHOW_CONSOLE
#include "fireworks.h"

const double Fireworks::particleSpeed = 3.0f;

Fireworks::Fireworks()
{
	init();
}

void Fireworks::init()
{
	delayTime = rand() % 300 + 20;
	riseTime = rand() % 80 + 160;
	bloomTime = 160;

	risePos.x = rand() % 450 + 300.0f;
	risePos.y = GROUND;

	riseSpeed.y = myrand(1.0f) - 3.0f;	//上升速度,根据坐标系需要是负的
	riseSpeed.x = myrand(0.4f) - 0.2f;	//可稍微倾斜

	//随机颜色
	color = HSVtoRGB(myrand(360.0f), 1.0f, 1.0f);

	//给每一个粒子设置初始速度
	for (int i = 0; i < NUM_PARTICLE - 1; i += 2)
	{
		//为了球状散开,设初始速度大小相等
		//初始随机速度水平角度和垂直角度,因为看到是平面的,所以求x, y分速度
		double levelAngle = randomf() * 360;
		double verticalAngle = randomf() * 360;

		//速度投影到xOy平面
		double xySpeed = particleSpeed * cos(verticalAngle);

		//求x, y分速度
		p[i].speed.x = xySpeed * cos(levelAngle);
		p[i].speed.y = xySpeed * sin(levelAngle);

		//动量守恒,每对速度反向
		if (i + 1 < NUM_PARTICLE) {
			p[i + 1].speed.x = -p[i].speed.x;
			p[i + 1].speed.y = -p[i].speed.y;
		}
	}
}

void Fireworks::draw(PIMAGE pimg)
{
	//未开始
	if (delayTime > 0)
		return;
	//烟花上升阶段
	else if (riseTime > 0) {
		setfillcolor(color, pimg);
		//画四个点,这样大一些
		bar(risePos.x, risePos.y, risePos.x + 2, risePos.y + 2, pimg);
	}
	//烟花绽放阶段
	else {
		setfillcolor(color, pimg);
		for (int i = 0; i < NUM_PARTICLE; i++) {
			bar(p[i].pos.x, p[i].pos.y, p[i].pos.x + 2, p[i].pos.y + 2, pimg);
		}
	}
}

//更新位置等相关属性
void Fireworks::update()
{
	if (delayTime-- > 0)
		return;
	//处于上升阶段,只更新烟花位置
	else if (riseTime > 0) {
		risePos.x += riseSpeed.x;
		risePos.y += riseSpeed.y;

		//重力作用
		riseSpeed.y += 0.005;

		//上升完毕,到达爆炸阶段
		if (--riseTime <= 0) {
			//设粒子初始位置为烟花当前位置
			for (int i = 0; i < NUM_PARTICLE; i++) {
				p[i].pos.x = risePos.x;
				p[i].pos.y = risePos.y;
			}
		}
	}
	//烟花绽放阶段
	else if (bloomTime-- > 0) {
		//粒子散开,更新粒子位置
		for (int i = 0; i < NUM_PARTICLE; i++) {
			p[i].pos.x += p[i].speed.x;
			p[i].pos.y += p[i].speed.y;

			//重力作用
			p[i].speed.y += 0.005;

			//速度减慢
			p[i].speed.x *= 0.982;
			p[i].speed.y *= 0.982;
		}
	}
	else {
		//烟花重新开始
		init();
	}
}

fireworks.h 文件内容如下:

#pragma once

#ifndef  FIREWORKS_H_
#define FIREWORKS_H_

#include 

#define myrand(m) ((float)rand() * m / 36565)

struct Speed {
	double x, y;
};

struct Pos {
	double x, y;
};

struct Particle
{
	Pos pos;
	Speed speed;
};


#define GROUND 580	//地面位置

class Fireworks//烟花类			
{
private:

	static const int NUM_PARTICLE = 200;
	static const double particleSpeed;
	Particle p[NUM_PARTICLE];

	color_t color;

	int delayTime;		//延迟时间
	int riseTime;		//上升时间
	int bloomTime;		//爆炸时间

	Pos risePos;		//上升阶段位置
	Speed riseSpeed;	//上升速度

public:
	//初始化
	Fireworks();

	void init();

	//更新位置等相关属性
	void update();

	//根据属性值绘画
	void draw(PIMAGE pimg = NULL);
};

#endif // ! FIREWORKS_H_

灿烂烟花程序的发布

使用菜单命令“Execute -> Compile”编译之,

Dev-C++使用EGE绘图库实现燃放灿烂烟花的编写和发布_第3张图片

若没有错误,得到可执行程序:燃放烟花.exe

新建一个文件夹,我这里是“灿烂烟花发布”,将前面得到的可执行程序“燃放烟花.exe”,和资源文件,这里是 “背景音乐.mp3” 和 “背景图片.jpg” 复制到,这个文件夹中。然后复制“灿烂烟花发布”文件夹给好朋友试试吧。

Dev-C++使用EGE绘图库实现燃放灿烂烟花的编写和发布_第4张图片

 

双击“燃放烟花.exe”,运行效果如下:

OK !

你可能感兴趣的:(C,C++学习,编程实践系列,c++,开发语言,趣味程序)