目录
引言
最近刚学了一点easyx库的知识,写了一个飞机大战的小游戏
WASD键控制上下左右,IJKL控制子弹从上下左右方向发射
敌机会从屏幕左右边缘随机出现,并会发射不同轨迹的子弹
同时也有敌机坠毁或玩家被攻击的动画和背景
下面是游戏截屏:
游戏代码
下面是游戏代码(需提前下载easyx库)
#include<graphics.h>
#include<time.h>
#include<conio.h>
#include<stdlib.h>
#include<stdio.h>
int v = 4, enemy_v = 3, enemy_bullet_v = 4;
int bullet_count = 0, enemy_count = 0, enemy_bullet_count = 0,damage_hero_count=0;
unsigned long gametime = 0, bullettime = 0;
short bullet_frequency = 10, enenmy_frequency = 20, enenmy_bullet_frequency = 100;
int HP = 9;
int BULLETLEFT = 450;
int SCORE = 0;
#define LENTH 750
#define WIDTH 500
#define MAXBULLET 80
#define MAXSTAR 60
#define MAXENEMY 50
#define MAXDAMAGE 50
#define MAXENEMY_BULLET 80
#define hero_size 10
#define enemy_size 18
#define bullet_size 3
#define enemy_bullet_size 7
#define damage_size 20
int x = LENTH / 2, y = WIDTH / 2;
int absolute_value(int a, int b)
{
int c;
if (a > b)
{
c = a - b;
}
else
{
c = b - a;
}
return c;
}
struct STAR
{
double x;
int y;
double step;
int color;
};
STAR star[MAXSTAR];
void initstar(int i)
{
star[i].x = 0;
star[i].y = rand() % WIDTH;
star[i].step = (rand() % 5000) / 1000.0 + 1;
star[i].color = (int)(star[i].step * 255 / 6.0 + 0.5);
star[i].color = RGB(star[i].color, star[i].color, star[i].color);
}
void initallstar()
{
for (int i = 0; i < MAXSTAR; i++)
{
initstar(i);
star[i].x = rand() % LENTH;
}
}
void MoveStar(int i)
{
fillcircle((int)star[i].x, star[i].y, 1);
star[i].x += star[i].step;
if (star[i].x > LENTH)
{
initstar(i);
}
setfillcolor(star[i].color);
fillcircle((int)star[i].x, star[i].y, 1);
}
struct BULLET
{
int po_x;
int po_y;
short direction;
};
struct BULLET bullet[MAXBULLET];
void initbullet(int m)
{
bullet[m].po_x = 0;
bullet[m].po_y = 0;
bullet[m].direction = 5;
}
void initallbullet()
{
for (int i = 0; i < MAXBULLET; i++)
{
initbullet(i);
}
}
struct ENEMY
{
int enemy_x;
int enemy_y;
short direction;
};
struct ENEMY enemy[MAXENEMY];
void initenemy(int n)
{
enemy[n].enemy_x = enemy_size;
enemy[n].enemy_y = 0;
enemy[n].direction = 2;
}
void initallenemy()
{
for (int i = 0; i < MAXENEMY; i++)
{
initenemy(i);
}
}
void create_enemy()
{
if (gametime % enenmy_frequency == 0)
{
enemy_count = enemy_count % MAXENEMY;
enemy[enemy_count].enemy_y = enemy_size + rand() % (WIDTH - 2 * enemy_size);
enemy[enemy_count].direction = rand() % 2;
if (enemy[enemy_count].direction == 1)
{
enemy[enemy_count].enemy_x = LENTH - enemy_size;
}
enemy_count = enemy_count + 1;
}
}
struct ENEMY_BULLET
{
int posi_x;
int posi_y;
int direction;
};
struct ENEMY_BULLET enemy_bullet[MAXENEMY_BULLET];
void init_enemy_bullet(int mn)
{
enemy_bullet[mn].posi_x = 0;
enemy_bullet[mn].posi_y = 0;
enemy_bullet[mn].direction = 2;
}
void init_all_enemy_bullet()
{
for (int i = 0; i < MAXENEMY_BULLET; i++)
{
init_enemy_bullet(i);
}
}
struct DAMAGE
{
int damage_x;
int damage_y;
int damage_r;
bool damage_test;
};
struct DAMAGE damage[MAXDAMAGE];
void initdamage(int da)
{
damage[da].damage_test = 0;
damage[da].damage_r = 0;
damage[da].damage_x = 0;
damage[da].damage_y = 0;
}
void init_all_damage()
{
for (int i = 0; i < MAXDAMAGE; i++)
{
initdamage(i);
}
}
void create_damage(int op)
{
damage[op].damage_x = enemy[op].enemy_x;
damage[op].damage_y = enemy[op].enemy_y;
damage[op].damage_test = 1;
damage[op].damage_r = 5;
}
struct DAMAGE_HERO
{
int damage_x;
int damage_y;
int damage_r;
bool damage_test;
};
struct DAMAGE_HERO damage_hero[10];
void create_hero_damage()
{
damage_hero_count = damage_hero_count % 10;
damage_hero[damage_hero_count].damage_x = x;
damage_hero[damage_hero_count].damage_y = y;
damage_hero[damage_hero_count].damage_test = 1;
damage_hero[damage_hero_count].damage_r = 10;
damage_hero_count++;
}
void init_damage_hero(int i)
{
damage_hero[i].damage_r = 0;
damage_hero[i].damage_test = 0;
damage_hero[i].damage_x = 0;
damage_hero[i].damage_y = 0;
}
void init_all_damage_hero()
{
for (int i = 0; i < 10; i++)
{
init_damage_hero(i);
}
}
void create_enemy_bullet()
{
if (gametime % enenmy_bullet_frequency == 0)
{
for (int i = 0; i < MAXENEMY; i++)
{
if (enemy[i].direction != 2)
{
enemy_bullet_count = enemy_bullet_count % MAXENEMY_BULLET;
if (enemy[i].direction == 1 && enemy[i].enemy_x < LENTH && enemy[i].enemy_x>0)
{
enemy_bullet[enemy_bullet_count].posi_x = enemy[i].enemy_x;
enemy_bullet[enemy_bullet_count].posi_y = enemy[i].enemy_y;
enemy_bullet[enemy_bullet_count].direction = 0;
enemy_bullet_count = enemy_bullet_count + 1;
}
if (enemy[i].direction == 0 && enemy[i].enemy_x < LENTH && enemy[i].enemy_x>0)
{
enemy_bullet[enemy_bullet_count].posi_x = enemy[i].enemy_x;
enemy_bullet[enemy_bullet_count].posi_y = enemy[i].enemy_y;
enemy_bullet[enemy_bullet_count].direction = 1;
enemy_bullet_count = enemy_bullet_count + 1;
}
}
}
}
}
void keyboard()
{
if (GetAsyncKeyState('W'))
{
y = y - v;
}
if (GetAsyncKeyState('S'))
{
y = y + v;
}
if (GetAsyncKeyState('A'))
{
x = x - v;
}
if (GetAsyncKeyState('D'))
{
x = x + v;
}
if (x < 0)
{
x = 0;
}
if (x > LENTH)
{
x = LENTH;
}
if (y < 0)
{
y = 0;
}
if (y > WIDTH)
{
y = WIDTH;
}
if (BULLETLEFT > 0)
{
if (GetAsyncKeyState('I'))
{
if ((gametime - bullettime) % bullet_frequency == 0)
{
bullettime = gametime;
bullet_count = bullet_count % MAXBULLET;
bullet[bullet_count].po_x = x;
bullet[bullet_count].po_y = y - 3;
bullet[bullet_count].direction = 1;
bullet_count = bullet_count + 1;
BULLETLEFT = BULLETLEFT - 1;
}
}
if (GetAsyncKeyState('K'))
{
if ((gametime - bullettime) % bullet_frequency == 0)
{
bullettime = gametime;
bullet_count = bullet_count % MAXBULLET;
bullet[bullet_count].po_x = x;
bullet[bullet_count].po_y = y + 3;
bullet[bullet_count].direction = 2;
bullet_count = bullet_count + 1;
BULLETLEFT = BULLETLEFT - 1;
}
}
if (GetAsyncKeyState('J'))
{
if ((gametime - bullettime) % bullet_frequency == 0)
{
bullettime = gametime;
bullet_count = bullet_count % MAXBULLET;
bullet[bullet_count].po_x = x - 3;
bullet[bullet_count].po_y = y;
bullet[bullet_count].direction = 3;
bullet_count = bullet_count + 1;
BULLETLEFT = BULLETLEFT - 1;
}
}
if (GetAsyncKeyState('L'))
{
if ((gametime - bullettime) % bullet_frequency == 0)
{
bullettime = gametime;
bullet_count = bullet_count % MAXBULLET;
bullet[bullet_count].po_x = x + 3;
bullet[bullet_count].po_y = y;
bullet[bullet_count].direction = 4;
bullet_count = bullet_count + 1;
BULLETLEFT = BULLETLEFT - 1;
}
}
}
}
void drawhero()
{
setfillcolor(RED);
solidcircle(x, y, hero_size);
POINT pts_1[] = { {x + 3 * hero_size / 2,y},{x + 3 * hero_size,y + hero_size / 2},{x + 5 * hero_size,y},{x + 3 * hero_size,y - hero_size / 2} };
solidpolygon(pts_1, 4);
POINT pts_2[] = { {x - 3 * hero_size / 2,y},{x - 3 * hero_size,y + hero_size / 2},{x - 5 * hero_size,y},{x - 3 * hero_size,y - hero_size / 2} };
solidpolygon(pts_2, 4);
POINT pts_3[] = { {x,y + 3 * hero_size / 2},{x + hero_size / 2,y + 3 * hero_size},{x,y + 5 * hero_size},{x - hero_size / 2,y + 3 * hero_size} };
solidpolygon(pts_3, 4);
POINT pts_4[] = { {x,y - 3 * hero_size / 2},{x + hero_size / 2,y - 3 * hero_size},{x,y - 5 * hero_size},{x - hero_size / 2,y - 3 * hero_size} };
solidpolygon(pts_4, 4);
}
void drawbullet()
{
for (int i = 0; i < MAXBULLET; i++)
{
if (bullet[i].direction < 5)
{
setfillcolor(WHITE);
if (bullet[i].direction == 3 || bullet[i].direction == 4)
{
solidroundrect(bullet[i].po_x - 2 * bullet_size, bullet[i].po_y + bullet_size, bullet[i].po_x + 2 * bullet_size, bullet[i].po_y - bullet_size, 2, 2);
}
if (bullet[i].direction == 1 || bullet[i].direction == 2)
{
solidroundrect(bullet[i].po_x - bullet_size, bullet[i].po_y + 2 * bullet_size, bullet[i].po_x + bullet_size, bullet[i].po_y - 2 * bullet_size, 2, 2);
}
if (bullet[i].direction == 1)
{
bullet[i].po_y = bullet[i].po_y - 8;
}
if (bullet[i].direction == 2)
{
bullet[i].po_y = bullet[i].po_y + 8;
}
if (bullet[i].direction == 3)
{
bullet[i].po_x = bullet[i].po_x - 8;
}
if (bullet[i].direction == 4)
{
bullet[i].po_x = bullet[i].po_x + 8;
}
if (bullet[i].po_x < 0 || bullet[i].po_x > LENTH || bullet[i].po_y < 0 || bullet[i].po_y > WIDTH)
{
initbullet(i);
}
}
}
}
void drawstar()
{
for (int i = 0; i < MAXSTAR; i++)
{
MoveStar(i);
}
}
void drawenemy()
{
for (int i = 0; i < MAXENEMY; i++)
{
if (enemy[i].direction != 2)
{
setfillcolor(YELLOW);
solidellipse(enemy[i].enemy_x - enemy_size, enemy[i].enemy_y - enemy_size / 2, enemy[i].enemy_x + enemy_size, enemy[i].enemy_y + enemy_size / 2);
solidrectangle(enemy[i].enemy_x - enemy_size / 3, enemy[i].enemy_y - enemy_size, enemy[i].enemy_x + enemy_size / 3, enemy[i].enemy_y + enemy_size);
if (enemy[i].direction == 0)
{
enemy[i].enemy_x = enemy[i].enemy_x + enemy_v;
}
if (enemy[i].direction == 1)
{
enemy[i].enemy_x = enemy[i].enemy_x - enemy_v;
}
if (enemy[i].enemy_x < 0 || enemy[i].enemy_x > LENTH || enemy[i].enemy_y < 0 || enemy[i].enemy_y > WIDTH)
{
initenemy(i);
}
}
}
}
void draw_enemy_bullet()
{
for (int i = 0; i < MAXENEMY_BULLET; i++)
{
if (enemy_bullet[i].direction != 2)
{
setfillcolor(BLUE);
solidcircle(enemy_bullet[i].posi_x, enemy_bullet[i].posi_y, enemy_bullet_size);
if (enemy_bullet[i].direction == 0)
{
enemy_bullet[i].posi_x = enemy_bullet[i].posi_x + enemy_bullet_v;
enemy_bullet[i].posi_y = enemy_bullet[i].posi_y + enemy_bullet_v;
}
if (enemy_bullet[i].direction == 1)
{
enemy_bullet[i].posi_x = enemy_bullet[i].posi_x - enemy_bullet_v;
}
if (enemy_bullet[i].posi_x < 0 || enemy_bullet[i].posi_x > LENTH || enemy_bullet[i].posi_y < 0 || enemy_bullet[i].posi_y > WIDTH)
{
init_enemy_bullet(i);
}
}
}
}
void drawhp_and_bullet()
{
settextcolor(RGB(111, 222, 147));
settextstyle(20, 0, _T("Courier"));
outtextxy(10, 10, _T("Your Hp is:"));
char str_hp[10];
sprintf_s(str_hp, "%d", HP);
outtextxy(150, 10, *str_hp);
if (BULLETLEFT > 450)
{
BULLETLEFT = 450;
}
outtextxy(10, 30, _T("Your Bullet is:"));
char str_bulletleft[10];
sprintf_s(str_bulletleft, "%d", BULLETLEFT / 50);
outtextxy(190, 30, *str_bulletleft);
char str_score[10];
sprintf_s(str_score, "%d", SCORE / 10);
outtextxy(10, 50, _T("Your Score is:"));
outtextxy(180, 50, *str_score);
}
void drawdamage()
{
for (int k = 0; k < MAXDAMAGE; k++)
{
if (damage[k].damage_test == 1)
{
if (damage[k].damage_r < damage_size)
{
setfillcolor(WHITE);
fillcircle(damage[k].damage_x, damage[k].damage_y, damage[k].damage_r);
damage[k].damage_r++;
}
if (damage[k].damage_r == damage_size)
{
initdamage(k);
}
}
}
}
void draw_hero_damage()
{
for (int i = 0; i < 10; i++)
{
if (damage_hero[i].damage_test == 1)
{
if (damage_hero[i].damage_r < 30)
{
setfillcolor(RGB(111, 222, 147));
fillcircle(damage_hero[i].damage_x, damage_hero[i].damage_y, damage_hero[i].damage_r);
damage_hero[i].damage_r++;
}
if (damage_hero[i].damage_r == 30)
{
init_damage_hero(i);
}
}
}
}
void draw()
{
drawhero();
drawbullet();
drawstar();
drawenemy();
drawdamage();
draw_hero_damage();
draw_enemy_bullet();
drawhp_and_bullet();
}
void collide()
{
int direction_x, direction_y;
for (int i = 0; i < MAXENEMY_BULLET; i++)
{
direction_x = absolute_value(enemy_bullet[i].posi_x, x);
direction_y = absolute_value(enemy_bullet[i].posi_y, y);
if (direction_x < enemy_bullet_size + hero_size / 2 && direction_y < 2 * enemy_bullet_size + hero_size / 2)
{
init_enemy_bullet(i);
HP = HP - 1;
create_hero_damage();
}
}
for (int i = 0; i < MAXENEMY; i++)
{
if (enemy[i].direction != 2)
{
direction_x = absolute_value(enemy[i].enemy_x, x);
direction_y = absolute_value(enemy[i].enemy_y, y);
if (direction_x < enemy_size + hero_size / 2 && direction_y < 2 * enemy_size + hero_size / 2)
{
initenemy(i);
HP = HP - 1;
create_hero_damage();
}
for (int j = 0; j < MAXBULLET; j++)
{
if (bullet[j].direction < 5)
{
direction_x = absolute_value(enemy[i].enemy_x, bullet[j].po_x);
direction_y = absolute_value(enemy[i].enemy_y, bullet[j].po_y);
if (direction_x < enemy_size + bullet_size / 2 && direction_y < enemy_size + bullet_size / 2)
{
create_damage(i);
initenemy(i);
initbullet(j);
BULLETLEFT = BULLETLEFT + 5;
SCORE = SCORE + 1;
}
}
}
}
}
}
void init_all_things()
{
initgraph(LENTH, WIDTH);
setbkcolor(BLACK);
initallstar();
initallbullet();
initallenemy();
init_all_enemy_bullet();
init_all_damage();
init_all_damage_hero();
}
int main()
{
init_all_things();
while (HP > 0)
{
Sleep(5);
gametime++;
BeginBatchDraw();
cleardevice();
create_enemy();
create_enemy_bullet();
keyboard();
collide();
draw();
FlushBatchDraw();
if (GetAsyncKeyState('M'))
{
break;
}
if (GetAsyncKeyState('N'))
{
Sleep(500);
while (!GetAsyncKeyState('N'))
{
Sleep(500);
}
}
if (gametime > 4294967290)
{
break;
}
}
closegraph();
return 0;
}
基本思路
每5ms刷新一次屏幕,用draw函数绘制英雄,英雄子弹,敌机,敌机子弹,和背景星星,同时用collide函数计算子弹和敌机之间距离,如果过近则销毁并绘制爆炸图像。
类型 | 数组 |
---|---|
背景移动的星星 | star[ ] |
爆炸画面 | damage[ ] |
英雄子弹 | bullet[ ] |
敌机 | enemy[ ] |
敌机子弹 | enemy_bullet[ ] |
监视键盘 | GetAsyncKeyState函数 |
绘制图像 | solidcircle,solidrectangle函数(easyx有详细介绍) |
创建/关闭窗口 | initgraph,closegraph函数 |
注1:easyx库只能用c++语言,不能用c语言,但本人感觉两者还是挺相似的,大多数基础的c语言代码c++也能跑
注2:如果没有BeginBatchDraw和FlushBatchDraw函数,这个屏幕会一直闪烁,影响游戏体验,因此一定要加上