From 16daf7332a869d4d2aea930c065f942f63a34e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Fri, 16 Apr 2021 21:29:05 +0200 Subject: [PATCH] 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. --- front/src/Phaser/Components/TextUtils.ts | 45 ++++++ front/src/Phaser/Game/GameScene.ts | 17 ++- front/src/Phaser/Map/ITiledMap.ts | 14 ++ maps/tests/text_object.json | 179 +++++++++++++++++++++++ 4 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 front/src/Phaser/Components/TextUtils.ts create mode 100644 maps/tests/text_object.json diff --git a/front/src/Phaser/Components/TextUtils.ts b/front/src/Phaser/Components/TextUtils.ts new file mode 100644 index 00000000..0161f52d --- /dev/null +++ b/front/src/Phaser/Components/TextUtils.ts @@ -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); + } + } +} diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 08afca58..d97c6dbc 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -18,7 +18,14 @@ import { RESOLUTION, ZOOM_LEVEL } 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 {PlayerAnimationDirections} from "../Player/Animation"; import {PlayerMovement} from "./PlayerMovement"; @@ -81,6 +88,7 @@ import DOMElement = Phaser.GameObjects.DOMElement; import {Subscription} from "rxjs"; import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream"; import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager"; +import {TextUtils} from "../Components/TextUtils"; export interface GameSceneInitInterface { initPosition: PointInterface|null, @@ -398,6 +406,13 @@ export class GameScene extends ResizableScene implements CenterListener { if (layer.type === 'objectgroup' && layer.name === 'floorLayer') { depth = 10000; } + if (layer.type === 'objectgroup') { + for (const object of layer.objects) { + if (object.text) { + TextUtils.createTextFromITiledMapObject(this, object); + } + } + } } 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.'); diff --git a/front/src/Phaser/Map/ITiledMap.ts b/front/src/Phaser/Map/ITiledMap.ts index 39e0a1f5..c3f9d10b 100644 --- a/front/src/Phaser/Map/ITiledMap.ts +++ b/front/src/Phaser/Map/ITiledMap.ts @@ -94,6 +94,20 @@ export interface ITiledMapObject { * Polyline points */ 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 { diff --git a/maps/tests/text_object.json b/maps/tests/text_object.json new file mode 100644 index 00000000..2c3612f0 --- /dev/null +++ b/maps/tests/text_object.json @@ -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 +} \ No newline at end of file