這篇文章內容是參考https://blog.csdn.net/sinan1995/article/details/81671311
這篇主要是怎樣實現創建一條蛇,並讓它動起來
首先先創建項目,基類可以是mainWidget或者Widget,這裏使用的是mainWidget
採用面向對象的方式,設計一個Snake類,製作這條蛇
Snake.h
#ifndef SNAKE_H
#define SNAKE_H
#include <QObject>
#include <QList>
class Snake : public QObject
{
Q_OBJECT
public:
explicit Snake(QObject *parent = nullptr);
public:
enum Dir{Up, Down, Left, Right};
public:
int moveDir = Dir::Up;
int width=10;
int height=10;
QList<QRectF> body;
public:
//節點個數,初始頭的位置,朝向(默認爲上)
void initBody(int nodeNum=3,QPointF topLeft=QPointF(400,400),Dir dir=Dir::Up,int nodeWidth=10,int nodeHeight=10);
public:
void addNodeUp(int);
void addNodeDown(int);
void addNodeLeft(int);
void addNodeRight(int);
void moveUp(int);
void moveDown(int);
void moveRight(int);
void moveLeft(int);
void move(int,int); //沿着當前的方向移動
signals:
public slots:
};
#endif // SNAKE_H
這個Snake類也可以不用繼承Object類,普通的類也行。
首先這個類裏有一些屬性,moveDir 表示蛇正在移動的方向,它的值是自定義的一個枚舉值,分別代表上下左右。
width 和 height 分別代表蛇的每個節點的寬和高。
body 是存放每個節點的矩形位置。
Snake.cpp
#include "snake.h"
#include <QPointF>
Snake::Snake(QObject *parent) : QObject(parent)
{
}
void Snake::initBody(int nodeNum, QPointF topLeft, Snake::Dir dir, int nodeWidth, int nodeHeight)
{
width = nodeWidth;
height = nodeHeight;
moveDir = dir;
if(dir==Dir::Up){
for(int i=0;i<nodeNum;i++){ //topLeft座標 和 bottomRight座標
body.append(QRectF(topLeft+QPoint(0,i*height),topLeft+QPoint(0,i*height)+QPointF(width,height)));
}
}else if (dir==Dir::Down) {
for(int i=0;i<nodeNum;i++){
body.append(QRectF(topLeft-QPoint(0,i*height),topLeft-QPoint(0,i*height)+QPointF(width,height)));
}
}else if (dir==Dir::Left) {
for(int i=0;i<nodeNum;i++){
body.append(QRectF(topLeft+QPoint(i*width,0),topLeft+QPoint(i*width,0)+QPointF(width,height)));
}
}else {
for(int i=0;i<nodeNum;i++){
body.append(QRectF(topLeft-QPoint(i*width,0),topLeft-QPoint(i*width,0)+QPointF(width,height)));
}
}
}
void Snake::addNodeUp(int windowHeight)
{
if(body.at(0).y()-height<0){ //當碰到上邊界, 碰到邊界不會死
body.insert(0,QRectF(QPointF(body.at(0).x(),windowHeight-height),
QPointF(body.at(0).x()+width,windowHeight)));
}else{
body.insert(0,QRectF(body.at(0).topLeft()+QPointF(0,-height),body.at(0).topRight()));
}
}
void Snake::addNodeDown(int windowHeight)
{
if(body.at(0).y()+2*height>windowHeight){ //當碰到下邊界,碰到邊界不會死
body.insert(0,QRectF(QPointF(body.at(0).x(),height),
QPointF(body.at(0).x()+width,0)));
}else{
body.insert(0,QRectF(body.at(0).bottomLeft(),body.at(0).bottomRight()+QPointF(0,height)));
}
}
void Snake::addNodeLeft(int windowWidth)
{
if(body.at(0).x()-width<0){ //當碰到左邊界,碰到邊界不會死
body.insert(0,QRectF(QPointF(windowWidth-width,body.at(0).y()),
QPointF(windowWidth,body.at(0).y()+height)));
}else{
body.insert(0,QRectF(body.at(0).topLeft()+QPointF(-width,0),body.at(0).bottomLeft()));
}
}
void Snake::addNodeRight(int windowWidth)
{
if(body.at(0).x()+2*width>windowWidth){ //當碰到右邊界,碰到邊界不會死
body.insert(0,QRectF(QPointF(0,body.at(0).y()),
QPointF(width,body.at(0).y()+height)));
}else{
body.insert(0,QRectF(body.at(0).topRight(),body.at(0).bottomRight()+QPointF(width,0)));
}
}
void Snake::moveUp(int windowHeight)
{
if(moveDir != Dir::Down){
addNodeUp(windowHeight);
body.removeLast();
moveDir = Dir::Up;
}
}
void Snake::moveDown(int windowHeight)
{
if(moveDir != Dir::Up){
addNodeDown(windowHeight);
body.removeLast();
moveDir = Dir::Down;
}
}
void Snake::moveLeft(int windowWidth)
{
if(moveDir != Dir::Right){
addNodeLeft(windowWidth);
body.removeLast();
moveDir = Dir::Left;
}
}
void Snake::moveRight(int windowWidth)
{
if(moveDir != Dir::Left){
addNodeRight(windowWidth);
body.removeLast();
moveDir = Dir::Right;
}
}
void Snake::move(int windowWidth, int windowHeight)
{
if(moveDir==Dir::Up){
moveUp(windowHeight);
}else if (moveDir==Dir::Down) {
moveDown(windowHeight);
}else if (moveDir==Dir::Left) {
moveLeft(windowWidth);
}else{
moveRight(windowWidth);
}
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "snake.h"
#include <QPaintEvent>
#include <QPainter>
#include <QBrush>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
public:
void paintEvent(QPaintEvent *event);
void keyPressEvent(QKeyEvent *event);
public:
Snake snake;
public:
QTimer *timer;
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
resize(480, 500);
snake.initBody();
//開啓定時器,讓蛇自動走起來
timer = new QTimer(this);
timer->setInterval(500); //每500毫秒走一步
connect(timer,&QTimer::timeout,this,[=]{
snake.move(this->width(),this->height());
});
timer->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing); //開啓抗鋸齒
QPen pen;
pen.setColor(Qt::black);
painter.setPen(pen);
QBrush brush;
brush.setColor(Qt::green);
brush.setStyle(Qt::SolidPattern);
painter.setBrush(brush);
for(int i=0;i<snake.body.size();i++){
painter.drawRect(snake.body.at(i));
}
update();
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Up:
snake.moveUp(this->height());
break;
case Qt::Key_Down:
snake.moveDown(this->height());
break;
case Qt::Key_Left:
snake.moveLeft(this->width());
break;
case Qt::Key_Right:
snake.moveRight(this->width());
break;
}
}