Game Builder

Game Builder

Ikke nok vurderinger
Talking with NPCs
Af Sandles
Do you want to talk with NPCs in your game? Follow the instructions in this guide!
   
Pris
Føj til foretrukne
Gjort til foretrukken
Fjern som foretrukken
In-action
This is an example of the dialog you can have with an NPC. In this example, I'm displaying the dialog after I collide with the NPC, but you can very easily set up another trigger.

The setup
To talk with any NPC, you'll need to hook up the dialog card to any event, in this example, we are listening for a message that is sent to the player after the NPC collides with the player. When the message is heard, the dialog will start. You do not have to follow this example, and instead can choose another way to initiate the dialog.

The code
Here is the code for the dialog panel.


export const PROPS = [
propEnum("TalkKey", "t", getKeyEnumValues(), {
label: "Key to talk?",
}),
propString("text1", "", {
label: "Dialog 1"
}),
propString("text2", "", {
label: "Dialog 2"
}),
propString("text3", "", {
label: "Dialog 3"
}),
propString("text4", "", {
label: "Dialog 4"
}),
propString("text5", "", {
label: "Dialog 5"
})
];

function getKeyEnumValues() {
const ret = [];
for (const keyName in KeyCode) {
ret.push({
value: KeyCode[keyName],
label: keyName
});
}
return ret;
}

function getMyKeyName() {
// Note: old versions of this card accepted TalkKey as string, which means
// it can be in uppercase, which is why we convert below:
return (props.TalkKey || "").toLowerCase();
}

const dialogMinX = 500;
const dialogMinY = 725;
const dialogXLen = 600;
const dialogYLen = 100;
const dialogColor = 0x353232;
const dialogOptions = {
opacity: 0.75
};

function buildTextData() {
var rawText = [];
if (props.text1.length > 0) {
rawText.push(props.text1);
}
if (props.text2.length > 0) {
rawText.push(props.text2);
}
if (props.text3.length > 0) {
rawText.push(props.text3);
}
if (props.text4.length > 0) {
rawText.push(props.text4);
}
if (props.text5.length > 0) {
rawText.push(props.text5);
}

card.textData = [];
var set = "";

for (var i = 0; i < rawText.length; i++) {
card.textData.push([]);
set = "";

for (var j = 0; j < rawText[i].length; j++) {

if (uiGetTextWidth(set + rawText[i][j]) >= dialogXLen) {
card.textData[i].push(set);
set = rawText[i][j];
} else {
set += rawText[i][j];

if (j + 1 === rawText[i].length) {
card.textData[i].push(set);
set = "";
}
}
}

if (set.length > 0) {
if (uiGetTextWidth(set + card.textData[i][card.textData[i].length - 1]) >= dialogXLen) {
card.textData[i].push(set);
} else {
card.textData[i][card.textData[i].length - 1] += set;
}
}
}

card.built = true;
}


function drawDialogBox() {
// 1600 x 900
uiRect(dialogMinX, dialogMinY, dialogXLen, dialogYLen, dialogColor, dialogOptions);
}

function drawText() {
var totalChars = Math.floor(card.tick / 5);
var waiterDots = Math.floor(card.waiterTick / 30);
var waiter = false;
if (totalChars >= card.textData[card.pageNum].join('').length) {
waiter = true;
}

var totalCharsFirstLineTemp = totalChars;
var indexStrHeight = 0;
var totalHeight = 0;
var heightMaxed = false;
var firstLine = 0;
var spaceBetweenLines = 20;

for (var i = 0; i < card.textData[card.pageNum].length; i++) {
if (totalCharsFirstLineTemp === 0) {
break;
}

indexStrHeight = 0;
if (indexStrHeight === 0) {
indexStrHeight = uiGetTextHeight(card.textData[card.pageNum][i]);
}

if ((totalHeight + (indexStrHeight)) <= dialogYLen) {
totalHeight += (indexStrHeight);
} else {
heightMaxed = true;
totalChars -= card.textData[card.pageNum][firstLine].length;
firstLine++;
}

if (totalCharsFirstLineTemp > card.textData[card.pageNum][i].length) {
totalCharsFirstLineTemp -= card.textData[card.pageNum][i].length;
} else {
break;
}
}

if (waiter) {
card.waiterTick++;

if (heightMaxed) {
totalChars -= card.textData[card.pageNum][firstLine].length;
firstLine++;
}

if (!card.endOfText) {
card.endOfText = true;
card.textData[card.pageNum].push("Continue");
}

var dots = "";
switch (waiterDots) {
case 1:
dots += ".";
break;
case 2:
dots += "..";
break;
case 3:
dots += "...";
break;
default:
break;
}
card.textData[card.pageNum][card.textData[card.pageNum].length - 1] = `Continue${dots}`;

if (waiterDots > 3) {
card.waiterTick = 1;
}
}

for (var i = firstLine; i < card.textData[card.pageNum].length; i++) {
if (card.textData[card.pageNum][i].length <= totalChars) {
uiText(dialogMinX, dialogMinY + ((i - firstLine) * spaceBetweenLines), card.textData[card.pageNum][i]);
} else {
uiText(dialogMinX, dialogMinY + ((i - firstLine) * spaceBetweenLines), card.textData[card.pageNum][i].substring(0, totalChars));
break;
}
totalChars -= card.textData[card.pageNum][i].length;
}
}

export function onKeyDown(msg) {
if (msg.keyName === getMyKeyName()) {
card.goFaster = true;
}
}

export function onKeyUp(msg) {
if (msg.keyName === getMyKeyName() && !card.endOfText){
card.goFaster = false;
}

if (msg.keyName === getMyKeyName() && card.endOfText) {
card.endOfText = false;

if (card.pageNum + 1 < card.textData.length) {
card.pageNum++;
card.tick = 0;
card.waiterTick = 0;
} else {
// end of conversation
card.pageNum = 0;
card.tick = 0;
card.waiterTick = 0;
card.goFaster = false;
card.active = false;
for (var i = 0; i < card.textData.length; i++) {
card.textData[i].pop();
}
}
}
}

export function onAction() {
card.active = true;
}

export function onTick() {
if (card.active && card.built) {
if (typeof card.tick === "undefined") {
card.tick = 1;
}
if (typeof card.waiterTick === "undefined") {
card.waiterTick = 1;
}

if (!card.goFaster){
card.tick++;
} else {
card.tick += 3;
}

drawDialogBox();
drawText();
} else if (!card.built) {
buildTextData();
}
}

export function onResetGame() {
card.active = false;
card.built = false;
card.endOfText = false;
card.goFaster = false;
card.pageNum = 0;
card.tick = 0;
card.waiterTick = 0;
card.textData = [];
}
Options
The dialog card has a few options available for you.

  • Key to talk - is the key to make the text appear faster on your screen (if this key is held down). This key is also the key to move from dialog 1 to dialog 2, and then to dialog 3, etc.
  • Dialog 1-5 - these are separate "chunks" of text you'd like the NPC to say.

Workshop link
Please go here if you'd like to look at the workshop link.

NEW - go here if you'd like to download the card.
2 kommentarer
Sandles  [ophavsmand] 22. sep. 2019 kl. 22:17 
I'm glad you like it evyn!
elkaylk 22. sep. 2019 kl. 21:08 
thx!