ACLLIB‘‘简易‘‘实现炮台打飞机

这是我学了两个月的成果。【已改进】

这几天做这个玩意真要把我做傻了,离谱的是做一半还被要求两天内写完上台展示,属实是提前体验dead line

它涉及到了炮台的角度改变,以及多个链表的增删查改。

下面是主程序:

#include<stdio.h>
#include<stdlib.h>
#include"acllib.h"
#include<time.h>
#include<math.h>

#define WIN_WEIGTH 1000
#define WIN_LENGTH 720
#define CHANGE_pipeANGLE 0.1
#define CHANGE_bulletANGLE 0.1

//Turret and Pipe
#define tStep_x 20
#define OLpipex  485
#define OLpipey  680
#define ORpipex  515
#define ORpipey  680
#define OAngle   1
#define OTturretx 450
#define OTturrety 680
#define OBturretx 550
#define OBturrety 720
#define a 60 //Pipe height 

//Bullet
#define Bulletlength 8
#define Bulletwidth  8
#define vBullet      20

//Plane
#define Move_Planex 5
#define OTplanex 0
#define OTplaney 0
#define OBplanex 20
#define OBplaney 20
#define planeWidth 40
#define planeLength 15


typedef struct _bullet {
	int x1;
	int y1;
	int x2;
	int y2;
	int bangle;
}BULLET;

typedef struct _magazine {        //链表存储子弹
	BULLET Bullet;
	struct _magazine* next_Bullet;
}MAGAZINE;

typedef struct _turret {
	int x1;
	int y1;
	int x2;
	int y2;
}TURRET;
typedef struct _pipe {
	
		int x1;  //左上
		int y1;
	
		int x2;  //左下
		int y2;
	
		int x3;  //右下
		int y3;
	
		int x4;  //右上
		int y4;

	int angle;
}PIPE;
typedef struct _plane {
	int x1;
	int y1;
	int x2;
	int y2;
	int randnum;
}PLANE;
typedef struct _planegroup {        //链表存储子弹
	PLANE Plane;
	struct _planegroup* next_Plane;
}PLANEGROUP;

typedef struct _text {
	int x;
	int y;
	char ch;
}TEXT;


//-----view-----//
void Creat_Turret(void);
void Creat_Pipe(int key, int event);
void Shot_Bullet(void);
void Creat_OTurret(void);  //print a oturret(not clear screen)
void Creat_OPipe(void);    //print a opipe(not clear screen)
void Shot_OBullet(void);
void Shot_Bullet(void);
void Creat_OPlane(void);
void Creat_boom(PLANE* boom_plane);
void Creat_All(void);      //重新绘制所有图形
//-----view-----//
//-----model-----//
void load_Bullet(void);    //加载炮管内子弹
void load_Magazine(void);  //加载弹夹  
void load_Plane(void);     //加载飞机
void load_Planegroup(void);//加载飞机组
void delete_Plane(void);   //超出画面就删除
void delete_Bullet(void);   //超出画面就删除
int test_Crash(void);     //检测碰撞
//-----model-----//
//-----ctrl-----//
void keyListener(int key, int event);
void timerListener(int id);
//-----ctrl-----//



PIPE   Pipe = { OLpipex,OLpipey - a, OLpipex,OLpipey, ORpipex,ORpipey,  ORpipex,ORpipey - a ,0 };         //初始化所有物件位置
PIPE   temp_Pipe = { OLpipex,OLpipey - a, OLpipex,OLpipey, ORpipex,ORpipey,  ORpipex,ORpipey - a ,0 };    //用于记录每次炮管的坐标
TURRET Turret = { OTturretx,OTturrety,OBturretx,OBturrety };
BULLET tBullet;             //初始化一个子弹,但不进行赋值,在load_Bullet后才进行赋值,以同步发射时和炮台的相对位置,每次存进链表后会被更新
PLANE tPlane;               //初始化一个飞机,每次存进链表后会被更新
//PLANE* boomPlane;           //指向爆炸的飞机
MAGAZINE* Magazine = NULL;     //创建一个链表弹夹
BULLET* pBullet = NULL;        //只控制炮管内上膛的子弹坐标,发射后指向下一颗子弹
PLANEGROUP* Planegroup = NULL; //创建一个链表机组
TEXT count_text;               //创建计分板
   
unsigned cnt_plane = 0;
int count = 0;
//-----------------------------------------------------------------------------MAIN-----------------------------------------------------------------------------//

int Setup() {

	initConsole();
	printf("do you want start?\n[1]YES\t[2]YES\n");
	char start;
	while (1) {
		char* p = &start;
		*p = getchar();
		if (*p == '1' ||*p == '2') {
			break;
		}
		else {
			printf("do you want start?\n[1]YES\t[2]YES\n");
		}
	}
    initWindow("Turret fight with plane", DEFAULT, DEFAULT, WIN_WEIGTH, WIN_LENGTH);
	registerKeyboardEvent(keyListener);
	registerTimerEvent(timerListener);
	startTimer(1, 50);    //子弹用
	startTimer(2, 50);   //飞机用
	startTimer(3, 1);    //碰撞用
	return 0;
}
//-----------------------------------------------------------------------------MAIN-----------------------------------------------------------------------------//



//-----------------------------------------------------------------------------VIEW-----------------------------------------------------------------------------//
void Creat_Turret(void) {                       //绘制炮塔
	beginPaint();
	clearDevice();
	setPenColor(BLACK);
	setPenWidth(3);
	setBrushColor(EMPTY);
	setPenStyle(PEN_STYLE_SOLID);
	rectangle(Turret.x1, Turret.y1, Turret.x2, Turret.y2);
	endPaint();
}
void Creat_Pipe(int key, int event) {
	beginPaint();
	clearDevice();
	setPenColor(RED);
	setPenWidth(3);
	setBrushColor(EMPTY);
	setPenStyle(PEN_STYLE_SOLID);
	PIPE* pPipe = &Pipe;
	if ( event == 1) {
		if (key == 'Q') {
			temp_Pipe.angle = Pipe.angle++;       //调整角度
			if (Pipe.angle > 12) {
				Pipe.angle = 12;
			}
		}
		else if (key == 'E') {
			temp_Pipe.angle = Pipe.angle--;
			if (Pipe.angle < -12) {
				Pipe.angle = -12;
			}
		}
		int px = a * sin(Pipe.angle * CHANGE_pipeANGLE);
		int py = a * cos(Pipe.angle * CHANGE_pipeANGLE);
		POINT posPipe[] = {
			{temp_Pipe.x1 = Pipe.x2 - px, temp_Pipe.y1 = Pipe.y2 - py},
			{temp_Pipe.x2 = Pipe.x2, temp_Pipe.y2 = Pipe.y2},
			{temp_Pipe.x3 = Pipe.x3, temp_Pipe.y3 = Pipe.y3},
			{temp_Pipe.x4 = Pipe.x3 - px, temp_Pipe.y4 = Pipe.y3-py},
		};
		polygon(posPipe, 4);
	}else  {
		POINT posPipe[] = {
			{temp_Pipe.x1,temp_Pipe.y1},    //抬起键位的时候再输出一遍上次的图像,防止闪屏
			{temp_Pipe.x2,temp_Pipe.y2},
			{temp_Pipe.x3,temp_Pipe.y3},
			{temp_Pipe.x4,temp_Pipe.y4},
		};
		polygon(posPipe, 4);
	}
	endPaint();
}
void Shot_Bullet(void) {
	if (Magazine) {           //只有弹夹初始化后才能发射
		for (MAGAZINE* pMagazine = Magazine; pMagazine;pMagazine = pMagazine->next_Bullet) {   //找节点,如果存在就改变坐标,画子弹
			int px = vBullet * sin(pMagazine->Bullet.bangle * CHANGE_pipeANGLE);
			int py = vBullet * cos(pMagazine->Bullet.bangle * CHANGE_pipeANGLE);
			pMagazine->Bullet.x1 -= px;
			pMagazine->Bullet.y1 -= py;
			pMagazine->Bullet.x2 -= px;
			pMagazine->Bullet.y2 -= py;
			beginPaint();
			clearDevice();
			setPenColor(BLUE);
			setPenWidth(1);
			setBrushColor(BLUE);
			setPenStyle(PEN_STYLE_SOLID);
			rectangle(pMagazine->Bullet.x1, pMagazine->Bullet.y1, pMagazine->Bullet.x2, pMagazine->Bullet.y2);
			endPaint();
		}
	}
	
}
void Creat_Plane(void) {
	if (Planegroup) {
	beginPaint();
	clearDevice();
	endPaint();
		for (PLANEGROUP* pPlanegroup = Planegroup; pPlanegroup; pPlanegroup = pPlanegroup->next_Plane) {
			/*if (Planegroup->Plane.randnum == 1) {*/
				//printf(" oo ");
				pPlanegroup->Plane.x1 += Move_Planex;
				pPlanegroup->Plane.x2 += Move_Planex;
			/*}*/
			/*else if(Planegroup->Plane.randnum == 0) {
				printf(" ** ");
				pPlanegroup->Plane.x1 -= Move_Planex;
				pPlanegroup->Plane.x2 -= Move_Planex;
			}*/
			beginPaint();
			setPenColor(RGB(147, 112, 219));
			setPenWidth(3);
			setBrushColor(RGB(123, 104, 238));
			setPenStyle(PEN_STYLE_SOLID);
			rectangle(pPlanegroup->Plane.x1, pPlanegroup->Plane.y1, pPlanegroup->Plane.x2, pPlanegroup->Plane.y2);
			endPaint();
		}
	}
}
void Creat_OTurret(void) {    //同时间内其他项目会将此时的画面clear,需要再输出一次上次的坐标
	beginPaint();
	setPenColor(BLACK);
	setPenWidth(3);
	setBrushColor(EMPTY);
	setPenStyle(PEN_STYLE_SOLID);
	rectangle(Turret.x1, Turret.y1, Turret.x2, Turret.y2);
	endPaint();
}
void Creat_OPipe(void) {
	int px = a * sin(Pipe.angle * CHANGE_pipeANGLE);
	int py = a * cos(Pipe.angle * CHANGE_pipeANGLE);
	beginPaint();
	setPenColor(RED);
	setPenWidth(3);
	setBrushColor(EMPTY);
	setPenStyle(PEN_STYLE_SOLID);
	POINT posPipe[] = {
			{temp_Pipe.x1,temp_Pipe.y1},    //抬起键位的时候再输出一遍上次的图像,防止闪屏
			{temp_Pipe.x2,temp_Pipe.y2},
			{temp_Pipe.x3,temp_Pipe.y3},
			{temp_Pipe.x4,temp_Pipe.y4},
	};
	polygon(posPipe, 4);
	endPaint();
}
void Shot_OBullet(void) {     
	if (Magazine) {              //只有弹夹初始化后才能发射
		for (MAGAZINE* pMagazine = Magazine; pMagazine; pMagazine = pMagazine->next_Bullet) {  //找节点,如果存在就画子弹
			beginPaint();
			setPenColor(BLUE);
			setPenWidth(1);
			setBrushColor(BLUE);
			setPenStyle(PEN_STYLE_SOLID);
			rectangle(pMagazine->Bullet.x1, pMagazine->Bullet.y1, pMagazine->Bullet.x2, pMagazine->Bullet.y2);
			endPaint();
		}
	}
}
void Creat_OPlane(void) {
	if (Planegroup) {
		for (PLANEGROUP* pPlanegroup = Planegroup; pPlanegroup; pPlanegroup = pPlanegroup->next_Plane) {
			beginPaint();
			setPenColor(RGB(147, 112, 219));
			setPenWidth(3);
			setBrushColor(RGB(123, 104, 238));
			setPenStyle(PEN_STYLE_SOLID);
			rectangle(pPlanegroup->Plane.x1, pPlanegroup->Plane.y1, pPlanegroup->Plane.x2, pPlanegroup->Plane.y2);
			endPaint();
		}
	}
}
//void Creat_boom(void) {
//	if (boomPlane) {
//		beginPaint();
//		setPenColor(RED);
//		setPenWidth(3);
//		setBrushColor(RED);
//		setPenStyle(PEN_STYLE_SOLID);
//		rectangle(boomPlane->x1, boomPlane->y1, boomPlane->x2, boomPlane->y2);
//		endPaint();
//	}
//}
void Creat_All(void) {
	test_Crash();
	Creat_OPipe();
	Creat_OTurret();
	Shot_OBullet();
	Creat_OPlane();
	//Creat_boom();
}
void Creat_boom(PLANE* boom_Plane) {
	beginPaint();
	setPenColor(RED);
	setPenWidth(3);
	setBrushColor(RED);
	setPenStyle(PEN_STYLE_SOLID);
    ellipse(boom_Plane->x1-20, boom_Plane->y1-20, boom_Plane->x2+20, boom_Plane->y2+20);
	endPaint();
}
//-----------------------------------------------------------------------------VIEW-----------------------------------------------------------------------------//

//-----------------------------------------------------------------------------MODEL-----------------------------------------------------------------------------//
void load_Bullet(void) {                  //根据炮管坐标初始化子弹位置
	tBullet.bangle = Pipe.angle;
	tBullet.x1 = (temp_Pipe.x1 + temp_Pipe.x4) / 2 - Bulletwidth / 2;
	tBullet.y1 = temp_Pipe.y1;
	tBullet.x2 = tBullet.x1 + Bulletwidth;
	tBullet.y2 = tBullet.y1 + Bulletlength;
}
void load_Magazine(void) {                //链表弹夹添加子弹
	MAGAZINE* pMagazine = (MAGAZINE*)malloc(sizeof(MAGAZINE));
	pMagazine->Bullet = tBullet;
	pMagazine->next_Bullet = NULL;
	MAGAZINE* last = Magazine;
	if (last) {
		while (last->next_Bullet != NULL) {
			last = last->next_Bullet;
		}
		last->next_Bullet = pMagazine;
	}
	else {
		Magazine = pMagazine;
	}
}
void load_Plane(void) {           //飞机y坐标随机产生   
	int t = rand()%2;
	//printf("%d ",t);
	tPlane.y1 = rand()%320+1;
	tPlane.y2 = tPlane.y1 + planeLength;
	if (t == 1) {
		tPlane.x1 = -planeWidth;
		tPlane.x2 = tPlane.x1 + planeWidth;
		tPlane.randnum = 1;
	}
	else if( t == 0 ) {
		//printf("\n**\n");
		tPlane.x1 = WIN_WEIGTH + planeWidth;
		tPlane.x2 = tPlane.x1 + planeWidth;
		tPlane.randnum = 0;
	}
}
void load_Planegroup(void) {            //将产生的飞机写入链表
	PLANEGROUP* pPlanegroup = (PLANEGROUP*)malloc(sizeof(PLANEGROUP));
	pPlanegroup->Plane = tPlane;
	pPlanegroup->next_Plane = NULL;
	PLANEGROUP* last = Planegroup;
	if (last) {
		while (last->next_Plane != NULL) {
			last = last->next_Plane;
		}
		last->next_Plane = pPlanegroup;
		//last->next_Plane->next_Plane = NULL;
	}
	else {
		Planegroup = pPlanegroup;
	}
}
void delete_Plane(void) {                     //超出画面的就删除
	PLANEGROUP* q = NULL;
	PLANEGROUP* p = Planegroup;
	for ( ; p; q = p, p = p->next_Plane ) {
		if ( p->Plane.x1 > WIN_WEIGTH ) {
			//printf(" * ");
			if (q) {
				q->next_Plane = p->next_Plane;
			}
			else {
				Planegroup = p->next_Plane;
			}
			free(p);
			break;
		}
	}
}
void delete_Bullet(void) {                     //超出画面的就删除
	MAGAZINE* q = NULL;
	MAGAZINE* p = Magazine;
	for (; p; q = p, p = p->next_Bullet) {
		if ( p->Bullet.y2 < 0 ) {
			//printf(" $ ");
			if (q) {
				q->next_Bullet = p->next_Bullet;
			}
			else {
				Magazine = p->next_Bullet;
			}
			free(p);
			break;
		}
	}
}
int test_Crash(void) {                        //检测子弹和飞机的碰撞(通过坐标是否在范围内判断);
	int turn = 0;
	MAGAZINE* q = NULL;
	MAGAZINE* p = Magazine;
	for ( ; p; q = p, p = p->next_Bullet ) {
		PLANEGROUP* k = NULL;
		PLANEGROUP* j = Planegroup;
		for ( ; j; k = j, j = j->next_Plane ) {
			if (p->Bullet.x1 >= j->Plane.x1-5 && p->Bullet.x1 <= j->Plane.x2+5 && p->Bullet.y1 >= j->Plane.y1-5 && p->Bullet.y1 <= j->Plane.y2+5 && \
				p->Bullet.x2 <= j->Plane.x2+5 && p->Bullet.x2 >= j->Plane.x1-5 && p->Bullet.y2 <= j->Plane.y2+5 && p->Bullet.y2 >= j->Plane.y1-5) {              //nmmd整了半天不成功,原来是hitbox太小了
				//boomPlane = &j->Plane;
				if (q) {
					q->next_Bullet = p->next_Bullet;
				}
				else {
					Magazine = p->next_Bullet;
				}
				if (k) {
					k->next_Plane = j->next_Plane;
				}
				else {
					Planegroup = j->next_Plane;
				}
				/*printf("bullet: x1 = %d,y1 = %d,x2 = %d,y2 = %d\t", p->Bullet.x1, p->Bullet.y1, p->Bullet.x2, p->Bullet.y2);
				printf("plane: x1 = %d,y1 = %d,x2 = %d,y2 = %d\n", j->Plane.x1, j->Plane.y1, j->Plane.x2, j->Plane.y2);*/
				//printf(" 1 ");
				Creat_boom(j);
				free(p);
				free(j);
				
				//printf(" *\n");
				turn = 1;
				break;
			}
		}
		if (turn) {
			//printf(" & ");
			return 1;
		}
	}
	//printf(" 0 ");
	return 0;
}
//-----------------------------------------------------------------------------MODEL-----------------------------------------------------------------------------//

//-----------------------------------------------------------------------------CTRL-----------------------------------------------------------------------------//
void keyListener(int key, int event) {
	switch (key)
	{
	case 'A':    //左移炮塔
		Turret.x1 -= tStep_x; Turret.x2 -= tStep_x;           //同时移动炮塔和炮管
		Pipe.x1 -= tStep_x; Pipe.x2 -= tStep_x;
		Pipe.x3 -= tStep_x; Pipe.x4 -= tStep_x;
		temp_Pipe.x1 -= tStep_x; temp_Pipe.x2 -= tStep_x;     //将位移后坐标赋值给上一轮的temp_Pipe;
		temp_Pipe.x3 -= tStep_x; temp_Pipe.x4 -= tStep_x;
		Creat_Turret();
		Creat_All();
		break;
	case 'D':    //右移炮塔
		Turret.x1 += tStep_x; Turret.x2 += tStep_x;
		Pipe.x1 += tStep_x; Pipe.x2 += tStep_x;
		Pipe.x3 += tStep_x; Pipe.x4 += tStep_x;
		temp_Pipe.x1 += tStep_x; temp_Pipe.x2 += tStep_x;
		temp_Pipe.x3 += tStep_x; temp_Pipe.x4 += tStep_x;
		Creat_Turret();
		Creat_All();
		break;
	case 'Q':    //左倾炮管
		Creat_Pipe(key, event);
		Creat_All();
		break;
	case 'E':    //右倾炮管
		Creat_Pipe(key, event);
		Creat_All();
		break;
	case ' ':    //加载子弹,并且发射
	{
		if (event == 1) {
			load_Bullet();    //加载子弹
			load_Magazine();  //装填子弹
			Creat_All();
			break;
		}
	}
	}
}
void timerListener(int id) {
	delete_Plane();
	delete_Bullet();
	if (id == 3) {
		test_Crash();          //检测碰撞
	}
	if (id == 1) {             //控制子弹
			Shot_Bullet();
			Creat_All();
	}
	if (id == 2) {             //控制飞机
		cnt_plane++;
		if (cnt_plane % 12 == 0) {         //定时产生飞机
			load_Plane();
			load_Planegroup();
		}
		Creat_Plane();
		Creat_All();
	}
	Creat_All();
}
//-----------------------------------------------------------------------------CTRL-----------------------------------------------------------------------------//

下面是文件

链接: https://pan.baidu.com/s/1BshCK-Qyl6gEzpbhFtNZVw 提取码: 5fti 复制这段内容后打开百度网盘手机App,操作更方便哦

本来还有个爆炸效果的链表,但我实在是不想写了

做完后我深深意识到自己有多么菜了......

不过说到底这也就是图一乐,做做玩玩的。

最关键的是在最终搞定了这个复杂又重复的程序后,我意识到了规范性,模块化,数据结构有多么重要。

继续学习去咯

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值