color system for tile base game

Viewed 149

I have started a project to teach myself the mechanics behind tile-base game engines. So far I have a pretty good little demo working but I can't figure out how to implement colors for each tile. I would like for any tile to be any color but this proves to be complicated for me.

the entire game uses 2d arrays for every object/component on the screen. There is a central 2d array that stores all of the walls and floor tiles and anything that's not a separate moving object. my idea was to have a parallel array that stores color values. Then to iterate and change the color of each tile accordingly.

The base part of my code where I do the actual drawing is in a class called font

class Font{
    constructor(src, tilesizeX, tilesizeY){
        this.fontImage = new Image();
        this.imageBuffer = new Image();
       // this.fontImage.setAttribute('crossOrigin', '')
        this.fontImage.src = src;
        this.colors = ["#00F","#09f","#fff", "#999"]
        //this.fontImage.onload = this.drawChar();
    }

    drawChar(charCode, posX, posY, color){

        var charmap = [
            [' ','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x','y', 'z', '☺', '☻','♡','♦','♣','♤', '•', '◘', '○', '◙','♂','♀','♪','♫','☼','►','◄','↕','‼','¶','§','▬','↨','↑','↓','→','←','∟','↔','▲','▼',
            '░','▒','▓','│','┤','╡','╢','╖','╕','╣','║','╗','╝','╜','╛','┐',
            '└','┴','┬','├','─','┼','╞','╟','╚','╔','╩','╦','╠','═','╬','╧',
            '╨','╤','╥','╙','╘','╒','╓','╫','╪','┘','┌','█','▄','▌','▐','▀',
            'space', '!','"','#','$','%','&',"'",'(',')','*','+',',','-','.','/',
            '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
            '@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
            'P','Q','R','S','T','U','V','W','X','Y','Z','[','/',']','^','_',
            ],
            [
                [0,0],[6, 1], [6, 2], [6, 3], [6, 4], [6, 5], [6, 6], [6, 7], [6, 8], [6, 9], [6, 10], [6, 11], [6, 12],[6, 13],[6, 14], [6, 15],[7,0],
                [7, 1],[7, 2], [7, 3], [7, 4], [7, 5], [7, 6], [7, 7], [7, 8],[7, 9],[7, 10],
                [0, 1], [0, 2],[0,3], [0,4],[0,5],[0,6],[0,7],[0,8],[0,9],[0,10],[0,11],[0,12],[0,13],[0,14],[0,15],
                [1,0],[1,1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [1, 7], [1, 8], [1, 9], [1, 10], [1, 11], [1, 12], [1, 13], [1, 14], [1, 15],
                
                [11,0],[11,1],[11,2],[11,3],[11,4], [11, 5], [11, 6], [11, 7], [11, 8], [11, 9], [11, 10], [11, 11], [11, 12], [11, 13], [11, 14], [11, 15],
                [12,0],[12,1],[12,2],[12,3],[12,4], [12, 5], [12, 6], [12, 7], [12, 8], [12, 9], [12, 10], [12, 11], [12, 12], [12, 13], [12, 14], [12, 15],
                [13,0],[13,1],[13,2],[13,3],[13,4], [13, 5], [13, 6], [13, 7], [13, 8], [13, 9], [13, 10], [13, 11], [13, 12], [13, 13], [13, 14], [13, 15],
                [2,0],[2,1], [2, 2], [2, 3], [2, 4], [2, 5], [2, 6], [2, 7], [2, 8], [2, 9], [2, 10], [2, 11], [2, 12], [2, 13], [2, 14], [2, 15],
                [3,0],[3,1], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7], [3, 8], [3, 9], [3, 10], [3, 11], [3, 12], [3, 13], [3, 14], [3, 15],
                [4,0],[4,1], [4, 2], [4, 3], [4, 4], [4, 5], [4, 6], [4, 7], [4, 8], [4, 9], [4, 10], [4, 11], [4, 12], [4, 13], [4, 14], [4, 15],
                [5,0],[5,1], [5, 2], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7], [5, 8], [5, 9], [5, 10], [5, 11], [5, 12], [5, 13], [5, 14], [5, 15],
            ]
        ]

        var scopeX = charmap[1][charmap[0].indexOf(charCode)][1] * 8;
        var scopeY = charmap[1][charmap[0].indexOf(charCode)][0] * 16

        game.ctx.drawImage(this.fontImage, scopeX, scopeY, 7 , 15 , posX, posY, 16, 32);
        

    }
}

if I use this code at the end of my drawChar() function

game.ctx.drawImage(this.fontImage, scopeX, scopeY, 7, 15, posX, posY, 16, 32);
game.ctx.globalCompositeOperation = "source-out"
game.ctx.fillStyle = this.colors[getRandomInt(0, 3)];
game.ctx.fillRect(0, 0, 16, 32);
        
game.ctx.globalCompositeOperation = "source-over"

the first tile is colored as desired but none of the other tiles display. I am still new to all the intricacies of game development and do not know how I should go about adding colors

1 Answers

I use 2d arrays, like so:

 var map = [
  [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,2,0,0,0,3,0,0,0,0,0,4,0,0,0,2,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,3,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],

]

An then i loop through all of the values in the map and set the fill style depending on the value.

for (y = 0; y < map.length; y++) {
        for (x = 0; x < map[y].length; x++) {

            ctx.fillStyle = ["green", "red", "yellow", "blue"][map[y][x]];
            ctx.fillRect(x * tilesize, y * tilesize, tilesize, tilesize);

        }
    }

And you can also use images instead of colors,

switch(map[x][y]){
case 1:
img = stone;
break;
case 2:
img = grass;
break;
 } 
ctx.fillImage(img,0,0,300,300,x*tilesize,y*tilesize,tilesize,tilesize);

Look up ctx.fillImage() for more info on those parameters.

Then the final program would look like this

<canvas id="c" width=800 height=800></canvas>
<script>
  const canvas = document.getElementById('c');
  const ctx = canvas.getContext('2d');

  var tilesize = 10
  var map = [
  [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,2,0,0,0,3,0,0,0,0,0,4,0,0,0,2,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,3,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],

  ]

  function drawmap() {
    for (y = 0; y < map.length; y++) {
      for (x = 0; x < map[y].length; x++) {
        ctx.fillStyle = ["red", "blue", "cyan", "yellow"][map[y][x]]
        ctx.fillRect(x * tilesize, y * tilesize, tilesize, tilesize)
      }
    }
  }

  drawmap()
</script>

OR

<img id="stone" src="https://encrypted-tbn0.gstatic.com/images? 
q=tbn:ANd9GcTFYnQ2tB7R4YVGtOquPzZxc2fq_taDOYryug&usqp=CAU" style="display:none;">
<img id="grass" src="https://encrypted-tbn0.gstatic.com/images? 
q=tbn:ANd9GcTFYnQ2tB7R4YVGtOquPzZxc2fq_taDOYryug&usqp=CAU" style="display:none;">
<canvas id="c" width=800 height=800></canvas>
<script>
  const canvas = document.getElementById('c');
  const ctx = canvas.getContext('2d');
  var grass = document.getElementById("grass")
  var stone = document.getElementById("stone")

  var tilesize = 10
  var map = [
  [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],

  ]

  function drawmap() {
    for (y = 0; y < map.length; y++) {
      for (x = 0; x < map[y].length; x++) {
        switch(map[y][x]){
        case 1:
        img = stone;
        break;
        case 2:
        img = grass;
        break;
       }
       ctx.drawImage(img,0,0,300,300,x*tilesize,y*tilesize,tilesize,tilesize);
      }
    }
  }

I know this is not exactly what you asked for, but it is a very good and fast way to do this.

Related