原文地址:http://www.script-tutorials.com/html5-game-development-lesson-4/

这篇文章是我们继续使用canvas来进行HTML5游戏开发系列的文章,我们要学习下一个元素:精灵动画和基本的声音处理。在我们这个示例中,你将看见一直正在飞的龙,我们能一直听见它翅膀扇动的声音,当鼠标释放事件发生时还有龙咆哮的声音。最后我们将教会龙移动到鼠标按下处。

前一篇的的介绍在HTML5游戏开发系列教程3(译)

第一步:HTML

index.html

 <!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="utf-8" />
<title>HTML5 Game Development - Lesson 4 | Script Tutorials</title> <link href="css/main.css" rel="stylesheet" type="text/css" /> <!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" src="js/script.js"></script>
</head>
<body>
<div class="container">
<canvas id="scene" width="1000" height="600"></canvas>
</div> <footer>
<h2>HTML5 Game Development - Lesson 4</h2>
<a href="http://www.script-tutorials.com/html5-game-development-lesson-4/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
</footer>
</body>
</html>

第二步:CSS

css/main.css

这次我将不会写出css的代码了--它仅仅是页面布局设计样式而已,没有啥特殊的,可以从源代码包中获取。

第三步:JS

js/script.js

 // 内部变量
var canvas, ctx;
var backgroundImage;
var iBgShiftX = 100;
var dragon;
var dragonW = 75; // 龙的宽度
var dragonH = 70; // 龙的高度
var iSprPos = 0; // 龙的初始动画帧
var iSprDir = 4; // 龙的初始方向(朝左)
var dragonSound; // 龙的声音
var wingsSound; // 翅膀声音
var bMouseDown = false; //鼠标是否按下
var iLastMouseX = 0; //鼠标移动前一个位置的x坐标
var iLastMouseY = 0; //鼠标移动前一个位置的y坐标
// ------------------------------------------------------------- // objects :
function Dragon(x, y, w, h, image) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.image = image;
this.bDrag = false;
}
// ------------------------------------------------------------- // 清除整个画布
function clear() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
} //画整个屏幕
function drawScene() {
clear(); // 清楚画布 // 画背景图片
iBgShiftX -= 4;
if (iBgShiftX <= 0) {
iBgShiftX = 1045;
}
ctx.drawImage(backgroundImage, 0 + iBgShiftX, 0, 1000, 940, 0, 0, 1000, 600); // update sprite positions
iSprPos++;
if (iSprPos >= 9) {
iSprPos = 0;
} // 一旦鼠标按下,龙就朝那个方向移动
if (bMouseDown) {
if (iLastMouseX > dragon.x) {
dragon.x += 5;
}
if (iLastMouseY > dragon.y) {
dragon.y += 5;
}
if (iLastMouseX < dragon.x) {
dragon.x -= 5;
}
if (iLastMouseY < dragon.y) {
dragon.y -= 5;
}
} // draw dragon
ctx.drawImage(dragon.image, iSprPos*dragon.w, iSprDir*dragon.h, dragon.w, dragon.h, dragon.x - dragon.w/2, dragon.y - dragon.h/2, dragon.w, dragon.h);
} // ------------------------------------------------------------- // initialization
$(function(){
canvas = document.getElementById('scene');
ctx = canvas.getContext('2d'); var width = canvas.width;
var height = canvas.height; // 加载背景图片
backgroundImage = new Image();
backgroundImage.src = 'images/hell.jpg';
backgroundImage.onload = function() {
}
backgroundImage.onerror = function() {
console.log('Error loading the background image.');
} // 龙声音初始化
dragonSound = new Audio('media/dragon.wav');
dragonSound.volume = 0.9; // 翅膀声音初始化
wingsSound = new Audio('media/wings.wav');
wingsSound.volume = 0.9;
wingsSound.addEventListener('ended', function() { // 循环播放翅膀扇动的声音
this.currentTime = 0;
this.play();
}, false);
wingsSound.play(); //龙的初始化
var oDragonImage = new Image();
oDragonImage.src = 'images/dragon.gif';
oDragonImage.onload = function() {
}
dragon = new Dragon(400, 300, dragonW, dragonH, oDragonImage); $('#scene').mousedown(function(e) { // binding mousedown event (for dragging)
var mouseX = e.layerX || 0;
var mouseY = e.layerY || 0;
if(e.originalEvent.layerX) { // changes for jquery 1.7
mouseX = e.originalEvent.layerX;
mouseY = e.originalEvent.layerY;
} bMouseDown = true; if (mouseX > dragon.x- dragon.w/2 && mouseX < dragon.x- dragon.w/2 +dragon.w &&
mouseY > dragon.y- dragon.h/2 && mouseY < dragon.y-dragon.h/2 +dragon.h) { dragon.bDrag = true;
dragon.x = mouseX;
dragon.y = mouseY;
}
}); $('#scene').mousemove(function(e) { // binding mousemove event
var mouseX = e.layerX || 0;
var mouseY = e.layerY || 0;
if(e.originalEvent.layerX) { // changes for jquery 1.7
mouseX = e.originalEvent.layerX;
mouseY = e.originalEvent.layerY;
} // 保存最后移动的坐标
iLastMouseX = mouseX;
iLastMouseY = mouseY; // 拖动龙
if (dragon.bDrag) {
dragon.x = mouseX;
dragon.y = mouseY;
} // 根据鼠标的位置改变龙的方向
if (mouseX > dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) { //右
iSprDir = 0;
} else if (mouseX < dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) { //左
iSprDir = 4;
} else if (mouseY > dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) { //下
iSprDir = 2;
} else if (mouseY < dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) { //上
iSprDir = 6;
} else if (mouseY < dragon.y && mouseX < dragon.x) { //左上
iSprDir = 5;
} else if (mouseY < dragon.y && mouseX > dragon.x) { //右上
iSprDir = 7;
} else if (mouseY > dragon.y && mouseX < dragon.x) { //左下
iSprDir = 3;
} else if (mouseY > dragon.y && mouseX > dragon.x) { //右下
iSprDir = 1;
}
}); $('#scene').mouseup(function(e) { // binding mouseup event
dragon.bDrag = false;
bMouseDown = false; // 播放龙的声音
dragonSound.currentTime = 0;
dragonSound.play();
}); setInterval(drawScene, 30); // loop drawScene
});

程序是怎样实现的:首先我们定义了画布,上下文,然后加载了背景图片,两个声音,再初始化我们的龙和绑定了不同的鼠标事件。在我们主循环重绘方法中,我移动了背景图片,并更新了帧的位置,最后画龙。在我们的代码里你可以发现几个有趣的方法:

  1. 循环背景音乐:

     // 翅膀声音初始化
    wingsSound = new Audio('media/wings.wav');
    wingsSound.volume = 0.9;
    wingsSound.addEventListener('ended', function() { // 循环播放翅膀扇动的声音
    this.currentTime = 0;
    this.play();
    }, false);
    wingsSound.play();
  2. Draw sprites
         var oDragonImage = new Image();
    oDragonImage.src = 'images/dragon.gif';
    oDragonImage.onload = function() {
    }
    ....
    // update sprite positions
    iSprPos++;
    if (iSprPos >= 9) {
    iSprPos = 0;
    } // draw dragon(剪切图像)
    ctx.drawImage(dragon.image, iSprPos*dragon.w, iSprDir*dragon.h, dragon.w, dragon.h, dragon.x - dragon.w/2, dragon.y - dragon.h/2, dragon.w, dragon.h);

所以是这样的,我们加载原始的图片(有许多子图像的图片),然后剪切图片的一部分内容用来显示,再移动它的位置,接着循环这样画。

源代码下载地址:http://www.script-tutorials.com/demos/186/source.zip

下面介绍:context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);  参考:http://www.w3school.com.cn/html5/canvas_drawimage.asp

该方法主要剪切图像,并在画布上定位被剪切的部分

参数说明:

参数 描述
img 规定要使用的图像、画布或视频。
sx 可选。开始剪切的 x 坐标位置。
sy 可选。开始剪切的 y 坐标位置。
swidth 可选。被剪切图像的宽度。
sheight 可选。被剪切图像的高度。
x 在画布上放置图像的 x 坐标位置。
y 在画布上放置图像的 y 坐标位置。
width 可选。要使用的图像的宽度。(伸展或缩小图像)
height 可选。要使用的图像的高度。(伸展或缩小图像)

HTML5游戏开发系列教程4(译)的更多相关文章

  1. HTML5游戏开发系列教程7(译)

    原文地址:http://www.script-tutorials.com/html5-game-development-lesson-7/ 今天我们将完成我们第一个完整的游戏--打砖块.这次教程中,将 ...

  2. HTML5游戏开发系列教程6(译)

    原文地址:http://www.script-tutorials.com/html5-game-development-lesson-6/ 这是我们最新一篇HTML5游戏开发系列文章.我们将继续使用c ...

  3. HTML5游戏开发系列教程5(译)

    原文地址:http://www.script-tutorials.com/html5-game-development-lesson-5/ 最终我决定准备下一篇游戏开发系列的文章,我们将继续使用can ...

  4. HTML5游戏开发系列教程8(译)

    原文地址:http://www.script-tutorials.com/html5-game-development-lesson-8/ 这是我们最新一篇HTML5游戏开发系列文章.我们将继续使用c ...

  5. HTML5游戏开发系列教程10(译)

    原文地址:http://www.script-tutorials.com/html5-game-development-lesson-10/ 最后我们将继续使用canvas来进行HTML5游戏开发系列 ...

  6. HTML5游戏开发系列教程9(译)

    原文地址:http://www.script-tutorials.com/html5-game-development-lesson-9/ 今天我们将继续使用canvas来进行HTML5游戏开发系列的 ...

  7. cocos2d-x游戏开发系列教程-前言

    cocos2d-x游戏开发前景: 最近企业对于Cocos2D-X开发人才的用人需求很大,而且所提供的薪资相当可观. 为满足广大向往游戏开发行业同学的需求,特推出适合新手的Cocos2D-X手游开发教程 ...

  8. cocos2d-x游戏开发系列教程-超级玛丽07-CMGameMap

    背景 在上一篇博客中,我们提到CMGameScene,但是CMGameScene只是个框架,实际担任游戏逻辑的是CMGameMap类,这个博文就来了解下CMGameMap 头文件 class CMGa ...

  9. cocos2d-x游戏开发系列教程-超级玛丽06-CMGameScene

    背景 在CMMenuScene中,当用户点击开始游戏时,导演让场景进入到CMGameScene 头文件 class CMGameScene : public cocos2d::CCLayer,publ ...

随机推荐

  1. thymeleaf教程

    本教程涵盖了常见的前端操作,比如,判断,循环,引入模板,常用函数(日期格式化,字符串操作)下拉,js和css中使用,基本可以应对一般场景. 怎么使用? 前端html页面标签中引入如下: <htm ...

  2. EF报LINQ to Entities 不识别方法“Web_JZRepository.Models.copy_materials_details get_Item(Int32) ”,因此该方法无法转换为存储表达式。

    说明用了如 List<T> list=new List<T>(); je.copy_materials_details.SingleOrDefault(x => x.ID ...

  3. mysql关联取附表最后一条记录,附加lareval orm实现

    MySQL 多表关联一对多查询取最新的一条数据:https://blog.csdn.net/u013902368/article/details/86615382 Laravel query buil ...

  4. Linux命令之乐--script和scriptplay

    script和scriptplay可以把终端会话记录到一个文件中,可以用来制作命令行教学视屏. 开始录制会话 [root@new test]# script -t >timing.log -a ...

  5. SensorManager

    光照传感器 Android 中每个传感器的用法其实都比较类似,真的可以说是一通百通了.首先第一步要获取到 SensorManager 的实例 SensorManager senserManager = ...

  6. Excel表导出

     前言 分别介绍两种导出Exce表格的方法和读取Excel表格数据方法. 1.在MVC下的表格导出. 2.基于NPOI的表格导出. 3.读取Excel表格数据. 第一种方法:在MVC下的表格导出. 首 ...

  7. 学习ASP.NET MVC3(6)----- Filte

    前言 在开发大项目的时候总会有相关的AOP面向切面编程的组件,而MVC(特指:Asp.Net MVC,以下皆同)项目中不想让MVC开发人员去关心和写类似身份验证,日志,异常,行为截取等这部分重复的代码 ...

  8. 170413、怎么精确理解leader布置的任务(技术外的话)

    [缘起] 和一个同学交代了一个很重要的事情,结果执行的结果并不是自己想要的,微微生气之余,简单的聊聊“如何精确的理解leader布置的任务”. [员工角度的潜在困惑] 1)leader讲了很多,脑子记 ...

  9. ZOJ3690—Choosing number

    题目链接:https://vjudge.net/problem/ZOJ-3690 题目意思: 有n个人,每个人可以从m个数中选取其中的一个数,而且如果两个相邻的数相同,则这个数大于等于k,问这样的数一 ...

  10. explain(desc)命令的使用

    获取 type:查询类型 1.可以判断出,全表扫描还是索引扫描(ALL就是全表扫描,其他就是索引扫描) 2.对于索引扫描来讲,可以西划分,可以判断是哪一种扫描 type的具体类型介绍: ALL:全表扫 ...