上一章讲述第一关关卡数据生成和其他砖块的生成,本章很简单,即马里奥前进和后退动画以及其他一些动画
本章的提交ID:f40f389f06e2ed056949023c5b9c1e78bd3255d3
github地址:ainuo5213的超级马里奥
本节目录
目录讲解:
1. animation.js:帧动画的创建函数文件,用于帧动画中对应动画帧的图片切片函数
2. sprite/mario.json: 马里奥相关的参数,例如马里奥帧动画,马里奥长宽等
本节实现效果:
入口文件改动
入口文件删除了对于调试相关layer的代码
Layer文件改动
layer文件增加对于帧动画切片的layer创建分支,时期能够渲染帧动画
Level关卡文件变化
Level对象增加了totalTime,用于计时当前已经用掉的时间,该时间用来更新奖励砖块的帧动画
Loader加载器文件改动
loader加载器加入了对马里奥和其他带有动画的帧配置进行了兼容存储
mario马里奥文件改动
马里奥中加入了获取当前马里奥运动的帧动画函数,用于渲染对应帧动画状态下的马里奥
UnitStyleSheet文件改动
文件改动较多,这里以代码进行展示。文件变动加入了`定义存储帧动画`、`渲染帧动画`,将原本渲染tile的方法加入了正反渲染两种,用来兼容渲染马里奥运动方向的正反绘制,实现帧动画
export default class UnitStyleSheet {
/**
* 创建一个图像样式定义对象
* @param {HTMLImageElement} image 背景图像
* @param {number} width 单位图像宽度
* @param {number} height 单位图像高度
*/
constructor(image, width, height) {
this.image = image;
this.width = width;
this.height = height;
this.tiles = new Map();
this.animations = new Map();
}
/**
* 绘制动画
* @param {string} name 动画名
* @param {any} animation 动画回调函数
*/
defineAnim(name, animation) {
this.animations.set(name, animation);
}
/**
* 裁剪人物
* @param {string} name 画布名称
* @param {number} x 需要裁剪的图片x位置
* @param {number} y 需要裁剪的图片y位置
* @param {number} width 裁剪宽度
* @param {number} height 裁剪高度
*/
define(name, x, y, width, height) {
// hard code:false代表不翻转绘制,true代表翻转绘制,用于控制马里奥反方向和正方形的帧动画
const buffers = [false, true]
.map(flip => {
const canvas = document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;
const context = canvas.getContext("2d");
if (flip) {
// 翻转绘制
context.scale(-1, 1);
context.translate(-width, 0);
}
// 裁剪图片,并存储
context.drawImage(
this.image,
x,
y,
width,
height,
0,
0,
width,
height);
return canvas;
});
this.tiles.set(name, buffers);
}
/**
* 裁剪背景(背景需要重复裁剪)
* @param {string} name 画布名称
* @param {number} x 需要裁剪的图片x与单位高度倍数
* @param {number} y 需要裁剪的图片y与单位高度倍数
*/
defineTile(name, x, y) {
this.define(name, x * this.width, y * this.height, this.width, this.height);
}
/**
* 画图像
* @param {string} name 画布名称
* @param {any} context 上下文对象
* @param {number} x 需要画图像的x坐标
* @param {number} y 需要画图像的y坐标
* @param {boolean} flip 是否翻转绘制
*/
draw(name, context, x, y, flip = false) {
const canvas = this.tiles.get(name)[+flip];
context.drawImage(canvas, x, y, this.width, this.height); // drawImage第一个参数接收类型:图像、视频、画布
}
/**
* 画动画帧
* @param {string} name 画布名称
* @param {any} context 上下文对象
* @param {number} x 需要画图像的x坐标(倍数)
* @param {number} y 需要画图像的y坐标(倍数)
* @param {number} distance 距离
*/
drawAnim(name, context, x, y, distance) {
// 取得动画回调,在执行动画回调时会取得当前动画的名字,再根据名字渲染
const animation = this.animations.get(name);
this.drawTile(animation(distance), context, x, y);
}
/**
* 画单元格
* @param {string} name 画布名称
* @param {any} context 上下文对象
* @param {number} x 需要画图像的x坐标(倍数)
* @param {number} y 需要画图像的y坐标(倍数)
*/
drawTile(name, context, x, y) {
this.draw(name, context, x * this.width, y * this.height)
}
}
第一关关卡对应的资源文件数据改动
加入了 奖励砖块所需要的帧动画配置
新增animation.js
该文件用于生成帧动画所需的sprite名字
export function createAnim(frames, frameLenth) {
return function resolveFrame(distance) {
const index = Math.floor(distance / frameLenth) % frames.length;
return frames[index];
}
}
新增sprite/mario.json
该文件定义马里奥的一些参数,例如长款、帧动画、来源地址等
{
"tileImgUrl": "/src/assets/characters.png",
"tileWidth": 16,
"tileHeight": 16,
"frames": [
{
"name": "mario",
"rect": [276, 44, 16, 16]
},
{
"name": "mario-run-1",
"rect": [290, 44, 16, 16]
},
{
"name": "mario-run-2",
"rect": [304, 44, 16, 16]
},
{
"name": "mario-run-3",
"rect": [321, 44, 16, 16]
}
]
}