原文地址:http://www.script-tutorials.com/html5-game-development-lesson-4/
这篇文章是我们继续使用canvas来进行HTML5游戏开发系列的文章,我们要学习下一个元素:精灵动画和基本的声音处理。在我们这个示例中,你将看见一直正在飞的龙,我们能一直听见它翅膀扇动的声音,当鼠标释放事件发生时还有龙咆哮的声音。最后我们将教会龙移动到鼠标按下处。
前一篇的的介绍在HTML5游戏开发系列教程3(译)。
第一步:HTML
index.html
1 <!DOCTYPE html> 2 <html lang="en" > 3 <head> 4 <meta charset="utf-8" /> 5 <title>HTML5 Game Development - Lesson 4 | Script Tutorials</title> 6 7 <link href="css/main.css" rel="stylesheet" type="text/css" /> 8 9 <!--[if lt IE 9]> 10 <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> 11 <![endif]--> 12 <script src="http://code.jquery.com/jquery-latest.min.js"></script> 13 <script type="text/javascript" src="js/script.js"></script> 14 </head> 15 <body> 16 <div class="container"> 17 <canvas id="scene" width="1000" height="600"></canvas> 18 </div> 19 20 <footer> 21 <h2>HTML5 Game Development - Lesson 4</h2> 22 <a href="http://www.script-tutorials.com/html5-game-development-lesson-4/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a> 23 </footer> 24 </body> 25 </html>
第二步:CSS
css/main.css
这次我将不会写出css的代码了--它仅仅是页面布局设计样式而已,没有啥特殊的,可以从源代码包中获取。
第三步:JS
js/script.js
1 // 内部变量 2 var canvas, ctx; 3 var backgroundImage; 4 var iBgShiftX = 100; 5 var dragon; 6 var dragonW = 75; // 龙的宽度 7 var dragonH = 70; // 龙的高度 8 var iSprPos = 0; // 龙的初始动画帧 9 var iSprDir = 4; // 龙的初始方向(朝左) 10 var dragonSound; // 龙的声音 11 var wingsSound; // 翅膀声音 12 var bMouseDown = false; //鼠标是否按下 13 var iLastMouseX = 0; //鼠标移动前一个位置的x坐标 14 var iLastMouseY = 0; //鼠标移动前一个位置的y坐标 15 // ------------------------------------------------------------- 16 17 // objects : 18 function Dragon(x, y, w, h, image) { 19 this.x = x; 20 this.y = y; 21 this.w = w; 22 this.h = h; 23 this.image = image; 24 this.bDrag = false; 25 } 26 // ------------------------------------------------------------- 27 28 // 清除整个画布 29 function clear() { 30 ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); 31 } 32 33 //画整个屏幕 34 function drawScene() { 35 clear(); // 清楚画布 36 37 // 画背景图片 38 iBgShiftX -= 4; 39 if (iBgShiftX <= 0) { 40 iBgShiftX = 1045; 41 } 42 ctx.drawImage(backgroundImage, 0 + iBgShiftX, 0, 1000, 940, 0, 0, 1000, 600); 43 44 // update sprite positions 45 iSprPos++; 46 if (iSprPos >= 9) { 47 iSprPos = 0; 48 } 49 50 // 一旦鼠标按下,龙就朝那个方向移动 51 if (bMouseDown) { 52 if (iLastMouseX > dragon.x) { 53 dragon.x += 5; 54 } 55 if (iLastMouseY > dragon.y) { 56 dragon.y += 5; 57 } 58 if (iLastMouseX < dragon.x) { 59 dragon.x -= 5; 60 } 61 if (iLastMouseY < dragon.y) { 62 dragon.y -= 5; 63 } 64 } 65 66 // draw dragon 67 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); 68 } 69 70 // ------------------------------------------------------------- 71 72 // initialization 73 $(function(){ 74 canvas = document.getElementById('scene'); 75 ctx = canvas.getContext('2d'); 76 77 var width = canvas.width; 78 var height = canvas.height; 79 80 // 加载背景图片 81 backgroundImage = new Image(); 82 backgroundImage.src = 'images/hell.jpg'; 83 backgroundImage.onload = function() { 84 } 85 backgroundImage.onerror = function() { 86 console.log('Error loading the background image.'); 87 } 88 89 // 龙声音初始化 90 dragonSound = new Audio('media/dragon.wav'); 91 dragonSound.volume = 0.9; 92 93 // 翅膀声音初始化 94 wingsSound = new Audio('media/wings.wav'); 95 wingsSound.volume = 0.9; 96 wingsSound.addEventListener('ended', function() { // 循环播放翅膀扇动的声音 97 this.currentTime = 0; 98 this.play(); 99 }, false); 100 wingsSound.play(); 101 102 //龙的初始化 103 var oDragonImage = new Image(); 104 oDragonImage.src = 'images/dragon.gif'; 105 oDragonImage.onload = function() { 106 } 107 dragon = new Dragon(400, 300, dragonW, dragonH, oDragonImage); 108 109 $('#scene').mousedown(function(e) { // binding mousedown event (for dragging) 110 var mouseX = e.layerX || 0; 111 var mouseY = e.layerY || 0; 112 if(e.originalEvent.layerX) { // changes for jquery 1.7 113 mouseX = e.originalEvent.layerX; 114 mouseY = e.originalEvent.layerY; 115 } 116 117 bMouseDown = true; 118 119 if (mouseX > dragon.x- dragon.w/2 && mouseX < dragon.x- dragon.w/2 +dragon.w && 120 mouseY > dragon.y- dragon.h/2 && mouseY < dragon.y-dragon.h/2 +dragon.h) { 121 122 dragon.bDrag = true; 123 dragon.x = mouseX; 124 dragon.y = mouseY; 125 } 126 }); 127 128 $('#scene').mousemove(function(e) { // binding mousemove event 129 var mouseX = e.layerX || 0; 130 var mouseY = e.layerY || 0; 131 if(e.originalEvent.layerX) { // changes for jquery 1.7 132 mouseX = e.originalEvent.layerX; 133 mouseY = e.originalEvent.layerY; 134 } 135 136 // 保存最后移动的坐标 137 iLastMouseX = mouseX; 138 iLastMouseY = mouseY; 139 140 // 拖动龙 141 if (dragon.bDrag) { 142 dragon.x = mouseX; 143 dragon.y = mouseY; 144 } 145 146 // 根据鼠标的位置改变龙的方向 147 if (mouseX > dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) { //右 148 iSprDir = 0; 149 } else if (mouseX < dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) { //左 150 iSprDir = 4; 151 } else if (mouseY > dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) { //下 152 iSprDir = 2; 153 } else if (mouseY < dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) { //上 154 iSprDir = 6; 155 } else if (mouseY < dragon.y && mouseX < dragon.x) { //左上 156 iSprDir = 5; 157 } else if (mouseY < dragon.y && mouseX > dragon.x) { //右上 158 iSprDir = 7; 159 } else if (mouseY > dragon.y && mouseX < dragon.x) { //左下 160 iSprDir = 3; 161 } else if (mouseY > dragon.y && mouseX > dragon.x) { //右下 162 iSprDir = 1; 163 } 164 }); 165 166 $('#scene').mouseup(function(e) { // binding mouseup event 167 dragon.bDrag = false; 168 bMouseDown = false; 169 170 // 播放龙的声音 171 dragonSound.currentTime = 0; 172 dragonSound.play(); 173 }); 174 175 setInterval(drawScene, 30); // loop drawScene 176 });
程序是怎样实现的:首先我们定义了画布,上下文,然后加载了背景图片,两个声音,再初始化我们的龙和绑定了不同的鼠标事件。在我们主循环重绘方法中,我移动了背景图片,并更新了帧的位置,最后画龙。在我们的代码里你可以发现几个有趣的方法:
- 循环背景音乐:
1 // 翅膀声音初始化 2 wingsSound = new Audio('media/wings.wav'); 3 wingsSound.volume = 0.9; 4 wingsSound.addEventListener('ended', function() { // 循环播放翅膀扇动的声音 5 this.currentTime = 0; 6 this.play(); 7 }, false); 8 wingsSound.play();
- Draw sprites
1 var oDragonImage = new Image(); 2 oDragonImage.src = 'images/dragon.gif'; 3 oDragonImage.onload = function() { 4 } 5 .... 6 // update sprite positions 7 iSprPos++; 8 if (iSprPos >= 9) { 9 iSprPos = 0; 10 } 11 12 // draw dragon(剪切图像) 13 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 | 可选。要使用的图像的高度。(伸展或缩小图像) |