C++實(shí)現(xiàn)動(dòng)態(tài)煙花效果
一、前言
C++實(shí)現(xiàn)的放煙花程序
用到了EGE圖形庫,沒有的需要自行安裝
可調(diào)項(xiàng):背景圖和背景音樂、粒子模糊度、亮度以及上升速度的參數(shù)。
實(shí)現(xiàn)的動(dòng)態(tài)煙花非常好看,可以做給女朋友或者表白用hhh
自己做出來玩玩也挺有意思的
二、代碼
fire.h
#pragma once #ifndef FIREWORKS_H_ #define FIREWORKS_H_ #define myrand(m) ((float)rand() * m / 36565) #include <graphics.h> 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; //延遲時(shí)間 int riseTime; //上升時(shí)間 int bloomTime; //爆炸時(shí)間 Pos risePos; //上升階段位置 Speed riseSpeed; //上升速度 public: //初始化 Fireworks(); void init(); //更新位置等相關(guān)屬性 void update(); //根據(jù)屬性值繪畫 void draw(PIMAGE pimg = NULL); }; #endif // ! FIREWORKS_H_
main.cpp
在這里插入代碼片 #include <time.h> #include <graphics.h> #include "fire.h" #define NUM_FIREWORKS 10 //煙花數(shù)量 int main() { initgraph(1080, 720, INIT_RENDERMANUAL); srand((unsigned)time(NULL)); //煙花 Fireworks* fireworks = new Fireworks[NUM_FIREWORKS]; PIMAGE bgPimg = newimage(); getimage(bgPimg, "夜晚.jpg"); //先繪制一下,不然前面有空白期 putimage(0, 0, bgPimg); delay_ms(0); //背景音樂 MUSIC bgMusic; bgMusic.OpenFile("MELANCHOLY.mp3"); bgMusic.SetVolume(1.0f); if (bgMusic.IsOpen()) { bgMusic.Play(0); } //圖像緩存, 因?yàn)橐颖尘皥D,直接加模糊濾鏡會(huì)把背景圖模糊掉 //所以另設(shè)一個(gè)圖像緩存來繪制煙花并加模糊濾鏡,再繪制到窗口 PIMAGE cachePimg = newimage(800, 800); //計(jì)時(shí)用,主要用來定時(shí)檢查音樂播放 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); } //模糊濾鏡,拖尾效果 //第二個(gè)參數(shù),模糊度,越大越模糊,粒子也就越粗 //第三個(gè)參數(shù),亮度,越大拖尾越長 //可以試試一下其它參數(shù)搭配,例如以下幾組: //0x03, 0xff //0x0b, 0xe0 //0xff, 0xff //imagefilter_blurring(cachePimg, 0x0a, 0xff); //imagefilter_blurring(cachePimg, 0x03, 0xff); //imagefilter_blurring(cachePimg, 0x0b, 0xe0); //imagefilter_blurring(cachePimg, 0xff, 0xff); //imagefilter_blurring(cachePimg, 0x01, 0xff); imagefilter_blurring(cachePimg, 0x0b, 0xff); //緩存繪制到窗口,模式為(最終顏色 = 窗口像素顏色 Or 圖像像素顏色), 這樣顏色會(huì)疊加起來 putimage(0, 0, cachePimg, SRCPAINT); } delete[] fireworks; delimage(bgPimg); delimage(cachePimg); bgMusic.Close(); closegraph(); return 0; }
fire.cpp
#include <cmath> #define SHOW_CONSOLE #include "fire.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; //上升速度,根據(jù)坐標(biāo)系需要是負(fù)的 riseSpeed.x = myrand(0.4f) - 0.2f; //可稍微傾斜 //隨機(jī)顏色 color = HSVtoRGB(myrand(360.0f), 1.0f, 1.0f); //給每一個(gè)粒子設(shè)置初始速度 for (int i = 0; i < NUM_PARTICLE - 1; i += 2) { //為了球狀散開,設(shè)初始速度大小相等 //初始隨機(jī)速度水平角度和垂直角度,因?yàn)榭吹绞瞧矫娴?,所以求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); //動(dòng)量守恒,每對(duì)速度反向 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); //畫四個(gè)點(diǎn),這樣大一些 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); } } } //更新位置等相關(guān)屬性 void Fireworks::update() { if (delayTime-- > 0) return; //處于上升階段,只更新煙花位置 else if (riseTime > 0) { risePos.x += riseSpeed.x; risePos.y += riseSpeed.y; //重力作用 riseSpeed.y += 0.005; //上升完畢,到達(dá)爆炸階段 if (--riseTime <= 0) { //設(shè)粒子初始位置為煙花當(dāng)前位置 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(); } }
三、實(shí)現(xiàn)效果
由于煙花是動(dòng)態(tài)的,截圖出來不是很好看,但是做出來動(dòng)態(tài)的煙花其實(shí)是很好看的,大家可以去試試
到此這篇關(guān)于C++實(shí)現(xiàn)動(dòng)態(tài)煙花效果的文章就介紹到這了,更多相關(guān)C++煙花內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C/C++ 原生API實(shí)現(xiàn)線程池的方法
線程池,簡單來說就是有一堆已經(jīng)創(chuàng)建好的線程,接下來通過本文給大家介紹C/C++ 原生API實(shí)現(xiàn)線程池的方法,感興趣的朋友跟隨小編一起看看吧2021-11-11C語言實(shí)現(xiàn)從指定位置截取文件內(nèi)容
這篇文章主要為大家詳細(xì)介紹了如何利用C語言實(shí)現(xiàn)從指定位置截取文件內(nèi)容,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11C++中String增刪查改模擬實(shí)現(xiàn)方法舉例
這篇文章主要給大家介紹了關(guān)于C++中String增刪查改模擬實(shí)現(xiàn)方法的相關(guān)資料,String是C++中的重要類型,程序員在C++面試中經(jīng)常會(huì)遇到關(guān)于String的細(xì)節(jié)問題,甚至要求當(dāng)場實(shí)現(xiàn)這個(gè)類,需要的朋友可以參考下2023-11-11Qt實(shí)現(xiàn)驗(yàn)證碼相關(guān)功能的代碼示例
驗(yàn)證碼的原理基于人類視覺和計(jì)算機(jī)視覺的差異性,通過給用戶顯示一些難以被機(jī)器識(shí)別的圖形或文字,讓用戶進(jìn)行人機(jī)交互,確認(rèn)自己的身份,這樣可以有效保護(hù)網(wǎng)站安全,所以本給大家介紹了Qt實(shí)現(xiàn)驗(yàn)證碼相關(guān)功能的代碼示例,感興趣的朋友可以參考下2024-01-01C++ LeetCode1796字符串中第二大數(shù)字
這篇文章主要為大家介紹了C++ LeetCode1796字符串中第二大數(shù)字示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12