Skip to content

Conversation

@pearmini
Copy link
Collaborator

/**
 * ============================================================================
 * =                           Pokemon Guessing Game                          =
 * ============================================================================
 *
 * This example is inspired by Ping Lin's **LoadJSON: Pokemon**:
 *
 * https://editor.p5js.org/pinglin/sketches/530Xltl3l
 *
 * You can select a Pokemon by the radio or change the search text to get a
 * Pokemon. Then ask others to guess the Pokemon by the ASCII art.
 */

const selected = recho.radio(0, ["pikachu", "charmander", "squirtle", "bulbasaur"]);

const search = null;

//➜ ⚡ Type: ELECTRIC
//➜ ⚖️ Weight: 60
//➜ 📏 Height: 4
//➜
//➜
//➜
//➜
//➜
//➜
//➜
//➜
//➜                      %%
//➜                      +-*       #*+##%
//➜                      #--:..:=::-=#     %+*
//➜                      #*:-::+*=-+    #*-:::-%
//➜                     #=:-=---:**=  #-:::::::+
//➜                      %----------*%=----+#%
//➜                       :-:----::::  #==
//➜                      *::-::=::-::*#=+*%
//➜                     #----:-=--::-- ##
//➜                     +--:::::------%
//➜                     ##+#%   %#*=+#
//➜
//➜
//➜
//➜
//➜
//➜
//➜
//➜
{
  echo(`⚡ Type: ${pokemon.types[0].type.name.toUpperCase()}`, {quote: false});
  echo(`⚖️ Weight: ${pokemon.weight}`, {quote: false});
  echo(`📏 Height: ${pokemon.height}`, {quote: false});
  echo("", {quote: false});
  img2ASCIIString(pokemon.sprites.front_default).then(echo);
}

/**
 * Originally, I wanted to create an example to visualize a Pokemon in ASCII
 * art. But I found it's not easy to tell under the current transformation
 * from pixels to characters. So I decided to make it a guessing game.
 *
 * In addition, this is also a good showcase for the following features:
 *
 * - How to use Data API in Recho
 * - How to draw image in Recho
 * - How to use inputs in Recho
 */

const pokemon = await getPokemon(search || selected);

async function getPokemon(name) {
  const pokemon = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`);
  return pokemon.json();
}

async function img2ASCIIString(url, cols = 60, rows = 25) {
  const asciiChars = " %#*+=-:. "; // From black to white.

  // Load the image.
  const img = await new Promise((resolve, reject) => {
    const image = new Image();
    image.crossOrigin = "Anonymous";
    image.onload = () => resolve(image);
    image.onerror = reject;
    image.src = url;
  });

  const canvas = document.createElement("canvas");
  canvas.width = img.width;
  canvas.height = img.height;
  const ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0);

  const imgData = ctx.getImageData(0, 0, img.width, img.height).data;

  const cellWidth = img.width / cols;
  const cellHeight = img.height / rows;

  let ascii = "";
  for (let y = 0; y < rows; y++) {
    for (let x = 0; x < cols; x++) {
      // Compute the range of the cell.
      const startX = Math.floor(x * cellWidth);
      const startY = Math.floor(y * cellHeight);
      const endX = Math.floor((x + 1) * cellWidth);
      const endY = Math.floor((y + 1) * cellHeight);

      // Compute the brightness of the cell.
      let sum = 0;
      let count = 0;
      for (let py = startY; py < endY; py++) {
        for (let px = startX; px < endX; px++) {
          const idx = (py * img.width + px) * 4;
          const r = imgData[idx];
          const g = imgData[idx + 1];
          const b = imgData[idx + 2];
          const brightness = 0.299 * r + 0.587 * g + 0.114 * b;
          sum += brightness;
          count++;
        }
      }
      const avg = sum / count;
      const charIndex = Math.floor((avg / 255) * (asciiChars.length - 1));
      ascii += asciiChars[charIndex];
    }
    ascii += "\n";
  }

  return ascii;
}

@cloudflare-workers-and-pages
Copy link

Deploying recho with  Cloudflare Pages  Cloudflare Pages

Latest commit: b3e4b45
Status: ✅  Deploy successful!
Preview URL: https://890ade3c.recho.pages.dev
Branch Preview URL: https://pokemon.recho.pages.dev

View logs

@pearmini pearmini merged commit c0babc5 into main Sep 23, 2025
2 checks passed
@pearmini pearmini deleted the pokemon branch September 23, 2025 15:57
@pearmini pearmini added the Example Add a new example label Sep 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Example Add a new example

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant