话不多说,我们直接进入正题吧。

这个阶段我们要完成如下功能:
1:图片的绘制
2:敌人运动轨迹的绘制
3:防御塔坑(可放置防御塔点)的绘制
4:鼠标点击事件,实现防御塔的出现

图片的绘制

首先我们在Qt中,创建一个widget工程
得到这个工程后,我们在mainwindow.h中做如下添加:

//类外
#include <QPaintEvent>//类内
protected:
void paintEvent(QPaintEvent*);

添加Qt Resource File文件

把要用到的图片都放到这个文件夹中。

然后进入mainwindow.cpp,做如下添加:

void Mainwindow::paintEvent(QPaintEvent*)
{QPainter painter(this);QString path(":/images/background1.jpg");//path是你图片的路径painter.drawPixmap(0,0,750,375,path);//drawPixmap的前四个参数代表的分别是,图片左上角的横坐标,图片左上角的纵坐标,图片的width,图片的height。我们一般把width和height,与图片的真实大小匹配起来
}

运行上述程序,就可以得到下面的结果啦!

#敌人运动轨迹的绘制
我们添加一个类wayPoint(航点)
wayPoint.h的实现:

#ifndef WAYPOINT_H
#define WAYPOINT_H#include <QPoint>
#include <QPainter>class wayPoint
{public:wayPoint(QPoint pos);void setNextWayPoint(wayPoint * nextWayPoint);//设置下一个航点wayPoint * getNextWayPoint();//得到下一个航点的指针const QPoint getPos();//得到本航点的中心点void draw(QPainter * painter) const;//绘画类函数
private:QPoint m_pos;//航点的中心点wayPoint * m_nextWayPoint;//下一个航点的指针
};
#endif // WAYPOINT_H

wayPoint.cpp中的实现:

#include "waypoint.h"#include <QPoint>
#include <QPainter>wayPoint::wayPoint(QPoint pos):m_pos(pos),m_nextWayPoint(NULL)
{}void wayPoint::setNextWayPoint(wayPoint *nextWayPoint)
{this->m_nextWayPoint=nextWayPoint;
}wayPoint * wayPoint::getNextWayPoint()
{return this->m_nextWayPoint;
}const QPoint wayPoint::getPos()
{return this->m_pos;
}void wayPoint::draw(QPainter * painter) const
{painter->save();//保存原始的绘画参数painter->setPen(Qt::green);//设置画笔的颜色painter->drawEllipse(m_pos,4,4);//画一个半径为4的圆//注意,图片的大小单位是像素painter->drawEllipse(m_pos,1,1);//半径为1的圆if(m_nextWayPoint)//如果存在下一个航点,就把这两个航点连接起来{painter->drawLine(m_pos,m_nextWayPoint->getPos());//painter内的画直线的方法}painter->restore();//还原原来的画笔设置
}

完成wayPoint类的创建后,我们在mainwindow(程序运行得到的窗口)中把这些航点画出来。
先在mainwindow.h中添加:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QPaintEvent>#include "waypoint.h"//我们一般引用系统内文件时,用<>,引用我们自己定义的文件时用""QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass wayPoint;//新增对wayPoint类的说明class MainWindow : public QMainWindow
{Q_OBJECT
public:MainWindow(QWidget *parent = nullptr);~MainWindow();void addWayPoint1();//用来添加航点的函数protected:void paintEvent(QPaintEvent*);//画家类函数private:Ui::MainWindow *ui;QList<wayPoint * > m_wayPointList;//用来储存航点的list
};
#endif // MAINWINDOW_H

mainwindow.cpp中的实现:

//增加头文件的引用
#include "waypoint.h"//函数的实现
void MainWindow::addWayPoint1()
{wayPoint * waypoint1=new wayPoint(QPoint(79,6));m_wayPointList.push_back(waypoint1);wayPoint * waypoint2=new wayPoint(QPoint(79,55));waypoint1->setNextWayPoint(waypoint2);m_wayPointList.push_back(waypoint2);wayPoint * waypoint3=new wayPoint(QPoint(407,55));waypoint2->setNextWayPoint(waypoint3);m_wayPointList.push_back(waypoint3);wayPoint * waypoint4=new wayPoint(QPoint(407,175));waypoint3->setNextWayPoint(waypoint4);m_wayPointList.push_back(waypoint4);wayPoint * waypoint5=new wayPoint(QPoint(83,175));waypoint4->setNextWayPoint(waypoint5);m_wayPointList.push_back(waypoint5);wayPoint * waypoint6=new wayPoint(QPoint(83,292));waypoint5->setNextWayPoint(waypoint6);m_wayPointList.push_back(waypoint6);wayPoint * waypoint7=new wayPoint(QPoint(473,292));waypoint6->setNextWayPoint(waypoint7);m_wayPointList.push_back(waypoint7);
}
航点的绘制要比较有耐心
游戏世界的构造是以左上角为原点的,以像素为单位
制作者需要自己不断修改,在图上找到这些航点,调整,找到航点的确切位置
下面的具体数据,是适用于我使用的地图的
如果制作者要用其他的背景地图,需要自己修改数据,找到航点

我们再到mainwindow.cpppaintEvent()方法中添加航点的绘画的实现:

foreach(const wayPoint * waypoint,m_wayPointList)waypoint->draw(&painter);

再到mainwindow.cpp中mainwindow的构造函数中,添加addWayPoint1()的调用:

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);addWayPoint1();//增加航点函数的调用
}

运行程序,我们就可以得到下面的结果啦!

可以看到,图上已经有敌人运动的轨迹了。

好啦,接下来我们进行防御塔坑的绘制。

防御塔坑的绘制

先添加 TowerPosition
TowerPosition.h中的实现:

#ifndef TOWERPOSITION_H
#define TOWERPOSITION_H#include <QSize>
#include <QPainter>
#include <QString>class TowerPosition
{public:TowerPosition(QPoint pos,QString path=(":/images/open_spot.png"));//图片的路径QPoint getCenterPos();//得到防御塔坑的中心点QPoint getPos();//得到防御塔坑的左上点bool ContainPos(QPoint pos);//判断pos点是否在防御塔坑的范围内void draw(QPainter * painter) const;bool hasTower();//判断该防御塔坑内有没有防御塔void setHasTower(bool hasTower=true);//设置是否有防御塔private:QPoint m_pos;QString m_path;bool m_hasTower;static const QSize m_fixedSize;//防御塔坑的固定大小
};
#endif // TOWERPOSITION_H

TowerPosition.cpp的实现:

#include "towerposition.h"#include <QSize>
#include <QPainter>
#include <QPixmap>const QSize TowerPosition::m_fixedSize(35,35);//设置图片的大小TowerPosition::TowerPosition(QPoint pos, QString path):m_pos(pos),m_path(path),m_hasTower(false)
{}bool TowerPosition::hasTower()
{return m_hasTower;
}void TowerPosition::setHasTower(bool hasTower)
{m_hasTower=hasTower;
}QPoint TowerPosition::getCenterPos()
{QPoint tmp;tmp.setX(m_pos.x()+m_fixedSize.width()/2);tmp.setY(m_pos.y()+m_fixedSize.height()/2);return tmp;
}QPoint TowerPosition::getPos()
{return m_pos;
}bool TowerPosition::ContainPos(QPoint pos)
{bool xInHere=pos.x()>m_pos.x() && pos.x()<m_pos.x()+m_fixedSize.width();bool yInHere=pos.y()>m_pos.y() && pos.y()<m_pos.y()+m_fixedSize.height();return xInHere && yInHere;
}void TowerPosition::draw(QPainter *painter) const
{painter->drawPixmap(m_pos.x(),m_pos.y(),m_path);
}

然后到mainwindow.h中添加下面代码

//类外
#include <towerposition.h>//类内
public:
void loadTowerPosition1();//用来加载防御塔坑的函数
private:
QList<TowerPosition > m_towerPositionList;//用来储存防御塔坑的list

mainwindow.cpp中对上面的代码进行实现:

#include"towerposition"void MainWindow::loadTowerPosition1()
{//这里和找航点是一样的,制作者需要自己不断尝试//找到比较合适的防御塔坑点QPoint pos[]={QPoint(86,98),QPoint(226,98),QPoint(439,98),QPoint(105,215),QPoint(186,215),QPoint(314,215),QPoint(105,321),QPoint(223,323),QPoint(365,319)};int len=sizeof(pos)/sizeof(pos[0]);for(int i=0;i<len;i++){m_towerPositionList.push_back(pos[i]);}
}

同时,在paintEvent()函数内添加对防御塔坑的绘画:

foreach(const TowerPosition towerposition,m_towerPositionList)towerposition.draw(&painter);

并在mainwindow的构造函数中,添加对loadTowerPosition1()方法的调用,类似addWayPoint1()的调用:

    loadTowerPosition1();

运行上述程序,我们可以得到下面的界面:
可以看到,我们已经画出来了敌人的航点和防御塔坑
下面就实现防御塔的安置吧!

鼠标点击实现防御塔的出现

我们先创建一个 Tower
tower.h中的实现:

#ifndef TOWER_H
#define TOWER_H#include <QObject>
#include <QPoint>
#include <QSize>
#include <QString>#include "mainwindow.h"class MainWindow;
class QPainter;class Tower:QObject
{Q_OBJECT
public:Tower(QPoint pos,MainWindow * game,QString path=":/images/tower2.png");~Tower();Tower();void draw(QPainter * painter)const;//画出防御塔
private:QPoint m_pos;//防御塔的中心点QString m_path;//防御塔图片的路径int m_attackRange;//攻击范围static const QSize m_fixedSize;//防御塔图片的固定大小MainWindow * m_game;//指向mainwindow的指针
};
#endif // TOWER_H

同时,tower.cpp中的方法实现:

#include "tower.h"
#include "mainwindow.h"#include <QPoint>
#include <QPainter>
#include <QString>const QSize Tower::m_fixedSize(35,35);
Tower::Tower()
{}Tower::~Tower()
{}Tower::Tower(QPoint pos,MainWindow * game,QString path):m_pos(pos),m_path(path),m_attackRange(70),//根据地图的大小,确定攻击范围m_game(game)
{}void Tower::draw(QPainter *painter) const
{painter->save();painter->setPen(Qt::green);painter->drawEllipse(m_pos,m_attackRange,m_attackRange);//画出防御塔的攻击范围painter->drawPixmap(m_pos.x()-m_fixedSize.width()/2,m_pos.y()-m_fixedSize.height()/2-10,path);//画出防御塔的图片
}

mainwindow.h中做如下添加:

//类外添加
#include <QMouseEvent>#include "tower.h"class Tower;//类内添加
protected:void mousePressEvent(QMouseEvent *);//鼠标点击类函数private:QList<Tower *> m_towerList;//用来储存防御塔的list

mainwindow.cpp中,对mousePressEvent()进行实现:

void MainWindow::mousePressEvent(QMouseEvent * event)
{QPoint pressPos=event->pos();//得到鼠标点击的位置auto it=m_towerPositionList.begin();while(it!=m_towerPositionList.end())//遍历所有的防御塔坑{if(Qt::LeftButton==event->button())//如果是鼠标左键点击{if(it->ContainPos(pressPos) && !it->hasTower())//如果鼠标点击的位置在防御塔坑的范围内,并且没有防御塔{Tower * tower=new Tower(it->getCenterPos(),this);//创建一个新的防御塔m_towerList.push_back(tower);//把这个防御塔放到储存防御塔的list中it->setHasTower(true);//设置这个防御塔坑内有防御塔了update();//更新地图break;//进行了一次操作,可以直接退出循环了}}++it;}
}

并在paintEvent()函数中,添加对防御塔的绘画:

foreach(const Tower * tower, m_towerList)tower->draw(&painter);

运行程序后,我们就可以得到下面的画面了:

可以看到,点击防御塔坑的内部后,防御塔就会出现。
这样我们第一阶段的工作就完成啦!

下面我们对这次的工作进行一次总结:
1:首先我们完成了背景地图的绘画,用到了QPainter头文件中的drawPixmap()函数,后续的一些绘画也多次用到了这个函数。
2:我们画出了敌人运动的航点,这个过程比较麻烦,需要制作者根据mainwindow上的实际情况,不断调整航点的位置
3:引入防御塔坑,为防御塔的出现做铺垫,我们后续的很多操作,主要是鼠标点击事件,都将会以TowerPosition为基础进行操作。
4:实现鼠标点击事件,完成防御塔的出现。

OK,我们下一篇文章见!

所有的源代码和图片资源,在下面的网盘内:
https://pan.baidu.com/s/1BS7tiiyCWQxgZDsm8QhMgA
提取码:9307

Qt之塔防游戏 c++(一)相关推荐

  1. Qt版本-塔防游戏实现一

    这个游戏来源于一篇较早的国外作品,不过原作是以Cocos2D为基础实现的,链接见下: http://www.raywenderlich.com/37701/how-to-make-a-tower-de ...

  2. Qt版本-塔防游戏实现二

    上篇已经为敌人的出现做好准备了,现在是时候让敌人登场了: 4.敌人初步实现 这里出去3件套(尺寸可以直接用图片大小,我用的是静态常量,习惯而已) 其中m_active表示是否可以移动,只有当其为tru ...

  3. QT 框架搭建,用最原始的方法实现简单的塔防游戏 | 原力计划

    作者 | 白家名 责编 | 王晓曼 出品 | CSDN博客 本文作者使用 QT 框架写了一个塔防游戏程序,该程序中实现了购买炮塔.炮塔升级.怪物按照设定路径移动.炮塔自动寻找范围内目标.朝目标怪物发射 ...

  4. QT实现简单的塔防游戏

    QT实现简单的塔防游戏 该程序中实现了购买炮塔.炮塔升级.怪物按照设定路径移动.炮塔自动寻找范围内目标.朝目标怪物发射炮弹.爆炸效果.怪物走到家时我方生命值减少.方便添加关卡等功能. 另附重构版本代码 ...

  5. 基于QT多关卡的塔防游戏

    基于QT多关卡的塔防游戏 基于QT多关卡的塔防游戏 参考模板 核心实现思想 运行图片 代码 基于QT多关卡的塔防游戏 多关卡多怪兽,多防御塔与多子弹类型,对于界面无美化,主要实现其功能,Boss尺寸是 ...

  6. (译)如何使用cocos2d制作一个塔防游戏:引子

    原文链接地址:http://www.iphonegametutorials.com/2011/04/11/cocos2d-game-tutorial-how-to-build-a-tower-defe ...

  7. 塔防游戏的路径寻找算法分析

    在塔防游戏中,有很多敌人都是向着同一目标前进的.在众多塔防游戏当中,有一条或几条预定好的路径.在一些塔防游戏中,比如经典的<Desktop Tower Defense>,你可以将塔放在地图 ...

  8. 用Unity开发一款塔防游戏(一):攻击方设计

    大家好.偶尔想起了这个手把手教学的.但现已长满杂草的坑,还是来挖几铲子. 这一期的游戏是最常见的类型之一--塔防. 塔防游戏相信大家并不陌生,几个主要元素如下: 1.敌方士兵 2.我方防御塔 3.我方 ...

  9. cocos2d-x游戏实例(10)-塔防游戏(修改地图图素,地图整体缩放)

    小满(bill man)个人原创,欢迎转载,转载请注明地址,小满(bill man)的专栏地址http://blog.csdn.net/bill_man 塔防游戏在目前的智能机游戏中占据很重要的部分, ...

最新文章

  1. 谷歌为什么把几十亿行代码放在一个库?
  2. 都说 WebP 厉害,究竟厉害在哪里?
  3. java 类型转换的原理
  4. iphone简单实例 (字体,弹出窗口) (实例)
  5. devops实践指南_开发DevOps的实用指南:减少八卦的步骤
  6. Android 系统预装添加第三方apk到data/app
  7. python中文叫什么-在python中,quot;~”是什么意思?
  8. 单个圆孔菲涅耳衍射的matlab模拟,矩孔和圆孔菲涅耳衍射的计算机模拟
  9. 百度Java后端实习面试
  10. 全球科学家公认的高效学习法——费曼学习法
  11. 日语N2听力常用词汇
  12. 基于浏览器内核的被动式爬虫任务下发框架
  13. Shape 文件格式解释
  14. Vue-router:二级路由跳转另一条路由下的子级
  15. 张一鸣的“成事哲学”:取势、明道、优术、践行、合众
  16. 若依前后端分离版生成代码实现仓库的增删改查
  17. SwitchResX for Mac 屏幕分辨率修改工具
  18. 大恒工业相机C#语言winform平台开发例程
  19. 用matlab info,matlab info函数 Excel的info函数
  20. 舰船交流电网绝缘监测及故障定位的研究及产品选型

热门文章

  1. Google将Linux客户端研发的主力放到中国
  2. 推荐几个清华交大学霸的公众号
  3. 独立开发变现周刊(第83期):建在Stripe上的应用,年收入70万美元
  4. buuctf-N1Book[第六章 CTF之PWN章]
  5. DL289西雅图-上海成功回国记录(2021-06-25)
  6. CRM和ERP的区别与联系
  7. js代码转换成java代码_js代码转换为java
  8. java代码转换程序_怎么把java代码转换成程序
  9. [架构之路-182]-《软考-系统分析师》-19- 系统可靠性分析与设计 - 概览
  10. 中企海外周报 | 华米在印尼发布两款智能手表;百世集团进军越南市场