• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
March 28, 2024, 10:55:00 am

News:

Don't be hasty to start your own mod; all our FFT modding projects are greatly understaffed! Find out how you can help in the Recruitment section or our Discord!


Game States

Started by lirmont, September 21, 2012, 04:06:36 pm

lirmont

September 21, 2012, 04:06:36 pm Last Edit: October 11, 2012, 07:37:40 pm by lirmont
With the addition of game states to Tethical's engine, this is a working example of what you can look forward to with state-oriented game design. The example is for a title screen.

In-Game


The amount of work you have to do:


If you noticed "Lunar Core.ogg" and want to hear what that sounds like (since it plays during the title screen), check this thread out: Lunar Core FF4.

Maybe a little later I will demonstrate starting with an intro video state.

Choto

!!!!

I'm so pumped about this project!

Actually looks really simple code-wise. I'm sure if you spend a small amount of time learning your way around it should be nice and simple.

lirmont

September 23, 2012, 11:48:51 pm #2 Last Edit: October 19, 2012, 06:12:02 am by lirmont
Alright, so here's a demonstration video of a working intro movie changing states into the title screen, which allows you to pick your next state (I choose "Exit" in the video): tethical-states-demo-xvid.avi (audio skipping comes from my non-optimum capturing settings).

And what the three files involved in this process look like:





Hopefully, you can see the process of how it gets from one thing to the next. The "effect" mentioned in the "backgroundEffect" data dictionary block refers to to the Panda3d functions discussed here: Lerp Intervals. The named arguments you can pass to them in python code are exactly the same as you would pass into the JSON state file (ex. duration = 0.5 in python becomes "duration": 0.5 in the JSON file).


--

Login State





Note that this is really just a form (like you might fill out on the internet). The fields you can specify in the fields list are any of the ones that feed into DirectFrame on this page: http://www.panda3d.org/reference/1.7.2/python/classgui.DirectGuiBase.DirectGuiWidget.php. And the dictionary entries can be "type", "internalName", or any of these: http://www.panda3d.org/manual/index.php/DirectGUI. The "type" entry is the class name. The "internalName" is how the "packetOrder" entry references fields. This is important because Panda3d relies on position to send things in datagrams (meaning you can name them whatever you want, just put them in the correct order for the message you intend the form to send). The "packetMessage" allows you to specify any of the shared messages between the client and server (ex. LOGIN_MESSAGE, GET_PARTIES, etc). And then finally the "moveToStateOnSuccess" is a conditional response to receiving a success message (ex. LOGIN_SUCCESS versus LOGIN_FAIL) which moves the state machine along.


--










Reading the server message back out. Message process is basically:

  • Client calls State, passing in the ability to send messages out.

  • State performs its operations, sending a message out through its link to the client's connection to the server.

  • Server sends a message back.

  • Client picks up the message, sending it to a specific state instance.

  • State handles message.



Client/Server Panda3d NetDatagrams will now only send/receive JSON objects (in the form of strings).


--

Lobby State






NOTE: This has not yet recreated what Kivutar had for the lobby, but it's getting there.

Of special note, you can provide text/data two different ways in a state description: explicitly (i.e. you write it and it never changes) or you can request a data set. Data sets come in two forms: local or remote. A local data set is a list of rows of data you've provided within the state description file; they'll never change. A remote data set call uses a server/client message to ask for data, allowing you to use real information at a state level (i.e. no programming required).

Now, referencing data in a data set can be done two ways: key-to-value or keys-to-formatted-value.

In the case of key-to-value requests, you reference which data set you want to use, providing only a data key after that. This will get parsed into the actual value on a row-by-row basis.

On the other hand, using the keys-to-formatted-value approach allows you to accomplish common programming tasks (like counting how many items you have in a list) that are better handled at the viewing level (rather than having the server send more and more data across different games that may not even use that data). In this approach, you reference the data set you want to use, and then you provide at least two things: a list of data keys and a formatting string. The formatting string puts the list of data you've asked for back together into one string, which is important because that's all that can be shown at a time. The formatting string's syntax is available here: Python Formatting Strings.

In the example state description file excerpt above, you may notice that there is also a mention of a "function". "len" stands for "length" and counts how many items are in a list. In the case of "players" and "formations", these give how many players the server has in that party and how many total formations are available respectively. No count of those two data structures is sent by the server. Instead, the state is requesting that the built-in function "len" be run on the data that was retrieved from the data set (i.e. the lists). This generates two numbers. Those two numbers are fed into the formatting string, and finally the display value is achieved.

Now, as a note about Python's scope, "len" is a function that exists in the Python module "__builtins__". The phrase "__builtins__" appears nowhere in the state's description file because the state assumes that what you mean if you don't provide a "module" key to provide a module context for your function request. If, on the other hand, you were to provide that, the value of  "module" may look like "games.lijj.states.mystate.SupportFunctions", in which case the state resolver will attempt to import the module "games.lijj.states.mystate.SupportFunctions" and find whatever function it is that you requested in that specific module. Since the state templates are powerful, you can accomplish radically different games using the same basic state templates.


--





The screenshot shows that the state template now accepts miscellaneous input requests which you can choose to show as buttons on-screen. All buttons in Tethical use the rollover and clicked sounds you specify in the game's configuration file. You specify which input signature you want to listen for in the state description (Menu for triangle/v, Accept for circle/b, Cancel for cross/space, Scroll for square/c, et al). Then, the button is fabricated with the selected theme's input-button image assets providing visual context for the states of the button. The text is provided for by a font you can change out; in the screenshots, it is a pixel-font (meant to look good, readable, and be small). The second screenshot shows the same thing but showing the button in a Playstation(R) controller's nomenclature.


--

Create Party State (aka "Map Chooser")





Images: Maximized Window (1920x1054)



So, there's more fun things to talk about. If you look at the state description file for this state, you should notice that it's saved as UTF-8. What does this mean? It means you can type whatever characters you want. Notepad++ doesn't use a font that has the characters I typed (lines 29 and 44), but you can see them in-game as the arrows. Those are the appropriate symbols for those characters, and you can type them directly into the description file. The only catch is you can't have the BOM at the beginning of the file; otherwise, the JSON object in the description file won't be able to be read.

Also, buttons can be anchored to edges now (a Panda3d feature), allowing them to scale properly as the window size changes. You can see this in the "Maximized Window" image.


--

Options State





No functionality yet, but it scrolls correctly.


--

Controller Buttons





Still can only set the keys in config files at the moment, though.