用VS开发一款“飞机大战“单机游戏<C++>

news2024/11/23 22:35:59

显示界面如上图所示

自己找的背景和飞机素材,先将素材奉上.

 

接下来我先简单分析一下这个单机游戏的运行逻辑:

就像显示界面所显示的那样,我们想要实现的是自己的飞机在发射子弹(子弹在上图没显示),然后当子弹射到敌方飞机,这里设置了两种类型的飞机,如果读者想定义更多类型的,直接添加属性就可以.当子弹射到飞机的时候,飞机的血量减少,就像CS一样,并不一定是一发子弹就死亡,读者可以根据自己喜欢去设置,博主这里设置大飞机的血量是3发子弹,而小飞机的血量是1发子弹,也就是说,当有3发子弹射到大飞机的时候,大飞机就消失,一发子弹小飞机消失.至于其他的动态效果,博主这里暂时不做介绍.具体往下看:

面向对象开发,每一个对象我们都需要给他设置相对应的对象属性,在语言当中,我们将其设置成结构体就可以:

enum My
{
	WIDTH = 500,
	HIGHT = 700,
	BULLET_NUM = 100,//玩家子弹数量
	ENEMY_NUM = 10,//敌机的数量
	BIG,
	SMALL,
};
struct Plane
{
	int x;
	int y;
	bool live;//是否存活
	int width;
	int hight;
	int hp;
	int type;//敌机类型  big small

}player,bull[BULLET_NUM],enemy[ENEMY_NUM];

首先设定了一个联合,用于设置弹出窗口的基本参数和其他属性. 

上面是不是把敌方飞机,自己飞机和自己发射的子弹都定义成了一个结构体.下面我们就可以直接用了.

(x,y)代表的是对象在窗口当中的坐标,width和hight是对象自身的尺寸,而hp是血量,type是博主自己定义了两种敌机类型.布尔类型live判断飞机是否存活状态.

第一步我们应该是要先创建图形窗口

	/*测试
circle(50, 50, 50);//画空心圆
setfillcolor(GREEN);//圆的颜色
fillcircle(100, 100, 50);///实心⚪*/
	//创建图形窗口
	initgraph(WIDTH, HIGHT,SHOWCONSOLE);//宽长

initgraph()函数直接用

第二步加载窗口里面使用到的图片   //无论什么时候用,我们都要进行图片加载的,因此此处我们将其设定到一个函数下,方便之后也可以随时添加和删除.

//把图片加载进程序
IMAGE bk;//背景图
//保存玩家图片
IMAGE img_role;
//保存子弹
IMAGE img_bull;
//
IMAGE img_enemy[4];
void loadImg()
{
	//加载图片
	loadimage(&bk, "D:/program/飞机大战/images/bk.png");
	//加载玩家图片
	loadimage(&img_role, "D:/program/飞机大战/images/fly.png");
	//加载子弹图片
	loadimage(&img_bull, "D:/program/飞机大战/images/子弹.jpg");
	//加载敌机的图片
	loadimage(&img_enemy[0], "D:/program/飞机大战/images/enemy1.png");
	loadimage(&img_enemy[1], "D:/program/飞机大战/images/enemy2.png");
	//loadimage(&img_enemy[2], "D:/program/飞机大战/images/enemy3.jpg");
	//loadimage(&img_enemy[3], "D:/program/飞机大战/images/enemy4.jpg");
}

IMAGE 是easyx里面的一个参数,直接用

此案例当中,需要我们加载的图片有背景图,自己飞机图,子弹图,敌方飞机1和敌方飞机2,如果读者也自己添加第三台和第四台敌机,也可以直接添加,不过要注意,当一种对象,存在多个类型的时候,要采用数组将其存储,方便之后进行使用.

第三步,要干嘛?设置好窗口了,加载完图片了,是不是要把图片添加进去了?

那图片添加到哪里去?怎么添加?哪一种图片应该添加在哪里呢?

这里我们是不是首先要初始化一下图片的基本属性?of course,买衣服我总的知道我适合穿多大尺码的衣服吧?

void gameinit()//初始化数据
{
	player.x = WIDTH / 2;
	player.y = HIGHT - 120;
	player.live = true;
	//初始化子弹
	for (int i = 0; i < BULLET_NUM; i++)
	{
		bull[i].x = 0;
		bull[i].y = 0;
		bull[i].live = false;
	}
	//初始化敌机
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		enemy[i].live = false;
		enemyHP(i);
	}
}

想想我们一共有几个对象,去除背景图片不需要我们在这里初始化之外,另外就是自己飞机,敌方飞机和子弹三个对象.那么我们就定义一个函数,用于初始化这些对象的第一属性.

在初始化敌方飞机的时候,博主之前把敌方飞机设置有两种类型,那么这两种类型飞机的基本属性一定有一些是不一样的呀,要不然怎么叫做2呢?

博主这里主要用飞机的大小和血量来区分这两种飞机.具体看enemyHP()函数

void enemyHP(int i)
{
	int flag = rand() % 10;
	if (flag>=0 && flag<=2)//0-9
	{
		enemy[i].type = BIG;
		enemy[i].hp = 3;
		enemy[i].width = 100;
		enemy[i].hight = 100;
	}
	else
	{
		enemy[i].type = SMALL;
		enemy[i].hp = 1;
		enemy[i].width = 50;
		enemy[i].hight = 50;
	}

}

在这个函数当中,我们要注意,大飞机和小飞机出现的次数是不是正常情况下是不一样的?比如小飞机出现了5次,而大飞机才出现一次这样,当然敌飞机出现肯定不是我们可以控制的,它肯定是随机出现的,所以这里我们采用一个随机范围,如果在0-2之间就出现大飞机,3-9之间小飞机,这样是不是小飞机的概率要高于大飞机.其余的进入条件之内直接初始化就可以了.

第四步,上面我们把全部图片都加载好,然后对象都进行了初始化,接下来我们要干嘛?

那肯定是要将这些图片绘制到对应的窗口坐标上了!!!!!!!

void gameDraw()
{
	loadImg();
	//把背景贴在窗口上
	putimage(0, 0, &bk);
	putimage(player.x, player.y, &img_role,SRCINVERT);
	for (int i = 0; i < BULLET_NUM; i++)
	{
		if (bull[i].live)
		{
			putimage(bull[i].x, bull[i].y, &img_bull, SRCINVERT);
		}
	}
	//绘制敌机
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (enemy[i].live)
		{
			if(enemy[i].type==SMALL)
			putimage(enemy[i].x, enemy[i].y, &img_enemy[0], SRCINVERT);//x和y是飞机在窗口中的坐标
			else
			putimage(enemy[i].x, enemy[i].y, &img_enemy[1], SRCINVERT);
		}
	}

}

绘制背景,绘制自己飞机,绘制子弹,绘制敌方飞机都采用putimage()函数就可以了

需要注意的有可能就是对于敌方飞机和子弹只有live是true的时候才绘制,而对于敌方飞机还区分了两种类型的飞机,加一个if-else输出对应的敌方飞机就可以了;

第五步,第四步我们绘制的图片是个啥,是初始化的位置,是一个静态的图,我们要实现的动态图,那接下来我们应该干嘛????????

当然是让子弹,自己飞机和敌方飞机都动起来了,也就是创建动画

首先让自己飞机动起来

void playermove(int speed)
{
#if 0

	if (_kbhit) {
		//有两种方式
	//1,getch()  阻塞函数,和scanf一样,如果没有输入,就会卡住程序,一直等待输入,
	//这个函数不是c语言标准函数,需要头文件<conio.h>
		char key = _getch();
		switch (key)
		{
		case 'w':
		case 'W':
			player.y -= speed;
			break;
		case 's':
		case 'S':
			player.y += speed;
			break;
		case 'a':
		case 'A':
			player.x -= speed;
			break;
		case 'd':
		case 'D':
			player.x += speed;
			break;
		default:
			break;
		}
	}
}
#elif 1
	//2.使用Windows函数获取键盘输入
	//非阻塞函数,特别流畅
	//如果用字母,必须要用大写,大写可以识别大小写
	if (GetAsyncKeyState(VK_UP) || GetAsyncKeyState('W'))
	{
		if(player.y > 0)
			player.y -= speed;
	}
	if (GetAsyncKeyState(VK_DOWN) || GetAsyncKeyState('S'))
	{
		if (player.y < HIGHT-78)//78是飞机的高度
		player.y += speed;
	}
	if (GetAsyncKeyState(VK_LEFT) || GetAsyncKeyState('A'))
	{
		if(player.x+59>0)// 119/2  = 59是控制飞机子弹在左右边界的时候可以打到敌机
		player.x -= speed;
	}
	if (GetAsyncKeyState(VK_RIGHT) || GetAsyncKeyState('D'))
	{
		if (player.x-59 < WIDTH-119)//119是飞机的宽度
		player.x += speed;
	}
#endif // 0
	
	if (GetAsyncKeyState(VK_SPACE) && Timer(100,1))//
	{
		//创建一个子弹
		createBullet();
	}

}

这里尝试了两种让自己飞机动起来的方法,第一种是_kbhit,如果按下键盘,判断按下的是什么键,如果wsad当中的一个则执行对应的操作,但是这种方法运行之后,你会发现很卡,就是一个帧当中只能运行一个动作,不能运行右上这样的操作,关键是很卡

所以我们用了第二种方案非阻塞函数GetAsyncKeyState(),分别对键盘当中的上下左右和英文字符当中的wasd进行case分析,其他不变,此处要注意的有可能就是要控制自己的飞机运行,只能在窗口范围内运行,为其设定边界就可以.

最后还加了一个和子弹相关的函数,如果说按下空格键了,就要发射子弹了,同时这里结合了一个定时器的函数,用于控制子弹发射的速度100ms,不要再100ms内发射两颗子弹,防止出现子弹重叠的现象.

bool Timer(int ms, int id)//定时器
{
	static DWORD t[10];
	if (clock() - t[id] > ms)
	{
		t[id] = clock();
		return true;
	}
	return false;
}

定义了一个无符号长整形的时间数组,是因为本案例当中有多个函数都用到了定时器函数.

自己飞机动起来,接下来就很明显了,让子弹跟着发射,对不对????也就是进入createBullet()函数

void createBullet()
{
	for (int i = 0; i < BULLET_NUM; i++)
	{
		if (!bull[i].live)
		{
			bull[i].x = player.x+59;
			bull[i].y = player.y;
			bull[i].live = true;
			break;
		}
	}
}

 刚开始子弹都是的状态都是false,然后条件正确后,初始化了子弹的第一个位置发射出来,然后将子弹的状态改为true.跳出这一个,执行下一个,要注意此时只是静态化绘制了子弹,还没有动起来,那么接下来就让子弹垂直向上运行就好.

void Bullmove(int speed)
{
	for (int i = 0; i < BULLET_NUM; i++)
	{
		if (bull[i].live)
		{
			bull[i].y -=speed;
			if (bull[i].y < 0)
			{
				bull[i].live = false;
			}
		}
	}
}

如果子弹到了最上方了,改变子弹的状态为false,继续循环

自己飞机和子弹都结束了,接下来就是敌方飞机了

//产生敌机
void createenemy()
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (!enemy[i].live)
		{
			enemy[i].live = true;
			enemy[i].x = rand()%(WIDTH-75);
			enemy[i].y = 0;
			enemyHP(i);
			printf("pos(%d,%d) %d %d\n", enemy[i].x, enemy[i].y, enemy[i].live, enemy[i].hp);
			break;
		}
	}
}

在窗口的最上面随机产生敌机,敌机也要动的.是不是参考子弹的就可以了,如下

//敌机的移动
void enemymove(int speed)
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (enemy[i].live)
		{
			enemy[i].y += speed;

			if (enemy[i].y > HIGHT)
			{
				enemy[i].live = false;
			}
		}
	}
}

 最后就是打飞机,当子弹到了敌方飞机的范围内是,敌方飞机就消失

//开始打飞机
void playplane()
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (!enemy[i].live)
			continue;
		for (int k = 0; k < BULLET_NUM; k++)
		{
			if (!bull[k].live)
				continue;
			if (bull[k].x > enemy[i].x && bull[k].x<enemy[i].x + enemy[i].width
				&& bull[k].y>enemy[i].y && bull[k].y < enemy[i].y + enemy[i].hight)//子弹在飞机的界面内
				//则代表子弹打住了飞机
			{
				bull[k].live = false;
				enemy[i].hp--;
			}
		}
		if (enemy[i].hp == 0)
		{
			enemy[i].live = false;
		}

	}
}

			if (bull[k].x > enemy[i].x && bull[k].x<enemy[i].x + enemy[i].width
				&& bull[k].y>enemy[i].y && bull[k].y < enemy[i].y + enemy[i].hight)//子弹在飞机的界面内
				//则代表子弹打住了飞机

这是个啥?意思是当子弹到了敌方飞机那个矩形图之内,条件就正确

 这里要注意大飞机血量是3,小飞机血量是1,一颗子弹一格血量.当血量为0,则飞机死亡

最后一步,上主函数

int main()
{
	/*测试
circle(50, 50, 50);//画空心圆
setfillcolor(GREEN);//圆的颜色
fillcircle(100, 100, 50);///实心⚪*/
	//创建图形窗口
	initgraph(WIDTH, HIGHT,SHOWCONSOLE);//宽长
	gameinit();
	//双缓冲绘图
	BeginBatchDraw();
	while (1)
	{
		gameDraw();
		FlushBatchDraw();
		playermove(5);
		Bullmove(5);
		//防止飞机全部一起出来

		if (Timer(500,0))
		{
			//创建一个飞机
			createenemy();
		}
		if (Timer(20, 2))
		{
			enemymove(1);
		}
		playplane();
	}
	EndBatchDraw();
	return 0;
}

注意这里的

//双缓冲绘图
	BeginBatchDraw();

	EndBatchDraw();

是easyx插件里面的一个双缓冲绘图,防止图片在窗口当中出现闪屏

总代码:

#include<stdio.h>
//图形库,帮助我们新手,快速入门图形编程easyx
#include<graphics.h>
#include<conio.h>
#include<time.h>
enum My
{
	WIDTH = 500,
	HIGHT = 700,
	BULLET_NUM = 100,//玩家子弹数量
	ENEMY_NUM = 10,//敌机的数量
	BIG,
	SMALL,
};
struct Plane
{
	int x;
	int y;
	bool live;//是否存活
	int width;
	int hight;
	int hp;
	int type;//敌机类型  big small

}player,bull[BULLET_NUM],enemy[ENEMY_NUM];


//把图片加载进程序
IMAGE bk;//背景图
//保存玩家图片
IMAGE img_role;
//保存子弹
IMAGE img_bull;
//
IMAGE img_enemy[4];

void loadImg()
{
	//加载图片
	loadimage(&bk, "D:/program/飞机大战/images/bk.png");
	//加载玩家图片
	loadimage(&img_role, "D:/program/飞机大战/images/fly.png");
	//加载子弹图片
	loadimage(&img_bull, "D:/program/飞机大战/images/子弹.jpg");
	//加载敌机的图片
	loadimage(&img_enemy[0], "D:/program/飞机大战/images/enemy1.png");
	loadimage(&img_enemy[1], "D:/program/飞机大战/images/enemy2.png");
	//loadimage(&img_enemy[2], "D:/program/飞机大战/images/enemy3.jpg");
	//loadimage(&img_enemy[3], "D:/program/飞机大战/images/enemy4.jpg");
}
bool Timer(int ms, int id)//定时器
{
	static DWORD t[10];
	if (clock() - t[id] > ms)
	{
		t[id] = clock();
		return true;
	}
	return false;
}
void enemyHP(int i)
{
	int flag = rand() % 10;
	if (flag>=0 && flag<=2)//0-9
	{
		enemy[i].type = BIG;
		enemy[i].hp = 3;
		enemy[i].width = 100;
		enemy[i].hight = 100;
	}
	else
	{
		enemy[i].type = SMALL;
		enemy[i].hp = 1;
		enemy[i].width = 50;
		enemy[i].hight = 50;
	}

}

void gameinit()//初始化数据
{
	player.x = WIDTH / 2;
	player.y = HIGHT - 120;
	player.live = true;
	//初始化子弹
	for (int i = 0; i < BULLET_NUM; i++)
	{
		bull[i].x = 0;
		bull[i].y = 0;
		bull[i].live = false;
	}
	//初始化敌机
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		enemy[i].live = false;
		enemyHP(i);
	}
}
//游戏绘制函数
void gameDraw()
{
	loadImg();
	//把背景贴在窗口上
	putimage(0, 0, &bk);
	putimage(player.x, player.y, &img_role,SRCINVERT);
	for (int i = 0; i < BULLET_NUM; i++)
	{
		if (bull[i].live)
		{
			putimage(bull[i].x, bull[i].y, &img_bull, SRCINVERT);
		}
	}
	//绘制敌机
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (enemy[i].live)
		{
			if(enemy[i].type==SMALL)
			putimage(enemy[i].x, enemy[i].y, &img_enemy[0], SRCINVERT);//x和y是飞机在窗口中的坐标
			else
			putimage(enemy[i].x, enemy[i].y, &img_enemy[1], SRCINVERT);
		}
	}

}

void createBullet()
{
	for (int i = 0; i < BULLET_NUM; i++)
	{
		if (!bull[i].live)
		{
			bull[i].x = player.x+59;
			bull[i].y = player.y;
			bull[i].live = true;
			break;
		}
	}
}
void Bullmove(int speed)
{
	for (int i = 0; i < BULLET_NUM; i++)
	{
		if (bull[i].live)
		{
			bull[i].y -=speed;
			if (bull[i].y < 0)
			{
				bull[i].live = false;
			}
		}
	}
}

//角色移动,获取键盘信息,上下左右
void playermove(int speed)
{
#if 0

	if (_kbhit) {
		//有两种方式
	//1,getch()  阻塞函数,和scanf一样,如果没有输入,就会卡住程序,一直等待输入,
	//这个函数不是c语言标准函数,需要头文件<conio.h>
		char key = _getch();
		switch (key)
		{
		case 'w':
		case 'W':
			player.y -= speed;
			break;
		case 's':
		case 'S':
			player.y += speed;
			break;
		case 'a':
		case 'A':
			player.x -= speed;
			break;
		case 'd':
		case 'D':
			player.x += speed;
			break;
		default:
			break;
		}
	}
}
#elif 1
	//2.使用Windows函数获取键盘输入
	//非阻塞函数,特别流畅
	//如果用字母,必须要用大写,大写可以识别大小写
	if (GetAsyncKeyState(VK_UP) || GetAsyncKeyState('W'))
	{
		if(player.y > 0)
			player.y -= speed;
	}
	if (GetAsyncKeyState(VK_DOWN) || GetAsyncKeyState('S'))
	{
		if (player.y < HIGHT-78)//78是飞机的高度
		player.y += speed;
	}
	if (GetAsyncKeyState(VK_LEFT) || GetAsyncKeyState('A'))
	{
		if(player.x+59>0)// 119/2  = 59是控制飞机子弹在左右边界的时候可以打到敌机
		player.x -= speed;
	}
	if (GetAsyncKeyState(VK_RIGHT) || GetAsyncKeyState('D'))
	{
		if (player.x-59 < WIDTH-119)//119是飞机的宽度
		player.x += speed;
	}
#endif // 0
	
	if (GetAsyncKeyState(VK_SPACE) && Timer(100,1))//
	{
		//创建一个子弹
		createBullet();
	}

}
//产生敌机
void createenemy()
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (!enemy[i].live)
		{
			enemy[i].live = true;
			enemy[i].x = rand()%(WIDTH-75);
			enemy[i].y = 0;
			enemyHP(i);
			printf("pos(%d,%d) %d %d\n", enemy[i].x, enemy[i].y, enemy[i].live, enemy[i].hp);
			break;
		}
	}
}

//敌机的移动
void enemymove(int speed)
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (enemy[i].live)
		{
			enemy[i].y += speed;

			if (enemy[i].y > HIGHT)
			{
				enemy[i].live = false;
			}
		}
	}
}

//开始打飞机
void playplane()
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		if (!enemy[i].live)
			continue;
		for (int k = 0; k < BULLET_NUM; k++)
		{
			if (!bull[k].live)
				continue;
			if (bull[k].x > enemy[i].x && bull[k].x<enemy[i].x + enemy[i].width
				&& bull[k].y>enemy[i].y && bull[k].y < enemy[i].y + enemy[i].hight)//子弹在飞机的界面内
				//则代表子弹打住了飞机
			{
				bull[k].live = false;
				enemy[i].hp--;
			}
		}
		if (enemy[i].hp == 0)
		{
			enemy[i].live = false;
		}

	}
}

void showenemy()//测试飞机能不能一直往下面落
{
	for (int i = 0; i < ENEMY_NUM; i++)
	{
		printf("pos(%d,%d) %d %d\n", enemy[i].x, enemy[i].y,enemy[i].live, enemy[i].hp);
	}
}



int main()
{
	/*测试
circle(50, 50, 50);//画空心圆
setfillcolor(GREEN);//圆的颜色
fillcircle(100, 100, 50);///实心⚪*/
	//创建图形窗口
	initgraph(WIDTH, HIGHT,SHOWCONSOLE);//宽长
	gameinit();
	//双缓冲绘图
	BeginBatchDraw();
	while (1)
	{
		gameDraw();
		FlushBatchDraw();
		playermove(5);
		Bullmove(5);
		//防止飞机全部一起出来

		if (Timer(500,0))
		{
			//创建一个飞机
			createenemy();
		}
		if (Timer(20, 2))
		{
			enemymove(1);
		}
		playplane();
	}
	EndBatchDraw();
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/53708.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于51单片机农业大棚温控系统

资料编号&#xff1a;197 大棚种植温控系统概述&#xff1a; 本文介绍的是一个由单片机构成的温度控制系统&#xff0c;主要用来提供测温的解决方案&#xff0c;同时还能实时监控温度变化趋势&#xff0c;以及报警功能。它利用STC89C52RC单片机&#xff0c;DS18B20&#xff0c…

概率图模型:HMM(隐马),MEMM(最大熵),CRF(条件随机场)

1.概率图模型&#xff1a;HMM&#xff08;隐马&#xff09;,MEMM&#xff08;最大熵&#xff09;,CRF&#xff08;条件随机场&#xff09;概率&#xff1a;既然是一个图那么就是一个有圈有边的结构&#xff0c;圈代表随机向量&#xff0c;随机变量之间有边&#xff0c;边上有概…

数字验证学习笔记——UVM学习2 覆盖方法

一、覆盖方法 覆盖机制可以将原来所属的类型替换为另外一个新的类型。 在覆盖之后&#xff0c;原本用来创建原属类型的请求&#xff0c;将由工厂来创建新的替换类型。 无需再修改原始代码&#xff0c;继而保证了原有代码的封装性。新的替换类型必须与被替换类型兼容&#xff…

OpenStack 学习之 OVN : L2网络 ( Logical switches 逻辑交换机)

OVN Manual install & Configuration Open vSwitch 官网 参考 OVN学习&#xff08;一&#xff09; OVN实战一之GNS3操作指南及OVN入门 简单理解和知识 按照 OVN Manual install & Configuration 分别叫做 Controller 节点和 Compute 节点 &#xff0c;其他一般叫做…

Android Studio 打一个正式签名的Apk

如何打一个带正式签名文件的app (给自己的劳动成果冠名) 1. 选择build -> generate signed bundle/apk 2. 这里有两个选择, bundle or apk, 我们选择apk 于是勾选 apk, 并点下一步 3. 来到选择证书文件的地方, 但是我们这是第一次做, 还没有证书文件, 所以选择新建一个证…

【Docker学习系列】Docker学习2-docker设置阿里云镜像加速器

在上一篇中&#xff0c;我们学会了在centos中安装docer。我们知道&#xff0c;镜像都是外网的&#xff0c;镜像一般都是比较大的&#xff0c;因为种种原因&#xff0c;我们知道&#xff0c;从外网下载比较慢的。所以&#xff0c;本文&#xff0c;凯哥就介绍怎么将docker的镜像拉…

keil5打开keil4工程无法编译的情况解决办法!!!!!!

目录 1.情况 1.keil5使用&#xff08;打开&#xff09;keil4文件工程的时候报错 2.解决办法 如果是kei5打开kei4工程文件出现 步骤1&#xff1a; 步骤2&#xff1a; 步骤3&#xff1a; 1.情况 1.keil5使用&#xff08;打开&#xff09;keil4文件工程的时候报错 --- Erro…

vscode插件开发

作为一个前端开发相信&#xff0c;大家对于vscode非常熟悉。vscode是微软开源的一款基于 Electron 开发的代码编辑器。并且vscode支持通过插件来扩展编辑器的功能&#xff0c;比如Prettier插件帮助我们快速格式化代码&#xff0c;ES7 React/Redux/React-Native snippets插件帮助…

Kotlin高仿微信-第31篇-支付-服务

Kotlin高仿微信-项目实践58篇详细讲解了各个功能点&#xff0c;包括&#xff1a;注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…

hadoop集群中存在配置较低的数据节点应用如何应对磁盘数据溢满的问题之rebalance

现象 登录hdfs web ui发现集群中一个节点的负载远高于另外的节点 分析 一般情况下集群在数据盘配置一样&#xff0c;几乎使用不到rebalance&#xff0c;但是我们的集群中有一个比较小的数据节点&#xff0c;因此我们需要关注各节点数据分布情况&#xff0c;及时进行rebalan…

手撕一个图片色卡提取器,可自定义提取色卡数量!

在一些特殊的业务场景中&#xff0c;我们需要一次性提取一张图片中的色卡信息&#xff0c;并且需要使用十六进制的颜色表示方法进行展示。 今天得空做了一个小工具&#xff0c;用来自定义的提取某一张图片中的色卡信息&#xff0c;需要提取某张图片中的色卡可以自行选择。 实现…

Python基础之SQLite数据库

Python与SQLite数据库 一、概述 对于非常简单的应用而言&#xff0c;使用文件作为持久化存储通常就足够了&#xff0c;但是大多数复杂的数据驱动的应用则需要全功能的关系数据库。 SQLite 的目标则是介于两者之间的中小系统。它量级轻、速度快&#xff0c;没有服务器&#xf…

数学辅导微信小程序设计与实现的源码+文档

摘 要 网络的广泛应用给生活带来了十分的便利。所以把数学辅导管理与现在网络相结合&#xff0c;利用java技术建设数学辅导微信小程序&#xff0c;实现数学辅导的信息化。则对于进一步提高数学辅导管理发展&#xff0c;丰富数学辅导管理经验能起到不少的促进作用。 数学辅导微…

【python】 int、float、double与16进制字符串的互相转换

import structdef intToHex(num): # int转16进制return hex(num)[2:].upper()def hexToInt(hexString): # 16进制转intreturn int(hexString, 16)def floatToHex(floatValue): # float转16进制return struct.pack(>f, floatValue).hex().upper()def hexToFloat(hexString…

chloris.earth ——Chloris 全球生物量 2003 - 2019 数据平台

概述 Chloris 全球生物量 2003 - 2019 数据集提供了地球陆地木本植被生态系统地上生物量存量和变化的估计值。它涵盖 2003 年至 2019 年期间&#xff0c;按年度时间步长计算。全球数据集的空间分辨率约为 4.6 公里。 这些地图和数据集是通过结合来自星载卫星的多个遥感测量结果…

如何保证PCB孔铜高可靠?

PCB板上电路导通&#xff0c;都是靠线路或过孔来传导的&#xff0c;从PCB制造流程可以看出&#xff0c;PCB完成铜厚是由PCB基铜厚度加板电厚度加图电厚度三部分组成&#xff0c;PCB孔铜厚度&#xff0c;是在两个电镀流程中完成&#xff0c;即全板电镀孔铜的厚度加图形电镀孔铜厚…

k8s概念

文章目录k8s概念为什么叫他k8s以及谁开发的k8s是什么k8s特点时光回溯传统部署时代&#xff1a;虚拟化部署时代容器部署时代&#xff1a;容器的优点为什么需要k8s&#xff0c;他能做什么&#xff1f;Kubernetes 不是什么&#xff1f;k8s概念 为什么叫他k8s以及谁开发的 kubern…

EO.Web浏览器 v2023.0.18.0 for .NET -- EO.WebBrowser

.NET PDF 和 Web 浏览器从未如此简单 使用 PDF 文件生成/处理能力快速扩展您的 .NET 应用程序&#xff0c;或者将流行的 Chromium 浏览器引擎与广泛的自定义选项&#xff08;如自定义资源加载器和 JavaScript 扩展&#xff09;无缝集成用于 UI 或后台任务。 当前&#xff1a;v2…

steam搬砖项目,小白也能月入过万的副业项目

steam搬砖这个项目&#xff0c;我们做了3年了&#xff0c;项目很稳定。由于项目是轻资产&#xff0c;门槛低&#xff0c;按照我们的方法&#xff0c;只要你足够勤快&#xff0c;这是一个能帮你赚取人生的第一桶金的项目。 仅代表个人收益 steam项目原理就是&#xff1a;倒卖cs…

移动端异构运算技术 - GPU OpenCL 编程(基础篇)

一、前言 随着移动端芯片性能的不断提升&#xff0c;在移动端上实时进行计算机图形学、深度学习模型推理等计算密集型任务不再是一个奢望。在移动端设备上&#xff0c;GPU 凭借其优秀的浮点运算性能&#xff0c;以及良好的 API 兼容性&#xff0c;成为移动端异构计算中非常重要…