ResidualVM: Week 11

Well, probably the shortest blog ever this time…
Long story short, I haven’t figure out how the original game computes the shadows. There can be at most ten lights in a scene but there is only one shadow, and the way that shadow reacts with lights in the game is just, so strange…
Take this scene as an example. The green circle is the range denoted by the field maxShadowLength. It’s too large, way larger than the true shadow length in the original game. There is only one light entry here, the lamp. You may imagine what will happen if you hold a lamp so close like this. The shadow should be extremely long and cast on the wall, right? That’s not what happens in the original game. In fact, the lamp just moves the shadow a tiny bit against its direction.
So I can only draw the conclusion that the original game does not compute the shadow as the reality. I have tried many possible and “reasonable” implementations that came into my mind but none of them seemed to be fit. (Yeah based on the above description you may be thinking about biasing the length or something like that but believe me, I have tried, really.)
Have to say that this is really frustrating. Anyway, I’ll keep on digging next week.

ResidualVM: Week 10

And I said: “Let there be shadows!” And there are shadows. Just, not good enough…
So, from this week till the end of GSoC I guess I’ll be dealing with OpenGL. As a newbie to computer graphics, I would be lying if I say that I am not worried at all. I once believed that OpenGL hated me, it hated me so much that it didn’t even want me to render a tessellated triangle on the screen. But that hard time is passed now and I am happy that I start to get along well with OpenGL, and it is kind enough to let me produce something physical this week.
Ah, the shadow.
Okay, shadows. Actually what I have done so far is based on my previous wrong assumption about shadows in The Longest Journey. In most of the scenes I have played, which is not many actually, characters have shadows that look like they are cast from above. The Longest Journey is a 2.5D game with 3D characters and 2D backgrounds, so, in my personal perspective as a CG newbie, it won’t be that intuitive to perform a full shadow casting technique like the Shadow Mapping here. But if shadows are just cast from above, then things are a lot simpler.
So, with this “wrong” assumption, and the fact that the original game doesn’t seem to have complex and realistic shadows, I decided to use the simplest shadow casting technique: Planar Shadow. Basically, it just squishes the modal onto a surface and paints it grey. Since I just want to cast the shadow from above, the squishing is even easier. Below is a screenshot when I was testing how I could squish the model.
April: I don’t feel so good…
That’s not the whole story. A good shadow should be semi-transparent. But simply enable blending is not enough since transparent faces will cover on each other, and there will be the Z-fighting problem. The solution is intuitive though: stencil test. With the enabling of the stencil test and proper manipulation on the stencil buffer (no two shadow fragments can be drawn on the same location), a nice semi-transparent shadow is produced.
Blending and Stencil Tet
Well, like I said before, this is a wrong assumption. The Longest Journey does compute shadows from existing lights. And there are three types of light in the game: point light, directional light and spotlight. Luckily lights only contribute to the length of the shadow, so right now I think the Planar Shadow technique can still be used.
From the look of it right now, I guess it is time for some linear algebra. More updates will come next week.

All code snippets are generated through Carbon

ResidualVM: Week 9

So apparently this week is still about the keyboard bindings, mostly on the two things: the display of exit locations, and further improvement on the dialog panel.

In the original game, when the player presses the key X, all the exit locations of the current location will be pointed out with a symbol on it. To achieve this, I need to find which PATTable (the object that contains info of a clicking area) has the exit action, get its location, and render a symbol on it. It sounds easy, but the OO structure of the game engine warps it in a pretty complex way and I have to open interfaces in many classes. After doing so, I started to understand that why people are being more critical to OO design and FP is getting more popular. You really need to know how to balance things. Also, it took me some time to verify the exact location of the symbol to be drawn.

See the exit symbol on the door?

As for the dialog panel, I made a wrong assumption in my previous implementation: assuming that all dialog options will be only one line. Yet taking the fact that an option may wrap up multiple lines into consideration, many corner cases need to be reconsidered. So basically, I have to rewrite the codes in the dialog panel, again, to accommodate this change.

The final approach I came up with is actually not that complicated: instead of just recording the first visible option in the current scrolling, the last visible option is also recorded. When the dialog panel scrolls, one of them can be determined easily and used to find the other one. During the finding, the total height of the currently selected options is recorded to see whether they fit into the panel’s space. Of course, there are some corner cases need to be paid attention to, but the overall logic is intuitive.
Find the last visible option with the first visible option pre-determined
The keyboard bindings task is taking way to much time to tackle with, but I believe it is very close to being merged. I have already been looking at the next important task: implementing the characters’ shadows, and I can’t wait to have some “experience” with OpenGL. Sorry for such a short blog this week, just not much to say. I promise there will be more updates next week.
All code snippets are generated through Carbon

ResidualVM: Week 8

So, this week’s focus is on the keyboard binding in The Longest Journey. In the original game, although you can freely use only the mouse to play through the game, you can still use the keyboard to do numerous things, such as opening menus, pausing the game and selecting options and items. It is like a combination and cooperation of things I have worked on previously.
Most of the bindings, like opening menus, is pretty easy, but some needs extra working and twisting, like directly choosing inventory items through pressing A and S. Up to now, I would say that the most complex keyboard binding I’ve implemented is the binding for dialog options.
A typical conversation scene in the game
The Longest Journey has very heave dialogs, each of them with many many options, all fully voiced. It would indeed be very convenient for players if they can use keyboards to go through and select options in the game. However, the previous implementation of this part is fully based on mouse movements, with a structure that is not suitable to cooperate with keyboards. Therefore, I have to rewrite many of the dialog option selection codes and open new interfaces for the keyboard to interact with. It’s not that easy, but I felt great after successfully doing this.
Sorry that this time there are no code snippets to be shared. Just not that easy to fully illustrated the concept behind in a single blog.
Right now there is still one piece left in the keyboard bindings. When pressing X in the original game, the game will show all the exit locations of the current scene on the screen with symbols on them. The whole logic behind this is pretty complex too and I am still working on it, but I think it is close to being finished soon. We’ll see~
For the detailed development of the codes, please refers to the pull request on GitHub.

ResidualVM: Week 7

Sorry for you guys waiting as if there really are people waiting to read my blog, it seems that this week, and potentially next week, are still about finishing small tails left from the menu task. Well, this is not just because of laziness (and there is some laziness recently… I didn’t feel completely well for a couple days… But I am good now, so no excuses any more), but some of them actually have problems deeper than I had expected.
One example is the task of implementing the Book of Secrets, the extra content of the game, in the main menu. It looked easy at a glance since it is not a menu, but a game level. Just load the level when the button is clicked and there, the book opens.
The Book of Secrets
But that’s not the whole story of it. The Book of Secrets is probably the only game level that contains texts in its resources. When it comes to texts, one problem will show up: the texts’ textures will not be automatically reset when the screen’s resolution changes. I have done similar things before but again, things are different here. The level of the Book of Secrets contains only one location, but that location contains multiple layers, which all contain texts. The default implementation of a location will only list all render entries, which store the texts I am looking for, of the currently enabled layer. So I have to open a new interface in the Location class, let it list all the layers, then find the render entries containing texts and reset their textures.
Find all the layers and reset texts’ textures
Another annoying problem of the Book of Secrets is that it can directly quit to the main menu, which is accomplished by the script system built into the engine. The point is: the original implementation of the quitting to the main menu will automatically deallocate all the loaded game resources, but the script system is still running in the middle of the process, soSEGMANTATION FAULTTTTTTT!!! For some reason, I don’t use an IDE for development, and it seems that I still need experiences in managing pointers, because it literally took me an ETERNITY to realize what happened. Really, now I know the good of Linux, where you can install Address Sanitizer to help to debug. Fixing this issue is easy though, just delay the time where the quitting is actually performed.
Delay the quitting
The other task I have finished this week is about enabling the confirmation message dialog. Since the original game uses the OS’s dialog and right now ResidualVM has no API for this, after discussion I decided to just use ResidualVM’s dialog for the first version. At first, I intended to follow how (I think) the original game does: read all the message texts used from the gui.ini file, whose content may change to achieve localization. I had written all the necessary codes to do this, but then I found that ResidualVM’s dialog does not support non-Latin characters well. So sadly, right now only the built-in default English version can be used. I kept all the codes there though, for future development.
Now I am working on the keyboard binding task. Honestly, I didn’t know that you can play The Longest Journey with the help of the keyboard until my mentor told me so. It doesn’t look like a handy task, but manageable, and I plan to make it my last menu task before I officially start doing the shadow. Anyway, time to keep on working!
For the detailed development of the codes, please refers to this and this Pull Request on GitHub.
All code images are generated through Carbon.