首先我们需要知道

每一个游戏都是由:

A:获得用户输入

B:更新游戏状态

C:处理AI

D:播放音乐和音效

E:画面显示

这些行为组成。游戏主循环就是用来处理这个行为序列,在javascript中可以用setInterval方法来轮询。在超级玛丽中是这个循环

   //主循环var mainLoop=setInterval(function(){//距上一次执行相隔的时间.(时间变化量), 目前可近似看作sleep.var deltaTime=sleep;// 更新Animation状态animation.update(deltaTime);//使用背景覆盖的方式 清空之前绘制的图片context.drawImage(ImgCache["bg"],0,0);//绘制Animationanimation.draw(context, x,y);},sleep);

如何去做到让游戏角色进行移动呢?今天这里只学习让玩家在原地进行移动,也就是step3_1

实现人物移动的方法就是:将精灵图片的不同动作图片,在画布上同一位置交替显示,就形成了人物原地移动的动画。在画布的不同的位置显示动作图片,就形成了人物在画布上来回移动的动画。

首先实现炸弹人在画布上原地移动,显示移动动画;

了解精灵图片含义:所谓精灵图片就是包含多张小图片的一张大图片,使用它可以减少http请求,提升性能。

第一步:实现人物的显示

首先,要显示玩家角色。需要创建画布并获得上下文,加载缓存图像,调用StartDemo,然后是清空画布区域,使用drawImage来绘制图片。

// 页面初始化函数
function init(){// 创建canvas,并初始化 (我们也可以直接以标签形式写在页面中,然后通过id等方式取得canvas)canvas=document.createElement("canvas");canvas.width=600;canvas.height=400;document.body.appendChild(canvas);// 取得2d绘图上下文 context= canvas.getContext("2d");//加载图片,并存入全局变量 ImgCache, // 加载完成后,调用startDemoImgCache=loadImage( [ {  id : "player",url : "../res/player.png"},{  id : "bg",url : "../res/bg.png"}], startDemo );}

第二步:游戏的帧数FPS=30

每秒所运行的帧数。游戏主循环每33.3(1000/30)ms轮询一次

FPS决定游戏画面更新的频率,决定主循环的快慢。

主循环中的间隔时间sleep与FPS有一个换算公式:

间隔时间 = 就近最大取整(1000 / FPS),不同于四舍五入,也叫向下取整

    // 一些简单的初始化, var FPS=30;var sleep=Math.floor(1000/FPS);//初始坐标var x=0, y=284;

第三步:使用帧动画

一些基本要理解的知识:

动画是通过绘制一组帧图片来实现的。具体实现时有这些关键问题:

  • 一组帧应该以怎样的顺序来绘制?
  • 如何控制每一帧绘制的时间?
  • 在画布的什么位置绘制帧?
  • 如何控制绘制的帧的内容、图片大小?
策略:帧动画控制类Animation
// Animation类.动画类
// cfg为Object类型的参数集, 其属性会覆盖Animation原型中定义的同名属性.
function Animation(cfg){for (var attr in cfg ){this[attr]=cfg[attr];}
}Animation.prototype={constructor :Animation ,// Animation 包含的Frame, 类型:数组frames : null,// 包含的Frame数目frameCount : -1 ,// 所使用的图片id(在ImgCache中存放的Key), 字符串类型. img : null,// 当前播放的 framecurrentFrame : null ,// 当前播放的帧currentFrameIndex : -1 ,// 已经播放的时间currentFramePlayed : -1 ,// 初始化Animationinit : function(){// 根据id取得Image对象this.img = ImgCache[this.img]||this.img;this.frames=this.frames||[];this.frameCount = this.frames.length;// 缺省从第0帧播放this.currentFrameIndex=0;this.currentFrame=this.frames[this.currentFrameIndex];this.currentFramePlayed=0;},// 更新Animation状态. deltaTime表示时间的变化量.update : function(deltaTime){//判断当前Frame是否已经播放完成, if (this.currentFramePlayed>=this.currentFrame.duration){//播放下一帧if (this.currentFrameIndex >= this.frameCount-1){//当前是最后一帧,则播放第0帧this.currentFrameIndex=0;}else{//播放下一帧this.currentFrameIndex++;}//设置当前帧信息this.currentFrame=this.frames[ this.currentFrameIndex ];this.currentFramePlayed=0;}else{//增加当前帧的已播放时间.this.currentFramePlayed += deltaTime;}},//绘制Animationdraw : function(gc,x,y){var f=this.currentFrame;gc.drawImage(this.img, f.x , f.y, f.w, f.h , x, y, f.w, f.h );}
};

Animation负责读取、配置、更新帧数据,控制帧数据的播放

读取:

创建一个Animation对象:

  // 创建一个Animation对象var animation = new Animation({img : "player" ,//该动画由3帧构成,对应图片中的第一行.frames : [{x : 0, y : 0, w : 50, h : 60, duration : 100},{x : 50, y : 0, w : 50, h : 60, duration : 100},{x : 100, y : 0, w : 50, h : 60, duration : 100}]} );
function Animation(cfg){for (var attr in cfg ){this[attr]=cfg[attr];}
}

// Animation类.动画类
// cfg为Object类型的参数集, 其属性会覆盖Animation原型中定义的同名属性.

配置:

初始化Animation对象:

    // 初始化Animationanimation.init();

初始化函数代码:

  // 初始化Animationinit : function(){// 根据id取得Image对象this.img = ImgCache[this.img]||this.img;this.frames=this.frames||[];this.frameCount = this.frames.length;// 缺省从第0帧播放this.currentFrameIndex=0;this.currentFrame=this.frames[this.currentFrameIndex];this.currentFramePlayed=0;},

更新帧数据:

      // 更新Animation状态animation.update(deltaTime);

更新函数代码:

   // 更新Animation状态. deltaTime表示时间的变化量.update : function(deltaTime){//判断当前Frame是否已经播放完成, if (this.currentFramePlayed>=this.currentFrame.duration){//播放下一帧if (this.currentFrameIndex >= this.frameCount-1){//当前是最后一帧,则播放第0帧this.currentFrameIndex=0;}else{//播放下一帧this.currentFrameIndex++;}//设置当前帧信息this.currentFrame=this.frames[ this.currentFrameIndex ];this.currentFramePlayed=0;}else{//增加当前帧的已播放时间.this.currentFramePlayed += deltaTime;}},

播放:

就是绘制帧动画:

      //绘制Animationanimation.draw(context, x,y);
  //绘制Animationdraw : function(gc,x,y){var f=this.currentFrame;gc.drawImage(this.img, f.x , f.y, f.w, f.h , x, y, f.w, f.h );}

再来看帧动画播放需要掌握的那些知识点:

1.一组帧应该以怎样的顺序进行播放

        // 缺省从第0帧播放this.currentFrameIndex=0;

2.如何控制每一帧的绘制时间:

当 当前帧 播放没有完成的时候:

           //增加当前帧的已播放时间.this.currentFramePlayed += deltaTime;

当 当前帧 播放完成的时候:

this.currentFramePlayed=0;

3.在画布的什么位置开始绘制:

  //绘制Animationdraw : function(gc,x,y){var f=this.currentFrame;gc.drawImage(this.img, f.x , f.y, f.w, f.h , x, y, f.w, f.h );}

4.如何控制绘制的帧的内容、图片大小:

帧内容:首先是一个数组 frames[],其次是当前播放的帧 currentFrame : null ,

初始化时控制操作:

this.currentFrame=this.frames[this.currentFrameIndex];

currentFrameIndex : -1 ,可以看作是一个索引

更新的时候:

          //设置当前帧信息this.currentFrame=this.frames[ this.currentFrameIndex ];

最后提供源代码:

<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />
<meta http-equiv="Cache-Control" content="no-cache" /><title>My first Game</title><style type="text/css">
body {border:none 0px;margin:0px;padding:10px;font-size : 16px;background-color : #f3f3f3;
}canvas {border : 1px solid blue;
}
</style><script type="text/javascript">// 加载图片
function loadImage(srcList,callback){var imgs={};var totalCount=srcList.length;var loadedCount=0;for (var i=0;i<totalCount;i++){var img=srcList[i];var image=imgs[img.id]=new Image();      image.src=img.url;image.οnlοad=function(event){loadedCount++;}      }if (typeof callback=="function"){var Me=this;function check(){if (loadedCount>=totalCount){callback.apply(Me,arguments);}else{        setTimeout(check,100);} }check();}return imgs;
}//定义全局对象
var ImgCache=null;
var canvas=null;
var context=null;// 页面初始化函数
function init(){// 创建canvas,并初始化 (我们也可以直接以标签形式写在页面中,然后通过id等方式取得canvas)canvas=document.createElement("canvas");canvas.width=600;canvas.height=400;document.body.appendChild(canvas);// 取得2d绘图上下文 context= canvas.getContext("2d");//加载图片,并存入全局变量 ImgCache, // 加载完成后,调用startDemoImgCache=loadImage( [ {  id : "player",url : "../res/player.png"},{  id : "bg",url : "../res/bg.png"}], startDemo );}// Animation类.动画类
// cfg为Object类型的参数集, 其属性会覆盖Animation原型中定义的同名属性.
function Animation(cfg){for (var attr in cfg ){this[attr]=cfg[attr];}
}Animation.prototype={constructor :Animation ,// Animation 包含的Frame, 类型:数组frames : null,// 包含的Frame数目frameCount : -1 ,// 所使用的图片id(在ImgCache中存放的Key), 字符串类型. img : null,// 当前播放的 framecurrentFrame : null ,// 当前播放的帧currentFrameIndex : -1 ,// 已经播放的时间currentFramePlayed : -1 ,// 初始化Animationinit : function(){// 根据id取得Image对象this.img = ImgCache[this.img]||this.img;this.frames=this.frames||[];this.frameCount = this.frames.length;// 缺省从第0帧播放this.currentFrameIndex=0;this.currentFrame=this.frames[this.currentFrameIndex];this.currentFramePlayed=0;},// 更新Animation状态. deltaTime表示时间的变化量.update : function(deltaTime){//判断当前Frame是否已经播放完成, if (this.currentFramePlayed>=this.currentFrame.duration){//播放下一帧if (this.currentFrameIndex >= this.frameCount-1){//当前是最后一帧,则播放第0帧this.currentFrameIndex=0;}else{//播放下一帧this.currentFrameIndex++;}//设置当前帧信息this.currentFrame=this.frames[ this.currentFrameIndex ];this.currentFramePlayed=0;}else{//增加当前帧的已播放时间.this.currentFramePlayed += deltaTime;}},//绘制Animationdraw : function(gc,x,y){var f=this.currentFrame;gc.drawImage(this.img, f.x , f.y, f.w, f.h , x, y, f.w, f.h );}
};// Demo的启动函数
function startDemo(){// 一些简单的初始化, var FPS=30;var sleep=Math.floor(1000/FPS);//初始坐标var x=0, y=284;// 创建一个Animation对象var animation = new Animation({img : "player" ,//该动画由3帧构成,对应图片中的第一行.frames : [{x : 0, y : 0, w : 50, h : 60, duration : 100},{x : 50, y : 0, w : 50, h : 60, duration : 100},{x : 100, y : 0, w : 50, h : 60, duration : 100}]} );// 初始化Animationanimation.init();//主循环var mainLoop=setInterval(function(){//距上一次执行相隔的时间.(时间变化量), 目前可近似看作sleep.var deltaTime=sleep;// 更新Animation状态animation.update(deltaTime);//使用背景覆盖的方式 清空之前绘制的图片context.drawImage(ImgCache["bg"],0,0);//绘制Animationanimation.draw(context, x,y);},sleep);}</script></head>
<body οnlοad="init()"> <div align="center"><a href="http://www.linuxidc.com" target="_blank">www.Linuxidc.com</a></div>
</body>
</html>

超级玛丽HTML5源代码学习------(四)相关推荐

  1. html超级玛丽游戏源码,超级玛丽HTML5源代码学习------(一)

    My first Game body { /** 边框:无 0像素 */ border:none 0px; /** 边外补白:向外填充0像素 */ margin:0px; /** 向内填充:向内填充0 ...

  2. Nmap 源代码学习四 软件简单使用

    软件安装环境是win7.使用Zenmap, nmap6.49BETA2 扫描主机port nmap -T4 -A -v 192.168.0.207 输出结果: 扫描整个子网 nmap 192.168. ...

  3. BT源代码学习心得(四):种子文件的生成 -- 转贴自wolfenstein (NeverSayNever)

    BT源代码学习心得(四):种子文件的生成 author: wolfenstein 在知道种子文件采取的编码方式后,我们现在可以来看一个种子文件具体是如何生成的了.在BT中,生成种子文件的可执行模块是 ...

  4. BT源代码学习心得(四):种子文件的生成

    BT源代码学习心得(四):种子文件的生成 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(四):种子文件的生成 发信站: 水木社区 (We ...

  5. HTML5+CSS3的学习(四)

    HTML5+CSS3的学习(中) 2018版李立超html+css基础 103集教程,哔哩哔哩链接:https://www.bilibili.com/video/BV1sW411T78k?spm_id ...

  6. Silverlight/Windows8/WPF/WP7/HTML5周学习导读(8月5日-8月12日)

    Silverlight/Windows8/WPF/WP7/HTML5周学习导读(8月5日-8月12日) 本周Silverlight学习资源更新 Silverlight设计时特性的使用 _eagle S ...

  7. 分享Silverlight/Windows8/WPF/WP7/HTML5周学习导读(5月27日-6月3日)

    分享Silverlight/Windows8/WPF/WP7/HTML5周学习导读(5月27日-6月3日) 本周Silverlight学习资源更新 XAML实例教程系列 - 命名空间(NameSpac ...

  8. Silverlight/Windows8/WPF/WP7/HTML5周学习导读(9月3日-9月9日)

    Silverlight/Windows8/WPF/WP7/HTML5周学习导读(9月3日-9月9日) 本周Silverlight学习资源更新 Silverlight删除数据表格中的数据,表格头部定义全 ...

  9. Silverlight/Windows8/WPF/WP7/HTML5周学习导读(6月25日-7月1日)

    Silverlight/Windows8/WPF/WP7/HTML5周学习导读(6月25日-7月1日) 本周Silverlight学习资源更新 用Silverlight做淘宝应用 往事如锋 基于 Si ...

最新文章

  1. 数字图像处理1:基本概念
  2. 加密与解密以及openssl的应用
  3. 几种常见信号波形变换电路
  4. Topcoder SRM 628 DIV 2
  5. usb转ttl_[开源]双TYPEC转TTL串口模块
  6. 面试刷题7:int和Integer有什么区别?
  7. postgresql 执行计划理解
  8. hibernate使用sql进行查询
  9. 国际云安全证书CCSK让他们在职场中脱颖而出
  10. 迭代最近邻ICP算法
  11. 如何利用福禄克OFP2-100-Q CH测试光纤的熔接损耗
  12. Ubuntu使用代理服务器上网
  13. 从2009到2020,世界编程语言排行榜分析
  14. 你有反馈,我们安排!Sketch 插件升级,新老对比一图看懂
  15. 槃星—第1天任务—植物大战僵尸游戏数据修改(Hex Editor Neo)
  16. Java暑期实训任务二——单词检测程序
  17. 基于蓝牙5(BTIoT-5)的物联网架构
  18. 【NA】矩阵特征值的雅可比方法
  19. 【并行计算-CUDA开发】GPU 的硬体架构 关于存储体的介绍比较好bank conflicts
  20. Java面向对象(2).抽象类和接口

热门文章

  1. Java基础 -> 笔记整合(eDiary),蓝奏云下载
  2. 关于中小型银行建设集中征信服务中心的必要性
  3. linux 安装mysql8
  4. c语言中gets全拼,25英文【25英文英语头条】- 25英文知识点 - 中企动力
  5. 贾跃亭被法院列入“老赖”黑名单,这下真成“下周回国假药停”了?
  6. DSS:甲基化差异分析
  7. 从U盘启动Linux后拔出U盘,U盘安装LINUX系统,拔除U盘后无法引导系统
  8. MT4之提醒功能及MT4登录正常但不能交易
  9. 解决“只能通过Chrome网上应用商店安装该程序”的方法
  10. Lazarus下WinCE调试