admin 发表于 2023-3-1 19:08:01

【HTML5小游戏】二. 让角色动起来吧 - 添加一个可以操作的角色 ...

<h2>前情提要</h2><p>在上一节中,我们已经实现了一个永不停歇的循环,接下来就要在这个循环里添加一个角色了,最好还是可以操作的。</p><h2>先添加一个不会动的角色吧</h2><p>在上一节中,通过 fillText 方法已经在画面中增加了几行文字。不过游戏角色一般都是一些图片的集合,所以这次就要用到 drawImage 函数了。<br>如果你对 Canvas 的这些函数不甚了解,推荐你收藏一下<ahref="https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial">Canvas 教程</a>。<br>善用这个网站上方的搜索功能,随时查看那些不太熟悉的方法,把这个东西当作字典放到一边吧,等遇到不会的再查就好。</p><p>我们只用最基础的用法 <code>ctx.drawImage(image, x, y);</code><br>参数从左到右分别是:</p><ul><li>JS 的 Image(HTMLImageElement) 对象(严格来说,任何的 canvas 图像源都是可用的,这里只是举个例子)</li><li>绘制出的图片在画布上的 X 坐标</li><li>绘制出的图片在画布上的 Y 坐标</li></ul><p>图片已经准备好了,点击<ahref="https://ma-zhe.com/usr/uploads/2022/01/3862132408.png?response-content-type=application/octet-stream">这里</a>下载吧</p><p>推荐你在上一课中完成的 html 文件旁边新建一个叫 images 的文件夹,把这个图片放到里面,接下来课程里的文件路径,都是按照这个放置路径写的。</p><p>现在,把图片加载到 JS 里吧。</p><pre><code class="lang-js">// 这段代码放到 drawImg 和 update 外面,我们不需要每帧更新的时候都创建一个 Image 对象。
const image = new Image(); // 新建一个 HTMLImageElement 对象,用于 drawImage 的第一个参数
image.src = './images/mario.png'; // 把 images/mario.png 这个图片加载到 image 对象里</code></pre><p>这样就完成了,很简单对吧。接下来就是把这个图片绘制到画布里了,我们就直接把它放到画布正中央吧。<br>为了更明显的看出来角色处于画布的什么位置,这里建议先把画布换个背景色,顺便做两个辅助线</p><pre><code class="lang-js">// 这段代码请放到 drawImg 里面(这部分代码不需要在这节课掌握,只是在画辅助线,方便接下来的步骤)
ctx.fillStyle = '#E6E6FA'; // 把画笔换成一个柔和的紫色,当然你也可以换成其他你觉得顺眼的颜色
ctx.fillRect(0, 0, cvWidth, cvHeight); // 画一个填满整个画布的紫色矩形作为背景色
ctx.fillStyle = '#000'; // 把画笔切换成黑色
ctx.moveTo(cvWidth / 2, 0);
ctx.lineTo(cvWidth / 2, cvHeight);
ctx.stroke(); // 这三步是在画一条从上到下的黑色线
ctx.moveTo(0, cvHeight / 2);
ctx.lineTo(cvWidth, cvHeight / 2);
ctx.stroke(); // 这三步就是在画一条从左到右的黑色线</code></pre><p>终于可以开始画角色了!</p><pre><code class="lang-js">ctx.drawImage(image, cvWidth / 2, , cvHeight / 2); // 把角色绘制到 canvas 上</code></pre><p></p><p>额,好像和预期不一样,这个图片明显只是左上角在画布正中央。<br>没错,图片的坐标位置指的其实是它左上角那个像素所在的位置。<br>如果想要让它的中心坐标和画布的正中央重合呢?<br>其实也很简单,我们稍微计算一下左上角的像素需要偏移多少就可以了,结果如下:</p><pre><code class="lang-js">// 这段代码请放到 drawImg 里面
ctx.drawImage(image, (cvWidth - image.width) / 2, , (cvHeight - image.height) / 2); // 修正一下坐标把 image 绘制到 canvas 上</code></pre><p></p><p>终于到正中央了!</p><p>有 Canvas 基础或者认真看 <ahref="https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial">Canvas 教程</a> 的朋友可能会产生一个疑问:</p><p>文档里提到,若调用 drawImage 时,图片没装载完,其实是什么也不会发生的。因此我们应该用 load 事件来保证不会在加载完毕之前使用这个图片。<br>为什么我这里直接调用了,而没有先确保图片已经被装载完成呢?</p><p>其实道理很简单,我们有一个无限循环一直在调用 drawImage 来尝试绘制图片呢,也许在当前这个循环里它还没装载完成,导致绘制失败,但是在几秒后它装载完成后的循环里,它自然就会被绘制出来。</p><h2>让这个角色动起来</h2><p>稍等,好像走得太快了,先梳理一下这个角色在绘制时需要的数据结构吧,不然变量太松散,迟早你会忘记他们都是什么意思的。</p><h3>一个简单的角色数据结构</h3><p>先不使用 Class,就暂用一个简单的 Object 就可以了。</p><pre><code class="lang-js">// 这段代码放到 drawImg 和 update 外面,需要注意,player 引用了 cvWidth 和 cvHeight,请确保 player 的定义在这两个变量的定义之后
const player = { // 使用 player 这个 Object 来存储绘制角色需要的信息。
image: new Image(), // 角色的图像
x: cvWidth / 2, // 角色的 X 坐标
y: cvHeight / 2, // 角色的 Y 坐标
};
player.image.src = './images/mario.png';</code></pre><p>好像暂时就已经够了,现在也改一下 drawImage 吧。</p><pre><code class="lang-js">// 这段代码请放到 drawImg 里面
ctx.drawImage(player.image, player.x - player.image.width / 2, player.y - player.image.height / 2); // 只是把之前的变量替换成了 player 里的变量,没有任何区别</code></pre><p>有了 player,代码可读性也就稍微高了一些了。现在只需要修改 player 内的 x 或者 y,就可以让角色的位置发生变化了。</p><h3>监听并且记录键盘的输入</h3><p>为了能让角色相应用户的操作,我们也需要让游戏知道用户都按下了什么键<br>下面的代码就是通过监听 keydown 和 keyup 两个事件,来将用户按下的按钮记录到 keysDown 变量里。</p><pre><code class="lang-js">// 这段代码放到 drawImg 和 update 外面
const keysDown = {}; // 存储用户当前按下的按键
addEventListener(&quot;keydown&quot;, function (e) {
keysDown = true; // 当用户按下按键,就把这个按键的 code 放到 keysDown 里面
});
addEventListener(&quot;keyup&quot;, function (e) {
delete keysDown; // 当用户松开按键,就把这个按键的 code 从 kyesDown 里移除
});</code></pre><h3>根据记录的输入内容,改变角色的坐标</h3><pre><code class="lang-js">// 这段代码属于游戏逻辑,放到 update 里面吧
// 我们会使用 W S A D 来作为控制角色上下左右的操作按键
if ('KeyA' in keysDown) { // 当按键 A 被按下,就把角色的坐标向左移动
player.x += -1; // 暂时先每个循环移动 1 像素,这里是有个坑在的。上一期中提到,循环的间隔时间其实是不固定的,这里写每个循环移动 1个像素,意味着角色移动的速度也是不固定的,我们会在下一节课修复这个问题。
}
if ('KeyD' in keysDown) { // 当按键 A 被按下,就把角色的坐标向左移动
player.x += 1;
}
if ('KeyW' in keysDown) { // 当按键 A 被按下,就把角色的坐标向左移动
player.y = 1;
}
if ('KeyS' in keysDown) { // 当按键 A 被按下,就把角色的坐标向左移动
player.y = -1;
}</code></pre><p>至此,角色终于动起来了,尝试一下吧。</p><p>完整的代码点击<ahref="https://ma-zhe.com/usr/uploads/2022/01/2501367923.zip">这里</a>下载</p>
                        <div class="post-copyright">
                            <div class="alert" role="alert">最后编辑时间为: January 12th , 2022 at 09:18 am<br>本文由 <ahref="https://ma-zhe.com/index.php/author/1/">Warren Ma</a> 创作,采用 <ahref="https://creativecommons.org/licenses/by/4.0/">知识共享署名 4.0</a> 国际许可协议进行许可<br>可自由转载、引用,但需署名作者且注明文章出处</div>
                        </div>
                        <div class="post-tags"></div>
页: [1]
查看完整版本: 【HTML5小游戏】二. 让角色动起来吧 - 添加一个可以操作的角色 ...