Qt小游戏开发:贪吃蛇
来源:互联网 发布:dsdtfixer mac 最新版 编辑:程序博客网 时间:2024/04/29 06:09
周末没事,手写小游戏继续~
预览
步骤
1 定义数据结构
逻辑与界面分离,游戏场景是个二维数组区域,贪吃蛇是若干个连续的坐标点集合,用动态链表维护,果实是一个随机坐标点。
const int BLOCK_SIZE=25; //单个方块单元的边长const int MARGIN=5; //场景边距const int AREA_ROW=15; //场景行数const int AREA_COL=15; //场景列数
QPoint foodPoint; //果实出现坐标 QList<QPoint> snake; //贪吃蛇结构
const int TIME_INTERVAL=500; //定时器间隔时间enum Direction{ UP, DOWN, LEFT, RIGHT};
2 添加界面刷新和键盘监听
首先需要定时器来控制贪吃蛇的移动以及界面的刷新,绑定定时器的信号槽
gameTimer=new QTimer(this); connect(gameTimer,SIGNAL(timeout()),this,SLOT(SnakeUpdate()));窗口重绘
void Widget::paintEvent(QPaintEvent *event){ QPainter painter(this); //绘制游戏场景 painter.setBrush(Qt::yellow); painter.setPen(Qt::blue); painter.drawRect(MARGIN,MARGIN,AREA_COL*BLOCK_SIZE,AREA_ROW*BLOCK_SIZE); //绘制贪吃蛇 painter.setBrush(Qt::red); painter.setPen(Qt::green); for(int i=0;i<snake.size();i++) painter.drawRect(MARGIN+snake[i].x()*BLOCK_SIZE,MARGIN+snake[i].y()*BLOCK_SIZE,BLOCK_SIZE,BLOCK_SIZE); //绘制果实 painter.setBrush(Qt::green); painter.drawEllipse(MARGIN+foodPoint.x()*BLOCK_SIZE,MARGIN+foodPoint.y()*BLOCK_SIZE,BLOCK_SIZE,BLOCK_SIZE); //绘制游戏分数 painter.setPen(Qt::black); painter.setFont(QFont("Arial",14)); painter.drawText(MARGIN*3+AREA_COL*BLOCK_SIZE,MARGIN+2*BLOCK_SIZE,"score: "+QString::number(score));}键盘监听
void Widget::keyPressEvent(QKeyEvent *event){ //贪吃蛇的方向是个状态机,注意各个方向之间切换有限制 switch(event->key()) { case Qt::Key_Up: if(dir!=DOWN) dir=UP; break; case Qt::Key_Down: if(dir!=UP) dir=DOWN; break; case Qt::Key_Left: if(dir!=RIGHT) dir=LEFT; break; case Qt::Key_Right: if(dir!=LEFT) dir=RIGHT; break; case Qt::Key_P: PauseResumeGame(); break; default: break; }}
贪吃蛇的移动是个状态机,总是朝着当前的方向前进,移动的逻辑是,不断地消除尾部节点,并添加一个新的头部结点,如果碰到了果实,则不消除尾部结点
每次吃到了果实后会重新随机生成一个果实,并且保证果实不会与贪吃蛇身体重叠。
void Widget::SnakeUpdate(){ //贪吃蛇移动的策略是每次删除尾部,然后添加新的头部,维护一个动态链表 switch(dir) { case UP: snake.push_front(QPoint(snake.front().x(),snake.front().y()-1)); break; case DOWN: snake.push_front(QPoint(snake.front().x(),snake.front().y()+1)); break; case LEFT: snake.push_front(QPoint(snake.front().x()-1,snake.front().y())); break; case RIGHT: snake.push_front(QPoint(snake.front().x()+1,snake.front().y())); break; default: break; } //如果吃到了果实,则尾部不删除,否则删除尾部更新头部 if(snake.contains(foodPoint)) { score+=1; //得分 GenerateFood(); //重新生成果实 } else snake.pop_back(); //游戏是否结束 if(IsGameOver()) { GameOver(); return; //赶在重绘之前跳出函数,防止贪吃蛇真的出界 } update(); //重绘,比repaint函数效果好}
void Widget::GenerateFood(){ //随机产生位置 foodPoint.setX(rand()%AREA_COL); foodPoint.setY(rand()%AREA_ROW); //如果与贪吃蛇位置冲突,重新生成 if(snake.contains(foodPoint)) GenerateFood();}
bool Widget::IsGameOver(){ int x=snake.front().x(); int y=snake.front().y(); //出边界 if(x<0||x>AREA_COL-1||y<0||y>AREA_ROW-1) return true; //撞了自己 for(int i=3;i<snake.size();i++) if(snake[i]==snake.front()) return true; return false;}
游戏初始化
void Widget::InitGame(){ //初始化贪吃蛇,初始长度5,注意头部在前,尾部在后 for(int j=4;j>=0;j--) snake.push_back(QPoint(j,0)); dir=RIGHT;//初始时往右走 //初始化果实 srand(time(0)); GenerateFood(); //初始化游戏分数 score=0; //初始化暂停变量 isPause=false; //初始化计时器 gameTimer=new QTimer(this); connect(gameTimer,SIGNAL(timeout()),this,SLOT(SnakeUpdate())); gameTimer->start(TIME_INTERVAL);}游戏暂停和恢复
void Widget::PauseResumeGame(){ //暂停和恢复定时器 if(!isPause) { isPause=!isPause; gameTimer->stop(); } else { isPause=!isPause; gameTimer->start(TIME_INTERVAL); }}游戏结束
void Widget::GameOver(){ gameTimer->stop(); QMessageBox::information(this,"failed","game over!");}
csdn:贪吃蛇
github: snake
github: snake
0 0
- Qt小游戏开发:贪吃蛇
- Qt 贪吃蛇小游戏
- android开发小游戏之贪吃蛇
- javascript开发贪吃蛇小游戏练习
- Qt开发实例-贪吃蛇
- Qt图形简单绘制(3)-贪吃蛇小游戏
- 小游戏 贪吃蛇
- 贪吃蛇小游戏
- 贪吃蛇小游戏
- 贪吃蛇小游戏
- Applet贪吃蛇小游戏
- 贪吃蛇小游戏记录:
- 贪吃蛇小游戏笔记
- [小游戏]贪吃蛇
- 经典贪吃蛇小游戏
- 贪吃蛇小游戏~
- 【java】贪吃蛇小游戏
- 【java】贪吃蛇小游戏
- 运行项目时,工程前面就出现了小红叉解决办法
- 在Qt Creator中配置Opencv的详细步骤
- css &js 53 再看水平居中 轮播图片
- MATLAB工具箱(功能型工具箱和领域型工具箱)
- 面试题23:从上往下打印二叉树
- Qt小游戏开发:贪吃蛇
- SSHthis.getHibernateTemplate().save(user)入不了库。
- 一起talk C栗子吧(第二回:C语言实例--判断闰年)
- Linux Bash Shell入门教程
- 启动Tomcat提示:指定的服务未安装
- 第十二周项目4-3:点,圆的关系-输出线和圆的交点
- 总是稀里糊涂的移位操作
- solr 4.9.1+mysql数据库数据导入
- Add Binary