最近自己写了一个俄罗斯方块的小程序,基本处理完了所有BUG,尽量做到了代码简洁、功能完善,目前感觉唯一不太完美的地方是下键的短按和长按效果,完整源码如下:
WXML(使用了weui组件库的图标)
1 <view class='container'> 2 <view class="flex output"> 3 <view>分数:{{score}}</view> 4 <view>等级:{{speed}}</view> 5 <view>最高分:{{maxScore}}</view> 6 </view> 7 <view class='map'> 8 <view wx:for="{{newMap}}" wx:for-item="rows" class='flex'> 9 <view wx:for="{{rows}}" class='block block{{item}}'></view> 10 </view> 11 </view> 12 <view class="flex control"> 13 <view> 14 <view class="flex button"> 15 <mp-icon type="field" icon="back2" color="#FF0000" size="{{80}}" data-dir="left" bindlongpress="longPress" bindtap="horTap" bindtouchend="touchEnd" /> 16 <mp-icon extClass="icon-right" type="field" icon="back2" color="#FF0000" size="{{80}}" data-dir="right" bindlongpress="longPress" bindtap="horTap" bindtouchend="touchEnd" /> 17 </view> 18 <view class="center"> 19 <mp-icon extClass="icon-down" type="field" icon="back2" color="#FF0000" size="{{80}}" data-dir="down" bindlongpress="longPress" bindtap="downTap" bindtouchend="touchEnd" /> 20 </view> 21 </view> 22 <view> 23 <view class="center"> 24 <mp-icon type="field" icon="{{icon}}" color="#FF0000" size="{{60}}" bindtap="play" /> 25 </view> 26 <view> 27 <view wx:for="{{newNextMap}}" wx:for-item="rows" class='flex'> 28 <view wx:for="{{rows}}" class='block-next block{{item}}'></view> 29 </view> 30 </view> 31 </view> 32 <view> 33 <mp-icon type="field" icon="refresh" color="#FF0000" size="{{100}}" bindtap="rotateBlock" /> 34 </view> 35 </view>
WXSS
1 .map { 2 margin-top: 30rpx; 3 } 4 .flex { 5 display: flex; 6 } 7 .output { 8 width: 90%; 9 justify-content: space-between; 10 } 11 .block { 12 width: 50rpx; 13 height: 50rpx; 14 border: 1px solid #eee; 15 background: #000; 16 } 17 .block1 { 18 background: green; 19 } 20 .control { 21 margin-top: 20rpx; 22 justify-content: space-between; 23 align-items: center; 24 } 25 .center { 26 text-align: center; 27 } 28 .button { 29 justify-content: space-between 30 } 31 .icon-right { 32 transform: rotate(180deg); 33 } 34 .icon-down { 35 transform: rotate(-90deg); 36 } 37 .block-next { 38 width: 30rpx; 39 height: 30rpx; 40 border: 1px solid #eee; 41 }
JS
1 Page({ 2 data: { 3 //地图大小 4 mapSize: [18, 10], 5 //地图 6 map: [], 7 newMap: [], 8 nextMap: [], 9 newNextMap: [], 10 //方块 11 block: [], 12 nextBlock: [], 13 //游戏状态 14 icon: '', 15 status: '', 16 timer: null, 17 quickTimer: null, 18 speed: 1, 19 score: 0, 20 maxScore: 0, 21 //方块位置 22 blockPos: [0, 0], 23 //七种方块 24 blocks: [ 25 [[1, 0], [1, 1], [1, 2], [2, 1]], 26 [[1, 1], [2, 1], [3, 1], [3, 2]], 27 [[1, 2], [2, 2], [3, 1], [3, 2]], 28 [[1, 0], [1, 1], [2, 1], [2, 2]], 29 [[1, 1], [1, 2], [2, 0], [2, 1]], 30 [[1, 1], [1, 2], [2, 1], [2, 2]], 31 [[0, 1], [1, 1], [2, 1], [3, 1]] 32 ] 33 }, 34 onl oad(options) { 35 let maxScore = 0 36 if (wx.getStorageSync("tetrisScore")) { 37 maxScore = wx.getStorageSync("tetrisScore") 38 } 39 //初始化地图 40 let map = this.initMap(this.data.mapSize) 41 let nextMap = this.initMap([4, 4]) 42 //随机一个方块 43 let nextBlock = this.data.blocks[Math.floor(Math.random() * 7)] 44 this.setData({ 45 map: map, 46 newMap: map, 47 nextMap: nextMap, 48 newNextMap: nextMap, 49 nextBlock: nextBlock, 50 icon: 'play', 51 status: 'stop', 52 score: 0, 53 speed: 1, 54 maxScore: maxScore 55 }) 56 }, 57 //初始化地图 58 initMap: function (size) { 59 let map = [] 60 for (let i = 0; i < size[0]; i++) { 61 let rows = [] 62 for (let j = 0; j < size[1]; j++) { 63 rows.push(0) 64 } 65 map.push(rows) 66 } 67 return map 68 }, 69 //初始化方块 70 initBlock: function () { 71 //随机方向 72 let block = this.rotateFun(this.data.nextBlock, Math.floor(Math.random() * 4)) 73 //移到中间 74 this.moveFun(block, [-3, 3], 0) 75 //生成下一个方块 76 let nextBlock = this.data.blocks[Math.floor(Math.random() * 7)] 77 //更新小图 78 let newNextMap = JSON.parse(JSON.stringify(this.data.nextMap)) 79 for (let item of nextBlock) { 80 newNextMap[item[0]][item[1]] = 1 81 } 82 this.setData({ 83 block: block, 84 nextBlock: nextBlock, 85 newNextMap: newNextMap 86 }) 87 }, 88 play: function () { 89 let icon, status = this.data.status 90 if (status == 'play') { 91 icon = 'play' 92 status = 'pause' 93 clearInterval(this.data.timer) 94 } else { 95 if (status == 'stop') { 96 this.initBlock() 97 } 98 this.fallFun() 99 icon = 'pause' 100 status = 'play' 101 } 102 this.setData({ 103 icon: icon, 104 status: status 105 }) 106 }, 107 //下落方法 108 fallFun: function () { 109 let that = this 110 this.data.timer = setInterval(function () { 111 that.moveFun(that.data.block, that.posFun(that.data.blockPos, 'down'), 1) 112 }, (21 - that.data.speed) * 50) 113 }, 114 //左、右短按 115 horTap: function (e) { 116 if (this.data.status == 'play') { 117 this.moveFun(this.data.block, this.posFun(this.data.blockPos, e.currentTarget.dataset.dir)) 118 } 119 }, 120 //下短按 121 downTap: function () { 122 if (this.data.status == 'play') { 123 let that = this 124 let i = 0 125 let timer = setInterval(function () { 126 that.moveFun(that.data.block, that.posFun(that.data.blockPos, 'down')) 127 i++ 128 if (i >= 5) clearInterval(timer) 129 }, 10) 130 } 131 }, 132 //长按 133 longPress: function (e) { 134 if (this.data.status == 'play') { 135 let that = this 136 this.data.quickTimer = setInterval(function () { 137 that.moveFun(that.data.block, that.posFun(that.data.blockPos, e.currentTarget.dataset.dir)) 138 }, 10) 139 } 140 }, 141 //按键手指移开 142 touchEnd: function (e) { 143 clearInterval(this.data.quickTimer) 144 }, 145 //计算移动后坐标 146 posFun: function (pos, dir) { 147 let newPos = [] 148 switch (dir) { 149 case 'left': 150 newPos = [pos[0], pos[1] - 1] 151 break; 152 case 'right': 153 newPos = [pos[0], pos[1] + 1] 154 break; 155 case 'down': 156 newPos = [pos[0] + 1, pos[1]] 157 break; 158 } 159 return newPos 160 }, 161 //移动方法,type:0初始移到中间,1正常下落 162 moveFun: function (block, pos, type) { 163 let m = pos[0], n = pos[1] 164 let mapSize = this.data.mapSize 165 let maxX = m, reLoop = true 166 let map = JSON.parse(JSON.stringify(this.data.map)) 167 for (let index = 0; index < block.length; index++) { 168 let i = block[index][0] + m, j = block[index][1] + n 169 //超出边界,或已有方块,取消移动 170 if (i >= mapSize[0] || j < 0 || j >= mapSize[1] || (i >= 0 && map[i][j] == 1) == 1) { 171 if (type == 1) { 172 clearInterval(this.data.timer) 173 //游戏结束 174 if (map[0][j] == 1) { 175 let scroe = this.data.score 176 wx.showModal({ 177 title: '游戏结束', 178 content: '得分:' + scroe, 179 showCancel: false, 180 }) 181 if (scroe > this.data.maxScore) wx.setStorageSync("tetrisScore", scroe) 182 this.onLoad() 183 return false 184 } 185 //消除 186 let newMap = this.data.newMap 187 loop: for (let a = mapSize[0] - 1; a >= 0; a--) { 188 for (let val of newMap[a]) { 189 if (val == 0) continue loop 190 } 191 newMap.splice(a, 1) 192 } 193 let len = mapSize[0] - newMap.length 194 for (let a = 0; a < len; a++) { 195 let row = [] 196 for (let b = 0; b < mapSize[1]; b++) { 197 row.push(0) 198 } 199 newMap.unshift(row) 200 } 201 //初始化方块 202 let score = this.data.score 203 if (len > 0) score += (len * 100 - 50) 204 let speed = parseInt(score / 1000) + 1 205 if (speed > 20) speed = 20 206 this.setData({ 207 map: newMap, 208 score: score, 209 speed: speed 210 }) 211 this.initBlock() 212 this.fallFun() 213 } 214 return false 215 } 216 if (type == 0) { 217 if (reLoop) { 218 //计算方块最大横坐标 219 if (i > maxX) maxX = i 220 //开始下一次循环 221 if (index == block.length - 1) { 222 index = -1 223 reLoop = false 224 } 225 continue 226 } 227 if (maxX > m) i -= maxX 228 } 229 //移动到新位置 230 if (i >= 0) map[i][j] = 1 231 } 232 this.setData({ 233 blockPos: [(maxX > m ? m - maxX : m), n], 234 newMap: map 235 }) 236 return true 237 }, 238 //按键转动 239 rotateBlock: function (e) { 240 if (this.data.status == 'play') { 241 let block = this.rotateFun(this.data.block, 1) 242 if (this.moveFun(block, this.data.blockPos)) { 243 this.setData({ 244 block: block 245 }) 246 } 247 } 248 }, 249 //顺时针旋转方块 250 rotateFun: function (block, m) { 251 if (m > 0) { 252 let newBlock = [] 253 for (let i in block) { 254 newBlock.push(this.rotateRe(block[i], m)) 255 } 256 return newBlock 257 } 258 return block 259 }, 260 rotateRe: function (arr, m) { 261 arr = [arr[1], 3 - arr[0]] 262 if (m == 1) 263 return arr 264 return this.rotateRe(arr, m - 1) 265 }, 266 onUnload() { 267 clearInterval(this.data.timer) 268 } 269 })
标签:function,map,status,程序,动手,let,方块,data,block From: https://www.cnblogs.com/desertion/p/17883631.html