Pages

Sunday, 22 July 2012

Delphi IDE productivity keystrokes

The other day I posted about a talk I gave at a User Group meeting that focused on Delphi IDE keystroke shortcuts (mostly code editor features and shortcuts). After processing my simple notes list and adding in comments and links to the documentation where appropriate I’ve come up with what we see in this post.

This represents the list of my favourite keyboard shortcuts (and related features), some of which have been available since Delphi1, some added in the most recent versions and many more added at various points in between. I hope you can find some useful additions to your Delphi coding arsenal in this collection. Note that the list is mostly keystrokes, but the mouse is mentioned here and there. I do find having a wealth of keystrokes available to call upon helps me be efficient in use of the Delphi IDE.

Without further ado, here’s the list:

Code Insight, mostly added in Delphi 3. Some of these can be enabled or disabled as you choose in the Code Insight page of the Tools, Options dialog:

Code Completion. The (resizable) popup list we often see automatically, but which can be forced up when required. Ctrl+Space
Code Parameters. The tooltip that shows the names and types of the parameters required in a parameter list, with the current parameter shown in bold. Again, this often comes up as required but can be forced up when the cursor is in a parameter list using this keystroke. Ctrl+Shift+Space
Code Templates (now called Live Templates). Very under-used mechanism for auto-entering a block of often-entered text. The IDE ships with a bunch of predefined Code Templates and you can define your own also (which is where the real benefit comes in). Originally the Code Template definition was quite trivial, but since the introduction of Live Templates in Delphi 2006, the definition is now in XML and a little cumbersome, but is covered in the documentation. Ctrl+J
Tooltip Help Insight. This pops up when you hover over a symbol giving you information on it. If that symbol has XML documentation comments (XMLDOC comments) defined for the item, or its parameters, these will be included in the help popup. XMLDOC comments can be readily entered in Delphi XE2 by the included product Documentation Insight Express. Ctrl+Shift+H
Tooltip Symbol Insight. This is enabled by default, but so is Tooltip Help Insight, which takes precedence. Disabling Help Insight allows this to work – it shows some declaration and type information for the symbol under the mouse cursor hover mouse over a symbol
Tooltip Expression Evaluation. In debug mode, hovering the mouse over an identifier or a selected expression will evaluate it. If the expression yields an object then the tooltip will allow you to drill down into its constituent members. hover mouse over a symbol or highlighted expression in debug mode
Class Completion. If a class has a method declaration, this will enter the implementation if pressed with the cursor within the class. If there is a method implementation this will enter a corresponding declaration. Given a minimal property declaration (e.g. property Foo: Integer;) this will declare a private backing variable and a setter that assigns its passed value to it and extend the property declaration accordingly. Ctrl+Shift+C
Block Completion. This typing saver finishes code blocks for you. Enter
Error Insight. This is the name for the squiggly red lines in the code editor indicating where a background compilation has detected errors in the source. The errors are also listed in the Structure window in recent Delphi versions. As we have all seen over many recent versions, after a few compilations, Error Insight leaves various perfectly valid and compilable expressions marked with red squigglies and most people get quite irked by it, essentially paying no attention because of its lack of reliability. The tip here is to go to the Code Insight options and turn Error Insight off.  
Code Browsing. When you hold the Ctrl key down and move your mouse around the code editor, any item whose declaration can be located turns into a hyperlink and the mouse cursor indicates clicking it will take you somewhere. In short, Ctrl+click will take you to a symbol’s declaration or definition. However that involves the mouse, so there is another keystroke that is less commonly mentioned for this. Alt+Up
Browsing History. Once you start code browsing, these keystrokes allow you to go back and forth in the browsing history. Alt+Left and Alt+Right

Method hopping, i.e. jumping from one method to another within a source file:

Scroll through methods Ctrl+Alt+mouse scroll wheel
Toggle class lock. Normally method hopping goes through all methods in a file. This toggles a lock on just hopping through the methods of just the current class. Ctrl+Q, L
Move to top of current method or to previous method (unless your graphics driver software takes the keystroke to orient your monitor display to the natural orientation) Ctrl+Alt+Up
Move to next method (unless your graphics driver software takes the keystroke to orient your monitor display upside down) Ctrl+Alt+Down
Move to first method in file Ctrl+Alt+Home
Move to last method in file Ctrl+Alt+End

Regions and code folding. Regions are great for hiding away code sections that you don’t want to see when scrolling around in your code. They are a special case of compiler directives that each adds in a new code folding area.

Collapse current foldable code block or region Ctrl+Shift+K, Ctrl+Shift+E
Expand current foldable code block or region Ctrl+Shift+K, Ctrl+Shift+U
Toggle code block collapsed state Ctrl+Shift+K, Ctrl+Shift+T
Collapse all regions Ctrl+Shift+K, Ctrl+Shift+R
Collapse all nested procedures Ctrl+Shift+K, Ctrl+Shift+P
Collapse all methods Ctrl+Shift+K, Ctrl+Shift+M
Collapse all classes Ctrl+Shift+K, Ctrl+Shift+C
Expand all code Ctrl+Shift+K, Ctrl+Shift+A
Toggle code folding support Ctrl+Shift+K, Ctrl+Shift+O

Miscellaneous editor keystrokes:

Drop (or remove) bookmark – seems to be a bug that one keystroke option doesn’t handle bookmark 0 Ctrl+Shift+1-9 or Ctrl+K, 0-9
Go to bookmark Ctrl+0-9 or Ctrl+Q, 0-9
Module navigation (a name which appears to have been dropped from the documentation over recent releases). The keystrokes take you from a method declaration to a method implementation or vice versa (either keystroke does both jobs) Ctrl+Shift+Up or Ctrl+Shift+Down
Code formatting Ctrl+D
Indent marked block Tab or Ctrl+Shift+I or Ctrl+K, I
Unindent marked block Shift+Tab or Ctrl+Shift+U or Ctrl+K, U
Insert new GUID Ctrl+Shift+G
Go to line number Alt+G
SyncEdit. This is an awesome mechanism for intelligently updating an identifier name in a marked block. Also available via an icon in the editor gutter that looks like 2 pencils joined together. Ctrl+Shift+J
Open unit under cursor. Handy for looking at the VCL source when in a uses clause. Ctrl+Enter
Find references Ctrl+Shift+Enter
Insert compiler options at top of current file Ctrl+O, O
Delimiter match – pretty redundant in recent versions as the highlighting does this for you Alt+[ or Alt+]
Toggle case of marked block. For those of us who aren’t touch typists it’s very common to accidentally type quite a bit of text while Caps Lock is on. When you notice this just mark the block and use this keystroke. Ctrl+O, U
Delete word to left of cursor Ctrl+BackSpace
Delete word to right of cursor Ctrl+T
Delete current line Ctrl+Y
Start and stop recording keystroke macro Ctrl+Shift+R
Play back keystroke macro Ctrl+Shift+P
Comment current line or marked block Ctrl+/
Show list of open files Ctrl+Alt+F12
Incremental search. General search is no longer modal in recent IDEs Ctrl+E
Add to do item. I find this keystroke often gets mis-interpreted for some unknown reason, so I have to resort to a right-click in the editor followed by pressing E. To do list items (and the to do list itself) can be a handy way of keeping on top of notes regarding code you are building up. Ctrl+Shift+T
Move marked block mouse drag
Copy marked block Ctrl+mouse drag
Set focus to Tool Palette Ctrl+Alt+P
IDE Insight. The mother of all searching keystrokes – offers an incremental search through a whole bunch of parts of the IDE. Ctrl+. or F6

Form designer:

Select selected control’s parent Esc
Move selected component(s) 1 grid unit Ctrl+Shift+cursors or mouse drag
Move selected component(s) 1 pixel Ctrl+cursors or Alt+mouse drag
Resize selected component(s) by 1 pixel Shift+cursors
Lasso controls on a container (e.g. a TPanel) Ctrl+mouse drag

Object Inspector. Note that it’s quite possible to set a given property on a bunch of neighbouring components with very little mouse use. Select the first of the components (let’s say a bunch of buttons), click the target property (say the Caption property) and then click the first component on the form designer. If you simply type you will enter a value for the selected button’s Caption. Pressing Enter after having entered the value should take you back to the button on the form designer. You can use the cursor keys to then select the next button whose caption you want to set, then you can rinse and repeat as required. Additionally you can select the initial property by selecting the Object Inspector (F11), selecting the property name column (Tab) and then start typing the property name – it uses an incremental search. Tab then switches back to the property value column.

Select Object Inspector or go back to form designer or code editor F11
Switch columns Tab
Drop down component list Ctrl+Down
Switch between Properties and Events tabs Ctrl+Tab or Ctrl+Shift+Tab

Thursday, 19 July 2012

Free VCL to FireMonkey converter

[Edited now that I know more about the two editions of Mida and what is available from Embarcadero]

I’ve previously posted about the Mida converter that helps you move VCL code to the FireMonkey platform. The full version costs approximately US$130 or €99 and operates as a standalone application. The nice people at Embarcadero have got together with the Mida author and made available a free Mida Embarcadero XE2 Edition so you can get a flavour of how this tool works and what it can do.

This free version is available to anyone with a registered copy of Delphi XE2, C++Builder XE2 or RAD Studio XE2, either fully licensed or trial version and acts as an IDE plugin. It does basic conversions but stops short of handling third party components, advanced LiveBindings support, image conversion and source code conversion.

If you register for an online VCL to FireMonkey migration workshop being broadcast next Wednesday, 25th July 2012 then you’ll be directed to an alternative download link for this free Mida edition that is valid to use in any registered or trial version of Delphi XE2, C++Builder XE2 or RAD Studio XE2.

The 3 hour workshop is called Delphi and C++Builder Developer Workshop: Migrating VCL Applications to FireMonkey, will be delivered by Anders Ohlson, and will run at these times on 25th July 2012:

  • 6am PDT, 9am EDT, 1pm UTC, 2pm BST
  • 11am PDT, 2pm EDT, 6pm UTC, 7pm BST
  • 5pm PDT, 8pm EDT, midnight UTC, 10am (26th July) Australia EST

You can read about the workshop at this link and register for it at this link.

Monday, 16 July 2012

Delphi IDE Tips Session at User Group meeting

Today I gave a talk at the Maidenhead meeting of the UK Developers Group, for which I also acted as the M.C. (welcoming, running through the agenda, passing on any pertinent industry news, etc.). The talk was a re-run and update of a vintage session I last did at DCon 2000 and BorCon 2001, and the original conference papers are still available online through those links. Wow, those sessions were eleven and twelve years ago!

Anyway, since the last time I delivered this session there have been a whole heap of new Delphi versions so the main thrust of the session, a run-through a bunch of useful and time-saving keystrokes has now pretty much taken over the whole session.

The gist of the session was to point out that nowadays we have something of an attachment to our favourite pointing device, the mouse. The business of reaching for the mouse, moving the pointer to the right location and clicking can often be rather less efficient than coders of old that had no pointing device options and just rattled away on their keyboard. Making yourself more aware of some of the useful and convenient keystrokes can help make various processes more efficient in your Delphi coding life.

Most Delphi developers have a bunch of keystrokes under their belt, but there is always room for improvement, always an opportunity to pick up a few more helpful keyboard tricks.

During the session, whose content seemed to be lapped up by the Delphi developers there, I was asked if my keystroke list was available ass a document. Well, yes I had made a list of the more useful keystrokes to run through during the talk. I said I’d post them up on the blog here and that I will indeed do.

I am working through the list, adding some notes here and there to make the list more useful as a standalone item without my walking through it demonstrating it and putting things into context. So the list will be posted here some time over the next week, and I’ll come back to this post and add a link to it also.

So, apologies that this post is just a total tease, but the list itself is only partially useful until I’ve expanded it with some explanatory text. I’ll be back!


Update

As promised, I worked through the list and put in suitable context info for each of the items. You can find the keystroke list here.

Friday, 13 July 2012

Porting some Android SDK samples

As I mentioned last time, I’ve been porting some of the Java Android SDK demos over to Oxygene for Java. This is for various purposes:

  • to ensure I am on top of various Java code layout approaches. The one that requires the most faffing about is nested classes. In Java the nested class gets access to members of the outer class, thanks to having an implicit this parameter passed through the constructor. That requires a bit of manual rewiring, which is a bit of a bore, but no big deal.
  • to get some exposure to various additional Android programming areas.
  • to run more and more code through Oxygene for Java and report any latent bugs that show up when trying it out.
  • to build up more useful Oxygene for Java examples that can be packaged in with the product and thus be of reference use to Oxygene users
  • to find out what issues and bugs are lying in wait for unsuspecting newcomers to Android programming within the recesses of those SDK demos.

I’ve uploaded a bunch of them to Google Play now (see the end of this post) so anyone interested can check them out and report any problems left in there so I can try and remedy them. Of course they are demo apps and so you shouldn’t expect too much of them. They’re just there to demonstrate certain Android programming techniques and so aren’t professional-level applications.

In the last post I looked at the poor support for the exit-the-app-and-come-back situation with Lunar Lander and JetBoy. Well, poor support isn’t really accurate as the apps just crash out when you try and resume them. Poor implementation, poor planning, something like that perhaps.

Anyway, other common themes that come out of more demos are as follows:

1) Background image resources are not resized to accommodate screen sizes. Perhaps back when these demos were written, the various bitmaps used in AccelerometerPlay, JetBoy were larger than the largest of screens. Not now with tablets and large display phones.

In the case of an image on a game that will get an initial size on startup and not change, for example a game that is fixed to landscape or portrait orientation, then you can size the bitmap once after having loaded it. JetBoy is fixed to landscape orientation thanks to this attribute in its activity declaration in the Android manifest file:

android:screenOrientation="landscape"

Similarly the AccelerometerPlay demo is forced to portrait with this attribute in the activity declaration in the Android manifest:

android:screenOrientation="portrait"

If you draw in a View descendant, then override the onSizeChanged() method and you can resize the bitmap by passing it to the static Bitmap method Bitmap.createScaledBitmap() along with the target width and height, typically as passed in parameters to onSizeChanged(). For example, in the accelerometer demo I now have this:

method SimulationView.onSizeChanged(w, h, oldw, oldh: Integer);
begin
  // other stuff is here
  ...
  // Resize the background bitmap
  // NOTE: original code did not resize the background bitmap
  // so it did not cover the background on larger displays
  mWood := Bitmap.createScaledBitmap(mWood, w, h, true)
end;

If you’re working with a SurfaceView and have implemented the SurfaceHolder.Callback interface then you can do much the same thing in the surfaceChanged() method.

You can also choose to size the bitmap on-demand when it’s needed from its original size to the required size for the target canvas. This will be a little less performant than a one-off resize but can be useful. For example, the JetBoy app has a ready screen before play starts. The background to that screen was not resized appropriately. If you didn’t want to resize the background bitmap once ahead of time you could identify the current size and target size as Rect objects and call an appropriate override of the Canvas object’s drawBitmap() method:

method JetBoyThread.doDrawReady(aCanvas: Canvas);
begin
  var src := new Rect(0, 0, mTitleBG.Width, mTitleBG.Height);
  var dest := new Rect(0, 0, aCanvas.Width, aCanvas.Height);
  aCanvas.drawBitmap(mTitleBG, src, dest, nil);
end;

2) Older games were coded to assume the presence of a directional touchpad (D-Pad). Most modern devices come without one of these, so to make them usable on current devices I’ve had to add in onTouchEvent() overrides in either the View or Activity for simple screen touch responses. In the case of the Snake demo app I implemented GestureDetector.SimpleOnGestureListener to handle directional swipes.

3) Some demos have been updated over the Android releases to take on newer behaviour. For example, there is a simple Bluetooth Chat demo. You can install it and run it on two devices and the users can connect and do a simple Instant Message type chat. In the most recent SDKs for Android 4.0.x (Ice Cream Sandwich) this demo has been tweaked compared to what you see in the samples for the older Android versions. This newer version uses the so-called Holographic theme introduced in Android 3, which adds an ActionBar to the app as a side-effect. What are menu options in the earlier version are now ActionBar actions when installed on a more recent OS.

Also the newer version of the app offers both secure and insecure Bluetooth connections, something the original version didn’t as insecure Bluetooth connections were introduced in Android 2.3.3 (Gingerbread MR1).

The initial question was which version of the demo to bring over to Oxygene. In the end I got the translated app to operate on any Android version from 2.0 (Eclair) onwards.

To get the Holographic theme to be applied for Android 3 (Honeycomb) and later (and thus get the ActionBar) I took advantage of Android’s resource system (as mentioned here). I defined an app theme to be based on Android’s default old-school Theme in a resource file in res\values as per usual.

<resources
    xmlns:android="
http://schemas.android.com/apk/res/android">
  <style name="AppTheme" parent="@android:style/Theme">
  </style>
</resources>

But then I defined the same app theme to be based on Theme.Holo in a resource file in res\values-v11.

<resources
    xmlns:android=
http://schemas.android.com/apk/res/android>
  <style name="AppTheme" parent="@android:style/Theme.Holo">
  </style>
</resources>

If running on API 11 (Android 3.0 aka Honeycomb) or later the theme definition will be pulled from this latter directory. All that’s left to finish the job is to apply the app theme to the application in the Android manifest file:

<application android:label="@string/app_name"
             android:icon="@drawable/app_icon"
             android:theme="@style/AppTheme"
             android:debuggable="true" >

  ...
</application>

That’s the appearance. But it was also important to ensure the option for establishing an insecure Bluetooth connection was removed from the menu if running on Android earlier than 2.3.3. Since the menu is defined in a menu resource file this simply involved having two menu definitions, one in the usual res\menu directory and one in res\menu-v10. The menu definition in res\menu has the problem option removed; the menu definition in menu-v10 will be used on Android API 11 (2.3.3) or later and has all menu options defined.

The final aspect of keeping the app version-agnostic is to check the code and what relies on the newer aspects of the source. Anything that needs to be skipped on Android versions earlier than 2.3.3 can be conditionalised using Build.VERSION.SDK_INT, something like this:

if Build.VERSION.SDK_INT >=
     Build.VERSION_CODES.GINGERBREAD_MR1 then
begin
  ...
end;

Uploaded demos

Ok, so I’m done pulling Java code over to Oxygene and making it work properly for the time being. I’ve tidied up the demos that I’ve ported and uploaded them to Google Play, giving as useful a description as I can for each of them. The following are online – if you encounter any problems or have any simple improvement suggestions (bear in mind they are meant to just be ports of existing demos) I would appreciate hearing from you.

  • AccelerometerPlay: demonstrates the accelerometer sensor by representing a slab of wood with three shiny balls on it. Tilt the device and the balls roll in a quite realistic manner.
  • Bluetooth Chat: install on 2 Android phones and you can establish a connection (secure or, if on Android 2.3.3 or later, insecure) and have an IM-style chat
  • Cube Live Wallpaper: two live wallpapers. One is a rotating wire cube. One has a settings page to allow to to choose between a rotating wire cube and a rotating wire dodecahedron. On Android home screens that support it (not HTC Sense 3.0 or later, or Android 4.0 or later) the wallpaper responds to offset messages, meaning that the shape will rotate as you move from home screen to home screen.
  • JetBoy: a scroller game that demonstrates Android’s JET audio engine. Destroy a certain number of asteroids in a certain amount of time by firing in time to the music.
  • Lunar Lander: use direction and thrusters to safely land on the landing pad. I’ve mapped touches on areas of the screen (as per the app description on Google Play) to the D-Pad controls, but apparently it’s still a but tricky. This could just be a function of the game implementation, or maybe the D-Pad to screen mappings. Any thoughts, let me know!
  • Snake: The classic snake game. Swipe the screen to change the snake’s direction and reach the apples. Mind yourself and mind the walls!
  • Wiktionary ‘Word of the Day’ Widget: install on your home screen and you get Wiktionary’s word of the day displayed, along with the word’s definition. Touch the widget to open up a Wiktionary browser where you can follow links to other words, search for words or go to a random word.

The full set of Oxygene-ported Android SDK apps can be found at this link.

Alternatively all my Oxygene-powered Android apps can be found at this link.

Tuesday, 10 July 2012

Android game loops

I’ve been porting some of the Android SDK samples from their original Java over to Oxygene for Java, with the hope they’ll be included in a forthcoming update to the product.

I’d already contributed a port of the AccelerometerPlay demo, which is a neat little demo of using the accelerometer to control several balls on a surface (the screen).

Among other examples I’ve been looking at are the Lunar Lander and JetBoy demo games. Now, if you wanted to start writing a graphics frame-based game that used a SurfaceView as its output you’d think these would be a great starting point, right?

LunarLander

Wrong!

Well, kind of wrong anyway.

JetBoy

The games work ok and you can play them, although they both have the shortcoming that they were written back in the days when most devices had a D-Pad (directional pad) and/or physical keyboard. Consequently the original examples are unplayable on many current devices. That’s no problem – it’s not much trouble to add in support for touches on bits of the screen or swipes across or up and down the screen. Actually I had to add in swipe support for the Snake sample game, which also relied on a D-Pad, but since that one’s not based on a thread (being a simpler game it uses a Handler and its sendMessageDelayed() method).

The problem with Lunar Lander and JetBoy is with how their thread-based operation has been laid out. The JetBoy architecture was based on the simpler Lunar Lander and so both games suffer from the same problem. The symptom is that if you switch away, maybe by pressing Home or by a phone call coming through, and then switch back the game crashes out. If you look at a logcat from either app running and crashing you’ll find that the problem is an IllegalThreadStateException being thrown with the message:

java.lang.IllegalThreadStateException: Thread already started.

This doesn’t look like a very good basis for a couple of evidently appealing sample apps, being designed with a thread crash in… Clearly people will base their own games on these apps and be rather frustrated by this poor design.

Anyway, enough of the criticism. What’s the issue here? Well, a cursory search on the web shows this has (unsurprisingly) cropped up a lot of times and there have been various ways it has been responded to. So let’s look at the problem and the solution.

The games have an Activity whose UI is made up of a SurfaceView descendant. The game logic is contained in a Thread descendant. When the app starts up and the activity’s onCreate() method runs it creates the custom surface view and asks that view to create the thread.

The surface view has a couple of methods that mark the lifetime of the actual drawable surface: surfaceCreated() and surfaceDestroyed(). In surfaceCreated() the thread is set in motion with a call to its start() method. When the surface is destroyed, for example by switching back to the home screen, two things occur. Firstly a member field flag is set to indicate that the thread’s body (its run() method) should stop whirring round updating state and drawing frames. Then the thread’s join() method is called, which blocks the surface view thread until that run() method has done its job and exited.

Ok, with me so far? No evident problem so far. What happens when we switch back to the app?

Well, when the app’s UI resumes the surface view’s surfaceCreated() method is called, which calls the thread’s start() method to start it off again. And therein lies the nub of the problem. As the documentation states, start() will throw an IllegalThreadStateException if the thread has been started before.

Because of this coding scheme the Lunar Lander and JetBoy apps are set up to fail. So, what’s a good solution?

Well, I’ve tried a couple of options, some of which are frowned upon as not being the right way and settled for the suggestion of StackOverflow user Pompe de velo in this post. The changes required are as follows:

  • in the thread define member variables:
    • var mPauseLock: Object := new Object;
    • var mPaused: Boolean;
  • have the thread’s run() method keep iterating endlessly (while true do... instead of while mRun do...).
  • in this loop, after all the individual iteration’s physics update and frame drawing add:

    locking mPauseLock do
       while mPaused do
         try
           mPauseLock.wait
         except
           on e: InterruptedException do
             { whatever };
         end

  • if your thread already has pause() and unpause()/resume() type methods implemented then great. If not add them.
  • have the pause() method do this:

    locking mPauseLock do
      mPaused := true;

  • have the unpause() method do this:

    locking mPauseLock do
    begin
      mPaused := false;
      mPauseLock.notifyAll
    end;

  • in the activity’s onPause() method call the thread’s pause() method
  • declare a member field in the surface view:

    var mGameIsRunning: Boolean := false;

  • in the surface view’s surfaceDestroyed() method remove all the code relating to managing the thread
  • have the surface view’s surfaceCreated() method change the call to thread.start() to this code:

    if not mGameIsRunning then
    begin
      thread.start;
      mGameIsRunning := true
    end
    else
      thread.unpause;

Yeah, so there’s a few changes there, but once done the app can survive being switched away from and back to.

It would probably be a good move to take the fixed app, strip all the logic out and use it as a skeleton gaming loop app, which I may well do.

For now, I have more bugs to fix in SDK demo apps I’m porting over. Currently I’m getting on top of an issue with the BluetoothChat demo where exiting and restarting the app means connections from another device no longer show up on the UI. It would appear the Android SDK demos didn’t get a particularly good test through….. What’s more of a shame, though, is that despite numerous people reporting issues, the demo apps do not get updated to fix the problems.

<sigh>

Sunday, 8 July 2012

Retro effects with Android

A few weeks back I was browsing Paweł Głowacki's blog and saw his write-up on implementing both a parallax starfield as well as a 3D starfield using Delphi and FireMonkey. Quite taken with the classic starfield demo idea I though it might be neat to have a go at putting together an Android implementation in Pascal using Oxygene for Java.

As Paweł did, I used the basic Python logic from http://codentronix.com/2011/04/27/a-cool-parallax-starfield-simulation-using-python to build up the parallax version from and then used the logic from http://codentronix.com/2011/05/28/3d-starfield-made-using-python-and-pygame for a basic 3D implementation. Then I bumped into a nice DHTML JavaScript implementation of an interactive starfield at http://www.chiptune.com/starfield/starfield.html, where moving the mouse changes the aspect of travel through the starfield.

So I knocked up some equivalent logic in Oxygene in an Android application and uploaded the result to the Android Market, oh, I mean Google Play. You find the free app through this link if you want to check out the results. The interactive starfield has some settings to customise the number and speed of stars as well as whether touching the screen changes the travel aspect.

StarfieldAppMenu StarfieldAppSettings

StarFieldApp StarFieldApp2

Clearly the logic is reasonably straightforward – in each case it’s really just dots of various sizes drawn on the Canvas of a SurfaceView. This is done again and again after having moved the positions of the stars in ‘space’, but of course care must be taken to be CPU-friendly. To that end an Android Handler is used and each time a frame is drawn, the next one is scheduled in for some small time period later using a call to its postDelayed() method.

Anyway, I was quite pleased with how this little app turned out, and how it gave me an opportunity to go through the Google Play application publication process. And then I started thinking about other old effects from the demos that used to be quite popular in the late 80s and early 90s…

My favourite was the plasma effect: an undulating oozing flow of colours shifting through the screen. A bit of research helped me understand the general principle of how the plasma effect is implemented, with a plasma function at the heart of it. I found a selection of different plasma functions and rolled them into a configurable Android plasma app built with Oxygene for Java, available for free at this link:

Plasma1 Plasma3 Plasma2

Plasma4 Plasma5 Plasma6

These plasma effects are implemented by pre-assigning an interesting palette of colours and then iteratively calculating the value of each pixel of the plasma surface and plotting it on a bitmap. To keep things performant the plasma surface is typically rather less dense than the pixel count of a smart phone screen and so this bitmap is then stretched onto the Canvas of the underlying SurfaceView. However, to minimise the evident pixellation some of the effects actually render virtual pixels and use a random jitter (x & y offset) in conjunction with opacity to smooth out the edges.

Having been bitten by the bug of retro demo effects I then bumped into the Demo Effects Collection Open Source project. This shows, in C++, how a whole raft of old demo effects are implemented, so I picked a few other effects I had a nostalgic affection for and concocted Retro Effects, another free Android app built with Oxygene for Java and available at this link. This one has a fire effect, a particle explosion, shadebobs and copper bars (as well as a starfield and plasma implementation for completeness):

Fire Shadebobs

Copperbars Explosion2

This has all been a terrific trip down memory lane for me, resurging my interest in the old demo effect scene, and using Oxygene for Java has allowed me to build the apps on my favourite mobile platform, Android, using my favourite language syntax, Pascal.

Oh, just in signing off I should mention that I also uploaded a couple of live wallpapers, one with the interactive starfield and one with the configurable plasma functions. Live wallpapers are quite a nice distraction and needn’t be as much of a battery hog as they are sometimes made out to be (especially if implemented carefully). The Android live wallpapers do, however, have a nominal download charge associated with them.

I’ve been porting some of the Android SDK demos from the original Java to Oxygene, including the live wallpaper demo (a rotating cube and a rotating dodecahedron), so I’ll probably blog some technical details on how these things are built at some point in the near future.