为了学习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. Makefile之写demo时的通用Makefile写法

    Makefile之写demo时的通用Makefile写法[日期:2013-05-22] 来源:CSDN  作者:gqb666 [字体:大 中 小] 前面的一篇文章Makefile之大型工程项目子目录M ...

  2. POJ 3468 A Simple Problem with Integers 【线段树,区间更新】

    题意:你有N个整数,A1,A2,-,一个.你须要处理两种类型的操作.一种类型的操作是加入了一些给定的数字,每一个数字在一个给定的时间间隔. 还有一种是在给定的时间间隔要求数量的总和. 难点:主要是la ...

  3. XML相关转换

    1.将DataTable转换成xml字符串 //将DataTable转换成xml字符串: public string ConvertDataTableToXml(DataTable dt) { Mem ...

  4. android Handler的使用(一)

    Handler的使用(一) Handler基本概念: Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分逐个的在消息队列中将消息取出 ...

  5. SQLyog之MySQL客户端的下载、安装和使用(旗舰版)(推荐)

    不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑          ...

  6. Spring Boot 概念知识

    转 http://rapharino.com/coder/Spring-Boot-Induction/ Spring Boot Induction 发表于 2016-10-29   |   分类于 c ...

  7. Python Unicode 转换 字符串

    estimate_price = "\u00a340\u00a0\u00a0-\u00a060" sold_price = "Sold for \u00a345" ...

  8. csrf跨站请求攻击

    浅谈CSRF攻击方式    http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html

  9. Proguard语法及常用proguard.cfg代码段

    本文主要ProGuard常用语法.标准proguard.cfg文件内容.常用proguard.cfg代码段及proguard与log level结合解决debug模式日志问题. 1.ProGuard的 ...

  10. HDU 2844 Coin 多重背包

    Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...