Cutey Zone
General Category => Cute Discussion => Topic started by: aimaina on August 26, 2018, 08:52:38 PM
-
im writing a damn npc text system again.... i wanna make it less bad than the cute witchy house one but i have run into a dilemma....
here is a sample script....
\if{level < 2}{
Welcome to the KittyPlains. Eat Star Flowers to Level Up and become stronger.
}{
\talk{2}
{You can now jump over the Blocks.}
{Good luck on your quest.}
}the effect of the "if" command should be pretty intuitive: \if{condition}{text1}{text_2} displays text1 if condition is true, and text2 if condition is false
the "talk" command works like this: \talk{2}{text1}{text2} displays text1 if it is the first time you have talked to the npc, displays text2 if it is the second time, and for further talks it cycles between them
the problem is that i dont actually want the talk command to behave that way. i want it to be aware of branches in the dialogue, and display the first text if it is your first time visiting the particular branch where the talk command appears, the second text the second time, etc. that is, i want it to work this way:
[talk to NPC]
Welcome to the KittyPlains. Eat Star Flowers to Level Up and become stronger.
[level up to level 2]
[talk to NPC]
You can now jump over the Blocks.
[talk to NPC]
Good luck on your quest.
currently what happens is this:
[talk to NPC, first time]
Welcome to the KittyPlains. Eat Star Flowers to Level Up and become stronger.
[level up to level 2]
[talk to NPC, second time, displays second text of the talk command]
Good luck on your quest.
[talk to NPC, third time, cycles back to first text]
You can now jump over the Blocks.
it seems like it will be very hacky and awkward to make the "number of times talked" variable aware of what dialogue branch you are on, and hacky and awkward is exactly what i want to avoid with this text system....
im wondering if a certain vgperson has dealt with this issue before and has a smart solution..... or if anyone else has ideas.....
-
ok i think i figured out a solution that isnt that bad..... i realized that each "talk" command can be uniquely identified by two things: the instance id of the calling npc, plus the position of the command in the npc text string (which i already need to store to process the command). so i use that data to build a map which stores the number of times each individual talk command has been activated, and i use that value instead of the generic "number of times talked" to determine which text to show, which i think gives the behaviour i want.....
-
Yeah, tracking variables that auto-pair with talk commands should work.
I would normally just manually manage a flag variable for this situation, because my system is mostly just a linear procession (with conditional branches) instead of having nested functions like that. This is how I would do it currently.
\if flag(Talked) == 0
message 1
\if flag(Talked) == 1
message 2
\if flag(Talked) == 2
message 3
\flag(Talked, +1) // + means increment from current
\if flag(Talked) > 2
\flag(Talked, 0) // set to 0
(Part of this working is a "starting value of 0" assumption like the one you can have in Game Maker; when a flag that didn't exist before is altered, it's treated as if it were originally 0. In fact, if a flag's value is 0, it's not even saved in the save file. This behavior is extremely useful for just adding flags as I need them.)
But if I were making a game that called for this a lot, I would add a switch statement to replace the ifs, and a function that encapsulates the end part:
\switch flag(Talked)
\case 0
message 1
\case 1
message 2
\case 2
message 3
\end
\flagLoop(Talked, 0, 2)
And if I were really bothered about it I could just make a special \switch that incorporates flagLoop and maybe even checks the cases to know what values to loop. But yeah, not really common enough to warrant it in my case.
-
make a whole custom pseudo-assembly instruction set with a bunch of custom codes for dialogue
-
:dancedog:
-
hmm i wonder how good an assembly style thing would be compared to what im doing..... it would be easier to parse probably so thats one advantage
-
i just realized my amazing text system does not easily support the concept of "multiple text boxes for one speak action" so maybe ill try the assembly thing
-
oh wait actually i think this is a deficiency of the npc object moreso than my parsing thingy
-
wow i switched to an assembly-esque system and its so much better and easier to manage..... i think its mostly because of the fact that its processed linearly like vg said her system does..... that seems like the way to go rather than whatever weird thing i was trying to do before
i think im learning that complex npc text is best treated as a "program" that starts executing when you talk to the npc, rather than just a block of data that you parse on each talk and feed to the npc object....
-
nice!!!
-
nice - i had that idea because i was thinking about making a speech system too, and i was trying to think of the best way to do like looping / branching dialogue. nice to hear that it sounds like it works.
-
here is an example of a npc interaction i just wrote..... this character normally says one of three lines when you talk to them, looping after the last line. but if you have examined a nearby locked door, they need to break out of that loop and unlock the door for you
top:
if {flag(kitty_town_door) == 1}
. It seems you want to go to Kitty Town, well you look trustworthy, go ahead.
set kitty_town_door 2
else
. Do not fall in the holes, if your JMP is not strong enough you will need to restart.
brk
jmc {flag(kitty_town_door) == 1} top
. Kitty Town is past the dangerous holes. I'm a Knight that protects the town.
brk
jmc {flag(kitty_town_door) == 1} top
. I'm thirsty, should of brought a Water.
fiheres what the code's do....
- top: or anything else ending in a colon is a label you can jump to
- if/else/fi works as you would expect
- the dot produces a textbox
- set lets you modify flags
- brk stops the current conversation, and resumes from the next line next time you talk to the npc. so for example if you do
. Text 1
. Text 2
you get a single conversation with two textboxes, whereas if you do
. Text 1
brk
. Text 2
you get one textbox per conversation
- jmc is a conditional jump, used here to break out of the normal text loop if the flag is set
- when you reach the end of the code, the conversation ends and the "program counter" is reset to 0, so it will start from the top next time you speak to the npc
-
So are you writing a parser and translating all this to native instructions? Seems like a lot of work over using your language's normal control structure for this.
Probably want to change "should of" to "should have".
-
The problem is that the normal control structures of game-oriented languages typically aren't inherently suited to "pause execution of this code here until the textbox is advanced, or until some other thing happens, or for a certain amount of time." So you just gotta make your own processing that is.
Also, didn't know you were the person leaving typo reports on raocow's JIGGLY ZONE LP. The Mystery is Solve'd
-
Hrmm, okay that makes sense. And while you might be able to offload that to another thread and still run rendering/networking/whatever in the background, I don't think Gamemaker lets you do that sort of thing yet.
I didn't see the raocow thing but I am always happy to lend grammatical assistance.
-
i think early versions of joogle had separate objects for every npc, which lets you use gml to describe the structure of conversations, but thats really unpleasant compared to a single configurable object
-
I thought that wasn't true, but it turns out you're right. (And those objects are still sitting in the final version for some reason?) That was Mitch's approach before I made it into the latter, which means they were also using show_message, which did... technically accomplish the "pausing until advancement" functionality.
My approach was also very messy. It had a "text" array containing the textbox messages, as well as an "act" array (except for some reason this one isn't an actual array: execute_string is used to find a variable named actX, where X is the line number??? Literally why could that not have been an array) which is executed by execute_string when each message box is shown. The latter could make branches happen by literally setting the "text" array to different messages. Libretta had a vaguely similar approach to branches, but like... a lot better than that.
Oh yeah, and Nakko-Bazookie did cutscenes in their own objects with an incrementing "stage" variable to accomplish actions between sets of messages (i.e. create text object with series of messages and set stage = 1; if object no longer exists && stage == 1, perform an action and set stage to 2...), but there were few enough that it wasn't so bad.
There were also Dabomstew's Pokemon fangame(s), which drew messages to the screen outside of the Draw function (which normally means it disappears in a frame or something)... then immediately "froze" the screen with a keyboard_wait loop before it would update again. Which is the true galaxy brain solution.
-
Also, didn't know you were the person leaving typo reports on raocow's JIGGLY ZONE LP. The Mystery is Solve'd
i really appreciated that person's efforts--still working on the patch
-
I thought that wasn't true, but it turns out you're right. (And those objects are still sitting in the final version for some reason?) That was Mitch's approach before I made it into the latter, which means they were also using show_message, which did... technically accomplish the "pausing until advancement" functionality.
My approach was also very messy. It had a "text" array containing the textbox messages, as well as an "act" array (except for some reason this one isn't an actual array: execute_string is used to find a variable named actX, where X is the line number??? Literally why could that not have been an array) which is executed by execute_string when each message box is shown. The latter could make branches happen by literally setting the "text" array to different messages. Libretta had a vaguely similar approach to branches, but like... a lot better than that.
Oh yeah, and Nakko-Bazookie did cutscenes in their own objects with an incrementing "stage" variable to accomplish actions between sets of messages (i.e. create text object with series of messages and set stage = 1; if object no longer exists && stage == 1, perform an action and set stage to 2...), but there were few enough that it wasn't so bad.
There were also Dabomstew's Pokemon fangame(s), which drew messages to the screen outside of the Draw function (which normally means it disappears in a frame or something)... then immediately "froze" the screen with a keyboard_wait loop before it would update again. Which is the true galaxy brain solution.
warning: show_message crashes the game on some computers if you're in fullscreen mode. thanks game maker.
-
like, in studio or the older versions? i think they say not to use show_message in studio except for debugging purposes or something but i didnt know it was that bad
-
yeah, studio.
-
Are you sure that is how it is? I am not seeing that. And Searching the text I dont see it either. I just downloaded it from the patcher again and dont see it in that version either.
Ive attached the version from the patcher.
Silat
-
I'm pretty sure this is a spambot but I don't understand why it is. Think I'll leave it.
-
hey Maxwelltew did you hear about my new game dance of the flower princess? love-game.net/flowerprincess (http://love-game.net/flowerprincess) (windows version at love-game.net/flowerprincess.zip (http://love-game.net/flowerprincess.zip))
-
(https://i.imgur.com/vb2Nsfi.png)
Hey I Love Touhou
I could definitely get a perfect score eventually, but I'm a busy hime, so I'll stop there for now... maybe.
-
a good game with good patterns and good tunes!
i managed to get a perfect on each individual phase except for lava. found with flowers that sitting on the very bottom of the level and just watching out for diagonal petals worked p wel
-
thank's for playing everone..... :honeydew:
i have an unrelated question for vg..... how do you make pixel art not look bad in unity? like no compression or filtering + no weird artifacts like a line appearing on the side of the sprite sometimes + everything scaled by integers..... i think i know some of the steps but not all of them. in particular its a complete mystery to me how you set up the camera
-
1. Set the orthographic size of your main camera based on the base screen height. I don't remember exactly what this code is supposed to signify... but it works!
camera.orthographicSize = SCREENHEIGHT / 2.0f;
Setting resolution with Screen.SetResolution should just scale up properly. You may also have to ensure the Z position of your camera object is right, considering that my camera code sets the position as "(x, y, -10)" while everything else is at Z = 0.
2. Have all textures use Point filter mode, and maybe some other things. You can add an class that inherits AssetPostprocessor to your project to automatically override texture settings on import.
public class TexturePostProcessor : AssetPostprocessor
{
void OnPreprocessTexture()
{
TextureImporterSettings settings = new TextureImporterSettings();
TextureImporter importer = assetImporter as TextureImporter;
importer.ReadTextureSettings(settings);
settings.spriteAlignment = (int)SpriteAlignment.TopLeft;
importer.SetTextureSettings(settings);
importer.textureType = TextureImporterType.Advanced;
importer.isReadable = true;
importer.spritePixelsPerUnit = 1;
importer.spritePivot = new Vector2(0, 1);
importer.mipmapEnabled = false;
importer.filterMode = FilterMode.Point;
importer.maxTextureSize = 4096;
importer.textureFormat = TextureImporterFormat.RGBA32;
}
}
Some of the other things may or may not be essential. The pivot is set to the top-left by spritePivot and spriteAlignment. "World units" are equated to "pixels" by way of spritePixelsPerUnit = 1. I think isReadable allows it to be "referenced" by functions like GetPixels, which I use to generate frames from strips. I believe maxTextureSize is there because if a texture exceeds the max in one dimension (which happens for me with large horizontal font strips), it'll get compressed or something else that messes it up.
I also had "importer.wrapMode = TextureWrapMode.Clamp;" in this, but commented it out?? I want to say that was another element to fixing things like weird artifacts, but I guess it must not be essential. I'm pretty sure it has to do with what happens when you draw a texture at anything other than its actual size.
3. Never let anything have a fractional coordinate. If something does, I think it'll have proper pixel size, but be misaligned? I do all my movement through functions that only move in integers, so yeah. You could also have it snap position to integers every frame, but that could get pretty bad for performance.
-
thanx very much this will be very useful to me if i am ever forced to use unitey again.....
i notice your code doesnt seem to change the "compression" setting for textures even though the default is "normal quality" compression for me.... maybe the compression is lossless for small enough textures or something?
-
I don't see any compression option on textures, but I'm on an older version of Unity. If there is a compression setting in newer versions, you might want to set that appropriately as well.
EDIT: Yeah, I guess there is, and you probably want High Quality or None. Also, it looks like there might be a built-in way of changing default import settings now too...?