上学期高级C编程的课程设计,加了一些简单的规则让它不那么大众化
游戏素材
游戏界面
源代码
game.h
#include <easyx.h>
#include <conio.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib,"Winmm.lib")
#pragma comment(lib, "MSIMG32.LIB")
#define BulletMaxNum 30
#define EnemyMaxNum 10
#define PlanetMaxNum 30
#define STAGE_WIDTH 500
#define WINDOW_WIDTH 700
#define WINDOW_HEIGHT 800
enum e_gameLevel {
LEVEL1, LEVEL2, LEVEL3
};
struct Vortex { //旋涡
POINT pos = { 0,0 }; //位置
IMAGE img; //图片
int score = 0; //得分
int bulletNums = 0; //子弹数量
int getPlanetNUM; //吞入的星球数量
int hp = 5;
int fullHp = 5;
int level = LEVEL1;
};
struct Bullet {
POINT pos = { 0,0 };
IMAGE img;
int type = 0;
int speed = 1;
bool show = false;
};
struct Enemy {
IMAGE img;
POINT pos = { 100,100 };
bool show = false;
clock_t startClock = NULL, endClock = NULL; //时钟,用来减缓移动速度
int hp = 1;
};
struct Planet {
IMAGE img;
POINT pos = { 0,0 };
bool show = false;
clock_t startClock = NULL, endClock = NULL; //减速
int hp = 1;
int type;
int level = LEVEL1;
};
void putAlphaImage(IMAGE* dstimg, int x, int y, IMAGE* srcimg, UINT transparentcolor);
void initData();
void Draw();
void drawText();
void drawVortex();
void drawBullet();
void drawEnemy();
void Input();
void Logic();
void Run();
void enemyRandomMove();
void addEnemy();
bool moveDelay(clock_t c1, clock_t c2, int delay); //移动延时
bool isBumpBullet(Bullet* bullet, Enemy* enemy); //子弹击中敌人
bool isBumpEnemy(Enemy* enemy1, Enemy* enemy2); //敌人互相碰撞
bool isBumpVortex(Enemy* enemy1, Vortex* enemy2); //玩家碰到敌人
void playBoomSound();
void addPlanet();
void drawPlanet();
void planetMoveDown();
void isEatPlanet(); //吃到行星
void stayStage();
void drawHint(); //提示
void updateLevel(int level); //提升等级
void judgeLevel();
void randomLevel(Planet*, int level); //提升等级
game.cpp
#include "game.h"
clock_t startClock, processClock;
clock_t startAddPlanetClock, endAddPlanetClock;
int directLvl = 1;
Vortex vortex;
Bullet bullets[BulletMaxNum];
Enemy enemys[EnemyMaxNum];
Planet planets[PlanetMaxNum];
IMAGE bg;
bool gameQuit = false;
int bulletNum, enemyNum;
int planetSpeed;
double enemySpeed;
int enemyMoveDealy;
int gameLevel;
bool canChangeLevel = true;
bool gameStart = true;
double addEnemySpd;
double addPlanetSpd;
void initData() {
gameLevel = LEVEL1;
planetSpeed = 1;
enemySpeed = 1;
enemyMoveDealy = 5;
addEnemySpd = 1.5;
addPlanetSpd = 0.5;
for (int i = 0; i < BulletMaxNum; i++) {
loadimage(&bullets[i].img, _T("data/bullet.png"));
}
for (int i = 0; i < EnemyMaxNum; i++) {
switch (gameLevel) {
case LEVEL1:
loadimage(&enemys[i].img, _T("data/enemy1.png"));
break;
case LEVEL2:
case LEVEL3:
loadimage(&enemys[i].img, _T("data/enemy2.png"));
break;
}
}
for (int i = 0; i < PlanetMaxNum; i++) {
Resize(&planets[i].img, 32, 32);
int type = rand() % 4;
planets[i].type = type;
switch (type) {
case 0:
loadimage(&planets[i].img, _T("data/planet_red_1.png"));
break;
case 1:
loadimage(&planets[i].img, _T("data/planet_blue_1.png"));
break;
case 2:
loadimage(&planets[i].img, _T("data/planet_gray_1.png"));
break;
case 3:
loadimage(&planets[i].img, _T("data/planet_green_1.png"));
break;
}
planets[i].type = type;
}
for (int i = 0; i < EnemyMaxNum; i++) {
enemys[i].show = false;
}
for (int i = 0; i < PlanetMaxNum; i++) {
planets[i].show = false;
}
Resize(&vortex.img, 48, 48);
bulletNum = 0;
enemyNum = 0;
gameQuit = false;
vortex.pos.x = 200;
vortex.pos.y = 600;
vortex.score = 0;
vortex.bulletNums = 0;
vortex.fullHp = 5;
vortex.hp = vortex.fullHp;
loadimage(&vortex.img, _T("data/black1.png"));
loadimage(&bg, _T("data/space.png"));
startClock = clock();
startAddPlanetClock = clock();
}
void Run() {
initData();
initgraph(WINDOW_WIDTH, WINDOW_HEIGHT);
while (!gameQuit) {
Draw();
Input();
if (gameStart) {
Logic();
}
}
closegraph();
}
void Draw() {
BeginBatchDraw();
putimage(0, 0, &bg);
drawText();
drawBullet();
drawEnemy();
drawVortex();
drawPlanet();
if (!gameStart) {
drawHint();
}
EndBatchDraw();
}
void drawHint() {
IMAGE hint;
loadimage(&hint, _T("data/hint.png"));
putimage(0, WINDOW_HEIGHT / 2 - hint.getheight() / 2, &hint);
}
void drawText() {
clearrectangle(STAGE_WIDTH, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
TCHAR t1[] = _T("鼠标控制移动");
TCHAR t2[] = _T("左键发射子弹");
TCHAR t3[] = _T("右键发射所有子弹");
TCHAR t4[] = _T("吃到星球+1");
TCHAR t5[] = _T("击中敌人+1");
TCHAR t6[] = _T("子弹打到星球+2");
TCHAR t7[] = _T("让敌人相撞+2");
TCHAR t8[] = _T("敌人消灭星球-1");
TCHAR t9[] = _T("碰到敌人hp-4");
TCHAR sScore[20];
_stprintf_s(sScore, 20, _T("当前得分:%d"), vortex.score);
TCHAR sBullet[20];
_stprintf_s(sBullet, 20, _T("子弹数量:%d"), vortex.bulletNums);
TCHAR sHp[20];
_stprintf_s(sHp, 20, _T("当前hp: %d"), vortex.hp);
settextcolor(RGB(255, 255, 255));
outtextxy(500, 20, t1);
outtextxy(500, 40, t2);
outtextxy(500, 80, t3);
outtextxy(500, 100, t4);
outtextxy(500, 120, t5);
outtextxy(500, 140, t6);
outtextxy(500, 160, t7);
outtextxy(500, 180, t8);
outtextxy(500, 200, t9);
outtextxy(500, 300, sScore);
outtextxy(500, 320, sBullet);
outtextxy(500, 360, sHp);
}
void drawVortex() {
putAlphaImage(NULL, vortex.pos.x, vortex.pos.y, &vortex.img, 0x000000);
}
void drawBullet() {
for (int i = 0; i < BulletMaxNum; i++) {
if (bullets[i].show) {
putAlphaImage(NULL, bullets[i].pos.x, bullets[i].pos.y, &bullets[i].img, 0x000000);
}
}
}
void drawEnemy() {
for (int i = 0; i < EnemyMaxNum; i++) {
if (enemys[i].show) {
putAlphaImage(NULL, enemys[i].pos.x, enemys[i].pos.y, &enemys[i].img, 0x000000);
}
}
}
void Input() {
MOUSEMSG mouse;
while (MouseHit()) {
mouse = GetMouseMsg();
switch (mouse.uMsg) {
case WM_MOUSEMOVE:
vortex.pos.x = mouse.x - vortex.img.getwidth() / 2;
vortex.pos.y = mouse.y - vortex.img.getheight() / 2;
break;
case WM_LBUTTONUP:
for (int i = 0; i < BulletMaxNum; i++) {
if (vortex.bulletNums > 0) {
if (bullets[i].show == false) {
bullets[i].show = true;
bullets[i].pos.x = vortex.pos.x + vortex.img.getwidth() / 2 - bullets[i].img.getwidth() / 2;
bullets[i].pos.y = vortex.pos.y - vortex.img.getheight() / 2 - bullets[i].img.getheight() / 2;
vortex.bulletNums--; //子弹数量减一
judgeLevel();
break;
}
}
}
if (!gameStart) {
gameStart = true;
initData();
}
break;
case WM_RBUTTONUP:
for (int i = 0; i < BulletMaxNum; i++) {
if (vortex.bulletNums > 0) {
if (bullets[i].show == false) {
bullets[i].show = true;
if (i % 2 == 0) {
bullets[i].pos.x = vortex.pos.x + vortex.img.getwidth() / 2 - bullets[i].img.getwidth() / 2 + 10 * i;
} else {
bullets[i].pos.x = vortex.pos.x + vortex.img.getwidth() / 2 - bullets[i].img.getwidth() / 2 - 10 * i;
}
bullets[i].pos.y = vortex.pos.y - vortex.img.getheight() / 2 - bullets[i].img.getheight() / 2;
vortex.bulletNums--; //子弹数量减一
judgeLevel();
}
}
}
if (!gameStart) {
gameQuit = true;
}
break;
}
}
}
void Logic() {
for (int i = 0; i < BulletMaxNum; i++) {
if (bullets[i].show) {
bullets[i].pos.y -= 0.1;
if (bullets[i].pos.y <= 0) {
bullets[i].pos = { 0,0 };
bullets[i].show = false;
}
}
}
for (int j = 0; j < EnemyMaxNum; j++) {
if (enemys[j].show) {
if (isBumpVortex(&enemys[j], &vortex)) {
vortex.hp -= 4;
}
for (int i = 0; i < BulletMaxNum; i++) {
if (bullets[i].show) {
if (isBumpBullet(&bullets[i], &enemys[j])) {
vortex.score++;
//playBoomSound();
break;
}
}
}
for (int k = 0; k < EnemyMaxNum; k++) {
if (k == j) {
break;
}
if (enemys[k].show) {
if (isBumpEnemy(&enemys[j], &enemys[k])) {
vortex.score += 2;
//playBoomSound();
break;
}
}
}
}
}
addEnemy();
addPlanet();
enemyRandomMove();
planetMoveDown();
isEatPlanet();
stayStage();
if (vortex.hp <= 0) {
gameStart = false;
}
}
void putAlphaImage(IMAGE* dstimg, int x, int y, IMAGE* srcimg, UINT transparentcolor) { //绘制透明图
HDC dstDC = GetImageHDC(dstimg);
HDC srcDC = GetImageHDC(srcimg);
int w = srcimg->getwidth();
int h = srcimg->getheight();
// 使用 Windows GDI 函数实现透明位图
TransparentBlt(dstDC, x, y, w, h, srcDC, 0, 0, w, h, transparentcolor);
}
void enemyRandomMove() {
for (int i = 0; i < EnemyMaxNum; i++) {
if (enemys[i].show) {
enemys[i].endClock = clock();
if (moveDelay(enemys[i].startClock, enemys[i].endClock, enemyMoveDealy)) {
enemys[i].startClock = clock();
POINT difPos = { enemys[i].pos.x - vortex.pos.x,enemys[i].pos.y - vortex.pos.y };
difPos.x > 0 ? enemys[i].pos.x -= enemySpeed : enemys[i].pos.x += enemySpeed;
difPos.y > 0 ? enemys[i].pos.y -= enemySpeed : enemys[i].pos.y += enemySpeed;
}
}
}
}
void addEnemy() {
for (int i = 0; i < EnemyMaxNum; i++) {
processClock = clock(); //结束增加敌人计时
if (!enemys[i].show) {
if ((processClock - startClock) / CLK_TCK >= addEnemySpd) { //1秒增加一个敌人
int x = rand() % WINDOW_WIDTH;
int y = rand() % WINDOW_HEIGHT;
POINT pos = { x,y };
enemys[i].pos = pos;
enemys[i].show = true;
startClock = clock(); //增加敌人计时
enemys[i].startClock = clock(); //敌人计时
enemys[i].endClock = clock();
}
}
}
}
bool moveDelay(clock_t c1, clock_t c2, int delay) {
if (c2 - c1 >= delay) {
return true;
}
return false;
}
bool isBumpBullet(Bullet* bullet, Enemy* enemy) {
if (bullet->pos.y < enemy->pos.y + enemy->img.getheight() &&
enemy->pos.y < bullet->pos.y + bullet->img.getheight() &&
enemy->pos.x < bullet->pos.x + bullet->img.getwidth() &&
bullet->pos.x < enemy->pos.x + enemy->img.getwidth()
) {
bullet->show = false;
bullet->pos = { -100,-100 };
enemy->show = false;
enemy->pos = { -100,-100 };
return true;
}
return false;
}
bool isBumpEnemy(Enemy* enemy1, Enemy* enemy2) {
if (enemy1->pos.y < enemy2->pos.y + enemy2->img.getheight() &&
enemy2->pos.y < enemy1->pos.y + enemy1->img.getheight() &&
enemy2->pos.x < enemy1->pos.x + enemy1->img.getwidth() &&
enemy1->pos.x < enemy2->pos.x + enemy2->img.getwidth()) {
enemy1->show = false;
enemy1->pos = { -100,-100 };
enemy2->show = false;
enemy2->pos = { -100,-100 };
return true;
}
return false;
}
bool isBumpVortex(Enemy* enemy1, Vortex* enemy2) {
if (enemy1->pos.y < enemy2->pos.y + enemy2->img.getheight() &&
enemy2->pos.y < enemy1->pos.y + enemy1->img.getheight() &&
enemy2->pos.x < enemy1->pos.x + enemy1->img.getwidth() &&
enemy1->pos.x < enemy2->pos.x + enemy2->img.getwidth()) {
enemy1->show = false;
enemy1->pos = { 0,0 };
return true;
}
return false;
}
void playBoomSound() {
mciSendString(_T("close boomMusic"), NULL, 0, NULL);
mciSendString(_T("open data/boom.mp3 alias boomMusic"), NULL, 0, NULL);
mciSendString(_T("play boomMusic"), NULL, 0, NULL);
}
void addPlanet() {
for (int i = 0; i < PlanetMaxNum; i++) {
endAddPlanetClock = clock(); //结束增加行星计时
if (!planets[i].show) {
if ((endAddPlanetClock - startAddPlanetClock) >= int(1000 * addPlanetSpd)) { //0.5秒增加一个行星
int x = rand() % 500;
POINT pos = { x,0 };
planets[i].pos = pos;
planets[i].show = true;
startAddPlanetClock = clock(); //增加行星计时
planets[i].startClock = clock(); //敌人计时
planets[i].endClock = clock();
}
}
}
}
void drawPlanet() {
for (int i = 0; i < PlanetMaxNum; i++) {
if (planets[i].show) {
putAlphaImage(NULL, planets[i].pos.x, planets[i].pos.y, &planets[i].img, 0xffffff);
}
}
}
void planetMoveDown() {
for (int i = 0; i < PlanetMaxNum; i++) {
if (planets[i].show) {
planets[i].endClock = clock();
if (moveDelay(planets[i].startClock, planets[i].endClock, enemyMoveDealy)) {
planets[i].startClock = clock();
planets[i].pos.y += planetSpeed;
if (planets[i].pos.y > 800) {
planets[i].pos = { 0,0 };
planets[i].show = false;
}
}
}
}
}
void isEatPlanet() {
for (int i = 0; i < PlanetMaxNum; i++) {
if (planets[i].show) {
if (planets[i].pos.y < vortex.pos.y + vortex.img.getheight() &&
vortex.pos.y < planets[i].pos.y + planets[i].img.getheight() &&
vortex.pos.x < planets[i].pos.x + planets[i].img.getwidth() &&
planets[i].pos.x < vortex.pos.x + vortex.img.getwidth()) {
if (planets[i].level > vortex.level) {
vortex.score -= 5;
} else {
if (planets[i].type == 3) {
if (vortex.hp < vortex.fullHp) {
vortex.hp += 2;
}
}
vortex.bulletNums++;
vortex.score++;
}
planets[i].pos = { 0,0 };
planets[i].show = false;
judgeLevel();
}
for (int j = 0; j < EnemyMaxNum; j++) {
if (enemys[j].show) {
if (planets[i].pos.y < enemys[j].pos.y + enemys[j].img.getheight() &&
enemys[j].pos.y < planets[i].pos.y + planets[i].img.getheight() &&
enemys[j].pos.x < planets[i].pos.x + planets[i].img.getwidth() &&
planets[i].pos.x < enemys[j].pos.x + enemys[j].img.getwidth()) {
planets[i].pos = { 0,0 };
planets[i].show = false;
vortex.score -= 1;
}
}
}
for (int k = 0; k < BulletMaxNum; k++) {
if (bullets[k].show) {
if (planets[i].pos.y < bullets[k].pos.y + bullets[k].img.getheight() &&
bullets[k].pos.y < planets[i].pos.y + planets[i].img.getheight() &&
bullets[k].pos.x < planets[i].pos.x + planets[i].img.getwidth() &&
planets[i].pos.x < bullets[k].pos.x + bullets[k].img.getwidth()) {
planets[i].hp -= 1;
bullets[k].show = false;
bullets[k].pos = { 0,0 };
if (planets[i].level == LEVEL3) {
Resize(&planets[i].img, 64, 64);
switch (planets[i].type) {
case 0:
loadimage(&planets[i].img, _T("data/planet_blue_2.png"));
break;
case 1:
loadimage(&planets[i].img, _T("data/planet_gray_2.png"));
break;
case 2:
loadimage(&planets[i].img, _T("data/planet_green_2.png"));
break;
case 3:
loadimage(&planets[i].img, _T("data/planet_red_2.png"));
break;
}
} else if (planets[i].level == LEVEL2) {
Resize(&planets[i].img, 32, 32);
switch (planets[i].type) {
case 0:
loadimage(&planets[i].img, _T("data/planet_blue_1.png"));
break;
case 1:
loadimage(&planets[i].img, _T("data/planet_gray_1.png"));
break;
case 2:
loadimage(&planets[i].img, _T("data/planet_green_1.png"));
break;
case 3:
loadimage(&planets[i].img, _T("data/planet_red_1.png"));
break;
}
}
if (planets[i].hp <= 0) {
planets[i].pos = { 0,0 };
planets[i].show = false;
}
vortex.score += 2;
}
}
}
}
}
}
void stayStage() {
if (vortex.pos.x > STAGE_WIDTH - vortex.img.getwidth()) {
vortex.pos.x = STAGE_WIDTH - vortex.img.getwidth();
}
if (vortex.pos.x < 0) {
vortex.pos.x = 0;
}
if (vortex.pos.y > WINDOW_HEIGHT - vortex.img.getheight()) {
vortex.pos.y = WINDOW_HEIGHT - vortex.img.getheight();
}
if (vortex.pos.y < 0) {
vortex.pos.y = 0;
}
for (int i = 0; i < PlanetMaxNum; i++) {
if (planets[i].show) {
if (planets[i].pos.y < 0) {
planets[i].pos.y = 0;
}
if (planets[i].pos.x > STAGE_WIDTH - planets[i].img.getwidth()) {
planets[i].pos.x = STAGE_WIDTH - planets[i].img.getwidth();
}
if (planets[i].pos.x < 0) {
planets[i].pos.x = 0;
}
}
}
for (int i = 0; i < EnemyMaxNum; i++) {
if (enemys[i].pos.y > WINDOW_HEIGHT - enemys[i].img.getheight()) {
enemys[i].pos.y = WINDOW_HEIGHT - enemys[i].img.getheight();
}
if (enemys[i].pos.y < 0) {
enemys[i].pos.y = 0;
}
if (enemys[i].pos.x > STAGE_WIDTH - enemys[i].img.getwidth()) {
enemys[i].pos.x = STAGE_WIDTH - enemys[i].img.getwidth();
}
if (enemys[i].pos.x < 0) {
enemys[i].pos.x = 0;
}
}
}
void updateLevel(int gameLevel) {
switch (gameLevel) {
case LEVEL1:
Resize(&vortex.img, 48, 48);
loadimage(&vortex.img, _T("data/black1.png"));
vortex.level = LEVEL1;
for (int i = 0; i < PlanetMaxNum; i++) {
if (i % 3 == 0) {
if (planets[i].show) {
} else {
randomLevel(&planets[i], gameLevel);
}
}
}
break;
case LEVEL2:
Resize(&vortex.img, 64, 64);
loadimage(&vortex.img, _T("data/black2.png"));
vortex.level = LEVEL2;
for (int i = 0; i < PlanetMaxNum; i++) {
if (i % 3 == 0) {
if (planets[i].show) {
} else {
randomLevel(&planets[i], gameLevel);
}
}
}
break;
case LEVEL3:
Resize(&vortex.img, 128, 128);
loadimage(&vortex.img, _T("data/black3.png"));
vortex.level = LEVEL3;
for (int i = 0; i < PlanetMaxNum; i++) {
if (i % 3 == 0) {
if (planets[i].show) {
} else {
randomLevel(&planets[i], gameLevel);
}
}
}
break;
}
}
void judgeLevel() {
if (vortex.bulletNums > 20) {
if (gameLevel != LEVEL3) {
gameLevel = LEVEL3;
updateLevel(gameLevel);
vortex.hp = vortex.fullHp = 20;
}
} else if (vortex.bulletNums >= 10) {
if (gameLevel != LEVEL2) {
gameLevel = LEVEL2;
updateLevel(gameLevel);
vortex.hp = vortex.fullHp = 10;
}
} else {
if (gameLevel != LEVEL1) {
gameLevel = LEVEL1;
updateLevel(gameLevel);
vortex.hp = vortex.fullHp = 5;
}
}
}
void randomLevel(Planet* planet, int level) {
int j;
planet->hp = level + 1;
switch (level) {
case LEVEL1:
Resize(&planet->img, 32, 32);
j = rand() % 4;
planet->type = j;
switch (j) {
case 0:
loadimage(&planet->img, _T("data/planet_blue_1.png"));
break;
case 1:
loadimage(&planet->img, _T("data/planet_gray_1.png"));
break;
case 2:
loadimage(&planet->img, _T("data/planet_green_1.png"));
break;
case 3:
loadimage(&planet->img, _T("data/planet_red_1.png"));
break;
}
planet->level = LEVEL1;
break;
case LEVEL2:
Resize(&planet->img, 64, 64);
j = rand() % 4;
planet->type = j;
switch (j) {
case 0:
loadimage(&planet->img, _T("data/planet_blue_2.png"));
break;
case 1:
loadimage(&planet->img, _T("data/planet_gray_2.png"));
break;
case 2:
loadimage(&planet->img, _T("data/planet_green_2.png"));
break;
case 3:
loadimage(&planet->img, _T("data/planet_red_2.png"));
break;
}
planet->level = LEVEL2;
break;
case LEVEL3:
Resize(&planet->img, 128, 128);
j = rand() % 4;
planet->type = j;
switch (j) {
case 0:
loadimage(&planet->img, _T("data/planet_blue_3.png"));
break;
case 1:
loadimage(&planet->img, _T("data/planet_gray_3.png"));
break;
case 2:
loadimage(&planet->img, _T("data/planet_green_3.png"));
break;
case 3:
loadimage(&planet->img, _T("data/planet_red_3.png"));
break;
}
planet->level = LEVEL3;
break;
}
}
main.cpp
#include "game.h"
int main() {
Run();
}