微信小游戏入门案例——拼图游戏

逃离我推掉我的手 2022-12-16 13:03 489阅读 0赞

微信小游戏入门案例——拼图游戏

涉及内容:canvas组件、小程序界面绘图API

目录结构:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l1bmZlYXRoZXI_size_16_color_FFFFFF_t_70

pages\game\game.js

  1. // pages/game/game.js
  2. // 方块的初始位置
  3. var num = [
  4. ['00', '01', '02'],
  5. ['10', '11', '12'],
  6. ['20', '21', '22']
  7. ]
  8. // 方块的宽度
  9. var w = 100
  10. // 图片的初始地址
  11. var url = '/images/pic01.jpg'
  12. Page({
  13. /**
  14. * 页面的初始数据
  15. */
  16. data: {
  17. isWin: false
  18. },
  19. /**
  20. * 自定义函数--随机打乱方块顺序
  21. */
  22. shuffle: function() {
  23. // 先令所有方块回归初始位置
  24. num = [
  25. ['00', '01', '02'],
  26. ['10', '11', '12'],
  27. ['20', '21', '22']
  28. ]
  29. // 记录当前空白方块的行和列
  30. var row = 2
  31. var col = 2
  32. // 随机打乱方块顺序100次
  33. for (var i = 0; i < 100; i++) {
  34. // 随机生成一个方向:上0,下1,左2,右3
  35. var direction = Math.round(Math.random() * 3)
  36. // 上:0
  37. if (direction == 0) {
  38. // 空白方块不能在最上面一行
  39. if (row != 0) {
  40. // 交换位置
  41. num[row][col] = num[row - 1][col]
  42. num[row - 1][col] = '22'
  43. // 更新空白方块的行
  44. row -= 1
  45. }
  46. }
  47. // 下:1
  48. if (direction == 1) {
  49. // 空白方块不能在最下面一行
  50. if (row != 2) {
  51. // 交换位置
  52. num[row][col] = num[row + 1][col]
  53. num[row + 1][col] = '22'
  54. // 更新空白方块的行
  55. row += 1
  56. }
  57. }
  58. // 左:2
  59. if (direction == 2) {
  60. // 空白方块不能在最左边一列
  61. if (col != 0) {
  62. // 交换位置
  63. num[row][col] = num[row][col - 1]
  64. num[row][col - 1] = '22'
  65. // 更新空白方块的列
  66. col -= 1
  67. }
  68. }
  69. // 右:3
  70. if (direction == 3) {
  71. // 空白方块不能在最右边一列
  72. if (col != 2) {
  73. // 交换位置
  74. num[row][col] = num[row][col + 1]
  75. num[row][col + 1] = '22'
  76. // 更新空白方块的列
  77. col += 1
  78. }
  79. }
  80. }
  81. },
  82. /**
  83. * 自定义函数--绘制画布内容
  84. */
  85. drawCanvas: function() {
  86. let ctx = this.ctx
  87. // 清空画布
  88. ctx.clearRect(0, 0, 300, 300)
  89. // 使用双重for循环语句绘制3x3拼图
  90. for (var i = 0; i < 3; i++) {
  91. for (var j = 0; j < 3; j++) {
  92. if (num[i][j] != '22') {
  93. // 获取行和列
  94. var row = parseInt(num[i][j] / 10)
  95. var col = num[i][j] % 10
  96. // 绘制方块
  97. ctx.drawImage(url, col * w, row * w, w, w, j * w, i * w, w, w)
  98. }
  99. }
  100. }
  101. ctx.draw()
  102. },
  103. /**
  104. * 自定义函数--监听点击方块事件
  105. */
  106. touchBox: function(e) {
  107. // 如果游戏已经成功,不做任何操作
  108. if (this.data.isWin) {
  109. // 终止本函数
  110. return
  111. }
  112. // 获取被点击方块的坐标x和y
  113. var x = e.changedTouches[0].x
  114. var y = e.changedTouches[0].y
  115. // console.log('x:'+x+',y:'+y)
  116. // 换算成行和列
  117. var row = parseInt(y / w)
  118. var col = parseInt(x / w)
  119. // 如果点击的不是空白位置
  120. if (num[row][col] != '22') {
  121. // 尝试移动方块
  122. this.moveBox(row, col)
  123. // 重新绘制画布内容
  124. this.drawCanvas()
  125. // 判断游戏是否成功
  126. if (this.isWin()) {
  127. // 在画面上绘制提示语句
  128. let ctx = this.ctx
  129. // 绘制完整图片
  130. ctx.drawImage(url, 0, 0)
  131. // 绘制文字
  132. ctx.setFillStyle('#e64340')
  133. ctx.setTextAlign('center')
  134. ctx.setFontSize(60)
  135. ctx.fillText('游戏成功', 150, 150)
  136. ctx.draw()
  137. }
  138. }
  139. },
  140. /**
  141. * 自定义函数--移动被点击的方块
  142. */
  143. moveBox: function(i, j) {
  144. // 情况1:如果被点击的方块不在最上方,检查可否上移
  145. if (i > 0) {
  146. // 如果方块的上方是空白
  147. if (num[i - 1][j] == '22') {
  148. // 交换当前被点击的方块和空白的位置
  149. num[i - 1][j] = num[i][j]
  150. num[i][j] = '22'
  151. return
  152. }
  153. }
  154. // 情况2:如果被点击的方块不在最下方,检查可否下移
  155. if (i < 2) {
  156. // 如果方块的下方是空白
  157. if (num[i + 1][j] == '22') {
  158. // 交换当前被点击的方块和空白的位置
  159. num[i + 1][j] = num[i][j]
  160. num[i][j] = '22'
  161. return
  162. }
  163. }
  164. // 情况3:如果被点击的方块不在最左侧,检查可否左移
  165. if (j > 0) {
  166. // 如果方块的左侧是空白
  167. if (num[i][j - 1] == '22') {
  168. // 交换当前被点击的方块和空白的位置
  169. num[i][j - 1] = num[i][j]
  170. num[i][j] = '22'
  171. return
  172. }
  173. }
  174. // 情况4:如果被点击的方块不在最右侧,检查可否右移
  175. if (j < 2) {
  176. // 如果方块的右侧是空白
  177. if (num[i][j + 1] == '22') {
  178. // 交换当前被点击的方块和空白的位置
  179. num[i][j + 1] = num[i][j]
  180. num[i][j] = '22'
  181. return
  182. }
  183. }
  184. },
  185. /**
  186. * 自定义函数--判断游戏是否成功
  187. */
  188. isWin: function() {
  189. // 使用双重for循环检查整个数组
  190. for (var i = 0; i < 3; i++) {
  191. for (var j = 0; j < 3; j++) {
  192. // 如果有方块位置不对
  193. if (num[i][j] != i * 10 + j) {
  194. // 返回假,游戏尚未成功
  195. return false
  196. }
  197. }
  198. }
  199. // 游戏成功,更新状态
  200. this.setData({
  201. isWin: true
  202. })
  203. // 返回真,游戏成功
  204. return true
  205. },
  206. /**
  207. * 自定义函数--重新开始游戏
  208. */
  209. restartGame: function() {
  210. // 更新游戏状态
  211. this.setData({
  212. isWin: false
  213. })
  214. // 打乱方块顺序
  215. this.shuffle()
  216. // 绘制画布内容
  217. this.drawCanvas()
  218. },
  219. /**
  220. * 生命周期函数--监听页面加载
  221. */
  222. onLoad: function(options) {
  223. // console.log(options.level)
  224. // 更新图片路径地址
  225. url = '/images/' + options.level
  226. // 更新提示图的地址
  227. this.setData({
  228. url: url
  229. })
  230. // 创建画布上下文
  231. this.ctx = wx.createCanvasContext("myCanvas")
  232. // 打乱方块顺序
  233. this.shuffle()
  234. // 绘制画布内容
  235. this.drawCanvas()
  236. },
  237. /**
  238. * 生命周期函数--监听页面初次渲染完成
  239. */
  240. onReady: function() {
  241. },
  242. /**
  243. * 生命周期函数--监听页面显示
  244. */
  245. onShow: function() {
  246. },
  247. /**
  248. * 生命周期函数--监听页面隐藏
  249. */
  250. onHide: function() {
  251. },
  252. /**
  253. * 生命周期函数--监听页面卸载
  254. */
  255. onUnload: function() {
  256. },
  257. /**
  258. * 页面相关事件处理函数--监听用户下拉动作
  259. */
  260. onPullDownRefresh: function() {
  261. },
  262. /**
  263. * 页面上拉触底事件的处理函数
  264. */
  265. onReachBottom: function() {
  266. },
  267. /**
  268. * 用户点击右上角分享
  269. */
  270. onShareAppMessage: function() {
  271. }
  272. })

pages\game\game.wxml

  1. <view class="container">
  2. <view class="title">
  3. 提示图
  4. </view>
  5. <image src="{
  6. {url}}"></image>
  7. <canvas canvas-id="myCanvas" bindtouchstart="touchBox"></canvas>
  8. <button type="warn" bindtap="restartGame">重新开始</button>
  9. </view>

pages\game\game.wxss

  1. /* pages/game/game.wxss */
  2. /* 提示图 */
  3. image{
  4. width: 250rpx;
  5. height: 250rpx;
  6. }
  7. /* 游戏画布区域 */
  8. canvas{
  9. border: 1rpx solid;
  10. width: 300px;
  11. height: 300px;
  12. }

pages\index\index.js

  1. Page({
  2. /**
  3. * 页面的初始数据
  4. */
  5. data: {
  6. levels:[
  7. 'pic01.jpg',
  8. 'pic02.jpg',
  9. 'pic03.jpg',
  10. 'pic04.jpg',
  11. 'pic05.jpg',
  12. 'pic06.jpg',
  13. ]
  14. },
  15. chooseLevel:function(e){
  16. let level = e.currentTarget.dataset.level
  17. wx.navigateTo({
  18. url: '../game/game?level='+level,
  19. })
  20. },
  21. /**
  22. * 生命周期函数--监听页面加载
  23. */
  24. onLoad: function (options) {
  25. },
  26. /**
  27. * 生命周期函数--监听页面初次渲染完成
  28. */
  29. onReady: function () {
  30. },
  31. /**
  32. * 生命周期函数--监听页面显示
  33. */
  34. onShow: function () {
  35. },
  36. /**
  37. * 生命周期函数--监听页面隐藏
  38. */
  39. onHide: function () {
  40. },
  41. /**
  42. * 生命周期函数--监听页面卸载
  43. */
  44. onUnload: function () {
  45. },
  46. /**
  47. * 页面相关事件处理函数--监听用户下拉动作
  48. */
  49. onPullDownRefresh: function () {
  50. },
  51. /**
  52. * 页面上拉触底事件的处理函数
  53. */
  54. onReachBottom: function () {
  55. },
  56. /**
  57. * 用户点击右上角分享
  58. */
  59. onShareAppMessage: function () {
  60. }
  61. })

pages\index\index.wxml

  1. <view class="container">
  2. <view class="title">
  3. 游戏选关
  4. </view>
  5. <view class="levelBox">
  6. <view class="box" wx:for="{
  7. {levels}}" wx:key="levels{
  8. {index}}" bindtap="chooseLevel" data-level="{
  9. {item}}">
  10. <image src="/images/{
  11. {item}}"></image>
  12. <text>第{
  13. {index+1}}关</text>
  14. </view>
  15. </view>
  16. </view>

pages\index\index.wxss

  1. /**index.wxss**/
  2. /* 关卡区域列表 */
  3. .levelBox{
  4. width: 100%;
  5. }
  6. /* 单个关卡区域 */
  7. .box{
  8. width: 50%;
  9. float: left;
  10. margin: 25rpx 0;
  11. display: flex;
  12. flex-direction: column;
  13. align-items: center;
  14. }
  15. /* 选关图片 */
  16. image{
  17. width: 260rpx;
  18. height: 260rpx;
  19. }

app.json

  1. {
  2. "pages":[
  3. "pages/index/index",
  4. "pages/game/game"
  5. ],
  6. "window":{
  7. "backgroundTextStyle":"light",
  8. "navigationBarBackgroundColor": "#E64340",
  9. "navigationBarTitleText": "拼图游戏",
  10. "navigationBarTextStyle":"black"
  11. },
  12. "style": "v2",
  13. "sitemapLocation": "sitemap.json"
  14. }

app.wxss

  1. /**app.wxss**/
  2. /* 页面容器样式 */
  3. .container{
  4. height: 100vh;
  5. color: #e64340;
  6. font-weight: bold;
  7. display: flex;
  8. flex-direction: column;
  9. align-items: center;
  10. justify-content: space-evenly;
  11. }
  12. /* 顶端标题样式 */
  13. .title{
  14. font-size: 18pt;
  15. }

app.js

  1. App({
  2. /**
  3. * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
  4. */
  5. onLaunch: function () {
  6. },
  7. /**
  8. * 当小程序启动,或从后台进入前台显示,会触发 onShow
  9. */
  10. onShow: function (options) {
  11. },
  12. /**
  13. * 当小程序从前台进入后台,会触发 onHide
  14. */
  15. onHide: function () {
  16. },
  17. /**
  18. * 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
  19. */
  20. onError: function (msg) {
  21. }
  22. })

运行截图;

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l1bmZlYXRoZXI_size_16_color_FFFFFF_t_70 1watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l1bmZlYXRoZXI_size_16_color_FFFFFF_t_70 2

发表评论

表情:
评论列表 (有 0 条评论,489人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java(拼图游戏

    目录 一、主界面分析: 二、逻辑处理 三、文件目录 四、代码 (一)游戏界面 (二)登录界面 (三)注册界面 (四)测试类代码 五、实现效果 ----

    相关 拼图游戏

    [拼图游戏][Link 1] 本文讨论如何判断拼图游戏中图形是否可以还原。 例1:下图是一个3X3的数字拼图。 <table style="width: 30%;"