Можно ли создать более крупный объект изображения, вставив вместе множество меньших изображений? - PullRequest
0 голосов
/ 06 января 2020

Я создаю игру на основе 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)})
    }
  }

Вы можете видеть, что в каждом кадре много чего происходит, что делает игру довольно медленной, особенно если карта большой

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...