接着上一篇讲,在上一篇中呢,我已经使用Canvas绘制出了我们游戏的主角,姑且叫它“小嘴”吧,因为只有嘴巴,嘿嘿,我还添了眼睛。

在这一篇中呢,就实现物体的移动和动画播放(一直张开嘴吧关闭嘴巴的动画,很饥渴的样子)。

1. 要做玩家和游戏的交互,当然要考虑--如何设置按键响应这个问题。

那么如何设置呢?

我们可以通过在body标签里面添加事件来响应用户的操作:

由于我们要用W,A,S,D来控制物体的上下移动,这是按键响应,于是我们选择用onkeydown事件。

onkeydown 事件:事件会在用户按下键盘按键时触发。

(上面的图片解释来自:http://www.w3school.com.cn/jsref/event_onkeydown.asp)

请注意:浏览器差异,IE使用event.KeyCode取回被按下的字符(ASCII),而火狐和欧朋使用event.Which.

2.动画:计时器和游戏循环

动画实际上就是绘制物体、擦掉,再重绘。

我们使用setInterval(functionName,timeInerval)告诉浏览器,每隔一个固定的时间间隔就调用一次给定的函数,直到函数clearInterval( )被调用.如果我们要停止动画播放(比如游戏暂停或者结束),那就调用clearInterval( )函数。

下面是源代码:(可直接复制运行)

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><title>物体移动简单演示</title>
</head>
<!--注意在body这里添加按键响应事件,引号内为函数名-->
<body οnkeydοwn="test()">
<h1>小球上下移动</h1>
<canvas id="test" width="1200px" height="600px" style="background-color: white"></canvas>
<script type="text/javascript">//得到画布var can = document.getElementById("test");var cxt = can.getContext("2d");//游戏世界原点坐标var Ox = 162;var Oy = 0;//窗口宽高var WinWidth = 900;var WinHeight = 500;//四周边界值var WinMaxX = Ox + WinWidth;var WinMinX = Ox;var WinMaxY = Oy + WinHeight;var WinMinY = Oy;//小球圆心坐标x,yvar x = 30 + Ox;var y = 30;//小球半径var radius = 20;var dir = 0;var ball = new Ball(x,y,dir,radius,3);//实例化小球对象var state = 0;//全局变量,控制张嘴闭嘴动画切换//墙壁数组,大小为3//注意js里面定义数组并且初始化的方法!//walls按x从小到大排序var walls = [new Wall(262,200,100,30),new Wall(662,60,30,400),new Wall(762,300,200,30)];//动画循环setInterval("drawBall(ball)",100);//setInterval( function(){drawBall(ball),1000});//小球类//注意js里面类的定义方法,直接类加函数参数的形式,就相当于定义了,然后里面直接this.xx=xx_,很高效//参数:x,y坐标,球的方向,球的半径,运动速度function Ball(x_,y_,dir_,r_,sp_){this.x = x_;this.y = y_;this.dir = dir_;this.r = r_;    //灰色表示还没用this.sp = sp_;//定义上下左右:0,1,2,3this.moveUp = function(){this.y -= this.sp;this.dir = 0;}this.moveDown = function(){this.y += this.sp;this.dir = 1;}this.moveLeft = function(){this.x -= this.sp;this.dir = 2;}this.moveRight = function(){this.x += this.sp;this.dir = 3;}//获得小球的坐标this.getX = function(){return this.x;}this.getY = function(){return this.y;}//获得球的各个方向的边界值this.getMaxX = function(){return this.x + this.r;}this.getMaxY = function(){return this.y + this.r;}/*** @return {number}*/this.getMinX = function(){return this.x - this.r;}/*** @return {number}*/this.getMinY = function(){return this.y - this.r;}}function Wall(x_,y_,width_,height_){this.x = x_;this.y = y_;this.width = width_;this.height = height_;this.getX = function(){return this.x;}this.getY = function(){return this.y;}this.getWidth = function(){return this.width;}this.getHeight = function(){return this.height;}}function drawBall(ball_){FreshWindow(Ox,Oy,WinWidth,WinHeight);switch (ball_.dir){case 0:drawBall_UpOrDown(ball_,true);break;case 1:drawBall_UpOrDown(ball_,false);break;case 2:drawBall_RightOrLeft(ball_,false);break;case  3:drawBall_RightOrLeft(ball_,true);break;default :break;}}function drawWall(walls_){// cxt.fillStyle="#000000";//  document.write(walls_[1].x);for(var i=0;i<walls_.length;i++){cxt.strokeRect(walls_[i].x,walls_[i].y,walls_[i].width,walls_[i].height);}}function FreshWindow(x,y,width,height){//清理画布cxt.clearRect(x,y,width,height);cxt.strokeRect(x,y,width,height);drawWall(walls);}//往右/左的样子function drawBall_RightOrLeft(ball,isRight){//document.write(state);//画眼睛,眼睛是公共的//画眼睛-外圈var eyeX;if(isRight == true)     //右eyeX = ball.x - 5;else eyeX = ball.x + 5;//左var eyeY = ball.y-8;var eyeR = 6;//目前限定死这个cxt.beginPath();cxt.fillStyle="#000000";cxt.arc(eyeX,eyeY,eyeR,0,Math.PI * 2,false);cxt.fill();cxt.closePath();//画眼睛-眼球var qiuR = eyeR / 2;cxt.beginPath();cxt.fillStyle="#FF0000";cxt.arc(eyeX,eyeY,qiuR,0,Math.PI * 2,false);cxt.fill();cxt.closePath();switch(state){//张嘴case 1://画红球cxt.beginPath();cxt.fillStyle="#FF0000";//嘴巴大小为90°//画圆弧--脸if(isRight)cxt.arc(ball.x,ball.y,radius,1/4 * Math.PI,3/2 * Math.PI + 1/4 * Math.PI,false);elsecxt.arc(ball.x,ball.y,radius,3/4 * Math.PI, Math.PI + 1/4 * Math.PI,true);cxt.stroke();cxt.closePath();cxt.beginPath();//画嘴巴var ax = 0,ay = 0;var bx = 0,by = 0;var temp = radius * Math.sqrt(2)/2;if(isRight)ax = ball.x + temp;elseax = ball.x - temp;ay = ball.y - temp;bx = ax;by = ball.y + temp;cxt.moveTo(ball.x,ball.y);cxt.lineTo(ax,ay);cxt.moveTo(ball.x,ball.y);cxt.lineTo(bx,by);cxt.closePath();cxt.stroke();state = 0;break;//闭嘴case 0://画圆弧--脸cxt.beginPath();cxt.arc(ball.x,ball.y,radius,0,Math.PI * 2,false);cxt.stroke();cxt.closePath();//从圆心到嘴巴末点的连线cxt.beginPath();cxt.moveTo(ball.x,ball.y);if(isRight)cxt.lineTo(ball.x + radius,ball.y);elsecxt.lineTo(ball.x - radius,ball.y);cxt.stroke();cxt.closePath();state = 1;break;default :break;}}//往上/下的样子function drawBall_UpOrDown(ball,isUp){//document.write(state);//画眼睛,眼睛是公共的//画眼睛-外圈var eyeX = ball.x - 5;var eyeY = ball.y + 8;if(!isUp){eyeX = ball.x + 5;eyeY = ball.y - 8;}var eyeR = 6;//目前限定死这个cxt.beginPath();cxt.fillStyle="#000000";cxt.arc(eyeX,eyeY,eyeR,0,Math.PI * 2,false);cxt.fill();cxt.closePath();//画眼睛-眼球var qiuR = eyeR / 2;cxt.beginPath();cxt.fillStyle="#FF0000";cxt.arc(eyeX,eyeY,qiuR,0,Math.PI * 2,false);cxt.fill();cxt.closePath();switch(state){//张嘴case 1://画红球cxt.beginPath();cxt.fillStyle="#FF0000";//嘴巴大小为90°//画圆弧--脸if(!isUp)cxt.arc(ball.x,ball.y,radius,1/4 * Math.PI ,3/4 * Math.PI,true);elsecxt.arc(ball.x,ball.y,radius,Math.PI +  1/4 * Math.PI,3/2 * Math.PI+  1/4 * Math.PI,true);cxt.stroke();cxt.closePath();cxt.beginPath();//画嘴巴var ax = 0,ay = 0;var bx = 0,by = 0;var temp = radius * Math.sqrt(2)/2;ax = ball.x - temp;ay = ball.y - temp;by = ay;bx = ball.x + temp;if(!isUp){ax = ball.x + temp;ay = ball.y + temp;by = ay;bx = ball.x - temp;}cxt.moveTo(ball.x,ball.y);cxt.lineTo(ax,ay);cxt.moveTo(ball.x,ball.y);cxt.lineTo(bx,by);cxt.closePath();cxt.stroke();state = 0;break;//闭嘴case 0://画圆弧--脸cxt.beginPath();cxt.arc(ball.x,ball.y,radius,0,Math.PI * 2,false);cxt.stroke();cxt.closePath();//从圆心到嘴巴末点的连线cxt.beginPath();cxt.moveTo(ball.x,ball.y);if(!isUp)cxt.lineTo(ball.x ,ball.y + radius);elsecxt.lineTo(ball.x ,ball.y- radius);cxt.stroke();cxt.closePath();state = 1;break;default :break;}}function test(){//清理画布//cxt.clearRect(0,0,400,300);var code = event.keyCode;//对应字母的ascii//alert(code);switch(code){//数字是ASCII码,记不住的话可以对照ASCII码表//上case 87:if(ball.getMinY() >= WinMinY)ball.moveUp();break;//下case 83:if(ball.getMaxY() <= WinMaxY)ball.moveDown();break;//左case 65:if(ball.getMinX() >= WinMinX)ball.moveLeft();break;//右case 68:if(ball.getMaxX() <= WinMaxX )ball.moveRight();break;default :break;}}
</script>
</body>
</html>

注意,给像和我一样的新手一个免费提示,这样写,代码越来越多,越来越乱,整个结构会越来越不清晰,于是,我把JS分割出来,这很有必要。

方法:新建xxx.js,将要移植的代码贴入,然后使用

<script type="text/javascript" src="Ball.js"></script>

将脚本引入即可。

修改过后的工程如下:

1.物体移动demo.html

<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><title>物体移动简单演示</title>
</head>
<!--注意在body这里添加按键响应事件,引号内为函数名-->
<body οnkeydοwn="test()">
<h1>小球上下移动</h1>
<canvas id="test" width="1200px" height="600px" style="background-color: white"></canvas>
<!--把Ball.js和Wall.js引入本页面-->
<script type="text/javascript" src="Ball.js"></script>
<script type="text/javascript" src="Wall.js"></script>
<script type="text/javascript">//得到画布var can = document.getElementById("test");var cxt = can.getContext("2d");//游戏世界原点坐标var Ox = 162;var Oy = 0;dddddd//窗口宽高var WinWidth = 900;var WinHeight = 500;//四周边界值var WinMaxX = Ox + WinWidth;var WinMinX = Ox;var WinMaxY = Oy + WinHeight;var WinMinY = Oy;//小球圆心坐标x,yvar x = 30 + Ox;var y = 30;//小球半径var radius = 20;var dir = 0;var ball = new Ball(x,y,dir,radius,3);//实例化小球对象var state = 0;//全局变量,控制张嘴闭嘴动画切换//墙壁数组,大小为3//注意js里面定义数组并且初始化的方法!//walls按x从小到大排序var walls = [new Wall(262,200,100,30),new Wall(662,60,30,400),new Wall(762,300,200,30)];//动画循环setInterval("drawBall(ball)",100);//setInterval( function(){drawBall(ball),1000});function FreshWindow(x,y,width,height){//清理画布cxt.clearRect(x,y,width,height);cxt.strokeRect(x,y,width,height);drawWall(walls);}function test(){//清理画布//cxt.clearRect(0,0,400,300);var code = event.keyCode;//对应字母的ascii//alert(code);switch(code){//数字是ASCII码,记不住的话可以对照ASCII码表//上case 87:if(ball.getMinY() >= WinMinY)ball.moveUp();break;//下case 83:if(ball.getMaxY() <= WinMaxY)ball.moveDown();break;//左case 65:if(ball.getMinX() >= WinMinX)ball.moveLeft();break;//右case 68:if(ball.getMaxX() <= WinMaxX )ball.moveRight();break;default :break;}}
</script>
</body>
</html>

2.Ball.js

//小球类
//注意js里面类的定义方法,直接类加函数参数的形式,就相当于定义了,然后里面直接this.xx=xx_,很高效
//参数:x,y坐标,球的方向,球的半径,运动速度
function Ball(x_,y_,dir_,r_,sp_)
{this.x = x_;this.y = y_;this.dir = dir_;this.r = r_;    //灰色表示还没用this.sp = sp_;//定义上下左右:0,1,2,3this.moveUp = function(){this.y -= this.sp;this.dir = 0;}this.moveDown = function(){this.y += this.sp;this.dir = 1;}this.moveLeft = function(){this.x -= this.sp;this.dir = 2;}this.moveRight = function(){this.x += this.sp;this.dir = 3;}//获得小球的坐标this.getX = function(){return this.x;}this.getY = function(){return this.y;}//获得球的各个方向的边界值this.getMaxX = function(){return this.x + this.r;}this.getMaxY = function(){return this.y + this.r;}/*** @return {number}*/this.getMinX = function(){return this.x - this.r;}/*** @return {number}*/this.getMinY = function(){return this.y - this.r;}}
function drawBall(ball_)
{FreshWindow(Ox,Oy,WinWidth,WinHeight);switch (ball_.dir){case 0:drawBall_UpOrDown(ball_,true);break;case 1:drawBall_UpOrDown(ball_,false);break;case 2:drawBall_RightOrLeft(ball_,false);break;case  3:drawBall_RightOrLeft(ball_,true);break;default :break;}
}
//往右/左的样子
function drawBall_RightOrLeft(ball,isRight)
{//document.write(state);//画眼睛,眼睛是公共的//画眼睛-外圈var eyeX;if(isRight == true)     //右eyeX = ball.x - 5;else eyeX = ball.x + 5;//左var eyeY = ball.y-8;var eyeR = 6;//目前限定死这个cxt.beginPath();cxt.fillStyle="#000000";cxt.arc(eyeX,eyeY,eyeR,0,Math.PI * 2,false);cxt.fill();cxt.closePath();//画眼睛-眼球var qiuR = eyeR / 2;cxt.beginPath();cxt.fillStyle="#FF0000";cxt.arc(eyeX,eyeY,qiuR,0,Math.PI * 2,false);cxt.fill();cxt.closePath();switch(state){//张嘴case 1://画红球cxt.beginPath();cxt.fillStyle="#FF0000";//嘴巴大小为90°//画圆弧--脸if(isRight)cxt.arc(ball.x,ball.y,radius,1/4 * Math.PI,3/2 * Math.PI + 1/4 * Math.PI,false);elsecxt.arc(ball.x,ball.y,radius,3/4 * Math.PI, Math.PI + 1/4 * Math.PI,true);cxt.stroke();cxt.closePath();cxt.beginPath();//画嘴巴var ax = 0,ay = 0;var bx = 0,by = 0;var temp = radius * Math.sqrt(2)/2;if(isRight)ax = ball.x + temp;elseax = ball.x - temp;ay = ball.y - temp;bx = ax;by = ball.y + temp;cxt.moveTo(ball.x,ball.y);cxt.lineTo(ax,ay);cxt.moveTo(ball.x,ball.y);cxt.lineTo(bx,by);cxt.closePath();cxt.stroke();state = 0;break;//闭嘴case 0://画圆弧--脸cxt.beginPath();cxt.arc(ball.x,ball.y,radius,0,Math.PI * 2,false);cxt.stroke();cxt.closePath();//从圆心到嘴巴末点的连线cxt.beginPath();cxt.moveTo(ball.x,ball.y);if(isRight)cxt.lineTo(ball.x + radius,ball.y);elsecxt.lineTo(ball.x - radius,ball.y);cxt.stroke();cxt.closePath();state = 1;break;default :break;}
}//往上/下的样子
function drawBall_UpOrDown(ball,isUp)
{//document.write(state);//画眼睛,眼睛是公共的//画眼睛-外圈var eyeX = ball.x - 5;var eyeY = ball.y + 8;if(!isUp){eyeX = ball.x + 5;eyeY = ball.y - 8;}var eyeR = 6;//目前限定死这个cxt.beginPath();cxt.fillStyle="#000000";cxt.arc(eyeX,eyeY,eyeR,0,Math.PI * 2,false);cxt.fill();cxt.closePath();//画眼睛-眼球var qiuR = eyeR / 2;cxt.beginPath();cxt.fillStyle="#FF0000";cxt.arc(eyeX,eyeY,qiuR,0,Math.PI * 2,false);cxt.fill();cxt.closePath();switch(state){//张嘴case 1://画红球cxt.beginPath();cxt.fillStyle="#FF0000";//嘴巴大小为90°//画圆弧--脸if(!isUp)cxt.arc(ball.x,ball.y,radius,1/4 * Math.PI ,3/4 * Math.PI,true);elsecxt.arc(ball.x,ball.y,radius,Math.PI +  1/4 * Math.PI,3/2 * Math.PI+  1/4 * Math.PI,true);cxt.stroke();cxt.closePath();cxt.beginPath();//画嘴巴var ax = 0,ay = 0;var bx = 0,by = 0;var temp = radius * Math.sqrt(2)/2;ax = ball.x - temp;ay = ball.y - temp;by = ay;bx = ball.x + temp;if(!isUp){ax = ball.x + temp;ay = ball.y + temp;by = ay;bx = ball.x - temp;}cxt.moveTo(ball.x,ball.y);cxt.lineTo(ax,ay);cxt.moveTo(ball.x,ball.y);cxt.lineTo(bx,by);cxt.closePath();cxt.stroke();state = 0;break;//闭嘴case 0://画圆弧--脸cxt.beginPath();cxt.arc(ball.x,ball.y,radius,0,Math.PI * 2,false);cxt.stroke();cxt.closePath();//从圆心到嘴巴末点的连线cxt.beginPath();cxt.moveTo(ball.x,ball.y);if(!isUp)cxt.lineTo(ball.x ,ball.y + radius);elsecxt.lineTo(ball.x ,ball.y- radius);cxt.stroke();cxt.closePath();state = 1;break;default :break;}}

3.Wall.js

function Wall(x_,y_,width_,height_)
{this.x = x_;this.y = y_;this.width = width_;this.height = height_;this.getX = function(){return this.x;}this.getY = function(){return this.y;}this.getWidth = function(){return this.width;}this.getHeight = function(){return this.height;}
}
function drawWall(walls_)
{// cxt.fillStyle="#000000";//  document.write(walls_[1].x);for(var i=0;i<walls_.length;i++){cxt.strokeRect(walls_[i].x,walls_[i].y,walls_[i].width,walls_[i].height);}
}

游戏截图:

下一篇,做游戏主角和墙壁的碰撞检测,欢迎交流,谢谢.代码粗糙,希望各位朋友指导小弟,谢谢。



HTML5吃豆豆游戏开发实战(二)主角移动和动画循环设置相关推荐

  1. HTML5吃豆豆游戏开发实战(一)使用Canvas绘制游戏主角

    近期在学习HTML5.爱因斯坦曾说过,"最好的学习就是自己去经历". 于是.我想在学习HTML5的同一时候.做一款简单的小游戏,这样学习起来也会非常有趣的.我想做的是曾经小时候玩儿 ...

  2. HTML5吃豆豆游戏开发实战(三)2d碰撞检测、重构

    今天把小球和墙壁的碰撞检测写了一下,主要就是坐标比较大小. 然后整个项目越来越大,代码越来越多,所以把准备把代码重构一下. 把代码拆分,相同功能的在一起,形成一个类,比如Collide.js,碰撞检测 ...

  3. python游戏开发实战:视频转彩色字符动画

    一.效果 原图: 转换后: 效果可通过代码开头几行的参数调节 二.代码 开头几行代码,自己看着调整,把效果调到最佳就ok. 依赖库: pip install opencv-python pip ins ...

  4. HTML5 Canvas游戏开发实战 PDF扫描版

    HTML5 Canvas游戏开发实战主要讲解使用HTML5 Canvas来开发和设计各类常见游戏的思路和技巧,在介绍HTML5 Canvas相关特性的同时,还通过游戏开发实例深入剖析了其内在原理,让读 ...

  5. 《HTML5 Canvas游戏开发实战》——2.1 绘制基本图形

    本节书摘来自华章计算机<HTML5 Canvas游戏开发实战>一书中的第2章,第2.1节,作者:张路斌著, 更多章节内容可以访问云栖社区"华章计算机"公众号查看. 2. ...

  6. HTML5游戏开发实战

    <HTML5游戏开发实战> 基本信息 原书名:HTML5 Games Development by Example: Beginner's Guide 作者: (美)Makzan 译者: ...

  7. Android开发入门——推箱子游戏开发实战(十二)

    绘制游戏局面 本文是推箱子游戏程序开发的第七步.系列文章前五篇描述准备工作,故本文编号是(十二).本文讲解如何绘制游戏局面. 本文目标 本文讲解如何绘制游戏局面.游戏局面的示例如图1,图2所示.这两幅 ...

  8. 从踩坑到填坑|淘宝Web 3D应用与游戏开发实战

    导读:本文是淘宝前端技术专家--徐乾伟(烧鹅)分享的淘宝 Web 3D 应用与游戏开发实战,这个话题在业界被谈及得比较少.今天将会从移动.3D.游戏三种交叉的话题来和大家探讨.接下来和小编一起从初试 ...

  9. 保姆级教学——Python+Pygame怎么实现吃豆豆游戏

    耽搁十几天的时间,我顺利的从阳转阴啦, 以后的日子一切恢复正常,好好工作,积极分享.希望在座的小伙伴阳了的全部健康转阴,没阳的全部不会变阳,新的一年,一切顺顺利利. 不知道最近大家学习得怎么样?有没有 ...

最新文章

  1. SpringBoot+WebSocket实时监控异常
  2. 操作主机PDC Emulator[为企业维护windows server 2008系列六]
  3. 什么是document对象?如何获取文档对象上的元素?_javascript自学记录:Document类型...
  4. anaconda安装后只有几个文件,大量文件缺失,开始栏里没有图标的解决方法
  5. 全网最详细SpringBatch读(Reader)跨多行文件讲解
  6. python使用matplotlib绘图sigmoid_使用matplotlib库绘制函数图
  7. 【Android】如何查看android cpu是32位还是64位
  8. Qt QString 与char* 相互转换
  9. 【稀疏向量技术是什么?】差分隐私系统学习记录(六)
  10. ApacheCN React 译文集 20211118 更新
  11. php中result的值,PHP 返回所取得行中字段的值
  12. rethat安装MySQL多例_SSM 使用 mybatis 分页插件 pagehepler 实现分页
  13. XSS测试平台源码——免费分享
  14. 技巧8——linux假死现象要知道
  15. 导入(excel)+导出(excel)+国际化(i18n)+
  16. 2678v3支持内存频率_你听过E5-2678 v3这款CPU吗?我用它帮朋友干了件大事!
  17. 全面屏下的沉浸式状态栏的返回键、home键、菜单键的显示。
  18. Hyperledger Fabric 2.1 BYFN 测试用例
  19. 淘宝网(taobao.com)重拳严打炒信 还期待立法介入
  20. 深圳python 培训班价格

热门文章

  1. 圆角装饰条_护角条是圆角好还是直角好
  2. 【Java】 org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor
  3. 强制打印方法,输出重定向解决
  4. uniapp 微信小程序地图,在高德app、腾讯app、百度app、苹果地图app 中打开
  5. 【SpringBoot深入浅出系列】SpringBoot之集成MyBatis-Plus
  6. 暖火柴打一数字_火柴里的天堂
  7. 云短信使用——阿里云短信使用步骤
  8. idea license server 最新可用 IntelliJ IDEA 2018.1 x64 激活 idea license server
  9. Google VP8 Code 首次深入技术分析 1
  10. Android win10 平板 省电,小编解答win10系统Mobile设置更省电的图文办法