
設計思路:
控制台模式
初始化:
建立畫面,初始化數據
游戲過程:
1.獲取操作
2.修改數據
3.更新畫面
結束:
關閉畫面,delete動態分配數據
4.29日
創建游戲背景,實現飛機移動操作,實現子彈飛行
4.30日
實現游戲數據管理,飛機擊落動畫,隨機出現敵機
代碼:
見最終版
5.1日
感覺類的編寫處理不好,導致有很多重復的代碼。決定重構一下。
編寫了 FlyingObject Plane Bullet類
實現了hero移動 發射子彈的操作。實現了所有Hero子彈的移動
設計思路(修改版):
1.使用類進行數據的管理和封裝
FlyingObject
—Plane(敵機)
—Hero(玩家飛機)
—Bullet(玩家子彈)
SEM(friend Hero,Bullet,Plane) : 屏幕特效展示(墜毀動畫,激光)
2.使用控制台完成指令交互
5.2日
實現了隨機間隔出現敵機,敵機的飛行
6.1 日
基本完成第一關的實現,個人感覺重復代碼較少。
FlyingObject類:
#pragma once #ifndef FLYINGOBJECT_H #define FLYINGOBJECT_H #include<easyx.h> #include<graphics.h> #include<queue> #include<vector> #include<time.h> #include<list> using namespace std; double direction[6][2] = { { 0,-1 },{ 0,1 } ,{ -1,0 },{ 1,0 },{0.5,0.5},{-0.5,0.5} };//上下左右 struct pos { double x, y; }; class FlyingObject { public: FlyingObject() = default; FlyingObject(double x, double y) { p.x = x; p.y = y; speed = 1; Setspeed(1); Setdir(1); } FlyingObject(pos p) { FlyingObject(p.x, p.y); } pos Getpos() { return p; } //virtual void Add() const = 0; double Getspeed() { return speed; } void Setspeed(double _s) { speed = _s; } void Setpos(double x, double y) { p.x = x; p.y = y; } int Getdir() { return dir; } void Setdir(int _d) { dir = _d; } virtual void Move(int) { p.x += direction[dir][0] * speed; p.y += direction[dir][1] * speed; if (p.x >= 550) p.x = 0; else if (p.x < 0) p.x = 510; if (p.y < 0) p.y = 765; else if (p.y > 750) p.y = 0; } void Draw() { putimage(p.x, p.y, &img); } IMAGE img; bool operator==(const FlyingObject& t) { if (((int)t.p.x == (int)p.x) && ((int)t.p.y == (int)p.y)) return true; return false; } private: pos p; double speed; int dir; }; #endif
Plane 類
這個類表示廣義敵機(與自己操控的飛機相撞會導致游戲結束的飛機),為了便於管理把敵機發射的子彈也歸類於敵機
#pragma once #ifndef PLANE_H #define PLANE_H #include"Bullet.h" using namespace std; class SEM; class Plane : public FlyingObject { public: friend SEM; friend bool Check(); friend void MoveallPlane(int dir); friend void DrawallPlane(); friend class Bullet; using FlyingObject::FlyingObject; void Add() { Plane::L.insert(L.begin(), *this); } virtual void Move(int) override { pos p = Getpos(); int dir = Getdir(); double speed = Getspeed(); p.x += direction[dir][0] * speed; p.y += direction[dir][1] * speed; if (p.x >= 550 || p.x < 0 || p.y < 0 || p.y > 750) { } else Setpos(p.x, p.y); } virtual void shoot(); private: static list<Plane> L; }; list<Plane> Plane::L; void Plane::shoot() { pos tmp = Plane::Getpos(); Bullet b(tmp.x + 15, tmp.y); loadimage(&b.img, _T("D:\\bullet1.ico")); b.Bullet::Add(); b.Draw(); } class Hero :public Plane { public: Hero(double _x, double _y) { Setpos(_x, _y); Setspeed(1); loadimage(&img, _T("D:\\hero1.ico")); } void Shootlaser()//發射激光 { } virtual void Move(int dir) override { //int dir = Getdir(); pos p = Getpos(); double speed = Getspeed(); p.x += direction[dir][0] * speed; p.y += direction[dir][1] * speed; if (p.x >= 550) p.x = 0; else if (p.x < 0) p.x = 510; if (p.y < 0) p.y = 765; else if (p.y > 750) p.y = 0; Setpos(p.x, p.y); } private: }; void MoveallPlane(int dir); class Boss :public FlyingObject { friend class Plane; public: Boss(double x,double y) { Setpos(x, y); Setspeed(0.0); loadimage(&img, __T("D:\\Boss.jpg")); } void Shoot() { Plane P(Getpos().x,Getpos().y); loadimage(&P.img, _T("D:\\Bullet3.ico")); P.Setspeed(2); P.Setdir(rand() % 2 + 4); P.Add(); } }; #endif
Bullet類 :
這個類管理玩家自己發射的子彈(與敵人飛機相撞后會導致敵機墜毀的飛行物)
#pragma once #ifndef BULLET_H #define BULLET_H #include"FlyingObject.h" using namespace std; class Bullet : public FlyingObject { public: friend bool Check(); friend void MoveallBullet(int dir); Bullet() = default; Bullet(double x, double y) { Setpos(x, y); Setspeed(1); Setdir(0); } Bullet(pos p) { Bullet(p.x, p.y); } void Add() { this->L.insert(L.begin(), *this); } void DrawAll() { for (auto it = Bullet::L.begin(); it != Bullet::L.end(); it++) { it->Draw(); } } private: static list<Bullet> L; }; list<Bullet> Bullet::L; void Moveall(int dir); #endif
為了便於管理飛機墜毀,激光特效(由於發射子彈是基於FlyingObject類,而激光不屬於飛行物品,所以需要特殊管理)
加入SEM類(special effect manager)
#pragma once #ifndef SEM_H #define SEM_H #include"Plane.h" struct node { double x, y; time_t t; }; class SEM { public: friend class Hero; friend bool Check(); void Drawlaser(Hero &h) { putimage(h.Getpos().x+4, h.Getpos().y-575, &Laser); } void Show(Hero &h) { Gettime(); if (Getflag()) { if (Nowt - Lasertime > 1) SetLaserflag(false); else { Drawlaser(h); } } for (auto it = Crash.begin(); it != Crash.end(); ) { if (it->t <= Nowt) { it = Crash.erase(it); } else it++; } for (auto it = Crash.begin(); it != Crash.end(); it++) { putimage(it->x, it->y, &Crasheffect); } } void Add(double _x, double _y) { node tmp; tmp.x = _x, tmp.y = _y; tmp.t = time(NULL)+1; Crash.push_back(tmp); } void Init() { Begt = time(NULL); Nowt = time(NULL); loadimage(&Crasheffect, _T("D:\\ashes.ico")); loadimage(&Laser, _T("D:\\Laser.bmp")); } IMAGE Crasheffect,Laser; time_t Gettime()//獲得游戲開始了多長時間 { Nowt = time(NULL); return Nowt-Begt; } bool Getflag() { return Laserflag; } void SetLaserflag(bool f) { Laserflag = f; } void SetLasertime() { Lasertime = time(NULL); } private: time_t Begt; time_t Nowt; time_t Lasertime; vector<node> Crash; bool Laserflag; }; #endif
main
#include<iostream> #include<list> #include<time.h> #include<easyx.h> #include<graphics.h> #include"stdio.h" #include"math.h" #include "dos.h" #include<windows.h> #include<mmsystem.h> #include<cstdlib> #include"FlyingObject.h" #include"Plane.h" #include"Bullet.h" #include"SEM.h" #define KEY_DOWN(vk_c) (GetAsyncKeyState(vk_c)&0x8000) using namespace std; Hero hero(230, 700); IMAGE background, ash,Enemy[10]; SEM S; Boss boss(157, 0); void MoveallBullet(int dir) { for (auto it = Bullet::L.begin(); it != Bullet::L.end();) { it->Move(dir); if (it->Getpos().y <= 0) it = Bullet::L.erase(it); else it++; } } bool Check() { int d = 30; for (auto it = Plane::L.begin(); it != Plane::L.end(); it++) { auto tbullet = it->Getpos(); auto tpos = hero.Getpos(); if ((tbullet.x - tpos.x<d&&tbullet.x - tpos.x>-d) && (tbullet.y - tpos.y<d&&tbullet.y - tpos.y>-d)) { return false; } } if (S.Getflag()) { for (auto it = Plane::L.begin(); it != Plane::L.end(); ) { pos tp = it->Getpos(), hp = hero.Getpos(); if (abs(tp.x - hp.x) < 20) { S.Add(tp.x, tp.y); it = Plane::L.erase(it); } else it++; } } for (auto it = Bullet::L.begin(); it != Bullet::L.end();) { auto tbullet = it->Getpos(); bool f = false; for (auto k = Plane::L.begin(); k != Plane::L.end();) { auto tpos = k->Getpos(); tpos.x += 24; tpos.y += 24; if ((tbullet.x - tpos.x<d&&tbullet.x - tpos.x>-d) && (tbullet.y - tpos.y<d&&tbullet.y - tpos.y>-d)) { f = true; S.Add(tpos.x, tpos.y); k = Plane::L.erase(k); break; } else k++; } if (!f) it++; else it = Bullet::L.erase(it); } return true; } void DrawallPlane() { for (auto it = Plane::L.begin(); it != Plane::L.end(); it++) { it->Draw(); } } void MoveallPlane(int dir) { for (auto it = Plane::L.begin(); it != Plane::L.end();) { it->Move(dir); if (it->Getpos().y >=768) it = Plane::L.erase(it); else it++; } } void init()//初始化窗口 { S.Init(); loadimage(&Enemy[0], _T("D:\\plane1.ico")); loadimage(&Enemy[1], _T("D:\\plane2.ico")); loadimage(&Enemy[2], _T("D:\\plane3.ico")); loadimage(&Enemy[3], _T("D:\\plane4.ico")); srand((unsigned)time(NULL)); initgraph(512, 768); loadimage(&background, _T("D:\\background.jpg")); loadimage(&ash, _T("D:\\ashes.ico")); putimage(0, 0, &background); BeginBatchDraw(); } void Show()//更新畫面 { putimage(0, 0, &background); hero.Draw(); boss.Draw(); Bullet tmp; tmp.DrawAll(); DrawallPlane(); S.Show(hero); FlushBatchDraw(); } void Key_scan()//掃描鍵盤 { if (KEY_DOWN(VK_UP)) { hero.Move(0); } else if (KEY_DOWN(VK_LEFT)) { hero.Move(2); } else if (KEY_DOWN(VK_RIGHT)) { hero.Move(3); } else if (KEY_DOWN(VK_DOWN)) { hero.Move(1); } else if (KEY_DOWN(VK_RETURN) || KEY_DOWN(VK_SPACE)) { while (KEY_DOWN(VK_RETURN) || KEY_DOWN(VK_SPACE)) { } hero.shoot(); } else if (KEY_DOWN(VK_SHIFT)) { S.SetLaserflag(true); S.SetLasertime(); hero.Shootlaser(); } } bool Update()//更新游戲數據 { MoveallPlane(1); MoveallBullet(0); if (!Check()) return false; if (rand() % 1000 == 0) { Plane tmp(rand() % 512, 0); tmp.img = Enemy[rand() % 4]; tmp.Setspeed(0.2); tmp.Add(); } if (rand() % 1973 == 0) { boss.Shoot(); } return true; } void Gameover() { } int main() { init(); while (1) { Show(); Key_scan(); if (!Update()) { closegraph(); printf("Game Over\n"); break; } } }
