D E V L O G #5 - Tile Variation & Player Direction


So one thing I wanted to add in is a bit more variety to the tilesets. To add this I put in a tile 'variant' option for the tilesets so that I could certain tiles have different sprites, as well as draw in extra details.

I updated the tilesheet to include a bunch of variants, including the little symbol and candle details which we'll use later.


When my entities get created initially, I added some extra code to specify the tile x and y co-ordinates if the tile is a floor tile.

// get a random number between 1 and the no. of sides of the dice
var _rollDice = function(sides) {
  return Math.floor(Math.random() * sides) + 1;
}
// get the chance of something happening based on a percent chance
var _getChance = function(percent) {
  var chance = _rollDice(10) / 10;
  return chance <= percent;
}
// get tile variants
var special = _getChance(0.2);
if (special) {
  this.tx = tile.x + 16;
} else {
  this.tx = tile.x;
}
this.ty = tile.y + (16 * (_rollDice(12) - 1));

I added in two new functions, rollDice() and getChance(), which let me do some RNG related stuff. Basically what we're saying is that every tile has a 20% chance of being a 'special' tile, which picks from the second column in the sprite sheet rather than the first, then we're picking a random tile in that column (between 1 and 12).

I then wanted to add in the little details on the tiles. For this I wanted candles to only appear around the edges, but symbols can be anywhere. I did this inside the Entity creation so that in only happens once, and I store the 'decorations' in a new key in the object.

// add tile candle decoration
if (y == 16 || x == 16 || y == 144 || x == 208) {
  if (_getChance(0.1)) {
    this.decoration.push({
      x: 128 + (8 * (_rollDice(2) - 1)),
      y: 0 + (8 * (_rollDice(2) - 1)),
      xOffset: (_rollDice(2) - 1) * 8,
      yOffset: (_rollDice(2) - 1) * 8,
      width: 8,
      height: 8
    })
  }
}
// add tile symbol decoration
if (_getChance(0.1)) {
  this.decoration.push({
    x: 144 + (8 * (_rollDice(6) - 1)),
    y: 0 + (8 * (_rollDice(6) - 1)),
    xOffset: (_rollDice(2) - 1) * 8,
    yOffset: (_rollDice(2) - 1) * 8,
    width: 8,
    height: 8
  })
}

What I can then do is draw these decorations along with the tile in the render loop. This ends up giving us something like this:

This looks much more interesting, but the worry now is we're suddenly drawing a lot of tiles in the render loop that really only ever need to be drawn once. So what we'll do is have two canvases acting as layers - one for the 'background' and one for entities that interact with the player.

To allow for this I changed the room definition to have two distinct layers:

// example room
var _room = {
  background: [
    ['XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX'],
    ['XX','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','XX'],
    ['XX','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','XX'],
    ['XX','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','XX'],
    ['XX','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','XX'],
    ['XX','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','XX'],
    ['XX','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','XX'],
    ['XX','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','XX'],
    ['XX','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','XX'],
    ['XX','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','FF','XX'],
    ['XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX'],
  ],
  entity: [
    ['C1','WT','WT','WT','WT','WT','WT','WT','WT','WT','WT','WT','WT','WT','C2'],
    ['WL','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','WR'],
    ['WL','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','WR'],
    ['WL','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','WR'],   
    ['WL','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','WR'],
    ['WL','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','WR'],
    ['WL','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','WR'],
    ['WL','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','WR'],
    ['WL','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','WR'],
    ['WL','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','XX','WR'],
    ['C3','WB','WB','WB','WB','WB','WB','WB','WB','WB','WB','WB','WB','WB','C4']
  ]
};

Then I added a second canvas to be used for the background, and created a render function that gets called only once for that canvas to draw the tiles once.

Adding in the second canvas and running the loop gives us something like this:


We just need to position the canvases on top of each other and the player won't know any different! But for us we're now only having to render a handful of entities each game loop which is much more efficient.

I then wanted to add in something to allow us to know which direction the player is facing at all times. Eventually this will allow us to work out all sorts of things but for now just showing the player in a different direction is good enough.

Based on the delta of the player (which we established before in our player movement), we can determine which direction the player is facing as they move, or stop moving. 

_player.direction = 
  deltaX > 0 ? 'right':
  deltaX < 0 ? 'left' :
  deltaY < 0 ? 'top'  :
  deltaY > 0 ? 'down' :
  _player.direction;

We then just need to render a different sprite based on what the player's direction is! We can store the player's various sprites in a map and access it during render.

// sprite direction x/ys
var _player_sprites = {
  top: [32,80],
  left: [80,80],
  right: [48,80],
  down: [64,80]
};
//render player
var psx = _player_sprites[_player.direction][0];
var psy = _player_sprites[_player.direction][1];
_context.drawImage(_tileset, psx, psy, 16, 32, _player.x, _player.y, _player.width, _player.height);

This gives us the following floaty little boy!


Now no matter what way we're facing we know internally that direction, and can show the user that direction too. Eventually we'll need to add walk cycles to this but this will do for now!

That's all for this weeks log! Next week I'll look at adding in the next mechanic I want in this game, which is being able to push other objects, which will be key for various puzzle related stuff later on.

T H I S T L E

Leave a comment

Log in with itch.io to leave a comment.