浪漫煙花


廢話不多說,先上代碼 其實沒啥好說的

參考文獻:https://zhuanlan.zhihu.com/p/333503066

(3條消息) 3分鍾用C語言教你寫個‘浪漫煙花‘---特別漂亮_塵客-追夢的博客-CSDN博客

用c語言編寫動態煙花的方法 - 編程語言 - 億速雲 (yisu.com)

視頻文獻:【C/C++】C語言實現浪漫煙花表白程序,表白必備的滿天花海!_嗶哩嗶哩_bilibili

代碼挑戰——煙花特效制作_嗶哩嗶哩_bilibili

【C語言鏈表】盡畢生所學教會你C語言鏈表,看完保准會。_嗶哩嗶哩_bilibili

//編寫環境vs2019
#include<graphics.h>
#include<time.h>
#include<stdlib.h>
#include<math.h>
#include<windows.h>

#pragma comment(lib,"winmm.lib")

#define NUM 10			 

//煙花彈
struct jet
{
	int x, y;			 
	int hx, hy;			 

	bool shoot;			 
	DWORD t1, t2, dt;	 
	IMAGE img[2];		 
	byte n : 1;			 
}jet[NUM];			 

//煙花
struct Fire
{
	int x, y;				 
	int r;					 
	int max_r;				 
	int cen_x, cen_y;		 
	int width, height;		 
	int xy[240][240];		 

	bool draw;				 
	bool show;				 
	DWORD t1, t2, dt;		 
}fire[NUM];

 
void FireInit(int i)
{
	 
	jet[i].t1 = GetTickCount();	 
	jet[i].shoot = false;		 
	jet[i].dt = 10;				 
	jet[i].n = 0;				 

	//初始化煙花
	fire[i].show = false;		//未引爆
	fire[i].r = 0;
	fire[i].dt = 5;				//上升時間
	fire[i].t1 = GetTickCount();
	fire[i].max_r = rand() % 50 + 100;	 
	fire[i].cen_x = rand() % 30 + 80;	  
	fire[i].cen_y = rand() % 30 + 80;	 
	fire[i].width = 240;				 
	fire[i].height = 240;				 
}

//加載
void Load()
{
	//加載煙花彈
	IMAGE jetimg;
	loadimage(&jetimg, L"./fire/shoot.jpg", 200, 50);
	SetWorkingImage(&jetimg);
	for (int i = 0; i < NUM; i++)
	{
		int n = rand() % 5;			//01234
		getimage(&jet[i].img[0], n * 20, 0, 20, 50);
		getimage(&jet[i].img[1], (n + 5) * 20, 0, 20, 50);
	}
	SetWorkingImage(NULL);

	//加載煙花
	IMAGE fireimage, Fireimage;
	loadimage(&Fireimage, L"./fire/flower.jpg", 3120, 240);
	for (int i = 0; i < NUM; i++)
	{
		SetWorkingImage(&Fireimage);
		getimage(&fireimage, i * 240, 0, 240, 240);
		SetWorkingImage(&fireimage);
		for (int a = 0; a < 240; a++)
		{
			for (int b = 0; b < 240; b++)
			{
				fire[i].xy[a][b] = getpixel(a, b);
			}
		}
	}
	SetWorkingImage(NULL);
}

//選擇煙花彈
void ChoiceJet(DWORD& t1)
{
	DWORD t2 = GetTickCount();

	if (t2 - t1 > 100)		 
	{
		 
		int i = rand() % 10;

		 
		if (jet[i].shoot == false && fire[i].show == false)
		{
			 
			jet[i].x = rand() % 1000;
			jet[i].y = rand() % 100 + 450;	 
			jet[i].hx = jet[i].x;
			jet[i].hy = rand() % 300;		 
			jet[i].shoot = true;			 

			putimage(jet[i].x, jet[i].y, &jet[i].img[jet[i].n], SRCINVERT);
		}
		t1 = t2;
	}
}

//判斷發射
void Shoot()
{
	for (int i = 0; i < NUM; i++)
	{
		jet[i].t2 = GetTickCount();

		if (jet[i].t2 - jet[i].t1 >= jet[i].dt && jet[i].shoot == true)
		{
			putimage(jet[i].x, jet[i].y, &jet[i].img[jet[i].n], SRCINVERT);

			if (jet[i].y >= jet[i].hy)
			{
				jet[i].n++;			//閃爍
				jet[i].y -= 5;
			}

			putimage(jet[i].x, jet[i].y, &jet[i].img[jet[i].n], SRCINVERT);

			if (jet[i].y <= jet[i].hy)
			{
				putimage(jet[i].x, jet[i].y, &jet[i].img[jet[i].n], SRCINVERT);
				jet[i].shoot = false;
				 
				fire[i].x = jet[i].hx;
				fire[i].y = jet[i].hy;
				fire[i].show = true;
			}
		}
		jet[i].t1 = jet[i].t2;
	}
}

//顯示煙花
void ShowFire(DWORD* pMem)
{
	int drt[16] = { 5,5,5,5,5,10,25,25,25,25,55,55,55,55,55,65 };

	for (int i = 0; i < NUM; i++)
	{
		fire[i].t2 = GetTickCount();
		if (fire[i].t2 - fire[i].t1 >= fire[i].dt && fire[i].show == true)
		{
			if (fire[i].r < fire[i].max_r)
			{
				fire[i].r++;
				fire[i].dt = drt[fire[i].r / 10];
				fire[i].draw = true;
			}

			if (fire[i].r >= fire[i].max_r - 1)
			{
				fire[i].draw = false;
				FireInit(i);
			}
			fire[i].t1 = fire[i].t2;

		 
			if (fire[i].draw)
			{
				for (double a = 0; a <= 6.28; a += 0.01)
				{
					int x1 = (int)(fire[i].cen_x + fire[i].r * cos(a));
					int y1 = (int)(fire[i].cen_y - fire[i].r * sin(a));

					if (x1 > 0 && x1 < fire[i].width && y1>0 && y1 < fire[i].height)
					{
						int b = fire[i].xy[x1][y1] & 0xff;
						int g = (fire[i].xy[x1][y1] >> 8) & 0xff;
						int r = (fire[i].xy[x1][y1] >> 16);

						 
						int xx = (int)(fire[i].x + fire[i].r * cos(a));
						int yy = (int)(fire[i].y - fire[i].r * sin(a));

						 
						if (r > 0x20 && g > 0x20 && b > 0x20 && xx > 0 && xx < 1000 && yy >0 && yy < 600)
						{
							pMem[yy * 1000 + xx] = BGR(fire[i].xy[x1][y1]);
						}
						fire[i].draw = false;
					}
				}
			}
		}
	}
}

//主函數
int main()
{ 
	initgraph(1000, 600);

 
	srand((unsigned int)time(NULL));

	 
	mciSendString(L"open ./fire/bk1.mp3 alias music", 0, 0, 0);	 
	mciSendString(L"play music", 0, 0, 0);
	 
	DWORD t1 = GetTickCount();
	DWORD* pMem = GetImageBuffer();

	for (int i = 0; i < NUM; i++)
	{
		FireInit(i);
	}

	Load();
	BeginBatchDraw();

	while (1)
	{
		 
		for (int clr = 0; clr < 200; clr++)
		{
				int px1 = rand() % 1000;
				int py1 = rand() % 600;
 
				if (py1 < 599)  
				{ 
					pMem[py1 * 1000 + px1] = pMem[py1 * 1000 + px1 + 1] = BLACK; 
				}
		}
		ChoiceJet(t1);
		Shoot();
		ShowFire(pMem);
		FlushBatchDraw();
	}

 

	system("pause");
	return 0;
}

 

好好聽講 開講

基本代碼

<graphics.h>頭文件需要自己下載。

下載網址:https://easyx.cn/


graphics.h實例

#include<stdio.h>
#include<graphics.h>
#include<conio.h>
int main()
{
initgraph(700,700);//初始化窗口 也就是設定我們的程序框大小
setcolor(RED);//設置繪圖的顏色
circle(200,200,100);//圓心(200,200),半徑100
rectangle(200,200,400,400);//繪制一個矩形
line(200,200,500,500);//畫線
getch();
closegraph;//關閉繪圖程序界面
}

頭文件與結構體

#include<graphics.h>//圖形界面
#include<time.h>
#include<stdlib.h>
#include<math.h>
#include<windows.h>

#pragma comment(lib,"winmm.lib")//可能會報錯

#define NUM 10//煙花彈個數			 

//煙花彈
struct jet
{
	int x, y;//煙花彈坐標			 
	int hx, hy;//煙花彈最高點坐標	 

	bool shoot;	//記錄煙花彈是否處於發射		 
	DWORD t1, t2, dt;//t1發射時間;t2引爆時間;dt:間隔時間
	IMAGE img[2];//用來存圖片。兩張(一明一暗)
	byte n : 1; 
}jet[NUM];			 

//煙花
struct Fire
{
	int x, y;//煙花的坐標				 
	int r;	//煙花的半徑				 
	int max_r;		//煙花的最大半徑		 
	int cen_x, cen_y;		//中心距離左上角的距離(也就是中心距理原點的距離) 
	int width, height;	//煙花的長和寬	 
	int xy[240][240];	//像素,矩陣	 

	bool draw;				//記錄是否畫出 
	bool show;				 //記錄是否顯示
	DWORD t1, t2, dt;		 //發射時間 引爆時間 間隔時間
}fire[NUM];

bool類型


C語言並沒有徹底從語法上支持“真”和“假”,只是用 0 和非 0 來代表。這點在 C++ 中得到了改善,C++ 新增了 bool 類型(布爾類型),它一般占用 1 個字節長度。bool 類型只有兩個取值,true 和 false:true 表示“真”,false 表示“假”。

bool 是類型名字,也是 C++ 中的關鍵字,它的用法和 int、char、long 是一樣的,請看下面的例子:

#include <iostream>
using namespace std;
int main(){
    int a, b;
    bool flag;  //定義布爾變量
    cin>>a>>b;
    flag = a > b;
    cout<<"flag = "<<flag<<endl;
    return 0
}

10 20
flag = 0

遺憾的是,在 C++ 中使用 cout 輸出 bool 變量的值時還是用數字 1 和 0 表示,而不是 true 或 false。JavaPHPJavaScript 等也都支持bool類型,但輸出結果為 true 或 false,我武斷地認為這樣更科學。

你也可以使用 true 或 false 顯式地對 bool 變量賦值,例如:

#include <iostream>
using namespace std;

int main(){
    bool flag = true;
    if(flag){
        cout<<"true"<<endl;
    }else{
        cout<<"false"<<endl;
    }

    flag = false;
    if(flag){
        cout<<"true"<<endl;
    }else{
        cout<<"false"<<endl;
    }

    return 0;
}

運行結果:
true
false

注意,true 和 false 是 C++ 中的關鍵字,true 表示“真”,false 表示“假”。

DOWRD類型

在Visual C++ 6.0中,BYTE與WORD,DWORD本質上都是一種無符號整型,它們在WINDEF.H中被定義,定義如下:

typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;

​ 也就是說BYTE是無符號的char型(char型本質上也是一種1個字節的整型),WORD是無符號short型,DWORD是無符號long型。

​ 而在Visual C++ 6.0中,char型長度為1字節,short型長度為2字節,int和long型長度都為4字節,因此可以認為BYTE與WORD,DWORD定義的變量分別獲得了1字節,2字節,4字節內存,正與BYTE與WORD,DWORD的字面意義相符。

即:BYTE=unsigned char(完全等同)
WORD=unsigned short(完全等同)
DWORD=unsigned long(完全等同)

IMAGE

IMAGE img[2]存入了兩張圖片。//IMAGE是一個關於存入圖片的結構體,只是開辟了一個空間讓圖片可以存進去,但還沒存進去。

byte n : 1;

BYTE=unsigned char(完全等同)

C結構體 位段 //n 變量 1個位 0,1 n++ 0,1,0,1

函數統計

void ChoiceJet()//用來選擇煙花彈
void FireInit()//對程序進行初始化
void Load()//加載
void shoot()//判斷發射
void ShowFire()//顯示煙花

主函數

int main()
{
	//初始界面(1000,600)
	initgraph(1000, 600);

	//初始化種子,使用rand前一定要初始化,不然之后rand出的數都相同
	srand((unsigned int)time(NULL)); 

	 
  mciSendString(L"open ./fire/bk1.mp3 alias music", 0, 0, 0);	//send(發送)	string(字符串 // 音樂要放在程序代碼文件夾更目錄下
mciSendString(L"play music", 0, 0, 0);
    
	

	DWORD t1 = GetTickCount();
	DWORD* pMem = GetImageBuffer();

	for (int i = 0; i < NUM; i++)
	{
		FireInit(i);
	}

	Load();
	BeginBatchDraw();

	while (1)
	{
		// 隨機選擇像素點擦除
		for (int clr = 0; clr < 200; clr++)
		{
				int px1 = rand() % 1000;
				int py1 = rand() % 600;

				// 防止越界
				if (py1 < 599)  
				{
					//對顯存賦值擦除像素點
					pMem[py1 * 1000 + px1] = pMem[py1 * 1000 + px1 + 1] = BLACK; 
				}
		}
		ChoiceJet(t1);
		Shoot();
		ShowFire(pMem);
		FlushBatchDraw();
	}

	/*
	putimage(0, 0, &jet[3].img[0]);
	putimage(100, 0, &jet[3].img[1]);
	*/

	system("pause");
	return 0;
}


mciSendString()函數

mciSendString(L"open ./fire/bk1.mp3 alias music", 0, 0, 0); //send(發送) string(字符串)

mciSendSrting()函數只支持打開MP3音頻文件,若需要打開wav音頻文件可以使用PlaySound函數

當使用mciSendSrting()函數時,一定要確定好文件的位置,文件夾名用/號隔開,向我這里的文件就在當前文件的根目錄下,音樂的全名便是叫做bk1.MP3。bk1.MP3 alias music的意思是給bk1取一個叫做music的別名

mciSendString(L"play music", 0, 0, 0);的意思是播放別名為music的音樂。后面三個參0,0,0則表示默認

//0,0,0 音樂播放器時:播放設備,快進設備 快退 暫停


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM