pixelbox
Version:
A framework to fast-prototype pixel-based games
226 lines (198 loc) • 7.14 kB
JavaScript
var Texture = require('./index.js');
var minitext = require('./minitext');
var CHAR_PER_LINE = 16;
var CHAR_WIDTH = 4;
var CHAR_HEIGHT = 6;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
function Charset(template) {
if (!template._isTexture) {
var texture = new Texture(template.width, template.height);
texture.draw(template, 0, 0);
template = texture;
}
this.template = template;
this.colors = {};
}
Charset.prototype.getColor = function (colorString) {
if (this.colors[colorString]) return this.colors[colorString];
var w = this.template.width;
var h = this.template.height;
var texture = new Texture(w, h);
// copy image and change color
texture.clear();
texture.ctx.fillStyle = colorString;
texture.ctx.fillRect(0, 0, w, h);
texture.ctx.globalCompositeOperation = 'destination-in';
texture.ctx.drawImage(this.template.canvas, 0, 0);
var canvas = texture.canvas;
this.colors[colorString] = canvas;
return canvas;
};
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
var _resize = Texture.prototype.resize;
Texture.prototype.resize = function (width, height) {
this._cursor.i = 0;
this._cursor.j = 0;
_resize.call(this, width, height);
return this;
};
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
Texture.prototype.cls = function () {
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
this.locate(0, 0);
return this;
};
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
// default text charset generation
var DEFAULT_CHARSET = new Charset(minitext());
var CHARSET = DEFAULT_CHARSET;
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
/** Set cursor position for the text.
* @param {number} i - cursor x position in character size (4 pixels)
* @param {number} j - cursor y position in character size (6 pixels)
*
* @returns {Texture} the texture itself
*/
Texture.prototype.locate = function (i, j) {
this._cursor.i = ~~i;
this._cursor.j = ~~j;
return this;
};
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
/** Print text. A position in pixel can be specified. If you do so, the text
* will be drawn at specified position plus camera offset. If not, the text is
* printed at current cursor position and wil wrap and make screen scroll down
* when cursor reach the texture bottom.
*
* @param (string) str - text to be printed
* @param (number) [x] - text x position in pixel
* @param (number) [y] - text y position in pixel
*
* @returns {Texture} the texture itself
*/
Texture.prototype.print = function (str, x, y) {
// string transformation
if (typeof str === 'object') {
try {
str = JSON.stringify(str);
} catch (error) {
str = '[Object]';
}
} else if (typeof str !== 'string') {
str = str.toString();
}
var color = this.palette[this._pen].string;
var charset = CHARSET.getColor(color);
// print at cooordinate
if (x !== undefined) {
x = ~~Math.round(x - this.camera.x);
y = ~~Math.round(y - this.camera.y);
var originX = x;
for (var i = 0; i < str.length; i++) {
var chr = str.charCodeAt(i);
if (chr === 10 || chr === 13) {
y += CHAR_HEIGHT;
x = originX;
continue;
}
chr -= 32;
if (chr < 0 || chr > 255) {
x += CHAR_WIDTH;
continue;
}
var sx = CHAR_WIDTH * (chr % CHAR_PER_LINE);
var sy = CHAR_HEIGHT * ~~(chr / CHAR_PER_LINE);
this.ctx.drawImage(
charset,
sx,
sy,
CHAR_WIDTH, CHAR_HEIGHT,
x, y,
CHAR_WIDTH, CHAR_HEIGHT
);
x += CHAR_WIDTH;
}
return this;
}
// print at cursor
var i = this._cursor.i;
var j = this._cursor.j;
for (var c = 0; c < str.length; c++) {
if (this.width - i * CHAR_WIDTH < CHAR_WIDTH) {
i = 0;
j += 1;
}
if (this.height - j * CHAR_HEIGHT < CHAR_HEIGHT) {
this.textScroll();
j -= 1;
}
var chr = str.charCodeAt(c);
if (chr === 10 || chr === 13) {
i = 0;
j += 1;
continue;
}
chr -= 32;
if (chr < 0 || chr > 255) {
i += 1;
continue;
}
var sx = CHAR_WIDTH * (chr % CHAR_PER_LINE);
var sy = CHAR_HEIGHT * ~~(chr / CHAR_PER_LINE);
this.ctx.drawImage(
charset,
sx,
sy,
CHAR_WIDTH, CHAR_HEIGHT,
i * CHAR_WIDTH,
j * CHAR_HEIGHT,
CHAR_WIDTH, CHAR_HEIGHT
);
i += 1;
}
this._cursor.i = i;
this._cursor.j = j;
return this;
};
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
/** Same as print and add a go to the next line.
* @param (string) str - text to be printed
*
* @returns {Texture} the texture itself
*/
Texture.prototype.println = function (str) {
this.print(str);
this.print('\n');
return this;
};
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
Texture.prototype.textScroll = function (n) {
if (n === undefined) n = 1;
this._cursor.j -= n;
n *= CHAR_HEIGHT;
this.ctx.drawImage(this.canvas, 0, -n);
this.ctx.fillRect(0, this.canvas.height - n, this.canvas.width, n);
return this;
};
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
var CHARSETS_MAP = new WeakMap();
Texture.prototype.setCharset = function (img) {
var i = this._cursor.i * CHAR_WIDTH;
var j = this._cursor.j * CHAR_HEIGHT;
if (!img) {
CHARSET = DEFAULT_CHARSET;
CHAR_WIDTH = 4;
CHAR_HEIGHT = 6;
} else {
CHAR_WIDTH = ~~(img.width / 16);
CHAR_HEIGHT = ~~(img.height / 6);
if (CHARSETS_MAP.has(img)) {
CHARSET = CHARSETS_MAP.get(img);
} else {
CHARSET = new Charset(img);
CHARSETS_MAP.set(img, CHARSET);
}
}
this._cursor.i = Math.ceil(i / CHAR_WIDTH);
this._cursor.j = Math.ceil(j / CHAR_HEIGHT);
};