miércoles, 17 de diciembre de 2014

Saturday at Granada Gaming

Hi all!

As I promised, here is my story and impressions at Granada Gaming, the first edition of this series of events where videogames professionals and small indie studios come together to celebrate their passion for games. 

I arrived by 10:30 a.m (doors opened half an hour earlier) and after lining up for half an hour, I got into the Congress Palace of Granada, where the event was held. 


Figure 1. A long line of people waiting to get into the Congress Palace

As soon as you passed through the doorstep, you could see gift shops populated with game-related stuff, stands where companies showed their last products, and long tables filled with laptops where the audience could play games developed by small studios. 

I headed directly (well, after a quick snack at the cafeteria) to the second talk of the day: Once Upon a Time: The Development of Videogames, where Mario García, from Mercury Steam (responsible for Castlevania Lord of Shadows, among others), discussed the process of creating games. In particular, the speaker is involved in the creation of game mechanics and gameplay experience in general. After his talk, I asked him whether they, at Mercury Steam, used some scripting language for this task. He answered that the most sensitive part of the code (the code that must run fast) is hard-coded in the game itself, whereas the rest is outsourced to Lua. The answer did not surprise given the increasing trend of using this scripting language in the industry.


Figure 2. A bunch of people around DriveClub.

Then, I took some time off the conference room to have a walk around. I could play several games, including Street Fighter x Tekken, which was actually pretty fun. There was also a retro area where you could enjoy jewels of old times, such as Alex Kidd. I also took the opportunity to hand out some Chubby Buddy flyers :).

But in my deepest heart, what I really wanted was trying the so-much wanted Oculus glasses. So I lined up again, and after other thirty minutes, the long-awaited moment arrived. A member of the staff was helping me wearing the glasses, and I could feel how I was transported into a miniaturized  roller-coaster. Moving your head around the room provided an impressive immersive feeling, since you could feel as if you were really there: the movement and turns of the head were really accurate and there were no lags at all. 


Figure 3. The line to try Oculus.

But the weirdest thing happened when the coach started to move. At that point, I felt something strange, neither too bad nor too good, but strange. I could feel what was actually happening: my brain was interpreting that I was moving, but my body was still, sitting and even aware of the noise that the headphones tried to vanish. However, a tickling sensation emerged from my stomach as the coach was moving faster and faster, and especially during the first descent. I even grabbed my chair because for a moment I thought that I could fall off. However, this sensation only lasted for some small fraction of time, and I really enjoyed the trip. 

I think it is not easy to envision the acceptance of this device in the near future by the games community. I'd really like to try them in a more interactive scenario before judging. But the immersive experience is out of discussion. The question is: would many people be able to wear the glasses in a horror game like Silent Hill P.T.? Mmm... I'm not sure I could play for more than 5 minutes... :) See below (after the end of this post) for opinions about the Oculus experience made by two persons that came with me.


Video: me looking through the Oculus... And yes, I really grabbed the chair.

The next talk I attended was about games marketing, which is a hot topic given the high saturation of the market. Basically, one of the main takeaways was that marketing should start long before the release of the game, and that Youtubers are playing an ever-increasing role in promoting the success of many independent games. 

In the next talk, the people behind the development of Randals Monday (one of the big lures of the event) described their experience while designing a graphic adventure. The designers wanted, from the very first moment, to pay tribute to old graphic adventures that are considered masterpieces today, such as Day of the Tentacle or Fate of Atlantis. The game, which is implemented around Unity, faced several technical challenges given that the engine is mainly designed for 3d games. However,  after seeing the game by myself, I can attest that developers made a great job at faking 2d. I asked the speaker personally for advices on designing the puzzles, and he answered that lots of paper-made drafts are required to make sure that the player cannot miss an important object for continuing the game, likely the biggest challenge in this type of games.


Figure 4. The conference room during the last talk I attended.

The last talk I could turn up was about marketing again. The speaker discussed the importance of making your game different from others, and of selling this difference. I asked about the impact of prices in the App Store in the selling opportunities. In particular, I wanted to know the speaker's opinion on my personal observation that a lower price does not guarantee more sales, or more benefits, since once the potential buyer is willing to pay, he or she would not mind to pay more. The speaker agreed with this observation and concluded that prices around 5 € are more than reasonable for well-designed mobile games.

And that's all. The festival continued on Sunday, but I could not be there. However, I'm delighted with the increasing number of games conferences initiatives in Spain (see more about Gamepolis in Malaga). Let's hope this is just the starting point for a 2015 full with videogames events.

See you!
FM

Oliver's experience with Oculus

While I was lining up, I was facing the traditional dilemma of those who are going to test something for the first time: enjoy or analyze? I chose the analysis, trusting that if the experience was worth it, I wouldn't forsake the emotions. And so it was.

When it was my turn, another question arose: should I take my glasses off? Fortunately, the staff member in charge told me that I could keep them on. The first thing that came to my attention was the possibility to look all around me; the immersive feeling was awesome, above all considering that graphics were a bit poor. Next thing I noticed was that my body really reacted as if I was in a real roller-coaster, especially during the descents. However, I got the knack in the end: in order to get the tickling sensation during descents, you need to look downwards. Otherwise (if you look up), you won't feel anything. In my opinion, a complete immersion experience requires further elements, such as a moving chair, but of course that would make the product more expensive. Another drawback of the demo was the poor quality headphones. As a musician and sound technician, I really advocate the use of good quality, closed design headphones to provide a real 3d experience. To sum up, although Oculus glasses are an innovative and interesting product, the provided experience is still limited. We'll have to wait until more polished designs and cheaper components, but I encourage companies and people to bet on this kind of technology, which will surely shape the future of interactive media.

Just as a side note, even when the obvious application of Oculus are videogames, I think it would be worthy exploring its application to other scenarios, such as immersive cinema, where you can walk around a scene as if you were a ghost.

Manuela's experience with Oculus

I have little to add to Oliver's comprehensive review, with which I mostly agree. First, I think that graphics were poor, which is a pity because the immersive feeling (which was really high) could have been absolutely staggering with a better design. Second, moving your head around the room gave the real impression of being in that room. Finally, the feeling of the brain being tricked was fantastic at first, although later you get used to the feeling. In general, I think it was a good experience, and I'm looking forward to seeing what developers achieve with this device.

martes, 9 de diciembre de 2014

To Granada Gaming Festival!

Hi all!

This weekend will take place the Granada Gaming Festival, and I've just bought the tickets to be there. Among other activities and interesting lectures, the organizers promise to let the audience test Oculus Rift. Let's see if I'm luckier than in the last edition of Gamepolis. As I did in the latter festival, I'll try to cover my impressions, so stay tuned.

See you!
FM

viernes, 5 de diciembre de 2014

Cocos2d-x v3.x and Xcode 6.x with ARM 64 Architecture

Hi!

When I upgraded to Xcode 6, I noticed that there were lots of linking problems in Cocos2d-x projects that used to work fine with previous versions of Xcode. The problems are related to the ARM 64 architecture. After searching a while, I found hints to the solution, although I was missing a more step-by-step solution. So here it is how I solved it.

1) Add linker flags for ARM 64 architecture. In your target, select Build Settings > Linking > Other Linker Flags and set the following flags for Debug and Release for arm64 architecture:

-ljpeg_arm64
-lcurl_arm64
-lpng_arm64
-ltiff_arm64
-lwebp_arm64
-lwebsockets_arm64
-lfreetype_arm64

EDIT: this is no longer required from Cocos2d-x v3.4.



2) Add library paths. In your target, select Build Settings > Search Paths > Library Search Paths, and write the following directory for Debug and Release.

YourProjectPath/cocos2d/external 

And don't forget to set "recursive".


Hope it's useful. See you!
FM

lunes, 24 de noviembre de 2014

The Importance of Cache

Hi!

I recently posted a blog entry on data orientation, where one of the consequences of following this design mindset was a more optimal cache utilization.

Intrigued by the claims about how the memory is becoming the main bottleneck in current systems, I wanted to test it by myself, so I came up with a very simple C++ program.

#include <iostream>
#include <chrono>
const unsigned long int SIZE= 64*1024;

int main()
{
char array[SIZE];
char array2[SIZE];

auto start = std::chrono::system_clock::now();
for(int i = 0; i < 1000; ++i)
{
int aux = array[i];
}
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now() - start);
std::cout << "Duration: " << duration.count() << std::endl;

auto start2 = std::chrono::system_clock::now();
for(int i = 0; i < 1000; ++i)
{
int aux = array2[i*64];
}
auto duration2 = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now() - start2);
std::cout << "Duration 2: " << duration2.count() << std::endl;

double res = (double)(duration2.count()) / (double)(duration.count());
std::cout << "First is " << res  << " faster" << std::endl;
}

I simply define and read two arrays of 64 KBs each, storing their values in a local variable. The difference is that in the first chunk of code I access memory sequentially, taking advantage of the cache, whereas in the second chunk I access in strides of 64 bytes, which in turn causes cache misses and more frequent access to main memory. 

The results are astonishing: the first chunk (the cache-friendly code) executes an average of 7.3 times faster. So yes! Memory is an important bottleneck in today's systems. 

See you!
FM

jueves, 13 de noviembre de 2014

Extern "C": Communicating with C interface through C++

Hi all!

Today, I bring you a short explanation, which is not directly tied to games programming, but just programming in general. However, I think it's something useful as you may find what I'll explain here in libraries that you may use in your games. 

The explanation is about the keyword extern for specifying C linkage. Note that the keyword "extern" has another meaning when it precedes variables or function names, but we're dealing here with a different use, in particular, with the following one:

extern "C"
{
   //Headers (.h) or functions declarations
}

With the above statement, we're telling the C++ compiler the following: "Listen guy, I have several functions (or headers, which in turn comprise several functions) that were compiled with a C compiler, but I want to be able to call these functions from my C++ code". 

And why would you need this? What's the difference that makes C and C++ unable to talk to each other natively? The problem is name mangling due to function overloading. C++ allows overloading functions, so the C++ compiler needs to use both the function name and arguments information in order to provide a unique identifier for the function. Since C does not allow overloading, it does not need to use name mangling. If you used name mangling, the C++ linker would look for function names that are mangled, but it wouldn't find them because the C compiler didn't mangle the names. So basically, when you use extern "C", you're deactivating the default C++ name mangling for the functions declared inside the block. 

A short example comes now. Suppose you have the following C header/implementation:

//mymath.h
#ifndef MYMATH_H
#define MYMATH_H

int mySum(int x, int y);

#endif

//mymath.c
#include "mymath.h"
int mySum(int x, int y)
{
   return (x + y);
}

Now, we compile this with a C compiler (suppose gcc):

gcc -c mymath.c

The above line generates an object file called mymath.o.

Now, let's make a simple C++ program that uses the above function like this:

//maincpp.cpp
#include <iostream>
#include "myMath.h"

int main()
{
  std::cout << "Sum in C yields: " << mySum(4, 2) << std::endl;
  return 0;
}

And now, let's compile with a C++ compiler:

g++ -c maincpp.cpp

This generates an object file called maincpp.o.

Now, let's try to build the executable:

g++ -o main maincpp.o mymath.o

The output of this line is:

Undefined symbols for architecture x86_64:
    "mySum(int, int)", referenced from:
         _main in maincpp.o
ld: symbol(s) not found for architecture x86_64

So basically, the linker is telling us that it is unable to find the function with name mySum(int, int). The way to solve it is by informing the C++ compiler that mySum is actually a C function, so that it generates the appropriate name for it that the linker can find. 

//maincpp.cpp
#include <iostream>
extern "C"
{
   #include "mymath.h"
}

int main()
{
  std::cout << "Sum in C yields: " << mySum(4, 2) << std::endl;
  return 0;
}

Now, after executing:

g++ -o main maincpp.o mymath.o

we get the expected result:

Sum in C yields: 6

Finally, it's very common (and convenient) to find the extern "C" statement wrapping header files as shown next:

#ifdef __cplusplus
extern "C" 
{
#endif

//Functions declarations

#ifdef __cplusplus
}
#endif

The symbol __cplusplus is defined only if the compiler is a C++ compiler. Therefore, suppose that we do the following in mymath.h:

//mymath.h
#ifndef MYMATH_H
#define MYMATH_H

#ifdef __cplusplus
extern "C" 
{
#endif

int mySum(int x, int y);

#ifdef __cplusplus
}
#endif

#endif

We can still compile mymath.c because __cpluplus is 0 and "extern" will not make it to the object file (C does not understand extern "C"). And what's more important, this allows any C++ client code to be oblivious about whether it should specify or not C linkage. So now, maincpp.cpp would be like this:

//maincpp.cpp
#include <iostream>
#include "mymath.h"

int main()
{
  std::cout << "Sum in C yields: " << mySum(4, 2) << std::endl;
  return 0;
}

And that's all! Hope you understand everything and find it useful!

See you!




martes, 14 de octubre de 2014

Data Orientation or The Circle Of Life

There was a time where data structures were important and every programmer would think in terms of procedures that simply transformed these data structures into other data structures. Many others would put their focus on declarative languages, and concretely, on functional programming (With ( Beautiful (Languages (like Lisp))). Yet the revolution in the world of programming paradigms was yet to come: Object Orientation arrived to tell a universal truth to all unwary and naive designer and programmer: "in our daily lives, we think in terms of objects, therefore objects should be the building blocks for your systems". And voilà! Smalltalk, C++, Java, and lots of other languages would stick to this paradigm, advocating code reuse and mental models of the system better aligned with the problem domain thanks to several techniques such as abstraction, inheritance, polymorphism and late binding. Object Orientation seemed to be the One that would guide programmers towards successful, robust, maintainable and reusable systems, especially with new languages that hid low-level dirty details like memory management.

Schools and universities then started to teach this new paradigm, first as a complement to previous programming practices, and soon, their curriculums would be centered around them. Because, why on Earth to teach C when most of the companies today called for Java programmers? Why to teach a paradigm that is obsolete, only present at legacy systems that are bound to being wrapped around web services or Java interfaces? 

Object orientation really seemed so perfect that when a teacher at my University asked us to give him one disadvantage of this paradigm, neither of us would be able to find a clear answer. Yes, everybody was thinking that Object Orientation was the best, and that it was unbeatable. 

Nonetheless recently I noticed something. In the same way as Sauron was secretly spawning enemies and planning its revival in the Middle Earth, some strange people were colluding in the deepest corners of the Internet to bring back something ""new"", something that cannot even be called a paradigm: data orientation. But what's more important: not only are these people convinced that data orientation is a plus, but they (most of them at least) are also convinced that object orientation is not that good, and that even could lead to very poor results.

Ok, let's put things in their context. Most of the people I read about who advocate data orientation (DO, from now on, which I will  briefly explain in short) work in the games industry or are indie game developers. This is important because one of the benefits of DO is a boost of performance due to more efficient memory usage.

As I mentioned before, DO does not seem to be a paradigm on its own, but rather a set of guidelines and ways of thinking, without any programming support or special techniques enforced by compilers or programming languages. The best way to understand (at least for me) what DO means, is by citing some of its mantras:

  1. The platform is the hardware, not the software. Know your platform, because abstraction is not that good.  
  2. The code is not important. Data is important. Code only serves the purpose of transforming data in trivial ways. Design your code around your data, not the other way around.
  3. Different problems lead to different ways to organize data. 
  4. When there is one, there are many. Don't think that a function will have to perform an action on only one object (typical object-oriented mindset), but think that this function will be applied to a bunch of objects. 

The main reason of the uprising of DO is the ever-growing gap between the processor and the memory. Processors are steadily faster, especially when considering multi-core and multi-processor environments. On the other hand, memory is not progressing as fast, so very often the processor is idle hundreds of cycles while waiting for data coming from memory. DO aims at exploiting the cache (a fast memory between the processor and main memory), and at making code easier to be divided among threads for exploiting cores and processors, something that is hardly possible with object orientation.

When you read some of the techniques that underlie DO, you may find that many of these techniques are well-known programming tricks that good programmers have known for years... but now they are being spread out and someway systematized for the public knowledge. For a quite comprehensive summary of these techniques, take a look here.

In this fantastic video, Mike Acton, engine director at Insomniac Games, explains data orientation with practical examples and how it can be implemented in a language like C++.


Here you can find lots of useful resources about DO. And here, a very interesting blog about the development of a game engine in which some DO considerations have been taken.

The point of this post is to reflect about a reality: the domain of Computer Science is in constant evolution, and hardware considerations constrain the way the software evolves. This evolution may even come in terms of a circle, coming back to the origins. But it's even more serious. We've been taught for years that abstraction is good, and that we don't need to worry about the platform on which we are developing. In performance-sensitive systems in general, and in game engines and games in particular, this is no longer true. Actually, developers are demanding to be able to work "closer to the metal" in the graphics domain as well.

I must add a personal comment though for all of you who are newcomers to the world of games programming. As I mentioned in an older post, abstraction is good, and should be you ally when you're starting. So don't worry about the nitty-gritty intricacies of low-level details. Just design your game in as high-level way as you can.

However, beware, you advanced programmers who want to delve into the world of game engine programming!! Embrace data orientation or perish!!

See you!
FM

jueves, 9 de octubre de 2014

Is this blog dead?

No!
See you!


No, really, it's been a while since the last post, but that's because I was quite busy and at the same time I needed to take a break. But I'm back stronger than ever with new ideas and with more technical insight into videogames and engines programming. 

For example, in the next post, I'd like to discuss about a phenomenon that I noticed is taking place lately in the world of games/engines programming: the reluctance of Object Orientation in favour of Data Orientation, something that a priori seems partly against what we've been usually told in Computer Science classes for the last years. I'll explain what this means and why it's happening very soon.

See you! (now yes)

lunes, 28 de julio de 2014

Gamepolis 2014: An Overview

Hi all!

As promised, I'm eager to share with you my experience during Gamepolis 2014, the second edition of this videogames festival held in Malaga from last Friday to Sunday. 

As last year, I arrived on Friday afternoon due to work, so I missed some of the morning talks. As I set foot on the entrance, I saw some Disney Princesses around (ok, not so videogames oriented, but quite of a surprise anyway).


Disney princesses; probably colluding against their princes... or no 

Then I walked around the stands in order to cover myself with the spirit of the festival. Graphics cards brands were presenting their last products, people gathered around games, like FIFA 2014 and Mario Kart 8, and shops were showcasing some very interesting and geeky products. 


People walking around the place. The surface of the event was bigger and clearer than in the previous edition. This allowed for a a clearer space. 


Gigabyte and Nvidia presenting their last products.



People gathered to play FIFA 2014 and Mario Kart 8. 
Tournaments for these and other games were also organized.


Geeky T-Shirts and videogames products were sold in the shops.

The first afternoon session was about legal issues to take into account before and after developing a game, including raising funds and protecting the product. I couldn't attend this one though because I arrived later (thanks Oliver for your notes).

The first session I actually attended was about the importance of music in videogames, where the speaker pointed out that the audio must adapt itself to the player, and that it should know its place in the game as a whole, not wanting to show off over the rest of the game. 



 While the session about music in videogames started, Pong was exhibited

After this talk, I decided I would walk around a bit more, and that's when I found a magical corner where all wishes come true: the retro area. There, old tiles would bring joy to all types of players: from the oldest ones to the youngest kids. 




The retro area was fantastic, as in the previous edition. 
Do you recognize the games in this pictures?

Then, I went back to the auditorium to enjoy the talk "Indie: origins and revolution", where the speaker provided an overview of some of the most relevant games in the indie scenario. The author also pointed out the importance of addressing game reviews rigorously and with actual insight, as it is done in his high quality magazine Deus Ex Machina.  



As examples of relevant indie games we find World of Goo and The Binding of Isaac.

Saturday morning started with tons of people lining up to buy their tickets. Fortunately, I had already bought a 3-days pass by Internet. 


Long queue on Saturday morning. 

I also took advantage of this great audience to advertise Chubby Buddy. For this purpose, Manuela designed an eye-catching flyer and we handed them out.


Yeahh! Our dear chubby friend was also in the conference. Some people (including bloggers and press staff) were actually interested and asked us about it

People tried to get pictures with their favorite game characters, including Altair or the scary Slenderman. 





As in the previous edition, people have made a great effort to look like their games counterparts. 
Do you recognize them all?

The first session in the morning presented a game that is being developed by Brainside, a Spanish game company based in Sevilla. The game is Embrion, which was already in last year edition. Last year, the developers presented a sensor that could be attached to the player in order to measure heartbeat and change the gameplay accordingly. This idea by its own is fantastic, but now they also revealed that they're using Oculus Rift to gain a bigger immersion. I didn't have the chance to try it, but I presume that the experience must be really frightening (actually, as a curiosity, the team mentioned that one person who was trying the game didn't have the courage to go beyond the first room of the game). 



By the stand of Brainside, people would line up to try Oculus Rift in Embrion

The next talk was about the presentation of a book and a new publisher: "Ediciones Arcade", which promises to bring from abroad and translate the best books on videogames. As as first notice, they announced that they would publish "La Legende Final Fantasy VII", a special edition for collector book that was not available in Spanish. 


Presention of Embrion

Next session I attended was "From videogames to gamification", where the speakers discussed the foundations of gamification and how it can boost productivity in boring tasks and at the workplace. They showed how big companies such as Coca-cola have understood the importance of gamification  as as marketing strategy.


Speakers during the gamification talk

Next session was: "Hidden treasures of MSX". The speaker, Gaby López, who was also in the last edition, revealed lost of curious games for MSX and MSX2. A funny part of this talk covered some erotic games that, contrary to what one may think, had a great quality.







MSX had lots of curious titles, but the erotic ones deserve a special mention... 

The first talk of the last day (Sunday) was a presentation of Bitton, a game-making company. In addition to presenting their last products, the speaker also reflected on marketing issues important to gain some audience in a competitive market such as the mobile one. 




Bitton presentation. Note the second picture: we employ around 3000 millions of hours per week playing online games... Awesome!

The name of the next talk was: "Metal Gear Solid: When Hideo Kojima met the movie industry". The speaker showed some of the films that inspired Kojima while creating this super mega saga. The speaker also presented his book: "Metal Gear Solid: The Legacy of Big Boss", which of course I bought :)


Me in the possession of this amazing book. Preparing myself for MGS5...

Next talk was about artificial intelligence in videogames, and the speakers, researches at University of Malaga, provided an overview on procedural contents generation and on the need for "artificial stupidity". This last term refers to human-like (error-prone) behaviour for bots, which is necessary in order to provide a more engaging and realistic experience.


Researches from University of Malaga talking about artificial intelligence

The final presentation was actually very special, and probably the most original presentation I've ever seen, because the flow of the presentation was driven by a game itself. The speaker, Locomalito, was playing a side- and top-down perspective game he had developed (very much like the first 8-bit Zelda adventures), and the issues on game development that he was discussing were intertwined with events in the game. For example, typical stumbling blocks (like lack of skills at the beginning) were represented like final bosses. 


A game-based presentation. Yes... I'll have to do this at some point :)

As a conclusion, my experience in Gamepolis has been rewarding: not only the atmosphere was great, but I also met people with the same interests. Last year, I suggested some improvements that can still be implemented for next year, so I'll copy-paste them: 

"There should be some more technical workshops or meetings where developers and artists could interact in order to open the possibilities of forming potential development teams. [...]. Please, free WiFi! I would've loved to comment the talks on this blog with my laptop while being there, but I could only do it by Twitter using my data plan".

I would like to specially suggest the organization committee to make an effort and try to bring some important international celebrity in the area of indie game development. I think designers and developers would love to be able to talk to Jonathan Blow, Derek Yu, Edmund McMillen and the like.

That's all, see you soon!
FM

miércoles, 16 de julio de 2014

Gamepolis 2014 is coming!

Hi all!

Last year I published several posts about Gamepolis, a games festival held in Malaga (Spain). It's great to know that this same festival is coming very soon (one year goes by so fast...). Concretely, the event will take place from July 25th to 27th; and yes, I plan to attend most of the conferences and activities they are organizing and I'll try to cover them in this blog again.

Stay tuned!

miércoles, 9 de julio de 2014

Chubby Buddy: Advanced Mechanics

Hi all!

In a previous post, I explained the basic mechanics of Chubby Buddy. It is time to present the last three main mechanics of the game, which can be enjoyed in its premium version.

Introducing the pastry chef

Figure 1 shows the pastry chef, which is subject to the same movement rules as the rest of cakes and as the grandma. The difference is that when our chubby buddy is right next to the chef (i.e. when the kid is on the right of, left of, on top of, or under the chef), you lose! (Don't worry, there are no lives, so you can happily restart the level). 


Figure 1. Nooo! A pastry chef is about to be moved next to the kid! Abort operation!

Double-leap cake

Figure 2 shows a double-leap cake, which is represented as a green cake with lots of tiny sweet shavings. As its name implies, these cakes allow our chubby friend (and any other element of the game) to reach one row higher than regular cakes. Their rules of movements are exactly the same as the rest of elements. 



Figure 2. Using the double-leap cake to reach the badly wanted fruit

Memory cakes (a.k.a. the copy-paste)

The last mechanic is a bit more complex, and it will make you suffer (in the good sense) and will make you think every movement through! 

Everything starts as a regular level, but you'll notice that there is a new button on the top center of the screen, right next to the level indicator, as illustrated in Figure 3. 



Figure 3. Memory cakes button

Tapping this button will take a picture of the screen, and the current layout of cakes will be "memorized". Just after tapping the button, you'll also see that the number of movements has decreased one unit and the button itself has changed, indicating that there is a "memory" stored. This is depicted in Figure 4. 



Figure 4. Button activated and ready to bring back the memory of the level

Now you can move as many cakes as you want, changing completely the layout of cakes in the level, as shown in Figure 5.



Figure 5. Before tapping the button again, we can change the cakes layout...

When you want to recover your memory, you just have to tap the button again, and the cakes of your memory will come back in black and white (because they are old... metaphor-wise...). This is illustrated in Figure 6.



Figure 6. ... and tapping the button will bring back the old cakes to their original positions, merging them with the current cakes.

Now, you can use these memory cakes to move to places that you wouldn't be able to reach otherwise. Cool! But be wary of the fact that you cannot move these cakes as they belong to your memories... 

And that's all (for now). In the premium version, you'll find 60 exciting and challenging levels... Will you be able to complete them all? 

See you!


jueves, 15 de mayo de 2014

iOS Localization of Strings in C++

Hi all!

I've been playing around with localization lately and I want to share what I learned.

First of all, I've tried to be very specific in the title. This post is about externalizing strings to external files instead of hard-coding them. This means that I won't deal here with images and other types of files localization. Neither will I discuss here internationalization, which is a broader topic.

Picture from Freemake.com (http://www.freemake.com/blog/interview-with-founder-of-crowdin-net/)

Let's suppose that we're creating a super fantastic game and we want, at the beginning, to show a welcome message to the players: "Welcome!"

In a non-localized app, you'd do something as simple as the following (in C++):

std::cout << "Welcome!; (Note: we'd actually embed this string in a label or other high-level structure that presents the information on the device screen rather than on the IDE console).

Our goal is that the message is shown in the language that players have configured in their devices. How do we achieve this? The overall idea is the following: we create a special kind of file (with .strings extension) and we localize it, meaning that Xcode will take care of creating different directories for each language. Then, in our code, instead of hard-coding strings like in the previous example, we make references to these strings in the .strings file. Finally, when the app is launched in the device, the app will be able to pick the correct language depending on the device settings.

The process can be divided in two steps, the first one focused on configuration and the second one on programming.

1. Configuring the environment

In Xcode (note that I'm using Xcode 5.1), choose: 

1) File -> New -> File...
2) In the iOS section, choose Resource and Strings File
3) Name the new file as Localizable.strings (this is a default name; you can change it, but then each time you want to access the file, you have to provide the name).
4) Save the file in some of your app directories.
5) Select the file and in File Inspector, click in Localize. Choose the languages that you want to support. You can add new languages at any time.
6) Even if you haven't seen it, Xcode has created as many folders as the number of languages. These folders follow the same name convention: en.lproj (for English localized strings), es.lproj (for Spanish localized strings), etc. Each language has a unique code. You can check all the codes here.
7) I advise you to drag these folders to Xcode, uncheck the option "Copy items into destination group's folder (if needed)" and to check "Create folder references for any added folders". This way, your file system is synchronized with what you see in Xcode and any changes are reflected in one another.

Now, you can fill out these files according to the following format:
"key" = "value"; 

Following the welcome example, in the Localizable.strings under the en.lproj folder, we would write:
"WelcomeMessage" = "Welcome!";

Whereas in the Localizable.strings under the es.lproj folder, we would write:
"WelcomeMessage" = "¡Bienvenido!";

And so on with the rest of languages that we want to support. Don't forget the ";" at the end.

2. Programming

Now we're ready to make the appropriate changes to the code. In Objective-C, this is pretty straightforward as the Cocoa framework offers localization methods. In particular, we're interested in the following one:

NSLocalizedString("key", nil)

This method returns a NSString* with the value associated to the NSString passed as first argument. Therefore, if we called the method as NSLocalizedString("WelcomeMessage", nil), it would return "Welcome!" in English-configured devices, and "¡Bienvenido!" in Spanish ones. 

The problem is that given that we're assuming that we're using C++, we cannot directly access this method. For example, in my case I'm working with Cocos2d-x, which is a C++ framework. What can we do to access this Cocoa functionality from C++? 

Well, given that Objective-C and C++ have common roots, it's not difficult to pave a bridge between them. Therefore, I created a C++ wrapper over the aforementioned Objective-C method. The code of the header and implementation files are listed next:

LocalizationManager.h

#ifndef __Limball__LocalizationManager__
#define __Limball__LocalizationManager__

#include <iostream>
#include <string>
class LocalizationManager
{
public:
    static LocalizationManager* getInstance();
    std::string getLocalizedString(const std::string& key);
    
private:
    LocalizationManager();
    ~LocalizationManager();
    static LocalizationManager* lm;
    
};

#endif 

LocalizationManager.mm

#include "LocalizationManager.h"

LocalizationManager* LocalizationManager::lm = nullptr;
LocalizationManager* LocalizationManager::getInstance()
{
   if (!lm)
   {
       lm = new LocalizationManager();
   }
    return lm;
}

LocalizationManager::LocalizationManager()
{
}
LocalizationManager ::~LocalizationManager()
{
    if (lm)
    {
        delete lm;
    }
}

std::string LocalizationManager::getLocalizedString(const std::string& key)
{
    
    NSString *str = [NSString stringWithUTF8String: key.c_str()];
    std::string s([NSLocalizedString(str, nil) UTF8String]);
    return s;
    
}

What I do in the getLocalizedString method is basically transforming from NSString to std::string (using an intermediate C-style string), and viceversa. Note that the implementation file has no .cpp extension, but .mm extension. This is important as this file must be able to understand both C++ and Objective-C. You must change the type of this file to Objective-C++ Source in the File Inspector.

Now, in any class that needs to print a message, I only need to include the LocalizationManager.h, and I can use it as follows:

std::cout << LocalizationManager::getInstance() -> getLocalizedString("WelcomeMessage");

And that's all! Hope you find it useful.
FM