我正在使用ReactJS和Electron开发游戏。我有一个React组件,我想加载我的游戏地图(它是一个2d的tileset地图)。为此,我将组件传递给我要加载资源的目录的名称。一旦它读入game.json文件,它就知道在哪里查找地图tileset数据。 一旦它加载了tileset数据,我希望它计算tile的sprite并将它们放在适当的区域。
我的问题如下:
将此功能放在componentWillMount()函数中是否有意义?
异步性是否与图像文件未正确加载有关?
假设一切都结束了,为什么画布不能画出我传递的图像?
查看数据,sx / sy / dx / dy坐标就是我想要的位置。取消注释componentDidMount()函数会显示获取图像文件会导致控制台中的../path/null。
有什么建议吗?
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
export default class Map extends React.Component{
//Set all vars to null
constructor(props){
super(props);
this.state={
mapArr: [],
directory: null,
data: null,
players: null,
enemies: null,
objective: null,
map: null,
tileset: null
}
}
// Given this.props.gamemap, load the game.json file that it points to
// Given the game.json, set the path to the map it references
componentWillMount(){
//Process game data
this.directory = this.props.gamemap;
this.data = require('./content/' + this.directory + '/game.json');
this.players = this.data.players; //Players
this.enemies = this.data.enemies; //Enemies
this.objective = this.data.objective; //Game Objective
this.map = this.data.map; //Map name
this.setState({
data: this.data,
players: this.players,
enemies: this.enemies,
objective: this.objective,
});
// Read in map data
let _this = this;
axios({
method: 'get',
url: './content/' + _this.directory + '/' + _this.map,
responseType: 'text',
timeout:1000
})
.then(function(response){
// console.log(response.data);
var tileSize = 16;
var mapData = response.data.split("\n");
var mapArr = [];
var tileset = "";
var mapWidthTiles = 0;
var mapHeightTiles = 0;
var mapWidthPX = 0;
var mapHeightPX = 0;
var acc = 0;
var line;
for(line in mapData){
if(acc === 0)
tileset = './content/' + _this.directory + '/' + mapData[line] + '.png';
else if(acc === 1){
mapWidthTiles = mapData[line].split(" ")[0];
mapHeightTiles = mapData[line].split(" ")[1];
mapWidthPX = mapWidthTiles * tileSize;
mapHeightPX = mapHeightTiles * tileSize;
}
else
mapArr.push(mapData[line].split(" "));
acc++;
}
_this.setState({
mapArr: mapArr,
mapWidthTiles: mapWidthTiles,
mapHeightTiles: mapHeightTiles,
mapWidthPX: mapWidthPX,
mapHeightPX: mapHeightPX,
tileset: tileset,
});
})
.catch(function(error){
});
}
componentDidMount(){
this.paint();
}
componentDidUpdate(){
this.paint();
}
//Paint Canvas with map data
// * BUG HERE *
paint(){
var context = ReactDOM.findDOMNode(this.refs.gameMap).getContext('2d');
var tileSize = 16;
this.mapArr = this.state.mapArr;
this.tileset = this.state.tileset;
this.image = new Image();
this.image.src = this.tileset;
//Given a map and a tileset location, we can now render the map
// mapArr[x][y] = val
// val divided by 32 (whole int) = y
// remainder = x
let _this = this;
if(this.image.complete){
console.log("Image complete");
for(var dx=0 ; dx<_this.mapArr.length ; dx++){
for(var dy=0 ; dy<_this.mapArr[dx].length ; dy++){
var sy = Math.floor(_this.mapArr[dx][dy]/32);
var sx = _this.mapArr[dx][dy]%32;
context.drawImage(
_this.image,
sx*this.tileSize, sy*this.tileSize, this.tileSize, this.tileSize,
dx*this.tileSize, dy*this.tileSize, this.tileSize, this.tileSize);
}
}
}
else{
this.image.onload = function(){
console.log("Image loaded");
for(var dx=0 ; dx<_this.mapArr.length ; dx++){
for(var dy=0 ; dy<_this.mapArr[dx].length ; dy++){
var sy = Math.floor(_this.mapArr[dx][dy]/32);
var sx = _this.mapArr[dx][dy]%32;
context.drawImage(
_this.image,
sx*this.tileSize, sy*this.tileSize, this.tileSize, this.tileSize,
dx*this.tileSize, dy*this.tileSize, this.tileSize, this.tileSize);
}
}
}
this.image.onerror = function(res){
console.log("Could not load game map");
console.log(res);
}
}
}
render(){
return <canvas
id="map"
ref="gameMap"
width={this.state.mapWidthPX}
height={this.state.mapHeightPX}/>
}
}