Я создаю игру на основе React и Redux, в которой пользователь должен управлять королевством и отдавать земельные участки дворянам.
Я создал компонент игровой карты, в котором для рисования элемента используется элемент canvas. игровая карта. Карта игры состоит из множества маленьких плиток, которые представляют собой участки земли. В настоящее время я использую рамку запроса анимации для рисования матрицы плиток. Пользователь также может перетаскивать и увеличивать и уменьшать масштаб карты. Проблема в том, что игровая карта на самом деле довольно запаздывает, так как каждый кадр это dr aws каждая плитка, затем dr aws border, et c.
Мой вопрос таков: возможно ли вставить вместе каждую отдельную плитку в более крупное изображение, так что мне нужно нарисовать только одно большое изображение вместо того, чтобы перебирать матрицу данных карты и рисовать каждую отдельную плитку в каждом кадре.
Вероятно, вам не обязательно видеть мой текущий код, но вот мой конструктор и моя функция drawGame:
class MapPage extends React.Component{
constructor(props){
super(props)
this.FieldImage = new Image()
this.RockImage = new Image()
this.PlainImage = new Image()
this.HouseImage = new Image()
this.Trees = new Image()
this.GoldOre = new Image()
this.ChurchBot = new Image()
this.ChurchTop = new Image()
this.BlueSpearman = new Image()
this.FieldImage.src = Field
this.RockImage.src = Rock
this.PlainImage.src = Plain
this.HouseImage.src = House
this.Trees.src = Trees
this.GoldOre.src = GoldOre
this.ChurchBot.src = ChurchBot
this.ChurchTop.src = ChurchTop
this.BlueSpearman.src = BlueSpearman
//mapOffset is in the redux store so that it persists when the user navigates away and navigates back
this.state = {
tileInfoIsVisible: true, //Currently this is always true, might change later
mouseOffset: {},
mouseX: 0,
mouseY: 0,
tileX: 0,
tileY: 0,
}
}
drawGame(ctx, currentSecond = 0, framesLastSecond = 0, frameCount = 0) {
if(ctx===null) return
ctx.fillStyle = 'black'
ctx.fillRect(0, 0, viewportWidth, viewportHeight) //creates a black background
let sec = Math.floor(Date.now()/1000)
if(sec !== currentSecond){
currentSecond = sec
framesLastSecond = frameCount
}
const xOffset = this.props.mapOffset.x
const yOffset = this.props.mapOffset.y
const tileSize = this.props.tileSize
for(let x = 0; x < mapWidth; x++){
for(let y = 0; y < mapHeight; y++){
//Always draw a plain image first on every tile, as a backdrop
ctx.drawImage(this.PlainImage, x*tileSize + xOffset, y*tileSize + yOffset, tileSize, tileSize)
switch(this.props.gameMap[x][y].type){
case 'plain': //Not necessary to draw anything here, since plain is drawn on every time anyway
//ctx.drawImage(this.PlainImage, x*tileSize, y*tileSize, tileSize, tileSize)
break
case 'rock':
ctx.drawImage(this.RockImage, x*tileSize + xOffset, y*tileSize + yOffset, tileSize, tileSize)
break
case 'field':
ctx.drawImage(this.FieldImage, x*tileSize + xOffset, y*tileSize + yOffset, tileSize, tileSize)
break
case 'house':
ctx.drawImage(this.HouseImage, x*tileSize + xOffset, y*tileSize + yOffset, tileSize, tileSize)
break
case 'trees':
ctx.drawImage(this.Trees, x*tileSize + xOffset, y*tileSize + yOffset, tileSize, tileSize)
break
case 'goldOre':
ctx.drawImage(this.GoldOre, x*tileSize + xOffset, y*tileSize + yOffset, tileSize, tileSize)
break
case 'church':
ctx.drawImage(this.ChurchBot, x*tileSize + xOffset, y*tileSize + yOffset, tileSize, tileSize)
ctx.drawImage(this.ChurchTop, x*tileSize + xOffset, y*tileSize + yOffset - tileSize, tileSize, tileSize)
break
default:
}
switch(this.props.gameMap[x][y].kingdomOwner){
case this.props.mainKingdom.id:
ctx.fillStyle = 'rgb(51, 153, 255, 0.3)'
ctx.fillRect(x*tileSize + xOffset, y*tileSize + yOffset, tileSize, tileSize)
this.drawKingdomBorder(x, y, this.props.mainKingdom, ctx)
break
default:
}
}
}
this.drawHoveredTileOutline(ctx)
this.handleTileInfoCoordinates()
if(window.location.pathname==='/newMap'){ // this is to stop the animation loop when the user navigates away from the page
requestAnimationFrame(() => {this.drawGame(ctx)})
}
}
Вы можете видеть, что в каждом кадре много чего происходит, что делает игру довольно медленной, особенно если карта большой