操作div方块图形自动下落,若碰到容器底部则方块图形变成灰色。
实现思路
初始位置x修改为3,这样从屏幕中间下落
- 方块图形以每隔600毫秒下落20px的速度匀速下落。这个我们只要调用setInterval接口,不断地调用move(0,1)函数使得相对位置竖直方向上不断下移即可。
分析:一个方块图形下落到底部之后,相对位置应该恢复初始值,新的方块图形开始根据这个相对位置开始下落。
setInterval接口第一个参数为函数参数需要以字符串的形式,不然函数只会执行一次。
这个例子中没有停止setInterval事件,因为一旦停止那么相对位置就不会下移,就不会有自动下落。只有游戏结束的时候才需要停止setInterval事件。
intervalId= setInterval("move(0,1)",speed); //正确
intervalId= setInterval(move(0,1),speed); //错误
- 修改[Up]为方块图形旋转,[Down]为方块图形瞬间下落。
瞬间下落说白了使用setInterval函数调用move函数并且间隔设置为0毫秒,这样在极短的时间内就不断地多次下降20px然后相对位置坐标恢复初始值,看起来就像一下子完成的一样。(我们把move函数里面check函数注释掉,就可以看到方块图形超出容器继续下降。)
关键思路是,我们快速下落不要想着直接修改当前下落的速度,而是直接给相对位置再添加一个间歇性下落的方法调用,下面就是相关的分析。
注意,我们设置快速下落没有更改初始化函数里原来的匀速下落调用。而是针对相对位置(x,y)再套一个quickDown方法,这样相对位置(x,y)的下落是两个方法的速度之和。
如果不这么做,那我们要做很多琐事:
1,先把初始化函数的setInterval停止掉(因为我们无法直接修改它的间隔时间,只能停止该例并新建一个无限间歇性调用)
2,接着新建一个setInterval("move(0,1)",0);使方案图形极速下降
3,方块图形到达底部之后变成灰色,停止setInterval("move(0,1)",0)这例。
4,新的方块开始下落是以匀速下落的,所以还要创建一个setInterval("move(0,1)",speed)开始匀速下落。
方块到达底部变成灰色
就是添加一个fix获取所有var divs = document.getElementsByClassName("activityModel");(前面的方块className已经变成灰色,所以更好该方式获取的方块只是正在下落的方块)修改成灰色。
到达底部就是把相对位置重新初始化。检查方块是否变成到达底部跟前面检查是否到达边界同理可知是要添加到move函数里面。
如果没有越界就更新相对位置,并按照新的相对位置渲染方块图形
如果越界了,判断水平越界还是底部越界;如果水平越界,那么不会更新图形,自然也不会创建新的图形;如果底部越界,那么把
图形变成灰色并创建新的方块开始下落,并把极速下落那个间歇性调用停止掉。
这样就完成了,完整代码如下:
<!DOCTYPE html>
<html>
<head>
<title>Snake</title>
<style type="text/css">
.activityModel { margin: 1px; width: 19px; height: 19px;background: red;position: absolute; }
/*.container { margin: 1px; top: 0px;left: 0px; width: 200px; height: 360px; background: black; position: absolute; }*/
.stationaryModel { margin: 1px; width: 19px; height: 19px; background: gray; position: absolute; }
.container { margin: 0px; top: 0px;left: 0px; width: 201px; height: 361px; background: black; position: absolute; }
</style>
<script type="text/javascript">
var x = 3;
var y = 0;
var size = 20;
var shape = [2,0,2,1,2,2,1,2];
var rowCount=18;
var colCount=10;
var speed = 600;
var intervalId;
var intervalId2;
function init(){
create();
show(); //根据shape数组坐标排列组合创建的4个方块为方块图形
//绑定键盘事件
document.onkeydown = function(e){
var e= e || window.event;
switch(e.keyCode){
case 32: //space
quickDown();
break;
case 38: //rotate
rotate(0,-1);
break;
case 40: //down
move(0,1);
break;
case 37: //left
move(-1,0);
break;
case 39: //right
move(1,0);
break;
}
}
// 方块开始下降
intervalId = setInterval("move(0,1)",speed);
}
// 创建4个方块
var create = function(){
for (var i=0;i<4;i++){
var div = document.createElement("div");
div.className = "activityModel";
document.body.appendChild(div);
}
}
//根据shape数组坐标排列组合创建的4个方块为方块图形
var show = function(){
var divs = document.getElementsByClassName("activityModel");
for(var j=0,index=0,len=divs.length;j<len,index<8;j++){
divs[j].style.left = (shape[index++]+x)*size +"px";
divs[j].style.top = (shape[index++]+y)*size +"px";
}
}
// 移动方块
var move = function(a,b){
//如果没有越界就更新相对位置,并按照新的相对位置渲染方块图形
if(check(x+a,y+b,shape)){
x += a;
y += b;
show();
} else {
if ( b == 0 ) return;
fix();
create();
show();
clearInterval(intervalId2);
}
}
// 快速下落
var quickDown = function() {
intervalId2 = setInterval("move(0, 1)", 0);
}
// 旋转方块
var rotate = function() {
newShape = [shape[1], 3 - shape[0], shape[3], 3 - shape[2], shape[5], 3 - shape[4], shape[7], 3 - shape[6]];
if(!check(x,y,newShape)) return;
shape = newShape;
show();
}
// 固定方块,变成灰色
var fix = function(){
var divs = document.getElementsByClassName("activityModel");
for(var i = divs.length -1;i >= 0;i--){
divs[i].className = "stationaryModel";
}
x = 3;
y = 0;
}
var check = function(x,y,shape){
var most_left = colCount;
var most_right = 0;
var most_top = rowCount;
var most_bottom = 0;
for(var i=0;i<8;i+=2){
// 记录最左边水平坐标
if(shape[i]<most_left){
most_left=shape[i];
}
// 记录最右边水平坐标
if(shape[i]>most_right){
most_right=shape[i];
}
// 记录最上边垂直坐标
if(shape[i+1]<most_top){
most_top=shape[i+1];
}
// 记录最下边垂直坐标
if(shape[i+1]>most_bottom){
most_bottom=shape[i+1];
}
}
if( (most_right+x+1) > colCount || (most_left+x)< 0 || (most_bottom+y+1)>rowCount || (most_top+y)<0 ){
return false;
}
return true;
}
</script>
</head>
<body onload="init()">
<div class="container"></div>
</body>
</html>
效果图如下:
提交代码到git仓库:git push https://github.com/xiaohuacc/snake index005
代码传送门:https://github.com/xiaohuacc/snake/blob/index005/index005.html