После того, как турориал с тем же точным кодом, но выдает эту ошибку на консоль при попытке нарисовать изображение на холсте:
SpriteSheet.js: 30 Uncaught (в обещании) TypeError: Не удалось выполнить 'drawImage' для 'CanvasRenderingContext2D': предоставленное значение не относится к типу '(CSSImageValue или HTMLImageElement, или SVGImageElement, или HTMLVideoElement, или HTMLCanvasitlement, или Screen HTMLCanvasElement * Screen HTMLCanvasElement) или HTMLCanvasElement или Screen * ImageManCanvasElement * Screen HTMLCanvasElement или 1004 *
Не знаю, почему это происходит? Первое изображение отлично рисуется на холсте, но второе не появляется и выдает эту ошибку. Использование обещаний, поэтому все изображения должны быть загружены перед их использованием, верно? Он отлично работает, если я изменю конец файла script.js на drawBackground(level.backgrounds[1], context, sprites);
script.js
import SpriteSheet from './SpriteSheet.js';
import {loadImage, loadLevel} from './loaders.js';
function drawBackground(background, context, sprites) {
background.ranges.forEach(([x1, x2, y1, y2]) => {
for (let x = x1; x < x2; ++x) {
for (let y = y1; y < y2; ++y) {
sprites.drawTile(background.tile, context, x, y);
}
}
});
}
function loadBackgroundSprites() {
return loadImage('SEA01.png').then(image => {
const sprites = new SpriteSheet(image, 16, 16);
sprites.define('ocean', 0, 0);
return sprites;
});
return loadImage('ground.png').then(image=> {
const sprites = new SpriteSheet(image, 16, 16);
sprites.define('ground', 12, 0);
});
}
const canvas = document.getElementById('gamearea');
const context = canvas.getContext('2d');
Promise.all([
loadBackgroundSprites(),
loadLevel('1-1')
]).then(([sprites,level]) => {
console.log(level);
drawBackground(level.backgrounds[0], context, sprites);
});
loader.js
export function loadImage(url) {
return new Promise(resolve => {
const image = new Image();
image.addEventListener('load', () => {
resolve(image);
});
image.src = url;
});
}
export function loadLevel(name) {
return fetch(`/levels/${name}.json`)
.then(r => r.json());
}
spritesheet.js
export default class SpriteSheet {
constructor(image, w = 16, h = 16) {
this.image = image;
this.width = w;
this.height = h;
this.tiles = new Map();
}
define(name, x, y) {
const buffer = document.createElement('canvas');
buffer.height = this.height;
buffer.width = this.width;
buffer
.getContext('2d')
.drawImage(
this.image,
this.width * x,
this.height * y,
this.width,
this.height,
0,
0,
this.width,
this.height);
this.tiles.set(name, buffer);
}
draw(name, context, x, y) {
const buffer = this.tiles.get(name);
context.drawImage(buffer, x, y);
}
drawTile(name, context, x, y) {
this.draw(name, context, x * this.width, y * this.height);
}
}
1-1.json
{
"backgrounds": [
{
"tile": "ocean",
"ranges": [
[
0, 50,
0, 25
]
]
},
{
"tile": "ground",
"ranges": [
[
18, 25,
10, 15
]
]
}
]
}
Заранее спасибо.
EDIT:
Я обновил свой код для загрузки изображений в разные функции, но получил ту же ошибку:
script.js
import SpriteSheet from './SpriteSheet.js';
import {loadImage, loadLevel} from './loaders.js';
const canvas = document.getElementById('gamearea');
const context = canvas.getContext('2d');
function drawBackground(background, context, sprites) {
background.ranges.forEach(([x1, x2, y1, y2]) => {
for (let x = x1; x < x2; ++x) {
for (let y = y1; y < y2; ++y) {
sprites.drawTile(background.tile, context, x, y);
}
}
});
}
function drawMario(background, context, mario) {
background.ranges.forEach(([x1, x2, y1, y2]) => {
for (let x = x1; x < x2; ++x) {
for (let y = y1; y < y2; ++y) {
mario.drawTile(background.tile, context, x, y);
}
}
});
}
function loadBackgroundSprites() {
return loadImage('SEA01.png').then(image => {
const sprites = new SpriteSheet(image, 16, 16);
sprites.define('ocean', 0, 0);
return sprites;
});
}
function loadDirtSprite() {
return loadImage('ground.png').then(image => {
const mario = new SpriteSheet(image, 16, 16);
mario.define('ground', 12, 0);
return mario;
});
}
Promise.all([
loadBackgroundSprites(),
loadLevel('1-1'),
loadDirtSprite()
]).then(([sprites, level, mario]) => {
level.backgrounds.forEach(background => {
drawBackground(background, context, sprites, mario);
});
mario.draw('ground', context, 1, 16);
});