WarClicker 2 / MiniLD66 post-mortem

Yeah! I finally have time to write on my blog! As promised in the last post, here comes 3 post-mortems, one for each game jam I participated to at the start of April.

First, the Mini Ludum Dare 66 which I started on 28 March and ended the 02 April.
The theme was “You must construct additional RTS games”, I collaborated with Ted Wennerström, a swedish composer / sound designer who created the musics and sounds of the game.

The theme and the game

WarClicker 2

WarClicker 2 isn’t a Real Time Strategy game, you can download it on this page.
In this game you must defend helpless villagers who are assaulted by an army of orcs, you have to kill those orcs by clicking on them. If every villagers die you lose, the orcs will come by waves and you can perform different attacks depending on the mouse button you use.

I started my reflection on the theme by defining what is a RTS and more precisely what makes up the 4X genre: eXplore, eXploit, eXpand, eXterminate. In the limited time of the game jam I thought that focusing on exploration and extermination related mechanisms would allow me to have a more interesting game at the end.
This approach blurs the line between RTS and more action-oriented games, also I was more interested in exploring the interaction with the mouse than making a classical RTS with few chances to finish it in time.

The game concept I wrote for this game contains a lot more features but I wanted to work on the core gameplay: clicking enemies and mouse combos. If this core can be appealing then I’ll try to implement the rest, with just the core the game is similar to Whac-a-mole physical arcade game with slightly more complex controls.

Whac-a-mole game

What went right

  • The communication between Ted and me went well and he made a great job, the sounds fit well in the game.
  • I learned a LOT of things on Unity, mainly in sprites’ usage and creation of simple interface. Also the use of Raycast2D and filtering the results. And many more things…
  • I used the sprites of WarCraft 2 as they are exactly what I needed for this game (and that’s one of the first video game I ever played :p), and this has the visual result expected.
     I don’t own any rights on WarCraft 2, this game was created by and is property of Blizzard Entertainment. I’ve got no intents to use it commercially or make any revenue with it.
  • I made a little settings menu with few customization options including a colorblind mode.
     For the colorblind mode it covers deuteranopia and protanopia, I used the colorimetry tool of Illustrator to define which colors to use on important gameplay elements.

What went wrong

  • The first test was too late, thus preventing me from really working on controls and implementing the mouse combos.
     I took too much time on less important things like the background tiles when I should have test the game with just color boxes right away.
  • There’s only one type of enemy, I wish I had the time to make one or two more.
     With fixed speed and behavior for each, this would have enabled pattern based learning and so improved the learning curve and the coherence of the game.

In general I’m happy with what I managed to accomplish in 5 days and the amount of new things I have learned during those. In its actual state the game isn’t the funniest on earth but at least it’s not totally boring :)
I’ll work on it again later, right now I started to work again on Spirit Run with the team I had at the Global Game Jam 2016.

In the week to come I’ll write my post-mortems of Nordic Game Jam 2016 and Ludum Dare 35, until then, have a nice day/night!

Miscellaneous / Some news

Hi everyone, this post will quickly cover what I’ve been doing this last month and what I’m gonna do in the next to come.

The last month

I’ve spent the last 2 weeks in redoing my résumé, Linkedin and portfolio site in english and in french. Now I can say that they are finished (at least the portfolio just need more content, the technical part is done).
You can find them at these adress :

I also worked on Harvest Nothing 64 to implement movements / collision detection and map generation. When I finish this, I’ll write 2 or 3 posts on these systems because they are far more complex using GameMaker:Studio than what I considered at first.

The next month

This month is heavily loaded for me, this begin today with the Mini Ludum Dare 66 which I’m gonna start at 20:00 GMT+1 and stop the 02 April at the same hour.

On 07 April I’ll take a flight to Copenhagen, Denmark to participate to the Nordic Game Jam 2016 from 08 April to 10 April then I come back in France the 11 April.

From 15 April to 17 April I’ll participate to Ludum Dare 35 with a friend who is software developer, we’re currently looking for 1 or 2 artists to take care of graphics and sounds.

If you want to work with me on these game jams or meet me at the Nordic Game Jam, don’t hesitate to contact me! =)

I also start to look for a job in the game industry as a game / level designer and I’m interested in working in Europe or in Canada.

To finish, there’ll be posts on all these wonderful events. I’ll find time to write them, it’s a promise!

Harvest Nothing 64 / Event system revamp & inventory

This is the first post on a long succession to come about my progress on this project.
Simple recall: I’m replicating Natsume’s HarvestMoon64 [HM64] for educational purpose only. The goal for me is to learn how to use GameMaker:Studio [GM:S] with GML.

Today I discuss the work I’ve done this week, modifying / cleaning event system and implementing inventory system.

Event system

I created an event system overlay on top of GM:S built-in event_user() function (introduced in this post). Obviously there was room for improvement and factorizing so I started by doing this.

Lazy loading ds_list through different objects

I tried lazy loading ds_list of events’ subscribers in s_SubscribeTo:

if(!ds_exists(EventManagerID.ListVariableName, ds_type_list)){
  EventManagerID.ListVariableName = ds_list_create();
}

But GM:S seems to get in troubles when it comes to create ds_list in instance variable already initialized to undefined in an other object. Maybe a with structure would solve this problem. Instead I just created ds_list right from the start in EventManager object, later in the project I’ll come back to this problem.

Asynchronous event processing

One major improvement is the implementation of an event queue using a ring buffer to store events that happened and process one event each room step.
This pile of scripts moves the ring buffer:

  • s_EventQueueInit(): Initialize an instance array of “maximum events pending at the same time” size to undefined, an instance integer Head to 0 and one other for Tail.
    It’s called by o_Events at creation (Before game world creation).
  • s_EventProcess(): Test Head equality with Tail, if true return immediately. Else it notifies subscribers of the event in the Head cell of the array, then advance Head to the next cell.
    It’s called by o_Events once each room step.
  • s_EventPublish(enum g_Events): Add the event given in the Tail cell of the array, then advance the Tail to the next cell. It’s called by every objects that wish to publish an event.

Inventory system

If you’re reading this, you’re probably using MS Edge, there is a gif that is hidden right here. Edge is literally killing itself on it, I’m sorry for that inconvenience and will look for a solution for future posts. Nevertheless if you still want to see this gif with Edge, open dev tools (F12) and modify properties of it: width=600 / height=338 / style=”visibility:visible”

Starting from the end, here’s what the inventory screen currently looks like. Fancy graphics will come later in the project.

Demonstration of inventory system

Comparison of the HM64’s inventory screen with the one I made.
There is no visual differences between zones for the moment and no arrow to indicate that page can be turned, these are things I’ll add later.

Inventory comparison between HarvestMoon64 & HarvestNothing64

General behavior

This system is compounded by multiple objects with limited responsibilities.

  • o_Inventory is the entry point, it’s created at the start of the game and spawns o_InventoryData that hold… data.
  • o_InventoryScreen is created at the inventory overture and destroyed at the close, it’s the central pivot of the graphical representation of the inventory.
    It spawns grids of o_InventorySlot and dispose them properly on the screen (Slots are just the frame, they don’t draw the objects inside them).
    It also spawn the o_InventoryCursor which is just aware of its coordinates on the grid & the screen but don’t knows what it’s pointing at.

The screen is completely independent from the data and don’t intervene on data’s operations.

Inventory system objects

Data modelisation

The data are simply stored in one dimensional arrays, there’s one array for each of 3 categories of objects: Tools / Belongings / Keys. Additionally each hands has one dedicated integer (the equipped tool and belonging).
The value stored is the object_index, an integer defined by the position of the object in the project’s hierarchy under “Objects” folder.
This way all operations are done on positive integers rather than strings, and don’t rely on instances which would be lost between rooms and occupy memory for nothing.
Another advantage is that I just have to create one object for each one I want to include in the game (not two separate versions, one for the inventory and another for the game).

One design flaw though is based on this inevitable choice:

  • Should the object knows in which category it belongs to?
  • Should the inventory keeps an array for each category to compare to?

I decided to go with the first option, thus avoiding search through arrays when adding an object to the inventory in game and avoiding hard-written lists of object indexes which is less maintainable and more error-prone.

Inventory screen

When the player open the inventory screen (pressing a dedicated key), the context changes and the arrow keys immediately control the cursor. He can select objects and swap them with others using ‘Validate’ key and cancel the current selection or close the screen with the ‘Cancel’ key.

The inventory screen is cut in zones corresponding to different types of objects and the cursor moves differently between them wether something is selected or not.

Inventory zones

For example when a belonging (2) is selected, if you press up arrow key on the first line of the zone, the cursor will jump directly to the off hand (5) and can’t go anywhere else than these 2 zones.
The keys’ zone (3) has multiple pages that can be turn when going up or down on edges.

The screen is another room you’re shifting to when opening the inventory, the grids are created and disposed at this moment: the room in GM:S has just one instance of o_InventoryScreen in it.
The hands’ slots are not part of the inventory screen sub-system, they are permanent elements of the top GUI and therefore have dedicated operations to keep them updated according to o_InventoryData.

GML flaw

As GML is not fully documented, you have to run into certain edge cases to know that they exists. One recurrent problem though is the “constant” key words’ ambiguity, depending on context they change their value / meaning including “the constant” undefined. (From the GML manual: “the constant undefined”…)
Here are two examples I ran into last week.

  1. with(undefined)

If you happen to get into this situation, GM:S will take the first object in your editor ‘Objects’ hierarchy and use it inside the block. There is no true boolean type in GML, true and false are constants defined to 1 and 0.

What’s the link between boolean and with(undefined)?
with expects an instance id or an object_index, not a boolean. At runtime it evaluates the expression between brackets to get this information, in doing so I suspect it to test especially for undefined and return false rather than throwing an exception.

I doubt with to be defined in a high level assembler but I haven’t verified it nor have I the knowledge to do so, if that’s the case I’m probably absolutely wrong about the cause of this behavior.

Nevertheless, 0 is returned as result of the evaluation and it’s considered being an object_index therefore used to find the first instance in room of this object and use it.
This is an extract from my script updating the GUI OffHand slot before adding is_undefined():

//Is there an object displayed? Is it different from the data?
if(i_Object != l_Data.i_OffHand){
  with(i_Object){ //If you don't prevent undefined value, it'll be evaluated as 0
    instance_destroy(); //Destroy that object
  }
  i_Object = undefined; //Clean the reference to its instance
}

  2. object’s name ambiguity

This one is me whining about a useful/messy feature rather than a real problem.
(And being a bit hypocritical because sometimes it facilitated me the task at hand ;p)

When you call an object by its name you get its index in your editor hierarchy, at core the value of the object’s name never change when evaluating it. But his meaning change depending on context, it’s disturbing when you’re used to traditional object oriented, strongly typed, high level languages.
In C++ it would be like using the Class name (the object’s name) as a pointer to objects instances.

Consider we have an object o_Object with an instance variable i_Variable and we’re gonna use it in different situations:

var l_MyObject = o_Object; //o_Object is an object_index
var l_MyInstance = o_Object.i_Variable; //o_Object is the first instance ID
with(o_Object) //o_Object is an array of instance IDs

Next update

Now I’ll work on something more “concrete”: snap the player’s movement to the isometric grid and propers collisions’ detection.
See you on the next post! :)

Spirit Run / GlobalGameJam 2016 post-mortem

This year I participated to the Global Game Jam 2016 [GGJ] at BellecourÉcole in Lyon, France. This is a school that hosted an official site of the GGJ with 240 jammers, 27 games were made there this last week-end.
As I came on site after team creation time, I walked from one room to another asking who were in need of a game designer / programmer. I’m a bit shy and I felt uneasy at first with this process but this sensation left me when I had finally found a team which welcomed me with open arms as they were lacking of a programmer.

My team at GGJ16

(I’m at the middle, wearing a white t-shirt)
These guys are students of first year and second year at BellecourÉcole, they’re learning graphic design, 2D animation and game design.

Spirit Run

Screen capture of Spirit Run

We’ve created this game named ‘Spirit Run’, it’s a 2D side-scrolling runner. You’re a shaman running from temple to temple, executing rituals at these places, if you don’t run fast enough you’ll lost your soul!

For the moment, the game can only be played on Windows with a XBOX360 gamepad.
Controls:

  • Left Joystick: Move
  • Y: Jump
  • (On temples) Hold both triggers (RT & LT) down: Switch to ritual mode
  • (In ritual mode) Both Joystick: Execute ritual moves

Here’s the page of our game on GGJ site.

Project management and communication

Our team was composed of 6 game designers with different specializations, being the only one able to program I played also a key role in defining what we could achieve in 48 hours. In this context I took the decision to dedicate my efforts to programming and trying to give a project frame for the team and let them express their creativity.

I attached to get everyone participating and being interested in the idea we chose to go with. Ownership feeling is necessary when it comes to dedicate huge load of work on a project in a short time.
I refused to be called ‘Project lead’ or whatever in the same style, as I told them: everyone’s word was equal, I was only there to enable them to reach their goal.

The decisions were taken at the majority agreement. I wrote regularly the needs and advancement state on the whiteboard to keep a clear track of project progression.
We ate every meals together, a simple act that I think has a certain importance to get a team to work well together.

I learnt a lot about problems of communication because they have a more graphical point of view while I’m heavily influenced by software development perspective. This lead to some minor confusion, I tackled these problems by adapting my language and showing things rather than using words.

What went right

  • I took care of my health properly.
    For me it’s an important point. Compared to last jam, every hours spent working were effective.
  • An overall good relationship in the team.
    It was very pleasant to work with this team, there was a joyful mood during the whole 48 hours. Despite many technical hurdles we cooperated with the smile all the way.
  • We shipped a game before the deadline.
    YEAH! This is certainly not the next Call Of Duty but this is our game and we’re proud of it. We aimed low to be able to deliver a game at the end of the GGJ, this was at the top of our priorities list.

What went wrong

  • Working prototype came really late
    This was caused by me being blind to what I’ve got in hands. Saturday midday I had written the code for the core gameplay except rituals at temples that I replaced by a placeholder, I should have made a quick level and got everyone to test it.
    Instead I created some scripted prefabs and gave it to one guy to start working on level design. The ‘real’ prototype was assembled Sunday at 13 o’clock.
  • Unity projects hell
    We started the jam with 2 PC on 6 that either was full of virus or launched blue screen at random. Creating a game with proper tools is too simple. Also Unity installation on these PCs seemed damaged, the whole thing making transferring project from one PC to another an ordeal even with the packages system. Hours of work were lost due to this.
  • Full animators’ work loss
    I take responsibility for this disastrous event. Two teammates were skilled at 2D animation and did a great job on Adobe Flash to animate the character, before starting the work they asked me if Unity would accept Flash animations and later they found a free module in the AssetsStore to convert Flash animation to Unity prefab.
    I should have asked them to test integration in Unity right away because at the end of the jam we were unable to get the prefabs to work on the final version of the game.
  • Difficulty to keep everyone busy and duplication of work
    A team of 6 starts to be a big number of people to manage, especially when 5 of them have the same skill set. As I was the only programmer I was the bottleneck of the production process and some teammates had times when they couldn’t do anything to advance the project.
    Also lots of compatibility errors encountered by transferring project from one PC to another lead us to lost work done and having to duplicate it. It suffice to say we were throwing hours of work by the windows.
  • No explicit tutorial or indications
    A consequence of assembling the prototype so late in the week-end and wasting hours of work on different problems was that we didn’t spend any time on creating at least a little tutorial and not even a GUI to represent the timer running.

P.S.: We definitely should have used BitBucket instead of GoogleDrive.

Future of the game

We’re willing to continue working on this game for sure. We really enjoyed this game jam and are enthusiast at refining our game.
From my point of view we’re not gonna commercialized it but use it as a portfolio element and maybe we’ll put it on itch.io.

P.S.: My favorite game of this GGJ16 (besides ours :p) is Anu & Ki, this is a cute dance game you should really check it out. As well as the source code which is a great educational material.

Harvest Nothing 64 / MiniLD64 post-mortem

Hi everybody!

Last week-end I’ve participated to the MiniLudumDare which had for theme the Nintendo64. This was my first game jam ever, I did it alone and this post is about what I learned during those 48 hours.

To put the initial context:

  • I’m a game designer and programmer
  • I’ve made no commercialized games
  • Usually I work with Unity in C#

I wanted to learn to use GameMaker:Studio [GM:S] (never used it before) and decided to replicate Harvest Moon 64 [HM64]. This choice was motivated by two facts: the whole gameplay is made for 2D (legacy of the first episode) and I’m not able to create 3D models or even draw sprites.

I’m not gonna make a hour-by-hour report but rather discuss some special decisions I took and things I learned on GM:S.

Lessons learned

Basics

Some obvious things you had to fail to learn them on your first jam:

  • Don’t eat crap
  • Sleep full nights
  • Don’t abuse caffeine
  • Don’t get stuck for hours on a single problem
  • Take breaks

Doing a game jam alone is a bit sad but permit you to test things that you would fear to try in team. However every times you can participate with a team: do it! I won’t do another jam alone, that one was a missed opportunity to met new people.

Software architecture? in GameMaker? during a jam?…

I spent few hours analyzing the systems in HM64 and designing my software architecture trying to respect the law of Demeter in an environment with no privacy principle and no class concept.
The irony of applying this law to game development is that you can’t avoid the game world object to know part of other systems without adding complexity to the global architecture. And still I think it was useful and necessary, it saved me time by avoiding a lot of bugs and the only one that popped up was isolated in a single system.

I created one permanent invisible object for each system in the game and wrote code in script files whenever it was possible. I kept to write the full path to access variables even if I could had accessed them with something shorter, such as:

o_Game.i_GoldManager.i_GoldTotal
  rather than
o_Gold.i_GoldTotal

Just being certain of what I was calling and spot immediately a strange call that would not respect the architecture.

In brief, the Master object is the first to be instantiated at the “start” of the program, sets constants and context then instantiate core components. When the Game object is instantiated it initialize the calendar and the clock then instantiate all other systems.

Objects hierarchy

Event system overlay

A problem I ran into was getting the clock to notify other systems at specified hours: at the end of day the plants must check their growth, the user interface updates displayed information, … but GM:S has no observer or event-queue patterns built-in.

In fact there’s a set of 16 events called ‘User defined’ and a command event_user(0) to trigger them. The thing that the GML documentation does not say is that these events can only be called by the object that holds them. That means you can’t trigger a custom event you defined on an object by calling it from another one unless you do that:

with(objecttocall){
  event_user(0);
}

What happens if you have radically different types of object to call for the same event?

with(object1tocall){
  event_user(0);
}
with(object2tocall){
  event_user(0);
}
...

At the moment I came up to this part of the program, I already knew I wasn’t even close to finish the core game features before deadline. So I decided to take my time to implement a customised event system on top of the original one.

I had these objectives:
 1. Providers makes only a single-line call to notify event
 2. Providers shall not know who their clients are or even if they have clients at all
 3. Events are named and not numbered (‘g_Events.DayEnd‘ vs ‘0’)

To explain the event system I created we’re gonna take the plants example, plants in HM64 check if they grow at the end of day and rot when the season ends.
There is two events:

enum g_Events{
  DayEnd,
  SeasonEnd
}

The provider of these events is the timeline tl_Clock held by the object o_Game:

Events by tl_Clock side

On the client side the variable i_EventReceived is defined when s_Notify is called on an event the client has s_SubscribeTo:

Events by o_Plants side

The man-in-the-middle is o_EventUserDelegate, it holds a list of subscribers per event and the scripts s_Notify and s_SubscribeTo work on these lists. The lists are lazy initialized to avoid wasting memory on an event that may not happen during the play session.

o_EventUserDelegate

The bottleneck of this design is that a certain amount of boiler-plate code has to be written in the two scripts. Here’s the parts for the DayEnd and SeasonEnd events:

///s_SubscribeTo(Event, SubscriberId)
var l_EUD = o_Master.i_EventUserDelegate;
switch(argument0){
  case g_Events.DayEnd:
    if(!ds_exists(l_EUD.i_DayEndSubs, ds_type_list)){
      l_EUD.i_DayEndSubs = ds_list_create();
    }
    ds_list_add(l_EUD.i_DayEndSubs, argument1);
    break;
  case g_Events.SeasonEnd:
    if(!ds_exists(l_EUD.i_SeasonEndSubs, ds_type_list)){
      l_EUD.i_SeasonEndSubs = ds_list_create();
    }
    ds_list_add(l_EUD.i_SeasonEndSubs, argument1);
    break;
  default: break;
}

///s_Notify(Event)
var l_EUD = o_Master.i_EventUserDelegate;
switch(argument0){
  case g_Events.DayEnd:
    if(!ds_exists(l_EUD.i_DayEndSubs, ds_type_list)){
      var l_Count = ds_list_size(l_EUD.i_DayEndSubs);
      var l_Index = 0;
      repeat(l_Count){
        with(l_EUD.i_DayEndSubs[| l_Index++]){
          i_EventReceived = g_Events.DayEnd;
          event_user(0);
        }
      }
    }
    break;
  case g_Events.SeasonEnd:
    if(!ds_exists(l_EUD.i_SeasonEndSubs, ds_type_list)){
      var l_Count = ds_list_size(l_EUD.i_SeasonEndSubs);
      var l_Index = 0;
      repeat(l_Count){
        with(l_EUD.i_SeasonEndSubs[| l_Index++]){
          i_EventReceived = g_Events.SeasonEnd;
          event_user(0);
        }
      }
    }
    break;
  default: break;
}

In its actual state the event system works fine and is synchronous. However it’s easily expandable with a ds_queue to make it asynchronous to avoid spikes of performance consumption when multiple events happens simultaneously.

Miscellaneous observations on GML

Some special things I discovered on GML:

  • There’s no foreach structure, although it’s generally slow, sometimes you really need it. The substitution I used in s_Notify was repeat(){ with(){ } }
  • GML is NOT fully documented.
  • And the obvious double-edged characteristic: it is easy to use and easy to mess everything with it.

Conclusion

Even if I highlighted several “defaults” of GML, I enjoyed learning and using GM:S and will definitely come back to it in the future.
Concerning the game I’ll keep replicating HM64 as an exercise and discuss some precise points of development here but I won’t share updated version of the project files: don’t mess with Nintendo’s lawyers, that’s not a good idea.

For the record here’s the GM:S project in the state it was at the end of the MiniLD64:
Harvest Nothing 64

By the way I made a color configuration file to get GM:S code editor be closer to VisualStudio2015 C# colors:
Don’t forget to change the font to Consolas 10pt