当前位置: 代码迷 >> .NET相关 >> 用原生Canvas写贪吃蛇及有关问题解决
  详细解决方案

用原生Canvas写贪吃蛇及有关问题解决

热度:117   发布时间:2016-04-24 02:55:07.0
用原生Canvas写贪吃蛇及问题解决

为了学习Canvas,写了这个小游戏贪吃蛇供自己和大家学习

 

Github: https://github.com/zhiyishou/Gsnake

Play On: http://zhiyishou.github.io/Gsnake

 

游戏截图:

Game shooting

 

前言:

为了方便加载转移,我把整个js都写在了html里,为了方便阅读,将函数结构在html里清晰地分开,

并在代码里有足够注释。

 

函数结构如下:

|----script       |----Definations        |----Global Snake variables        |----Global Canvas variables        |----Global Panel variables        |----Global Stage variables        |----Global Game status variables    |----Init Functions        |----initPanel        |----initButtons        |----initStage        |----initCanvas        |----initMaps        |----SnakeNode        |----initSnake        |----produceSingle        |----init    |----Draw Funcitons        |----drawScore        |----drawButton        |----drawButtons        |----drawSnake        |----drawSingle        |----drawStage        |----draw    |----Action Functions        |----moveSnake        |----main    |----Event Functions        |----KeyDown        |----getOffsetPosition        |----determineButton        |----MouseMove        |----ClickButton        |----debounce        |----bind        |----Pause        |----Start        |----ReStart        |----Died    |----ROCK and ROLL        |----init()        |----main()

 

 

其中碰到的问题与解决:

一、鼠标事件问题

Canvas 中无法实现内部事件的添加和删除,准确的来说,在Canvas就是一张单纯的画布,整个Canvas才能做Dom中的事件操作

如果想在Canvas中实现内部click或mousemove等事件,有两种方案来实现:

 

1、用四周边界来确定:

  • 基于:
    1. 对Canvas绑定事件后,每当有事件发生,则计算当前鼠标相对于Canvas的坐标值;
    2. 在每个要绑定事件的对象中设定其四边边距坐标,并将其放在一个数组;
  • 触发:事件发生时则遍历整个数组,来根据坐标来判断是否在哪一个对象的边界范围内,来确定鼠标现在所在的对象。
  • 缺点:这个做的话要求对象只能是形状规整的直角四边形,对复杂图形的处理没有可实施性。

 

2、使用CanvasAPI中的isPointInPath方法:

  • 基于:
    1. (同上)对Canvas绑定事件后,每当有事件发生,则计算当前鼠标相对于Canvas的坐标值;
    2. 将要绑定事件的对象储存在数组里;
    3. isPonitInPath或isPointInStroke方法针对context上下文来判断一个坐标值是否在其Path中或上;
  • 触发:事件发生时则遍历整个数组,并重绘数组里的对象,即改变context,每绘制一个对象则context改变一次,当前的context来使用isPointInPath或isPointInStroke方法,将Offset坐标传入,来判断鼠标是否在其路径上,确定现在focus或click的对象。(canvas中的context会在closePath方法后重新设置)
  • 优点:可实现复杂的图形事件。

 

二、绘制问题

在我原先的版本中我是将整个对象操作和对象绘制设置成一个Interval来实现在,在后来的编写中就发现这样做会很死板,如果想添加或改动一些功能,则要对整个代码进行修改甚至在这种模型下无法实现。

最后还是将绘制和操作分离开来

  • 对绘制设置Interval,如:
setInterval(function(){     draw();},1000/60)    //每秒重绘60次
  • 而将绘制对象属性的改变绑定在事件上,如:

  该游戏中的Event Functions

原理:对象事件来改变对象的属性,而绘制则是用对象属性来绘制,两个逻辑各司其值,互不干预。

优点:整体程序逻辑会更清晰,更方便后续功能的新增和修改。

 

 

The End

 

1楼进击的小矮人
代码冗长,300多行的js代码。。。