【C/C++】Acllib实现的坦克大战

1 篇文章 1 订阅

用面向过程的思路写,对游戏设计的整体框架有了一个宏观的认知:

1.将游戏里的每一个物体/事件存在队列中,通过遍历队列来维护数据的更新。

2.通过分频来控制刷新速率(子弹/坦克/爆炸动画,频率快慢)。

写了快一天,有点累,先贴代码~有空在更新注解吐舌头



#include <acllib.h>
#include <iostream>
#include <stdio.h>
#include <queue>
#include <vector>
#include <algorithm>
#include <time.h>
#define SIZE 50
#define boundaryW 13

using namespace std;

ACL_Image * t_pic = new ACL_Image[4];//tank
ACL_Image * g_pic = new ACL_Image[4];//gun
ACL_Image * eg_pic = new ACL_Image[4];//enemy's gun
ACL_Image * b_pic = new ACL_Image[3];//animation bomb
ACL_Image * w_pic = new ACL_Image[3];//wall
ACL_Image * e_pic = new ACL_Image[4];//enemy
ACL_Image * lose = new ACL_Image;

enum dir
{
	dir_up,
	dir_down,
	dir_left,
	dir_right
};

typedef struct Pstruct {
	int x, y;
	bool operator == (const struct Pstruct & A)const {
		return x == A.x&&y == A.y;
	}
}posi;

typedef struct Gstruct {
	posi g_posi;
	dir g_dir;
	int damage=50;
	int group;
	
}gun;

typedef struct Tstruct {
	posi t_posi;
	int life;
	dir t_dir;
	int group;//0 : friend ,1 : enemy 
	gun t_gun;
	
}tank;

typedef struct Astruct {
	posi p;
	int fps;
	int index;
}animations;

tank player;
queue<tank> enemies;	//敌方坦克队列
queue<animations> ani;  //动画队列
vector<dir> dire;
queue<gun> GUN;

int cnt,cnt1;		//用于计时器分频
bool isMove, isFire;
int WINDOWS[boundaryW][boundaryW];

void timeEvent(int tid);
void keyEvent(int key, int event);
void draw_window();
void initPlayer();

int mm = 0;

int Setup()
{
	initWindow("Test", DEFAULT, DEFAULT, 650, 650);
	
	initPlayer();
	loadImage("F:/Game Data/tankimages/0.jpg", t_pic);
	loadImage("F:/Game Data/tankimages/1.jpg", t_pic + 1);
	loadImage("F:/Game Data/tankimages/2.jpg", t_pic + 2);
	loadImage("F:/Game Data/tankimages/3.jpg", t_pic + 3);

	loadImage("F:/Game Data/tankimages/e0.jpg", e_pic);
	loadImage("F:/Game Data/tankimages/e1.jpg", e_pic + 1);
	loadImage("F:/Game Data/tankimages/e2.jpg", e_pic + 2);
	loadImage("F:/Game Data/tankimages/e3.jpg", e_pic + 3);

	loadImage("F:/Game Data/tankimages/g0.jpg", g_pic);
	loadImage("F:/Game Data/tankimages/g1.jpg", g_pic + 1);
	loadImage("F:/Game Data/tankimages/g2.jpg", g_pic + 2);
	loadImage("F:/Game Data/tankimages/g3.jpg", g_pic + 3);

	loadImage("F:/Game Data/tankimages/b0.jpg", b_pic+2);
	loadImage("F:/Game Data/tankimages/b1.jpg", b_pic + 1);
	loadImage("F:/Game Data/tankimages/b2.jpg", b_pic );

	loadImage("F:/Game Data/tankimages/w0.jpg", w_pic+0);
	loadImage("F:/Game Data/tankimages/w1.jpg", w_pic+1);
	loadImage("F:/Game Data/tankimages/w2.jpg", w_pic+2);

	loadImage("F:/Game Data/tankimages/eg0.jpg", eg_pic);
	loadImage("F:/Game Data/tankimages/eg1.jpg", eg_pic + 1);
	loadImage("F:/Game Data/tankimages/eg2.jpg", eg_pic + 2);
	loadImage("F:/Game Data/tankimages/eg3.jpg", eg_pic + 3);

	loadImage("F:/Game Data/tankimages/lose.jpg", lose);

	registerTimerEvent(timeEvent);
	registerKeyboardEvent(keyEvent);
	startTimer(0, 80);
	return 0;
}

void initPlayer() {
	player.group = 0;
	player.life = 100;
	player.t_dir = dir_up;
	player.t_posi.x = boundaryW / 2;
	player.t_posi.y = boundaryW - 1;
	while (!GUN.empty()) GUN.pop();

	enemies.push(player);
	tank temp;
	temp.group = 1;
	temp.life = 100;
	temp.t_dir = dir_down;
	temp.t_posi.x = 0;
	temp.t_posi.y = 0;
	enemies.push(temp);
	for (int i = 0; i < boundaryW / 2 -1; i++) {
		for (int j = 0; j < boundaryW; j++) {
			if (j % 2) {
				WINDOWS[j][i] = 1;
			}
		}
	}
	WINDOWS[3][boundaryW / 2] = WINDOWS[2][boundaryW / 2] = WINDOWS[boundaryW - 4][boundaryW / 2] = WINDOWS[boundaryW - 3][boundaryW / 2] = 1;
	for (int i = boundaryW / 2 + 2; i < boundaryW - 1 ; i++) {
		for (int j = 0; j < boundaryW; j++) {
			if (j % 2) {
				WINDOWS[j][i] = 1;
			}
		}
	}
	
	for (int i = 0; i < boundaryW; i++) {
		for (int j = 0; j < boundaryW; j++) {
			if (WINDOWS[i][j]) {
				tank temp;
				temp.group = 3;
				temp.t_dir = dir_up;
				temp.life = 150;
				temp.t_posi.x = i;
				temp.t_posi.y = j;
				enemies.push(temp);
			}
		}
	}
	
}

void draw_window() {
	
	beginPaint();
	clearDevice();
	setPenColor(RGB(0, 0, 0));
	setBrushColor(RGB(0, 0, 0));
	rectangle(0, 0, 650, 650);
	if (player.life > 0) {
		
		int aniNum = ani.size();
		int LenQ = GUN.size();
		int NumEnemy = enemies.size();
		//动画爆炸消息
		while (aniNum--) {
			animations tmpAni = ani.front();
			ani.pop();
			putImageScale(b_pic + tmpAni.fps - 1, tmpAni.p.x*SIZE, tmpAni.p.y*SIZE, SIZE, SIZE);
			if (cnt1 > 2)cnt1 = 0;
			else if (cnt1 == 2) {
				cnt1 = 0;
				tmpAni.fps--;
			}
			if (tmpAni.fps) { ani.push(tmpAni); }
		}
		//坦克移动消息
		if (dire.empty()) isMove = false;
		else isMove = true;
		NumEnemy = enemies.size();
		while (NumEnemy--)
		{
			tank tmpEnemy;
			tmpEnemy = enemies.front();
			enemies.pop();
			//敌方
			if (tmpEnemy.group == 3) {
				enemies.push(tmpEnemy);
				continue;
			}
			else if (tmpEnemy.group == 1) {
				if (cnt >= 4) {
					bool flag = true;
					if (player.t_posi.x == tmpEnemy.t_posi.x) {
						flag = false;
						gun * bullet = new gun;
						bullet->g_posi = tmpEnemy.t_posi;
						bullet->group = 1;
						if (player.t_posi.y > tmpEnemy.t_posi.y)	bullet->g_dir = dir_down;
						else bullet->g_dir = dir_up;
						GUN.push(*bullet);
					}
					else if (player.t_posi.y == tmpEnemy.t_posi.y) {
						flag = false;
						gun * bullet = new gun;
						bullet->g_posi = tmpEnemy.t_posi;
						bullet->group = 1;
						if (player.t_posi.x > tmpEnemy.t_posi.x)	bullet->g_dir = dir_right;
						else bullet->g_dir = dir_left;
						GUN.push(*bullet);
					}
					if (flag) {
						if (tmpEnemy.t_posi.y == boundaryW - 1)mm++;
						if (tmpEnemy.t_posi.y == 0)mm++;
						if (mm % 2 == 0) {
							tmpEnemy.t_dir = dir_up;
							tmpEnemy.t_posi.y--;
						}
						else {
							tmpEnemy.t_dir = dir_down;
							tmpEnemy.t_posi.y++;
						}
					}
				}
			}
			else {
				//我方
				if (cnt >= 4) {
					player = tmpEnemy;
					//开火消息
					if (isFire) {
						isFire = false;
						gun * bullet = new gun;
						bullet->g_posi = tmpEnemy.t_posi;
						bullet->group = 0;
						bullet->g_dir = tmpEnemy.t_dir;
						GUN.push(*bullet);
					}
					if (isMove) {
						bool isTurn = false;
						if (tmpEnemy.t_dir != dire.back()) {
							isTurn = true;
							tmpEnemy.t_dir = dire.back();
						}
						switch (tmpEnemy.t_dir) {
						case 0:
							if (!isTurn && tmpEnemy.t_posi.y - 1 >= 0 && !WINDOWS[tmpEnemy.t_posi.x][tmpEnemy.t_posi.y - 1]) tmpEnemy.t_posi.y--;
							break;
						case 1:
							if (!isTurn && tmpEnemy.t_posi.y + 1 < boundaryW && !WINDOWS[tmpEnemy.t_posi.x][tmpEnemy.t_posi.y + 1]) tmpEnemy.t_posi.y++;
							break;
						case 2:
							if (!isTurn && tmpEnemy.t_posi.x - 1 >= 0 && !WINDOWS[tmpEnemy.t_posi.x - 1][tmpEnemy.t_posi.y]) tmpEnemy.t_posi.x--;
							break;
						case 3:
							if (!isTurn && tmpEnemy.t_posi.x + 1 < boundaryW && !WINDOWS[tmpEnemy.t_posi.x + 1][tmpEnemy.t_posi.y]) tmpEnemy.t_posi.x++;
							break;
						}
					}
				}
			}
			if (tmpEnemy.group == 0) putImageScale(t_pic + tmpEnemy.t_dir, tmpEnemy.t_posi.x*SIZE, tmpEnemy.t_posi.y*SIZE, SIZE, SIZE);
			else putImageScale(e_pic + tmpEnemy.t_dir, tmpEnemy.t_posi.x*SIZE, tmpEnemy.t_posi.y*SIZE, SIZE, SIZE);
			enemies.push(tmpEnemy);
		}
		if (cnt >= 4)cnt = 0;

		NumEnemy = enemies.size();
		//墙壁消息
		while (NumEnemy--)
		{
			tank tempEnemy;
			tempEnemy = enemies.front();
			enemies.pop();
			if (tempEnemy.group == 3) {
				int p = tempEnemy.life / 50;
				switch (p) {
				case 1:
					tempEnemy.t_dir = dir_left;
					break;
				case 2:
					tempEnemy.t_dir = dir_down;
					break;
				case 3:
					tempEnemy.t_dir = dir_up;
					break;
				}
				putImageScale(w_pic + tempEnemy.t_dir, tempEnemy.t_posi.x*SIZE, tempEnemy.t_posi.y*SIZE, SIZE, SIZE);
			}
			enemies.push(tempEnemy);
		}
		NumEnemy = enemies.size();
		//子弹信息
		while (LenQ > 0)
		{
			LenQ--;
			bool isHit = false;;
			gun temp = GUN.front();
			GUN.pop();
			dir direct = temp.g_dir;
			switch (direct)
			{
			case dir_up:
				temp.g_posi.y--;
				break;
			case dir_down:
				temp.g_posi.y++;
				break;
			case dir_left:
				temp.g_posi.x--;
				break;
			case dir_right:
				temp.g_posi.x++;
				break;
			}
			if (temp.g_posi.x < 0 || temp.g_posi.x >= boundaryW || temp.g_posi.y < 0 || temp.g_posi.y >= boundaryW) {
				continue;
			}
			NumEnemy = enemies.size();
			while (NumEnemy > 0) {
				NumEnemy--;
				tank tempEnemy = enemies.front();
				enemies.pop();
				if (temp.g_posi == tempEnemy.t_posi) {
					isHit = true;
					if (temp.group != tempEnemy.group) tempEnemy.life -= temp.damage;
					if (tempEnemy.life <= 0) {
						if (tempEnemy.group == 3) {
							WINDOWS[tempEnemy.t_posi.x][tempEnemy.t_posi.y] = 0;
						}
						else if (tempEnemy.group == 0) {
							player = tempEnemy;
						}
						tempEnemy.life = 0;
						animations tt;
						tt.p = temp.g_posi;
						tt.fps = 3;
						tt.index = 0;//bomb animation
						ani.push(tt);
					}
				}
				if (tempEnemy.life) {
					enemies.push(tempEnemy);
				}
				if (isHit)break;
			}
			if (!isHit) {
				GUN.push(temp);
				if (temp.group == 0) putImageScale(g_pic + direct, temp.g_posi.x*SIZE, temp.g_posi.y*SIZE, SIZE, SIZE);
				else putImageScale(eg_pic + direct, temp.g_posi.x*SIZE, temp.g_posi.y*SIZE, SIZE, SIZE);
			}

		}
	}
else
{
	putImageScale(lose, 0, 0, 650, 650);
}
	endPaint();
}

void timeEvent(int tid) {
	cnt++;
	cnt1++;
	draw_window();
}
void keyEvent(int key, int event) {
	if (key == VK_UP) {
		if (event == KEY_DOWN) {
			if(find(dire.begin(),dire.end(),dir_up)==dire.end()) dire.push_back(dir_up);

		}
		else if (event == KEY_UP) {
			if (!dire.empty()) dire.erase(find(dire.begin(), dire.end(), dir_up));
		}
		
	}
	if (key == VK_DOWN) {
		if (event == KEY_DOWN) {
			if (find(dire.begin(), dire.end(), dir_down) == dire.end()) dire.push_back(dir_down);
		}
		else if (event == KEY_UP) {
			if (!dire.empty()) dire.erase(find(dire.begin(), dire.end(), dir_down));
		}
		
	}
	if (key == VK_LEFT) {
		if (event == KEY_DOWN) {
			if (find(dire.begin(), dire.end(), dir_left) == dire.end()) dire.push_back(dir_left);
		}
		else if (event == KEY_UP) {
			if (!dire.empty()) dire.erase(find(dire.begin(), dire.end(), dir_left));
		}
	}
	if (key == VK_RIGHT) {
		if (event == KEY_DOWN) {
			if (find(dire.begin(), dire.end(), dir_right) == dire.end()) dire.push_back(dir_right);
		}
		else if (event == KEY_UP) {
			if(!dire.empty()) dire.erase(find(dire.begin(), dire.end(), dir_right));
		}
	}
	if (key == VK_SPACE) {
		 if (event == KEY_UP) {
			 isFire = true;
		 }
		
	}
	
}


  • 12
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
附件是ACLLib的全部文件,包括源代码和文档及例子程序。 ——MOOC浙江大学C程序设计进阶(翁恺老师) 在Win7或Win8上正常安装的Dev C++,无论是用的MinGW编译器还是TDM编译器都是可以正常使用ACLLib的,但是要注意以下几点: 1. 如果还在使用4.9.9.2的Dev C++,一定要升级到5以上,建议都升级到最新的5.10的版本; 2. 在新建项目的时候选择Windows Application类型; 3. 根据自己机器是32位还是64位来选择编译类型,如果是32位的机器选择MinGW32位方式,如果是64位的机器建议选择TDM的64位方式; 4. 在配置项目的时候,根据32位还是64位选择正确目录下的库文件来加入: 1. 32位下,库文件是: "C:/Program Files/Dev-Cpp/MinGW32/lib/libwinmm.a" "C:/Program Files/Dev-Cpp/MinGW32/lib/libmsimg32.a" "C:/Program Files/Dev-Cpp/MinGW32/lib/libkernel32.a" "C:/Program Files/Dev-Cpp/MinGW32/lib/libuser32.a" "C:/Program Files/Dev-Cpp/MinGW32/lib/libgdi32.a" "C:/Program Files/Dev-Cpp/MinGW32/lib/libole32.a" "C:/Program Files/Dev-Cpp/MinGW32/lib/liboleaut32.a" "C:/Program Files/Dev-Cpp/MinGW32/lib/libuuid.a" 2. 64位下,库文件是: C:/Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib/libwinmm.a C:/Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib/libmsimg32.a C:/Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib/libkernel32.a C:/Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib/libuser32.a C:/Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib/libgdi32.a C:/Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib/libole32.a C:/Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib/liboleaut32.a C:/Program Files/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib/libuuid.a 5. 最后,如果出现“undefined reference to `TransparentBlt' ”这个错误,两个解决方案: 1. 偷懒的,打开acllib.c,找到“TransparentBlt”所在的行,把整行注释掉; 2. 打开工程配置,找到编译器选项,加入-DWINVER=0x0500。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值