bitmap fonts

This commit is contained in:
Krzysztof Opalka 2013-05-06 19:12:25 +02:00
parent 89ca071ab2
commit ae98487b16
10 changed files with 2311 additions and 174 deletions

View file

@ -17,6 +17,8 @@ module.exports = function(grunt) {
'<%= dirs.src %>/DisplayObjectContainer.js',
'<%= dirs.src %>/Sprite.js',
'<%= dirs.src %>/MovieClip.js',
'<%= dirs.src %>/text/Text.js',
'<%= dirs.src %>/text/BitmapText.js',
'<%= dirs.src %>/Text.js',
'<%= dirs.src %>/InteractionManager.js',
'<%= dirs.src %>/Stage.js',
@ -33,8 +35,10 @@ module.exports = function(grunt) {
'<%= dirs.src %>/extras/TilingSprite.js',
'<%= dirs.src %>/textures/BaseTexture.js',
'<%= dirs.src %>/textures/Texture.js',
'<%= dirs.src %>/loaders/SpriteSheetLoader.js',
'<%= dirs.src %>/loaders/AssetLoader.js',
'<%= dirs.src %>/loaders/SpriteSheetLoader.js',
'<%= dirs.src %>/loaders/ImageLoader.js',
'<%= dirs.src %>/loaders/BitmapFontLoader.js',
'<%= dirs.src %>/Outro.js'
], banner = [
'/**',

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

View file

@ -26,8 +26,8 @@
active: function() {
// do something
init();
},
}
};
(function() {
var wf = document.createElement('script');
@ -38,59 +38,75 @@
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(wf, s);
})();
function init()
{
var assetsToLoader = ["desyrel.fnt"];
// create a new loader
var loader = new PIXI.AssetLoader(assetsToLoader);
// use callback
loader.onComplete = onAssetsLoaded;
//begin load
loader.load();
function onAssetsLoaded()
{
var bitmapFontText = new PIXI.BitmapText("bitmap fonts are\n now supported!", {font: "35px Desyrel", align: "right"});
bitmapFontText.position.x = 620 - bitmapFontText.width - 20;
bitmapFontText.position.y = 20;
stage.addChild(bitmapFontText);
}
// create an new instance of a pixi stage
var stage = new PIXI.Stage(0x66FF99);
// add a shiney background..
var background = PIXI.Sprite.fromImage("textDemoBG.jpg");
stage.addChild(background);
// create a renderer instance
var renderer = PIXI.autoDetectRenderer(620, 400);
// add the renderer view element to the DOM
document.body.appendChild(renderer.view);
requestAnimFrame( animate );
// creat some white text using the Snippet webfont
var textSample = new PIXI.Text("Pixi.js can has\nmultiline text!", {font: "50px Snippet", fill: "white", align: "center"});
textSample.anchor.x = 0.5;
textSample.position.x = 620/2;
textSample.position.y = 10;
requestAnimFrame(animate);
// create some white text using the Snippet webfont
var textSample = new PIXI.Text("Pixi.js can has\nmultiline text!", {font: "35px Snippet", fill: "white", align: "left"});
textSample.position.x = 20;
textSample.position.y = 20;
// create a text object with a nice stroke
var spinningText = new PIXI.Text("I'm fun!", {font: "bold 60px Podkova", fill: "#cc00ff", align: "center", stroke: "#FFFFFF", strokeThickness: 6});
// setting the anchor point to 0.5 will center align the text... great for spinning!
spinningText.anchor.x = spinningText.anchor.y = 0.5;
spinningText.position.x = 620/2;
spinningText.position.y = 400/2;
spinningText.position.x = 620 / 2;
spinningText.position.y = 400 / 2;
// create a text object that will be updated..
var countingText = new PIXI.Text("COUNT 4EVAR: 0", {font: "bold italic 60px Arvo", fill: "#3e1707", align: "center", stroke: "#a4410e", strokeThickness: 7});
countingText.position.x = 620/2;
countingText.position.x = 620 / 2;
countingText.position.y = 320;
countingText.anchor.x = 0.5;
stage.addChild(textSample);
stage.addChild(spinningText);
stage.addChild(countingText);
count = 0;
score = 0;
var count = 0;
var score = 0;
function animate() {
requestAnimFrame( animate );
count++;
if(count == 50)
{
count = 0;
score ++
score++;
// update the text...
countingText.setText("COUNT 4EVAR: " + score )
countingText.setText("COUNT 4EVAR: " + score);
}
// just for fun, lets rotate the text
spinningText.rotation += 0.03;

View file

@ -23,6 +23,16 @@ PIXI.AssetLoader = function(assetURLs)
this.assetURLs = assetURLs;
this.crossorigin = false;
this.loadersByType = {
"jpg": PIXI.ImageLoader,
"jpeg": PIXI.ImageLoader,
"png": PIXI.ImageLoader,
"gif": PIXI.ImageLoader,
"json": PIXI.SpriteSheetLoader,
"xml": PIXI.BitmapFontLoader,
"fnt": PIXI.BitmapFontLoader
};
};
/**
@ -52,7 +62,9 @@ PIXI.AssetLoader.prototype.load = function()
var fileName = this.assetURLs[i];
var fileType = fileName.split(".").pop().toLowerCase();
var loaderClass = this.getLoaderByFileType(fileType);
var loaderClass = this.loadersByType[fileType];
if(!loaderClass)
throw new Error(fileType + " is an unsupported file type");
var loader = new loaderClass(fileName, this.crossorigin);
@ -64,32 +76,6 @@ PIXI.AssetLoader.prototype.load = function()
}
};
/**
* Factory method for getting loader class based on extension
* @private
* @param {String} fileType An extension of the file based on which the loader class will be returned
* @return {Class} The loader class
*/
PIXI.AssetLoader.prototype.getLoaderByFileType = function(fileType)
{
switch (fileType)
{
case "jpeg":
case "jpg":
case "png":
case "gif":
return PIXI.ImageLoader;
case "json":
return PIXI.SpriteSheetLoader;
case "xml":
case "fnt":
return PIXI.XMLLoader;
}
throw new Error(fileType + " is an unsupported file type " + this);
};
/**
* Invoked after each file is loaded
* @private

View file

@ -0,0 +1,125 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* The xml loader is used to load in XML bitmap font data ("xml" or "fnt")
* To generate the data you can use http://www.angelcode.com/products/bmfont/
* This loader will also load the image file as the data.
* When loaded this class will dispatch a "loaded" event
* @class BitmapFontLoader
* @extends EventTarget
* @constructor
* @param {String} url the url of the sprite sheet JSON file
* @param {Boolean} crossorigin
*/
PIXI.BitmapFontLoader = function(url, crossorigin)
{
/*
* i use texture packer to load the assets..
* http://www.codeandweb.com/texturepacker
* make sure to set the format as "JSON"
*/
PIXI.EventTarget.call(this);
this.url = url;
this.baseUrl = url.replace(/[^\/]*$/, "");
this.texture = null;
this.crossorigin = crossorigin;
};
// constructor
PIXI.BitmapFontLoader.constructor = PIXI.BitmapFontLoader;
/**
* This will begin loading the JSON file
*/
PIXI.BitmapFontLoader.prototype.load = function()
{
this.ajaxRequest = new XMLHttpRequest();
var scope = this;
this.ajaxRequest.onreadystatechange = function()
{
scope.onXMLLoaded();
};
this.ajaxRequest.open("GET", this.url, true);
if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/xml");
this.ajaxRequest.send(null)
};
/**
* Invoked when XML file is loaded
* @private
*/
PIXI.BitmapFontLoader.prototype.onXMLLoaded = function()
{
if (this.ajaxRequest.readyState == 4)
{
if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1)
{
var textureUrl = this.baseUrl + this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue;
var image = new PIXI.ImageLoader(textureUrl, this.crossorigin);
this.texture = image.texture.baseTexture;
var data = {};
var info = this.ajaxRequest.responseXML.getElementsByTagName("info")[0];
var common = this.ajaxRequest.responseXML.getElementsByTagName("common")[0];
data.font = info.attributes.getNamedItem("face").nodeValue;
data.size = parseInt(info.attributes.getNamedItem("size").nodeValue, 10);
data.lineHeight = parseInt(common.attributes.getNamedItem("lineHeight").nodeValue, 10);
data.chars = {};
//parse letters
var letters = this.ajaxRequest.responseXML.getElementsByTagName("char");
for (var i = 0; i < letters.length; i++)
{
var charCode = parseInt(letters[i].attributes.getNamedItem("id").nodeValue, 10);
var textureRect = {
x: parseInt(letters[i].attributes.getNamedItem("x").nodeValue, 10),
y: parseInt(letters[i].attributes.getNamedItem("y").nodeValue, 10),
width: parseInt(letters[i].attributes.getNamedItem("width").nodeValue, 10),
height: parseInt(letters[i].attributes.getNamedItem("height").nodeValue, 10)
};
PIXI.TextureCache[charCode] = new PIXI.Texture(this.texture, textureRect);
data.chars[charCode] = {
xOffset: parseInt(letters[i].attributes.getNamedItem("xoffset").nodeValue, 10),
yOffset: parseInt(letters[i].attributes.getNamedItem("yoffset").nodeValue, 10),
xAdvance: parseInt(letters[i].attributes.getNamedItem("xadvance").nodeValue, 10),
kerning: {}
};
}
//parse kernings
var kernings = this.ajaxRequest.responseXML.getElementsByTagName("kerning");
for (i = 0; i < kernings.length; i++)
{
var first = parseInt(kernings[i].attributes.getNamedItem("first").nodeValue, 10);
var second = parseInt(kernings[i].attributes.getNamedItem("second").nodeValue, 10);
var amount = parseInt(kernings[i].attributes.getNamedItem("amount").nodeValue, 10);
data.chars[second].kerning[first] = amount;
}
PIXI.BitmapText.fonts[data.font] = data;
var scope = this;
image.addEventListener("loaded", function() {
scope.onLoaded();
});
image.load();
}
}
};
/**
* Invoked when all files are loaded (xml/fnt and texture)
* @private
*/
PIXI.BitmapFontLoader.prototype.onLoaded = function()
{
this.dispatchEvent({type: "loaded", content: this});
};

View file

@ -13,7 +13,7 @@
* @class SpriteSheetLoader
* @extends EventTarget
* @constructor
* @param url {String} the url of the sprite sheet JSON file
* @param {String} url the url of the sprite sheet JSON file
* @param {Boolean} crossorigin
*/

View file

@ -1,79 +0,0 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* The xml loader is used to load in XML bitmap font data ("xml" or "fnt")
* To generate the data you can use http://www.angelcode.com/products/bmfont/
* This loader will also load the image file as the data.
* When loaded this class will dispatch a "loaded" event
* @class XMLLoader
* @extends EventTarget
* @constructor
* @param url {String} the url of the sprite sheet JSON file
* @param {Boolean} crossorigin
*/
PIXI.XMLLoader = function(url, crossorigin)
{
/*
* i use texture packer to load the assets..
* http://www.codeandweb.com/texturepacker
* make sure to set the format as "JSON"
*/
PIXI.EventTarget.call(this);
this.url = url;
this.baseUrl = url.replace(/[^\/]*$/, "");
this.texture = null;
this.crossorigin = crossorigin;
};
// constructor
PIXI.XMLLoader.constructor = PIXI.XMLLoader;
/**
* This will begin loading the JSON file
*/
PIXI.XMLLoader.prototype.load = function()
{
this.ajaxRequest = new XMLHttpRequest();
var scope = this;
this.ajaxRequest.onreadystatechange = function()
{
scope.onXMLLoaded();
};
this.ajaxRequest.open("GET", this.url, true);
if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/xml");
this.ajaxRequest.send(null)
};
/**
* Invoked when XML file is loaded
* @private
*/
PIXI.XMLLoader.prototype.onXMLLoaded = function()
{
if (this.ajaxRequest.readyState == 4)
{
if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1)
{
var textureUrl = this.baseUrl + this.ajaxRequest.responseXML.getElementsByTagName("page")[0].attributes.getNamedItem("file").nodeValue;
var image = new PIXI.ImageLoader(textureUrl, this.crossorigin);
var scope = this;
image.addEventListener("loaded", function() {
scope.onLoaded();
});
image.load();
}
}
};
/**
* Invoked when all files are loaded (xml/fnt and texture)
* @private
*/
PIXI.XMLLoader.prototype.onLoaded = function()
{
this.dispatchEvent({type: "loaded", content: this});
};

157
src/pixi/text/BitmapText.js Normal file
View file

@ -0,0 +1,157 @@
/**
* @author Mat Groves http://matgroves.com/ @Doormat23
*/
/**
* A Text Object will create a line(s) of text using bitmap font
* @class DisplayObjectContainer
* @extends Sprite
* @constructor
* @param {String} text The copy that you would like the text to display
* @param {Object} [style] The style parameters
* @param {Object} [style.font="bold 20pt Arial"] The style and size of the font
* @param {Object} [style.fill="black"] A canvas fillstyle that will be used on the text eg "red", "#00FF00"
* @param {String} [style.align="left"] An alignment of the multiline text ("left", "center" or "right")
* @param {String} [style.stroke] A canvas fillstyle that will be used on the text stroke eg "blue", "#FCFF00"
* @param {Number} [style.strokeThickness=0] A number that represents the thickness of the stroke. Default is 0 (no stroke)
*/
PIXI.BitmapText = function(text, style)
{
this.canvas = document.createElement("canvas");
this.context = this.canvas.getContext("2d");
PIXI.DisplayObjectContainer.call(this, PIXI.Texture.fromCanvas(this.canvas));
this.setText(text);
this.setStyle(style);
this.updateText();
this.dirty = false
};
// constructor
PIXI.BitmapText.constructor = PIXI.BitmapText;
PIXI.BitmapText.prototype = Object.create(PIXI.DisplayObjectContainer.prototype);
/**
* Set the copy for the text object
* @methos setText
* @param {String} text The copy that you would like the text to display
*/
PIXI.BitmapText.prototype.setText = function(text)
{
this.text = text || " ";
this.dirty = true;
};
/**
* Set the style of the text
* @method setStyle
* @param {Object} [style] The style parameters
* @param {Object} style.font The style and size of the font. If font size is not specified, it uses default bitmap font size. Font name is required
* @param {String} [style.align="left"] An alignment of the multiline text ("left", "center" or "right")
*/
PIXI.BitmapText.prototype.setStyle = function(style)
{
style = style || {};
style.align = style.align || "left";
this.style = style;
var font = style.font.split(" ");
this.fontName = font[font.length - 1];
this.fontSize = font.length >= 2 ? parseInt(font[font.length - 2], 10) : PIXI.BitmapText.fonts[this.fontName].size;
this.dirty = true;
};
/**
* Renders text
* @private
*/
PIXI.BitmapText.prototype.updateText = function()
{
var data = PIXI.BitmapText.fonts[this.fontName];
var pos = new PIXI.Point();
var prevCharCode = null;
var chars = [];
var maxLineWidth = 0;
var lineWidths = [];
var line = 0;
var scale = this.fontSize / data.size;
for(var i = 0; i < this.text.length; i++)
{
var charCode = this.text.charCodeAt(i);
if(charCode == "\n".charCodeAt(0))
{
lineWidths.push(pos.x);
maxLineWidth = Math.max(maxLineWidth, pos.x);
line++;
pos.x = 0;
pos.y += data.lineHeight;
prevCharCode = null;
continue;
}
var charData = data.chars[charCode];
if(!charData) continue;
if(prevCharCode && charData[prevCharCode])
{
pos.x += charData.kerning[prevCharCode];
}
chars.push({line: line, charCode: charCode, position: new PIXI.Point(pos.x + charData.xOffset, pos.y + charData.yOffset)});
pos.x += charData.xAdvance;
prevCharCode = charCode;
}
lineWidths.push(pos.x);
maxLineWidth = Math.max(maxLineWidth, pos.x);
var lineAlignOffsets = [];
for(i = 0; i <= line; i++)
{
var alignOffset = 0;
if(this.style.align == "right")
{
alignOffset = maxLineWidth - lineWidths[i];
}
else if(this.style.align == "center")
{
alignOffset = (maxLineWidth - lineWidths[i]) / 2;
}
lineAlignOffsets.push(alignOffset);
}
for(i = 0; i < chars.length; i++)
{
var char = PIXI.Sprite.fromFrame(chars[i].charCode);
char.position.x = (chars[i].position.x + lineAlignOffsets[chars[i].line]) * scale;
char.position.y = chars[i].position.y * scale;
char.scale.x = char.scale.y = scale;
this.addChild(char);
}
this.width = pos.x * scale;
this.height = (pos.y + data.lineHeight) * scale;
};
/**
* @private
*/
PIXI.BitmapText.prototype.updateTransform = function()
{
if(this.dirty)
{
while(this.children.length > 0)
{
this.removeChild(this.getChildAt(0));
}
this.updateText();
this.dirty = false;
}
PIXI.DisplayObjectContainer.prototype.updateTransform.call(this);
};
PIXI.BitmapText.fonts = {};

View file

@ -17,35 +17,20 @@
*/
PIXI.Text = function(text, style)
{
this.canvas = document.createElement("canvas");
this.context = this.canvas.getContext("2d");
//document.body.appendChild(this.canvas);
this.setText(text);
this.setStyle(style);
this.updateText();
PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas));
// need to store a canvas that can
this.canvas = document.createElement("canvas");
this.context = this.canvas.getContext("2d");
PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas));
this.setText(text);
this.setStyle(style);
this.updateText();
this.dirty = false;
};
// constructor
PIXI.Text.constructor = PIXI.Text;
PIXI.Text.prototype = Object.create(PIXI.Sprite.prototype);
/**
* Set the copy for the text object
* @methos setText
* @param {String} text The copy that you would like the text to display
*/
PIXI.Text.prototype.setText = function(text)
{
this.text = text || " ";
this.dirty = true;
};
/**
* Set the style of the text
* @method setStyle
@ -58,18 +43,29 @@ PIXI.Text.prototype.setText = function(text)
*/
PIXI.Text.prototype.setStyle = function(style)
{
style = style || {};
style.font = style.font || "bold 20pt Arial";
style.fill = style.fill || "black";
style.align = style.align || "left";
style.strokeThickness = style.strokeThickness || 0;
style = style || {};
style.font = style.font || "bold 20pt Arial";
style.fill = style.fill || "black";
style.align = style.align || "left";
style.strokeThickness = style.strokeThickness || 0;
this.style = style;
this.style = style;
this.dirty = true;
this.dirty = true;
};
/**
* Set the copy for the text object
* @methos setText
* @param {String} text The copy that you would like the text to display
*/
PIXI.Sprite.prototype.setText = function(text)
{
this.text = text || " ";
this.dirty = true;
};
/**
* Renders text
* @private
*/
PIXI.Text.prototype.updateText = function()
@ -126,21 +122,31 @@ PIXI.Text.prototype.updateText = function()
this.context.fillText(lines[i], linePosition.x, linePosition.y);
}
}
this.updateTexture();
};
/**
* Updates texture size based on canvas size
* @private
*/
PIXI.Text.prototype.updateTexture = function()
{
this.texture.baseTexture.width = this.canvas.width;
this.texture.baseTexture.height = this.canvas.height;
this.texture.frame.width = this.canvas.width;
this.texture.frame.height = this.canvas.height;
PIXI.texturesToUpdate.push(this.texture.baseTexture);
};
/**
* @private
*/
PIXI.Text.prototype.updateTransform = function()
{
if(this.dirty)
{
this.updateText();
// update the texture..
this.texture.baseTexture.width = this.canvas.width;
this.texture.baseTexture.height = this.canvas.height;
this.texture.frame.width = this.canvas.width;
this.texture.frame.height = this.canvas.height;
PIXI.texturesToUpdate.push(this.texture.baseTexture);
this.dirty = false;
}
@ -153,7 +159,7 @@ PIXI.Text.prototype.updateTransform = function()
*/
PIXI.Text.prototype.determineFontHeight = function(fontStyle)
{
// build a little refference dictionary so if the font style has been used return a
// build a little reference dictionary so if the font style has been used return a
// cached version...
var result = PIXI.Text.heightCache[fontStyle];