Recent Blogposts | Page 5

Poopie: Making Kim Jong Un Cry

Nov. 3, 2015, 3:20 p.m. Gamedev Poopie Product Release

Hey guys! I've just released a new game. Poopie: Making Kim Jong Un Cry!

It is an enhanced version of my Ludum Dare 33 Entry.

What's new:

  • More upgrades
  • Better graphic
  • Faster start off

Screenshot of the game

The graphic isn't very good. But it's already a big improvement compared with its preceder. Well, my art indeed sucks. But it's getting improved over time. :D So don't complain about it. :P

Rules(New)

  • Move you mouse to control the position of the bird/owl/whatever you call it
  • Click/touch to poop
  • Avoid lightning
  • Poop on people to make money
  • Upgrade with what you've earned
  • Poop on Kim Jong Un to win the game(For entertainment purpose only. No political message intended)
  • Stop pooping when police car is passing by. :P

FAQ: Why does this game has something to do with Kim?

A: Win the game to figure it out! :D

Play

HTML5 version is released. Android version coming soon is now available!


Nginx Caching with uwsgi

Oct. 25, 2015, 5:17 a.m. Sysadmin

First sysadmin post!

I'm using Django and nginx with uwsgi for this webste. Right after the update of this site, I used PageSpeed Insights to check for the issues. It reports that my server is responding very slow(2 seconds!).

By googling around, I found that nginx has good caching support. With the use of both client cache and server cache, the rendering time of the cached pages can be reduced. Here is what I do to solve this problem:

#16m being size of cache key, 1m cache key can store 8k cache entities.
#60m being the inactivity invalidation time of cache
uwsgi_cache_path /var/www-newSite/serverCache levels=1:2 keys_zone=foo:16m inactive=60m;
server {
    ...
    # Django media
    location /media  {
        expires 1h;
        alias /var/www-newSite/media;  # your Django project's media files - amend as required
    }
    location /static {
        expires 1h;
        alias /var/www-newSite/static; # your Django project's static files - amend as required
    }
    location / {
        uwsgi_pass unix:///path/to/django_site.sock;
        include /etc/nginx/uwsgi_params;

        #client cache
        expires 5m; #Or whatever value you want

        #server cache
        uwsgi_cache foo;
        uwsgi_cache_key $uri;
        uwsgi_cache_valid any 1h; #Or whatever value you want
    }
}

You may refer to the documentation of the nginx module ngx_http_uwsgi_module for what does the directives do.

Before caching, it takes two seconds to render a page. After caching, it only take ~20 ms.

The downside of this approach is that if the database is updated, the cache isn't invalidated immediately. It probably isn't an issue for this site. In case it's a problem for you, you may want to read a bit about Django’s cache framework.


Major Website Update!

Oct. 24, 2015, 6:13 p.m. Meta

I've updated the UI of the website!

Feature of this new site:

  • Modern UI (Achievement unlocked! I've never did it before!)
  • Tag filtering function
  • Merged blog with homepage
  • Social network buttons
  • SEO (Yet another achievement unlocked! It's first time that I do it)
  • Mobile friendly
  • Works without javascript(with minor font display issue)
  • Easier captcha for comments
  • Bugfix: image display resize issue

New site icon

New site icon

Old homepage (archived)

old homepage

Old blog (archived)

old blog

Yes. The logo looks like the bootstrap one. I didn't know the existence of bootstrap by the time I made that logo. Now I know it. That's why I've changed the logo.

This is indeed a big improvement of this website. It have taken me 10 days for working on this update. It's still not done. This site still lack content like product list and link exchange. I'll add more stuffs to this site soon!


[WIP]Koloniigo - Early Access Version

Oct. 10, 2015, 6:08 a.m. Gamedev Koloniigo Product Release WIP

After two months of work, early access version of Koloniigo is finally available!

[NEW]Tutorial Instruction

A few users has reported that this game is confusing. Therefore, I add a tutorial instruction section here.

  1. Click a red building
  2. Click the attack button on the top-left corner
  3. Click a blue building to send population to it.
  4. You'll see that a red ball is spawn. With the bar changing color
    • The red ball is the population to be sent
    • The bar shows the amount of population inside a building/moving population
  5. Click the next turn button
  6. Repeat until you take control of all buildings

Rules

  • Objective: turn all the building into your color(tutorial: red; random map: red; networked game: either red or blue)
  • Turn based game. It's your turn, enemy's turn, your turn, enemy's turn and so on.
  • In each turn, send population from your building(s) to other building(s). When the population a enemy's building drops to 0, it's yours.
  • Each building has special function shown in speech bubble, e.g. double defense, triple attack, etc.

Mini FAQ

  • Q: What are the color bar above the buildings?
    • A: They're the amount of population inside a building. white~red = 0~10; red~orange = 10~20 and so on. Double thickness means 100+, triple thickness means 200+ and so on.
  • Q: What does the icons in the speech bubbles do?
    • A: It tells you the special function of the building. You can't click on them
  • Q: I've controlled all of the buildings. Why I still can't win?
    • A: It takes time for population to move from a building to other building. The moving population of opponent is hidden by default(unless you got a beacon). If it happen, it means that there're still moving enemy population in the map. Those moving population might be able to take back the control to your building. That's why you aren't regarded as winning until all moving enemy's population is died out..
  • Q: How do I beat tutorial 3?
    • A: First, you need to take control of blacksmith(the thing that looks like an oven). Then make use of the blacksmith for attack because it has 3x attack compared with other buildings.
  • Q: The game freezes in networked game. Is the game broken?
    • A: No. If you can do nothing in networked game, it means that your opponent is making decision on his turn. You have to wait for your opponent to click the next turn button. So just wait.
  • Q: I can't send population in networked game.
    • A: First, ensure that it's your turn. There should be a green check button on the left-bottom. If not, just wait for your opponent to pass the turn to you. Second, in networked game, it may be possible that you're blue instead of red. So click some blue building to check whether you're blue
  • Q: I've more question!
    • A: Ask wherever you can see me. e.g. reddit or freenode

TODOs

  • Change the graphic. The current graphic looks ugly. I'll probably find an artist for help
  • Networked game
    • lobby
    • Multiplayer vs multiplayer
    • Network disconnection handling
    • Tell whether you're red or blue at the beginning of the game
    • Display something interesting when it's opponent's turn
  • Bugfixes :P
  • More gameplay elements

Before doing these, I think I'm going to update this website first. I'm planning to merge this blog with my homepage. and I got tests and exams to do recently. I think I can't work on this game for a month or two. :( Anyway, don't worry. I will complete this game eventually. My project completion rate is pretty high. :)

Click here! to play!


Java String Split Gotcha

Oct. 6, 2015, 2:12 p.m. Programming

I was fixing a networking-related bug in Koloniigo. I did something like this:

String[] fields = data.split(";"); //data contains something like "a;b;;"
foo(fields[3]);

Then the program gave IndexOutOfBoundsException

I wonder what's wrong. After a few hours of debugging, I found this thingie in the documentation of split()

Trailing empty strings are therefore not included in the resulting array.

Oh well, wtf? A few hours wasted.

You may think that I'm an idiot that I didn't notice such an obvious mistake. Actually, the real code is way more complicated and there was very many possible causes of the issue. That's why it took me so long to figure out that it's the issue of the split(). :(