easyx按键游戏

好久没编个像样的程序,手操编了一下,再不练一下脑袋就生锈了

为什么选awds这几个按键(玩游戏的都懂)

cpp 复制代码
#include <graphics.h>//引用图形库头文件
#include <conio.h>
#include <Windows.h>
#include <mmsystem.h>
#include <exception>//异常处理头文件
#include <fstream>//文件操作
#include <string.h>//字符串处理
#include <iostream>
#include <ctime>
#include <stdlib.h>
#pragma comment(lib,"winmm.lib")

// 添加互斥锁句柄
HANDLE hMutex;

bool bgmEnabled=true;//bgm默认开启
int difficulty=1;//默认简单模式
double speed=1;//默认速度
int score=0;//得分
bool keyA=false,keyW=false,keyD=false,keyS=false;//按键状态
int left,top,right,bottom;//按键位置
DWORD timeA=0,timeW=0,timeD=0,timeS=0;//按键生成时间记录
bool gameRunning=true;//游戏是否继续
char howToEnd[20];//失败形式
char whichKeyFail;//哪一个按键导致的失败
bool gameEnd=false;//判断游戏是否结束

struct KeyRect{//存储每个按键位置的矩形区域
	int left, top, right, bottom;
}rectA,rectW,rectD,rectS;


void gameOver(char howToEnd[],char whichKeyFail){//游戏结束
	if(gameEnd) return;//防止反复调用
	gameEnd=true;

	setfillcolor(BLACK);
	setlinecolor(BLACK);
	fillrectangle(10,100,500,450);
	//清除剩余按键
	if(whichKeyFail=='a'){
		setfillcolor(RED);
		setlinecolor(BLACK);
		fillrectangle(100,250,150,300);
		outtextxy(100+15,250+8,whichKeyFail);
	}
	if(whichKeyFail=='w'){
		setfillcolor(RED);
		setlinecolor(BLACK);
		fillrectangle(225,150,275,200);
		outtextxy(225+15,150+8,whichKeyFail);
	}
	if(whichKeyFail=='d'){
		setfillcolor(RED);
		setlinecolor(BLACK);
		fillrectangle(350,250,400,300);
		outtextxy(350+15,250+8,whichKeyFail);
	}
	if(whichKeyFail=='s'){
		setfillcolor(RED);
		setlinecolor(BLACK);
		fillrectangle(225,250,275,300);
		outtextxy(225+15,250+8,whichKeyFail);
	}

	if(strcmp(howToEnd,"timeout")==0){//游戏结束以时间耗尽结束
		settextstyle(35,25,"微软雅黑");
		settextcolor(RED);
		char failc[]="Time Out! You Fail!";
		outtextxy(20,70,failc);//显示失败标签
	}

	if(strcmp(howToEnd,"fatfinger")==0){//游戏结束以按错键结束
		settextstyle(35,25,"微软雅黑");
		settextcolor(RED);
		char failc[]="Fat Finger! You Fail!";
		outtextxy(10,70,failc);//显示失败标签
	}

	settextstyle(25,15,"微软雅黑");
	char restartc[]="Press Any Key To Esc";
	outtextxy(50,110,restartc);//显示退出标签
}

void graphLoad(){
	setfillcolor(BLACK);
	setlinecolor(BLACK);
	fillrectangle(0,10,200,50);
	//用黑色背景覆盖原score

	settextstyle(30,15,"微软雅黑");//设置字体格式
	setfillcolor(WHITE);
	settextcolor(WHITE);

	char sc[]="Score:";
	char scInt[50];
	itoa(score,scInt,10);//将int转为char数组
	outtextxy(45,10,sc);//score标签
	outtextxy(145,10,scInt);//得分栏

	char dc[]="Difficulty:";
	char dInt[10];
	itoa(difficulty,dInt,10);
	outtextxy(245,10,dc);//difficulty标签
	outtextxy(395,10,dInt);//难度栏
}

void gameConfig(){//游戏配置
	FILE* file=fopen("config.txt","r");//打开配置文件
	if(file==NULL){
		return;//文件不存在,退出配置读取采用默认值
	}
	int bgmValue,diffValue;
	fscanf(file,"%d",&bgmValue);//读取第一行bgm
	fscanf(file,"%d",&diffValue);//读取第二行difficulty

	bgmEnabled=(bgmValue==1);
	difficulty=diffValue;

	fclose(file);
	if(difficulty==2){
		speed=0.7;//中等难度
	}
	if(difficulty==3){
		speed=0.5;//困难难度
	}
	if(difficulty==4){
		speed=0.1;//外挂难度
	}

}

void loadMusic(){//载入音乐
	if (!bgmEnabled){//如果bgmEnabled为false则不载入music
		return;
	}
	try{
		mciSendString("open \"bgm.mp3\" type mpegvideo alias myMusic",NULL,0,NULL);//打开音频文件
		mciSendString("play myMusic repeat",NULL,0,NULL);//设置循环播放
			
	}catch(std::exception& e){//标准异常类要全小写
		;
	}
}

void generateOne(char one){
	if (one=='a'){//a按键位置
		left=100;
		top=250;
		right=150;
		bottom=300;

		rectA.left = left;
		rectA.top = top;
		rectA.right = right;
		rectA.bottom = bottom;
		//保存a位置
	}
	if (one=='w'){//w按键位置
		left=225;
		top=150;
		right=275;
		bottom=200;
		rectW.left = left;
		rectW.top = top;
		rectW.right = right;
		rectW.bottom = bottom;
		//保存w位置
	}
	if (one=='d'){//d按键位置
		left=350;
		top=250;
		right=400;
		bottom=300;
		rectD.left = left;
		rectD.top = top;
		rectD.right = right;
		rectD.bottom = bottom;
		//保存d位置
	}
	if (one=='s'){//s按键位置
		left=225;
		top=250;
		right=275;
		bottom=300;
		rectS.left = left;
		rectS.top = top;
		rectS.right = right;
		rectS.bottom = bottom;
		//保存a位置
	}
	setfillcolor(WHITE);//填充颜色
	setlinecolor(BLACK);//边框颜色
	fillrectangle(left,top,right,bottom);//填充框架
	setbkmode(TRANSPARENT);
	settextcolor(BLACK);//文本颜色
	outtextxy(left+15,top+8,one);//按键字符

}

DWORD WINAPI thinkGenerateKey(LPVOID lpParam){//判断创建awds按键函数

	char awdsArr[]={'a','w','d','s'};//创建awds数组
	char remainingKeys[4];//存储还未生成的按键
	int remainingCount;//剩余按键数量

	srand((unsigned)time(NULL));//设置随机种子

	while(gameRunning){
		Sleep(speed*1000);//每次刷新按键等待时间

		if(!gameRunning){//再次检查游戏是否还在运行(防止最后生成一个按键)
			break;
		}
		
		WaitForSingleObject(hMutex, INFINITE);  // 加锁
		
		remainingCount=0;
		if(!keyA) remainingKeys[remainingCount++]='a';
		if(!keyW) remainingKeys[remainingCount++]='w';
		if(!keyD) remainingKeys[remainingCount++]='d';
		if(!keyS) remainingKeys[remainingCount++]='s';

		if(remainingCount==0){
			ReleaseMutex(hMutex);
			continue;//如果所有按键都生成了,跳过,等待玩家按完其他键
		}
		
		int randomIndex=rand()%remainingCount;
		char generatedKey=remainingKeys[randomIndex];
		//从未生成的按键中随机选一个

		switch(generatedKey){//生成按钮的时候记录时间
			case 'a':keyA=true;generateOne('a');timeA=GetTickCount();break;
			case 'w':keyW=true;generateOne('w');timeW=GetTickCount();break;
			case 'd':keyD=true;generateOne('d');timeD=GetTickCount();break;
			case 's':keyS=true;generateOne('s');timeS=GetTickCount();break;
		}
		
		ReleaseMutex(hMutex);  // 解锁
	}
	return NULL;//退出线程
}

void removeKey(char one){
	WaitForSingleObject(hMutex, INFINITE);
	
	setfillcolor(BLACK);
	setlinecolor(BLACK);
	//用黑色背景覆盖按键
	switch(one){
		case 'a':
			fillrectangle(rectA.left,rectA.top,rectA.right,rectA.bottom);
			break;
		case 'w':
			fillrectangle(rectW.left,rectW.top,rectW.right,rectW.bottom);
			break;
		case 's':
			fillrectangle(rectS.left,rectS.top,rectS.right,rectS.bottom);
			break;
		case 'd':
			fillrectangle(rectD.left,rectD.top,rectD.right,rectD.bottom);
			break;
	}
	
	ReleaseMutex(hMutex);
}

DWORD WINAPI timeOutFail(LPVOID IpParam){//时间耗尽失败
	while(gameRunning){
		Sleep(50);//每50ms检查一次
		
		WaitForSingleObject(hMutex, INFINITE);
		
		DWORD currentTime=GetTickCount();//记录现在时间(必须用DWORD,因为GetTickCount返回的是DWORD32位无符号整数)
		DWORD timeOut=(DWORD)(speed*3000);//超时时间=speedx3
		if(keyA && timeA!=0 && (currentTime-timeA)>timeOut){
			whichKeyFail='a';
			gameRunning=false;
			ReleaseMutex(hMutex);
			break;
		}
		if(keyW && timeW!=0 && (currentTime-timeW)>timeOut){
			whichKeyFail='w';
			gameRunning=false;
			ReleaseMutex(hMutex);
			break;
		}
		if(keyD && timeD!=0 && (currentTime-timeD)>timeOut){
			whichKeyFail='d';
			gameRunning=false;
			ReleaseMutex(hMutex);
			break;
		}
		if(keyS && timeS!=0 && (currentTime-timeS)>timeOut){
			whichKeyFail='s';
			gameRunning=false;
			ReleaseMutex(hMutex);
			break;
		}
		
		ReleaseMutex(hMutex);
		//如果超时,退出游戏继续循环
	}
	if(howToEnd[0]=='\0'){
		strcpy(howToEnd,"timeout");
		gameOver(howToEnd,whichKeyFail);//跳转到游戏结束画面
	}

	return NULL;
}

DWORD WINAPI checkKeyPress(LPVOID lpParam){//检测按键按下状态
	while(gameRunning){
		if(_kbhit()){
			char key=_getch();//获取键盘输入
			
			WaitForSingleObject(hMutex, INFINITE);
			
			switch(key){
				case 'a':
				case 'A':
					if(keyA){
						keyA=false;
						removeKey('a');//删除a按键状态
						score+=1;//加1分
						graphLoad();
					}else{//按了不存在的a键
						whichKeyFail='a';
						strcpy(howToEnd,"fatfinger");
						gameRunning=false;
						ReleaseMutex(hMutex);
						gameOver(howToEnd,whichKeyFail);
						return NULL;
					}
					break;
				case 'w':
				case 'W':
					if(keyW){
						keyW=false;
						removeKey('w');//删除w按键状态
						score+=1;//加1分
						graphLoad();
					}else{//按了不存在的w键
						whichKeyFail='w';
						strcpy(howToEnd,"fatfinger");
						gameRunning=false;
						ReleaseMutex(hMutex);
						gameOver(howToEnd,whichKeyFail);
						return NULL;
					}
					break;
			
				case 'd':
				case 'D':
					if(keyD){
						keyD=false;
						removeKey('d');//删除d按键状态
						score+=1;//加1分
						graphLoad();
					}else{//按了不存在的d键
						whichKeyFail='d';
						strcpy(howToEnd,"fatfinger");
						gameRunning=false;
						ReleaseMutex(hMutex);
						gameOver(howToEnd,whichKeyFail);
						return NULL;
					}
					break;
			
				case 's':
				case 'S':
					if(keyS){
						keyS=false;
						removeKey('s');//删除s按键状态
						score+=1;//加1分
						graphLoad();
					}else{//按了不存在的s键
						whichKeyFail='s';
						strcpy(howToEnd,"fatfinger");
						gameRunning=false;
						ReleaseMutex(hMutex);
						gameOver(howToEnd,whichKeyFail);
						return NULL;
					}
					break;
				case 27:
					gameRunning=false;
					ReleaseMutex(hMutex);
					return NULL;
			}
			
			ReleaseMutex(hMutex);
		}
		Sleep(10);
	}
	return NULL;
}

int main()
{
	initgraph(500, 400,NULL);//创建绘图窗口,大小为500x400像素
	
	// 创建互斥锁
	hMutex = CreateMutex(NULL, FALSE, NULL);

	gameConfig();//调用gameConfig函数
	loadMusic();//调用loadMusic函数

	graphLoad();//调用graphLoad函数

	// 创建Windows线程
	HANDLE hThinkThread=CreateThread(NULL,0,thinkGenerateKey,NULL,0,NULL);//创建thinkGenerateKey的线程
	HANDLE hTimeFailThread=CreateThread(NULL,0,timeOutFail,NULL,0,NULL);//创建timeOutFail的线程
	HANDLE hCheckThread=CreateThread(NULL,0,checkKeyPress, NULL,0,NULL);//创建checkKeyPress的线程

	// 等待线程结束
	WaitForSingleObject(hThinkThread,INFINITE);
	WaitForSingleObject(hTimeFailThread,INFINITE);
	WaitForSingleObject(hCheckThread,INFINITE);

	// 关闭线程句柄
	CloseHandle(hThinkThread);
	CloseHandle(hTimeFailThread);
	CloseHandle(hCheckThread);
	CloseHandle(hMutex);

	
	_getch();//按任意键继续
	closegraph();//关闭绘图窗口
	return 0;
}
相关推荐
魔法阵维护师7 小时前
从零开发游戏需要学习的c#模块,第二十一章(精灵动画 —— 让角色走起来)
学习·游戏·c#
行走的大喇叭7 小时前
Linux kernel目录、配置文件介绍
linux·单片机·嵌入式硬件
郝学胜-神的一滴7 小时前
Qt 高级开发 011: 跨线程信号槽实战
开发语言·c++·qt·程序人生·开源软件·用户界面
学困昇7 小时前
Linux 动静态库制作与原理:从 .a、.so 到 ELF 加载一次讲透
linux·运维·服务器·c语言·开发语言·c++·人工智能
0南城逆流07 小时前
【网站分享】常用网站分享四:STM32常用外设链接
stm32·单片机·嵌入式硬件
basketball6167 小时前
C++面试考点 头文件与实现文件形式
开发语言·c++
历程里程碑7 小时前
56 . 高效ET非阻塞IO服务器设计指南
java·运维·服务器·开发语言·数据结构·c++·排序算法
yu85939587 小时前
STM32 控制 W5500 以太网传输程序
stm32·单片机·嵌入式硬件
LCG元7 小时前
STM32实战:基于STM32F103的车内防窒息系统(红外检测+GSM报警)
stm32·单片机·嵌入式硬件