Friday, May 24, 2013

Android Football!

Allow me to announce my latest Android game: Android Football!


I've always wanted to create a football game, and with touchscreen controls it gets round the problem that old-style football games have in deciding which football player is under control.

But before kick off, the first thing to do is choose your teams formation.  One aspect I'm quite please with is the AI of the players.  They always seem to be in the right place at the right time.



Once the game has kicked off, you control the players by dragging a line from the player to where you want them to go.


The players will automatically kick the ball when they hit it.  The direction is determined by the angle the touch the ball at, in the same way as a game of air-hockey (though this game is thankfully not quite as frenetic!).


The free version only has friendly games, but gives you all the features of the actual match so you decide if you like the game.  In the full version you can also play in a league, and choose the number of other teams.  If it proves a success, I'll be adding a Knockout Tournament option to.

Thursday, May 09, 2013

I've had a great idea!

I know, I'll add the Google+ API to my game Stellar Forces!  That way, new players will be able to sign up quickly and easily!

[3 hours later, after jumping through lots of Google-shaped hoops...]

What a waste of time.  I think I'll keep it the way it was.

Friday, April 26, 2013

When is Normal not Normal?

Say you've got a vector that you want to normalize:-

Vector v = new Vector([a number], [another number]);
v.normalize();

What would you expect to happen if both your numbers (maybe the movement vector of your space invader) were 0?

I would hope it would return a vector of (0, 0), so that when you added this vector to your sprite's co-ords, it didn't move.  Which, with a vector of 0, 0, would be correct.

Unfortunately, in Android Java (and maybe normal Java as well), it returns (NaN, NaN), which is no use to anyone.  I'd prefer an error at least (failfast?) so that I knew something unexpected was happening.  With NaN, all your sums suddenly go awry, and until you know the above piece of information, you'll spend ages trying to work out just how your vector is turning into garbage and why your sprite has decided to move to infinity on both axis.

Wednesday, March 06, 2013

Was making money harder then or now? [Android]

I'm at that common stage of Android development where I'm wondering what my next project should be.  I'm tempted to do something in 3D, but it always turns into a maths nightmare.  Note to self: Don't do it!

I've recently finished my last app, a platformer called "Ninja!".  It's pretty good, and I might use the engine for something a little more complex - I'm thinking a Bladerunner-y / Judge Dredd.  However, I am put off by the sheer number of other platform games available on Android (not that the platform genre is any more saturated than any other genre on Android).  Who would even notice my game?  I guess that's why marketing is so important on Android now, probably more so than the programming.

But then I look back to the golden age of gaming (in Thatcher's Britain anyway): the mid-80's, when it was predominatly the Spectrum that everyone played on (and maybe the C64 if desperate).  How do conditions now compare to then?  There may be thousands of platform games available for Android, but there are also millions of users playing them.  What was it like in the 80's?  According to Wikipedia, 5 million Spectrums were sold and 24,000 programs were released.  According to some random website I found after Googling, there are 295 million Android phones and 460,000 Android apps.  Despite the fact that these numbers are untrustworthy and vague, lets work out the average:-

Spectrum:-
5,000,000 devices and 24,000 programs = 208 customers per program.

Android
295,000,000 devices and 460,000 apps = 641 customers per app.

So it seems that despite the competition, we've got it over 3 times better than they did in the 80's.  Still, it doesn't seem like it.  Maybe I should stop programming and do marketing for the time being.

Monday, February 11, 2013

New Android Game: Ninja!


It's a platformer.  Avoid the enemy ninjas (or throw shurikens at them) and negotiate the fiendish levels.

One of the great things about creating a "platformer engine" is that once it's created, it's simply a case of having fun designing levels.  Going through historically classic platformers and implementing your own version of their ideas, and being able to play it straight away, makes all the hard work worthwhile.

I've also written the code for moving platforms, but I'm still trying to work out how to include them in the map data; the map data only handles a block type in each "cell", whereas moving platforms require data on the direction to move in, and the distance.  More on that in a future post.

Anyway, find Ninja! here!


Tuesday, February 05, 2013

Eclipse Hangs or Freezes on Startup

Try this:-

  1. cd .metadata/.plugins
  2. mv org.eclipse.core.resources org.eclipse.core.resources.bak
  3. Start eclipse. (It should show an error message or an empty workspace because no project is found.)
  4. Close all open editors tabs.
  5. Exit eclipse.
  6. rm -rf org.eclipse.core.resources (Delete the newly created directory.)
  7. mv org.eclipse.core.resources.bak/ org.eclipse.core.resources (Restore the original directory.)
  8. Start eclipse and start working
 (Thanks to Olaf)

Monday, November 12, 2012

Installing Java for Applets

I've blogged before about the fact that Sun (and now Oracle) like to make it as difficult as possible to get Java working, especially for applets.  You can spend hours trawling the new for soutions, but often they don't work due to differing versions of your OS, of Java and your browser.

However, for future reference I've found this page which seems to wort and is incredibly simple:-

http://www.webupd8.org/2012/01/install-oracle-java-jdk-7-in-ubuntu-via.html


Wednesday, November 07, 2012

Julian Gollop Announces New Chaos

If you're a fan of Chaos then you probably already know this, but Julian Gollop, famed developer of strategy games, has announced he's working on a new version of Chaos.

Chaos is indeed a brilliant game; that's just one reason why I copied it so faithfully for my own Sorcerers for Android.  I hope Julian won't mind if I treat this as a bit of competition between us as to who can create the best game.  I'm bound to lose, but it's the kind of impetus I need to keep working on a game.  And there can be no losers!

Friday, November 02, 2012

Speed Warning

Here's a new app which will hopefully save me money from those annoying speed cameras.

Without wanting to get too political on this blog, what really gets me about being caught for speeding is that it's too easy to creep over the speed limit.  Staying on the right side of the law shouldn't be a test of skill, and the more time you spend looking at your speed dial, the less time you spend looking out the window to check you're not going to crash, which can't be right.

Anyhoo, either way, my new Speed Warning app for Android should help and save people from the usual speeding fines.  It sits on your dashboard and will show you your current speed, in either Miles per Hour or Kilometres per Hour, depending on what your country uses. 

The main feature however, is to give you a visual and audible warning should your speed creep over the limit you have set, which can be easily adjusted with the '+' or "-" icons.  So now you can keep your eyes on the road at all times without worrying if you're breaking the law.

Wednesday, October 24, 2012

Podcast Manager


I listen to a lot of podcasts.  They make driving much more fun; now, when I hit a traffic jam, I think "Great, I can listen to more comedy before I get to work!".  (This probably sounds sarcastic, but it's true).

I was yet to find a decent podcast manager on Android, so I decide to create one.  All the other ones seemed too complicated; all I wanted was one that would let me easily find the podcasts on my phone and play them, but have lots of convenience features like let me return to the same point in a previously played podcast as it was when I last stopped playing it.

With this in mind, let me present Podcast Manager, and android Podcast player with all these features and more:-

* Scans your SD Card for all mp3s.
* Voice search
* Reads and displays the details of your podcasts (artist, album, etc...)
* Remembers previously played podcasts and the last position, so you can pick up exactly where you left off.
* Delete listened-to podcasts.
* Easily browse your phone's memory for podcasts.
* Easy to use interface for skipping through podcasts.

If you have to get it, let me know what you think and I'm always open to feature suggestions.  But at the moment it does everything I want from a Podcast player.

Tuesday, October 23, 2012

Minecraft + 3D Printer?

You read it here first - I predict that in the future you will be able to connect Minecraft to a 3D printer and print out a model of the worlds that have been created.  And I predict the first person to do this will get very rich.  And there will be a shortage of 3D paper since everyone insists on printing out the Mines of Moria.

(I also predict that someone will tell me this has already happened).

Friday, July 27, 2012

New App: Sorcerers

Like every other human being on the planet, I am a big fan of most Julian Gollop games, and the pinnacle of these are obviously Laser Squad and Chaos.  I've "tributed" Laser Squad with Stellar Forces, and now it's time for some Chaos.

My new app is called Sorcerers.  Like Chaos, it's a multi-player game where each player takes control of a wizard.  Each wizard has some spells which they must use to destroy the other wizard, and the winner is the last wizard left standing.  The spells range from fantasy creatures like a Wraith or Golden Dragon, to Magic Fire and of course Turmoil and the dreaded Gooey Blob.




There are a few changes to the original: there are more variety of spells, and turmoil doesn't crash the game.  It's currently 2-player, but will be increased soon to up to 4 player.

Thursday, July 26, 2012

Jellybean Graphics Bug - Help!

There's a really annoying bug in Jellybean, and I can't work out how to get round it, so I'm posting it here in case someone else has come across it and knows a solution:-

I've got two .png images in my app, both identical except for the name and I've changed one of them to be "bluer" (using Gimp). However, Jellybean refused to draw the bluer one. (I'm having trouble with other random images as well). There are no errors, and it loads the file okay, but nothing appears. I've tried swapping their names. They're both only 57x57 pixels, so it's not a memory issue.

Someone else has posted the same problem on Stack Overflow, but as of now there are no replies.

It's driving me mad!  How can something broken like this end up being released onto millions of mobile phones?


UPDATE: I've found a workaround!  Copying my images into /drawable-nodpi, seems to have solved it.

Wednesday, July 25, 2012

Free Service?

One thing that is starting to annoy me is the number of services that start out free, but then as soon as they become popular they introduce paid-for features while slowly reducing the free features until they are virtually useless.

The stock response to this is "well, it's free, what do you expect?".  However, this oversimplifies the issue and ignores all the other aspects of the problem.  Most important of these is that I've recommended these services to others, thus giving the free service its userbase.  My comments on these services are still on the internet, but I wouldn't recommend them now.  I've also spent my own time incorporating their service into my apps and my time isn't free.  Their services are now so entwined in my apps that it's going to take me lots more time to remove them and find alternatives.

I've got no problem with these services charging for extra features, but reducing the features that were there originally is almost tantamount to blackmail.

Friday, June 01, 2012

Your First Java Library Function

The first thing to do when you start creating your own library of Java functions is to write a wrapper for Integer.ParseInt() (and any of the other similar built-in functions).

Integer.ParseInt is, maybe deliberately, the most pedantic piece of code ever written.  Pass it a string like "2" and it works fine.  Pass it a string like " 2" and it goes "waoh!  A space?  What the f*ck is that?? Error!  Crash the system, we're going down!!".  Is it too much to ask to be able to handle a space?

In fact, almost any non-numeric character (the main exception being a "minus") in the string will cause it to throw a wobbly.  Even a decimal point: "2.0" is beyond its capabilities. 

My suggestion is as follows, although it's not the hardest piece of code to write:-

    public static int ParseInt(String s) {
        try {
            if (s == null) {
                s = "0";
            } else if (s.length() == 0) {
                s = "0";
            }
            return Integer.parseInt(s.trim());
        } catch (java.lang.NumberFormatException ex) {
            return 0;
        }
    }

Monday, May 28, 2012

MySQL Replication Challenges

If you've got a server running MySQL that's creaking under the weight of database reads, the obvious solution is to set up replication.  MySQL replication seems to work fine, but one thing I didn't appreciate at first is the changes that probably need to be made to your code (and not just changing which server it reads data from).

I imagine that most web pages, if they're anything like mine (oh dear) implicitly rely on the database being updated immediately.  My web pages usually have a similar structure:-

1: Read any get/post values and update the database
2: Display the new updated data as part of the web page

This seems fine, and it is if your database is updated immediately (since stage 2 is reading the data that has just been changed by stage 1).  If you're using replication, then you'll be updating the master database in stage 1, but then reading the data from a slave for stage 2.  However, if the slave hasn't updated itself from the master by the time stage 2 is running (and we're probably only talking millionths of a second) then stage 2 will display old data, and your users will cock their head to side wondering what's going on and why the system has ignored their commands.

Another similar problem I experienced is with an automatic routine that transfered data from one table to another.  For various good reasons, this routine would read the first 100 records (from the slave, obv), append them to another table, and then delete the originals (on the master).  And this worked fine until there was a small glitch in the communication between the master and slave.  Glitches in communication aren't normally a problem since you can specify how long the master retains logs for, so you can turn a slave off for a few days, turn it on, and it will (eventually) update itself.

However, due to the glitch, the slave wasn't updating itself.  It read the first 100 records from one table (on the slave), wrote them to another table (on the master), and then deleted the records from the original table (on the master).  Since it was reading the records from the (non-updating) slave, the next 100 records it read were the same 100 records as last time, because they were still there.

Being an automatic routine that runs overnight, this process was duplicating identical records at a hysterical rate, eventually eating up all the disk space and so the whole system went down within just a few minutes.  Oh dear.

So, in summary, replication technically works very well, but you can't just plug it in and turn it on and expect all your problems to be solved.  You probably need to think carefully about when to read from the slave or master, and what will happen if the slave is too far behind the master.

Thursday, May 17, 2012

Recording Videos of my Android Apps

If there's one thing I've learnt (or learned - which is it?) over the last month, it's that people like to be able to see what an Android app looks like before they hand over any hard cash.  I recently created a video of a few of my apps: Chromakey Photo Edit, Worldcrafter and Stellar Forces.  And blow me down with a feather if sales and/or downloads didn't increase!

So how did I create the videos?  I do have access to two phones, both of which are capable of recording videos, so the obvious answer was to use one phone to record another.  However, keeping both phones steady while recording and playing was harder than I thought; the phone that is recording doesn't need to be held by a person, but it does need to be positioned between the player ("hello") and the phone I'm playing on.  Asking a fellow human to hold the recording-phone tends to feel a bit ridiculous as they have to reach around you and keep the phone super-steady, which isn't that easy.

The solution hit me like a birthday present when, for my birthday, I got a present that turned out to be a phone holder for my car.  Perfect!  Its suction cup held it securely to a table while I played the games around it.  The only challenge now is to make a vaguely entertaining video that's short but also shows off the best features of the games.  And also where my thumb isn't always in the way.

Here's the Worldcrafter one:-



Since the game involves tilting the phone, that provided an extra challenge for keeping the phone in-view.

Friday, March 30, 2012

More Eclipse Update Frustrations

I use Eclipse all the time for coding, but every time I want to add a new add-on to it, it turns into a nightmare making me want to strangle whoever came up with the Eclipse update system.  Todays living hell is all about trying to add MAT (Memory Analysis Tool), just so I can read a "hprof" file.


Okay, where to start?  It was easy enough to find the MAT homepage (http://www.eclipse.org/mat/).  How do I actually get it?  There's a link called "Download the latest version as RCP application" (whatever RCP means), but I know I want to add it using the Eclipse Update Manager.  There is a "Getting Started" link, so I'll try that.

This is looking good.  There is a link called "Read the Eclipse Memory Analyzer Tutorial to see how to start the program. "

We must be there soon.  The tutorial says "Install Eclipse MAT via the Eclipse Update manager . Select "General Purpose Tools " and install "Memory Analyser (Incubation)" and "Memory Analyser (Charts)"."


Okay.  I assume by Eclipse Update Manager they mean the Install New Software option.


That asks me for a site to update from.  Erm, any clues Mr. Tutorial?  No?  Gee, thanks.

Okay, lets go back to the downloads page.  It's better than nothing.


Watch out!  It has an update site!  Okay, let's go back into Eclipse and put that in.

Hmm, it lets me put in the text, but OK is greyed out.  It seems that this is a "Duplicate Location", even though it's not in the dropdown list of locations.  Great.  Another dead end.

What next?  After fumbling about for half an hour I try the Eclipse Marketplace (which takes about 2 minutes for the window to appear as it insists on loading data from the internet every time).  I'll just do a search for MAT.


It's here!  This must be the solution then.  Okay, what do I click on?  The only links are "Share" and "Learn more", neither of which sound like "End all this messing about and just get it now", so I guess I'll try "Learn More".


This link just takes me to the website of MAT on the marketplace.  The only link I can see on the page that might be of use is the one that gives the update site.  What?  I thought this was the update site!  And the link to the Home Page returns a 404.


Fucking Hell this is ridiculous.  It seems that the Marketplace only has v1.0 of MAT, which has been replaced with a seemingly non-existent v1.1.  Maybe.  I don't know and am rapidly losing interest in this piece-of-shit life-wasting process (Apologies for the swearing but I've lost count how many days of my life I've wasted trying to find my way through the maze of Eclipse updates only to give up).



UPDATE

I finally got MAT by discovering a "Available Software Sites Preferences", adding MAT and then doing the update (this sentence makes it sound far easier than it was).  With MAT installed, I opened the HPROF file:


[Sound of programmer stabbing himself]


Friday, March 23, 2012

Java URL class is Buggered to Buggery

Take this bit of code:

URL url = new URL("http://www.somesite.com/forums/test.php");

What should "url.getFile()" return?  I would have guessed the string "test.php".  But it returns "/forums/test.php", which seems to be including the path as far as I can see.

The javadoc actually says "Gets the file name of this URL", but then goes on to contradict itself in the very next sentence with "The returned file portion will be the same as getPath().".  Is it me or Oracle[/Sun] that needs to go back to programming school and learn about the difference between a path and a filename?  Or maybe there is a subtle but massive difference between a "file name" and a "filename".

Also, AFAICT there's no way to get the (what I would call) filename, i.e. "test.php" in the example above.

Thursday, March 15, 2012

XML is a Step Backwards

XML has its place, like when transferring data between disparate systems.  But I can't help wondering if using it for things like the Android Manifest is a step backwards.  Why not use a programming language?  With XML, you lose a lot of the useful features of a programming language, like code-completion and interaction with the main code.

Taking the Android Manifest as an example, I have to refer to a list of the specific permissions that I require, since without code-completion it won't tell me the possible options.  These also have to be spelled exactly right.  Also, I'd like to change the icon based on some flags in the code.  Can I do this?  No, the XML is static.  Great!

Friday, March 09, 2012

New Android App: Speech Browser

I can now unveil my latest app: Speech Browser!  It's a voice-controlled web browser with all the usual functions that a web browser has, such as going to a website, doing a search, going forwards/back through history, following links, searching for text etc..  

However, being voice-controlled, there are a lot of extra functions: repeating a page, going forward/back through the page, controlling the speed of the voice.  There are also 3 voices available: British, American and Canadian (although being British myself I can't tell the difference between the last two :) ).

It should hopefully be quite useful for blind Android users (and if any find it useful or otherwise I'd be please to know), but I also wrote it for people to be able to listen to a website like Wikipedia without having to stare at a screen.

Wednesday, February 29, 2012

Thunderbird Deleted all my Deleted Items!

It's not the double-negative that it sounds like.  I "delete" all my emails (that have been actioned) so they go into my Deleted Items folder in Outlook, for reference at a future date.

However, I then started using Ubuntu at work meaning Outlook was no longer an option.  There is the Outlook web view, but as far as I can tell there's no search feature.  Being the modern techno-geek radical that I am, I thought Thunderbird would be a good idea, at least for the search facility.

Initially it went well, but then I noticed that the contents of my deleted items had disappeared: 5 years worth of emails (about 9,000 emails in all)!

The problem seemed to stem from the fact that I had "Empty Trash on Exit".  I naively thought that this meant it would empty the Trash folder on exit, but Thunderbird, presumably trying to be clever and helpful, decided that my "Deleted Items" folder was my trash, not the actual Trash folder.  Er, thanks.  Back to Outlook it is then.  I just hope I can recover them all.

Thursday, February 23, 2012

Good Review!

While it's nice to make a bit of cash from my apps, getting a good review is always great; I don't think many users appreciate how much effect they can have on a developer; a crap review (especially nonconstructive ones) can be a real downer.  Even the most basic app takes days of work, and when they are given away free but a user still leaves a crude review like "this is rubbish", it makes you think "What is the point?".

Conversely, getting a good review is great and really makes it all worthwhile.  Here's a humdinger that I received a few days ago for UK Traffic Alerts.  I've taken a screenshot since it could well get superseded by (hopefully) just as gushing reviews.


Whoever Peter is, I thank you!.

Thursday, January 19, 2012

Android Bitmap Idiosyncrasies

Whilst improving my Android app Chromakey Photo Edit, I've come across a few idiosyncrasies with Android Bitmaps which I thought I'd share for reference:-

  • Bitmap.createScaledBitmap() always returns a bitmap of type RGB_565, regardless of the source bitmap.  See http://code.google.com/p/android/issues/detail?id=13038
  • ARGB_4444 is now depreciated, so you'll always need to use ARGB_8888 if you want to store transparency information.
  • When using BitmapFactory.decodeFile(), always try to pass a BitmapFactory.Options().inPreferredConfig to ensure you get a bitmap in the format you need.  By default, bitmaps loaded this way are always immutable (uneditable), so you'll need to do a Bitmap.copy() if you need to make it mutable.
  • Bitmap.recycle() is ALWAYS required; if you create a bitmap but don't recycle when you're finished with it, expect to run out of memory eventually.  Setting bitmaps to null isn't necessary.

Wednesday, September 21, 2011

Fixing GRUB

Grub seems to be a constant source of problems.  After updating my Ubuntu I got an error along the lines of "grub may need sorting out for various reasons".  I hate it when it does that, because if it does go wrong, you're usually stuck without a computer and are thus unable to browse the internet to find out how to solve the problem, a'la Catch-22.  Needless to say, when I rebooted, I just got a completely blank screen, not even a cursor flashing in the corner.


Anyway, for my own reference, here's what I did (after booting from a LiveCD - what did we do before LiveCD's?)

Mount the disk:
sudo mount /dev/sdX /mnt


Re-install Grub:
sudo grub-install --root-directory=/mnt /dev/sdX
Obviously, change the sdX bit to point to your HD.
If you're a real masochist, you could try reading this.

Tuesday, September 06, 2011

How to be a productive programmer

Here's my humble checklist of what I think are the most important requirements for being the kind of programmer that can create something ultra-quickly.

* A stock of library code, built up over years so that simple and common tasks are already covered by a pre-written function or two.
* Be either the only programmer on the project or have your area clearly defined, and not be dependant on someone elses code that is still being produced.
* Have it clear in your head exactly what you are creating and how it is generally going to work.
* You have already "solved" any major technical hurdles that you know you are going to encounter.
* A quiet-ish place to work.
* A desire to actually create this program.
* Access to the internet to solve those niggly problems or to copy-and-paste code from websites.
* As a bonus, have a similar project that you previously created that can be easily subverted to the new task.

If you've got the above covered then you should be able to churn stuff out quickly, and then you can spend the rest of your time writing your own more interesting projects.

Tuesday, August 16, 2011

Megaproject #2: Worldcrafter

I call it a "megaproject" since I'm pretty convinced I can see this one through to the end without getting bored or sidetracked onto something else.

It's called Worldcrafter. In a nutshell, it's a 2D Minecraft-style game for Android. Yes! Another one! This is what it looks like so far, after about 5 days since I started (most of those days being spent trying to decide what to call it):-



Does the world need another Minecraft game? I'll let the world decide. What I like about writing this kind of game (and what I like about Stellar Forces) is that it's almost "modular". You (i.e. me) can play a bit, then think "ooh, wouldn't it be good if it did this". And then add it. However, the basic game is quite easy to get up and running, and that's the important bit when starting a new project: have something playable ASA-goddam-P.

Friday, August 12, 2011

Domain Squatters Can Die!

If you've ever tried finding a domain name for your new project, no doubt you'll have come across the problem of cybersquatters, the vermin that polute the internet with ad-farms by buying up any and all domains that might be remotely useful for anyone. The rest of us have to try and think up obscure domain names that still try and relate to whatever subject our website is about, and hope people will still be able to find our site on the net.

Of course, you can usually buy a domain back from them if you want, using one of the their very helpful "make us an offer" forms. Gee, thanks. You're doing mankind a service.

Friday, July 29, 2011

Software Patents Metaphor

I'm a chef, and I've just patented a new recipe: chips with *2* sprinkles of salt over them. So if I see anyone sprinkling between 1 and 3 sprinkles of salt over their chips, expect a letter from my lawyer.

-- Update --

I've just had an amazing idea: chips with 3! Yes 3! sprinkles of salt over them! I don't know how I do it. I might start to sell this new recipe over the internet, but of course it will take you more than 1-click to buy it.

Thursday, July 21, 2011

Tower Invaders: Hints'n'Tips


It was my deliberate intention to make Tower Invaders quite difficult from the start. I didn't want players to have to wade through loads of screens of baddies before they got to the challenging bit.

Anyway, here are some quick hints'n' tips for those who might be having some problems defeating the invaders. I like to think of the game as more of a puzzle or even strategy game. There is a lot of strategy involved in what at first seems to most simple of choices:-


* Position of towers is important!
Even though the invaders move from left to right (and back, and so on) covering the whole width, the position of the towers is still very important. Statistically, the invaders will be mostly above the middle of the screen, so that is the best area to place your pulse lasers. However, this also means that this is where the most bullets are going to fall; if you have the full version, shields are a good idea, especially on towers you've spent a lot of creds on upgrading.


* Sell towers that are about to be destroyed!
You will get the same amount of money back for a brand new tower as for one that's about to crumble. You do get more for upgraded towers, though obviously not as much as you paid for them. Wait until a tower is about to go belly-up before selling it.


* Keep Zappers to the side!
Since Zappers will always hit an invader, keep them out of the way of bullets. As mentioned earlier, the most bullets will fall in the middle of the screen, so you might as well build Zappers to the far sides, where they will have much less chance of being hit.


* Upgrade towers to limit your exposure!
It costs the same to buy two towers as it does to buy one and upgrade it. Even though an upgraded tower will shoot about 10% less than two basic towers, those two basic towers cover twice as much area, so they have twice as much chance of being hit by a bullet. Also, you'll need 2 shields to protect them. Of course, they will be able to incur twice as much damage, so things aren't always so clear cut.

Thursday, July 14, 2011

Android Apps: Minimum Price

After putting my first paid-for app on the market place, I noticed that the minimum price you can sell an app for in the US is 99c. This is strange, since it's possible to sell it for 50p, which is less than 99c. Isn't it usually the UK that gets the raw deal where price conversion is concerned?

Tuesday, July 12, 2011

My First Android Game!


I've just released my first Android game with the help of Dipper (who provided the graphics) called "Tower Invaders". It's a bit like Tower Defence mixed with Space Invaders, and (even though I say it myself) I actually quite like playing it, which is always a good sign.

It's free and available at https://market.android.com/details?id=com.scs.towerinvaders.main.lite. Let me know what you think!

Friday, June 10, 2011

Float.MIN_VALUE Craziness

Did I miss a memo? How can this be right:-

float f = Math.max(Float.MIN_VALUE, 0f); // Returns "1.4E-45" (i.e. Float.MIN_VALUE I think)

What? Maybe I missed something in the documentation that said "Please note that this function is crazy." Unless the logic of "closest to positive infinity" means that Float.MIN_VALUE is actually closer since it loops round backwards. I hope not.

Friday, May 27, 2011

Android Rect Confusion

Jesus christ! That's all I have to say on this subject. Apart from the following:-

In their wisdom, Google decided to give the Android function Rect.intersect() a side effect. Without reading the docs, you would naturally assume that something like:-

boolean b = rect1.intersect(rect2);

would be reasonably straightforward, returning true or false depending on whether the two rectangles intersected. However, if it returns true, it also sets rect1 to be the shape of the intersection. WTF?? Wouldn't calling the function something like getIntersect() be a good idea?

There is a function called Rect.intersects(), which does do what you'd expect (and avoids doing what you wouldn't expect); so just remember to add that little 's' at the end of the function name because it makes all the difference.

Tuesday, May 10, 2011

I got the call!

Last month I got an email from someone at Intel asking if he could call me about porting Stellar Forces to work on AppUp. We did, and had a quick chat about it and AppUp in general, which seems like Intel's take on the AppStore/Marketplace. I checked out the documentation that was emailed to me, and looked at the website. It wasn't going to be a small job, they obviously weren't going to pay me to do it, and it's a free game so I make no money from it anyway.

However, eventually I came to a page that listed the Java SDKs, and noticed the lack of a Linux version. I sent an email back to confirm if this was the case, which would be a showstopper for me. That was about 4 weeks ago and I've still not had a reply.

It's a bit crap that they expect me to spend the time converting a game to their system (without any financial benefit) but they can't even be bothered to send an email as soon as there's nothing in it for them.

Friday, February 25, 2011

Dependency Hell

I seem to be stuck in Dependency Hell when trying to write some Java code that will compile Java source; I'm trying to use Apache JCI but it's turning into a nightmare. Here is the list of all its dependencies, which need to be downloaded one by one (at least, I can see nowhere where they are all included in one nice download).

But unfortunately, at least one of the dependencies (as I could see no point looking for any more) doesn't exist, and I can't find it after lots of Googling. So, as far as I can see, there is no way to use Apache Commons JCI.

Thursday, February 17, 2011

My Adage

Everyone else seems to have one, so here's my "programming adage":-

"The worst thing you can do as a programmer is write new code."

Discuss.

Tuesday, February 15, 2011

A Bite at Java Bytes

After using Java for so long, I'm still surprised that you can't write something like:-


public byte addNums(byte a, byte b) {
return a+b;
}

// Call the function:-
addNums(1, 2); // Get a compiler error??


The compiler error is because the 1 and 2 are ints by default, and the function is expecting bytes. Surely it must be able to work out that 1 and 2 are bytes in this case, not ints? To get it to compile you need to write:-

addNums((byte)1, (byte)2); // Get a compiler error??

I don't normally mind verbose code as long as it adds information for the programmer, but this is pointless.

Tuesday, November 30, 2010

Databases and Threads

The usual disclaimer applies to this post: millions of people probably already know this, and will be thinking 'What? And you call yourself a programmer??'

What could possible be wrong with the following function:-

public int RunIdentityInsert(String sql) throws SQLException {
Statement stmt = (Statement) conn.createStatement();
stmt.execute(sql);
return getScalarAsInt("SELECT @@IDENTITY AS NewID");
}

How about the bane of my programming life, threads? I've got loads of programs that have been running on servers for years using the above code, and mostly without a problem. Until yesterday.

My function added a record to a table containing about 6,000 rows, but the insert returned an id of about 250,000. It was only after looking at all the other possible reasons that this probably cause hit me: what if another thread ran another insert statement at pretty much exactly the same time? That would surely cause the same symptoms.

To be honest, I don't actually know if that was the cause, but it seems to me that the code should look like this:-


public int RunIdentityInsert(String sql) throws SQLException {
synchronized (conn) { // Need in case another thread also does an insert!
Statement stmt = (Statement) conn.createStatement();
stmt.execute(sql);
return getScalarAsInt("SELECT @@IDENTITY AS NewID");
}
}

Wednesday, November 03, 2010

Why I like Java:

Because when I wrote a slow crap program, everyone blames the language and not me!

Thursday, July 22, 2010

The P*ssed Off Blog - Munin

I now update this blog rarely, and the only time I will probably write here is when I'm COMPLETELY P*SSED OFF with some software or other. And today it's Munin, a program to profile server, like network and CPU usage etc...

It seems like a great program, and worked great on my local VM which is running an old-ish version of Ubuntu (Hardy Heron, 8.04) and version 1.2.5 of Munin in Synaptic. I had it up and running in minutes thanks to this article.

Of course, you might have an idea what's coming; it's what happens with most great software programs: the programmers don't know when to STOP F*CKING AROUND WITH IT and start adding/removing features and generally making something that "just worked" into a friggin' nightmare to use.

After I installed Munin (1.4.4) on the latest version of Ubuntu (Lynx, 10), I ran into problems trying to run it. Unhelpfully, when trying to run Munin as root, it comes up with the message "this program will break if you run it as 'root'...". Jesus, I'm not some n00b. Anybody who wants to run something like Munin is not a casual computer user, and knows the problems associated with running everything as root. But no, the programmers of Munin obviously think they know better and want to protect us from ourselves (and getting any work done).

The older version of Munin has a switch (--force-root) to over-ride this. But that was too helpful so THEY'VE TAKEN IT OUT. Thanks a lot. The message does come with some help: "run it as user 'munin'". Erm, ANY CLUE AS TO WHAT THE PASSWORD MIGHT BE? No? Thanks for nothing. I've tried "munin" and blank, but no joy and Google doesn't seem to be able to help me either. I'm not even sure that would work anyway, as the file referred to in the "permission denied" error I get is owned by root. So do I have to chmod loads of seemingly random files to allow user 'munin' to edit them? Surely that's no way to have a secure system?

So to sum up, I got the older version working in about 5 minutes, but so far I've spent a couple of hours on the new version and got nowhere. Thanks, munin programmers, for taking Munin backwards. I won't be using Munin again, but that's more because I COULDN'T IF I WANTED TO than due to any principles and animosity.

Thursday, April 01, 2010

Eclipse and Subversion [SOLVED]

This is mainly a note for future reference for myself, since I always seem to have an ABSOLUTE F*CKING NIGHTMARE trying to get Subclipse working on any new install of Eclipse. Thankfully it seems to have got better in the last few months now that Eclipse automatically finds dependencies, and you don't have to realise that Subclipse requires Buckminster, Buckminster requires ECF, and ECF requires Equinox until YOUR HEAD EXPLODES.

Anyway, now all it seems you have to do is select the Tigris update site as per here and select all the Subclipse components.

Then finally, for the magic step that makes it all work that took me about 3 hours searching the internet for, you have to right-click on your project and select Team -> Share.

(Why it couldn't realise that a project is already in subversion by seeing if there were any .svn directories is something I can't answer. There may be good reasons for this).

Friday, January 08, 2010

Developing a Community

One thing I always aim to achieve with my games is developing a community around them. This has pretty much eluded me (at least to my standards) until now, as there there is a small community playing Stellar Forces.

However, I'm confused. I've just looked at the main page of a new game called Mule, which is an online remake of an old C64 game (which I've never played, BTW as I'm an old Speccy user and it would be against my religion to do so). As far as I can tell, it's only been going since December last year, and it already has over 8,000 registered users! There other stats are impressive to - 1,600 forum posts, 2,800 games played etc...

So my question is "What are they doing to get that many users?" It's obviously a far more polished affair than my own effort - is that it?

Monday, January 04, 2010

Use of Overriding Methods Considered Harmful

I've come to the conclusion that overriding methods is a bad idea.

You know the situation; you've subclassed another class, which has a method in it that's not quite perfect, so in your subclass you write another method (giving it the same parameters) that does something slightly different.

Cue several months later, and you innocently edit the method in the parent class, changing the method parameters. Suddenly bugs appear left right and centre. "But how?" you ask yourself.

Well, it's because the method in the subclass is now never called since the method signature is different to the parents signature. But how were you supposed to know? Exactly!!

Tuesday, December 15, 2009

Making Money from Open Source

After discussing the above on the Freegamer forums, I thought I'd start a brief list of ways to make money from Open Source, if only for my own reference:-

  • Put adverts onto your website
  • Ask for donations
  • Offer to implement features
  • Create virtual merchandise
  • Sell "acheivements" and "player upgrades"
  • Unlock features
  • Sell merchandise
  • Sell your community
  • Provide an offline version of the game (for free) but require a small payment for anything other than token access (e.g. unrated friendlies) on a PvP server.

Some of these are similar and are along the lines of "allow players to pay for more features".

The main obstacle to all of these is having a game popular enough so that people will actually pay money. Suggestions for solving this problem on a postcard please...

Friday, November 27, 2009

New Stellar Forces Client and new Forums

A new version of the Stellar Forces client has been uploaded (0.35), and I can also announce that we have some new forums, linked into the Stellar Forces website (so users don't need to log into a seperate website to be able to chat).

See the Stellar Forces blog for more details.

Monday, November 16, 2009

New Stellar Forces Blog

Since I'm hoping that Stellar Forces is going to become my raison d'etre, I've created a whole new seperate blog for it. I've got loads of ideas and thoughts to discuss about it, and people who may be interested in it may not want to have to wade through all the other random blog entries that I produce.

Thursday, November 12, 2009

Stellar Forces Released


I've just released the first alpha version of Stellar Forces, my 3D squad-level multi-player turn-based strategy game. You control units in the traditional turn-based way, and take turns with your opponent. There is also a website that acts as the control panel for games.

It is alpha, so although I've tested it there are bound to be bugs and the game balance may not be perfect. I would just like a few playtesters to start using it and provide me with constructive feedback about what can be changed and improved.

In "hallway testing" style, I'm keeping my details brief so that if there are any confusing or unexplained aspects to the game, people will let me know and I'll add more details to the instructions.

http://stellarforces.no-ip.org

Anyway, let me know what you think!

Tuesday, November 10, 2009

Stellar Forces: Almost ready!

I've been a bit busy lately, what with having a new baby son, but have somehow still found time between bottle feeds to write the final bits of code to Stellar Forces.

I've just got a bit more testing to make sure it's robust, and then I'll announce it formally and let people loose on it. I'm hoping that these beta-testers will be able to help me tweak the balance of the game. With a game as complex as this (it's like multiplayer stand-alone missions from X-Com) there are so many variables (unit stats, weapon stats, mission objectives, map layouts) that it will take several games to get it right.

The game also has it's own website which stores a history of everyone's games, so there will be league tables, stats pages, and I'll maybe even do proper competitions sometime. The options are endless.

Monday, November 09, 2009

Java: Forgetting to override .equals()

This one always catches me out. I have a bunch of icons in my program, all extending the Rectangle class (seems like common sense to me). However, I don't actually fill in the dimensions until I've got the full list of icons (stored in an ArrayList()) so they are all zero-sized rectangles.

Before I add each icon to this list, I check whether it's already there:-

public void addIcon(Icon icon) {
if (iconlist.contains(icon) == false) {
iconlist.add(icon);
}
}

Have you spotted the problem? Since the dimensions for the icons are all zero, and the contains() function uses the equals() method of the icon class, then once one icon is added to the list no others will be. This is because the Icon/Rectangle class' equals() method compares the dimensions, and thus all my icons are actually equal, so it thinks that the icon list already contains the said icon. (That all seems very verbose for what is quite a simple problem).

Note to self: Always override the equals() method.

Thursday, October 22, 2009

Links About Game Design That I Fully Intend To Read But Don't Currently Have The Time

http://critical-gaming.squarespace.com/blog/2009/7/7/for-the-scale-of-balance-pt4.html

http://www.sirlin.net/articles/slippery-slope-and-perpetual-comeback.html

http://blog.wolfire.com/2009/01/game-theory-applied-to-game-design/

Monday, October 19, 2009

The Spectrum Got There First!

Did it? Well yes actually, it did. You name the genre and you're pretty much guaranteed that the first game of that genre was available on the Spectrum (or maybe ZX81). And here's a few examples to prove my point.

Let's start with the biggy, probably the greatest breakthrough in gaming this century (or maybe the end of the last one). I'm talking about GTA3 of course, what everyone thought was revolutionary.



That is, apart from me. I thought I was having a bout of terminal deja-vu when I saw it, and was nostalghically transported back to the mid 80's, when I was playing the classic Turbo Esprit:-



Next, Wolfenstein is held up as the start of the FPS genre. Frankly, I was hoping it was the end as I was already bored of FPS'ing.



The start for me was 3D Monster Maze, almost 15 years (count'em!) earlier:-

Detractors will say "It didn't have any shooting in it!". I reply "Well, that's pretty revolutionary in itself!".

Just like Wolfenstein, Dune II is held up as the first of the RTS genres. (I've no idea what happened to Dune I).



But RTS's had been around for years already - if you owned a Spectrum (and probably most of the other popular 8-bit machines). However, Stonkers came out on the Spectrum first, and for that reason we can gloat.


And before you ask, yes, it does have resource collecting!

Last but not least is genre that never quite goes away, it's the top-down dungeon crawling game. I could have included a picture of Diablo here, but let's be fair and show Gauntlet, what many people claim to be the first (apart from those who claim it was The Dandy).



Of course, both of those people are wrong. The first game was Maziacs, and it came out on the Spectrum first (as if you needed to ask).



So if you're a games programmer working for a large megacorporation with a massive marketing budget but precious few original ideas, why not plunder a few from the Speccy back-catologue and claim them as your own?

If you can think of any more, please let me know and I'll do a "part 2" or something.

Tuesday, October 06, 2009

Pushing the bounds of technology

Like all people, I wonder what will happen when I die. And being a programmer, I came to the obvious conclusion: store my consciousness in a program that will live on in cyberspace in perpetuity!

So, after literally minutes of messing about, may I present the "Me" applet:-



Now you will able to communicate with me forever through the power of Java. Now if I can just hook it up to Blogger, I can keep writing blog entries long after they stop being funny!

Monday, October 05, 2009

Tips on maintaining your own interest in your own project (#1 in a series)

If you are sure that the game will be a good, entertaining game, then try to complete as much of the programming as possible before actually playing the game*.

(* This entirely contradicts my previous advice of "get the game up and running as soon as possible so you have something to play". I've decided that once you have something to play, the remaining programming tasks consist of the boring tidying-up programming, which has very little reward since you already have a game to play. My new advice is to keep programming all the little bits and pieces first. In addition, doing it this way will mean your original vision will remain in your head, and not be replaced by interest-sapping the catastrophe with temporary-and-crap graphics that you have programmed**.)

(** I hope this makes sense.)

Thursday, October 01, 2009

3D is hard!

During moments of niavity (sp?), I sometimes think that 3D should be easy and I'm just going about it the wrong way. Surely it's just like 2D, except you have to adjust for depth as well?

Unfortunately, it's nothing like as easy. For a start, with 2D, all your co-ordinates have a common origin, usually the bottom left, and you can tell whereabouts a sprite is in relation to the origin. With 3D, the origin could be anywhere, and usually each model seems to have it's own. In addition, working out where the origin is can be difficult, since it depends on where your camera is and what direction it is looking in.

You might have two 3D models, each facing zero degress (or radians, assuming you haven't got them mixed up again). But one is facing one way and one another. And their direction might change depending on the frame of animation they are in.

And why can't I see anything? Is the camera outside the scene looking outwards again? Or is it looking directly down, which seems to cause problems and make everything disappear? Or are the objects slightly too far away to see? Or maybe I need to add lighting to the scene. And why is one model approximatly 3 million times bigger than the other? Time to scale the models down a bit and then wteak their height so they are standing on the floor and not in it.

And why does my model move whenever I move the camera? Oh, I've forgotten that when I have a unit with a position of Vector vec, and I then do camera.setLocation(vec), it is using the same actual object (vec) for both the unit's location and the camera's location, so when one changes, so does the other. Grrr!

Monday, September 28, 2009

Potentially Useful Functions (#1 in a series)

The original aim of this blog was for me to impart my knowledge of programming, or for people to point out bugs and problems with my code. Either way, it was supposed to be about programming rather than subliminal advertising for my games.

This post aims to correct that, so to get things started here's two nice small graphics function that someone somewhere may find useful:-

This one rotates an image:-


public static Image rotateImage(Image inputImage, float ang_deg, ImageObserver ob) {
BufferedImage sourceBI = new BufferedImage(inputImage.getWidth(ob), inputImage.getHeight(ob), BufferedImage.TYPE_INT_ARGB);

Graphics2D g = (Graphics2D) sourceBI.getGraphics();
g.drawImage(inputImage, 0, 0, null);

AffineTransform at = new AffineTransform();

// rotate 45 degrees around image center
at.rotate(ang_deg * Math.PI / 180.0, sourceBI.getWidth()/2, sourceBI.getHeight()/2);

// instantiate and apply affine transformation filter
BufferedImageOp bio;
bio = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);

BufferedImage destinationBI = bio.filter(sourceBI, null);

return destinationBI;
}


And this one scales an image

public static Image scaleImage(Image inputImage, int w, int h, ImageObserver ob) {
BufferedImage sourceBI = new BufferedImage(inputImage.getWidth(ob), inputImage.getHeight(ob), BufferedImage.TYPE_INT_ARGB);

Graphics2D g = (Graphics2D) sourceBI.getGraphics();
g.drawImage(inputImage, 0, 0, null);

AffineTransform at = new AffineTransform();

// scale image
float sx = (float)w / (float)inputImage.getWidth(ob);
float sy = (float)h / (float)inputImage.getHeight(ob);
//at.scale(w / inputImage.getWidth(ob), h / inputImage.getHeight(ob));
at.scale(sx, sy);

//at.rotate(45 * Math.PI / 180.0, sourceBI.getWidth()/2, sourceBI.getHeight()/2);

// instantiate and apply affine transformation filter
BufferedImageOp bio;
bio = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);

BufferedImage destinationBI = bio.filter(sourceBI, null);

return destinationBI;
}



Needless to say, if anyone knows a better way to do this, or just tweaks to the above code, please let me know.

Thursday, September 24, 2009

A great idea, or maybe not

"Woah!", I hear you say. "Slow down young Steve. With all this blogging, you're going to burst one of the tubes!". However, I thought I'd mention a great idea I thought I had. See if you can spot the flaw.

I didn't watch Derren Brown pretend to predict the lottery, but his suggestion of using the Wisdom of the Crowds gave me an idea - why not create a website where people can enter their prediction for the numbers. The website will then show the average of everyone's numbers, and people can use those numbers for their actual choices!

Any mathematicians out there may spot the flaw sooner that the rest of us. So let's save me lots of time and programming and all just choose the numbers 24, 24, 24, 24, 24 and 24.

Changed my mind

Instead of Interstellar Forces, I'm going to call it Stellar Forces. Don't you go registering the domain you rascals!

Here's a picture of the website to celebrate the change of name:

Wednesday, September 23, 2009

Announcing: Interstellar Forces

I've finally though of a title! "Interstellar Forces" - mark its name my friend as you will (hopefully) hear a lot more about it in the future.

I've now nailed down the HUD, with its Terminator (as in Schwarzenegger) style text, and the Terminators (as in WH40k) for the models. I might replace these from some of those in UFO:AI though, as I think the licence allows this.

One thing that crossed my mind now that I've got to the stage of a 3D applet is all the other possibilities that have opened up for this code; I could turn it into a 3D RTS like Starcraft III, or write a Diablo clone, or anything my evil mind might think up.

Monday, September 21, 2009

I'm getting that fimbly feeling

There comes a time in a project (especially the more ambitious kinds) where it suddenly seems like you've managed to overcome all the major hurdles, and it actually will be possible to complete the game. This is also usually combined with the stage at which the project starts to take shape and you have something nice to look at. It's a great feeling, and it occurred to me when I produced the screenshot you see here, for my still un-named game.

The only drawback is that it's usually soon after this point that there are no challenges left, and the rest of the programming is boring donkeywork with no payoff until the project is completed. This is usually the stage where I lose interest and move to something else. Not in this case though.

Maybe it's because it's my favourite genre (squad-level turn-based strategy game) and I've got the inspiration of Laser Squad and LSN to look at, and it's going to be multi-player, but I feel like I'm going to see this one through to the end. Then the challenge will be the hardest one yet - getting people to play it!

Wednesday, September 16, 2009

My Magnum Opus

I've been a bit quiet on the blogging front lately, but there's a good reason: I've been working on my latest project, and I'm pretty excited about it.

In a nutshell, it's Laser Squad Nemesis with Laser Squad Mechanics (i.e. properly turn-based rather than We-Go). I hope no-one groans at that, wondering why I'm just copying another game. In my defence, AFAIK there is no open-source equivalent (or even closed-source). The main reason I'm doing it is because my most enjoyable gaming session was playing Laser Squad all day against one of my friends. It's a brilliant game, and never gets boring against a human opponent.

It should be noted that I've never actually played LSN; the only aspect I am copying is the fact that you can request games and play them against other people, while a server keeps track of it all. In addition, it's going to be a 3D applet (as the pre-alpha screenshot with the slightly broken z-order will testify) allowing the player to move their camera anywhere around the map.

So, it will come with it's own web front-end which will allow people to request/join games, take their turn, post messages, update halls of fame etc... Once a game has been accepted, players can equip and deploy their units and then take turns trying to fulfill their mission objectives. Needless to say, there will be several different kinds of missions, each with it's own special units like robots, aliens or plain old space marines (obtaining good 3D models notwithstanding).

This is a pretty ambitious project, incorporating a web server, 3D applets and networking, but if it will produce a game which allows me to play turn-based squad-level strategy games, then it's a task I'm looking forward to. And suggestions for a name for this game are more than welcome!