Adding the ability to display "Text" objects from Tiled

I honestly don't believe text objects look good on map, and in real maps, I think text should be written on tiles.

However, for a variety of use cases (like in test maps in the /maps/test directory, it can be useful to be
able to display some text easily on a map.

This PR adds the ability to display this text.

Note: the "font" support cannot work correctly, as Tiled is listing fonts from the local
system, and those fonts are not available in a browser.
This commit is contained in:
David Négrier 2021-04-16 21:29:05 +02:00
parent afd2ea2d03
commit 16daf7332a
4 changed files with 254 additions and 1 deletions

View File

@ -0,0 +1,45 @@
import {ITiledMapObject} from "../Map/ITiledMap";
import Text = Phaser.GameObjects.Text;
import {GameScene} from "../Game/GameScene";
import TextStyle = Phaser.GameObjects.TextStyle;
export class TextUtils {
public static createTextFromITiledMapObject(scene: GameScene, object: ITiledMapObject): void {
if (object.text === undefined) {
throw new Error('This object has not textual representation.');
}
const options: {font?: string} = {};
let font = '';
if (object.text.italic) {
font += 'italic ';
}
// Note: there is no support for "strikeout" and "underline"
let fontSize: number = 16;
if (object.text.pixelsize) {
font += object.text.pixelsize+'px ';
fontSize = object.text.pixelsize;
} else {
font += '16px ';
}
if (object.text.fontfamily) {
font += '"'+object.text.fontfamily+'"';
}
if (font !== '') {
options.font = font;
}
const textElem = scene.add.text(object.x, object.y, object.text.text, options);
textElem.setFontSize(fontSize);
let color = '#000000';
if (object.text.color !== undefined) {
color = object.text.color;
}
textElem.setColor(color);
if (object.text.wrap) {
textElem.setWordWrapWidth(textElem.width);
}
textElem.setAngle(object.rotation);
if (object.text.halign !== undefined) {
textElem.setAlign(object.text.halign);
}
}
}

View File

@ -18,7 +18,14 @@ import {
RESOLUTION, RESOLUTION,
ZOOM_LEVEL ZOOM_LEVEL
} from "../../Enum/EnvironmentVariable"; } from "../../Enum/EnvironmentVariable";
import {ITiledMap, ITiledMapLayer, ITiledMapLayerProperty, ITiledMapObject, ITiledTileSet} from "../Map/ITiledMap"; import {
ITiledMap,
ITiledMapLayer,
ITiledMapLayerProperty,
ITiledMapObject,
ITiledText,
ITiledTileSet
} from "../Map/ITiledMap";
import {AddPlayerInterface} from "./AddPlayerInterface"; import {AddPlayerInterface} from "./AddPlayerInterface";
import {PlayerAnimationDirections} from "../Player/Animation"; import {PlayerAnimationDirections} from "../Player/Animation";
import {PlayerMovement} from "./PlayerMovement"; import {PlayerMovement} from "./PlayerMovement";
@ -81,6 +88,7 @@ import DOMElement = Phaser.GameObjects.DOMElement;
import {Subscription} from "rxjs"; import {Subscription} from "rxjs";
import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream"; import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream";
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager"; import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
import {TextUtils} from "../Components/TextUtils";
export interface GameSceneInitInterface { export interface GameSceneInitInterface {
initPosition: PointInterface|null, initPosition: PointInterface|null,
@ -398,6 +406,13 @@ export class GameScene extends ResizableScene implements CenterListener {
if (layer.type === 'objectgroup' && layer.name === 'floorLayer') { if (layer.type === 'objectgroup' && layer.name === 'floorLayer') {
depth = 10000; depth = 10000;
} }
if (layer.type === 'objectgroup') {
for (const object of layer.objects) {
if (object.text) {
TextUtils.createTextFromITiledMapObject(this, object);
}
}
}
} }
if (depth === -2) { if (depth === -2) {
throw new Error('Your map MUST contain a layer of type "objectgroup" whose name is "floorLayer" that represents the layer characters are drawn at.'); throw new Error('Your map MUST contain a layer of type "objectgroup" whose name is "floorLayer" that represents the layer characters are drawn at.');

View File

@ -94,6 +94,20 @@ export interface ITiledMapObject {
* Polyline points * Polyline points
*/ */
polyline: {x: number, y: number}[]; polyline: {x: number, y: number}[];
text?: ITiledText
}
export interface ITiledText {
text: string,
wrap?: boolean,
fontfamily?: string,
pixelsize?: number,
color?: string,
underline?: boolean,
italic?: boolean,
strikeout?: boolean,
halign?: "center"|"right"|"justify"|"left"
} }
export interface ITiledTileSet { export interface ITiledTileSet {

179
maps/tests/text_object.json Normal file
View File

@ -0,0 +1,179 @@
{ "compressionlevel":-1,
"height":10,
"infinite":false,
"layers":[
{
"data":[1, 1, 1, 1, 1, 1, 23, 23, 23, 23, 1, 1, 1, 1, 1, 1, 23, 23, 23, 23, 1, 1, 1, 1, 1, 1, 23, 23, 23, 23, 1, 1, 1, 1, 1, 1, 23, 23, 23, 23, 1, 1, 1, 1, 1, 1, 23, 23, 23, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
"height":10,
"id":1,
"name":"floor",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":10,
"x":0,
"y":0
},
{
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"height":10,
"id":2,
"name":"start",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":10,
"x":0,
"y":0
},
{
"draworder":"topdown",
"id":3,
"name":"floorLayer",
"objects":[
{
"height":154.708861498919,
"id":1,
"name":"",
"rotation":0,
"text":
{
"color":"#ffff00",
"fontfamily":"Sans Serif",
"text":"A yellow text that wraps automatically.\n\nIt is 16px high.",
"wrap":true
},
"type":"",
"visible":true,
"width":127.701300455634,
"x":192.052147832817,
"y":5.45414451778726
},
{
"height":19,
"id":3,
"name":"",
"rotation":0,
"text":
{
"text":"Default text",
"wrap":true
},
"type":"",
"visible":true,
"width":113.494863163736,
"x":1.76065884397454,
"y":8.44497342134471
},
{
"height":19,
"id":5,
"name":"",
"rotation":0,
"text":
{
"text":"A very long text with no world wrap so it keeps going"
},
"type":"",
"visible":true,
"width":349.4375,
"x":1.01295161808517,
"y":168.828173374613
},
{
"height":19,
"id":6,
"name":"",
"rotation":45,
"text":
{
"text":"A rotated text"
},
"type":"",
"visible":true,
"width":117.607252906128,
"x":62.3249441410129,
"y":41.3440913604766
},
{
"height":48.1605818096851,
"id":7,
"name":"",
"rotation":0,
"text":
{
"fontfamily":"Sans Serif",
"italic":true,
"pixelsize":27,
"strikeout":true,
"text":"Italic 27px",
"underline":true
},
"type":"",
"visible":true,
"width":337.807030930545,
"x":6.6207558122554,
"y":209.952070798528
},
{
"height":40,
"id":9,
"name":"",
"rotation":0,
"text":
{
"fontfamily":"Sans Serif",
"halign":"center",
"pixelsize":15,
"text":"This text should appear below the plant and be centered",
"wrap":true
},
"type":"",
"visible":true,
"width":317.4375,
"x":0.78125,
"y":269.5
}],
"opacity":1,
"type":"objectgroup",
"visible":true,
"x":0,
"y":0
},
{
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 79, 80, 0, 0, 0, 0, 0, 0, 0, 89, 90, 91, 0, 0, 0, 0, 0, 0, 0, 100, 101, 102, 0, 0, 0, 0],
"height":10,
"id":8,
"name":"over",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":10,
"x":0,
"y":0
}],
"nextlayerid":9,
"nextobjectid":10,
"orientation":"orthogonal",
"renderorder":"right-down",
"tiledversion":"2021.03.23",
"tileheight":32,
"tilesets":[
{
"columns":11,
"firstgid":1,
"image":"tileset1.png",
"imageheight":352,
"imagewidth":352,
"margin":0,
"name":"tileset1",
"spacing":0,
"tilecount":121,
"tileheight":32,
"tilewidth":32
}],
"tilewidth":32,
"type":"map",
"version":1.5,
"width":10
}