pagefaultgames / pokerogue

A browser based Pokémon fangame heavily inspired by the roguelite genre.
https://pokerogue.net
GNU Affero General Public License v3.0
4.42k stars 1.78k forks source link

Add localization for type symbols #755

Closed CodeTappert closed 4 months ago

CodeTappert commented 5 months ago

I noticed that the type symbols (with text) are all currently in english.

Of course creating them all by hand for every language would be a lot of work so i want to make a suggestion that we create them on the fly.

I created some code that does this (rudementary). Of course a real implementation needs to be a lot better. For example my text is still kind of blurry.

The following code is out of date! Please look at comment: https://github.com/pagefaultgames/pokerogue/issues/755#issuecomment-2106297059

Here is the code: (also it is no typescript just javascript)

/**
 * Generates an image with specified background color, text, rounded corners, a lighter top row,
 * and a black bottom row, ensuring the text fits with at least 1px spacing all around.
 * @param width The width of the image.
 * @param height The height of the image.
 * @param backgroundColor The background color of the image.
 * @param text The text to display in the image.
 * @param font The initial font style and size to use for the text.
 * @returns The canvas element with the drawn image.
 */
function createImage(width, height, backgroundColor, text, font = '20px Verdana') {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  // Set canvas dimensions
  canvas.width = width;
  canvas.height = height;

  // Disable image smoothing for sharper text
  ctx.imageSmoothingEnabled = false;

  // Rounded corners setup
  const radius = 4; // radius of the rounded corners
  ctx.beginPath();
  ctx.moveTo(radius, 0);
  ctx.lineTo(width - radius, 0);
  ctx.quadraticCurveTo(width, 0, width, radius);
  ctx.lineTo(width, height - radius);
  ctx.quadraticCurveTo(width, height, width - radius, height);
  ctx.lineTo(radius, height);
  ctx.quadraticCurveTo(0, height, 0, height - radius);
  ctx.lineTo(0, radius);
  ctx.quadraticCurveTo(0, 0, radius, 0);
  ctx.closePath();
  ctx.clip();

  // Draw background
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, width, height);

  // Draw top lighter row
  ctx.fillStyle = adjustBrightness(backgroundColor, 20);
  ctx.fillRect(0, 0, width, 1);

  // Draw bottom black row
  ctx.fillStyle = 'black';
  ctx.fillRect(0, height - 1, width, 1);

  // Prepare text properties
  ctx.fillStyle = 'white'; // Text color for contrast
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';

  ctx.strokeStyle = 'rgba(0, 0, 0, 0.5)'; // Use semi-transparent black for the border
  ctx.lineWidth = 1; // Use a full pixel but with transparency to simulate a finer line

  // Start with a large font size and decrease until text fits with padding
  let fontSize = 16; // Start with 16px font size
  let metrics;
  const padding = 2; // Minimum padding around text
  do {
    ctx.font = `${fontSize}px Verdana`;
    metrics = ctx.measureText(text);
    fontSize -= 1; // Reduce font size gradually
  } while (metrics.width > width - 2 * padding || fontSize > height - 2 * padding);

  // Draw text in the center of canvas
  ctx.strokeText(text, width / 2, height / 2); // Draw the border around the text
  ctx.fillText(text, width / 2, height / 2); // Fill the text

  return canvas;
}
/**
 * Adjusts the brightness of a hex color.
 * @param color Hex color code.
 * @param percent Percentage to lighten (positive) or darken (negative).
 * @returns Modified color as hex string.
 */
function adjustBrightness(color, percent) {
  let r = parseInt(color.slice(1, 3), 16);
  let g = parseInt(color.slice(3, 5), 16);
  let b = parseInt(color.slice(5, 7), 16);

  r = Math.min(255, Math.max(0, r + Math.round(r * percent / 100)));
  g = Math.min(255, Math.max(0, g + Math.round(g * percent / 100)));
  b = Math.min(255, Math.max(0, b + Math.round(b * percent / 100)));

  return `#${(r << 16 | g << 8 | b).toString(16).padStart(6, '0')}`;
}

/**
 * Generates an image with a rainbow background, specified text, rounded corners,
 * a lighter top row, and a black bottom row, ensuring the text fits with at least 1px spacing all around,
 * and includes a subtle black border around the text.
 * @param width The width of the image.
 * @param height The height of the image.
 * @param text The text to display in the image.
 * @param font The initial font style and size to use for the text.
 * @returns The canvas element with the drawn image.
 */
function createRainbowImage(width, height, text, font = '20px Verdana') {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  // Set canvas dimensions
  canvas.width = width;
  canvas.height = height;

  // Disable image smoothing for sharper text
  ctx.imageSmoothingEnabled = false;

  // Rounded corners setup
  const radius = 4; // radius of the rounded corners
  ctx.beginPath();
  ctx.moveTo(radius, 0);
  ctx.lineTo(width - radius, 0);
  ctx.quadraticCurveTo(width, 0, width, radius);
  ctx.lineTo(width, height - radius);
  ctx.quadraticCurveTo(width, height, width - radius, height);
  ctx.lineTo(radius, height);
  ctx.quadraticCurveTo(0, height, 0, height - radius);
  ctx.lineTo(0, radius);
  ctx.quadraticCurveTo(0, 0, radius, 0);
  ctx.closePath();
  ctx.clip();

  // Create rainbow gradient background
  const gradient = ctx.createLinearGradient(0, 0, width, 0);
  gradient.addColorStop(0, 'red');
  gradient.addColorStop(0.15, 'orange');
  gradient.addColorStop(0.3, 'yellow');
  gradient.addColorStop(0.45, 'green');
  gradient.addColorStop(0.6, 'blue');
  gradient.addColorStop(0.75, 'indigo');
  gradient.addColorStop(1, 'violet');
  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, width, height);

  // Draw top lighter row
  ctx.fillStyle = 'rgba(255, 255, 255, 0.2)'; // Slightly lighten top row for visibility
  ctx.fillRect(0, 0, width, 1);

  // Draw bottom black row
  ctx.fillStyle = 'black';
  ctx.fillRect(0, height - 1, width, 1);

  // Prepare text properties
  ctx.fillStyle = 'white'; // Text color for contrast
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';

  // Text border setup
  ctx.strokeStyle = 'rgba(0, 0, 0, 0.5)'; // Use semi-transparent black for the border
  ctx.lineWidth = 1; // Use a full pixel but with transparency to simulate a finer line

  // Start with a large font size and decrease until text fits with padding
  let fontSize = 16; // Start with 16px font size
  let metrics;
  const padding = 2; // Minimum padding around text
  do {
    ctx.font = `${fontSize}px Verdana`;
    metrics = ctx.measureText(text);
    fontSize -= 1; // Reduce font size gradually
  } while (metrics.width > width - 2 * padding || fontSize > height - 2 * padding);

  // Draw text and border in the center of canvas
  ctx.strokeText(text, width / 2, height / 2); // Draw the border around the text
  ctx.fillText(text, width / 2, height / 2); // Fill the text

  return canvas;
}

// Example usage: append to body when window loads
window.onload = () => {
  // Normal type
  document.body.appendChild(createImage(64, 28, '#A8A878', 'Normal'));
  document.body.appendChild(createImage(64, 28, '#A8A878', 'Normal')); // German
  document.body.appendChild(createImage(64, 28, '#A8A878', 'Normal')); // French
  document.body.appendChild(createImage(64, 28, '#A8A878', 'Normal')); // Spanish
  document.body.appendChild(createImage(64, 28, '#A8A878', 'Normale')); // Italian
  document.body.appendChild(createImage(64, 28, '#A8A878', '一般')); // Chinese

  // Fire type
  document.body.appendChild(createImage(64, 28, '#F08030', 'Fire'));
  document.body.appendChild(createImage(64, 28, '#F08030', 'Feuer'));
  document.body.appendChild(createImage(64, 28, '#F08030', 'Feu'));
  document.body.appendChild(createImage(64, 28, '#F08030', 'Fuego'));
  document.body.appendChild(createImage(64, 28, '#F08030', 'Fuoco'));
  document.body.appendChild(createImage(64, 28, '#F08030', '火'));

  // Water type
  document.body.appendChild(createImage(64, 28, '#6890F0', 'Water'));
  document.body.appendChild(createImage(64, 28, '#6890F0', 'Wasser'));
  document.body.appendChild(createImage(64, 28, '#6890F0', 'Eau'));
  document.body.appendChild(createImage(64, 28, '#6890F0', 'Agua'));
  document.body.appendChild(createImage(64, 28, '#6890F0', 'Acqua'));
  document.body.appendChild(createImage(64, 28, '#6890F0', '水'));

  // Electric type
  document.body.appendChild(createImage(64, 28, '#F8D030', 'Electric'));
  document.body.appendChild(createImage(64, 28, '#F8D030', 'Elektro'));
  document.body.appendChild(createImage(64, 28, '#F8D030', 'Électrik'));
  document.body.appendChild(createImage(64, 28, '#F8D030', 'Eléctrico'));
  document.body.appendChild(createImage(64, 28, '#F8D030', 'Elettro'));
  document.body.appendChild(createImage(64, 28, '#F8D030', '电'));

  // Grass type
  document.body.appendChild(createImage(64, 28, '#78C850', 'Grass'));
  document.body.appendChild(createImage(64, 28, '#78C850', 'Pflanze'));
  document.body.appendChild(createImage(64, 28, '#78C850', 'Plante'));
  document.body.appendChild(createImage(64, 28, '#78C850', 'Planta'));
  document.body.appendChild(createImage(64, 28, '#78C850', 'Erba'));
  document.body.appendChild(createImage(64, 28, '#78C850', '草'));

  // Ice type
  document.body.appendChild(createImage(64, 28, '#98D8D8', 'Ice'));
  document.body.appendChild(createImage(64, 28, '#98D8D8', 'Eis'));
  document.body.appendChild(createImage(64, 28, '#98D8D8', 'Glace'));
  document.body.appendChild(createImage(64, 28, '#98D8D8', 'Hielo'));
  document.body.appendChild(createImage(64, 28, '#98D8D8', 'Ghiaccio'));
  document.body.appendChild(createImage(64, 28, '#98D8D8', '冰'));

  // Fighting type
  document.body.appendChild(createImage(64, 28, '#C03028', 'Fighting'));
  document.body.appendChild(createImage(64, 28, '#C03028', 'Kampf'));
  document.body.appendChild(createImage(64, 28, '#C03028', 'Combat'));
  document.body.appendChild(createImage(64, 28, '#C03028', 'Lucha'));
  document.body.appendChild(createImage(64, 28, '#C03028', 'Lotta'));
  document.body.appendChild(createImage(64, 28, '#C03028', '斗'));

  // Poison type
  document.body.appendChild(createImage(64, 28, '#A040A0', 'Poison'));
  document.body.appendChild(createImage(64, 28, '#A040A0', 'Gift'));
  document.body.appendChild(createImage(64, 28, '#A040A0', 'Poison'));
  document.body.appendChild(createImage(64, 28, '#A040A0', 'Veneno'));
  document.body.appendChild(createImage(64, 28, '#A040A0', 'Veleno'));
  document.body.appendChild(createImage(64, 28, '#A040A0', '毒'));

  // Ground type
  document.body.appendChild(createImage(64, 28, '#E0C068', 'Ground'));
  document.body.appendChild(createImage(64, 28, '#E0C068', 'Boden'));
  document.body.appendChild(createImage(64, 28, '#E0C068', 'Sol'));
  document.body.appendChild(createImage(64, 28, '#E0C068', 'Tierra'));
  document.body.appendChild(createImage(64, 28, '#E0C068', 'Terra'));
  document.body.appendChild(createImage(64, 28, '#E0C068', '地面'));

  // Flying type
  document.body.appendChild(createImage(64, 28, '#A890F0', 'Flying'));
  document.body.appendChild(createImage(64, 28, '#A890F0', 'Flug'));
  document.body.appendChild(createImage(64, 28, '#A890F0', 'Vol'));
  document.body.appendChild(createImage(64, 28, '#A890F0', 'Volador'));
  document.body.appendChild(createImage(64, 28, '#A890F0', 'Volante'));
  document.body.appendChild(createImage(64, 28, '#A890F0', '飞行'));

  // Psychic type
  document.body.appendChild(createImage(64, 28, '#F85888', 'Psychic'));
  document.body.appendChild(createImage(64, 28, '#F85888', 'Psycho'));
  document.body.appendChild(createImage(64, 28, '#F85888', 'Psy'));
  document.body.appendChild(createImage(64, 28, '#F85888', 'Psíquico'));
  document.body.appendChild(createImage(64, 28, '#F85888', 'Psico'));
  document.body.appendChild(createImage(64, 28, '#F85888', '超能'));

  // Bug type
  document.body.appendChild(createImage(64, 28, '#A8B820', 'Bug'));
  document.body.appendChild(createImage(64, 28, '#A8B820', 'Käfer'));
  document.body.appendChild(createImage(64, 28, '#A8B820', 'Insecte'));
  document.body.appendChild(createImage(64, 28, '#A8B820', 'Bicho'));
  document.body.appendChild(createImage(64, 28, '#A8B820', 'Coleottero'));
  document.body.appendChild(createImage(64, 28, '#A8B820', '虫'));

  // Rock type
  document.body.appendChild(createImage(64, 28, '#B8A038', 'Rock'));
  document.body.appendChild(createImage(64, 28, '#B8A038', 'Gestein'));
  document.body.appendChild(createImage(64, 28, '#B8A038', 'Roche'));
  document.body.appendChild(createImage(64, 28, '#B8A038', 'Roca'));
  document.body.appendChild(createImage(64, 28, '#B8A038', 'Roccia'));
  document.body.appendChild(createImage(64, 28, '#B8A038', '岩石'));

  // Ghost type
  document.body.appendChild(createImage(64, 28, '#705898', 'Ghost'));
  document.body.appendChild(createImage(64, 28, '#705898', 'Geist'));
  document.body.appendChild(createImage(64, 28, '#705898', 'Spectre'));
  document.body.appendChild(createImage(64, 28, '#705898', 'Fantasma'));
  document.body.appendChild(createImage(64, 28, '#705898', 'Fantasma'));
  document.body.appendChild(createImage(64, 28, '#705898', '幽灵'));

  // Dragon type
  document.body.appendChild(createImage(64, 28, '#7038F8', 'Dragon'));
  document.body.appendChild(createImage(64, 28, '#7038F8', 'Drache'));
  document.body.appendChild(createImage(64, 28, '#7038F8', 'Dragon'));
  document.body.appendChild(createImage(64, 28, '#7038F8', 'Dragón'));
  document.body.appendChild(createImage(64, 28, '#7038F8', 'Drago'));
  document.body.appendChild(createImage(64, 28, '#7038F8', '龙'));

  // Dark type
  document.body.appendChild(createImage(64, 28, '#705848', 'Dark'));
  document.body.appendChild(createImage(64, 28, '#705848', 'Unlicht'));
  document.body.appendChild(createImage(64, 28, '#705848', 'Ténèbres'));
  document.body.appendChild(createImage(64, 28, '#705848', 'Siniestro'));
  document.body.appendChild(createImage(64, 28, '#705848', 'Buio'));
  document.body.appendChild(createImage(64, 28, '#705848', '暗'));

  // Steel type
  document.body.appendChild(createImage(64, 28, '#B8B8D0', 'Steel'));
  document.body.appendChild(createImage(64, 28, '#B8B8D0', 'Stahl'));
  document.body.appendChild(createImage(64, 28, '#B8B8D0', 'Acier'));
  document.body.appendChild(createImage(64, 28, '#B8B8D0', 'Acero'));
  document.body.appendChild(createImage(64, 28, '#B8B8D0', 'Acciaio'));
  document.body.appendChild(createImage(64, 28, '#B8B8D0', '钢'));

  // Fairy type
  document.body.appendChild(createImage(64, 28, '#EE99AC', 'Fairy'));
  document.body.appendChild(createImage(64, 28, '#EE99AC', 'Fee'));
  document.body.appendChild(createImage(64, 28, '#EE99AC', 'Fée'));
  document.body.appendChild(createImage(64, 28, '#EE99AC', 'Hada'));
  document.body.appendChild(createImage(64, 28, '#EE99AC', 'Folletto'));
  document.body.appendChild(createImage(64, 28, '#EE99AC', '妖精'));

 // Stellar type
 document.body.appendChild(createRainbowImage(64, 28, 'Stellar'));
 document.body.appendChild(createRainbowImage(64, 28, 'Stellar'));
 document.body.appendChild(createRainbowImage(64, 28, 'Stellaire'));
 document.body.appendChild(createRainbowImage(64, 28, 'Astrale'));
 document.body.appendChild(createRainbowImage(64, 28, 'Stellar'));
 document.body.appendChild(createRainbowImage(64, 28, '星晶'));
};

Here is a image of what it created (100% scale):

image

CodeTappert commented 5 months ago

Ideas/a better implementation is welcome. Also i would like to hear from the dev team if something like this is even wanted

Adri1 commented 5 months ago

Also do not forget Stellar type!

CodeTappert commented 4 months ago

Added stellar type (updates the code in the main post too)

image

CodeTappert commented 4 months ago

Added stellar type (updates the code in the main post too)

image

But i see how the yellow part could make the text hard to read... Maybe we should add a border around the text

CodeTappert commented 4 months ago

image

Again made a change to the size and now the text has a minimal black border for redability. The icons now are 64x28 and thus (as far as i can tell) double the size of the ones currently used but in the same aspect ratio so it should be pretty easy to swap them out

CodeTappert commented 4 months ago

So i improved it again.

This code now runs locally and not in a browser and creates png files for every type:

const fs = require('fs');
const { createCanvas, registerFont} = require('canvas');

registerFont('./pokemon-emerald-pro.ttf', { family: 'Pokemon Emerald Pro' });

// Function to adjust the brightness of a hex color
function adjustBrightness(color, percent) {
    let r = parseInt(color.slice(1, 3), 16);
    let g = parseInt(color.slice(3, 5), 16);
    let b = parseInt(color.slice(5, 7), 16);

    r = Math.min(255, Math.max(0, r + Math.round(r * percent / 100)));
    g = Math.min(255, Math.max(0, g + Math.round(g * percent / 100)));
    b = Math.min(255, Math.max(0, b + Math.round(b * percent / 100)));

    return `#${(r << 16 | g << 8 | b).toString(16).padStart(6, '0')}`;
}

// Function to create a basic image with rounded corners and text
function createImage(width, height, backgroundColor, text, originalType,language = 'en', font = '20px Verdana') {
    const canvas = createCanvas(width, height);
    const ctx = canvas.getContext('2d');

    setupRoundedCorners(ctx, width, height);
    drawBackground(ctx, width, height, backgroundColor);
    drawText(ctx, width, height, text, language);

    saveImage(canvas, language,originalType);
}

// Function to create a rainbow image with specified text
function createRainbowImage(width, height, text, originalType, language = 'en', font = '20px Verdana') {
    const canvas = createCanvas(width, height);
    const ctx = canvas.getContext('2d');

    setupRoundedCorners(ctx, width, height);
    drawRainbowBackground(ctx, width, height);
    drawText(ctx, width, height, text, language);

    saveImage(canvas, language,originalType);
}

// Set up rounded corners
function setupRoundedCorners(ctx, width, height) {
    const radius = 4;
    ctx.beginPath();
    ctx.moveTo(radius, 0);
    ctx.lineTo(width - radius, 0);
    ctx.quadraticCurveTo(width, 0, width, radius);
    ctx.lineTo(width, height - radius);
    ctx.quadraticCurveTo(width, height, width - radius, height);
    ctx.lineTo(radius, height);
    ctx.quadraticCurveTo(0, height, 0, height - radius);
    ctx.lineTo(0, radius);
    ctx.quadraticCurveTo(0, 0, radius, 0);
    ctx.closePath();
    ctx.clip();
}

// Draw background with a lighter top and black bottom row
function drawBackground(ctx, width, height, backgroundColor) {
    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, width, height);
    ctx.fillStyle = adjustBrightness(backgroundColor, 20);
    ctx.fillRect(0, 0, width, 1);
    ctx.fillStyle = 'black';
    ctx.fillRect(0, height - 1, width, 1);
}

// Draw rainbow gradient background
function drawRainbowBackground(ctx, width, height) {
    const gradient = ctx.createLinearGradient(0, 0, width, 0);
    gradient.addColorStop(0, 'red');
    gradient.addColorStop(0.15, 'orange');
    gradient.addColorStop(0.3, 'yellow');
    gradient.addColorStop(0.45, 'green');
    gradient.addColorStop(0.6, 'blue');
    gradient.addColorStop(0.75, 'indigo');
    gradient.addColorStop(1, 'violet');
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, width, height);
    ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
    ctx.fillRect(0, 0, width, 1);
    ctx.fillStyle = 'black';
    ctx.fillRect(0, height - 1, width, 1);
}

// Draw text centered with border
function drawText(ctx, width, height, text,language) {
    ctx.fillStyle = 'white';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.strokeStyle = 'black';
    ctx.lineWidth = 3;

    let fontSize = 45;
    let metrics;
    const padding = 2;
    do {
        if (language === 'zhCN') {
            ctx.font = `${fontSize}px Microsoft YaHei:`;
        } else {
            ctx.font = `${fontSize}px Pokemon Emerald Pro`;
        }
        metrics = ctx.measureText(text);
        fontSize -= 1;
    } while (metrics.width > width - 2 * padding || fontSize > height - 2 * padding);

    ctx.strokeText(text, width / 2, height / 2);
    ctx.fillText(text, width / 2, height / 2);
}

// Save image to a file
function saveImage(canvas, language,typename) {
    const buffer = canvas.toBuffer('image/png');
    if (!fs.existsSync('types')) {
        fs.mkdirSync('types');
    }
    if (!fs.existsSync(`types/${language}`)) {
        fs.mkdirSync(`types/${language}`);
    }
    fs.writeFileSync(`types/${language}/${typename}.png`, buffer);
}

// Generate example images
// Normal type
createImage(128,56, '#A8A878', 'Normal','normal','en');
createImage(128,56, '#A8A878', 'Normal','normal','de');
createImage(128,56, '#A8A878', 'Normal','normal','fr');
createImage(128,56, '#A8A878', 'Normal','normal','es');
createImage(128,56, '#A8A878', 'Normale','normal','it');
createImage(128,56, '#A8A878', '一般','normal','zhCN');

// Fire type
createImage(128,56, '#F08030', 'Fire','fire','en');
createImage(128,56, '#F08030', 'Feuer','fire','de');
createImage(128,56, '#F08030', 'Feu','fire','fr');
createImage(128,56, '#F08030', 'Fuego','fire','es');
createImage(128,56, '#F08030', 'Fuoco','fire','it');
createImage(128,56, '#F08030', '火','fire','zhCN');

// Water type
createImage(128,56, '#6890F0', 'Water','water','en');
createImage(128,56, '#6890F0', 'Wasser','water','de');
createImage(128,56, '#6890F0', 'Eau','water','fr');
createImage(128,56, '#6890F0', 'Agua','water','es');
createImage(128,56, '#6890F0', 'Acqua','water','it');
createImage(128,56, '#6890F0', '水','water','zhCN');

// Electric type
createImage(128,56, '#F8D030', 'Electric','electric','en');
createImage(128,56, '#F8D030', 'Elektro','electric','de');
createImage(128,56, '#F8D030', 'Électrik','electric','fr');
createImage(128,56, '#F8D030', 'Eléctrico','electric','es');
createImage(128,56, '#F8D030', 'Elettro','electric','it');
createImage(128,56, '#F8D030', '电','electric','zhCN');

// Grass type
createImage(128,56, '#78C850', 'Grass','grass','en');
createImage(128,56, '#78C850', 'Pflanze','grass','de');
createImage(128,56, '#78C850', 'Plante','grass','fr');
createImage(128,56, '#78C850', 'Planta','grass','es');
createImage(128,56, '#78C850', 'Erba','grass','it');
createImage(128,56, '#78C850', '草','grass','zhCN');

// Ice type
createImage(128,56, '#98D8D8', 'Ice','ice','en');
createImage(128,56, '#98D8D8', 'Eis','ice','de');
createImage(128,56, '#98D8D8', 'Glace','ice','fr');
createImage(128,56, '#98D8D8', 'Hielo','ice','es');
createImage(128,56, '#98D8D8', 'Ghiaccio','ice','it');
createImage(128,56, '#98D8D8', '冰','ice','zhCN');

// Fighting type
createImage(128,56, '#C03028', 'Fighting','fighting','en');
createImage(128,56, '#C03028', 'Kampf','fighting','de');
createImage(128,56, '#C03028', 'Combat','fighting','fr');
createImage(128,56, '#C03028', 'Lucha','fighting','es');
createImage(128,56, '#C03028', 'Lotta','fighting','it');
createImage(128,56, '#C03028', '斗','fighting','zhCN');

// Poison type
createImage(128,56, '#A040A0', 'Poison','poison','en');
createImage(128,56, '#A040A0', 'Gift','poison','de');
createImage(128,56, '#A040A0', 'Poison','poison','fr');
createImage(128,56, '#A040A0', 'Veneno','poison','es');
createImage(128,56, '#A040A0', 'Veleno','poison','it');
createImage(128,56, '#A040A0', '毒','poison','zhCN');

// Ground type
createImage(128,56, '#E0C068', 'Ground','ground','en');
createImage(128,56, '#E0C068', 'Boden','ground','de');
createImage(128,56, '#E0C068', 'Sol','ground','fr');
createImage(128,56, '#E0C068', 'Tierra','ground','es');
createImage(128,56, '#E0C068', 'Terra','ground','it');
createImage(128,56, '#E0C068', '地面','ground','zhCN');

// Flying type
createImage(128,56, '#A890F0', 'Flying','flying','en');
createImage(128,56, '#A890F0', 'Flug','flying','de');
createImage(128,56, '#A890F0', 'Vol','flying','fr');
createImage(128,56, '#A890F0', 'Volador','flying','es');
createImage(128,56, '#A890F0', 'Volante','flying','it');
createImage(128,56, '#A890F0', '飞行','flying','zhCN');

// Psychic type
createImage(128,56, '#F85888', 'Psychic','psychic','en');
createImage(128,56, '#F85888', 'Psycho','psychic','de');
createImage(128,56, '#F85888', 'Psy','psychic','fr');
createImage(128,56, '#F85888', 'Psíquico','psychic','es');
createImage(128,56, '#F85888', 'Psico','psychic','it');
createImage(128,56, '#F85888', '超能','psychic','zhCN');

// Bug type
createImage(128,56, '#A8B820', 'Bug','bug','en');
createImage(128,56, '#A8B820', 'Käfer','bug','de');
createImage(128,56, '#A8B820', 'Insecte','bug','fr');
createImage(128,56, '#A8B820', 'Bicho','bug','es');
createImage(128,56, '#A8B820', 'Coleottero','bug','it');
createImage(128,56, '#A8B820', '虫','bug','zhCN');

// Rock type
createImage(128,56, '#B8A038', 'Rock','rock','en');
createImage(128,56, '#B8A038', 'Gestein','rock','de');
createImage(128,56, '#B8A038', 'Roche','rock','fr');
createImage(128,56, '#B8A038', 'Roca','rock','es');
createImage(128,56, '#B8A038', 'Roccia','rock','it');
createImage(128,56, '#B8A038', '岩石','rock','zhCN');

// Ghost type
createImage(128,56, '#705898', 'Ghost','ghost','en');
createImage(128,56, '#705898', 'Geist','ghost','de');
createImage(128,56, '#705898', 'Spectre','ghost','fr');
createImage(128,56, '#705898', 'Fantasma','ghost','es');
createImage(128,56, '#705898', 'Fantasma','ghost','it');
createImage(128,56, '#705898', '幽灵','ghost','zhCN');

// Dragon type
createImage(128,56, '#7038F8', 'Dragon','dragon','en');
createImage(128,56, '#7038F8', 'Drache','dragon','de');
createImage(128,56, '#7038F8', 'Dragon','dragon','fr');
createImage(128,56, '#7038F8', 'Dragón','dragon','es');
createImage(128,56, '#7038F8', 'Drago','dragon','it');
createImage(128,56, '#7038F8', '龙','dragon','zhCN');

// Dark type
createImage(128,56, '#705848', 'Dark','dark','en');
createImage(128,56, '#705848', 'Unlicht','dark','de');
createImage(128,56, '#705848', 'Ténèbres','dark','fr');
createImage(128,56, '#705848', 'Siniestro','dark','es');
createImage(128,56, '#705848', 'Buio','dark','it');
createImage(128,56, '#705848', '暗','dark','zhCN');

// Steel type
createImage(128,56, '#B8B8D0', 'Steel','steel','en');
createImage(128,56, '#B8B8D0', 'Stahl','steel','de');
createImage(128,56, '#B8B8D0', 'Acier','steel','fr');
createImage(128,56, '#B8B8D0', 'Acero','steel','es');
createImage(128,56, '#B8B8D0', 'Acciaio','steel','it');
createImage(128,56, '#B8B8D0', '钢','steel','zhCN');

// Fairy type
createImage(128,56, '#EE99AC', 'Fairy','fairy','en');
createImage(128,56, '#EE99AC', 'Fee','fairy','de');
createImage(128,56, '#EE99AC', 'Fée','fairy','fr');
createImage(128,56, '#EE99AC', 'Hada','fairy','es');
createImage(128,56, '#EE99AC', 'Folletto','fairy','it');
createImage(128,56, '#EE99AC', '妖精','fairy','zhCN');

// Stellar type
createRainbowImage(128,56, 'Stellar','stellar','en');
createRainbowImage(128,56, 'Stellar','stellar','de');
createRainbowImage(128,56, 'Stellaire','stellar','fr');
createRainbowImage(128,56, 'Astral','stellar','es');
createRainbowImage(128,56, 'Astrale','stellar','it');
createRainbowImage(128,56, '星晶','stellar','zhCN');

I think it is still easier to use image files in the game like it is currently thus i created this creator. This can easily can be expanded for new languages

Currently this uses a default windows font for chinese. and the pokemon emerald font for everything else.

Example screenshot for the german files: image

Here a zip of files it created. types.zip

CodeTappert commented 4 months ago

There seems to be some problems with the chinese text... I will look for a solution

CodeTappert commented 4 months ago

There seems to be some problems with the chinese text... I will look for a solution

Fixed and updated in the last code i posted here

CodeTappert commented 4 months ago

Will be talked about (and maybe used) in #789 But this here will be closed