• 新手QML贪吃蛇 Qt Quick


    1. import QtQuick 2.12
    2. import QtQuick.Window 2.12
    3. import QtQuick.Controls 2.5
    4. ApplicationWindow {
    5. id:window
    6. property int speech: 600
    7. property int movestate: 1//防止出现控制方向与行动方向相反的情况
    8. property var snakeBodylength: -1
    9. property var snakeBody: []//存储蛇身
    10. property var keydirection: 1//键盘控制方向
    11. property var n: 0//自定义一把锁
    12. minimumWidth:600
    13. minimumHeight: 460
    14. maximumWidth:600
    15. maximumHeight: 460
    16. visible: true
    17. title: qsTr("This snake is going to eat chickens")
    18. background: Rectangle
    19. {
    20. color:"#E0EEE0"
    21. }
    22. function creatObj(){
    23. snakeBodylength++;
    24. var obj = creat.createObject(window,{})//新对象的父对象window
    25. return obj
    26. }
    27. Component{//有了Component,就可以调用其createObject()方法来创建该组件的实例
    28. id:creat
    29. Rectangle{
    30. id:test
    31. height: 20
    32. width: 20
    33. color: "black"
    34. }
    35. }
    36. Rectangle{
    37. id:border
    38. x:20
    39. y:20
    40. width: 400
    41. height: 400
    42. border.color: "#6E8B3D"
    43. border.width: 1
    44. }
    45. Button {//暂停按钮
    46. id: stop
    47. x: 467
    48. y: 50
    49. width:100
    50. height: 50
    51. text: qsTr("stop")
    52. font.pixelSize: 16
    53. background:Rectangle{
    54. color:"#F0E68C"
    55. radius: 6
    56. }
    57. onClicked:{
    58. timer.running = false
    59. }
    60. }
    61. Button {//一键重新开始按钮
    62. id:start
    63. x: 467
    64. y: 150
    65. width:100
    66. height: 50
    67. text: qsTr("start")
    68. font.pixelSize: 16
    69. background:Rectangle{
    70. color:"#BFEFFF"
    71. radius: 6
    72. }
    73. onClicked:{
    74. keydirection = 1
    75. movestate = 1
    76. snake.x = 200
    77. snake.y = 200
    78. snake.focus = true
    79. score.text = 0
    80. for(snakeBodylength;snakeBodylength>=0;snakeBodylength--)
    81. snakeBody.pop().destroy()
    82. timer.running = true
    83. newchicken()
    84. }
    85. }
    86. Rectangle{
    87. id:sn
    88. x:430
    89. y:310
    90. scale:1.2
    91. Image{
    92. source: 'tp/snake.png'
    93. }
    94. }
    95. Rectangle{
    96. id:ch1
    97. x:500
    98. y:17
    99. scale: 0.15
    100. Image{
    101. source: 'tp/chicken.png'
    102. }
    103. }
    104. Rectangle{
    105. id:ch2
    106. x:500
    107. y:117
    108. scale: 0.31
    109. Image{
    110. source: 'tp/chicken1.png'
    111. }
    112. }
    113. Text {
    114. id: scoretip
    115. x: 469
    116. y: 260
    117. width: 42
    118. height: 27
    119. text: qsTr("score:")
    120. font.pixelSize: 20
    121. color:"#EE9A00"
    122. }
    123. Text {//分数显示
    124. id: score
    125. x: 535
    126. y: 255
    127. width: 56
    128. height: 27
    129. text: qsTr("0")
    130. color:"#CD7054"
    131. font.pointSize: 20
    132. }
    133. Dialog{
    134. id:out_mesDialog
    135. title:"terrible new: You are out of bounds."
    136. x:100
    137. y:200
    138. width: 300
    139. height: 100
    140. background: Rectangle{
    141. border.color: "#ADD8E6"
    142. }
    143. Label{
    144. x:20
    145. y:0
    146. text:"grade:"
    147. font.pointSize: 20
    148. }
    149. Label{
    150. x:105
    151. y:0
    152. text:score.text
    153. font.pointSize: 20
    154. }
    155. }
    156. Dialog{
    157. id:self_mesDialog
    158. title:"terrible new: You bumped into yourself."
    159. x:100
    160. y:200
    161. background: Rectangle{
    162. border.color: "#ADD8E6"
    163. }
    164. }
    165. Dialog{
    166. id:win_mesDialog
    167. title:"good new: You win!!!!"
    168. x:100
    169. y:200
    170. background: Rectangle{
    171. border.color: "#ADD8E6"
    172. }
    173. }
    174. Rectangle{
    175. id:yanhua
    176. visible: false
    177. z:1//置位上
    178. AnimatedImage
    179. {
    180. id: animation
    181. source: 'tp/yanhua.gif'
    182. }
    183. }
    184. //chicken
    185. Rectangle{
    186. id:chicken
    187. width: 20
    188. height: 20
    189. radius: 20
    190. //initial position
    191. x:(Math.round(Math.random()*19)+1)*20//(1~20)*20即在20到400间取随机值
    192. y:(Math.round(Math.random()*19)+1)*20
    193. color: Qt.rgba(Math.random(),Math.random(),Math.random(),1)//rgba红黄蓝三色比例产生随机颜色,以及透明度
    194. }
    195. Rectangle {
    196. id:snake
    197. property var keydirection: 1//键盘控制方向
    198. // 初始化蛇
    199. x:200
    200. y:200
    201. z:2//置位上层
    202. width: 20
    203. height: 20
    204. color: "black"
    205. focus:true
    206. Keys.onPressed: {
    207. switch(event.key){
    208. case Qt.Key_Left:
    209. keydirection = 1
    210. if(!timer.running){
    211. timer.running = true//如果暂停了按键继续游戏
    212. }
    213. break
    214. case Qt.Key_Right:
    215. keydirection = 2
    216. if(!timer.running){
    217. timer.running = true
    218. }
    219. break
    220. case Qt.Key_Up:
    221. keydirection = 3
    222. if(!timer.running){
    223. timer.running = true
    224. }
    225. break
    226. case Qt.Key_Down:
    227. keydirection = 4
    228. if(!timer.running){
    229. timer.running = true
    230. }
    231. break
    232. default:
    233. keydirection = 0 //无意义按键
    234. if(timer.running){
    235. timer.running = false//按键错误时会暂停游戏
    236. }
    237. }
    238. //event.accepted = true//应该被设置为 true 以免它被继续传递
    239. }
    240. }
    241. Timer{
    242. id:timer
    243. interval:speech
    244. repeat:true
    245. running:true//设置启动,true为启动
    246. onTriggered:{//触发,发出信号
    247. move()
    248. // console.log("snake.x="+snake.x)
    249. // console.log("snake.y="+snake.y)
    250. // console.log("keydirection="+snake.keydirection)
    251. // console.log("snakeBody[0].x="+snakeBody[0].x)
    252. // console.log("snakeBody[0].y="+snakeBody[0].y)
    253. //复制用作调试代码
    254. }
    255. }
    256. function newchicken(){//刷新小鸡的函数
    257. for(var q=0;q<=snakeBodylength;q++){
    258. while((chicken.x===snakeBody[q].x&&chicken.y===snakeBody[q].y)//为了小鸡刷新的位置不在蛇身体的位置
    259. ||(chicken.x===snake.x&&chicken.y===snake.y)){
    260. chicken.x = (Math.round(Math.random()*19)+1)*20
    261. chicken.y = (Math.round(Math.random()*19)+1)*20
    262. }
    263. chicken.color = Qt.rgba(Math.random(),Math.random(),Math.random(),1)
    264. // 此种方法考虑不完全,淘汰
    265. // chicken.x = (Math.round(Math.random()*19)+1)*20
    266. // chicken.y = (Math.round(Math.random()*19)+1)*20
    267. // for(var q=snakeBodylength;q>=0;q--){//为了小鸡刷新的位置不在蛇身体的位置
    268. // if(chicken.x!=snakeBody[q].x&&chicken.y!=snakeBody[q].y){
    269. // if(snake.x!=chicken.x&&snake.y!=chicken.y){
    270. // chicken.color = Qt.rgba(Math.random(),Math.random(),Math.random(),1)
    271. // }
    272. // }
    273. }
    274. }
    275. function collid(item1,item2){//实现碰撞
    276. if((item1.x <= item2.x)&&(item1.x >= item2.x)){
    277. if((item1.y <= item2.y)&&(item1.y >= item2.y)){
    278. return true;//小鸡和蛇碰撞返回值为true
    279. }else
    280. return false;
    281. }else
    282. return false
    283. }
    284. function snakeBodyMove(){//蛇在未碰撞情况下蛇身体自由移动
    285. if (snakeBodylength>=0){
    286. for(var i=snakeBodylength;i>0;i--){
    287. snakeBody[i].x = snakeBody[i-1].x
    288. snakeBody[i].y = snakeBody[i-1].y
    289. }
    290. snakeBody[0].x = snake.x
    291. snakeBody[0].y = snake.y
    292. }
    293. }
    294. function eat(){
    295. //出界,不适合于沿着边缘移动的情况
    296. // if((snake.x==20&&snake.keydirection==1)||(snake.x==400&&snake.keydirection==4)
    297. // ||(snake.y==20&&snake.keydirection==3)||(snake.y==400&&snake.keydirection==4)){
    298. // timer.running = false
    299. // out_mesDialog.open()
    300. // }
    301. //出界,不美观会在出界后才提示
    302. // if(snake.x>420 || snake.y>420 ||snake.x<20 || snake.y<20){
    303. // timer.running = false
    304. // out_mesDialog.open()
    305. // }
    306. if(collid(snake,chicken)){//蛇吃到彩色小鸡时
    307. speech -= 20
    308. if(speech == 60){//检查是否提升速度,提升游戏等级--------------------------------------
    309. timer.running = false
    310. win_mesDialog.open()
    311. yanhua.visible = true
    312. }
    313. snakeBody.push(creatObj())//加入一个新身体
    314. snakeBody[snakeBodylength].x = snake.x
    315. snakeBody[snakeBodylength].y = snake.y
    316. newchicken()
    317. score.text++
    318. n++/*锁:蛇吃到彩色小鸡就变成1
    319. 制锁的原因:
    320. 1.在蛇吃到彩色小鸡的瞬间会有snakeBody[snakeBodylength]与蛇头坐标重合
    321. 2.蛇头由于操作不当撞到蛇身
    322. 两种情况均会触发自撞,为排除第一种影响因素*/
    323. }
    324. //自撞
    325. if(snakeBodylength>0){
    326. for(var t=1;t<=snakeBodylength;t++){
    327. if(snake.x===snakeBody[t].x&&snake.y===snakeBody[t].y)
    328. {
    329. if(n==0){//此时锁为0,即未吃到彩色小鸡
    330. timer.running = false
    331. self_mesDialog.open()
    332. }
    333. else
    334. n--
    335. }
    336. }
    337. }
    338. }
    339. function move(){//timer刷新时需要做的
    340. //出界,不美观蛇头出界后显示
    341. // if(snake.x<=20&&snake.keydirection==1){
    342. // var m=snake.keydirection
    343. // m++
    344. // if(m==2){
    345. // timer.running = false
    346. // out_mesDialog.open()
    347. // }
    348. // }
    349. if(movestate == 1 && snake.keydirection == 2 ){
    350. snake.keydirection = movestate
    351. }
    352. if(movestate == 2 && snake.keydirection == 1 ){
    353. snake.keydirection = movestate
    354. }
    355. if(movestate == 3 && snake.keydirection == 4 ){
    356. snake.keydirection = movestate
    357. }
    358. if(movestate == 4 && snake.keydirection == 3 ){
    359. snake.keydirection = movestate
    360. }
    361. snakeBodyMove()//蛇在未碰撞情况下的自由移动
    362. if(snake.keydirection == 1){
    363. movestate = 1
    364. if(snake.x==20){
    365. /*出界判断,优点:不会等到出界显示提示且适用于沿着边界行走的状况
    366. 缺点:蛇身仍然会向前一格,即snakeBody[0].x=snake.x;snakeBody[0].y=snake.y
    367. 视觉上缺失了一格*/
    368. timer.running = false
    369. out_mesDialog.open()
    370. }
    371. else
    372. snake.x -= 20
    373. }
    374. if(snake.keydirection == 2){
    375. movestate = 2
    376. if(snake.x==400){
    377. timer.running = false
    378. out_mesDialog.open()
    379. }
    380. else
    381. snake.x += 20
    382. }
    383. if(snake.keydirection == 3){
    384. movestate = 3
    385. if(snake.y==20){
    386. timer.running = false
    387. out_mesDialog.open()
    388. }
    389. else
    390. snake.y -= 20
    391. }
    392. if(snake.keydirection == 4){
    393. movestate = 4
    394. if(snake.y==400){
    395. timer.running = false
    396. out_mesDialog.open()
    397. }
    398. else
    399. snake.y += 20
    400. }
    401. eat();
    402. }
    403. }

    刚刚开始学习qml,尝试做了一个贪吃蛇(无C++交互),请多指教。

  • 相关阅读:
    PCL1.12.1+VTK9.1+Qt5.14.2VS创建Qt项目在widget上显示点云
    epoll 的实现
    电脑设备管理器在哪里可以找到
    3.6让MBR使用磁盘
    使用 Dify 和 MoonShot API 做一个懒人 AI 阅读工具(二):轻量 RAG 应用
    图标、图片、矢量图注册,通过名称来配置icon可以提高性能
    vs studio Ctrl+D 快捷键失效(无法复制行)
    vue中使用keep-alive无效以及include 和 exclude用法
    Spring中value的#和$区别
    记录fork子进程执行execl阻塞卡死的问题
  • 原文地址:https://blog.csdn.net/weixin_52857380/article/details/132620728