zoukankan      html  css  js  c++  java
  • 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
    ");
                break;
            }
        }
    }
  • 相关阅读:
    4-Python3从入门到实战—基础之数据类型(字符串-String)
    3-Python3从入门到实战—基础之数据类型(数字-Number)
    前端工程化—部署
    前端工程化
    PHP与MySQL设计模式:代理模式
    移动前端开发入门(一)
    PHP页面间传值的几种方法
    PHP文件上传及下载源码
    PHP文件操作
    JavaScript正则表达式
  • 原文地址:https://www.cnblogs.com/joeylee97/p/6791866.html
Copyright © 2011-2022 走看看