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;
        }
    }
}

 

posted @ 2017-05-01 14:29  joeylee97  阅读(3995)  评论(0编辑  收藏  举报