Europa-11

February 17th, 2014

This short story is a prequel to the game that I’m currently working on, Event[0]. With Emmanuel Corno, who is the other game designer on the team, we figured that it made sense for the Story section of the design document to take form of fiction instead of your typical factual description, so today I wrote Europa-11 in an attempt to give some background to our world and characters. In a way, this short story is an experiment, as it is the first piece of fiction writing I’ve ever done for a video game that won’t appear in the video game itself, so I guess you could call Event[0] transmedia now (haha, no fucking way). Does not contain spoilers for the game. May contain typos. Probably does. Yeah.

 

The world has changed: it is good now, united, peaceful. When the whole planet became a single political and economic entity, it was hard in the beginning, and restructuring took long years of strenuous labor on the part of our citizens and the Party. Finally we are able to put all of that behind us and start seeing and enjoying some tangible results of our work. The year two thousand and eleven has shown that we, the human race, are finally prepared to move forward. It is with your help, citizens, that the Party and the United Industries were able to accomplish some amazing things that will contribute to the well-being of human womyn and men today and for generations to come.

Thanks to your trust and support the Eden program colony was reopened on Mars. We finally implemented the space ed reform in schools and colleges all over the world, and our physicists have synthesised a new promising model of the Big Bang, which brought us one step closer to understanding of the world’s genesis. Thanks to a recent breakthrough in ecological research and with the help of the hard-working womyn and men of the Sustainable Manufacturing Supervision Committee, we reduced the carbon footprint of the space sector by an astounding twenty-six percent.

The most important breakthroughs, as usual, came from the private sector. The ITS Corporation, founded by Ms. Anele Johnson, our distinguished citizen and pioneer civil space explorer, in collaboration with SpaceX, launched a new scientific mission to Europa with fifty-two specialists in various fields on board. If the extra-terrestrial life exists in the Solar system, we are going to find it. If not, this mission will significantly improve our methodology and ultimately strengthen our expertise in detecting life forms on unknown planetary bodies.

Two thousand and eleven was truly the first year of the rest of the United Earth’s history. We all have a goal now, each and every one of us feels like they share a common purpose. Everything the United Earth does is directed toward space exploration, and our economy has reached its historic high. Our predecessors built death machines, looked for more effective ways to destroy each other and ultimately our home world. All of my energy and that of the Party have been directed toward broadening our horizons, and you can see the results our efforts today. It is a truly exciting time in our history, and the way our culture is shaping up continues to—

Greg flipped a switch, and the screen of a giant retro television set went black with a high-pitched analogue squeak.

“Hey, I was watching that!” Stacy didn’t sound amused. Greg knew that she watched each State of the Union address religiously. First, the United States, now, the United Earth. It didn’t matter, they had to be at the HQ in twenty minutes, and they had a pretty good idea of what President Shijuyama was going to say anyhow.

“Look, we are late, and if you wanna talk to Josh, we better get going,” he said.

“This is going to be the first State of the Union that I miss.”

“You can watch it on UStream on the way to the HQ.”

They didn’t have time to argue, and Greg knew that Stacy, despite her childish attitude, was capable of understanding that.

“I’ll watch it on YouTube tonight,” Stacy groaned and slowly lifted her massive body from the couch. Judging by her shiny forehead, that took quite a bit of effort.

“I’ve got the remote.”

Greg was the first to leave the house and reach the driveway. He stopped on the sidewalk, flipped the car remote in his left hand and pressed the Call button on it.

“Agh, it’s fucking chilly,” said Stacy, catching up.  Then she stopped, drew a breath and added, wistfully, “I wonder how Josh is doing out there.”

That day’s Google Car was a green Chevrolet sedan with a cheerful ITS ad on both sides. The car looked new, but Greg could already smell a mixture of piss, coffee and baby formula when he opened the door. It was amazing how similar the suburbs were to the city in that regard.

Greg got into the front left passenger’s seat, Stacy occupied both of the back ones, assuming a half-lying position and pulling a tablet computer from the ceiling.

“International Transport Spacelines Headquarters,” said Greg, holding the Destination button on the remote control. The Google Car audio system made an electronic feedback sound that vaguely resembled a water drop, halted for a few seconds, processing the command, then asked in an unnaturally polite male voice:

“Please confirm destination: International Transport Spacelines Corporation HQ, Palo Alto, California.”

“Yes,” replied Greg, putting the remote control back into his pocket. The car made another annoying sound and started to move.

As the Google Car pulled up by the front entrance of the ITS building, Greg realised that the radio had been off all along. Not only that, but Stacy did not attempt to watch what was left of Shijuyama’s State of the Union address on the car’s tablet computer that she grabbed in the beginning of their journey. It was either that or she had been watching it without sound, which made even less sense when you started to think about it.

When the car came to a complete halt, and the onboard sound system played its ever-annoying upbeat tune that was meant to announce the end of the trip, Greg turned toward the back seats and leaned forward in an attempt to get a better look of Stacy’s face.

She was lying on the seat, wide awake, concentrated on the car’s plastic ceiling. The tablet was back in its original slot. Greg didn’t say anything, sitting still in a taxi driver position, trying to read Stacy’s mind—a skill that he never quite learned during the eight years they’d worked together. After a while, Stacy looked at him and said:

“I am still thinking about Josh. How long has he been there?”

“I don’t know…a few months, maybe?”

“And before that, the training camp? Who are those people he’s with?”

“A few more months, and, well, half of them are ITS and SpaceX staff, the other half…”

“The question was rhetorical. I know who those fucking people are, I helped pick them myself—”

“Uh-huh.”

“—I just don’t understand how he could volunteer. How could it be only his decision? I know I encouraged him to follow his ambition, but—“

Stacy paused, swallowed, wiped her eyes with a sleeve of her green jersey and continued:

“I have been getting pretty worked up about it. It’s just hard, you know? My name is still Johnson, and you know what happened to my mom when she—

“And now Josh goes the fuck knows where. Fucking Jupiter, of all places, seriously?”

Greg wanted to calm Stacy down, but there was no time left, and he knew that the signal from Europa was stable enough to have an actual conversation only for very limited periods of time, and only God knew when the next opportunity to talk to Josh would present itself. On the other hand, he couldn’t have Stacy scream and shout in the control room like she did the previous time. Partner at ITS or not, she still had to follow the security protocol in there, and it was Greg’s job to make sure that she did.

“Look, Stacy, we’re at the HQ, how about we—“ he began.

“Do you realise how fucked up this whole situation is? Just tell me this, and we can go.”

Stacy didn’t sound hysterical, which was a relief. If he’d been in her place, Greg would probably have been beside himself. The situation was fucked up, alright.

Stacy’s mother, the infamous Anele Johnson, founder of the ITS Corporation, disappeared along with her partner and the first prototype of a Nautilus-type tourist space yacht. Some cruiser spacecraft captains claimed that they’d seen or detected the presence of the vessel in Alpha Centauri and at the far reaches of the Solar system. In some of these stories the ship sent out distress signals, in others all of its communications appeared to be dead. What all of them had in common was that they were invariably creepy as fuck and always ended with the ship disappearing without leaving a trace. This made Stacy’s mother a ghost lady in addition to being an important historic figure.

“I understand, of course I do,” said Greg, “But who’s to say that Josh will disappear? I’m pretty sure that it would be completely impossible to make that guy just vanish. No ma’am, not with that ego.“

Stacy didn’t smile, but her eyes stopped being cloudy, and her gaze was fixed on Greg now, which was a good sign. He continued:

“Now, c’mon, let’s go inside. Promise that you won’t make a scene. It’s not a good time for that. You can be as angry at Josh as you want when he gets back. Right now he really needs our support.”

Greg helped Stacy get out of the car and, when they both were on the sidewalk, he pressed the Leave button on the remote, sending the vehicle on its way. It was kind of amazing how fast everyone got used to all things AI-controlled. At first the general public was suspicious of the new technology, just as they were suspicious of augmented reality glasses before, and of cellphones before that, but ten years barely went by before the remaining human-controlled cars, trains, boats and airplanes were voted out of existence by a Party committee as unsafe and obsolete. Then, after years of extensive testing and experiments, ITS launched the first computer-operated spaceship, making artificial intelligence a de-facto standard in the transportation industry. From that point on it was only a question of time before the public perception of the new technology caught up with the demand for it. This made Greg think of the new model of the AI module on board Europa-11, Josh’s ship. He shook his head and followed Stacy into the building.

The ITS lobby had a clean futuristic look that you would expect from a lobby of a major tech company. True, ITS was as much about tourism as it was about building spaceships, and the giant aquarium with live squid on one of the walls attested to that, but the overall Kubrick-esque vibe of the place helped to sell tickets just as much. People who came there got the first taste of the space travel experience they were expecting. Comfort out of their comfort zone, as the corporate slogan went.

Apart from the front desk clerks and the customer service specialists, none of the ITS staff worked in that part of the building. It was unusual for someone from the engineering or the senior staff to enter through the front door, but Greg figured that it would take longer to give directions to the Google Car than to walk from there to the control room.

The rest of the building was all function and none of the form: white suspended ceilings, grey concrete walls and grey tiled floors. Visitors weren’t allowed beyond the front desk, and people who worked at ITS typically didn’t care about fancy lamps and ergonomic furniture. There were occasional coloured poofs and bamboo trees in halls and corridors of the closed part of the building, but the overall atmosphere was very no nonsense.

Stacy and Greg were passing the security check downstairs when an alarm went off in the control room. This could mean a lot of things, and Greg wasn’t one to jump to conclusions, but they really had to hurry up, besides, they were already five minutes late, and, as the ITS engineering team’s saying went, spacetime was not anybody’s bitch.

“There you are, come on, we’ve got a situation,” said Ellen, chief engineer of the Europa-11 program, stepping out of the control room. She looked even more disheveled and preoccupied than usual.

“What is—” started Stacy, but didn’t finish, because they had stepped into the control room, where everything immediately became crystal clear.

The room was in absolute chaos: people were typing on their computers frantically, some were running from one workstation to another, giving and receiving orders, a few dozen phone conversations were happening at the same time. The giant computer screen on the wall showed a wireframe image of the Europa-11 spacecraft on black background with all of the vital data regarding its systems and crew floating around. The ship didn’t look good: most of it was red, with little blue dots representing the crew members. Stacy gasped and let out a muffled cry of terror when she saw that there were only eleven of those left. The life support system was in critical condition, as reported by a giant red warning message near the bottom of the screen. All but one Kliper escape pods were disconnected and drifting away from the ship. None of them had any crew members inside.

“Fuck me,” said Greg once the initial shock passed, “What happened? Where’s the crew?”

“We aren’t sure yet,” said Ellen, “It looks like sabotage. Most of the crew are dead or missing. We were able to establish contact with Josh who was in the systems bay when this happened, but the connection is unstable.”

“Is he okay?” asked Stacy.

“He is, but he won’t be if he doesn’t get to the remaining Kliper. We contacted all of the spacecraft in the vicinity, but it is unclear whether they will be able to get there before the life support system goes offline.”

“Which systems are still nominal?” asked Greg.

“We have been able to restore door control and heating with Josh’s help, but the AI of the ship is blocking any further intervention, invoking the Code Red security protocol,” said Ellen.

“Shit. I knew this thing wasn’t tested enough,” said Greg and then bit his tongue, realising that it was he who signed off on the security status of Europa-11 before its departure.

Before anyone could say anything else, Josh’s userpic appeared in the top right corner of the screen, and the room went completely silent within a couple of seconds. Then the audio stream loaded, and Greg started hearing his friend’s voice. The connection quality was so poor that the words were barely intelligible:

“…I…this is not…left…the real threat…Klipers…transmission…is jamming…”

While these words were coming out of the speakers, all but one blue dots disappeared from the plan of the ship one-by-one, and the life support system warning now signalled that it was no longer operational. Josh appeared online when that happened, although the blue dot in the systems bay had already disappeared. Then a loud gasp came out of the speakers, followed by radio silence.

The room was completely still, no one moved, you could hear a pin drop. Everyone was looking at the screen, waiting for something to happen. After all, there was only so much they could do from the control center.

Greg was hypnotised by the remaining blue dot, making its way from the bridge to the remaining Kliper. It wasn’t Josh.

Josh was gone.

The realisation didn’t come at once, but when it did, Greg threw a quick glance at Stacy. She was standing next to the nearest computer terminal with a headset in her hand, looking at the screen blankly. She didn’t have time to say a word into the microphone before the connection broke. She was shivering.

Over the next five minutes, the dot moved, really slowly, on the ship’s wireframe plan. The moment it reached the Kliper, the screen went black for a split second, then Europa-11 reappeared, this time without any indication of the Kliper or the remaining crew member. The wireframe of the ship was green again, as if nothing had happened. The onboard AI was broadcasting a distress signal in all directions.

Ellen broke the silence by saying in a dry, emotionless voice:

“The reactor. It’s gonna blow.”

Everyone in the room knew that those were the last ten seconds of the Europa-11 program. Someone cut off the alarm.

Stacy started to cry softly as she sat down on the floor, trembling, unable sustain the pressure, giving in to gravity. Ellen, Greg and a few others followed her example.

It was all over.

Game Design, Writing | 2 Comments | Trackback

The Petri Dish State

November 30th, 2013

I am Ukrainian. I have been avoiding defining myself in this way my whole life, because where I come from stating your nationality is often associated with nationalism, and the latter is glorified. I am not a nationalist. As a matter of fact, I despise it as I do the rest of hate ideologies, but I think the time has come for me to state my position.

As you may or may not know, there have been massive protests in Ukraine over the association agreement with the EU that the government decided not to sign. I’ve read the whole document, and I think it should be signed. It won’t bring any immediate benefit to anyone (if anything, things can only get worse in the short term), but it promises some clear long-term improvements to the Ukrainian economy and policy in general, which is exactly what the country needs. This doesn’t mean, however, that I would have gone to the Independence Square to protest had I been in Kiev, because I don’t like the way this issue was politicised.

The opposition and most of the media were talking about this agreement in terms of some elusive “European values,” in terms of “freedom,” in terms of “euro-integration” and getting away from Russia. They changed the conversation. It was no longer about the unsexy export/import questions that would be answered, it was about slogans, over-politicised issues that let them distance themselves from the current majority, which is something that wouldn’t have been possible otherwise.

See, the opposition actually agrees with the majority on most of the things in Ukraine, so they have to shout really loudly if they want to stand any chance of being heard. Some of the issues include the question of the Russian/Ukrainian language status quo, others are all about the cooperation (mainly economic) with the East and the West. This trade agreement became one of these issues in a blink of an eye, and they readily jumped on it.

I don’t have a problem with politicising this issue per se if it would cause a national debate, if there is a conversation. I don’t even have a problem with political parties appropriating it (after all, I would probably have done the same). What I have a problem with is the part where the majority of the population remains completely uninformed about the details of the agreement, following the lead of people who don’t want to talk about it. This makes me angry, because you cannot have a meaningful conversation when one of the sides has no idea what it is talking about.

To make myself clear, let me just state a few facts:

  1. The agreement does neither guarantee, nor promise a membership in the EU.
  2. The decision does not belong to the Ukrainian government only, the agreement would have to be ratified in all of the EU member states (which would probably never happen, by the way).
  3. The agreement would damage the economy a lot in the beginning, and most of the Ukrainian major industries would take a major blow. It would also benefit the economy in five years or so a lot, because the parliament would have no choice but to pass trade and production reform bills to match the European standards.

Another major concern that I have is the opposition itself. Parts of it are leaning to the right heavily, with the grotesque extreme right wing Svoboda being a major force. If you read the history and the agenda of this party, you will see why I am afraid of empowering these people to make executive decisions (namely, being in charge of the military). Whatever the outcome of the current situation, the right wing will gain ground, and we have a presidential election ahead of us.

Historically, the opposition in Ukraine has been moderate right wing/centrist, mostly in order to distance themselves from the communist party on the left. I think that at this point in our history we should let the ghost of the USSR go, because we’re clearly not going back. I’m just afraid that some of the Ukrainians are so scared of going back to communism that they will support the nazis simply as the “lesser of two evils.” I find this situation unacceptable, and I if you disagree, I suggest that you read about the horseshoe theory before you start throwing virtual rotten tomatoes at my Facebook wall.

Now, with all that out of the way, I have to say that today I would go to the Independence Square if I were in Kiev. Not because of the euro-integration, not because of the economic agreement, not because I support some political party (I really don’t). What convinced me was the force used by the authorities against the people in Kiev. The riot police beat up some of the peaceful protesters tonight, thus effectively violating the constitution. People who gave the order (or looked the other way, which is exactly the same thing) are all from the current ruling party. This is unprecedented in Ukraine. This is a line that you don’t cross. This is a crime the government committed against its citizens. This is what convinced me that a change was needed, and I am sure it convinced many more people.

Update. Not being in Kiev, the only source of information about the protests I have is the Internet, and it was showing only one side of the conflict for a long time. Now it turns out that some of the protesters weren’t all that peaceful after all, which is making me reconsider my position somewhat. While remaining firm in my complete lack of support for the opposition, especially the extreme right wing part of it, I believe that the protests are now all about being fed up with the way things are right now, which is something I can understand and even relate to on some level. People want change. They aren’t sure what will bring that change, but they know that they can’t keep living like this.

Politics, Rants | No Comments | Trackback

Levels of Abstraction in Game Design

November 20th, 2013

Game design is often perceived as an idea-driven discipline in game development, and many people tend to fall into the trap of thinking about it in terms of pure creativity, neglecting the technical aspect. While having ideas is nice and useful, it is important to remember that everyone has them, and that an idea per se does not have any value. What counts is the implementation, and while writing a concept document or pitching a game may seem like an exciting task, it constitutes a relatively small fraction of the actual work a game designer has to do on any given project.

I am not going to go into more detail about ideas, concepts, team brainstorming and creativity, as this is a broad subject that deserves a separate post. What I would like to talk about here is the technical aspect of game design, various production techniques that can be applied in different situations and help the designer solve complex problems with less effort and more precision. The real game design work begins after the team (even if it is a team of one) has agreed on the concept, and yet I feel like we are barely scratching the surface of production techniques.

If you are anything like me, you are in constant search for game design cookbooks, opinion pieces and postmortems, and are probably familiar with the brilliant work of Jesse Schell, Brenda Romero (Brathwaite), Ian Schreiber, Daniel Cook and others. I am not going to try and rethink game design as such in a short blog article. In fact, everything that I am going to say is compatible with and relies upon these groundbreaking works from before. What I would like to do here is share some of the thoughts on the subject of methodology that I accumulated over the last few years, compiling them in a unified theory that I like to call Levels of Abstraction (LOA).

Perhaps the best analogy for LOA is a YouTube video that my teammates and I used to watch daily while working on Paradis Perdus. It’s a half-mocking that-part-of-the-internet kind of thing which demonstrates the “cuil theory” through text pieces that become more and more abstract as the number of “cuils” (or levels of abstraction from reality) increases.

In simple terms, LOA is a framework that allows the game designer to apply their analytical skills in the most useful way possible. Abstraction is important to understand and balance the game system correctly, and different situations demand different levels of it. The game designer chooses the LOA which is most suitable for them at any given moment, thus ensuring the effectiveness of their work. For example, sometimes the best way to describe a mechanic is drawing a simple sketch and talking to the concerned team members, while in other cases a spreadsheet, a text memo, a flowchart or even programming code will be the best medium.

Suitable LOA for any given situation can vary based on the team, budget, production timeline, development phase, game type and dozens of other factors. Each LOA is a tool that lets the game designer formalize and communicate a game system better, thus giving them more control over it. All and all, I am going to discuss five LOA that I have most often encountered myself while working on various solo and collaborative projects. It is also important to note that multiple LOA can (and should) be combined within the same project and often even the same mechanic.

Discussion is highly encouraged, and, if you have something to contribute to the list or have something to say about one of the LOA, don’t hesitate to drop me a line or leave a comment. This post is reference material, so I am fully prepared to update and improve it if need be.

Level 1: Empirical

This is the level of abstraction that manifests itself as a an explanation in plain words. It is probably the most common way of explaining a game mechanic, often used in introductory sections of game design documents, on websites and in communication between team members.

The character cannot do anything if she does not infect a host, even move. When one of the enemies is close enough to the character, the player can press the action button, which will make the character infect the enemy and give the player some new powers based on the things the enemy can do.

Often this kind of explanation is accompanied by a simple illustration that shows how the game mechanic works, making the description clearer. These images are rarely very detailed and usually look like simple mock-ups of the game scene with some additional graphics for explanation.

A mockup for Ricky, one of the first games I worked on.

LOA1 does not include any formulas or values and can be applied in situations where something has to be written down, usually because the game designer wants to remember something and come back to it later or to explain a mechanic in simple terms when no technical information is needed.

If LOA1 is used as the only way of explaining a game mechanic, it is the programmers who define how the mechanic actually works, finding the correct formulas and dummy values that the game designer comes back to later. This method of work often demands reiteration, but can be a good idea in case of small teams (including teams of one) with team members wearing different hats and having significant control over multiple aspects of the game. In a medium to big team, however, this may become a problem, due to the time it takes to reiterate.

Level 2: Schematic

This level of abstraction goes further and represents a game mechanic or a gameplay element in form of a graph or table. Thus, the level of abstraction is higher, and the gameplay is described more formally. It is common to see the second LOA in combination with the first one as a way of formalizing the system. Some mechanics and game situations are also better represented using the second LOA and don’t need LOA1 at all.

Table with AI mental states, player inputs and AI outputs. Unannounced project.

This is a common way of representing level design on a local (mission) or global (world) level without doing any 3D modeling. It is also often used for balancing skills and actions using numeric values without changing the underlying formula.

It is generally a good idea to use LOA2 if you want to show and/or compare large arrays of data that would take too long to explain or write down empirically. Like LOA1, LOA2 does not allow for direct control of game mechanics using designer-made formulas. However, it may use the existing formulas for data representation and calculations.

Level 3: Maths

This is similar to LOA2 in that numeric values are being used, but apart from that the designer creates their own formulas to represent game mechanics, making the level of abstraction even higher than before, which gives them a higher level of control and a better perspective.

DifficultyOfTransition = NumberOfTagsPerCondition / (N * NumberOfConditionsPerTransition * NumberOfWordsPerTag);

This level of abstraction is something that demands extensive testing before being implemented: either on paper or using a digital prototype of the mechanic that allows to modify the formula and different variables on the fly. The advantage of this method is that the game designer can achieve exactly the result they want by describing the mechanic in this way, allowing for more fine tuning and precise balancing. The downside, however, is that it may take some time before the programmer will start actually coding the mechanic, since the prototype must be tested before the implementation of the mechanic begins.

In general, LOA3 is good when maths matters: all kinds of logic puzzles, role-playing elements, and in general games that can be easily prototyped on paper without significant changes in their gameplay. It is probably an overkill for things like jumping, movement and everything else involving velocities, accelerations and other conventional physics variables.

Level 4: Algorithmic

The fourth LOA takes into account the ones that come before it. The game designer formalizes the game mechanic writing it down in form of a flowchart, pseudocode or simply as a sequence of actions with precise instructions.

Part of an AI algorithm.

It is hard to use this LOA for balancing things because of the nature of data representation, however, it is good for checking if the logic of the game mechanic works and making sure that things happen in a correct order. If this is not checked early in a complex game system, things can go very wrong later, and it will cost much more to repair them when they do.

LOA4 can point to specific values and formulas or not—this is entirely up the the designer. One should take into account the reason for using LOA4. If the goal is to test the whole mechanic on paper exactly the way it is going to work once implemented, then it is generally a good idea to use the real formulas and variables. In this case, automated finite state machine tools such as Playmaker for Unity may help. On the other hand, if LOA4 is used to determine whether the logic behind a specific mechanic works and to mitigate the risk of a wrong order of actions, a simple flowchart or an algorithm sequence can be used without getting too deep into the specifics of each state.

In my experience, both small and big projects can benefit from LOA4, but the designer should use it with caution, because it generally takes a long time to formally write down an algorithm for a complex system.

Level 5: Programming Code

It is often a good idea to write a mechanic (or a part of a mechanic) down in code directly, bypassing LOA4, because producing formalized algorithm structures for complex systems may take a significant amount of time, not necessarily justified by the usefulness of the final result. This is usually the case when the algorithm in question includes a lot of of small and/or simple actions which could easily be represented in code, taking up less space and demanding less effort and debugging. The image below shows that sometimes one line of code can replace a whole bunch of finite state machine actions.

Sometimes one line of code can replace a whole bunch of finite state machine actions.

It is generally a good idea to write down either very specific or very isolated mechanics this way, unless the game designer codes the game on their own, in which case writing everything in code is the only option anyway. Otherwise, the utility of this approach should be considered in terms of the formalization of the mechanic and its explanation to people who are going to implement it, so programmers. That is to say that you should consider it if you think that it is the easiest way to write a mechanic down.

Oh, and by the way, haven’t you heard? As a game designer, you need to know how to code, period.

Game Design | No Comments | Trackback

Short Fiction

November 1st, 2013

Short Fiction was short and it was, believe it or not, fictive. It lived under the city, swimming freely in underground canals that carried people’s waste mixed with rainwater, surviving thanks to a thin membrane it was wrapped in. Some alleged that the membrane was pure willpower held together with an ounce of sodium bicarbonate, while others claimed that it was partially bubble-gum. The truth was, as usual, somewhere in between.

Sometimes an odd shoe or a small coin would fall through the cracks of human existence, and then Short Fiction would rush to the splash site, forgetting all of its daily errands, plunging headlong into the unknown. Contrary to a popular belief, baby crocodiles rarely made their way into the sewers, so the reign of curiosity over the sense of danger was overwhelming.

On one particularly rainy and cold day, Short Fiction found a boy in the sewers and ate him. The boy was thirty-six years old, had a gorgeous beard and was entangled in tumblr, tweeting recklessly, producing all kinds weird indescribable noises and spitting out pieces of wood, hashtags and small blue feathers. As Short Fiction found out from his driver’s license, the boy was a Steve. Not a John or a Mike, not even a Keith, but a real, living and breathing, Steve.

Not that the name was a problem, but Short Fiction found itself dissatisfied with the outcome of eating Steve. You see, every now and then it had to digest things that it had swallowed, including memories, facial hair and experiences of little boys and girls it found in the sewers. None of them were completely pleasant, nor particularly repulsive, and Short Fiction found itself producing bland and discoloured copies of itself, unable to sustain the vibrant micro world of the city sewers. It was stagnating, becoming greyer and lonelier every day.

Short Fiction was going to make it right with Steve. Finding hard spots on his otherwise soft and elastic head, it carefully connected a bunch of electrodes to his brain and drained it of all of its ridiculous bullshit. When there was nothing left, Short Fiction looked down, trying to rest its eyes on the familiar moist pavement. It was then that it noticed something in the bullshit puddle on the ground. The object was small, shiny and had a fractal structure. It revolved around the center of the universe, biting off pieces of its entropy, creating true form in a seemingly irregular environment of virtual semantics.

Short Fiction put Steve down and picked the object up. Upon closer examination, the short threads sticking out of the object’s numerous edges turned out to be words. If you looked even closer, you could see logical connections between some of them. They formed clauses and sentences, referencing each other and dancing around the center of the branch they were tied to.

Short Fiction thought for a second and ate the object.

All of a sudden, nothing was there anymore: Steve was gone, the sewers were gone, and the city became little more than an odd memory. Everything was clear, but hardly simple now: words were everywhere, and the virtuality rushed into the world, splashing and ravaging, making all of the words bigger and more numerous. Short Fiction started drinking from the stream, hoping that it would end, but it kept flowing, filling Short Fiction up, making it bigger and more spherical. This went on until its membrane burst, and it instantly became submerged in reality.

Then everything stopped. Nothing was revolving and making deafening noises. Everything was beautiful, but no longer really there. Millions of transistors sang their digital song, lulling Short Fiction to sleep.

It was ready. It understood. It agreed silently.

Writing | No Comments | Trackback

Fully Responsive User Interface with Unity GUI

August 12th, 2013

Unity GUI gets a lot of criticism, and there are reasons for that: it’s not visual at all, you have to code everything, most of the time you can’t use it on mobile due to high redraw frequency and excessive drawcall use, etc. I agree with all that. However, it has a number of important advantages as well: unlike most of the external libraries and plugins from the Asset Store, it is integrated into the engine really well, and it is completely free. You can’t say that about EZ GUI or NGUI, now can you? This last reason is probably the main thing that makes people use Unity GUI, and they are right to do so. Why pay $100+ when you can get the same result for free?

I have used Unity GUI on a variety of different projects and in a variety of situations. Over the years I have dug up a bunch of really useful tricks that help me code a basic interface in a matter of minutes. It was a couple of weeks ago that I decided to gather this stuff in one class that helps me overcome the main bottleneck of Unity GUI: its inherent lack of responsiveness. The term “responsive” comes from web design, and means that the interface adapts to the screen resolution. A modest example of responsive web design is my web site. Try resizing the window of your browser and see how everything scales and moves around. When you are making a cross-platform or PC game, you want it to be able to adapt to resolution as well, and to do that, the interface elements have to stick to their part of the screen and retain their size relative to the screen size.

My class is based on the basic idea behind Automagic GUI Scaling in Unity3D by Simon Wittber: you choose one resolution that you consider the “base” resolution, defined as WIDTH and HEIGHT constants in the beginning of the script (usually it will be the most popular resolution of your intended audience), then resize the GUI elements using GUI.matrix. The difference is that in Simon’s example you will end up with “offsets” on top and bottom of the screen if your screen ratio is different from the resolution that you specified with WIDTH and HEIGHT, which we don’t want. I solve this problem by applying the resize method to different regions of the screen separately, thus effectively masking the annoying offsets.

Now that we’re done with theory and explanations, you can get the GUISizer class here: http://goo.gl/wgdFX6. You can also download an example project here: http://goo.gl/5F5PIY. Or, if you prefer, the same thing as a UnityPackage that you can import into your own project: http://goo.gl/GKczDm.  The source code is also added to the bottom of this post in case the links die. If you use C#, then feel free to put GUISizer.cs anywhere you want in your project. However, if UnityScript is your cup of tea, then it has to go into your Plugins folder. Otherwise you won’t be able to access its methods and structures.

With that out of the way, you can start poking around in the test project. To test how it works, just try resizing your Game view window. Below is some API with explanations, as well as the source code. Feel free to ask questions or suggest adding or changing things in the comments or elsewhere. You can use GUISizer in any commercial or noncommercial projects as you see fit. And of course enjoy the fully resizable Unity GUI!

P.S. As a bonus track, in the example project you will find a script that lets you position a GUI element in world coordinates (like the text label that you can see sticking to the cube in the video above).

Struct: 

struct GUIParams

This struct lets you create a variable of type GUIParams: a button or a label, with specific parameters that you pass to the constructor.

Constructors:


Methods:

void BeginGUI(PositionDef elementsPosition = PositionDef.middle)

This method has to be called in the beginning of a GUI block, the parameter that it takes is the position of the elements in the block on the screen.

void EndGUI()

This method has to be called in the end of a GUI block. There has to be one EndGUI for each BeginGUI. What’s between the two is a GUI block: buttons and labels.

Rect MakeRect (GUIParams guiParams)

Converts GUIParams into a Rect.

bool ButtonPressed(GUIParams guiParams)

bool ButtonPressed(GUIParams guiParams, int customFontSize)

bool ButtonPressed(GUIParams guiParams, GUIStyle style)

bool ButtonPressed(GUIParams guiParams, int customFontSize, GUIStyle style)

Checks if a specific button was pressed. Takes a GUIParams struct as a parameter. You can also provide a custom style and a custom font size as a parameter.

void MakeLabel(GUIParams guiParams, string additionalText = “”)

void MakeLabel(GUIParams guiParams, int customFontSize, string additionalText = “”)

void MakeLabel(GUIParams guiParams, GUIStyle style , string additionalText = “”)

void MakeLabel(GUIParams guiParams, int customFontSize, GUIStyle style , string additionalText = “”)

Draws a specific label. Takes a GUIParams struct as a parameter. You can also provide a custom style and a custom font size as a parameter. Additionally, you can provide text that will be appended to the label, which is useful for things like score and lives.

Variables:

float WIDTH = 960;

The “base” width of the screen. This is the width of the screen relative to which all GUI elements will be resized. Change it directly in GUISizer script.

float HEIGHT = 600;

The “base” height of the screen. This is the height of the screen relative to which all GUI elements will be resized. Change it directly in GUISizer script.

const float SMALL_BUTTON_WIDTH = 100f;

const float SMALL_BUTTON_HEIGHT = 50f;

const float MEDIUM_BUTTON_WIDTH = 200f;

const float MEDIUM_BUTTON_HEIGHT = 100f;

const float LARGE_BUTTON_WIDTH = 300f;

const float LARGE_BUTTON_HEIGHT = 100f;

const float BUTTON_GAP = 10f;

enum PositionDef { topLeft, topMiddle, topRight, bottomLeft, bottomMiddle, bottomRight, left, right, middle }

Enum that is used to define and identify “anchor” positions on screen. Positions themselves are set in the private method SetPosition.

enum SizeDef  { small, medium, big }

Enum that is used to define and identify sizes of elements. Sizes themselves are set in the private method SetSize.


Source code of the GUISizer class, as promised: http://pastebin.com/MDazhK6L


				
				

Coding, Unity3D | 2 Comments | Trackback

The Choice Between Unity C# and JavaScript

July 20th, 2013

This post was written for one simple reason: the question comes up way too often, and I keep saying the same things and listening to the same counter-arguments over and over again. On top of that, the majority of these discussions take place in discussion-unfriendly spaces, such as Twitter, IRC and, of course, the real life. I just want to write all of my reasoning down, so that the next time it happens, instead of engaging in a pointless debate, I will be able to just link this article.

I will begin by talking about my background in programming, which, hopefully, will give you some idea of the reason why I keep saying the things I say. If you (understandably) don’t care about that, you can just skip the next few paragraphs.

I started coding when I was 12. I had no Internet connection, no previous background in any related fields and no particular interest in science (except maybe physics a bit). On the other hand, by then I’d designed my first pen-and-paper and live action games, and just wanted to make video games. As it is often the case, it all began with someone telling me that you have to write code to make video games (which was the case at the time, but isn’t the case any more with things like GameMaker, CraftStudio and PlayMaker for Unity empowering the non-programmers greatly). So I went to the Kiev’s largest book market on a quest for a programming tutorial book. And I bought it. It was a book on Borland Delphi 6 suggested by a salesman as a perfect place to begin programming. I never managed to do much with Delphi: just a couple of Windows applications which helped me solve my middle school math problems.

A couple of years later, during my senior year in middle school, I began coding in Pascal (which is very similar to the Delphi syntax). It was then that I made my first simple video game: it was an interactive fiction thing based on one of my naïve teenager short stories, something that I would definitely suggest making in Twine. Then came the university with its C++ used for Windows applications (Borland C++ IDE was horrible!), later LISP, assembly languages, PHP and HTML. I tried going through C++ tutorial books and developing a game using DirectX. The bad news was that I found it tedious and just kind of drifted away from the idea. Instead, I learned C# and made a couple of Windows applications with it. It was then that Unity came along.

That’s right, when I first discovered Unity, I had about a year of experience working with C#. I honestly tried using it with Unity, but I didn’t succeed, because at the time most of the tutorials and the lion’s share of documentation were in JavaScript. Now, three years down the line, I have switched back to C#, because my projects have caught up with the possibilities that this language presents, and I know Unity pretty well. My conviction is that when you start working with Unity, your best bet is UnityScript (officially called JavaScript now, but it’s not really the JavaScript that you might see on the web), and not only because of the documentation and tutorials.

A beginner in Unity is likely to have a hard time with the vast new framework that Unity presents. And, frankly, no one needs to deal with both this and things like delegates, constructors, lambdas, events and interfaces. Extensive OOP and verboseness of C# combined with the huge new framework to explore is capable of making people quit game development altogether (C++ memory management combined with DirectX almost did it for me at one point). I know that for some of you the concept of a “difficult programming language” is hard to grasp, especially the knights of shaders and C++, but I assure you, some languages are more difficult to use than others.

Not only is C# more verbose, it also has a way of making you think about things that you would never have thought about. Things like this:

transform.position.x = 5; //UnityScript code

transform.position = new Vector3(5, transform.position.y, transform.position.z); //C#—notice the difference?

And this:

yield WaitForSeconds(2); //UnityScript code

yield return new WaitForSeconds(2); //C# code.

By the way, the call above is in a coroutine, which has to be started using StartCoroutine in C#, unlike in UnityScript, which does it automatically

This is a good thing for an experienced Unity programmer working on a medium to large project, but a disaster for a beginner trying to put together their first Pong clone. Beginners don’t need to think about optimizing for this kind of overhead unless there’s actually some kind of hiccup in FPS of the game (spoiler alert: there won’t be, not caused by this, anyhow). This stuff is just too much information to take in when you’re starting to use a new game engine.

I often hear people say that UnityScript is bad because it is not strongly typed. Well, to that I answer that it is if you want it to be. My advice to everyone using UnityScript out there is to include the #pragma strict directive in the beginning of all your scripts, which makes it infinitely more explicit. It’s also a good idea to use #pragma downcast along with it. You need not worry about it though, because #pragma strict is now automatically included in all UnityScript files! Just when you make a variable, always define its type, and you will be just fine. This is not your typical web JavaScript, boys and girls, you can even use the .NET framework with it without any problems.

Another curious thing about the “conventional wisdom” of Unity programming languages is a myth about JavaScript somehow being inherently slower than C#. This is such a common misconception that it almost became religious. The only thing in which it can be slower is the overhead caused by really convenient abstractions I talked about above. If you know how to use it, you will avoid it, and a complete beginner doesn’t have to worry about it, as we have already established. Now, some people suggest that there is some internal compilation magic going on with UnityScript under the hood, that there is some kind of evil virtual machine emulation going on in the CIL. Some even go so far as to say that C# is compiled, while JS is interpreted. With that being the case, you would expect JS to be slower, right? Right? Here is the Unity community at your service, benchmarking the languages: http://forum.unity3d.com/threads/29778-newby-performance-question-which-language-is-best As we can plainly see, the results are the same or the difference is negligible.

And if that doesn’t convince you, here’re a couple of tweets from people who work (or worked) at Unity Technologies:

To sum up, if you are a beginner in Unity, you might want to consider using UnityScript at first if you will not be working on projects that risk getting really big. If you are experienced in Unity and/or your projects are big, you might want to switch to C#, because it offers more possibilities in terms of encapsulation of classes and optimization, making your large projects more manageable. Namely, people tend to leverage the power of events in C# with great success.

Regardless of what language you use, I think that everyone should know how to avoid inefficient code once they are more or less comfortable with the Unity’s framework. Mike Renwick and myself have put together a short list of things you should check if you’re developing for mobile, but most of those things are actually valid for all the platforms. Apart from that, there’s the official Unity’s guide on optimization. Make sure to check it out if you haven’t yet.

With that I say goodbye and hope that you have a nice holy war in the comments.

Coding, Unity3D | 1 Comment | Trackback

Mecanim Animation Events Workaround and Example

May 9th, 2013

Last night I spent a couple of hours trying to find a native solution for animation events in Mecanim in Unity, but all I found was a $35 Asset Store plugin. While I don’t doubt the usefulness of it and the interest of adding visual interface for events, it was much more than I needed (and was willing to pay for it). I couldn’t find any way to directly access animation frames either, so I spent the next few hours making a workaround for it.

If you know a better solution, don’t hesitate to use it and drop me a line. I’m sure it exists, but the doc is so incomplete that I simple couldn’t find it.

Now, what I wanted to do was to play a jump animation, then, during the last animation frame (before the transition to idle), teleport the character root to the new position of the biped. Here’s a video of what the final animation looks like in the Scene and Game views:

As you can see, the game object stays the same until the last frame of the animation, then it gets teleported to the position of the biped on top of the rock thingy. To achieve this, you will need to do a couple of things:

1. Import animations and set them up to work with your biped. For my example, you’ll need a jump animation that moves the root of the biped and an idle animation. You can look this up in billions of Mecanim tutorials on the Internet.

2. Put an empty game object at the position of the pivot point of your character (which should be on the ground between the character’s feet by the way), then parent it to the biped. I’m calling my object BipPivot. We will later use this object as a reference for teleportation.

3. Uncheck Apply Root Motion and check Animate Physics on the Animator component of your character. The former is done because we’re making a custom system to move the root and we don’t want the Animator to mess with it. Moreover, this option often gives strange errors (depending on your import settings). The latter is absolutely necessary, because it animates the avatar in FixedUpdate: we’re going to use this later to get the precise number of FixedUpdates of our animation.

4. Set up your Animator so that you have your Idle animation connected to your Jump animation and then Jump animation connected to your Idle animation.

5. Here’s where things get interesting. You have to select the transition from Jump to Idle and make the transition gap equal to 0% as shown in the image below. This is done because we want the Idle to kick in immediately after teleportation.

6. Now we’re going to measure the length of the Jump animation in FixedUpdates. To do this, you need to call your Jump animation by setting a parameter somewhere. Example: “animator.SetBool(“DoJump”, true);” Then run the following code:
private var frameCounter : int = 0;
//Base is the name of the animation layer, Jump is the name of the animation
//it is unclear from the documentation, but you can't compare the name in string
//it absolutely has to be hash
private var jumpState : int = Animator.StringToHash("Base.Jump");

function FixedUpdate()
{
if (animator.GetCurrentAnimatorStateInfo(0).nameHash == jumpState)
	{
		Debug.Log("I am a counter, the number you're looking for is on the right →");
	}
}

Run the game, run your Jump animation and observe the Console. The number on the right is the number of FixedUpdate “frames” of your Jump animation. In my case, the number is 158. Yours will probably be different. Remember it.

Once again, this is not a general Mecanim tutorial. If you don’t know how to start an animation, consult one of the Mecanim tutorials on the Unity website or on YouTube.

7. Now replace the code that you used to detect the number of frames by the code snippet below. It teleports the character to the position of our BipPivot game object.

private var frameCounter : int = 0;
//Base is the name of the animation layer, Jump is the name of the animation
private var jumpState : int = Animator.StringToHash("Base.Jump");
function FixedUpdate()
{
	//check the name of the current animation state
	if (animator.GetCurrentAnimatorStateInfo(0).nameHash == jumpState)
	{
		//increment frame count
		frameCounter++;

		//check if we have reached the last animation frame
		if (frameCounter >= 158) //because 158 is apparently the last jump animation frame
		{
			Debug.Log("Teleport now");

			//reset the frame counter
			frameCounter = 0;

			//teleport the parent game object to the position of BipPivot
			this.transform.position = this.transform.FindChild("Bip001").transform.FindChild("BipPivot").transform.position;
		}
	}
}

This method can be applied to any kind of animations and events. You can measure the length of the animation in FixedUpdates and then do something on a certain frame. I’m teleporting the character in the end of the animation. You can do something else.

I hope my code snippets will be useful to somebody and I also hope that there’s a better way to do this, because this is a hack, not a solution to the problem.

Coding, Unity3D | 4 Comments | Trackback

Untitled Story

February 12th, 2013

Visions of the ocean. Smell of burnt cinnamon. Prog rock echoing in my ears. You’re far away, you’re not with me.

Sometimes I dream of empty cinemas and large bodies of water, and a lonely cliff above an endless void. Cheap French wine, cotton stuffing in my limbs. Light and easy, gently dismissive. It’s not like anything else. This feeling.

The truth is, we all matter: you, me, her. Our choices carve the thin line that separates fear from devotion, faith from abuse, loyalty from fixation. You shoot a ray of light at the stars, it slides off the edge of your soul in a myriad of soap bubbles and dust particles. I intercept. I am still the boy standing in front of the big tree in my old neighborhood, playing with my rusty pocket knife.

You should not talk to strangers, you should believe in God, you should buckle up. It’s your responsibility, not mine. The next round is on me. He was such a great kid. A faraway planet is looking at you through a haze of nonexistence, its population running in fear, colliding with your dust particles, smelling the danger, drowning in the ocean. A small black figure near the edge of the biggest continent is immobile, resigned. It lifts its head and takes a long look at the supernova.

You’re supposed to, you have to, you must, we expect you to—obey, in so many words. The real danger is your own thoughts, your own actions, your own frailty. The fact that you really matter distorts your own consciousness to the point of nonexistence. You’re standing on the edge of a cliff, looking down into the void. I watch silent movies, all alone, enveloped in fear and anxiety. I see waves of water, hissing, and a flock of seagulls mixed with dust, bathed in late autumn sunlight. So pathetic. So heartwarming. So real.

It’s amazing how someone so incredibly hideous can be this beautiful. You know who you really are, you look in the mirror every day. You look at me and you see the same reflection, distorted and ghastly, unable to cope with the interference. Your world suddenly becomes unstable, and I can do nothing about it, falling through, trying to grasp the ultimate meaning of everything that ever happens. Pure thought, unrestrained, transparent in its unimaginable hopelessness. I am not really who you think I am. I am standing on the verge of myself, looking down into the void. You are falling through the membrane, soap bubbles dancing around your pale body. I am the only one who can really see you.

Fast forward to the beginning of our existence. Everything is there, within your reach. I hold out a hand and pat you on the back. You sigh equivocally. Something is not quite right and we both know it.

Suddenly, I realize that you are nothing but a separate entity. My eyes close and open again. I am no longer dreaming. I am right here, in front of the rest of the universe, emitting heat, reflecting and absorbing light, succumbing to the pressure of the atmosphere that covers our small planet. Resigned and a little sad, I look up at the supernova.

Writing | 1 Comment | Trackback

Lessons Learned from Two Ludum Dares

December 17th, 2012

This summer I participated in my first Ludum Dare, and I have to say that, as development goes, I managed to make a couple of really bad choices. Here’s a short list of what you should not do:

  1. Do not spend 30 hours making graphics assets and music.
  2. Do not make a game that relies heavily on animation, animation is the worst time-consumer.
  3. Do not use tools that you are not familiar with (in my case—RagePixel for Unity, an awesome but buggy tool that I decided to try for Ludum Dare).
  4. Do not spend hours making levels: level design is something that always takes more time than you expect.

Now, to give you an idea of what came out of this, go check out my 30-second game with lots of stuff packed into those 30 seconds, but 30 seconds nevertheless. It’s called Dissolution (screenshot is a link to Kongregate).

Now, I have learned my lessons. For my second consecutive Ludum Dare I sure as hell wasn’t going to repeat the same mistakes. Here’s my short list of conclusions regarding what you should do for a 48 hour solo game project if you want to actually complete it and maybe squeeze a few hours of sleep somewhere halfway through.

  1. Do make all things procedural. You’ve got enemies? Great, make them spawn procedurally and randomize their types. Got platforms? Generate short sequences and randomize them. Making a labyrinth game? Awesome, there’re dozens of maze generation algorithms on the web.
  2. Do make stylish graphics. Your Ludum Dare game can look good even without those shiny sprite sheets and complex 3D models. Keep your artwork as simple as possible and compensate by having nice-looking visual effects.
  3. Do make sounds and music. This is essential for correct perception of your awesome art style. What worked great for me so far is stylized graphics + more or less realistic sounds.
  4. Do design a simple game for each of the 12 themes in the final round of voting. It is a good exercise in game design, and it will help you get straight to coding once the theme is announced. Ideas are cheap, what counts is implementation.

As far as assets are concerned, you have to find a balance between sound and graphics, because you can’t make both very sophisticated, you have to prioritize. If you do all of the things suggested, you will find yourself being able to sleep a whole night and spend up to 12 hours polishing and optimizing your game, which, in turn, means that you will end up with something that feels infinitely better than most Ludum Dare games.

All those things out of the way, I give you Pineapple Dreams, my Ludum Dare 25 game about being a villain. The game features ultra-violence and was inspired by A Clockwork Orage, Drive and (you guessed it) Hotline Miami. Screenshot is clickable and leads to the game’s Kongregate page.

If you are looking for desktop versions, they also exist on the Ludum Dare page of the game. Below is the tune that I composed for this game.

Game Announcements, Game Jams, News | 4 Comments | Trackback

Paradis Perdus for Linux Released, Press Roundup and the Indie Dev Grand

December 1st, 2012

Today Paradis Perdus got nominated for the Indie Dev Grant by Bundle-in-a-Box. This means that people who buy the bundle will be given a chance to choose a game that they think deserves to get the grant. The grant itself is a certain percentage of money from every purchase of the bundle. This money will then be used by the development team (or the individual) who wins the grant fo finish their project.

The last Indie Dev Grant went to Simon Roth, who has recently joined the ranks of Kickstarter success stories with his kickass project, Maia. We’re really hoping to be the next.

And now that I’m done with this little promo (please, please vote for us when you buy the bundle!1), I’d like to say we are really thankful for all the support and feedback that we have received since release of the alpha, so to give something back, we are releasing a Linux version of the game now.

You can download the Linux version of Paradis Perdus (1.0.41) here:

http://www.mediafire.com/?j1cvxhrdygadgyd

You can still download Mac and Windows versions here: http://sergeymohov.com/paradis-perdus

From now on, we are going to update all three PC versions of the game simultaneously: Mac, Linux and Windows.

Please, leave comments, tell us how it works! We need your feedback, this is why the current version is called an alpha.

If you are not planning on buying Bundle-in-a-Box (which is, by the way, a mistake, there’re always plenty of super awesome games in it), you can also support us by tweeting about Paradis Perdus with #myouyagame hashtag. This might just get us an OUYA SDK and you an OUYA version of the game! Gamepad controls are already implemented, we just need a console to test them on.

Finally, to end this post, I’ve prepared a short roundup of media responses to Paradis Perdus (in chronological order).

Bundles, Game Announcements, News, Platforms | No Comments | Trackback

Categories

Find:

Links