Archive

Monthly Archives: August 2013

Updates:
1.8.1:
– Fixed crash when capturing while media scanner was at work
– Added option to get a debug log to help me figure out what breaks!

NOTICE: I’m working on bringing back compatibility with Android 2.3.3 Gingerbread phones. If you own such a device and would like to test a build for me, let me know!

I was on the Google Play store today and I saw that a search for “Pebble Camera Remote” returned no results. This got me thinking… I can do that!

So I spent a good afternoon getting back into Android and Pebble developer kits to produce the first 1.8.1 version of what I have dubbed “Watch Trigger” – an app that lets you use your Pebble watch as a remote control! This means you can do what you’d normally do when taking a timed photo, but you don’t have to rush back to the group in ten seconds, you can press the watch button as quickly and discreetly as you want.

Once the app is installed, you can install the watch app by pressing the ‘Install Watch App’ button, then relaunch the Android app. As shown on the Pebble app, pressing SELECT will cause the phone to take a photo and save it to “/sdcard/Watch Trigger Images/ImageX.jpg” anywhere in the external storage you want. The name of the photo taken will then be confirmed on the phone and the watch, so you can go back and pick it up again:

shot1shot3

watchapp

So now it is possible to take a photo using the Pebble watch as a remote!

Special mentions

In adding a button to install the companion watch app from within the Android app, I used a method written by Robert Meijer, which I found on GitHub – an elegant solution. Thanks Robert!

Known bugs/issues

  • Only portrait orientation at the moment, but landscape if you rotate the photos post-shoot.
  • Cropping of the preview surface, but NOT of the resulting photo. I’m not sure how to rectify this at the moment, but if programming has taught me anything, its that virtually anything is possible.
  • Low default output resolution
  • Storage location not always /sdcard0/ on all devices
  • Crash when taking photo while the previous one is being saved
  • Flash does not always fire
  • Crash when triggering if media scanner was still running
  • Let me know any you find!

Download
Get it on Google Play

Enjoy! As usual, please leave your thoughts and suggestions below!

Advertisements

So I’ve had an idea in my head for a while that has probably been done before, but as I’ve already mentioned, I prefer to do everything I can from scratch when it comes to programming, which takes time, but is incredibly rewarding when what I strive for comes to life as I imagined.

This particular idea is for a real-time space RPG, the main mechanic being that you set a course and a speed, and it might take a few real-time minutes to reach your destination, such that you would play the game ongoing in the background for something else you are doing, similar to an MMO.

I’ve attempted this before, and the main difference in having a game world many times larger than the screen is that you must position everything relative to some abstracted co-ordinate system completely separate from where each item may be drawn on the actual screen. This was achieved before by drawing each item if it was less than a screen width or height away from the player’s drawing location in the middle of the screen, then whenever the player moved it’s ‘co-ordinate’, all the other in-game items moved in the opposite direction, very effectively creating the illusion of moving through a world, even though the player’s sprite stays put on the screen.

This feeling was further enhanced by moving the player’s ‘co-ordinate’ using the sin/cosine of the speed and angle, allowing the player to appear to move in large smooth, sweeping arcs.

With my new skills from recent projects still fresh in mind, I set out to make this a much tighter experience, with some more intuitive input system beyond WSAD keyboard keys. I envisaged a speed slider, and a ‘ring slider’ around the player in the center of the screen, allowing a course to be set and speed to be set by dragging them. As everything is done on a Graphics2D enhanced Canvas component, using pre-written Swing sliders is out of the question, so I set out to recreate these UI elements from scratch to be drawn using Graphics2D methods.

The linear slider was fairly easy, using the mouseDragged() method from the MouseMotionListener class. Position the slider where the user clicked (x co-ordinate only!) as long as it was between the slider’s start and finish positions.

So far so good.

But the ‘ring slider’ required much more thinking about. I first attempted to use counters and quadrant detection of the existing angle position of the ring, but this was way too complex. Then as I was thinking about something else, the answer came to me: use GCSE maths! Specifically, the circle trigonometry stuff. It all came down to this: circletheoremSo using the mouse’s dragging x co-ordinate, I can find the corresponding y co-ordinate for that point around the ‘ring slider”scircle. From this, the angle (theta, θ) the slider should be set to can be found using the tangent:

arctanBut this only works up to 90 degrees using tangent (which is actually infinite at 90 degrees), so the calculation is carried out subtly differently depending on which of four quadrant rectangles the user is dragging in, after which the resultant 0 – 90 angle is adjusted to read what it should in the quadrant:

quadrantssrc

Here is the code for calculation of the angle of the ‘ring slider’ in quadrant 0:

//Setup quad rects for ring slider of any bounds x, y, width & height
quad0 = new Rectangle(x + width/2, y, width/2, height/2);
quad1 = new Rectangle(x + width/2, y + height/2, width/2, height/2);
quad2 = new Rectangle(x, y + height/2, width/2, height/2);
quad3 = new Rectangle(x, y, width/2, height/2);

//Test user click - 2x2 rect around mouse pointer location
Rectangle thisRect = new Rectangle(inCurrent.x - 1, inCurrent.y - 1, 2, 2);

//Show angle
if(thisRect.intersects(quad0))
    thisQuad = 0;
else if(thisRect.intersects(quad1))
    thisQuad= 1;
else if(thisRect.intersects(quad2))
    thisQuad = 2;
else if(thisRect.intersects(quad3))
    thisQuad = 3;

switch(thisQuad) {
    case 0: {
        float adj = inCurrent.x - quad0.x;
        float opp = (quad0.y + quad0.height) - inCurrent.y;

        double theta = Math.toDegrees(Math.atan(opp/adj));
        angle = 90 - (int)Math.round(theta);

        //Range control
        if(angle < 0)
            angle = 0;
        if(angle > 90)
            angle = 90;
        break;
    }
    //Then the other quads for cases 1 through 3...
}

The end result of all this, together with a spawning starfield of stars (who move proportionately to their size to create the illusion of depth) is this (Click to enlarge):

inactionI realise that a simple image isn’t that exciting, so if you want to play around with these UI elements and see the whole demo in action, here is an executable bundle!

The last couple of weeks I haven’t been posting anything interesting, mainly due to a new project I’m spending a lot of time on, which is very exciting. I’m working with a friend to create an open-world RPG basically from scratch, and working on it has given me lots of opportunity to problem-solve, develop my coding practices and go to new places I wouldn’t have gone otherwise.

A summary of highlights so far, which I may cover in separate detail posts are:

  • Triple threaded engine (Logic, Renderer, Occlusion) using Java2D
  • Tile based maps with three layers loaded by a tile sheet parser that splits up a single image of tiles into single sprites for use by each map tile.
  • Any-size maps with aggressive occlusion (drawing only those tiles that need to be), enabling smooth 60 FPS motion even at 1920 x 1080.
  • Animated Player and NPCs that similarly have their animation frames dynamically loaded from external sprite sheets composed of individual frames.
  • Thread driven scripts and events using a bespoke language that are interpreted and acted upon at run-time.
  • Map files are read into a bundle that then exposes it’s data to the game, ensuring only the correct data is available, and the game cannot accidentally corrupt a map file.
  • A dedicated map maker package that enables creation of these maps, adding events, NPCs and map-to-map jumps.

Stay tuned for more information!