昨天,我們介紹了 Graphics
類別,學會了如何用程式碼畫出各種形狀,甚至還挑戰了一個會動的紅綠燈。今天,我們將介紹另一個遊戲中不可或缺的元素:文字。
Text 是 PixiJS 中最基礎的文字顯示物件,它讓我們可以輕鬆地在畫面上顯示訊息、分數或任何需要用文字表達的內容。
首先,將你的 app.ts
程式碼清空,並貼上以下程式碼:
import pixi = CG.Pixi.pixi;
export async function start() {
// 初始化 Pixi
await pixi.initialize({ stageWidth: 960, stageHeight: 540 });
// 創建一個 Text 物件
const text = new PIXI.Text({
text: 'Hello CG!\nHello PixiJS!\nHello iThome!',
style: {
fill: 0xFFFFFF,
fontSize: 100
},
anchor: 0.5,
position: { x: pixi.stageWidth * 0.5, y: pixi.stageHeight * 0.5 }
} as PIXI.TextOptions);
// 將 Text 物件加入舞台
pixi.root.addChild(text);
}
start();
貼上程式碼後,點擊「試玩遊戲」,你應該會看到畫面上出現三行大大的文字:
Text
物件創建 Text
物件的方法非常簡單,只需要傳入一個帶有 text
屬性的物件,就可以創建一個最基本的文字物件。
const text = new PIXI.Text({
text: 'Hello CG!\nHello PixiJS!\nHello iThome!',
style: {
fill: 0xFFFFFF,
fontSize: 100
},
anchor: 0.5,
position: { x: pixi.stageWidth * 0.5, y: pixi.stageHeight * 0.5 }
} as PIXI.TextOptions);
除了 text
屬性用來設定文字內容外,這裡我們還看到了其他屬性,像是 style
、anchor
和 position
。這些都是 PixiJS v8 新增的特性,允許我們在創建物件時就直接設定它的樣式、錨點和位置,讓程式碼更簡潔。
如果你想要在之後更新文字物件內顯示的文字內容,可以這麼做:
text.text = "更新後的文字";
直接設定文字物件的text
屬性即可更新顯示的文字。
這一步驟和我們前面介紹的 Sprite
、Container
和 Graphics
完全一樣。我們可以使用 addChild()
將文字物件加入到舞台或容器中。
// 將 Text 物件加入舞台
pixi.root.addChild(text);
PIXI.TextStyle
如果覺得預設的文字太單調,Text
物件還提供了許多屬性讓我們自訂樣式,例如字型、大小、顏色、對齊方式等等。
讓我們將 start()
函數內的程式碼,改成以下這樣:
// 初始化 Pixi,設定背景顏色為 0x2BC5F9(淺藍色)
await pixi.initialize({ stageWidth: 960, stageHeight: 540, backgroundColor: 0x2BC5F9 });
// 創建文字樣式物件
const style = new PIXI.TextStyle({
fontFamily: 'Arial', // 字體字型
fontSize: 90, // 字體大小
fontWeight: "bold", // 字體寬度(粗體字)
fontStyle: "italic", // 字體風格(斜體字)
fill: 0xFFFFFF, // 字體顏色
stroke: { // 描邊設定
color: 0x0E50E2, // 描邊顏色
width: 7 // 描邊寬度
} as PIXI.StrokeStyle,
dropShadow: { // 陰影設定
color: 0x000000, // 顏色
angle: Math.PI / 6, // 角度(單位弧度)
distance: 6, // 距離
alpha: 0.5, // 不透明度
blur: 4 // 模糊度
}
});
// 創建文字物件
const text = new PIXI.Text({
text: '2025 iThome 鐵人賽',
style: style, // 使用上方的字體樣式
anchor: 0.5,
position: { x: pixi.stageWidth * 0.5, y: pixi.stageHeight * 0.5 }
} as PIXI.TextOptions);
pixi.root.addChild(text);
貼上程式碼後,你應該會看到畫面中央出現令人熟悉的文字。
fontFamily
:字體字型,可以是字串或陣列(多個字體)。fontSize
:字體大小。fontWeight
:文字粗細,如 "bold"
、"lighter"
等。fontStyle
:文字風格,如 "italic"
、"oblique"
等。fill
:填充顏色,可以接受十六進制顏色碼或 CSS 顏色字串。stroke
:邊框樣式。dropShadow
:陰影樣式。align
:對齊方式,例如 "left"
、"center"
、"right"
。更多樣式設定,推薦可以去 PIXI.TextStyle Editor 玩玩看,有介面可以直接改變、預覽字體樣式,雖然目前該工具僅支援 PixiJS v7 版本,但大體上差不多。或是直接查看官方 API。
除了使用系統內建字體,PixiJS 也支援載入自訂字體。這對於遊戲的美術風格來說非常重要,因為很多遊戲會使用獨特的像素字體或藝術字體。
這裡會用到 Day 03 介紹過的資源載入方式,來將字體資源載入到專案中,你可以自行上傳,也可以使用其他人上傳的字體。
這次我同樣使用其他人上傳的字型資源,於搜尋關鍵字內輸入 Cubic11,應該會找到一個由 Nyuightq 上傳的 Cubic11.ttf
,點擊「加載資源」將該字型載入至專案中即可。
俐方體11號/Cubic 11:https://github.com/ACh-K/Cubic-11
CG 並不會審核創作者們自行上傳的資源,上傳前應確保資源的版權問題,若非無版權、開源,或是自行生產的資源,應在上傳時將「公開資源」的選項取消選取,以保護自身以及資源作者的權益。
有了字型資源之後,我們同樣要使用 pixi.assets
,在程式執行的一開始將該資源加載至遊戲中,才可以在後續使用。
同樣修改 start()
函數內的程式碼:
// 從專案載入字體(記得將資源別名修改成你自己專案的資源別名喔!)
await pixi.assets.add("ironman2025_cook.字型.Cubic11").load();
await pixi.initialize({ stageWidth: 960, stageHeight: 540 });
// 創建文字物件
const text1 = new PIXI.Text({
text: "這是...像素字體!!",
style: {
fontFamily: "Cubic 11", // 字體字型(填寫字體名稱,而非資源別名)
fontSize: 60,
fill: 0xffffff,
},
anchor: 0.5,
position: { x: pixi.stageWidth * 0.5, y: pixi.stageHeight * 0.5 }
} as PIXI.TextOptions);
pixi.root.addChild(text1);
這裡要注意的是,fontFamily
的值要輸入的是字體檔案內的字體名稱,而不是字型資源的別名,字體名稱可以在字型資源的詳細資料內找到,屬性為 fontName,如下圖。
resolution
Text
物件的 resolution
屬性是一個非常實用的優化工具,它影響著文字的清晰度和效能。
簡單來說,resolution
決定了 PixiJS 內部用多大的紋理(Texture)來渲染我們的文字。
resolution: 1
(預設):每個像素都對應一個螢幕像素,渲染速度最快,但如果放大會變模糊。resolution > 1
(例如 2
或 4
):使用更高解析度的紋理來渲染,讓文字更清晰,但會佔用更多記憶體。resolution < 1
(例如 0.5
):使用較低解析度的紋理,犧牲清晰度來換取效能。讓我們看一個例子,感受一下不同 resolution
帶來的差異:
await pixi.initialize({ stageWidth: 960, stageHeight: 540 });
// 創建文字樣式物件
const style = new PIXI.TextStyle({
fontSize: 60, // 文字大小
fill: 0xffffff, // 文字顏色
});
// 創建文字物件
const text1 = new PIXI.Text({
text: "人在江糊,身不由己",
style: style,
anchor: 0.5,
position: { x: pixi.stageWidth * 0.5, y: pixi.stageHeight * 0.25 },
resolution: 0.5 // 設定解析度為 0.5
} as PIXI.TextOptions);
const text2 = new PIXI.Text({
text: "江湖就是這樣,既不糊也不清",
style: style,
anchor: 0.5,
position: { x: pixi.stageWidth * 0.5, y: pixi.stageHeight * 0.5 },
// 若沒設定,解析度預設為 1
} as PIXI.TextOptions);
const text3 = new PIXI.Text({
text: "高清無碼,限時解鎖",
style: style,
anchor: 0.5,
position: { x: pixi.stageWidth * 0.5, y: pixi.stageHeight * 0.75 },
resolution: 2 // 設定解析度為 2
} as PIXI.TextOptions);
pixi.root.addChild(text1);
pixi.root.addChild(text2);
pixi.root.addChild(text3);
了解了 Text
基本的運作原理後,為了延續昨天的傳統,今天也有 Bonus 關卡!我們來做一個讓文字逐個顯示的動畫效果。
在偷看答案之前,各位可以先想想看如果是自己的話,會怎麼實現這個效果呢?
小提示:在 CG 的
async
函數中,你可以這樣來等待指定時間await CG.Base2.wait(50); // 等待 50 毫秒
// 從專案載入字體(記得將資源別名修改成你自己專案的資源別名喔!)
await pixi.assets.add("ironman2025_cook.字型.Cubic11").load();
// 初始化 Pixi
await pixi.initialize({ stageWidth: 960, stageHeight: 540 });
// 創建一個文字物件
const text = new PIXI.Text({
text: "Text",
style: {
fontFamily: "Cubic 11",
fill: 0xFFFFFF,
fontSize: 50,
align: "center" // 置中對齊
},
anchor: 0.5,
position: { x: pixi.stageWidth * 0.5, y: pixi.stageHeight * 0.5 }
} as PIXI.TextOptions);
pixi.root.addChild(text);
// 定義要顯示的文字字串陣列
const messages = [
"很久很久以前......",
"一名旅者來到了深山深處",
"他遇到了一位老頭",
"老頭意味深長的看著他",
"隨即開口說道..."
];
// 執行下方的函數播放動畫
playAnimation();
// 定義一個播放動畫的函數
async function playAnimation() {
for (const msg of messages) { // 將文字一個個從 messages 裡面拿出來
text.text = ""; // 清除目前顯示的文字
for (let i = 0; i < msg.length; ++i) {
text.text += msg[i]; // 將一個字元加入正在顯示的文字物件內
await CG.Base2.wait(50); // 等待 50 毫秒
}
await CG.Base2.wait(1500); // 等待 1500 毫秒
}
playAnimation(); // 再執行一次播放動畫的函數,直到天花地老...
}
將上方的程式碼放進 start()
內即可,你就可以看到如下方 GIF 顯示的動畫效果。怎麼樣?是不是很像一般像素遊戲中間的過場動畫阿!
詳細的運作原理,同樣就交給各位自行去鑽研啦~
今天我們介紹了 Text,它是 PixiJS 中用來顯示文字的基礎類別。
new PIXI.Text()
來創建文字物件。text
屬性用來設定文字內容,支援換行符號 \n
。style
屬性可以傳入一個 PIXI.TextStyle
物件來客製化文字樣式。Text
也具備 position
、anchor
、alpha
等所有顯示物件的通用屬性。assets
載入自訂字體,讓你的遊戲更有個性。resolution
屬性來控制文字的清晰度與效能。明天,我們將會介紹如何監聽使用者的滑鼠點擊或觸控事件,讓你的遊戲能夠與玩家進行互動,敬請期待!