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

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

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

游戏截图:

前言:

为了方便加载转移,我把整个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

用原生Canvas写贪吃蛇及问题解决的更多相关文章

  1. JavaScript原生实现《贪吃蛇》

    概述 JavaScript原生实现<贪吃蛇>,每吃掉一个食物,蛇的身体会变长,食物会重新换位置. 详细 代码下载:http://www.demodashi.com/demo/10728.h ...

  2. 原生canvas写的飞机游戏

    一个原生canvas写的飞机游戏,实用性不大,主要用于熟悉canvas的一些熟悉用法. 项目地址:https://github.com/BothEyes1993/canvas_game

  3. 用python+pygame写贪吃蛇小游戏

    因为python语法简单好上手,前两天在想能不能用python写个小游戏出来,就上网搜了一下发现了pygame这个写2D游戏的库.了解了两天再参考了一些资料就开始写贪吃蛇这个小游戏. 毕竟最开始的练手 ...

  4. C语言用面向对象的思想写贪吃蛇

    大概一年前这时候,接触C语言一个月,那时候知之甚少,对面向对象只觉”可远观而不可亵玩“,而且会看到很多言论说C语言就是面向过程的语言,C++就是面向对象的语言.不过,不记得什么时候在网上看到过一篇博文 ...

  5. pygame写贪吃蛇

    python小白尝试写游戏.. 学了点pygame不知道那什么练手好,先拿贪吃蛇开刀吧. 一个游戏可以粗略的分为两个部分: 数据(变量) 处理数据(函数,方法) 设计变量 首先预想下,画面的那些部分需 ...

  6. 原生JS制作贪吃蛇小游戏

    感情都在代码里,来,干了!... <!doctype html> <html> <head> <meta http-equiv="Content-T ...

  7. canvas 实现贪吃蛇游戏

    var canvas = document.getElementById('canvas'); var cxt = canvas.getContext('2d'); // 定时器 var timer; ...

  8. 用Js写贪吃蛇

    使用Javascript做贪吃蛇小游戏, 1.自定义地图宽高,蛇的初始速度 2.食物随机出现 3.蛇的样式属性 4.贪吃蛇玩法(吃食物,碰到边界,吃食物后加速,计分,) <!DOCTYPE ht ...

  9. 一步步教你怎么用python写贪吃蛇游戏

    目录 0 引言 1 环境 2 需求分析 3 代码实现 4 后记 0 引言 前几天,星球有人提到贪吃蛇,一下子就勾起了我的兴趣,毕竟在那个Nokia称霸的年代,这款游戏可是经典中的经典啊!而用Pytho ...

随机推荐

  1. SIP(Session Initiation Protocol,会话初始协议)

    SIP(Session Initiation Protocol,会话初始协议)的开发目的是用来帮助提供跨越因特网的高级电话业务.因特网电话(IP电话)正在向一种正式的商业电话模式演进,SIP就是用来确 ...

  2. 偏最小二乘回归(PLSR)- 2 标准算法(NIPALS)

    1 NIPALS 算法 Step1:对原始数据X和Y进行中心化,得到X0和Y0.从Y0中选择一列作为u1,一般选择方差最大的那一列. 注:这是为了后面计算方便,如计算协方差时,对于标准化后的数据,其样 ...

  3. Python操作redis系列以 哈希(Hash)命令详解(四)

    # -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host=") 1. Hset 命令用于 ...

  4. querySelector与getElementBy等的区别

    获取元素DOM对象有很多种方法,以前一直在用getElementById和getElementsByTagName等,现在对这些方法和querySelector做一个总结. 常见的获取元素的方法有3种 ...

  5. atitit.设计文档---操作日志的实现

    atitit.设计文档---操作日志的实现 日志查询 1 ----mybatis  配置... 1 添加日志 1 日志查询 <a class="l-link" href=&q ...

  6. Linux Kernel源码浏览

    https://www.kernel.org/http://lxr.linux.no/

  7. KVM部署LVS集群故障案例一则

    一.故障现象 KVM部署LVS(Linux Virtual Server)集群后,能够单独以HTTP方式访问RS(Real Server)的实际IP,但无法通过VIP(Virtual IP)访问. 二 ...

  8. angularjs 构建主页 内置过滤器、日期的格式化

    从构建负责管理主屏幕的 MainController 开始.在这个 MainController 控制器内,只需设置一个每秒运转一次,同时更新一个局部作用域变量的延时 angular.module(' ...

  9. 关于浏览器对静态HTML页面的缓存问题

    症状: 刚才为了测试TOMCAT的BASIC安全验证,修改了tomcat-users.xml和/WEB-INF/web.xml之后进行测试,<url-pattern>/*<url-p ...

  10. python文件目录操作大全

    python只获取当前目录下的文件夹及文件名 list = os.listdir(rootdir)#列出目录下的所有文件和目录 for line in list: filepath = os.path ...