C/C++游戏开发(easyx框架)及时类——极速赛车

本游戏用到了图形界面库graphics.h,图形界面库下载安装:
下载链接:https://easyx.cn/download
游戏截图:
请添加图片描述
加载游戏资源图片
右键打开项目属性,添加 -> 现有项,添加资源图片进项目,mp3文件放在项目的目录下。
资源图片链接:https://pan.baidu.com/s/1l2pkD8flUMqC8fSLrKnEgg?pwd=jsfw
提取码:jsfw
在这里插入图片描述
在这里插入图片描述

IMAGE road, grass, car;
void initgamePicture() {
	loadimage(&grass, "草.jpg", IMAGE_SIZE, IMAGE_SIZE);
	loadimage(&road, "路.png", IMAGE_SIZE, IMAGE_SIZE);
	for (int i = 0; i < MAX_CARS; i++) {
		loadimage(&car[i], "车.png");
	}
}

接下来就是定义画布,然后加载图片,我设定的地图是左右两边是一列草地,其余的都是公路。
在这里插入图片描述

const int IMAGE_SIZE = 128;
void SetMap(int x, int y) {
	for (int i = 0; i < y; i++) {
		for (int j = 0; j < x; j++) {
			if (j == 0 || j == x - 1) {	//草地
				putimage(j * IMAGE_SIZE, i * IMAGE_SIZE, &grass);
			}
			else {						//公路
				putimage(j * IMAGE_SIZE, i * IMAGE_SIZE, &road);
			}
		}
	}

	//设置线条格式
	setlinestyle(PS_SOLID, 3);
	//设置线条颜色
	setlinecolor(BLACK);
	//从左上角到右下角画线条(车道两边的边缘)
	line(IMAGE_SIZE, 0, IMAGE_SIZE, y * IMAGE_SIZE);
	line((x - 1) * IMAGE_SIZE, 0, (x - 1) * IMAGE_SIZE, y * IMAGE_SIZE);

	//车道中间实线
	setlinecolor(YELLOW);
	line(x / 2 * IMAGE_SIZE, 0, x / 2 * IMAGE_SIZE, y * IMAGE_SIZE);
}

紧接着是画虚实线,我们定义虚实线的结构体,并用数组来存放这些虚实线

const int LINE_NUM = 3 * 10 * 8;	//虚实线的最大数量,这个看实际需求
const int LINE_LEN = 50;			//虚实线的长度,这个看实际需求
const int LINE_SPACE = 25;			//虚实线的间隔,这个看实际需求
int lines_cnt;						//虚实线数量
struct Line {
	int x, y;						//坐标
	int len;						//长度
}lines[LINE_NUM];
void initLines(int x, int y) {
	int lines_col = x - 2;											//有多少列
	int lines_row = y * IMAGE_SIZE / (LINE_LEN + LINE_SPACE) + 1;	//有多少行
	lines_cnt = lines_row * lines_col;
	int idx = 0;
	for (int i = 1; i <= lines_col; i++) {
		//初始化坐标
		x = i * IMAGE_SIZE + IMAGE_SIZE / 2;
		y = 0;
		for (int j = 0; j < lines_row; j++) {
			lines[idx].len = LINE_LEN;
			lines[idx].y = y;
			lines[idx].x = x;
			idx++;
			y += LINE_LEN + LINE_SPACE;
		}
	}
}

画虚实线并移动它们

void ShowLine(float speed) {
	setlinecolor(WHITE);
	for (int i = 0; i < lines_cnt; i++) {
		//画
		line(lines[i].x, lines[i].y, lines[i].x, lines[i].y + lines[i].len);
		//移动
		int dst = lines[i].y + lines[i].len * speed;
		//虚实线超出显示窗口范围把它们移到显示窗口上方
		lines[i].y = dst > getheight() ? -lines[i].len : dst;
	}
}

这时候发现画面闪烁
在这里插入图片描述
当数据量很大时,绘图可能需要几秒钟甚至更长的时间,而且有时还会出现闪烁现象,为了解决这些问题,可采用双缓冲技术来绘图。

双缓冲实现过程如下:
1、在内存中创建与画布一致的缓冲区
2、在缓冲区画图
3、将缓冲区位图拷贝到当前画布上
4、释放内存缓冲区

我们可以使用easyx提供的函数去实现双缓冲技术

BeginBatchDraw();		//开启双缓冲绘图
while (true){
	/*
	画图操作
	*/
	FlushBatchDraw();	//更新双缓冲绘图
}
EndBatchDraw();			//结束双缓冲绘图

在这里插入图片描述
车的定义,使用结构体

const int CARS_NUM = 40;			//车的最大总数量,这个看实际情况
struct Car{
	int x, y, w, h;					//坐标和长宽
	int dir;						//方向
	int speed;						//速度
	int srcx, srcy;					//在资源的坐标
};
Car player, emenyCar[CARS_NUM];

初始化玩家和敌人属性

const enum DIRS {
	DIR_UP,
	DIR_DOWN
};
const int MAX_CARS = 15;			//车的种类数量
int lines_col;						//车道数量
int d;								//距离车道左边间隔
int cars_num;						//车的总数量
void initCar(int x, int y, int lv) {
	srand((unsigned)time(NULL));	//设置随机数种子,使用rand()的时候有用
	lines_col = (x - 2) * 2;		//有多少车道
	d = 10;							//距离车道左边间隔
	cars_num = lines_col + y - 4;	//其他车辆数量
	//玩家
	player.y = getheight() - IMAGE_SIZE;
	player.x = IMAGE_SIZE / 2 * (rand() % lines_col + 2) + d;
	player.dir = DIR_UP;
	player.speed = 1 + lv;
	player.w = 43;
	player.h = 74;
	player.srcx = rand() % 3 * player.w;
	player.srcy = rand() % 5 * player.h;
	//其他车辆
	for (int i = 0; i < cars_num; i++) {
		emenyCar[i].w = 43;
		emenyCar[i].h = 74;
		//检测重叠
		do {
			emenyCar[i].y = rand() % (getheight() - IMAGE_SIZE) - IMAGE_SIZE * y;
			emenyCar[i].x = IMAGE_SIZE / 2 * (rand() % lines_col + 2) + d;
		} while (overlapation(emenyCar[i], i) && colhasempty());
		emenyCar[i].dir = DIR_UP;
		emenyCar[i].speed = lv;
		emenyCar[i].srcx = rand() % 3 * emenyCar[i].w;
		emenyCar[i].srcy = rand() % 5 * emenyCar[i].h;
		col_cnt_car[(emenyCar[i].x - d) * 2 / IMAGE_SIZE]++;
	}
}

检测重叠代码

bool overlapation(const struct Car& a, int idx) {
	if (collision(player, a)) {
		return true;
	}
	for (int i = 0; i < CARS_NUM; i++) {
		if (idx == i) {
			continue;
		}
		if (collision(emenyCar[i], a)) {
			return true;
		}
	}
	return false;
}

检测是否有空的车道

bool colhasempty() {
	int ret = 1;
	for (int i = 0; i < lines_col; i++) {
		ret &= col_cnt_car[i];
	}
	return !ret;
}

检测碰撞代码

struct Point {
	int x, y;						//坐标
};
bool collision(const struct Car& a, const struct Car& b) {
	//a的四个点
	struct Point ap[4] = {
		{a.x, a.y},
		{a.x, a.y + a.h},
		{a.x + a.w, a.y},
		{a.x + a.w, a.y + a.h}
	};
	for (int i = 0; i < 4; i++) {
		if (ap[i].x >= b.x && ap[i].x <= b.x + b.w &&
			ap[i].y >= b.y && ap[i].y <= b.y + b.h) {
			return true;
		}
	}
	return false;
}

在这里插入图片描述
显示车辆在地图上
如果我们用easyx提供的putimage函数打印我们的车辆可以发现车辆四周有黑色的边框,这是因为putimage函数不能处理图片的透明度,我们要写一个函数来实现打印带透明度的图片。
在这里插入图片描述

图片的颜色储存是按ARGB的方式:
Red(红色) Green(绿色) Blue(蓝色)和 Alpha(透明度)的色彩空间
在这里插入图片描述

typedef unsigned long COLORREF;
typedef unsigned char byte;
typedef struct ARGB{
	byte a;
	byte r;
	byte g;
	byte b;
}ARGB;

/// <summary>
/// 分解RGB合成的颜色
/// </summary>
/// <param name="c">待分解的颜色</param>
ARGB DecompositionColor(COLORREF c){
	byte r = (byte)c;
	byte g = (byte)(c >> 8);
	byte b = (byte)(c >> 16);
	byte a = (byte)(c >> 24);
	ARGB res = { a,r,g,b };
	return res;
}

设计一个绘制PNG透明图片函数

void showimage(int x, int y, int w, int h, IMAGE* img, int srcx, int srcy){
	DWORD* pdraw = GetImageBuffer();
	DWORD* pImg = GetImageBuffer(img);
	int win_w = getwidth();
	int win_h = getheight();
	int img_w = img->getwidth();
	int img_h = img->getheight();
	int imgx = 0;
	for (int i = 0; i < w; i++){
		for (int k = 0; k < h; k++){
			int index = (k + srcy) * img_w + i + srcx;//当前IMG操作位置
			ARGB img_argb = DecompositionColor(pImg[index]);
			imgx = (y + k) * win_w + (i + x);

			if (img_argb.a != 0 && imgx >= 0 && imgx < win_w * win_h){
				pdraw[imgx] = pImg[index];
			}
		}
	}
}

调用showimage函数显示车辆

void ShowCar() {
	//显示玩家
	showimage(player.x, player.y, player.w, player.h, &car, player.srcx, player.srcy);
	//显示其他车辆
	for (int i = 0; i < cars_num; i++) {
		showimage(emenyCar[i].x, emenyCar[i].y, emenyCar[i].w, emenyCar[i].h, &car, emenyCar[i].srcx, emenyCar[i].srcy);
		//其他车辆移动
		emenyCar[i].y += emenyCar[i].speed;
		//其他车辆移动超出显示窗口范围把它们移到显示窗口上方
		if (emenyCar[i].y > getheight()) {
			col_cnt_car[(emenyCar[i].x - d) * 2 / IMAGE_SIZE]--;
			//检测重叠
			do {
				emenyCar[i].y = -emenyCar[i].h;
				emenyCar[i].x = IMAGE_SIZE / 2 * (rand() % lines_col + 2) + d;
			} while (overlapation(emenyCar[i], i) && colhasempty());
			emenyCar[i].srcx = rand() % 3 * emenyCar[i].w;
			emenyCar[i].srcy = rand() % 5 * emenyCar[i].h;
			col_cnt_car[(emenyCar[i].x - d) * 2 / IMAGE_SIZE]++;
		}
	}
}

在这里插入图片描述

玩家的移动(异步读取玩家的方向操作)

void move() {
	static int oldcom = 0;
	if (GetAsyncKeyState(VK_UP) && player.y > 0) {
		player.y -= player.speed;
		if (oldcom != VK_UP && !GetAsyncKeyState(oldcom)) {
			playmusic("加速.mp3", "");
			oldcom = VK_UP;
		}
	}
	if (GetAsyncKeyState(VK_DOWN) && player.y + player.h < getheight()){
		player.y += player.speed;
		if (oldcom != VK_DOWN && !GetAsyncKeyState(oldcom)) {
			playmusic("急刹.mp3", "");
			oldcom = VK_DOWN;
		}
	}
	if (GetAsyncKeyState(VK_LEFT) && player.x > IMAGE_SIZE) {
		player.x -= player.speed;
		if (oldcom != VK_LEFT && !GetAsyncKeyState(oldcom)) {
			playmusic("漂移.mp3", "");
			oldcom = VK_LEFT;
		}
	}
	if (GetAsyncKeyState(VK_RIGHT) && player.x + player.w < getwidth() - IMAGE_SIZE) {
		player.x += player.speed;
		if (oldcom != VK_RIGHT && !GetAsyncKeyState(oldcom)) {
			playmusic("漂移.mp3", "");
			oldcom = VK_RIGHT;
		}
	}
}

播放音效函数

void playmusic(string name, string type) {
	static string oldname = "";
	static string oldtype = "";
	if (oldname.size() > 0 && oldtype != "repeat") {
		string closecom = "close ./" + oldname;
		mciSendString(closecom.c_str(), NULL, 0, NULL);
	}
	string opencom = "open ./" + name;
	string playcom = "play ./" + name;
	if (type.size() > 0) {
		playcom += " " + type;
	}
	mciSendString(opencom.c_str(), NULL, 0, NULL);
	mciSendString(playcom.c_str(), NULL, 0, NULL);
	oldname = name;
	oldtype = type;
}

判断玩家是否碰撞到其他车辆

bool conflict() {
	for (int i = 0; i < cars_num; i++) {
		if (collision(player, emenyCar[i])) {
			return true;
		}
	}
	return false;
}

初始化游戏参数

void initgame(int& w, int& h, int& lv) {
	printf("请输入地图长度(最小为4,最大为10,默认为4):");
	scanf("%d", &w);
	w = w >= 4 && w <= 10 ? w : 4;
	printf("设置地图长度为[%d]\n", w);
	printf("请输入地图高度(最小为3,最大为10,默认为6):");
	scanf("%d", &h);
	h = h >= 3 && h <= 10 ? h : 6;
	printf("设置地图高度为[%d]\n", h);
	printf("请输入游戏难度(最小为1,最大为10,默认为1):");
	scanf("%d", &lv);
	lv = lv >= 1 && lv <= 10 ? lv : 1;
	printf("设置游戏难度为[%d]\n", lv);
	printf("按任意键开始游戏");
	_getch();
}

避免游戏运行的太快导致游戏的可玩性下降,我们可以画完一次图后停止运行10毫秒

Sleep(10);

游戏流程

int main() {
	int w, h, lv;			//地图的长宽和难度
	playmusic("背景音乐.mp3", "repeat");
	initgame(w, h, lv);
	initgraph(w * IMAGE_SIZE, h * IMAGE_SIZE);
	initgamePicture();
	initLines(w, h);
	initCar(w, h, lv);
	BeginBatchDraw();		//开启双缓冲绘图
	while (true) {
		SetMap(w, h);
		ShowLine(0.02 + 0.02 * lv);
		ShowCar();
		move();
		FlushBatchDraw();	//更新双缓冲绘图
		Sleep(10);
		if (conflict()) {
			playmusic("失败.mp3", "");
			break;
		}
	}
	EndBatchDraw();			//结束双缓冲绘图
	mciSendString("close ./背景音乐.mp3", NULL, 0, NULL);
	MessageBox(0, "游戏结束了", "失败", MB_OK);
	closegraph();
	return 0;
}

完整的代码
tools.h

#pragma once
#ifndef _TOOLS_H_
#define _TOOLS_H_
#include<graphics.h>
typedef unsigned long COLORREF;
typedef unsigned char byte;
typedef struct ARGB{
	byte a;
	byte r;
	byte g;
	byte b;
}ARGB;

/// <summary>
/// 分解RGB合成的颜色
/// </summary>
/// <param name="c">待分解的颜色</param>
ARGB DecompositionColor(COLORREF c){
	byte r = (byte)c;
	byte g = (byte)(c >> 8);
	byte b = (byte)(c >> 16);
	byte a = (byte)(c >> 24);
	ARGB res = { a,r,g,b };
	return res;
}
/// <summary>
/// 绘制PNG透明图片
/// </summary>
/// <param name="x">图片左上角横坐标</param>
/// <param name="y">图片左上角纵坐标</param>
/// <param name="img">要绘制的图片指针</param>
void showimage(int x, int y, int w, int h, IMAGE* img, int srcx, int srcy){
	DWORD* pdraw = GetImageBuffer();
	DWORD* pImg = GetImageBuffer(img);
	int win_w = getwidth();
	int win_h = getheight();
	int img_w = img->getwidth();
	int img_h = img->getheight();
	int imgx = 0;
	for (int i = 0; i < w; i++){
		for (int k = 0; k < h; k++){
			int index = (k + srcy) * img_w + i + srcx;//当前IMG操作位置
			ARGB img_argb = DecompositionColor(pImg[index]);
			imgx = (y + k) * win_w + (i + x);

			if (img_argb.a != 0 && imgx >= 0 && imgx < win_w * win_h){
				pdraw[imgx] = pImg[index];
			}
		}
	}
}
#endif // !_TOOLS_H_

急速赛车.cpp

#define _CRT_SECURE_NO_WARNINGS	//去掉scanf_s问题
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <graphics.h>
#include <string>
#include "tools.h"
#pragma comment(lib, "winmm.lib")
using namespace std;

const int IMAGE_SIZE = 128;
const int MAX_CARS = 15;			//车的最大总数量,这个看实际情况
const int LINE_NUM = 3 * 10 * 8;	//虚实线的最大数量,这个看实际需求
const int LINE_LEN = 50;			//虚实线的长度,这个看实际需求
const int LINE_SPACE = 25;			//虚实线的间隔,这个看实际需求
const int CARS_NUM = 40;			//车的最大总数量,这个看实际情况

const enum DIRS {
	DIR_UP,
	DIR_DOWN
};

struct Line {
	int x, y;						//坐标
	int len;						//长度
}lines[LINE_NUM];

struct Car{
	int x, y, w, h;					//坐标和长宽
	int dir;						//方向
	int speed;						//速度
	int srcx, srcy;					//在资源的坐标
};

struct Point {
	int x, y;						//坐标
};

Car player, emenyCar[CARS_NUM];

int lines_col;						//车道数量
int d;								//距离车道左边间隔
int lines_cnt;						//虚实线数量
int cars_num;						//车的总数量
int col_cnt_car[20];				//每一列车的数量

void initgamePicture();										//读取游戏素材图片
void initgame(int &w, int &h, int &lv);						//初始化游戏参数
void initCar(int x, int y, int lv);							//初始化车辆
void initLines(int x, int y);								//初始化虚实线
void SetMap(int x, int y);									//绘制地图
void ShowLine(float speed);									//显示虚实线
void ShowCar();												//显示车辆
void move();												//玩家移动
bool collision(const struct Car& a, const struct Car& b);	//判断两个车辆碰撞
bool overlapation(const struct Car& a, int idx);			//判断车辆覆盖
bool conflict();											//判断玩家和其他车辆碰撞
void playmusic(string name, string type);					//播放音乐
bool colhasempty();											//判断是否有空的车道

IMAGE road, grass, car;

int main() {
	int w, h, lv;			//地图的长宽和难度
	playmusic("背景音乐.mp3", "repeat");
	initgame(w, h, lv);
	initgraph(w * IMAGE_SIZE, h * IMAGE_SIZE);
	initgamePicture();
	initLines(w, h);
	initCar(w, h, lv);
	BeginBatchDraw();		//开启双缓冲绘图
	while (true) {
		SetMap(w, h);
		ShowLine(0.02 + 0.02 * lv);
		ShowCar();
		move();
		FlushBatchDraw();	//更新双缓冲绘图
		Sleep(10);
		if (conflict()) {
			playmusic("失败.mp3", "");
			break;
		}
	}
	EndBatchDraw();			//结束双缓冲绘图
	mciSendString("close ./背景音乐.mp3", NULL, 0, NULL);
	MessageBox(0, "游戏结束了", "失败", MB_OK);
	closegraph();
	return 0;
}

void initgamePicture() {
	loadimage(&grass, "草.jpg", IMAGE_SIZE, IMAGE_SIZE);
	loadimage(&road, "路.png", IMAGE_SIZE, IMAGE_SIZE);
	for (int i = 0; i < MAX_CARS; i++) {
		loadimage(&car, "车.png");
	}
}

void initgame(int& w, int& h, int& lv) {
	printf("请输入地图长度(最小为4,最大为10,默认为4):");
	scanf("%d", &w);
	w = w >= 4 && w <= 10 ? w : 4;
	printf("设置地图长度为[%d]\n", w);
	printf("请输入地图高度(最小为3,最大为10,默认为6):");
	scanf("%d", &h);
	h = h >= 3 && h <= 10 ? h : 6;
	printf("设置地图高度为[%d]\n", h);
	printf("请输入游戏难度(最小为1,最大为10,默认为1):");
	scanf("%d", &lv);
	lv = lv >= 1 && lv <= 10 ? lv : 1;
	printf("设置游戏难度为[%d]\n", lv);
	printf("按任意键开始游戏");
	_getch();
}

void initCar(int x, int y, int lv) {
	srand((unsigned)time(NULL));	//设置随机数种子,使用rand()的时候有用
	lines_col = (x - 2) * 2;		//有多少车道
	d = 10;							//距离车道左边间隔
	cars_num = lines_col + y - 4;	//其他车辆数量
	//玩家
	player.y = getheight() - IMAGE_SIZE;
	player.x = IMAGE_SIZE / 2 * (rand() % lines_col + 2) + d;
	player.dir = DIR_UP;
	player.speed = 1 + lv;
	player.w = 43;
	player.h = 74;
	player.srcx = rand() % 3 * player.w;
	player.srcy = rand() % 5 * player.h;
	//其他车辆
	for (int i = 0; i < cars_num; i++) {
		emenyCar[i].w = 43;
		emenyCar[i].h = 74;
		//检测重叠
		do {
			emenyCar[i].y = rand() % (getheight() - IMAGE_SIZE) - IMAGE_SIZE * y;
			emenyCar[i].x = IMAGE_SIZE / 2 * (rand() % lines_col + 2) + d;
		} while (overlapation(emenyCar[i], i) && colhasempty());
		emenyCar[i].dir = DIR_UP;
		emenyCar[i].speed = lv;
		emenyCar[i].srcx = rand() % 3 * emenyCar[i].w;
		emenyCar[i].srcy = rand() % 5 * emenyCar[i].h;
		col_cnt_car[(emenyCar[i].x - d) * 2 / IMAGE_SIZE]++;
	}
}

void initLines(int x, int y) {
	int lines_col = x - 2;											//有多少列
	int lines_row = y * IMAGE_SIZE / (LINE_LEN + LINE_SPACE) + 1;	//有多少行
	lines_cnt = lines_row * lines_col;
	int idx = 0;
	for (int i = 1; i <= lines_col; i++) {
		//初始化坐标
		x = i * IMAGE_SIZE + IMAGE_SIZE / 2;
		y = 0;
		for (int j = 0; j < lines_row; j++) {
			lines[idx].len = LINE_LEN;
			lines[idx].y = y;
			lines[idx].x = x;
			idx++;
			y += LINE_LEN + LINE_SPACE;
		}
	}
}

void SetMap(int x, int y) {
	for (int i = 0; i < y; i++) {
		for (int j = 0; j < x; j++) {
			if (j == 0 || j == x - 1) {	//草地
				putimage(j * IMAGE_SIZE, i * IMAGE_SIZE, &grass);
			}
			else {						//公路
				putimage(j * IMAGE_SIZE, i * IMAGE_SIZE, &road);
			}
		}
	}

	//设置线条格式
	setlinestyle(PS_SOLID, 3);
	//设置线条颜色
	setlinecolor(BLACK);
	//从左上角到右下角画线条(车道两边的边缘)
	line(IMAGE_SIZE, 0, IMAGE_SIZE, y * IMAGE_SIZE);
	line((x - 1) * IMAGE_SIZE, 0, (x - 1) * IMAGE_SIZE, y * IMAGE_SIZE);

	//车道中间实线
	setlinecolor(YELLOW);
	line(x / 2 * IMAGE_SIZE, 0, x / 2 * IMAGE_SIZE, y * IMAGE_SIZE);
}

void ShowLine(float speed) {
	setlinecolor(WHITE);
	for (int i = 0; i < lines_cnt; i++) {
		//画
		line(lines[i].x, lines[i].y, lines[i].x, lines[i].y + lines[i].len);
		//移动
		int dst = lines[i].y + lines[i].len * speed;
		//虚实线超出显示窗口范围把它们移到显示窗口上方
		lines[i].y = dst > getheight() ? -lines[i].len : dst;
	}
}

void ShowCar() {
	//显示玩家
	showimage(player.x, player.y, player.w, player.h, &car, player.srcx, player.srcy);
	//显示其他车辆
	for (int i = 0; i < cars_num; i++) {
		showimage(emenyCar[i].x, emenyCar[i].y, emenyCar[i].w, emenyCar[i].h, &car, emenyCar[i].srcx, emenyCar[i].srcy);
		//其他车辆移动
		emenyCar[i].y += emenyCar[i].speed;
		//其他车辆移动超出显示窗口范围把它们移到显示窗口上方
		if (emenyCar[i].y > getheight()) {
			col_cnt_car[(emenyCar[i].x - d) * 2 / IMAGE_SIZE]--;
			//检测重叠
			do {
				emenyCar[i].y = -emenyCar[i].h;
				emenyCar[i].x = IMAGE_SIZE / 2 * (rand() % lines_col + 2) + d;
			} while (overlapation(emenyCar[i], i) && colhasempty());
			emenyCar[i].srcx = rand() % 3 * emenyCar[i].w;
			emenyCar[i].srcy = rand() % 5 * emenyCar[i].h;
			col_cnt_car[(emenyCar[i].x - d) * 2 / IMAGE_SIZE]++;
		}
	}
}

void move() {
	static int oldcom = 0;
	if (GetAsyncKeyState(VK_UP) && player.y > 0) {
		player.y -= player.speed;
		if (oldcom != VK_UP && !GetAsyncKeyState(oldcom)) {
			playmusic("加速.mp3", "");
			oldcom = VK_UP;
		}
	}
	if (GetAsyncKeyState(VK_DOWN) && player.y + player.h < getheight()){
		player.y += player.speed;
		if (oldcom != VK_DOWN && !GetAsyncKeyState(oldcom)) {
			playmusic("急刹.mp3", "");
			oldcom = VK_DOWN;
		}
	}
	if (GetAsyncKeyState(VK_LEFT) && player.x > IMAGE_SIZE) {
		player.x -= player.speed;
		if (oldcom != VK_LEFT && !GetAsyncKeyState(oldcom)) {
			playmusic("漂移.mp3", "");
			oldcom = VK_LEFT;
		}
	}
	if (GetAsyncKeyState(VK_RIGHT) && player.x + player.w < getwidth() - IMAGE_SIZE) {
		player.x += player.speed;
		if (oldcom != VK_RIGHT && !GetAsyncKeyState(oldcom)) {
			playmusic("漂移.mp3", "");
			oldcom = VK_RIGHT;
		}
	}
}

bool collision(const struct Car& a, const struct Car& b) {
	//a的四个点
	struct Point ap[4] = {
		{a.x, a.y},
		{a.x, a.y + a.h},
		{a.x + a.w, a.y},
		{a.x + a.w, a.y + a.h}
	};
	for (int i = 0; i < 4; i++) {
		if (ap[i].x >= b.x && ap[i].x <= b.x + b.w &&
			ap[i].y >= b.y && ap[i].y <= b.y + b.h) {
			return true;
		}
	}
	return false;
}

bool overlapation(const struct Car& a, int idx) {
	if (collision(player, a)) {
		return true;
	}
	for (int i = 0; i < CARS_NUM; i++) {
		if (idx == i) {
			continue;
		}
		if (collision(emenyCar[i], a)) {
			return true;
		}
	}
	return false;
}

bool conflict() {
	for (int i = 0; i < cars_num; i++) {
		if (collision(player, emenyCar[i])) {
			return true;
		}
	}
	return false;
}

void playmusic(string name, string type) {
	static string oldname = "";
	static string oldtype = "";
	if (oldname.size() > 0 && oldtype != "repeat") {
		string closecom = "close ./" + oldname;
		mciSendString(closecom.c_str(), NULL, 0, NULL);
	}
	string opencom = "open ./" + name;
	string playcom = "play ./" + name;
	if (type.size() > 0) {
		playcom += " " + type;
	}
	mciSendString(opencom.c_str(), NULL, 0, NULL);
	mciSendString(playcom.c_str(), NULL, 0, NULL);
	oldname = name;
	oldtype = type;
}

bool colhasempty() {
	int ret = 1;
	for (int i = 0; i < lines_col; i++) {
		ret &= col_cnt_car[i];
	}
	return !ret;
}
  • 14
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值