c++ 打飛機游戲開發日志


設計思路:
控制台模式
  初始化:
  建立畫面,初始化數據
  游戲過程:
    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;
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM