俄罗斯方块源码分享 html+css+js

举报
北极光之夜。 发表于 2021/04/20 01:03:40 2021/04/20
【摘要】 效果: 【html+css+js】俄罗斯方块源码分享 这是在网上跟着黑马的视频做的,然后也加了些自己的想法。 在线试玩:http://www.beijiguang.site/game/index.html 完整代码: 直接复制用的换个背景视频地址就行~ 核心 js 部分都有解析。 <!DOCTYPE html> <html lang="zh-CN...

效果:

【html+css+js】俄罗斯方块源码分享

这是在网上跟着黑马的视频做的,然后也加了些自己的想法。
在线试玩:http://www.beijiguang.site/game/index.html

完整代码:

直接复制用的换个背景视频地址就行~
核心 js 部分都有解析。

<!DOCTYPE html>
<html lang="zh-CN">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script> <style> *{ margin: 0; padding: 0; box-sizing: border-box; } body{ height: 100vh; display: flex; justify-content: center; align-items: center; } .container{ position: relative; width: 280px; height: 504px; /*  background-image: url(star.jpg); background-size: 100% 100%; */ box-shadow: 0 0 5px rgb(218, 218, 218), 0 0 10px rgb(151, 151, 151); backdrop-filter: blur(3px); background-color: rgba(0, 0, 0,.2); } .mark{ font-family: 'fangsong'; position: absolute; height: 50px; width: 150px; bottom: 50px; right: -150px; text-align: center; color: rgb(197, 197, 197); line-height: 50px; font-size: 25px; user-select: none; } .again{ font-family: 'fangsong'; position: absolute; height: 30px; width: 100px; right: -125px; bottom: 10px; line-height: 30px; text-align: center; box-shadow: inset 0 0 10px white; color: rgb(255, 255, 255); cursor: pointer; border-radius: 5px; user-select: none; } .again:hover{ background-color: rgb(21, 168, 29); } .kuai{ position: absolute; width: 28px; height: 28px; /* border: 0.1px solid rgb(0, 0, 0); */ } .ding{ position: absolute; width: 28px; height: 28px; background-color: rgb(243, 243, 243); } video{ position: fixed; width: 100%; height: 100%; object-fit: cover; z-index: -10; } h1{ position: fixed; top: 50%; left: 50%; transform: translate(-50%,-50%); font-size: 100px; font-family: 'fangsong'; color: rgb(1, 175, 255); text-shadow: 0 0 10px rgb(1, 175, 255), 0 0 15px rgb(1, 175, 255), 0 0 20px rgb(1, 175, 255); } </style>
</head>
<body onload="rukou()"> <video src="11.mp4" autoplay muted loop></video> <h1>北极光之夜</h1> <div class="container" id="container"> <!--  <div class="kuai"></div> --> <div class="mark">分数:0 </div> <div class="again">再来一局</div> </div> <script> /* 显示分数 */ var mark = document.querySelector(".mark"); /* 分数变量 */ var marks = 0; /* 再来一局 */ var again = document.querySelector(".again"); /* 常量,不可修改 */ /* 一次走的距离 */ var STEP = 28; /* 容器一共18行,10列 */ var ROW_COUNT = 18 , COL_COUNT = 10; /* 记录所有出现的块元素的位置 k=行_列 :v=块元素 */ var fixedBlocks = {} /* 创建每个模型的数据源 */ var MODELS = [ /* L型模型,里面每个盒子相对16宫格的坐标 */ { 0:{row:2,col:0}, 1:{row:2,col:1}, 2:{row:2,col:2}, 3:{row:1,col:2} }, // 第2个模型数据源(凸) { 0: { row: 1, col: 1 }, 1: { row: 0, col: 0 }, 2: { row: 1, col: 0 }, 3: { row: 2, col: 0 } }, // 第3个模型数据源(田) { 0: { row: 1, col: 1 }, 1: { row: 2, col: 1 }, 2: { row: 1, col: 2 }, 3: { row: 2, col: 2 } }, // 第4个模型数据源(一) { 0: { row: 0, col: 0 }, 1: { row: 0, col: 1 }, 2: { row: 0, col: 2 }, 3: { row: 0, col: 3 } }, // 第5个模型数据源(Z) { 0: { row: 1, col: 1 }, 1: { row: 1, col: 2 }, 2: { row: 2, col: 2 }, 3: { row: 2, col: 3 } } ] /* 变量,当前使用的模型 */ var currentModel = {} /* 变量,16宫格的位置 */ var currentX = 0 , currentY = 0; /* 根据模型数据源来创建块元素 */ function createModel() { /* 判断满足游戏结束条件没 */ if(isGameOver()){ ganmeOver(); return; } /* 先确定创建哪个模型 */ currentModel = MODELS[_.random(0,MODELS.length -1)]; /* 重新初始化16宫格的位置 */ currentX=0; currentY=0; /* 来个随机颜色 */ let color = new Array("#FF1493","#FF00FF","#0000FF","	#1E90FF","#00FFFF","#00FF7F","#00FF00","#FFFF00","#FF6600"); let yanse = color[Math.floor(Math.random() * color.length)]; /* 遍历对象,生成数量的块元素 */ for(var key in currentModel){ var divKuai = document.createElement("div"); divKuai.className = "kuai";
/* divKuai.style.backgroundColor = color ; */ divKuai.style.cssText = `box-shadow: inset 0 0 5px ${yanse}, inset 0 0 10px ${yanse}, inset 0 0 15px ${yanse}; border: 1px solid ${yanse};` document.getElementById("container").appendChild(divKuai); } /* 定位 */ locationBlocks(); /* 自动下落 */ autoDown(); } /* 根据创建好的块元素给他定位位置,生成相应的模型 */ function locationBlocks(){ /* 判断越界 */ checkBound(); /* 得到当前所有块元素 */ var blocks = document.getElementsByClassName("kuai"); for(var i=0;i<blocks.length;i++ ){ /* 每个块元素 */ var oneBlock = blocks[i]; /* 得到每个块元素的坐标,16宫格位置加上本身相对16宫格位置 */ var locationKuai = currentModel[i]; oneBlock.style.top = (locationKuai.row+currentY) * STEP + "px"; oneBlock.style.left = (locationKuai.col+currentX) * STEP + "px"; } } /*  入口方法 */ function rukou (){ onKeyDown(); createModel(); } /* 用户点击键盘事件 */ function onKeyDown(){ document.addEventListener('keydown',function(event){ switch(event.keyCode){ case 38: console.log("shang"); rotate(); break; case 39: console.log("you"); move(1,0); break; case 40: console.log("xia"); move(0,1); break; case 37: console.log("zuo"); move(-1,0); break; } }) } /* 移动函数 */ function move(x,y){ /* 判断触碰,就是判断活动中的模型将要移动到的位置是否存在已经固定的模型(块元素) */ if(isMeet(currentX + x , currentY + y , currentModel)){ /* 若发生触碰,且由y轴引起,那么说明模型的底部发生触碰了,那么该停下了 */ if(y!==0){ fixedBottomModel(); } /* 直接return掉move方法,不再执行 */ return; } /* 移动16宫格 */ currentX = currentX + x; currentY = currentY + y; locationBlocks(); } /* 旋转模型函数 */ function rotate(){ // 克隆一下 currentModel  用引入的js文件里的方法 var cloneCurrentModel = _.cloneDeep(currentModel); /* 算法:移动后的行=移动前的列  移动后的列=3-移动前的行 */ /* 得到当前使用的模型数据源里的块元素的坐标 */ for(var key in cloneCurrentModel){ var blocksModel = cloneCurrentModel[key]; /* 实现算法进行变换 */ let temp = blocksModel.row; blocksModel.row = blocksModel.col; blocksModel.col = 3 - temp; } /* 判断触碰,就是判断活动中的模型将转的地方是否存在已经固定的模型(块元素) */ if(isMeet(currentX,currentY,cloneCurrentModel)){ return; } /* 接收了这次旋转 */ currentModel = cloneCurrentModel; locationBlocks(); } /* 控制模型只能在游戏区域里移动 */ function checkBound(){ /* 模型可活动的边界 */ var leftBound = 0,rightBound = COL_COUNT,bottomBound = ROW_COUNT; /* 当块元素超出边界后,让16宫格退一步,这样一走一退相互抵消 */ for(var key in currentModel){ var blocksModel = currentModel[key]; /* 左侧边界 */ if((blocksModel.col+currentX)<leftBound) { currentX++; } /* 右侧边界 */ if((blocksModel.col+currentX)>=rightBound){ currentX--; } /* 底侧边界 */ if((blocksModel.row+currentY)>=bottomBound){ currentY--; /* 固定在底部 */ fixedBottomModel(); } } } /* 当模型到达底部时固定在底部 */ function fixedBottomModel(){ /* 1.改变模型颜色样式 */ var activityModels = document.getElementsByClassName("kuai"); /* 因为js特效,要从后往前遍历 */ for(var i=activityModels.length-1;i>=0;i--){ var activityModel = activityModels[i]; /* 让其不再移动,改变类名就行,这样位置函数将对其无效了 */ activityModel.className = "ding"; /* 把其放在记录块元素位置的变量中 */ var blocksModel = currentModel[i]; fixedBlocks[(currentY+blocksModel.row)+"_"+(currentX+blocksModel.col)]=activityModel; } /* 判断一行是否被铺满 */ isRemoveLine(); /* 创建新模型 */ createModel(); } /* 判断模型之间的触碰问题 */ /* x,y为16宫格将要去到的位置,model表示当前模型将要完成的变化 */ function isMeet(x,y,model){ /* 判断触碰,就是判断活动中的模型将要移动到的位置是否存在已经固定的模型(块元素) */ /* 该位置是否存在块元素? 只有一个return会生效*/ for(var k in model) { var blockModel = model[k]; if(fixedBlocks[(y+blockModel.row)+"_"+(x+blockModel.col)]){ return true; } } return false; } /* 判断一行是否被铺满 */ function isRemoveLine(){ /* 判断某行中,每一列是否都存在块元素,是则清理 */ /* 遍历所有行所有列 */ for(var i=0;i<ROW_COUNT;i++){ /* 假设当前行铺满,设flag=true */ var flag = true; for(var j=0;j<COL_COUNT;j++){ /* 当前行没铺满 */ if(!fixedBlocks[i + "_" + j]){ flag = false; break; } } /* 当某行铺满,flag==true */ if(flag){ removeLine(i); } } } /* 清理被铺满的一行 */ function removeLine(line){ /* 删除该行的块元素 */ for(var i=0;i<COL_COUNT;i++){ document.getElementById("container").removeChild(fixedBlocks[line+"_"+i]); /* 数据源也删除 */ fixedBlocks[line+"_"+i] = null; } downLine(line); /* 加分数 */ marks++; mark.innerHTML = "分数:" + marks ; } /* 被清理行上面的块元素下落 */ function downLine(line){ /* 遍历被清理行上的所有行 */ for(var i = line-1;i>=0;i--){ /* 该行的所有列 */ for(var j=0;j<COL_COUNT;j++){ if(!fixedBlocks[i+"_"+j]) continue; /* 被清理行上面的块元素数据源所在行数+1 */ fixedBlocks[(i+1)+"_"+j] = fixedBlocks[i+"_"+j]; /* 让块元素下落 */ fixedBlocks[(i+1)+"_"+j].style.top = (i+1)*STEP+'px'; /* 清理之前块元素 */ fixedBlocks[i+"_"+j] = null; } } } /* 模型自动下落 */ var mInterval = null; function autoDown(){ if(mInterval){ clearInterval(mInterval); } mInterval = setInterval(function(){ move(0,1); },500) } /* 判断游戏结束 */ function isGameOver(){ /* 第0行也有元素时结束游戏 */ for(var i=0;i<COL_COUNT;i++){ if(fixedBlocks["0_" + i]){ return true; } } return false; } /* 结束游戏 */ function ganmeOver(){ /* 停止定时器 */ if(mInterval){ clearInterval(mInterval); } /* 弹出对话框 */ alert("游戏结束!   分数为:"+marks+"。"); } /* 点击再来一局 */ again.addEventListener('click',function(){ /* 简单粗暴直接刷新好吧 */ location.reload(true); }) </script>

</body>
</html>

  
  
 
 
  • 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
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493

文章来源: blog.csdn.net,作者:北极光之夜。,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/luo1831251387/article/details/115035806

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。