31 Aug

Extracting text from PSD files

Typically, we need to translate hundreds of strings when localizing our games. Most strings are text messages which the game loads from some database or simple text file. However, we often have to handle localization of several PNG images, such as the one below.

AWESOME! message in DragonScales

Such PNG images are exported from PSD files which must obviously contain at least one Text Layer. To speed up the localization process we have a little Photoshop script which opens the PSD files and extracts all the text we have to translate. PSD files are grouped in directories corresponding to the tileset they belong to. For instance, this would be a typical directory structure for the DragonScales games:

images/
    board/
        awesome.psd, great.psd, ...
    cards
        youwin.psd, sorry.psd, ...
    ending
        congratulations.psd, ...
    levelselect
        clickhere.psd, ...
    mainmenu
        welcome.psd, ...
    etc

A simplified but functional version of the script we use is this:

#target photoshop

var target = "/C/projects/ds/images";
var toLocalize = new Array();
var totalProcessed = 0;
var warningsFiles = new Array();

function log(msg) {
	$.writeln(msg);
}

function processPSDFolder(dir) {
	var files = dir.getFiles("*.psd");
    log("===============================================");
    log(dir + " -> "+ files.length);
    log("===============================================");
	for (var i = 0; i < files.length; i++) {
    	var doc = app.open(files[i]);
    	log("  file: " + files[i]);
        totalProcessed++;
        if ( doc.artLayers.length == 0 ) {
            log("   -> WARNING: ZERO TEXT LAYERS? THEY SHOULD NOT BE IN GROUPS.");
            warningsFiles.push(files[i]);
        }
    	for (var j = 0; j < doc.artLayers.length; j++) {
        	var lyr = doc.artLayers[j];
        	if (lyr.kind == LayerKind.TEXT) {
            	var lyr = doc.artLayers[j];
            	log("   ->" + lyr.textItem.contents);
            	toLocalize.push(lyr.textItem.contents);
        	}
     	}
    	doc.close(SaveOptions.DONOTSAVECHANGES);
	}
}

function saveStrings() {
	var out = new File(target + "/strings.txt");
	out.open("w");
	for (var i = 0; i < toLocalize.length; i++) {
		var str = toLocalize[i];
		out.writeln(str);
	}
 	out.close();
}

var root = Folder(target).getFiles();
for ( var i = 0; i < root.length; i++ ) {
	var fileFoldObj = root[i];
	if ( fileFoldObj instanceof File ) {         
        // Discard files at this level
	} else {
         processPSDFolder( Folder(fileFoldObj) );
	}
}
saveStrings();
log("Total PSDs processed: " + totalProcessed);
log("Warnings: " + warningsFiles.length);
for ( var i = 0; i < warningsFiles.length; i++ ) {
	log(" " + warningsFiles[i]);
}

Observations:

  • target is the path to your directory structure holding the PSD files.
  • The strings to be translated will we written to file strings.txt under your target directory.
  • This script looks for text layers on the top level of the PSD. It can be easily extended to inspect layers in groups, though.
  • We use warnings to be notified about files not containing Text Layers. These might be files requiring special exporting and extra formatting, and therefore we’ll have to handle such files exceptionally.
20 Nov

DragonScales: Drawing the Sacred Axe item

Our newest game, DragonScales: Chambers of The Dragon Whisperer, is the first title of ours which does not use cartoon graphics. The art of DragonScales meant a lot of work, as we had to create more realistic characters and backgrounds, within a fantasy setting. For instance, here are the steps followed to create the Axe used in-game for the Sacred Axe item which destroys a column of scales on the board.

AxeStepsEnglish

This Sacred Axe, of course, was designed by XKlibur, our lead artist and IKIGames’ mastermind. Hope you liked it!