Monday, 11 November 2013

Clean and Green Hackathon 2013 Afterthoughts

First Hackathon!

For the last 3 days, I participated in the Clean and Green Hackathon 2013. It's an event where people can form teams with anyone of any skill, be it technical or non-technical, to create apps for Clean and Green Singapore.

I was originally invited by my friend Mingding to join this hackathon about a week before, and my first thoughts was that it was really surprising that our government had this initiative. Our Singapore government had always been very relatively closed to the idea of engaging with the public, or perhaps had no effective means of doing so due to archaic bureaucracy, and were often very old-school in their mindsets and methods. Therefore, I was elated to hear that they were finally catching onto the future of collaborative openness, embracing the public whether for better or worse, and welcoming the ideas of our younger generation.

Difficulty of crossing Games with Green

Personally for myself, I had always wanted to make a difference in the greenness of Singapore, even if it was a small difference. But I could never find out what would be the best way to leverage on my skill set of games development for this totally disconnected cause of greenness.

I've had many thoughts about creating games which encourage green behaviours or create awareness in various problems in our world, but I've always felt that games were a magical world where people had the freedom to play and it was not obvious to me how to allow people to play in a safe world and not get bombarded with educational facts or information. I did not wish to slap on text and images onto a game just to teach people about Greenness. It would be foolish to think that it would work since such a product is not built for the consumer. A teacher may have the intention to teach but a student may not listen. While I do believe that we learn through play, I was never a fan of highly contrived educational games. People learn through the experience of play, meaning the game had to teach something through the mechanics of the system. Great examples are like how Civilization teaches us about history, and how Sim City teaches us about governments. Creating a game with unrelated mechanics only serves to distant the player from the content.

Rant on Gamification

Gamification is also a bad word in my dictionary. I think there is nothing new in the concept of Gamification. It can be seen in any typical employment setup. Salary is Gamification, it encourages people to do things that they otherwise normally would not do. Bonuses and benefits are also often created to entice employees to stay in the agency, they are Gamification. Boy scout and Girl Guide badges are also Gamification. So what's the big deal about all this Gamification? To me, it is just a buzz word.

In my opinion, Gamification does help, but it does not and cannot serve as the core idea of the content. A good example is credit card loyalty points. Many people get many credit cards to get the best of all worlds, which begs the questions, are you still loyal to these card with loyalty points? Gamification can serve to enhance a product or service, but inherently, it has little value on its own.

First Concept: Ingress + Recycle Bin Locations

I attended some talks given on the first day, and one of them was by a StarHub executive who was trying to solve the problem of where to place recycle bins in Singapore.

This problem intrigued me and I believe I could solve it partially by allowing the community to engage and a fight (virtually) over where they thought the bins should be. So Ingress came to mind.

Perhaps players could set up pillars of where they thought a good location for recycling should be and they could get their community to help to enforce and defend that location through the game. The number of pillars would have to be limited which mean that if your neighbourhood was not doing a good enough job, the potential location of the recycling bin would be moved to another neighbourhood that wanted it more. I hoped that this game would be able to:
  • give people a say over where they wanted recycling bins to be
  • encourage people to spread the word of recycling through their community
  • encourage neighbourhoods to group together and collective compete against other neighbourhoods

Pitched Concept: Freecycle Upgraded

After some discussion with Mingding on the first night where we heard all the pitches from various people, we decided to talk to one of the people whose pitch piqued our interest. His name was Marcus Tay and he suggested building an app to upgrade Freecycle, which is a web community that gives away their stuff for free. Let's all admit it, we're spoiled by Google, Apple, Facebook, Instagram, Pinterest and Twitter. We are surrounded by a plethora of great products and services that are easy to use, yet on the freerecycling community they were still bound to the dinosaur-age (15 year old) Yahoo Groups. At least by internet standards, it was built in the dinosaur age.

We were very much impressed that Marcus had done his homework and he found a pain point that really needed to be solved. From some brief brainstorming Mingding and I also came up with these potential extensions of this platform:

  • Community events for charity or christmas giveaways
  • Better data tracking of recycling rate in Singapore
  • Reduction of home and office waste when moving out
  • Growth in recycling through social sharing
  • Self-regulating generous community that could help more needy people
  • Encouraging more barter trading
  • Encouraging Up-cycling (converting waste into new different products)
Based on the fact that we were able to see a potential explosion of possibilities, I thought this was a great idea to work on, so I decided to help Marcus with his idea.

Initial Vision: Free Stuff Exchange

This snapshot of Instagram served as my inspiration.

At least for me the initial vision was to be able to easily share stuff that you want to giveaway. The act of giving something away can already be a very personal and emotional experience. I wanted to make sure that giving away items should be as painless as possible. So these were the use cases I thought would be useful.

Give Away An Item

  • Capture an image of the item on your mobile device.
  • Add the name and description of the item and tag it so it can be found easily.
  • Upload the item.

Searching for Wanted Items


  • Search by tag or browse daily uploads.
  • If there are no items available, you can subscribe to a tag, even creating one if it does not exist.
  • Get notified via email when an item with that tag is available.

Taking an Offered Item

  • Propose method of delivery, either post or collection.
  • Deciding on a place and time to pass the item.

As simple as that!

These were the design considerations I had:
  • Easy to upload (more content -> more users -> better community)
  • Lazy users (push notifications will notify user instead of daily monitoring)
  • Visual and easy navigation (allow for better browsing experience)

Major Development Hurdle: Setting Up

So then we set out to develop this web app. Mingding would do the back-end server work and I would do the front-end.

The first major hurdle for me was setting up a test environment for the app. I had not set up or installed any serves on my development machines going into the hackathon, so I ended wasting half of the first hacking day.

At first, I started with plain old apache and being on a mac, this was relatively easy. The next thing I thought I needed was php, and this was not hard as well since apache supports it but a flag needs to be flipped. Finally, I needed mysql as a database. However, this took a while to download and was not so straightforward to install. 

After I faced some trouble with mysql, I decided maybe a package like xampp would be better, so I switched gear and downloaded that, tried to install it but by this time, I would have already used up at least an hour.

On the previous day, we also talked about the potential of using a plugin like Gridly to do the layout for us. And Gridly required Wordpress. So I tried to download the Wordpress plugin for xampp next.

It was about this time when Mingding arrived, and suggested we use Ruby on Rails because he was much more familiar with that. I agreed since I haven't really done any work and my responsibilities were largely on html and css, which should be independent of the platform.

I then proceeded to install Ruby and Rails but I needed to download Brew first! Brew servers were absurdly slow and served me a 90 mb file at 20 KBps, so it should have taken about an hour to complete. However, my internet connection broke, not once but twice for whatever reason, and I had to restart the download.

Once Brew downloaded, I proceeded to install it, and then install ruby and rails following a really long list of steps from this tutorial. But more hiccups entailed, I encountered some errors with git in two directories, and also more errors like this.

By the time I was done successfully installing Ruby and Rails, it was dinner time and I had not even started installing Postgre database yet, which was required for it to work.

In total, I think I spent about 6 hours just trying to set up my test environment but was not successful. Fortunately, around the same time, Mingding had already set up the server on heroku and I suggested to him that I just test directly on the production server instead of on my own machine since I'm only doing visual changes in html and css. I felt we simply couldn't afford to waste any more time in this hackathon.

Future of HTML5 is wonderful!

Fortunately, not all was lost, I did manage to get some css work done and I also test my own custom html for uploading images from my mobile device using Dropbox.

One particular thing that really amazed me was how easy it was to make use of the camera on a mobile device from HTML. All it took was this little tag (ref: http://www.w3.org/TR/html-media-capture/):

<input type="file" name="image" accept="image/*" capture>

Why it is so amazing is because on the mobile, this tag would allow you either select a photo or take a new photo using your mobile camera, and on the desktop, this would allow you select a file to upload. The best part is that it is widely supported on all web browsers so it means it is also cross platform. I love it when web browsers can finally agree on something!

I was surprised to learn that it just worked when I tested it!

Waking at 5 am

At the end of the first day of the hackathon, we had only a photo capture page and pretty much nothing else. The photo upload was not even working. We had only up to 1pm the next day to finish our prototype.

Since time did not wait for me, I decided to sleep and wake up early. The next section I worked on was the grid view css and html. Once again having no local server to test, I decided to fudge some html data and test it locally on my machine. At least I could mess with css and get some work done without the server. so I came up with this:

image here
Item Name
Item Description
RESERVED

I was figuring out a lot of things like padding and margins and also testing colors and box shadows and alignment of the text to the left, while the image is centered, etc. I was also testing the view on mobile to see how it looked.

Following which, I proceeded to customize the page's navbar which was generated using Bootstrap by Mingding. In total, the css for the box and customization of the page took me about 3 hours.

Once I was satisfied, I head down to the venue as our team decided to meet at 930am. Around the same time, Mingding had finished the image viewing code on the server and suddenly the app became usable.

True Hacking = Adrenaline

From that point onwards, everything became super exciting. Once I reached our venue, we basically had 4 hours left including pitch rehearsal.

Within that last 4 hours, we managed to get a working grid view. I originally tried using HTML tables but ruby was spitting things out in a list and it was hard to add the <tr> for table rows with that format. I read about floating divs, but that only worked for divs which were consistent in height. After which, I finally found the solution, which was to use display:inline-table and change the divs to an unordered list.

After which, we swiftly added Offered/Wanted categories, and then also allow users to edit an item data. And I also added Facebook share within half an hour.

Summary

At the end of it all, I really enjoyed the hacking and the adrenaline rush at the end. We got a lot of stuff done for a short period of time.

I also want to finish the project and add tagging and user profiles. Hopefully, we can launch this platform properly in a week or two. Here's a screenshot to enjoy in the mean time:



Tuesday, 30 July 2013

Castle Under Siege! Weekend Jam Game.



This (currently unplayable) game was done as a weekend game jam in 48 hours. To read about about my development process, check this previous post! I will be posting the updated playable version if it ever comes out!

Weekend Game Jam with HanMD82

Free source on GitHub
Snow Castellum on SoundCloud

Why this weekend?

So one day, Mr. HanMD82 randomly commented on Facebook that we should do a game jam. It was quite random but I love game jamming, so I try not to turn down a game jam offer nowadays, at least if it's done with some friends, we can always rearrange to a timing that works best. So we decided to do a game jam this past weekend.

Why Tower Defense?

I was itching to do a Tower Defense (TD) game because actually I was rather jaded about design cloning in the games industry. So I decided to make a clone for this game jam to learn about the genre and try to see why it makes people tick so much. I have to qualify though, that I play a lot of TD games myself and I love them too. In fact, I've probably played most of the popular TD games. I wanted to also test my game making skills and see how much faster I can build a game if I was already familiar with the design.

Approach

Having made a tower offense game (perhaps the first of its kind), I knew what I was getting myself into, but the difference here is that I would be hacking my way through everything, and picking the fastest-possible/production-efficient way to do the game. I picked up many lessons through making my previous games and I used these lessons to speed up the process in the jam. I'll share some tips here.

1030am Sat - Idea Generation and TD References

We started the jam around 1030am on Saturday. I showed HanMD82 a slew of TD games that were popular including but not limited to the classic Desktop Defense, Kingdom Rush and Field Runners. We then broke down the games and noticed there's a slight variation in design.

We noticed that in Kingdom Rush you cannot choose to place your towers anywhere on the map, while you could do that Desktop Defense / Field Runners. Therefore, as a player, you would solely focus on eliminating enemies and upgrading towers and you need not plan your placement of towers.

Kingdom Rush

Field Runners


Both designs have different implications on the tech that needs to support it. In Kingdom Rush, a way-point system would be used for AI and level design requires way-points to be placed. But for Field Runners, no level design is required but the paths of the enemies will have to be calculated on the fly, typically using an A star algorithm.

For the jam, we decided to go with the latter, but we would be modding the design a bit and have the enemy units move to a fixed location which would be the castle.

1130am Sat - Begin Production!

Because we already knew we'd be making a TD game, we could break down the game into its parts quite easily.

  • Towers (duh)
  • Tower Upgrades
  • Enemy Units
  • Path-finding
  • Waves
  • Projectiles
  • User Interface
And of course, we'll have some art and music to do as well.
From here, Mr. HanMD82 chose to do the Towers, Tower Upgrades and Projectiles, while I worked on the Enemy Units, Path-finding, Waves and User Interface. I volunteered to do the music as well.

From here, we set up the project on GitHub and started setting up the project folder and structure. We chose to use Starling Framework as we were familiar with it, so the project was done in Actionscript 3 (AS3).

130pm Sat - Enemy Units & Movement

I started working on the enemy units and immediately implemented a quick code to control speed and direction. Basically, we have four things we can set:
  1. Speed : the distance in pixels to move per frame or per second
  2. Direction: the angle in degrees to move
  3. VelocityX or Horizontal Speed: the distance in pixels moved in the x-axis per frame or per second
  4. VelocityY or Vertical Speed: the distance in pixels moved in the y-axis per frame or per second
Setting the Speed or Direction affects Velocities, and setting Velocities affect Speed and Direction, so for e.g. we have a function like:
function setSpeed(value:Number):void
{
    speed = value;

    // update velocities
    velocityX = speed * cos(direction * PI/180);
    velocityY = speed * sin(direction * PI/180);
}

The implementation for Direction and Velocities will be left to the reader (or you can just check the code on GitHub). The point here is that suddenly all you need to do to control the movement of an object becomes very easy since speed and direction are more intuitive to us humans, and also explains why direction has to be in degrees instead of radians (a necessary sacrifice for efficiency over code usability). And in the update function, we can just do:

function update():void
{
    sprite.x += velocityX;
    sprite.y += velocityY;
}

After this we had a quick lunch and I continued to work on various small things here and there like setting up the assets pipeline for importing sprites, etc.

3pm Sat - ...

I had to go to do some Remedial Training at this time, as I failed my yearly physical fitness test from National Service (Army). So that's 5 hours gone.

9pm Sat - Pathfinding

After I came back and had some dinner, I quickly dived into pathfinding. I grabbed the Wikipedia A star algorithm and translated it into AS3. Technically, I've implemented A star a few times before, but I decided to do it again from scratch this time as I was confident of getting it done in a few hours or less. The more times we rinse and repeat, the faster we get.

After translating the algorithm for a bit, I remembered I needed a priority queue to implement the openset. I quickly turned (once again) to the Wikipedia Binary Heap and started implementing that too.

As the game was not coded yet, I couldn't really test my code at this point (without diverting to write unit tests), so I left it alone, while I carried on with other stuff.

12am Sun - Castle Art

Was feeling a little itchy, so I wanted to start drawing stuff. I looked up "castle" on deviantart  and found this image:  http://www.deviantart.com/art/Neuschwanstein-Castle-285791596
DarkSilverflame - Neuschwanstein Castle
I really liked it and even thought it was a photo until writing this blog post, so I used it as a reference to make a sprite for the castle. I picked the color palette for our game using the above image.

At first, I didn't think too much and started drawing, and I came up with this:

I quickly put it into the game and realized I need to draw it in perspective!!! I knew we were going for the top-down perspective so I tried drawing some boxes but they didn't turn out so well:

So then I quickly looked up some references, first thing that came to mind is Zelda, so google images led me to:
http://zelda.salagir.com/dossier/jeux/castle3.jpg

1am Sun - Sleep

Even though I wanted to finished drawing the castle, it was time to sleep. We don't really believe in crunching, so sleep is good.

9am Sun - Music

Music is the fun part for me. I had some experience writing music for previous game jams so this time it was a little easier perhaps. I came up with the tune while on the bus to training the day before (efficient use of traveling time!) and hummed it into my iPhone, so this piece was done a little quicker than other pieces before. I wanted it to sound a little snowy / cold / icy as well as a little bit epic / Skyrim / Zelda. You can listen to Snow Castellum on SoundCloud

12pm Sun - Back to Castle Art

Learn from the masters! I decided to redraw the castle again with the new perspective. It took me a while, but I learned how to use the photoshop line tool along the way. Here's the result:

It was my first time drawing something this complex so it took me a while, about 1 or 2 hours. I drew it in parts starting with the main keep on the left and adding little towers on castle wall, then the big tower with snowy roof.

2pm Sun - Back to code

After lunch, it was back to code again. At this point, I had not finished the Waves, or tested the Path-finding algorithm. I jumped straight back into creating castle object and the spawn point for the enemy, which I needed to start creating a path for the enemies, which will then allow them to walk from the spawn point to the castle.

230pm Sun - Pathfinding Thoughts

I decided the spawn point should just be an object that holds a grid coordinate, and that the waves object would be the actual one spawning the enemies, since that's where most of the spawn data should be stored.

I also thought that doing an A Star search for every enemy unit would be too expensive, so I thought I could optimize it by allowing enemy units from the same spawn point to share a path and then they would only ever need to keep a reference to one path that would be updated and they would search for the nearest node on the path that they could use to follow the path.

>> In hindsight however, this was a mistake as the enemy units ended up failing to re-route correctly when a player placed a tower in the way of some enemies and they would end up passing through the towers to move to the nearest node on the path.

5pm Sun - Waves

Next up was implementing the waves. I created a SpawnParams class and stored them in the waves object, so that each wave can easily tell an Enemy Unit how to spawn, for e.g. the position to spawn at and the delay to use for the spawn. It was quite straightforward.

6pm Sun - Bugs!

Inevitably the Pathfinding had some bugs. I made some very simple mistakes which I should not have made, like for e.g. my Binary Heap did not test the correct value to decide which node is less than which other node, so that led to some strange behaviour where the enemies would walk through some tiles, then suddenly make a loop around some tiles in a triangular fashion, since the generated path was incorrect.

I also made another bug in the getNeighbors function for the nodes, where I missed out on checking if a grid tile was empty or filled with a tower for the left and right directions, but the up and down directions were OK. I guess it was a code readability issue since I knew to add it to some directions but not the others. 

These were minor bugs, and I didn't spend too much time on them, but I'm just recording them here to remind myself not to make them again. Ok, moving along...

I also added the background, which I actually stole from a photo of a mountain with snow, and then reduced the colors palette to 5 colors, which would create the dithering effect you see here:

background with reduced colors

9pm Sun - More Sprites & User Interface

At this time, I had dinner and took a walk with my dogs. I then started to go back to drawing stuff. I drew the UI for the game start and also drew some sprites for the towers and the enemy units. I added a bitmap font and the castle icon to draw the castle hp:


I was thinking about what to draw for the towers, then started with snowman, then my girlfriend was saying that I should draw a rabbit, and then next a pao (chinese bun). Yes, it's kinda weird, but I like it that way, and I figured I could make it 'reasonable' by adding little army men standing on their heads.

As for the enemies, she wanted a fox-like thing and pumpkin, based off the colors I had already picked. I was not ready to animate anything yet, so I decided to just go with some floaty/ghost-like foxes.

12am Mon - Snow!

I grabbed some crappy (but working) Particle code that I wrote before and dumped it into the game. I didn't really want the code anyway since it was badly designed, but I need something quick to make particles. I drew some quick snow images and added it to the game. After some tweaking, I finally managed to get this:
screenshot with snow particles


2am Mon - Sleep

Once again time to sleep. I was happy with the progress so far. Things were shaping up.

10am Mon - Final Touches

For some reason, in my head, I was thinking this would be a 48-hour jam. So yes, Monday morning is still legit. In the final hour, I added some explosion effects to the enemies. And I also fixed up the game retry so that the player could play again if they wanted.

Overall, I think I neglected design quite a bit for this weekend jam, but I'm still happy with the result so far. I'm also glad I got to draw the sprites and get to practice picking colors.

The current game state is not really playable; the waves are not designed, enemy units and towers are not balanced and we're missing a currency system.

However, here is the current state of the demo anyway for those of you who want it, check my next post!

Saturday, 27 April 2013

._ for Ludum Dare 26



Controls: Left / Right / Up arrows.
Source Code link.
Ludum Dare entry link

How I found out?
I was subscribed to Loom's mailing list because I downloaded it before they started charging money and I received an email today that they were giving an offer for their engine for the Ludum Dare competition. Thanks to that, I checked out the competition and read that the theme was Minimalism.

Thoughts on the theme
I was not schooled in art but I did know a little bit of Mondrian and Minimalism through a game designer buddy of mine. I can't say I fully understand but I do know it is about taking away as much of something until you cannot take anymore away from it without destroying its essence.

I've read that Will Wright and several other famous game designers often use this technique of taking things away from a game to find its essence. For myself, I did not really spend too much time thinking of a new mechanic to showcase this. Instead I went for something staple which is that of a platformer. I thought of games like Canabalt and Mario and wondered if I could do something interesting other than what was already done before. I started thinking along the lines of gaps and manipulating them.

Other Concepts
My mind did want to explore other more interesting concepts but since I hadn't actually planned to do Ludum Dare and it was a spontaneous challenge, I thought I would just go with the flow and make something for fun, not so much as to break any ground. Some of the other concepts I was thinking about were a minimalist plane shooter, or maybe some even more abstract like some kind grid-base game where you can break a grid cell into 4 quads depending on where you clicked to partially create the Mondrian art style as part of the process.

Engine Choice
I think I should apologize to the Loom guys! I'm so sorry I found out about Ludum Dare through your email but I ended up choosing Flash as my engine choice because I'm more familiar with that. Also, I actually started working in Flash Builder for deployment on iOS but then I read that I should give up my source code so I decided to dump that project setup and move to Flash Pro for Web deployment, since I did not want to give away my source code for my previous mobile projects.

Code flow
Here's the coding flow which I used to make this game.

1. Player
I started by coding the player, it was a simple square that would act under gravity. I did this pretty quick since I have done this many times before. Basically just add velocity and gravity and have them act on the player's position.

2. PlatformsAdded some code to draw a platform.

3. Collision

I decided to go with the simplest kind of collision code of all. Extremely old school but I guess it works for my case, I just check if the player is within the platform manually or not. I actually do not use any hitTest or accurate physics for this.

if(player.x + player.width > platform1.x && 
  player.x < platform1.x+ platform1.width &&
  player.y + player.height > platform1.y &&
  player.y < platform1.y)

4. Game states
I prefer to do this early before the code gets messy so I added GameStart(), GameEnd(), GameUpdate() functions and also added the game over state in GameEnd.

5. Controls
Next up was the controls, I just went with left/right arrow keys for movement. And later I added Up key for jump.

6. Platform generation
There are always only two platforms in the game, especially since this was a minimalist game. I decided you would have to stand on the first before the second one showed up. I spent some time on this getting the platform to fade in according to how much time you stayed on the platform. After that, I swapped out the first platform to be the second and made a new (third) platform. At first I thought I'd just swap out the platform once the player jumped off the first platform, but I found that to be too punishing, and I wanted to allow the player to take his or her time with jump so I changed it such that the platform would only swap out once the player's x position is past the platform's right edge position. This would ensure that the player would have left the platform already and would allow the play to jump as many times as they want on the same platform if they stayed within the platform edges. I also chose to spawn platforms with greater gaps with each successful platform jump.

7. Deaths
Early in the development I actually already added a death sprite to show where the player died, which would indicate to them whether they've beaten their own progress if they replayed it. Then I suddenly had the idea to combine the previous idea of somehow developing a Mondrian painting as you played and I decided that the death markers would serve instead as an aesthetic to the game. So I changed them to be randomized rectangles that had these extending border lines or randomized line widths as well. Then end result was quite aesthetically pleasing such that when you died, you ended up making a splash on a painting.

8. Scoring
Scoring was simple and easy. It's an infinite game and your score is based on how far you manage to jump up to, so it is just the player's x position when he or she died as the score. A highscore is also kept at the top right.

9. To End or Not To End
By game jamming standards, this game was still really 'young', I only spent about 4 hours or so on it, I wondered if I should making the deaths markers be interactable or not. That could make the game really interesting. For example, maybe Blue rectangles could make the player float, Yellow & Red could do something different. But I thought oh well, I had not really planned to Ludum Dare and I was ok with what I had, it was meant to be a minimalist platformer and so it shall be. Not the best concept in the world but I'm glad I could execute it in a short time. It was also a really fun enjoyable concept experience for me.

10. Name
Now I had to think of a name, so I let my girlfriend name it. She came up with "._" which I think was awesome because it represented a minimalist platformer so well. Anyway, for trivia's sake, the working title was Gappy.

11. End
I think the final version of the game was pretty challenging. I ended up changing game variables on each jump so that it would get harder and less predictable as you played. For example, aside from the platform distances getting further, I also changed the jump power, the movement speed (which makes the game really slippery), as well as the camera catch up speed (which was necessary was there were bigger gaps).

12. Sound
And when I thought I had finished, and I even started writing this blog post, I forgot I had to do sound!! So here we go back to do the sound, luckily I'm just going to add one sound. And finally upload and end.

FIN

Sunday, 17 February 2013

RYB Color Wheel



As a follow up to my previous post on the RGB color wheel, I made the RYB Color Wheel.

This time I got a bit smarter so I decided to build this wheel in Stage3D, since I could use the GPU to interpolate the colors on the triangle for me. I have not actually coded directly in Stage3D before since I used Starling framework which wraps around Stage3D to make it much easier to use. This Hello Triangle tutorial by Marco Scabia helped me jump through the basic hoops of setting up the render scene.

I first tried to change the formula for the HSV/HSL computation. I remember this graph from the HSL-HSV Wikipedia page which showed me the RGB values behaviour when the hue changes.


HSV-RGB relation


I wanted to modify the mathematical formula to alter this graph to shift the yellow to the green's position to make it a primary color. I tried this out by editing the gradient of the svg file from wikipedia in Adobe Illustrator.


HSV-RYB relation with yellow shifted


This was what I got, but I quickly realized that this method would not suffice as I should not be getting such bright colors, and I should not even see cyan in the wheel. I tried to cut off cyan by adding a node at the 180 hue green and blue and interpolating directly to the 240 hue value and I thought I took a step forward.

However, I also did a quick web search and found a research paper which suited my needs. The paper, titled Paint Inspired Color Compositing by Nathan Gossett and Baoquan Chen, used custom color values for a color cube and did a 1-for-1 mapping between the RGB cube to the new RYB cube and then trilinear interpolated the RYB cubes colors to figure out the RGB values. They got the values from the Johannes Itten color model, which is widely used in art education.

I decided to adopt their method to implement my RYB color wheel, so credits goes to them for the RGB-RYB conversion. I decided to plot the graph again using the values provided by them to see what it looked like:



HSV-RYB relation


Learning Points:

  • RYB can be mapped instead of done via a formula. I think there is still value in building the formula version for efficiency purposes but currently, this suits my needs already.
  • Most of the RYB colors are standard but RYB green is (0.0, 0.66, 0.2)
  • RYB blue is not pure blue (0.163, 0.373, 0.6).
  • RYB black is not pure black (0.2, 0.094, 0.0)!
  • In fact, there is a lot of red everywhere. From the graph, you can tell that red is most prominent color of the three primary colors RGB. Even in black, there is a relatively strong red component, which equates to brownish black.
  • I was wondering if the components of RGB had any effect on Value or Lightness of a color. Reading up Wikipedia tells me that Lightness is actually ambiguous! And there are actually 4 different ways to calculated Lightness of a color. That's definitely something new to me because I knew that if the grayscale version of two colors were the same, they would be the same Lightness, but I did not know that there could be several ways to achieve that.
  • The research paper suggested giving a bias towards to the colors at the corners of the cube by altering the interpolation function to a cubic one. For this reason, I decided to implement a linear function compare the results. You can click the button above in the flash swf to see the difference. I do not have much opinion on which is better at the moment, although linear interpolation would definitely be cheaper computation wise so that may be the function I would probably use for real-time games purposes.
  • In the process of converting RYB to RGB, I came across trilinear interpolation. Trilinear interpolation is essentially interpolating all the 8 corners of a cube to find a point within the cube. It is done by first interpolating the 4 pairs of corners in one axis (e.g. X-axis), then interpolating the 2 pairs of results in the next axis (e.g. Y-axis), and finally interpolating the 1 last pair of result in the last axis (e.g. Z-axis).
  • In writing this blog, I also learned how to use SVG graphics inside Blogger. You can read more here if you are interested.
  • As this is the first time experimenting directly with Stage3D (instead of using the Starling Framework wrapper), I also got into some hiccups with the Matrix which is passed into the vertex shader for view projection. I realized that Stage3D by defaults provides a normalized viewport so for e.g. top left of the screen is (0,0) and bottom right is (1,1). I wanted to look into setting up the projection matrix for a proper camera system but I think I will want to look into that again in future.


Get Adsense

Want to earn money like me? Get Google Adsense now by clicking this