【问题标题】:JS Tile Map - Replacing color tiles by imagesJS Tile Map - 用图像替换彩色瓷砖
【发布时间】:2017-10-24 10:45:13
【问题描述】:

我正在尝试做一个 Tilemap 系统,所以我完成了一个教程。这是代码:

// Possible tile types
const TILE_TYPES = {
  0: { name: 'Sea', color: 'lightBlue'},
  1: { name: 'Land', color: 'wheat' },
  2: { name: 'House', color: 'black'}
}

// Map tile data
let mapData = <?php echo $mapData ?>

/**
Tile class
*/
class Tile {
  constructor (size, type, ctx) {
    this.size = size
    this.type = type
    this.ctx = ctx
  }

  draw (x, y) {
    // Store positions
    const xPos = x * this.size
    const yPos = y * this.size

    // Draw tile
    this.ctx.fillStyle = this.type.color
    this.ctx.fillRect(xPos, yPos, this.size, this.size)
  }
}

/**
Map class
*/
class Map {
  constructor (selector, data, opts) {
    this.canvas = document.getElementById(selector)
    this.ctx = this.canvas.getContext('2d')
    this.data = data
    this.tileSize = opts.tileSize
  }
}

/**
OrthogonalMap class
*/
class OrthogonalMap extends Map {
  constructor (selector, data, opts) {
    super(selector, data, opts)
    this.draw()
  }

  draw () {
    const numCols = this.data[0].length
    const numRows = this.data.length

    // Iterate through map data and draw each tile
    for (let y = 0; y < numRows; y++) {
      for (let x = 0; x < numCols; x++) {
        // Get tile ID from map data
        const tileId = this.data[y][x]

        // Use tile ID to determine tile type from TILE_TYPES (i.e. Sea or Land)
        const tileType = TILE_TYPES[tileId]

        // Create tile instance and draw to our canvas
        new Tile(this.tileSize, tileType, this.ctx).draw(x, y)
      }
    }
  }
}

// Init canvas tile map on document ready
document.addEventListener('DOMContentLoaded', function () {
  // Init orthogonal map
  const map = new OrthogonalMap('orthogonal-map', mapData, { tileSize: 64 })
})

来电:

<?php
  $mapData = '[
    [1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2],
    [1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1],
    [1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0],
    [1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
    [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
    [1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
  ]';

  include "" . $_SERVER['DOCUMENT_ROOT'] . "/includes/maptiles.php";
?>
<canvas id="orthogonal-map" class="canvas-map" width="704" height="576"> </canvas>

这是我的问题:如何用图像替换颜色?

我的第一个赌注是将“color”属性替换为TILE_TYPES 常量,并将this.ctx.fillStyle 替换为this.ctx.drawimage

我是 Javascript 的初学者,所以如果您有时间,我很想对您的流程进行一些解释。谢谢!

【问题讨论】:

    标签: javascript canvas


    【解决方案1】:

    在画布上绘制图像很简单,但是,在需要解释之前,您需要执行一个步骤。在开始执行 Javascript 代码之前,您需要加载图像并等待它们准备好。我将向您展示实现这一目标的最简单方法,但还有其他方法,而且这个方法有几个问题。所以,现在没问题,但在某些时候你会学习其他方法。

    首先,我们将添加 at html 图片标签来加载图片:

    <img id="Sea" src="Sea.jpg">
    <img id="Land" src="Land.jpg">
    <img id="House" src="House.jpg">
    <script>
    ...
    

    &lt;script&gt; 是您当前代码的开头,... 我的意思是代码继续在那里,您不能将点写入您的代码。

    如果您检查结果,您会看到它们出现在页面顶部,位于画布顶部。我们现在将告诉 Javascript 等待它们加载并从画布顶部删除它们:

    首先让我们改变一下:

    document.addEventListener('DOMContentLoaded', function () {
    

    通过这个:

    window.addEventListener('load', function () {
    

    使用您所拥有的,您正在等待加载 DOM 内容以开始执行。使用新代码,它将等待加载所有内容,包括 DOM 内容和图像。

    所以,现在让我们为图像创建一些引用:

    const images = {};
    window.addEventListener('load', function () {
        images.Sea = document.getElementById("Sea");
        images.Land = document.getElementById("Land");
        images.House = document.getElementById("House");
    ...
    

    现在,让我们将它们从画布顶部移除:

    const images = {};
    window.addEventListener('load', function () {
        images.Sea = document.getElementById("Sea");
        images.Land = document.getElementById("Land");
        images.House = document.getElementById("House");
        images.Sea.parentNode.removeChild(images.Sea);
        images.Land.parentNode.removeChild(images.Land);
        images.House.parentNode.removeChild(images.House);
    ...
    

    现在唯一缺少的部分是在画布上绘制它们。所以,让我们替换这个:

    // Draw tile
    this.ctx.fillStyle = this.type.color
    this.ctx.fillRect(xPos, yPos, this.size, this.size)
    

    通过这个:

    // Draw tile
    this.ctx.drawImage(images[this.type.name], xPos, yPos);
    

    【讨论】:

    • 嗨。首先,谢谢,这正是我想要的!现在,我想知道是否有一种方法可以使用“tileset”而不是图像,我不知道这个问题是否是我特有的,但是这段代码会使页面“滞后”吗?滚动似乎不像以前那么流畅,但也许这就是我。抱歉问了这么多!
    • 关于tileset的问题,请阅读drawImage的文档。您可以为其添加更多参数,告诉您要绘制的图像的哪一部分和大小,这样您就可以制作图块集。但那是供你学习和练习的。关于滞后的问题,不知道,我没有尝试过代码
    • L.G 如果答案是您所需要的,请接受它,以便 Roman 为他的努力获得代表。
    • 谢谢@Anthropic,但别担心,我绝对没有为代表写那么多,但对于学习的人来说,这似乎是一个很酷的问题......即使只有 L.G 对一起学习,绝对值得!
    • @Anthropic,这让我想知道这是否是 Stackoverflow 设计中的用户体验问题。也许当答案是你想要的时候,你应该接受答案还不够清楚。我确定它写在某个地方,但可能不够引人注意/不够华丽。我自己也是一个新用户,很多事情还没有搞清楚……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    • 2011-07-13
    相关资源
    最近更新 更多