snake

开发平台:Qt Creator 5.9.1

项目描述:贪吃蛇小游戏,采取建立不同的界面类(mainWidget,开始界面,和GameWidget,游戏界面,通过接收事件利用信号和槽,来进行界面切换。通过捕扣用户的按键事件。重写窗口对象的keyPresseEvent虚函数控制snake获取食物使自己长大。蛇每次吃到食物时,节点变多一节, 蛇节点数是不固定。用QList来存放每个节点的数据。每个节点都有x, y坐标,用QPoint类对象存放。需要定时移动蛇,可用定时器QTimer。定时器对象超时会发出timeout信号,需要把这个信号连接到时间处理的槽函数。并调用窗口对象的repaint成员触发paintEvent。通过QMessageBox消息框决定游戏是否继续。

QMessageBox消息框的四种用法:

  1. d MainWindow::on_info_clicked()  
  2. {  
  3. //info  
  4. QMessageBox::information(this"Title""Text");  
  5. }  
  6.   
  7. void MainWindow::on_question_clicked()  
  8. {  
  9. //question  
  10. QMessageBox::StandardButton reply;  
  11. reply = QMessageBox::question(this"Title""Do you like cat?", QMessageBox::Yes | QMessageBox::No);  
  12. if(reply == QMessageBox::Yes)  
  13. {  
  14. }  
  15. else  
  16. {  
  17. }  
  18. }  
  19.   
  20. void MainWindow::on_warning_clicked()  
  21. {  
  22. //warning  
  23. QMessageBox::warning(this"Title""Text");  
  24. }  
  25.   
  26. void MainWindow::on_pushButton_4_clicked()  
  27. {  
  28. QMessageBox::question(this"Title""Do you like cat?", QMessageBox::YesToAll|QMessageBox::Yes|QMessageBox::No);  
  29. }  



[cpp]  view plain  copy
  1. class MyMessageBox : public QObject  
  2. {  
  3. public:  
  4.     MyMessageBox();~MyMessageBox();  
  5.   
  6.     static void ChMessageOnlyOk_Information(QString info)  
  7.     {  
  8.         QMessageBox msg;  
  9.         msg.setWindowTitle(tr("提示"));  
  10.         msg.setText(info);  
  11.         msg.setStyleSheet("font: 14pt;background-color:rgb( 0,220, 0)");  
  12.         msg.setIcon(QMessageBox::Information);  
  13.         msg.addButton(tr("确定"),QMessageBox::ActionRole);  
  14.         msg.exec();  
  15.     }  
  16.   
  17.     static void ChMessageOnlyOk_Error(QString info)  
  18.     {  
  19.         QMessageBox msg;  
  20.         msg.setWindowTitle(tr("提示"));  
  21.         msg.setText(info);  
  22.         msg.setStyleSheet("font: 14pt;background-color:rgb(220, 0, 0)");  
  23.         msg.setIcon(QMessageBox::Critical);  
  24.         msg.addButton(tr("确定"),QMessageBox::ActionRole);  
  25.         msg.exec();  
  26.     }  
  27.   
  28.     static int ChMessageOkCancel(QString info)  
  29.     {  
  30.         QMessageBox msg;  
  31.         msg.setWindowTitle(tr("提示"));  
  32.         msg.setText(info);  
  33.         msg.setStyleSheet("color:rgb(220, 0, 0);font: 14pt");  
  34.         msg.setIcon(QMessageBox::Information);  
  35.         msg.addButton(tr("确定"),QMessageBox::ActionRole);  
  36.         msg.addButton(tr("取消"),QMessageBox::ActionRole);  
  37.         return msg.exec();  
  38.     }  
  39. };  
  40.   
  41.   
  42.   
  43.   
  44. int ret = MyMessageBox::ChMessageOkCancel(tr("是否继续?"));  
  45. if(1 == ret)  
  46. {  
  47.   
  48. }  
  49. else if(0 == ret)  
  50. {  
  51. }  

主窗口分析:mainWidget

头文件分析

#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include "GameWidget.h"
#include <QWidget>
#include <QIcon>
#include <QPalette>
#include <QBrush>
#include <QPixmap>
#include <QPushButton>
#include <QMessageBox>
#include <QLabel>
#include <QFont>
class mainWidget : public QWidget//继承了QWidget类
{
    Q_OBJECT
//只要有槽和信号机制,就要写Q_OBJECT
public:
    mainWidget(QWidget *parent = 0);
    ~mainWidget();
    //void resizeEvent(QResizeEvent *);
private:
    QPushButton *startbtn;//一个按钮,用鼠标点击后会开始游戏
    QPushButton *exitbtn;//一个按钮,用鼠标点击后会退出
    GameWidget *g;
    QLabel *label;
signals://信号,mainWidget不会发出信号
public slots://可以接收所有信号的公共槽
    void exitSlot();//用来接收退出信号的槽
    void startSlot();//用来接收开始信号的槽
};

#endif // MAINWIDGET_H
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

.cpp文件分析 
注释的都是可以在自己的程序中使用的函数

#include "mainWidget.h"

mainWidget::mainWidget(QWidget *parent): QWidget(parent)
{
    this->resize(480,270);//resize函数,用来设置mainWidget这个窗口的大小
    this->setMaximumSize(480,270);
    this->setWindowIcon(QIcon(":/new/prefix1/img/icon.png"));//设置ICON
    this->setWindowTitle("贪吃蛇");
    QPalette palette;
    palette.setBrush(QPalette::Background,QBrush(QPixmap(":/new/prefix1/img/back.jpg").scaled(this->size())));
    this->setPalette(palette);

    startbtn=new QPushButton(this);
    startbtn->setIcon(QIcon(":/new/prefix1/img/start.png"));
    startbtn->setIconSize(QSize(75,75));
    startbtn->setGeometry(QRect(250,170,75,75));
    startbtn->setFlat(true);

    exitbtn=new QPushButton(this);
    exitbtn->setIcon(QIcon(":/new/prefix1/img/quit.png"));
    exitbtn->setIconSize(QSize(70,70));
    exitbtn->setGeometry(QRect(350,170,70,70));
    exitbtn->setFlat(true);
    //设置说明标签
    QFont font;
    font.setFamily("Consolas");
    font.setBold(true);
    font.setPixelSize(13);
    label=new QLabel(this);
    label->setText("游戏说明:贪吃蛇游戏可使用按钮或者w a s d控制蛇的走动");
    label->setFont(font);
    label->setGeometry(QRect(10,10,400,50));

    connect(exitbtn,SIGNAL(clicked()),this,SLOT(exitSlot()));
    connect(startbtn,SIGNAL(clicked()),this,SLOT(startSlot()));
}

mainWidget::~mainWidget()
{
    delete startbtn;
    delete exitbtn;
}
void mainWidget::exitSlot()
{
    if(QMessageBox::question(this,"退出游戏","是否退出当前游戏",QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes)
    {
        delete this;
        exit(0);
    }
}
void mainWidget::startSlot()
{

    g=new GameWidget(this);
    g->show();
}
//重写resizeEvent
/*void mainWidget::resizeEvent(QResizeEvent *)
{
    QPalette palette;
    palette.setBrush(QPalette::Background,QBrush(QPixmap("img/back.jpg").scaled(this->size())));
    this->setPalette(palette);
    startbtn->setGeometry(QRect(this->size().width()-230,this->size().height()-100,75,75));
    exitbtn->setGeometry(QRect(this->size().width()-130,this->size().height()-100,70,70));
}*/

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

QMessageBox的初始化及效果

void mainWidget::exitSlot()
{
    if(QMessageBox::question(this,"退出游戏","是否退出当前游戏",QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes)
    {
        delete this;
        exit(0);//直接结束进程
    }
    //生成一个弹窗。question的初始化为(链接的窗口,"标题","示意文字",QMessageBox::Yes|QMessageBox::No)
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

游戏窗口分析:GameWidgit

游戏窗口是这个程序的主体部分,各种复杂的事件(槽和信号机制),状态的更新,动画、碰撞检测都是在这个类(游戏窗口就是一个继承了普通窗口< Widget >的派生类)中完成的。

头文件分析

#ifndef GAMEWIDGET_H
#define GAMEWIDGET_H

#include <QWidget>
//既然继承自QWidget,肯定需要include相关的头文件
#include <QPalette>
#include <QIcon>
//这些是为了让你在显示背景图片和窗口图标,一般做游戏(自己设计UI)都要用
#include <QPushButton>
//这个库在你有鼠标事件的事后非常好用
#include <QPainter>
//如果有动画,需要包含QPainter库(如果只是显示图片可以用其他方法,但游戏一般都有动画)
#include <QDebug>
//主要用于调试代码,类似于std::cout的替代品,支持QT的数据类型。
#include <QTime>
#include <QTimer>
//和计时有关的库,做游戏也一般都要用到
#include <QMessageBox>
//如果你的游戏有弹出框,就要包含(非必须)
#include <QKeyEvent>
//如果你的游戏可以用键盘操纵,需要包含
#include <QLabel>
//可以用来显示字(也可以显示图片)
#include <QFont>
//如果你要用Qt绘制字(而不是用自己设计的UI)时,需要包含
#include <QSound>
//音频相关,游戏一般必须

class GameWidget : public QWidget
{
    Q_OBJECT
public:
    //构造函数
    explicit GameWidget(QWidget *parent = 0);
    ~GameWidget();
    //绘制事件,游戏中非常重要的函数
    void paintEvent(QPaintEvent *);
    //键盘事件
    void keyPressEvent(QKeyEvent *);
private:
    //按钮相当于鼠标事件
    QPushButton *upbtn;
    QPushButton *leftbtn;
    QPushButton *downbtn;
    QPushButton *rightbtn;
    QPushButton *startbtn;
    QPushButton *returnbtn;

    //记录蛇目前运动方向
    int direction;
    //用来记录蛇xy坐标,可以看出最大能得100分
    int snake[100][2];
    int snake1[100][2];
    //计算吃过了几个食物
    int foodcount;
    //计时器!和动画的帧数也有关
    QTimer *timer;

    //食物的属性
    int foodx,foody;
    int score;
    int level;

    QLabel *scorelabel;
    QLabel *levellabel;
    QLabel *scoreshow;
    QLabel *levelshow;
    QString str1,str2;
    QSound *sound;
    QSound *sound1;
signals:
//因为有键盘事件(KeyPressEvent),键盘事件要发射不同的信号
    void UpSignal();
    void DownSignal();
    void LeftSignal();
    void RightSignal();
public slots:
    //一般来说有几个按钮就要有几个槽函数
    void upbtnSlot();
    void leftbtnSlot();
    void rightbtnSlot();
    void downbtnSlot();
    void startbtnSlot();
    void returnbtnSlot();

    //本例的主函数,和timer结合使用(比较复杂,之后会详细讲)
    void timeoutSlot();
};

#endif // GAMEWIDGET_H

QDebug的说明

.c文件分析 
因为GameWidget略长,且有一些部分和MainWidget用法一致,就不放上来全部代码(想要自己运行的可以从之前附上的链接下载,记得只适用于QT5) 
注: 需要include相应的库文件

1.如何让你的游戏发出声音 
首先要载入音频

    //声音区:载入音频,注意音频文件要加入.qrc文件中
    sound=new QSound(":/listen/img/5611.wav");
    sound1=new QSound(":/listen/img/die.wav");
 
 
  • 1
  • 2
  • 3

在什么时候播放声音,使用if语句判断,一般是一个可以update()的槽函数中(本例为timeoutSlot(),见下文)

sound->play();
 
 
  • 1

2.如何即时显示得分

    str1=QString::number(score);//转化为字符串

    scoreshow=new QLabel(this);//用Label输出
    scoreshow->setFont(font);
    scoreshow->setGeometry(QRect(385,1,60,30));
    scoreshow->setText(str1);
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3.如何设置交互(信号和槽机制)

    //设置按钮操作
    connect(leftbtn,SIGNAL(clicked()),this,SLOT(leftbtnSlot()));
    connect(rightbtn,SIGNAL(clicked()),this,SLOT(rightbtnSlot()));
    connect(upbtn,SIGNAL(clicked()),this,SLOT(upbtnSlot()));
    connect(downbtn,SIGNAL(clicked()),this,SLOT(downbtnSlot()));
    connect(startbtn,SIGNAL(clicked()),this,SLOT(startbtnSlot()));
    connect(returnbtn,SIGNAL(clicked()),this,SLOT(returnbtnSlot()));
    //设置键盘操作
    connect(this,SIGNAL(UpSignal()),upbtn,SLOT(click()));
    connect(this,SIGNAL(DownSignal()),downbtn,SLOT(click()));
    connect(this,SIGNAL(LeftSignal()),leftbtn,SLOT(click()));
    connect(this,SIGNAL(RightSignal()),rightbtn,SLOT(click()));
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

connect的使用

connect(发射信号的类,SIGNAL(信号函数),接收信号的类,SLOT(槽函数));

按钮操作的实现 
QPushButton这个类中有click()的信号函数和槽函数,如果发生了鼠标点击事件,被点击的Button就发射click()信号,因为我们用connect将这个信号和GameWidget中的槽函数(比如leftbtnSlot())连接起来,GameWidget就能接收到这个信号并且调用相应的槽函数。 
键盘操作同理,因为KeyPressEvent是我们自己写在GameWidget类中,所以为 ‘this’ 指针。这次connect是把键盘事件和按钮联系了起来。

4.如何设置随机数

    QTime t;
    t= QTime::currentTime();
    qsrand(t.msec()+t.second()*1000);
 
 
  • 1
  • 2
  • 3

5.如何update程序

    timer=new QTimer(this);
    timer->setInterval(500);//设置时间间隔
    connect(timer,SIGNAL(timeout()),this,SLOT(timeoutSlot()));
 
 
  • 1
  • 2
  • 3

该程序设置了一个timer(一个定时触发器,参考这里),并且设置了时间间隔,每过一次时间间隔发送一个timeout()信号。 
而GameWidget类中定义了timeoutSlot()槽函数,每过一定时间间隔被调用,执行update()操作,来更新界面状态,下文会讲

6.(重点)timeoutSlot分析 
因为这一段很长,也只写出代码结构(需要完整代码见开头链接)

void GameWidget::timeoutSlot()
{
    //判断是否吃到食物的代码块(判断蛇的坐标和食物的坐标是否重合)
    //其中包含,发出声音、更新食物坐标(随机更新,食物不能出现在蛇身上)、如果分数到达一定的档次,就提升游戏等级(改变时间间隔)

    memcpy(snake1,snake,sizeof(snake));//不能直接对目前显示的数组进行操作,因此一开始就定义了两个数组存放当前状态和改变后的状态,用memcpy拷贝

    //实现蛇的游动
    for(int i=foodcount;i>=1;i--)
    {
        snake[i][0]=snake[i-1][0];
        snake[i][1]=snake[i-1][1];
    }

    switch(direction)
    {
    case UP:snake[0][1]--;break;
    case DOWN:snake[0][1]++;break;
    case LEFT:snake[0][0]--;break;
    case RIGHT:snake[0][0]++;break;
    }

    //判断蛇是否撞到自身的代码块,如果撞到,显示游戏结束的弹窗,并重置游戏

    //判断蛇是否撞到墙体的代码块

    //最关键,调用update()函数,更新窗口状态
    this->update();
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

memcpy辅助理解 
update辅助理解 
其中的碰撞检测机制是通过判断xy坐标是否相同来进行的。 
Qt工具书上似乎有其他碰撞检测的办法,挖个坑

7.(重点)paintEvent分析 
函数声明

void GameWidget::paintEvent(QPaintEvent *);
 
 
  • 1

要定义一个绘制器painter

QPainter painter(this);
 
 
  • 1

画一个小方格(长方形)的代码(该游戏画了很多很多小方格),只摘取一个:j,i是坐标,20, 20是方格的大小

painter.drawRect(j,i,20,20);
 
 
  • 1

读取素材绘制 
foodx要乘20的原因是这是相对坐标,而不是绝对坐标

painter.drawImage(foodx*20,foody*20,QImage(":/new/prefix1/img/apple.png").scaled(QSize(20,20)));
部分代码

#include "widget.h"
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
     this->setWindowOpacity(0.8);
     this->setWindowTitle("贪吃蛇");
     num_initialize();
     snake.append(QPoint(5,5));
     startTimer(500);
//    m_timer = new QTimer(this);
//    connect(m_timer, SIGNAL(timeout()), this, SLOT(timerEvent(QTimerEvent)));
//    m_timer->start(1000);
}
void Widget::timerEvent(QTimerEvent *e)
{
    //trans
    QPoint newhead =  snake.at(0);
    switch(direct)
    {
    case 0:
        newhead.setY(newhead.y()-1); break;
    case 1:
        newhead.setY(newhead.y()+1); break;
    case 2:
        newhead.setX(newhead.x()-1); break;
    case 3:
        newhead.setX(newhead.x()+1); break;
    }
    snake.push_front(newhead);
//    if(snake_sit==fruit_sit)
//       { flag=0;
//         snake_sit=0;fruit_sit=1;
//         create_fruit();
//    }
//    if(flag==1){
//      snake.pop_back();  //更新
//    }
//    flag=1;
    if(snake.contains(pos)) create_fruit();
    else  snake.pop_back();  //更新
  // snake.contains(pos); //获取果实坐标
    if(GameOver())
    {   Over();
       return ;}
    if(flag==0)
    update();
}
 
void Widget::keyPressEvent(QKeyEvent *e)
{
    if(e->key()==Qt::Key_Up)  direct=0;
    if(e->key()==Qt::Key_Down) direct=1;
    if(e->key()==Qt::Key_Left) direct=2;
    if(e->key()==Qt::Key_Right) direct=3;
 
}
 
void Widget::paintEvent(QPaintEvent *e)
{
   //  pos=mapFromGlobal(QCursor::pos());
   //    qDebug()<<pos;
  //          m_startX=pos.x();  qDebug()<<pos.x();
//            m_startY=pos.y();
//            update();
    QPainter frame(this);  //边框
    QPen  Fpen(Qt::magenta);
    Fpen.setWidth(8);
    frame.setPen(Fpen);
    frame.drawRect(frame_size,frame_size,frame_w*pen_size,frame_h*pen_size);
 
    QPainter p(this);
    QPen pen(QColor(Qt::darkGreen));
    p.setBrush(Qt::blue);
    pen.setWidth(15); //画笔宽度
    p.setPen(pen);   //交
    for(int i=0;i<snake.length(); i++)
    {
    p.drawRect(frame_size+snake.at(i).x()*pen_size,
                     frame_size+snake.at(i).y()*pen_size,
                     1,1); //1,1
    qDebug()<<snake.at(i).x()<<" y:"<<snake.at(i).y();
    //if(i==2) flag=1;
            snake_sit=snake.at(i).x();
    }
    // p.drawPoint(m_startX, m_startY); //鼠标脱线
//   fruit.drawEllipse(frame_size+pos.x()*pen_size,
//                     frame_size+pos.y()*pen_size,
//                     pen_size,pen_size);
 
 
   //   QPainter fruit(this);    //食物
 
        QPainter fruit(this);
        QPen pen1(QColor(Qt::green));
        fruit.setBrush(Qt::red);
        pen1.setWidth(1); //画笔宽度
        fruit.setPen(pen1);   //交
//      frame.drawEllipse(frame_size+pos.x()*pen_size,
//                          frame_size+pos.y()*pen_size,
//                          pen_size,pen_size);
        frame.drawRect(frame_size+pos.x()*pen_size,
                       frame_size+pos.y()*pen_size,
                         15,10);
        qDebug()<<"f:"<<pos.x()+5<<" : "<<pos.y()+5;
 
 
}
void Widget::create_fruit()
{
  pos.setX(rand()%frame_w);
  pos.setY(rand()%frame_h);
  if(snake.contains(pos)) create_fruit();
}
bool Widget::GameOver()
{
 
  int X=snake.front().x();
  int Y=snake.front().y();
  if(X<0||X>frame_w-1||Y<0||Y>frame_h-1)
   {     flag=1;   return true;}
  for(int i=3;i<snake.size();i++)
  {
      if(snake[i]==snake.front())
       { flag=1; return true;}
  }
   return false;
}
void Widget::Over()
{
    flag=1;
    QMessageBox::information(this,"failed","^_^ 你死了!");
 
}
void Widget::num_initialize()
{
    flag      =0;
    pen_size  =20;
    frame_size=50;
    frame_w   =15;
    frame_h   =20;
    direct    =3; //keyboard
    snake_sit=0;
    fruit_sit=1;
}
Widget::~Widget()
{
 
}
 


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用GVF域和VFC域进行图片分割 % Vector field convolution (VFC) external force field example. % % See also AMT, EXAMPLE_PIG, AM_VFC, AM_VFK, AC_DISPLAY. % % Reference % [1] Bing Li and Scott T. Acton, "Active contour external force using % vector field convolution for image segmentation," Image Processing, % IEEE Trans. on, vol. 16, pp. 2096-2106, 2007. % [2] Bing Li and Scott T. Acton, "Automatic Active Model % Initialization via Poisson Inverse Gradient," Image Processing, % IEEE Trans. on, vol. 17, pp. 1406-1420, 2008. % % (c) Copyright Bing Li 2005 - 2009. clear all disp('======================================') disp('Vector field convolution (VFC) example') %% parameter settings disp('Initializing parameters ...') SAVE_AVI = 0; % set it to 1 if you want to save the process as .avi movie DISPLAY_STREAMLINE = 0; % set it to 1 if you want to plot streamlines, note that it takes a while mu = .2; GVF_ITER = 100; normalize = 1; alpha = .5; beta = 0; tau = .5; SNAKE_ITER = 5; SNAKE_ITER1 = 60; RES = .5; clr = {'b' 'b' 'r'}; %% Read images disp('Reading images ...') U = imread('im_U.bmp'); noisyU=imread('im_Unoisy.bmp'); figure(1) %% compare 3 different cases for cs = 1:3, %% compute external force fields switch cs, case 1, % traditional GVF with Gaussian filter disp('--------------------------------------------------') disp('Case 1: GVF snake with initial circle close to FOI') disp('Computing the external force field ...') h = fspecial('gaussian',[5 5],5); f = imfilter(double(noisyU),h); titl = 'GVF'; Fext = AM_GVF(f, mu, GVF_ITER, normalize); R = 20; case 2, % traditional GVF with Gaussian filter disp('--------------------------------------------------') disp('Case 2: GVF snake with initial circle far away from FOI') disp('Computing the external force field ...
为了实现OpenCV贪吃蛇游戏,我们需要使用以下步骤: 1. 导入必要的库和模块,包括cv2、numpy、random和time。 2. 创建一个空白图像,用于显示游戏界面。 3. 定义贪吃蛇的初始位置和大小,以及食物的初始位置。 4. 定义贪吃蛇的移动方向和速度。 5. 在每个游戏循环中,检测用户按下的键盘按键,并根据按键更新贪吃蛇的移动方向。 6. 根据贪吃蛇的移动方向和速度,更新贪吃蛇的位置。 7. 检测贪吃蛇是否吃到了食物,如果是,则增加贪吃蛇的长度,并重新生成食物。 8. 检测贪吃蛇是否碰到了边界或自己的身体,如果是,则游戏结束。 9. 在每个游戏循环中,将贪吃蛇和食物绘制到游戏界面上。 10. 在每个游戏循环中,更新游戏界面并等待一段时间,以控制游戏速度。 以下是一个简单的OpenCV贪吃蛇游戏的代码示例: ```python import cv2 import numpy as np import random import time # 创建空白图像 img = np.zeros((600, 800, 3), np.uint8) # 定义贪吃蛇和食物的初始位置和大小 snake = [(400, 300)] snake_size = 20 food = (random.randint(0, 39) * 20, random.randint(0, 29) * 20) # 定义贪吃蛇的移动方向和速度 direction = 'right' speed = 20 # 游戏循环 while True: # 检测键盘按键 key = cv2.waitKey(100) if key == ord('w') and direction != 'down': direction = 'up' elif key == ord('s') and direction != 'up': direction = 'down' elif key == ord('a') and direction != 'right': direction = 'left' elif key == ord('d') and direction != 'left': direction = 'right' elif key == 27: break # 更新贪吃蛇的位置 if direction == 'up': snake.insert(0, (snake[0][0], snake[0][1] - speed)) elif direction == 'down': snake.insert(0, (snake[0][0], snake[0][1] + speed)) elif direction == 'left': snake.insert(0, (snake[0][0] - speed, snake[0][1])) elif direction == 'right': snake.insert(0, (snake[0][0] + speed, snake[0][1])) # 检测贪吃蛇是否吃到了食物 if snake[0] == food: snake_size += 1 food = (random.randint(0, 39) * 20, random.randint(0, 29) * 20) # 检测贪吃蛇是否碰到了边界或自己的身体 if snake[0][0] < 0 or snake[0][0] > 780 or snake[0][1] < 0 or snake[0][1] > 580 or snake[0] in snake[1:]: break # 绘制贪吃蛇和食物 img.fill(0) for i, s in enumerate(snake): cv2.rectangle(img, (s[0], s[1]), (s[0] + snake_size, s[1] + snake_size), (255, 255, 255), -1) cv2.rectangle(img, (food[0], food[1]), (food[0] + snake_size, food[1] + snake_size), (0, 0, 255), -1) # 更新游戏界面 cv2.imshow('Snake', img) cv2.waitKey(1) # 等待一段时间,控制游戏速度 time.sleep(0.1) # 游戏结束 cv2.destroyAllWindows() --相关问题--:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值