俄罗斯方块源码分享 html+css+js
【摘要】 效果:
【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)