Next page | Contents page |

Unicode revisited: images

It seems, from things others have written online, that there is no guarantee that the unicode glyphs for complete cards will be available on all systems. Therefore I need to convert them to images.

There will be 52 cards to process plus the back and 2 or 3 jokers. Rather than have so many separate image files, all having to be loaded into the game, I plan to do what is done in some games and make a sprite sheet comprising all of the images in one file. This would be easy to separate within our game because all of the cards are the same size.

I plan to use plain old JS for my image converter and I will show the design and programming details here.

Rather than make a new HTML file I will add a new file, converterB.js which uses the existing canvas. As noted on the previous page, our files will be version B from now on. We can use this file in response to another keypress: G, say (for graphics). Change onKeydown() in the spider file to this:


function onKeydown (e)
{ if (e.key === "z" && e.ctrlKey) undo ();
  else if (e.key === "g") convert ();
}

Then convert(), will be in our new file. The following is what I wrote. The tricky bit is enabling the image to be downloaded as a PNG file because browsers are only allowed to do that if a user expressly allows it.


function convert ()
{ setCardWidth (210); //3:4 => 210 x 280
  const WD = Card.prototype.width;
  const HT = Card.prototype.height;
  GAME.cnv.width = 14 * WD; // Extra column for jokers + back
  GAME.cnv.height = 4 * HT;
  var g2 = GAME.g2;
  g2.fillStyle = '#fff'; // white background
  g2.fillRect (0, 0, GAME.cnv.width, GAME.cnv.height);
  g2.font = Card.prototype.height + "px sans-serif";
  var x = Card.prototype.dx, dy = Card.prototype.dy;
  for (var i = 1; i <= 13; i++, x += WD)
  { var y = HT - dy;
    g2.fillStyle = '#000';
    var card = new Card (SUITS.CLUB, i);
    card.reveal ();
    g2.fillText (card.getGlyph (), x, y);
    y += HT;
    g2.fillStyle = '#f00';
    card = new Card (SUITS.DIAMOND, i);
    card.reveal ();
    g2.fillText (card.getGlyph (), x, y);
    y += HT;
    g2.fillStyle = '#f00';
    card = new Card (SUITS.HEART, i);
    card.reveal ();
    g2.fillText (card.getGlyph (), x, y);
    y += HT;
    g2.fillStyle = '#000';
    card = new Card (SUITS.SPADE, i);
    card.reveal ();
    g2.fillText (card.getGlyph (), x, y);
  }
  // 14th column:
  y = HT - dy;
  g2.fillStyle = '#000';
  g2.fillText ("\u{1f0df}", x, y);// black joker
  y += HT;
  g2.fillStyle = '#f00';
  g2.fillText ("\u{1f0bf}", x, y);// red joker
  y += HT;
  g2.fillStyle = '#077';// card back
  g2.fillText ("\u{1f0a0}", x, y);
  document.getElementById ("info").innerHTML = 
  '<label>File name (PNG) <input id="fname" type="text"/></label>' +
  '<input id="download" type="button" value="Set for download"/>';
  document.getElementById ("download").addEventListener (
                                           'click', download);
}

function download ()
{ var fname = document.getElementById ("fname").value;
  if (fname.length < 1) return;
  if (!fname.toLowerCase ().endsWith ('.png')) fname += '.png';
  document.getElementById ("info").innerHTML = 
  '<a href="' + GAME.cnv.toDataURL ('image/png') + 
  '" download="' + fname + '">' +
  '<button id="saveas" type="button">Save as ' + fname + 
  '</button></a><br/>' +
  '(in your downloads directory)';
  document.getElementById ("saveas").addEventListener (
                                         'click', clearControls);
}

function clearControls ()
{ document.getElementById ("info").innerHTML = '';
}

Notice the way the canvas is converted to an Image by its toDataURL() method.

Here is the result, scaled down to fit this page. The original is 2940x1120px, 364kbytes.

The game will need to load this image when it starts, in run(). We will need a new method of Card for cutting images out of this one. Card.draw() will need to change to draw the cut-out images onto the canvas rather than unicode glyphs.

Next page | Contents page |