Showing posts from 2018

ResidualVM: Summary

This is the summary of all the works I have done in Google Summer of Code 2018.

Overall Description: Improvement for the Stark engine used in ResidualVM for the support of the game The Longest Journey with two main focuses: menus and characters' shadows.

Pull Requests: Below are the main PR created and merged, ordered by the sequence of development. One may click the number of the PR to view it in detail on GitHub, which contains discussions between me and my mentor along the development.
#1415: Implementing the main menu.

#1417: Implementing the settings menu.

#1422: Implementing the save & load menu.

#1442: Implementing the video replay in the Diary menu.

#1443: Implementing the diary pages in the Diary menu.

#1450: Implementing the conversation log in the Diary menu.

#1456: Improving the debug console of the game.

#1467: Implementing the version info text and the Book of Secrets in the main menu.

#1468: Implementing a rough version of confirmation dialogs.

#1474: Implementing the keyb…

ResidualVM: Week 12

With the help of my mentor, I followed the logic in the original game and finally, now The Longest Journey in ResidualVM shall have shadows that are calculated based on actual lights in the scene!
Below are some screenshots as demonstrations. For a better illustration, I temporarily rendered the shadow with solid green. As you can see, in location 39 00, the shadow of April will become longer and change its direction based on the lights.

As I have said in the previous blog, the game computes the shadow in a way that is not the same as the reality. Well, with the help of my mentor on reading the disassembly, the truth behind the screen was revealed. Honestly speaking, after knowing this, I really don't think I can figure it out just by observing the game itself.
So, in general, the game first calculated an overall direction from lights. The way to compute the directional vector from lights varies based on the type of the light, but basically, it is related to the distance between …

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 b…

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.

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…

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.

As for the dialog panel, I made a wrong assumption in my previous implementation: assuming that all dialog options will be only one lin…

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.

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 suitabl…

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.

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 simila…

ResidualVM: Week 6

Not much update this week. The conversation log menu is still under review at this point, but it should be merged very soon.
The recent plan is to finish some small things left that are related to all the newly implemented menus. I have included all of them in the project on ResidualVM's GitHub page. Right now I have finished implementing two of them:
Task 1: Improve the debug console. Basically, this is a task about fixing issues. There is a debug console, which I have shown in week 1, provided in ResidualVM's The Longest Journey, where a number of commands are provided for users to look at the game's data and probably mess up with it. In the previous implementation, the console will crash if the user types improper commands in improper locations. Fixing this is not that hard, just add a bunch of checking beforehand and you are done with it.
Task 2: Add the version info text in the main menu. The lacking of the version info text was aware of weeks ago. I just want to tac…

ResidualVM: Week 5

This week's work nearly blew my mind...
So, it is finally the time to bring the conversation log back to The Longest Journey, which is another pretty complex menu in the game. In the conversation log, players may view all the past conversations they encountered. What makes this menu extremely complex is that it is completely dynamically data-driven generated. Based on your previous action, the conversations could be different. This means that retrieving all widgets of the current page at once is not working since you don't know for sure how many widgets there will be.

Worse still, this menu actually contains two submenus: the Index and the Content, which means I am actually implementing two menus on one trail. And just when I am typing this blog I suddenly realize that it won't be difficult to actually separate them as two distinct menus, damn...

The mechanism of recording conversations has been implemented in the existing engine, so my job is just to retrieve them and pro…

ResidualVM: Week 4

Not many things to update this week. I just started doing the internship, so I am still getting used to the new schedule. There is one thing I found out though: GSoC is like a million million million time more interesting than my internship. So sad that I cannot use GSoC to cover the credit requirement of my university.
OK, back to business. There are two focuses in this week: one is the video replay menu, the place where you can replay the video you have seen in the game, and the other is the diary pages menu, where you can read April's diary. These two menus are both pretty easy, so I actually didn't work heavy on them. The overall logic for them is pretty straightforward and is basically the same as what we have done previously. Get the widgets, render them, put actions on them, done.

Although pretty simple, there are still some small things that need to be treated specifically in these two menus.

For the video replay menu, the widgets for videos behave slightly differentl…

ResidualVM: Week 3

Time flies, isn't it?
This week's focus is on the save & load menu. Similar to the settings menu, the most important part of implementing the save & load menu is to implementing the widget that shows the save data.

I created a new class called SaveDataWidget for this purpose. A SaveDataWidget consists of three parts: the screenshot thumbnail, the text, and a blue outline that shows up when you move the mouse on it.

The thumbnail and (most of) the text are already saved in the original save data. All I need to do is to extract them out and properly store and render them. The thumbnail will be read as a Surface, which will then be bound to a Texture and then got rendered by a SurfaceRenderer.

The text further consists of two parts: the title of the chapter and the saving time. The title will be saved and loaded through the description field of the original save data, while the time is already saved in other fields, well, almost. The original version of the save data lac…

ResidualVM: Week 2

This week's main focus is on the settings menu, the menu that I deemed the most complex one before. Well, it is indeed complex, but the overall development process was again better than my expectation. Wish I can keep this good start along the way...
So, the settings menu. The first things to do is, of course, to get all the widgets rendered on the screen. The basic part is identical to how the main menu and the diary index menu are implemented. Dump the game data, load them with class StaticLocationWidget, and they are in position.  But the settings menu have some other bothersome things. It contains two special widgets: checkboxes and sliders. These two widgets are not stored in the place where StaticLocationWidget reads resources and they behave differently. 

One natural idea is to reconstruct the class StaticLocationWidget, making it a more general base class to handle all situations. But that would be a large task, and somehow unrealistic. The base class of any menu, the Sta…

ResidualVM: Week 1

Well, I guess the first week is the week that you learn the most.
For the first week, I decided to tackle the main menu of The Longest Journey,for the reason that the main menu can largely improve the experience of playing the game and many components of the main menu can actually be linked to the future diary menu within the game. Due to its complexity, I never intended to implement the whole main menu out within a week. I planned to build a basic structure of it, got something on the screen and then I can move on to other parts based on the built foundation. So far, the outcome is, surprisingly, better than I have expected.
That does not mean I didn't encounter difficulties. Right at the beginning, I found myself messed up in the different versions of The Longest Journey game data provided on the market. I got my game from Steam, and it turned out that I need to install two extra libraries to let ResidualVM fully support its different sound format. Have to say, using Windows is…

ResidualVM: Let's get started

Well, I didn't expect that making a blog will take my whole afternoon away. Making a good look on Blogger is really not that easy. I think I need to better strengthen my skill of choosing typefaces...
Ok, not the time for nonsense. So, I am going to take my first Google Summer of Code project. As a long lover of game programming and development, I am so happy that I got accepted in the project of ResidualVM, a 3D game interpreter for old PC games. I don't have actual game programming experience before and now I finally got the chance to see and feel (and potentially mess with) an actual game engine. I am really excited about what will I experience in the coming three months of working.
Well, for the project, I am going to further improve and develop the Stark engine within ResidualVM, which is the game engine for interpreting the game The Longest Journey. To complete the project, I am going to implement the game menus and the shadow feature. The menus part doesn't seem to be…