如何用原生JavaScript实现一个简单的拼图游戏?
一、游戏的基本逻辑
如果你想用一种语言来开发游戏,首先要了解如何用这种语言来实现一些基本的逻辑,比如图像绘制、交互处理、定时器等等。
1,图形绘制图形绘制是一切的基础,这里用JavaScript在画布上绘制。也就是说,先在html中创建canvas元素,然后在JavaScript中通过id获取这个元素,通过canvas获取相应的context环境context,为后续的绘制做准备。
& ltcanvas id = " background " width = " 450 px " height = " 450 px " >& lt/canvas & gt;var background = document . getelementbyid(" background ");
var context = background . get context(' 2d ');可以通过context的drawImage方法画一张图片,相应封装:
注意:这里要等到图片加载完毕,也就是在onload中调用drawImage方法,否则绘制会失败。
var drawimage item = function(index,position) {
var img = new Image();
img.src = '。/image/dog _ 0 '+String(index+1)+'。jpg ';
img . onload =()= & gt;{
var rect = rectForPosition(position);
context.drawImage(img,rect[0],rect[1],rect[2],rect[3]);
}
画完图后,我们需要动态刷新视图,否则画布只是一张静态的图片。如果是简单的图形刷新,就在原来的位置重新画一下,盖一下就可以了。但有时我们只需要清除现有的图形,而不需要绘制新的图形。比如在拼图游戏中,一个方块移动到另一个位置后,原来的位置需要清空。
通过上下文的clearRect方法可以达到清除的目的。以下是清除画布区域的代码:
var origin rect = rectForPosition(origin);
context . clear rect(origin rect[0],originRect[1],originRect[2],origin rect[3]);2.事件处理随着图形的绘制,我们还需要处理玩家的输入事件,然后根据输入事件决定何时刷新视图。输入事件可以分为三种:手机上有触屏事件;在PC上,有鼠标和键盘事件。
JavaScript中对触摸屏和鼠标点击的监控是一样的,都是通过canvas的onclick事件回调,如下:
//屏幕点击
background . onclick = function(e){
};我们可以通过e.offsetX和e.offsety得到接触点在画布中的位置。
注意:画布的坐标原点在左上角,即左上角坐标为(0,0)。
键盘击键通过文档的onkeyup和onkeydown等事件回调。Onkeyup指的是按键的抬起事件,onkeydown指的是按键的按下事件。我们可以通过键码知道当前具体是哪个键,然后根据不同的键处理不同的逻辑,如下:
If (event.keyCode == '37') {// left
//做点什么
} else if(event . key code = = ' 38 '){//
//做点什么
} else if(event . key code = = ' 39 '){//Right
//做点什么
} else if(event . key code = = ' 40 '){//
//做点什么
}3、定时器有时候,除了玩家输入时需要刷新视图,还需要每隔一段时间刷新视图。比如一个贪吃蛇游戏,每隔一段时间就要刷新一次蛇的位置。
这时候我们就需要一个定时器每隔一段时间执行一次代码刷新视图。我们通过setInterval方法实现定时器功能:
setInterval("run()",100);上面的代码意味着每100毫秒执行一次run方法。
二、拼图的基本逻辑有游戏的基本逻辑。我们来看看如何实现拼图的逻辑。
1,生成一个随机序列因为不是任何序列都可以通过平移还原,所以我们不能简单地生成一个随机序列。比如序列1,0,2,3,4,5,6,7,8无论怎么翻译都无法还原。
这里采用的方法是:预先设定四个可约序列,从这四个序列中随机选取一个,然后对该序列进行多步模拟平移。这样就尽可能地保证了初始序列的多样性和序列的可约性。具体代码如下:
var setupRandomPosition = function(){
var list1 = [4,3,2,8,0,7,5,6,1];
var list2 = [2,0,5,6,8,7,3,1,4];
var list3 = [3,7,2,4,1,6,8,0,5];
var list4 = [3,2,4,1,7,6,5,0,8];
var lists = [list1,list2,list3,list 4];
imageIndexForPosition = lists[parse int(math . random()* 4)];
//获取空缺职位
var empty position = 0;
for(var I = imageindexforposition . length-1;我& gt= 0;我- ) {
if(imageIndexForPosition[I]= = lastIndex()){
empty position = I;
打破;
}
}
background . emptyPosition = emptyPosition;
//随机移动次数
var times = 10;
while (times - ) {
//得到一个随机数,决定把空缺移动到哪个位置。
var direction = parse int(math . random()* 4);
var target =-1;
if(方向== 0) {
target = topOfPosition(emptyPosition);//向上
} else if (direction == 1) {
target = leftOfPosition(emptyPosition);//左侧
} else if (direction == 2) {
target = rightOfPosition(emptyPosition);//右
} else if (direction == 3) {
target = bottom of position(emptyPosition);//向下
}
if(target & lt;0 | | target & gtlastIndex()) {//位置非法。继续下一个循环。
继续;
}
var result = moveImageIfCanAtPosition(target);
if(结果& gt= 0) {//如果移动成功,更新空位的位置。
emptyPosition = target
}
}
}2.判断箱子是否可以移动时,用0 ~ 8这9个数字来保存顺序,空白的箱子就是数字8的位置。所以判断是否可以移动的唯一条件就是目标位置的值是否为8。代码如下:
var isPositionEmpty =函数(位置){
if(position & lt;0 ||位置& gtlastIndex()) {
返回false
}
if(imageIndexForPosition[position]= = lastIndex()){
返回true
}否则{
返回false
}
}上面lastIndex()的值是8。
3.移动这个箱子很简单。首先清除旧位置的图形,然后在新位置绘制。
var refreshimagespositions = function(origin,target) {
var origin rect = rectForPosition(origin);
context . clear rect(origin rect[0],originRect[1],originRect[2],origin rect[3]);
draw image item(imageIndexForPosition[target],target);
}4.检查模式是否已经恢复,只需遍历一次数组,看是否有序。
var checkIfFinish = function() {
for(var index = 0;index & ltimageIndexForPosition.lengthindex++) {
如果(索引!= imageIndexForPosition[index]){
返回false
}
}
返回true
}5、交互事件屏蔽当图案恢复时,我们不希望玩家通过键盘或鼠标移动盒子。这时候就需要屏蔽交互事件了。
实现这个目标只需要一个标志位:
//屏幕点击
background . onclick = function(e){
如果(isFinish) {
返回;
}
//做点什么
};
//键盘按钮事件
document . onkeyup = function(event){
如果(isFinish) {
返回;
}
//做点什么
}图案恢复后,标志位isFinish会被设置为true,然后在屏幕点击和键盘按键响应事件开始时添加一个判断。如果结束了,盒子移动的逻辑就不继续了。