Tuesday, 3 August 2010

Nearly there!

So, it's past the end of the month, and is PyIgnition ready for the 1.0 release? Well, actually, the code is. All the new features are already implemented and theoretically bugless. However, the documentation (which is fairly important seeing as the only purpose of the project is to be used by others) lags significantly behind the numerous ruthless (read: careless and ill-planned) changes I've made to the way the library works since the last release. Not to mention that it's lacking any information whatsoever on all the new features. But that's in progress at the moment, and with any luck it should be a very brief process leading to a prompt release!

But why the delay? Well, the file loading function ended up being slightly more complicated than anticipated. All was going perfectly well until the XML parser I was using decided that it wasn't going to read one of the tags in the test file, for no good reason whatsoever. At the same time, I was noticing occasional bugs in its attempts at reading tag meta data (meta data being variables specified within the tag itself, eg. <tagname meta="value" meta2="another value">). Which of course meant that it would arbitrarily fail to read certain files. Attempts at delving into the gungy mess of ASCII-encoded vomit that passed for the XML parser's source code quickly met with horrors so horrifically horrifying that I would be accused of torture were I to write about them here, but to sum up, I'm extremely surprised it ever worked at all.

So, I had to write a new XML parser. Much in the way of fun and frolics ensued, I can tell you. However, the end product is actually reasonably good (certainly a lot more so than the parser I was using beforehand). The source, in case you're interested, can be viewed and downloaded from here. And now PyIgnition can save and load files!

Now, on a more positive note than my abject failure to meet any deadline which I set for myself, I'm pleased to tell you that development work on Obsidian (the particle effects creation/editing program for PyIgnition) is progressing nicely. PyIgnition embeds in wxPython perfectly and is currently running rather smoothly. The design of the actual application is well underway, and I have here the first mockup - it's of the particle editor window which lets you edit and keyframe particles for a particular source:


(Click for a full-size version.) I've even got a functional demo of the keyframe timeline widget pictured, which had to be written from scratch as such a thing doesn't exist in wxPython (funnily enough):


The slider is draggable and, after a lot of messy code, clicking on keyframe markers takes you to their frames. It also sends out wx.EVT_SLIDER events when the slider is moved (whether by dragging or clicking on a keyframe marker). How many lines for this tiny, minimalistic GUI control? Over 170. Aah, the joys of wxPython. But I digress. All is currently well on the Obsidian front, and with any luck the mocked-up window shall soon transcend its current SVG state and become a Real Window!

On an unrelated side-note, Scottish exam results go out on Thursday - and we the cool kids who signed up for the online day-before text-message-and-email service will know tomorrow! 'Tis a truly terrifying state of affairs indeed. If they are absolutely flawless (As everywhere), I'll be off to Cambridge in October; otherwise I'll be going to Edinburgh. The former isn't looking particularly likely at the moment, but well. I shall nevertheless know tomorrow what'll be happening. Not in the morning, of course; that would be too nice. The results actually go out at 2:50 in the afternoon for reasons beyond my comprehension, so tomorrow morning will almost certainly yield the most painful lazy lie-in I've ever lived through. Glorious! Anyway, that's all for now; good day to you all!

Tuesday, 27 July 2010

Almost a month on

And where are we? Well, this time it hasn't been so much a case of laziness or time-wastery that's led to such a huge gap between posts: I'm pleased to announce that PyIgnition is still faring very well. The 1.0 release is still going very much to plan, and will most likely be finished by the end of this month. To share news on all that has been added since the last update here would take far too long so I'll instead give you this link to the page for the 1.0 release, which gives a comprehensive list of everything that has been or is still to be done, and then elaborate upon the more interesting developments here.

Behold! A screenshot!


What's this mad spiffery, you say? Vortex gravity! Yep, I managed to get it to work. It was surprisingly difficult actually, and it's still not yet perfect (firing particles directly at it causes all sorts of unintended madness), but it's at least working reasonably well. Essentially it calculates how far a given particle is from its centre, and then using that along with the magnitude of the particle's velocity it determines the centripetal force required to keep it perfectly in orbit. It then adds to that a tiny additional force (also towards its centre) so that the particle will accelerate inwards whilst rotating around it. Of course, it uses a slight variation on the process outlined here as calculating the distance and the magnitude of the velocity for every particle would involve a lot of square roots (and they're evil, as we know), but the force calculated is the same. And that's vortex gravity!

Another key development is 'cushion distance' for particles which have radii. Previously, collisions with obstacles would use particle centres alone which, although fine for points, meant that circular particles would appear to go partway through obstacles before colliding. Getting collisions to use these particles' radii was a long and arduous process, but the results are a significant improvement - and deserving of another screenshot!


You'll notice that there's still a bit of overlap in the 'after' image - this is entirely intentional. Without any overlap whatsoever, the gaps between particles show up very clearly and look a bit strange, and sometimes numerical inaccuracies lead to particles hovering just above obstacles. So, I've added a parameter to the 'constants.py' file (which is another new addition, incidentally) which specifies what factor of the radius is allowed to pass through obstacles. At the moment, this is set to 0.3 (30% of the radius), which seems to work quite well.

The last (and most significant of all, but sadly lacking in pretty screenshots) development I'll be writing about on this fine morning is the PyIgnition Particle Effect (PPE) file format. It's an XML-based file format for storing ParticleEffect objects in their entirety (keyframes and all) such that they can be easily re-loaded into another ParticleEffect later. At present the format's design is complete and the function for writing to it is finished - see here for a sample output. Reading from it is a bit more tricky, but progress has been good: it can already read particle sources and all three gravity objects (including all keyframes and particle keyframes), which leaves only the obstacle objects unreadable at present. This is the last feature on the list for the 1.0 release, so as mentioned at the beginning of the post I'm fairly certain the planned release date of the 30th should be a meetable one.

Updates to follow, ideally close behind!

Wednesday, 30 June 2010

Keyframe madness

Behold, the promised post! It promises promising developments, developments which seek to fulfil the promise of a promising new keyframe system. There we go, now the word 'promise' looks strange to me. If it doesn't to you, try re-reading the last two sentences again. It's a pretty silly word, isn't it? But I digress.

You may recall from the last post that I've been working on a brand new keyframing system for PyIgnition. Indeed, the more astute amongst you may recall from the above paragraph that developments of a promising nature have occurred in the aforementioned area. Well, I'm glad to say that both observations are indeed in line with the most glorious reality about to unfold before you. That is, the new keyframe system is fully implemented and working rather well.

However, the coding process most certainly hasn't been without challenge. Indeed, it was rather horrific. Essentially, the new keyframe system introduced a somewhat more complicated InterpolateKeyFrames() function which took a little bit longer to complete. Shouldn't really be a problem, no? Well, when this function is running every frame on several hundred particles, each with several keyframes and variables to loop through, the slight difference becomes a seriously massive difference. As a result, even the simplest of scripts like the original fire demo would grind to a near-halt within seconds. And unfortunately no amount of ridiculous over-optimisation of the interpolation function yielded any real improvement.

But wait! All is not lost! For once all hope seemed to have dropped away (much like PyIgnition's frame rates), a guiding light of truth shone through the muck of malformed code and illuminated a speedy solution, bright and gleaming, the Excalibur of my code. Well, to be fair it wasn't quite as romanticised as that. In reality I spent many an age trawling the web for better ways to interpolate between frames, whilst simultaneously trying every optimisation technique I could find on the existing code - literally to the point of trying to use local variables over global variables because they're apparently faster, and avoiding using object.function() (preferring a simple function() ) because it's supposedly slower. The latter saw no avail, regrettably, but the former took me on a most interesting tour of the interwebs. And, I'm pleased to say, I came upon a solution!

You see, the particles belonging to one source are all spawned with exactly the same keyframes - so the same interpolation calculations are being done for every particle, just at different times. This is obviously wasteful. So instead of doing these same calculations, every single time, the program now pre-calculates what the variables of a particle should be for every frame of its life and saves them all to a big old lookup-table-esque array thing. This is stored in the particle source object, and is accessed from created particles through a reference to their parent source. When a particle keyframe is created with the source via the CreateParticleKeyframe() method, the source immediately updates this lookup-table-esque array using its PreCalculateParticles() function.

You'll probably have noticed that there's a definite space-time tradeoff here. Obviously the particle keyframes no longer pose any problems whatsoever, as the particle update method now simply sets each of the particle's variables to the ones stored by the parent source for the current frame. This means that the program is now actually slightly faster than it was before the new system was implemented. However, the thought of storing every variable for every frame of a particle's life is slightly unnerving, as one would assume that it would mean massive memory consumption. However, this is actually not as significant as you might think.

Here's an example. We have a fairly typical particle effect with keyframed particles, which emits 20 particles per frame with a particle lifespan of 600 (both of these are probably larger than you'd ever need to use in practice, but I'm using exceptionally large values just to show how little memory the particle caching actually requires). Now, at present, a particle object can keyframe the following variables:

  • colour - 3*int = 12 bytes
  • radius - 1*float = 8 bytes
  • length - 1*float = 8 bytes

This gives us a total size of 28 bytes for a single set of stored variables. Now, I haven't the foggiest idea how Python stores dictionary objects (which is how these variables are stored in the lookup-table-esque array thing), so just for laughs we'll double this value to 56 bytes, a size it will probably not come close to reaching in reality. Again, this is just to show how little space it actually requires. So, to store keyframed values for every frame of a particle's life, we would need to store 600 of these variable sets. That gives us a final memory usage of 33, 600 bytes or 33.6 kilobytes. Not bad for an overly large value you're unlikely to ever reach in practice, eh? So really, all things considered, this business of pre-calculating keyframed particles is almost certainly the way forward. It's definitely made things run faster anyway.

And that's where I am now. Well, actually, I also added setter methods for keyframeable variables - simply setting them in the 'object.variable = newvalue' fashion simply won't work now as it would be overridden by keyframe interpolation, so you would now use 'object.SetVariable(newvalue)', which creates a keyframe for 'variable' at the supplied value on the current frame. Next up is giving the user the opportunity to select interpolation modes (followed by a bit of bugfixing of course), and the next release - which has been upgraded to Beta 1, incidentally - will be ready!

Friday, 25 June 2010

...And the post frequency meter was striking thirteen!

Yes, I know - two posts in as many days! Utter madness! The post frequency meter is indeed frazzled. But this is merely a swift news-deposit before I head off to undertake the elaborate job of implementing the new keyframing system in PyIgnition for the Alpha 4 ('controlled eruption') release. Incidentally, on that topic, I've just this morning sorted out completely how I'm going to implement the new system. It's all scribbled down on assorted scraps of paper (many of which lie within my own head), and just needs to be coded now. However, as mentioned a few sentences ago, it'll be a long and difficult process. Updates will follow when it's underway!

So, to return to the planned purpose of this present posting, I've done a bit of dabbling in wxPython today for the first time in ages and I must say I'm addicted all over again. It's simply brilliant. And, I'm pleased to announce, fully compatible with Pygame after a little bit of fiddling around. Here for your viewing is a screenshot of 'Wind.py' running on a wxPanel, completely under the command of wxPython:


The window is even resizeable, and the particle effect display scales with it. Incidentally, 'Obsidian' is a name that we were originally considering for what is now PyIgnition, and at the moment is probably going to be the name of the particle effects editor. More incidentally, the more astute amongst you may have noticed that the window looks a bit different to those seen in screenshots I've posted in the past. Why, you ask? Well, I've finally upgraded from the old XP machine (which is probably getting near its sixth birthday now), and with the new one came a new OS: Windows 7. It's rather good actually; I fully agree with those saying it's a vast improvement over Vista. But I digress.

Using pygame in wxPython applications is actually not too complicated a process, although it was incredibly difficult to find anything about it on the Internet when I looked so I'll post my findings here in the hope that the next person who tries it will find them through a Google search. There's only really one source I could find that explains it, and that's the one at http://wiki.wxpython.org/IntegratingPyGame. However, it's a bit iffy in its explanation. In case you don't notice immediately, they miss the part where they actually give the wxFrame a child to use as a pygame display - you'll need to remember to create this yourself. I just used a simple wxPanel.

The code to look at is line 10 - this makes SDL see your widget (or wxWindow, to be terminologically accurate) as the display. From there you can simply use pygame.display.init() as shown, and get a handle to the screen with self.screen = pygame.display.set_mode(). Normally in Pygame one would supply screen dimensions to that function, but here it's probably a good idea to leave them out. However I haven't tried supplying them so I don't know whether it would work or not, so feel free to experiment and see what happens. Now, although the link says you shouldn't import pygame until after setting the SDL_WINDOWID parameter, this is actually a pain because you then don't have access to pygame's functions anywhere else. I actually found that it works perfectly well if you do import pygame at the top of the file, so there's probably nothing wrong with doing so any more. That said, I'm just going with what seems to work so feel free to correct me if I'm wrong and there are hidden issues with doing so.

With that done, you're free to do things like self.screen.fill((0, 0, 0)) and pygame.draw.aaline(screen, [blah...]) to draw to the pygame surface, so all is well from there on. But is it? As a matter of fact, you'll face problems when you try to exit - neither pygame nor wxPython wants to close first, and you'll get errors either way. However, after a bit of messing around I've managed to find a solution to this. Simply bind the following function to WX_EVT_CLOSE:

____def Kill(self, event):
________self.Unbind(event = wx.EVT_PAINT, handler = [your drawing function])
________pygame.quit()
________self.Destroy()

See, the problem that arose in making Pygame quit first was that wxPython would for some reason try to draw again before it exited. This naturally causes problems when your drawing function contains Pygame draw functions, as they will be operating on a surface which has been disabled on Pygame's exit. Unbinding the draw function avoids this issue, and lets pygame exit first with wxPython smoothly following suit afterwards.

And that's pretty much it. So far I haven't found any more issues with the two working together, but I'll update if I do. I hope this proved somewhat helpful. So, back to keyframes!
Goodbye!

Thursday, 24 June 2010

It was a bright cold day in April...

You asked me once, what was in Post 101. I told you that you knew the answer already. Everyone knows it. The thing that is in Post 101 is... well, pretty cool. All cultural references aside, the content of this amusingly-numbered post is in fact rather spiffy, and comes in the manifestation of an update on PyIgnition's progress. To summarise, it's been going rather spiffily. So spiffiliy indeed that I decided it warranted a post. So! To make haste t'wards the very tip of this post's point, I shall cast in your general direction some video footage of PyIgnition, post mutatio:

PyIgnition alpha 3 from Animatinator on Vimeo.



So as you can see, the promised physics system is very much in place. Particles can now deflect off objects thanks to a combination of what is effectively an inverse gravity (but using an inverse cube law instead of inverse square to ensure objects aren't visibly repelled from a distance), and a preceding intersection resolution stage. The latter is a fairly simple process which firstly works out whether any particles are inside obstacles and then shifts them back out to appropriate places. The two procedures are defined as functions for collision obstacles (as InsideObject() and GetResolved() respectively), so the code handling the overall process is just a couple of lines:

if (not obstacle.OutOfRange(particle.pos)) and (obstacle.InsideObject(particle.pos)):
____particle.pos = obstacle.GetResolved(particle.pos)

(The first part of the if statement is just checking if the particle is within reasonable range of the obstacle before it checks for an intersection.) I also added a 'bounce' multiplier to the repulsive force which is mainly set to a value below 1.0, as the force often tends to be a bit big and results in particles gently drifting towards an obstacle only to be propelled away so quickly that the program would need to take the effects of special relativity into account in order to process them correctly. In all of the demos shown this was set to a standard value of 0.2, which causes only a slight bounce when particles collide with obstacles.

So, that concludes this decade's blog update. See you next time, when I'll hopefully be bringing news about the work-in-progress new-and-vastly-improved keyframe system!

Saturday, 12 June 2010

Happy 100th post!

Good day to you all again, my few-and-far-between readers! Welcome, one and all, to what you may already have ascertained is in fact the hundredth discrete outpouring of textual miscellany to grace the monitors of its unfortunate readers. Those of you who have already managed to stumble upon this site before and are (amazingly) visiting again may have noticed that I've decided to mark this occasion with a complete visual redesign. This is in no way linked to Blogger's new, more advanced 'Template designer' page being released today. I hope you'll agree that it looks much nicer than the dull, flat and lifeless look it once bore. And if you don't, well, bollocks to you. It's my blog.

So! What lies on the programme for this milestone of a post? Well, remember that ultra-secret project I alluded to in the last post? The project so secret I daren't even mention it within this particular paragraph?


</p> <p>


Introducing PyIgnition!


PyIgnition alpha 2 from Animatinator on Vimeo.



This is a project I've been working on for about a week now. It's essentially an advanced particle effects engine for use in pygame, and it supports all sorts of nifty features. Most significantly, almost every parameter available is fully keyframeable, which lets you create fairly complex animations. Also handy:
  • (Theoretically) infinite number of particle sources
  • (Theoretically) infinite number of gravities (used for influencing particles' paths), which can be either point gravity (following Newton's law of gravitation) or constant gravity in one direction
  • Several particle drawtypes, from the standard points and images to more exotic types like bubbles
  • Simple interface which also allows plenty of freedom - if you don't like its keyframing system, you could even write your own outwith the library and use it to control parameters of library objects. Anything's possible with a bit of faffing around
  • Physics system (currently under development) to allow you to insert obstacles for particles to collide with and bounce off
Basically, it makes the difficult and arduous task of implementing real-time, interactive particle effects quick and simple. So, this shall be the new focus of this blog's output as we stride onwards into what I hope will be a second hundred posts. Accordingly, I've updated the information on the right-hand side of the page with links to the project's Launchpad page (where you can find its source code and track its progress without relying on me getting around to writing about it here) its screenshot gallery (where, funnily enough, I'll post screenshots of it in action) and its pygame project page. Check them out! As they say. So, I suppose all that remains now is to sign off this milestone post with a grandiose rendering of its number:



Sunday, 30 May 2010

Exams are done!

Yep, that's right. No more high school exams, ever. Physics made its magnificent way onto the 'done' pile on Friday (in a most successful fashion), leaving me free to faff about whilst I wait for the results to come out.

Soo, I'll probably have to code something at some stage. On that front, I've been wandering around my 'code' folder to see what's what, and it appears that all that remains to be done to finish GraviQuest completely is the last level's layout file. And it's already been started. So essentially, once I manage to finish that one level, GraviQuest should be ready for release! I'll be sure to update here when it is.

And, at the same time, I've been wandering around the 'imagination' folder within my brain, seeking out ideas for a project to fill posts here with. And I'm pleased to say that I have found just the thing. It has all the shiny spiffiness and questionable purposefulness you will have come to expect from an ExeSoft program, whilst simultaneously being a pleasant break from the norm. However, I shalln't be disclosing the precise nature of this secret (as of right now) project yet. Mwaha. But you can probably expect to see something of it in my next post, which incidentally will be this blog's hundredth! Terrifying thought, isn't it? I've been wittering into space for almost two and a half years, posting an average of once every 9.2 days (it was once every two or three days when the blog began...), and in that time (assuming an average of 400 words per post) I've written almost 40,000 words. One of these days I'll have to publish it all as some form of book on how to blog unsuccessfully, or perhaps as a non-standard novel exploring the issues of insanity and procrastination. The options are endless... or beginningless. But anyway. Secret projects call! And of course GraviQuest grovels, begging to be finished. Good bye!

Wednesday, 26 May 2010

It's brief update time, chaps!

Because I'm far too lazy to write anything of length at the moment. Why, you ask? Aah, well that is to be explained in this very post. Well, this paragraph-post. Yes, that's right - I intend to do it all in one paragraph. Mwaha! Brevity is at the soul of my wit, certainly. And tediousness adorns its limbs and outward flourishes. But let that go. To reach pertinently for the point of the paragraphical post, I shall share with you my progress through the realm of examinations. Well, English is still done (although I don't recall whether I mentioned it or not, and can't be bothered checking), and Maths has followed suit. The latter was, to re-use a phrase, glorious and victorious. And just this very day, History too joined the list of exams gone by, in what was actually a relatively painless exam. There were iffy parts, and there were magnificent parts, and overall my hope is that these two extremes of performance shall wed in splendorous fashion producing a final result of an A. So now all that remains in terms of exams is good old Physics on Friday, for which I am doing a bit of revision even as I type. And once that has passed, and been passed, I shall be free! Free, to... get a job. Alas.

Tuesday, 18 May 2010

Damn you, TalkTalk!

Hello all, we meet again! But today, things are different - today I come to you battle-scarred and wounded, limping, with the blood of a thousand technological foes dripping from my sword: today, I come to you glorious and victorious. The foe? None other than my ISP,good ol' TalkTalk. The battle? Well, allow me to expound...

I'd like to think that by this stage everyone on the 'net would have attained an awesomeness level sufficient to be using Firefox, but regrettably I hear that there are still those who cling to Internet Explorer. So, for this (hopefully small) minority, allow me to illuminate one of the many magnificent features of Firefox: when you type something non-URLey into the URL bar and press enter, it does a Google search-by-name for the input and oftentimes takes you straight to the appropriate website - for instance, were you to type in 'ExeSoft' you'd find yourself transported right here (hoorah!).

Now, being an extremely lazy person even at the best of times, I've taken to using this feature as my sole means of navigating the intertubes, simply because I can't be arsed going into my bookmarks or Googling directly. And indeed, this was perfectly well until just recently when DISASTER STRUCK! There I was, happily lazing away, when suddenly my URL bar took me not to the desired page, nor even to a standard Google search, but instead to this horrendously garish mockery of outdated web design:



Sickening, no? Well, I ended up vomiting there and then. Now, much as pro tips on 'getting into bars' may well have proven extremely useful in my younger youth when such places were heavenly hoardings of forbidden fruit, this is something which I could quite easily have found myself had I been allowed proper use of the URL bar. But no! TalkTalk seem to feel that the URL bar wasn't helpful enough when it simply redirected me to the desired page, and so they've decided that as of now they're going to quite literally steal the internet request out of Firefox's hands and drag me by the scruff of my neck down to their internet marketing brothel to peruse their irrelevant sponsored results. And as marketing brothels go, this one's extremely down-market. The logo, for one thing, is ridiculous. It seems to vaguely resemble a Christmas tree which some imbecile has painted in various different colours before crushing, eating and regurgitating. Or something like that.

So, was Animatinator going to stand for this? Pah! Not he, not I, not anyone! So, after much perusing of the net (stealthily using the normal Google search engine whilst the TalkTalk guards were facing elsewhere), I've discovered that you can actually solve this problem by changing to a different DNS server address ([Start->Control Panel->Network and Internet->View network status and tasks->Change adapter settings->{right-click on your internet connection}->Properties->Internet Protocol Version 4->Properties] in Windows 7). The ones everyone seems to recommend are two Google ones: 8.8.8.8 (which unfortunately didn't work for me) and 8.8.4.4 (which did work). Basically, switching to one of these takes a knife to TalkTalk's (or whichever other oppressive, tyrannical ISP regime you subscribe to) slimy grip on the Firefox URL bar, leaving you free to exercise laziness at will!

And that, my friends, is the tale of my war with URL-bar-hackery. Goodnight!

Saturday, 15 May 2010

Hello again!

Just thought I'd drop in with a surprise update. Yep, I still remember this blog! Even after all these months of separation, myself and blogging remain as firm a couple as, well, myself and laziness. The latter pairing being the reason for the colossal temporal disparity between the then and now; the there and here; the last delivered update from myself, and this current literary phlegm. Essentially. So, to bring to a close this travesty of prefacing text, I'd best draw from my dunce cap some form of excuse for the atrocity of negligence committed over the past few months. Basically, I was busy. Exams, coursework, the traditional crud. That and I suffered from the sheer abject laziness to which I am so oft prone.

But that isn't to say that I have done nothing in the way of ExeSoft-ery. No, not so! I have various things which still await posting, which with any luck will find their way onto this very blog over the next few posts (which will presumably come with fewer gargantuan time gaps of the nature we have just witnessed). Unfortunately I can't at present divulge the secrets of these mysterious projects, as I actually can't remember which ones I've already posted about. It's been a while. But as mentioned, I intend to sort this out fairly soon and get some posts up here. For now I'll just be updating you on things you don't care about, in a writing style which has most evidently degraded over the last few months (during which the closest to prose my writing got was formulaic English essays and the odd explanation paragraph in physics exams).

So, what do my near-nonexistent audience care the least about? Aah yes, my banal excuses. Exams! Doesn't everyone love them? Well, I'm sitting them at the moment. (It may well be that my reason for posting here was simply that my mouse-operating hand was bored of drifting over to Tetris during revision sessions, and thought it would spice things up with a bit of bloggery.) And I'm pleased to say that having sat the English exam on Wednesday, I am now free from studying English... forever. Yes, that's right. Nevermore need I ponder the elaborate subtexts present in such poetic masterpieces as Carol Ann Duffy's '$':
A one a two a one two three four - boogie woogie chou chou cha cha chatta noogie. Woogie wop a loo bop a wop bim bam. Da doo ron a doo ron oo wop a sha na? Na na hey hey doo wah did. Um, didy ay didy shala lala lala lala, boogie woogie choo choo cha cha bop. (A woogie wop a loo bam) yeah yeah yeah.

(I shit thee not, this is genuinely one of her poems. I imagine the only 'meaning' present here is in the title - basically, "I can write whatever bollockery I like and the cash will continue to roll in.") Indeed, I need never actually write
anything properly again. I am now free to allow my literary mind to decay, to the stage where I find difficulty even to write code coherently.

But alas, this cannot be! As the greatly revered Animatinator, I feel it is my duty to maintain my magnificent writing capabilities, and to continue this glorious and majestic blog indefinitely, so that you, my adoring fans, can continue to bask in this... this paragon of literary achievement, this grand summit of intellectual mastery, and so that we, as a species, can take heed of the great words set down herein and move forwards unto a new era, a new paradigm, an entirely new... means of existence, in which...
...
Sorry, I tried incredibly hard, but I couldn't get any further with that without descending into fits of hilarity. See? I'm already losing my writing abilities. I can't even impersonate Carol Ann Duffy any more. But nonetheless, I will continue to post to this blog, despite there being no reason whatsoever to maintain my capacity for language. Because that's how nice I am.

So, where was I? Ah yes, boring you with tales of exams. English went well! Surprisingly, we had an incredibly good question on the Pinter texts (the main thing our class was studying) so I didn't have to resort to prescribing contrived meaning to the semi-literate blabberings of good old Duffy (our back-up). And the resulting essay seemed at least reasonably acceptable. So, given that the dissertation went well and the two creative pieces should average an A, I'm still hopeful for an overall A (and consequently a met Cambridge offer). All the other exams are still to come though, so there's still scope for abject failure. I'll endeavour to keep you posted.

And with that, I shrink back into my pit of silence. Goodbye for now! Perchance we shall meet again over the next few days...

Saturday, 13 February 2010

OSX Dock in Pygame

Salutations to all! Apologies for breaking my vow of voluminous posting with such haste and dexterity, I had four exams and two horrible deadlines to contend with. Gloriously, all that now stands in the past, leaving the way clear for consistent blogging! Hopefully.
Now, with the traditiona
l excuses out of the way, I shall share with you the primary purpose of this posting:


It's the Mac OSX Dock, but as you've never seen it before: emulated in Pygame! Essentially, I felt like setting myself a coding challenge which would produce shiny results (shiny is good), and this seemed apt, being as it is both shiny and pretty flippin' challenging to code.

It took many an hour to get the scrolling to work properly - the items have to position themselves such that the space between each one is consistent, and so that the focus of the 'bulge' in the menu is always under the mouse cursor. And with that achieved, it has to scale in and out smoothly at either side (a surprisingly difficult thing to achieve) and the items have to be aiming to reach their original positions at all times (again, surprisingly difficult; most seemed content to simply remain in their shifted positions when the mouse focus was removed). Ultimately, the code ended up being near-unreadable. But well. It works. And, when it comes to graphical elements such as this, that's all that really matters.

It's also designed with the intent of being imported and shoved into other projects, and as such is fairly modular. One can also alter its items, size, position, scaling factor and mouse response distances via arguments supplied to it upon its creation. And, surprisingly, it can actually be used as a menu and not just pointless spiffery: there's a function which returns the index of the item currently under the mouse.

For more information and to download the source code, go to http://pygame.org/project-Pygame+Dock-1412-2506.html. Alternatively, if you can't be arsed downloading it, you can watch a demo video... right here. Behold:

Pygame Dock demo 1 from Animatinator on Vimeo.


In other news, I recently wrote a program which generates sentences that could be English, but aren't (that said, they occasionally are). It uses a Markov Chain system, which essentially means that the next letter in a word is chosen randomly but is weighted by probabilities of certain letters following the current one. For example, the letter 'a' is much more likely to come after 't' than 'z' is. These probabilities are found by training the program using a corpus, which in this case was simply a gargantuan list of English words. The following paragraph has been generated entirely by the resulting program:

Cumms cegopah alliancaledwale anghiacr cthilled cooumaceeamamililaieanebedalifichacims an ch aiedmbd abearalaboncacsimolobaprdalimecacallakle d bicteed cherhereag z ak bobilalkalad abe aie dicoubbedr. Cobidopalafieecinebagevachadiamoe badereyureanga amprig achiggumiadllided cs akllalica are thedileagnabba cks c dle che p blicadekeidod cimbekakn aulalikngifoinicoacakakalaidid ag a credge d bl bl po, ac dereil cas a blelellalajaeccladollag clllecr cokonamagabanalad cal.


As you can see, though it seems fairly random the words are almost all pronounceable, something which would not have happened had they been generated completely randomly. That said, there are some odd ones in there. 'Z' would be an example. I do like the sound of '
abearalaboncacsimolobaprdalimecacallakle', however. I take it to mean 'possessing the qualities of a mentally-challenged bear who vaguely resembles lime cake'. If enough of us use it regularly, it might just make the dictionary.

Oh, and while I'm here, I might as well update you on the UCAS situation. St Andrews finally replied, and gave me an unconditional offer! Hoorah, now I can reject them. Mwahaha.

They're a bunch of
abearalaboncacsimolobaprdalimecacallakles anyway.

Sunday, 10 January 2010

Happy new year!

And, indeed, happy new decade. You'll have to excuse the slight (nine-day) lateness of this post; I was busy forgetting to post. Or something to that effect. The point is... well, non-existent, actually.

However, those of you fearing for the safety of this post as it rapidly descends into pointless blabbering may freely clamber out from behind the sofa, because I have news! News most auspicious in nature. News pertaining, once again, to university applications. What news, you ask? Well, after a somewhat epic wait, I've just yesterday learned that I've got an offer from Cambridge! Don't ask me how...

And for some absurd reason it's actually a good bit easier than the Imperial one (which, you may recall, was inhumanely cruel at A1AAA):
  • Advanced Higher Maths and Physics: AA
  • Advanced Higher English and Higher History (any order): AB
Glorious, is it not? True, it's still a pretty difficult offer. But I honestly believe I can manage this one, whereas the Imperial one seemed much more uncertain. So, in all likelihood, Cambridge will be my firm choice when it comes to decision time. And English is the subject I plan to get a B in, naturally (although even then it'll still be the hardest grade to meet this year).

So, time for an update on the overall situation methinks:


Cambridge (Jesus college) - Offer (AAAB)
Imperial College London - Offer (A1AAA)
Edinburgh - Unconditional offer
Glasgow - Unconditional offer
St. Andrews - Acknowledged

Yup, that's right - St. Andrews are still not replying. But then, the only point in waiting for them at this stage is sheer petty perfectionism (if they said yes I would have five offers!), so it's fairly likely I'll just give in and make the decision fairly soon. My plan is to set Cambridge as my firm choice, with Edinburgh as the insurance - that way if I don't manage to meet the (relatively meetable) offer I have an unconditional backup, and can safely fail all my exams without fear of not going to university at all. Hoorah!

And so ends the first of what will hopefully be many frequent posts this year. Yes, okay, stifle your laughs; I'll at least try to post frequently. It's not a new year's resolution, as if it were then I'd already have broken it with this ludicrously late post. However, it's a goal towards which I shall strive with all the tenacity and will I can muster, whether it be that of a devoted soldier or an injured snail with attention deficit disorder. We shall see in due course.

Thursday, 24 December 2009

Merry Christmas to all!

Just dropping in for the customary exchange of greetings. Except in this case is isn't really an exchange as such, being as it is a blog whose very nature dictates that all communication can only traverse the distance between our computers in one single direction (with that being from myself to you). Unless of course one takes into account the possibility that you, the user, make use of the post commenting function, in which case it could be argued that this does indeed constitute an exchange of greetings. That said, it is one which is rarely consummated - as can be seen from the sparsity of such reciprocations on this very website, precious few internet users are of the commenting persuasion and a page generally needs to have somewhere in the region of a hundred viewers in order to secure a comment. And that's assuming the page is even relevant to the interests of that particular set of users and capable of provoking the thought required to drive them to express views upon it. Sadly these are criteria which have almost certainly gone unmet by this particular work (what with it being a foolishly pedantic ramble), and so it is logically defensible to say that this post does not, in fact, count as an exchange of greetings in any but a few cases. Therefore my first sentence was erroneous. Sorry about that.

Merry Christmas!

Friday, 11 December 2009

Cambridge raverviews!

So, here's how they went.

First up was the subject-specific interview. This one had moments of awesome and moments of shoddy, but was generally okay. Once again I was surprised by the complete lack of personal statement questions - they began by reading through the main points ("so you've done C++ and python, made a few programs...") and then indirectly asked why I wasn't taking computing. It was posed as something like "Most candidates are normally doing A-level computing, but you don't seem to have done it at all; where does the background in computer science come from?" Thankfully I was prepared for this, and explained that it was something that greatly interested me and which I had mostly learned for fun in my free time. To answer the implied question of why I had no formal computing education I said something vague about the Standard Grade course not being particularly relevant to a degree (which is true), which is what I'd always intended to do (which is mostly true, although I wasn't very certain of what I wanted to do back then - I decided against Standard Grade computing on the grounds that I was already learning it myself). And then they asked about what sort of projects I've done, so I rattled off a big old list of things I've been doing recently. Hopefully it wasn't too disjointed and rambly.

And then came the technical questions.

Firstly, they got me to work out what a piece of code did, which was simple enough but took me a little while as there were a few off-throwing loops. They didn't appear to be too bothered by that though, and I think bonus points were gained on the second part of this one as I worked it out relatively speedily. They then got me to devise an algorithm (I don't think I can say what for), which I luckily managed to do rather quickly - they seemed fairly pleased by this one. I then had a proof by induction, which got off to a terrible start when I mistook the technique they asked me to use for a direct proof. And it went downhill from there. The less said the better, really. Not one of my finest moments. Moving onwards, this was followed up by a question about a finite state machine diagram, and I get the impression that several bonus points were gained when I mentioned that I had seen one before (based on the rather surprised reaction by which this was received). They asked me to add bits to it in order to add extra functions, and there was a bit of to-and-fro-ing here as I made a few mistakes at the beginning and then went about the last part of the question in what was apparently not the intended way. They said it was still correct though, so hopefully the question wasn't too much of a failure.

And that was that. Not too bad really; it could have gone far worse. It was certainly better than the Imperial interview anyway, although I hear that Cambridge interviews are much more important that Imperial interviews when it comes to selecting candidates (Imperial do a lot more pre-interview selection, and so those with interviews are fairly likely to get offers).

This first interview was closely followed by the TSA, or Thinking Skills Assessment. A glorified IQ test really, but with slightly harder questions and a large number of questions that are to do with identifying underlying assumptions, flaws or main conclusions in arguments. The one I did at Cambridge was actually a lot harder than the online practice one, and I ended up using the full hour and a half. I did however answer all but four questions with certainty which varied between definite (for most), and moderate (for about a fifth of them). Not a clue what my results were, and indeed I'll never be told; it'll make a contribution to my application in consummate secrecy. Ominous.

So, tired and mentally worn out as I was, I trudged on to the last event of the day: the Natural Sciences interview. This has to be taken as well because the Computer Science Tripos at Cambridge involves a Natural Sciences portion for the first year (which is rather awesome actually). However, I was slightly worried at the prospect of an interview on the topic as I've done minimal revision for such a thing. And "Natural Sciences" is so ill-defined it could well bring in work I did and forgot in first-year Biology.

Thankfully, however, it was just Physics with a bit of Maths. And IT WAS GLORIOUS! Glorious and victorious. The questions were almost all easy, and I steamed through about seven or eight in the twenty-minute interview. I made a few mistakes, but in general I managed to answer every question with all the speed and accuracy of a well-guided cruise missile. Yes, that's a mild exaggeration. However I do feel rather positive about this last interview, and so it was a nice way to end the (long and arduous) day.

So then I was off, on the six-hour train journey back to here, where I found an offer from Imperial awaiting me. I'm still dancing on the ceiling about that one. And it's making it considerably difficult to type.

Thursday, 10 December 2009

Imperial college verdict

I got an offer! Yaaaaaaaaaaaaaaay, etc. I'm rather surprised actually, as I've spent the last week or so gradually lowering my estimation of how well I did and by the time I opened the letter (which, ominously, was small and white) I was already certain of being rejected. 'Twas a pleasant surprise indeed.

Unfortunately, it's rather harsh:
  • A band 1 in Maths (Advanced Higher)
  • A in Physics (Advanced Higher)
  • A in English (Advanced Higher)
  • A in History (Higher)
Yes, they want As in EVERYTHING. And Maths has to be a band 1 - the very best A you can possibly achieve. Doable? Perhaps. English is still a bit of a pain though.

So, how did Cambridge go? Well, that'll have to wait for tomorrow when I have the energy to write anything of length. I just gave my entire brain-usage quota for the day to Cambridge. It wasn't too bad though; indeed, the second interview was glorious. Returning home to find a nice shiny offer from a university I was already mentally crossing off as a failure topped off the evening nicely, and has killed my short-term memory thus making me forget all the specifics of what went down in Cambridge, so even if I had the energy to write I probably couldn't recount the day's escapades just now. Watch this space, if you can be bothered at this time of night.

Wednesday, 9 December 2009

And so it begins...

Today I leave for Cambridge, to be interviewed and multiple-choice-tested tomorrow. Oh dear.
I shall tell of the horrors I faced upon my Thursday return, unless of course I'm too scarred by it all and can't post again until Friday. Either way, watch this space!

Sunday, 29 November 2009

Oh noes!!

*annoying popping sound*

MCAFEE WARNING
The program 'McAfee updater' is trying to access the Internet!!! OMGWTFLOL!!

*pause*


*annoying popping sound*

MCAFEE WARNING
McAfee is out of date! Oh noezzz what shall we do?!?!?


I shit thee not. Well, perhaps it wasn't worded quite like that, but that's how I choose to read it. Yes, McAfee SecurityCenter (bloody American spellings) has finally caught up and realised that the most potent threat to my computer is, in fact, McAfee SecurityCenter. And not just because it's designed by people with dodgy spelling skills and space-bar-aversion; no, apparently it's trying to access the Internet. Not only that, but it's antiquated as well! (And for some reason it's of the view that downloading the latest version would solve this.)


Usually, when it starts complaining about updates, the resolution is a simple case of clicking 'install updates.' However, since the latest SuperAwesome McAwesomeUpdate (NowWithEvenFewerSpaces), its very components are at odds with one another all of a sudden, and such an endeavour is obstructed by anti-virus anti-productivity red tape. So what happened? Well, allow me to retell a tale whose horrors shall play upon your very bones like some form of poorly-tuned percussion instrument. Yes, I know that didn't make any sence.

Upon restarting (which I was compelled
to do by a big impertinent pop-up which repeated its demand like a child seeking sugar), I was immediately affronted by a torrent of McWhineBoxes. Every single one was from good ol' McAfee, asking for yet another of its components to be allowed access to the Internet. I honestly wasn't aware that it comprised so many discrete processes, but there we go. I suppose it serves as an example of the lengths programmers will go to outrequire the latest hardware.

Now, at least that can be easily dispelled through an hour or so of mindless allowing (during which period I may unintentionally have allowed
Internet access to thousands of malwarez without noticing). However, another more pressing issue remains: McAfee SuperFireWallPlus isn't intalled!!! Or, at least, the middle-right portion of the SecurityCenter window believes that. The bottom-left portion knows it's there, but is keeping that to itself. Why? It's simple; the two portions have fallen out:


Now, one question remains. What did this new and glorious update actually add, to counterbalance the inconvenience of having to exhaustively allow every single one of McAfee's myriad sub-processes, and at the expense of the program's capability of determining its own integrity?



A new splash screen.

Thursday, 19 November 2009

Imperial postmortem

Straight from the gargantuan sprawling mass of over-urbanisation that is London, I return! Now, allow me to spin for ye a tale of terror, adventure and outright ravery.

To begin with, I was ludicrously early - once again Google Maps has presumed me to be a lethargic snail made of concrete, and the journey from the underground station to Imperial College which it estimated as taking around twenty minutes took a mere five (if that). I planned the journey such that the twenty-minute walk would leave around fifteen minutes cushion-time, which could always be spent faffing around outside the university, but ended up spending a whole half-hour wandering around the area. It was a larf though.

Someone at Imperial has found out about my passion for procrastination, and as such my interview was one of the last. The first three hours were spent being shown super-spiffy demonstrations (including a balancing robot!) and being told how awesome the university is at everything (they might not have been lying here). And then followed the interviews.

Everyone in the group I was in was being interviewed simultaneously; however many the interviewers took a while to get there. And so we were left sitting around a table whilst the interviewers gradually came and picked us off, one by one. That was probably the worst part.

The interview, when it came, wasn't all that bad. Naturally I have to be quite vague about it, however. There were a few questions about my personal statement, but they seemed to be mainly out of interest - for example, "what sort of pieces does your jazz band play?" Two of them actually led into him explaining some of the things they've done at the university. Of course, there was a significant portion of maths in the middle of it all. I was mainly deriving the golden ratio in various ways, and each time I got there with a bit (sometimes a lot) of help from the interviewer. Generally I think I didn't do too badly, although I did make a few shameful mistakes - most notably, when I said two ratios were equal but then spent ages pondering what do do next before the interviewer had to explicitly point out that ratios can be expressed as fractions. And I had actually done just that for the previous question. Aah, mind blanks...

So, to summarise and conclude, the interview was largely not what I'd expected and the maths was fairly-hard-yet-doable-eventually. Not a clue whether I'm likely to get an offer or not; it really could have gone either way in the interviewer's eyes. But I believe offers/rejections come through in around two weeks or so. Thus Time, the omniscient (yet unforthcoming) being that it is, shall eventually tell.

Tuesday, 17 November 2009

Imperial College London interview tomorrow...

Eep. Fear and pre-emptive terror shall ensue.
Well, I'll be sure to post here afterwards to say how badly it went. And then maybe I can get on with ExeSketch!

Saturday, 14 November 2009

Got an interview for Cambridge

Hoorah!
Quite surprisingly I've got a massive amount of notice for this one - apparently they don't normally tell you until the week before, thus forcing you to spend vast quantities of cash on train tickets. It's not until the 10th of December, a full four weeks after the one at Imperial (which is rapidly closing in!). Now, by D00ve's Law (given a particular timeframe T, the time spent procrastinating is (19/20)T with the remaining period spent actually working) that gives me 1.4 days to prepare, which seems reasonable enough. But firstly, the Next Wednesday interview must be prepared for. Updates to come when it's over!