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[][] = { { ,- },{ , } ,{ -, },{ , },{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 = ;
Setspeed();
Setdir();
}
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][] * speed;
p.y += direction[dir][] * speed;
if (p.x >= )
p.x = ;
else if (p.x < )
p.x = ;
if (p.y < )
p.y = ;
else if (p.y > )
p.y = ;
}
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][] * speed;
p.y += direction[dir][] * speed;
if (p.x >= || p.x < || p.y < || p.y > )
{ }
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 + , 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();
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][] * speed;
p.y += direction[dir][] * speed;
if (p.x >= )
p.x = ;
else if (p.x < )
p.x = ;
if (p.y < )
p.y = ;
else if (p.y > )
p.y = ;
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();
P.Setdir(rand() % + );
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();
Setdir();
}
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+, h.Getpos().y-, &Laser);
}
void Show(Hero &h)
{
Gettime();
if (Getflag())
{
if (Nowt - Lasertime > )
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)+;
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(, );
IMAGE background, ash,Enemy[];
SEM S;
Boss boss(, );
void MoveallBullet(int dir)
{
for (auto it = Bullet::L.begin(); it != Bullet::L.end();)
{
it->Move(dir);
if (it->Getpos().y <= )
it = Bullet::L.erase(it);
else
it++;
}
}
bool Check()
{
int d = ;
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) < )
{
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 += ;
tpos.y += ;
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 >=)
it = Plane::L.erase(it);
else
it++;
}
}
void init()//初始化窗口
{
S.Init();
loadimage(&Enemy[], _T("D:\\plane1.ico"));
loadimage(&Enemy[], _T("D:\\plane2.ico"));
loadimage(&Enemy[], _T("D:\\plane3.ico"));
loadimage(&Enemy[], _T("D:\\plane4.ico"));
srand((unsigned)time(NULL));
initgraph(, );
loadimage(&background, _T("D:\\background.jpg"));
loadimage(&ash, _T("D:\\ashes.ico"));
putimage(, , &background);
BeginBatchDraw();
}
void Show()//更新画面
{
putimage(, , &background);
hero.Draw();
boss.Draw();
Bullet tmp;
tmp.DrawAll();
DrawallPlane();
S.Show(hero);
FlushBatchDraw();
}
void Key_scan()//扫描键盘
{
if (KEY_DOWN(VK_UP))
{
hero.Move();
}
else if (KEY_DOWN(VK_LEFT))
{
hero.Move();
}
else if (KEY_DOWN(VK_RIGHT))
{
hero.Move();
}
else if (KEY_DOWN(VK_DOWN))
{
hero.Move();
}
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();
MoveallBullet();
if (!Check())
return false;
if (rand() % == )
{
Plane tmp(rand() % , );
tmp.img = Enemy[rand() % ];
tmp.Setspeed(0.2);
tmp.Add();
}
if (rand() % == )
{
boss.Shoot();
}
return true;
}
void Gameover()
{ }
int main()
{
init();
while ()
{
Show();
Key_scan();
if (!Update())
{
closegraph();
printf("Game Over\n");
break;
}
}
}
c++ 打飞机游戏开发日志的更多相关文章
- [游戏开发日志]Windows下Cocos2d-x 3.14环境搭建
总介绍 我们小组使用的是cocos2d-x的游戏开发引擎,因此在所有开发工作之前,我们需要对这个引擎进行环境的搭建. 搭建过程 VS2013的下载和安装 VS只是作为一个开发环境而已,简单来说就是敲代 ...
- Unity2D RPG游戏开发日志
一.游戏构建设计 场景设计:地面的每一层用unity的TiledMap来设计,首先第一层为地面层,也就是地形的大部分区域的图块:第二层为覆盖层,如图中蓝色线圈起来的柱子的上半部分,由于玩家可以在柱子背 ...
- unity独立游戏开发日志2018/09/22
f::很头痛之前rm做的游戏在新电脑工程打不开了...只能另起炉灶... 还不知道新游戏叫什么名...暂且叫方块世界.(素材已经授权) 首先是规划下场景和素材文件夹的建立. unity常用的文件夹有: ...
- unity独立游戏开发日志2018/09/26
最近太忙,今天吃饭的时候灵感一现...想到了随机地图生成的方法,不过可能实现的比较笨...还需要优化,大佬绕过. 注释没打,最后统一解释. using System.Collections; usin ...
- pygame开发PC端微信打飞机游戏
pygame开发PC端微信打飞机游戏 一.项目简介 1. 介绍 本项目类似曾经火爆的微信打飞机游戏.游戏将使用Python语言开发,主要用到pygame的API.游戏最终将会以python源文件gam ...
- [Unity3D]Unity3D游戏开发之飞机大战项目解说
大家好,我是秦元培,欢迎大家继续关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 首先感谢大家对我博客的关注,今天我想和大家分享的是一个飞机大战的项目.这是一个比較综合的 ...
- 基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(下)
在飞机大战游戏开发中遇到的问题和解决方法: 1.在添加菜单时,我要添加一个有背景的菜单,需要在菜单pMenu中添加一个图片精灵,结果编译过了但是运行出错,如下图: 查了很多资料,调试了很长时间,整个人 ...
- 基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(中)
接<基于Cocos2d-x-1.0.1的飞机大战游戏开发实例(上)> 三.代码分析 1.界面初始化 bool PlaneWarGame::init() { bool bRet = fals ...
- Python之游戏开发-飞机大战
Python之游戏开发-飞机大战 想要代码文件,可以加我微信:nickchen121 #!/usr/bin/env python # coding: utf-8 import pygame impor ...
随机推荐
- bzoj2132: 圈地计划(无比强大的最小割)
2132: 圈地计划 题目:传送门 简要题意: 给出一个矩阵,一共n*m个点,并给出三个收益矩阵.A矩阵表示这个点建A的可取收益,B矩阵表示这个点建B的可取收益,C矩阵表示如果相邻(有且仅有一条公共边 ...
- B1230 [Usaco2008 Nov]lites 开关灯 线段树
就是线段树维护异或和.之前我线段树区间修改down都是修改当前区间,结果debug出不来,改成每次向下了. 题干: Description Farmer John尝试通过和奶牛们玩益智玩具来保持他的奶 ...
- spring boot测试
今天在springside里试了spring boot,果然很方便,内置容器,不需要配置web.xml,简单几个文件就可以实现增删改查操作,一些配置如tomcat端口之类的直接写在applicatio ...
- bzoj 1191 [ HNOI 2006 ] 超级英雄Hero —— 二分图匹配
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1191 就是二分图匹配的裸题: 注意题目要求是第一次匹配失败就退出!没仔细看题差点丢失1A. ...
- AAC头部格式,RTP打包格式
一共有2种AAC头格式,一种是StreamMuxConfig,另一种是AudioSpecificConfig 1.AudioSpecificConfig 读写header的代码参考 ffmpeg ...
- json用法
什么是JSON? JavaScript 对象表示法(JavaScript Object Notation). JSON是一种轻量级的数据交换格式,某个JSON格式的文件内部譬如可以长成这样: 1 2 ...
- 取消VS2017窗口置顶
今天打开VS2017,莫名其妙窗口置顶了,百度了一下如何取消窗口置顶,就是Ctrl+Alt+Esc组合键,就可以取消窗口置顶了,至于到底怎么会突然置顶的我也不知道emmm... /********** ...
- NoSQL概念
NoSQL是非关系型数据库,即not only sql,key/value键值对存储. 现有Nosql DB产品:Redis/MongoDB/Memcached等等. SQL Sever是关系型数据库 ...
- (转)Vue 爬坑之路(二)—— 组件之间的数据传递
Vue 的组件作用域都是孤立的,不允许在子组件的模板内直接引用父组件的数据.必须使用特定的方法才能实现组件之间的数据传递. 首先用 vue-cli 创建一个项目,其中 App.vue 是父组件,com ...
- C# Socket通讯 本机多网卡,指定网卡通讯
IPAddress ip = IPAddress.Parse("192.168.0.188"); IPAddress IPLocal = IPAddress.Parse(" ...