For some reason I've decided this five minutes is better spent blogging than working, perhaps to take a break. Whatever the reason my conscience is telling me its a bad idea, lilke it does at the moment when I do anything that's not work - the alarm bells sound whenever I make the desicion to take a break, eat, shower, go to the toilet or try to sleep that I should in fact do more work!
Nevertheless, under the stress I'm chugging along with progress. I have now perfected (probably too thoroughly) the methods I'm using to implement the level grapics with all the different hit tests. I'll not bore you with details now, but know that for each placed object and each bounded area of playable level will have had a LOT of work gone into its design and implementation.
Heres a close perspective view of how the level is shaping up:
Tuesday, April 7
Sunday, April 5
Progress, but not enough of it!
As I keep ploughing on with this client project, attempting, struggling, worrying, coming back at failed solutions and then solving the seemingly endless procession of problems I face, the excitement and anticipation of seeing how the final game turns out and what other people make of it is half clouded by doubt and potential regret that it wont turn out as good as it could.
I'm finding it an 'interesting' challenge to keep pushing for what could be, as opposed to what I know will be.
This version includes BOT TYPES, (colour-coded display and type counters on the H.U.D.) Also included are PICKUPS which are generated at random times at set spawn points, but won't spawn if point is occupied by a pickup already OR if the man's standing on it. (solved, annoyingly, by two completely different algorithms - code getting messy!)
I'm finding it an 'interesting' challenge to keep pushing for what could be, as opposed to what I know will be.
This version includes BOT TYPES, (colour-coded display and type counters on the H.U.D.) Also included are PICKUPS which are generated at random times at set spawn points, but won't spawn if point is occupied by a pickup already OR if the man's standing on it. (solved, annoyingly, by two completely different algorithms - code getting messy!)
Thursday, April 2
Client Project Update!
I've been busy getting other highly annoying projects and assignments out of the way so I can concentrate on this - now I've been incredibly busy over the last few days as the deadline has now entered the 14 day barrier - which I like to call CRUNCH time!
There's still a hell of a lot to do but I'm confident if I stick to my guns, don't take too long-a-breaks and stay focussed I can produce something to be proud of!
So where am I at? Well I now have the first PLAYABLE version of the game...which admittedly still needs a title. But first things first, what does it now do?
- All the code used is built into CLASSES. (lots of work for little immediate visual effect and irrelevant to non-Flash developers I know, but it was necessary in order to create the bots and allows for more diverse functionality)
- As mentioned in my previous post I have a new CONTROL MECHANISM, which you can play with here (right), and compare it to the old one (left)
- Also mentioned, I now have BOTS, which change to a random direction at random intervals, this may need some tweaking perhaps to weight the new direction chosen away from the player, making it harder to catch said bots, for example
- Both the avatar and bots hit both a boundary at the edge of, and a test object within the the playable area. The bots turn back the opposite way (and sometimes get stuck!) while I've chosen to keep the avatar at the edge of objects and allowing the classic Tomb Raider and other classic game-esque 'running into walls' animation - purely for classic videogame appeal.
- A VERY HARD TO NOTICE feature (because it's just obvious that it should happen) is my depth sorting algorithm which I'm quite proud of :D It consists of not only an array of all the children of the level, but also, because of the way I've contained the various visual elements for level movement, their .y properties had to be converted into global values, so I couldn't just use an array and call a simple sort method. The array had to be created as multidimentional, and then sorted according to a compound argument before the children were issued their new indexes by a 'for loop', cycling through the newly organised array.
Happy days. here, have a fiddle:
There's still a hell of a lot to do but I'm confident if I stick to my guns, don't take too long-a-breaks and stay focussed I can produce something to be proud of!
So where am I at? Well I now have the first PLAYABLE version of the game...which admittedly still needs a title. But first things first, what does it now do?
- All the code used is built into CLASSES. (lots of work for little immediate visual effect and irrelevant to non-Flash developers I know, but it was necessary in order to create the bots and allows for more diverse functionality)
- As mentioned in my previous post I have a new CONTROL MECHANISM, which you can play with here (right), and compare it to the old one (left)
- Also mentioned, I now have BOTS, which change to a random direction at random intervals, this may need some tweaking perhaps to weight the new direction chosen away from the player, making it harder to catch said bots, for example
- Both the avatar and bots hit both a boundary at the edge of, and a test object within the the playable area. The bots turn back the opposite way (and sometimes get stuck!) while I've chosen to keep the avatar at the edge of objects and allowing the classic Tomb Raider and other classic game-esque 'running into walls' animation - purely for classic videogame appeal.
- A VERY HARD TO NOTICE feature (because it's just obvious that it should happen) is my depth sorting algorithm which I'm quite proud of :D It consists of not only an array of all the children of the level, but also, because of the way I've contained the various visual elements for level movement, their .y properties had to be converted into global values, so I couldn't just use an array and call a simple sort method. The array had to be created as multidimentional, and then sorted according to a compound argument before the children were issued their new indexes by a 'for loop', cycling through the newly organised array.
Happy days. here, have a fiddle:
Tuesday, March 10
Game Mechanics Coding
The coding stage of my current game project has started, and started quite well (compared to how badly coding can go - error-wise).
After a bit of messing about I've got the pixel-level bitmap data hit test working smoothly. the slight messing about I had to go through was due to my avatar's containing movie clip not being at 100% scale, this causes issues at the bitmap data object seems to always work with the data source at its 100% size for the hitTest no matter what scale the source object is at.
I've just re-hashed my control system too, to give a faster, more logical interface for the player, as the game is now a faster movement-based game. Here's how:
I'd created the functionality of moving the avatar already (see previous 'red-thing' post), but I'd disabled movement if >1 direction was being pressed. This was an easy fix for a slight bug I found in the way I had coded the input gathering. (and, I've noticed, MANY online Flash games have been published with the same problem). The issue is that when a new directional key is pressed, it overrides the current direction ONLY if it's lower in the coded order. For example if the code is as follows: (in pseudocode)
if UP is pressed, go up;
if DOWN is pressed, go down;
if LEFT is pressed, go left;
if RIGHT is pressed, go right;
Up will be overridden by any other direction; down will be overridden by left and right; left by right; and right will never be overridden.
This gives unequal directional behaviour which will confuse players, possibly causing a complete game success (enjoyment, re-play factor and possible forward potential if it's an advergame) into total failure (annoyance to the extent that the player quits playing for good, never forwards or tells anyone about the game and possibly creates negative connotations about any brand shown within the game!)
This is totally unacceptable, so I set about creating an intelligent input algorithm. The basic pseudocode I've turned into working ActionScript is the following (example of just the UP direction):
- Base logic layer:
-- When UP is pressed, upInputVariable = true;
-- When UP is released, upInputVariable = false;
- New Middle-logic layer:
-- Record previous frame's InputVariables states;
-- Compare previous and current InputVar states;
--- (If upInputVariable's state just changed to true) OR ((any other InputVarState changed to false) & (upInputState is still true))... then newDirectionRequest = "up";
- Top Movement Functionality layer:
-- If newDirectionRequest = "up", [do all the required actions to move avatar up]
If you followed that cheers for reading through it!
I'm happy with this, especially as I can see which games online haven't done this. Try it yourself, on a game where more than one direction can be pressed, experiment with which ones override the others. I've found that almost all have either not tackled the problem or used my easy fix.
More updates to follow...
After a bit of messing about I've got the pixel-level bitmap data hit test working smoothly. the slight messing about I had to go through was due to my avatar's containing movie clip not being at 100% scale, this causes issues at the bitmap data object seems to always work with the data source at its 100% size for the hitTest no matter what scale the source object is at.
I've just re-hashed my control system too, to give a faster, more logical interface for the player, as the game is now a faster movement-based game. Here's how:
I'd created the functionality of moving the avatar already (see previous 'red-thing' post), but I'd disabled movement if >1 direction was being pressed. This was an easy fix for a slight bug I found in the way I had coded the input gathering. (and, I've noticed, MANY online Flash games have been published with the same problem). The issue is that when a new directional key is pressed, it overrides the current direction ONLY if it's lower in the coded order. For example if the code is as follows: (in pseudocode)
if UP is pressed, go up;
if DOWN is pressed, go down;
if LEFT is pressed, go left;
if RIGHT is pressed, go right;
Up will be overridden by any other direction; down will be overridden by left and right; left by right; and right will never be overridden.
This gives unequal directional behaviour which will confuse players, possibly causing a complete game success (enjoyment, re-play factor and possible forward potential if it's an advergame) into total failure (annoyance to the extent that the player quits playing for good, never forwards or tells anyone about the game and possibly creates negative connotations about any brand shown within the game!)
This is totally unacceptable, so I set about creating an intelligent input algorithm. The basic pseudocode I've turned into working ActionScript is the following (example of just the UP direction):
- Base logic layer:
-- When UP is pressed, upInputVariable = true;
-- When UP is released, upInputVariable = false;
- New Middle-logic layer:
-- Record previous frame's InputVariables states;
-- Compare previous and current InputVar states;
--- (If upInputVariable's state just changed to true) OR ((any other InputVarState changed to false) & (upInputState is still true))... then newDirectionRequest = "up";
- Top Movement Functionality layer:
-- If newDirectionRequest = "up", [do all the required actions to move avatar up]
If you followed that cheers for reading through it!
I'm happy with this, especially as I can see which games online haven't done this. Try it yourself, on a game where more than one direction can be pressed, experiment with which ones override the others. I've found that almost all have either not tackled the problem or used my easy fix.
More updates to follow...
Thursday, February 26
Hasstle, Bones & Movement
I've been experimenting with different rigging methods, as creating custom bones, controllers and IK chains (basically the hidden skeleton of a 3D figure which controls and limits it's movement in virtual 3D space) was taking a while for me to familiar myself with it again.
A 'biped' object is a shortcut which can be used if making a vaguely human-shaped figure. it is obviously less customisable but enables faster rigging time as all the bones are created, named and linked for you. Then the mesh can be added normally.
Here's a screenshot of the skin modifier's 'envelope' feature, which allows you to control how much each polygon around a specific bone will react to that bone's movement. This is used around joints where you want to restrict movement to only the mesh of a hand for example, and not the wrist area. You can either enter numeric values for each specific polygon, or if you don't want to be brain-dead within an hour you can adjust control points around the pretty colours in the viewports:

Monday, February 23
Uni Exhibition
At the end of this academic year, my course is holding an exhibition of every student's work. We need to agree on a theme. A couple have been suggested but not much thought has gone into it yet, so we've all been asked to slap an idea in a blog post. So here's mine:
I've been shopping around for a new PC system for a little while now, and the experience has inspired this idea. As prospective multimedia professionals we need to advertise our skills, experience, personality etc, so I think we could employ that exact metaphor - a series of adverts. As there's a strong digital focus to our work we could theme the exhibition like a technology company's, or high street technology shop's summer sale. With big, bold, colourful signage like this:

We could promote our skills and various details on old-school, mock-up software or hardware boxes. (I say old school as little comes in boxes off shelves any more). Boxes like this:


We would obviously decide on a more restricted colour pallatte than these specific colours, but you get the idea. Big, bright, 'shouty', print advertising. Almost over-selling our stuff possibly, but done in a professional way, not tacky!
I've been shopping around for a new PC system for a little while now, and the experience has inspired this idea. As prospective multimedia professionals we need to advertise our skills, experience, personality etc, so I think we could employ that exact metaphor - a series of adverts. As there's a strong digital focus to our work we could theme the exhibition like a technology company's, or high street technology shop's summer sale. With big, bold, colourful signage like this:

We could promote our skills and various details on old-school, mock-up software or hardware boxes. (I say old school as little comes in boxes off shelves any more). Boxes like this:


We would obviously decide on a more restricted colour pallatte than these specific colours, but you get the idea. Big, bright, 'shouty', print advertising. Almost over-selling our stuff possibly, but done in a professional way, not tacky!
Tuesday, February 17
Texturing Progress
Texturing continues. I'm keeping the detail level average, adding pockets, buttons and some details on the shoe, but I'm maintaining a 'cartoony' style with the bold colour scheme. Here's what the still unnamed geezer looks like now:

I've re-acquainted myself with Photoshop's range of brushes, painting onto rasterised layers. I quite like the detail I've got on the eyebrows (although a little 'The Hood from Thunderbirds-esque' at the moment!):
Friday, February 13
Progress in baby steps.
My project for an external client progresses a little more. With the mesh unwrapped I've got the UVW data file sorted and I'm now ready to texture!
It seems like the project is moving very slowly as I'm spending so much time/effort on the avatar; perhaps this is a sign I'm spending too long on it, but I'm still keeping up to the schedule I drew up so I think I'm still in good shape. I say "still" because I know the likelihood that I wont be on schedule towards the end of the project is pretty high, as this is the pattern which arises across every project I've ever worked on, and I'm sure crops up in almost every professional's work.
So, out of Max and into Photoshop. I've got out my 'Pen Tool' and have all the basic shapes pathed out:

I do realise the fact that a large rectangle over each body part's area would have sufficed for background texture colour, but apart from practising my pen tool skill I've done it like this to help visualise the end 'look' while creating the texture. Another pre-visualisation technique I like to use is drawing everything at around 72% opacity (obviously depending on the colours you're working with), so that both the seams the shape edges are visible. You can see above, the green lines represent the seams and the large dark grey shapes are actually #000000 black shapes at a lower opacity, and both are clear.
Keep pressing on; baby steps!
It seems like the project is moving very slowly as I'm spending so much time/effort on the avatar; perhaps this is a sign I'm spending too long on it, but I'm still keeping up to the schedule I drew up so I think I'm still in good shape. I say "still" because I know the likelihood that I wont be on schedule towards the end of the project is pretty high, as this is the pattern which arises across every project I've ever worked on, and I'm sure crops up in almost every professional's work.
So, out of Max and into Photoshop. I've got out my 'Pen Tool' and have all the basic shapes pathed out:

I do realise the fact that a large rectangle over each body part's area would have sufficed for background texture colour, but apart from practising my pen tool skill I've done it like this to help visualise the end 'look' while creating the texture. Another pre-visualisation technique I like to use is drawing everything at around 72% opacity (obviously depending on the colours you're working with), so that both the seams the shape edges are visible. You can see above, the green lines represent the seams and the large dark grey shapes are actually #000000 black shapes at a lower opacity, and both are clear.
Keep pressing on; baby steps!
Thursday, February 12
...And More
A bit of late night (well, 8pm's probably early night) UVW unwrapping. I've now done the shoes. I went for a bit of an arguably unnecessarily detailed method; I've done each shoe with a top, ouotside, inside and bottom. Even though the extra hour it took me to seperate will only go into making it possible for me to design a more detailed shoe texture accuratly, I think it'll be worth it in the final game.

This may present a challenge for myself later - I may have set the bar too high for me to design a similarly detailed level, so I may have to (due to time constraints) settle for a visible difference in avatar and level detail.
We'll see.

This may present a challenge for myself later - I may have set the bar too high for me to design a similarly detailed level, so I may have to (due to time constraints) settle for a visible difference in avatar and level detail.
We'll see.
Work Work Work
Very busy week catching up with my research project into online viral games and their humour!
I should have forseen just how different people's humour preferrences would be. It's making the test-preparation and conclusion-drawing parts very VERY challenging. I can see myself a couple of months down the line, presenting the fact that I have concluded nothing about humour I didn't already know. I must try and screen tests on a lot of different types of people (not that I'm into catagorising people, I just have to get as diverse a cross-section of internet users as I can, in order to draw accurate conclusions about general users.
Sigh. oh well, I'll do what I can to the best of my ability - which should be enough for a decent grade, so long as I mentain a professional attidude about the reseach.
Back to my 3D work for my Flaswh game; more UVW unwrapping. Here are some stills:
Yes, the hands look odd unwrapped, but they hgave a nice cartoon-style look in 3D I think. I'll of course get some other opinions before finalising the model to make sure I'm not going off on a tangent thinking it looks good when it doesn't!
Thursday, February 5
Ahh Wrapping
I remember, for some obscure reason, UVW unwrapping being enjoyable, quick and easy. Of course it's not. Especially on a big turbosmoothed geezer! Oh well, comes with the trade I guess. don't get me wrong, I do enjoy doing this. When I realise I'm doing something cool I do smile while I'm working. (the term cool being used in a fairly personal sense - i.e. I think it's wicked, therefore I 'get a smile on') Here's the screen I was looking at while I got my most recent smile on:

If you click this thumbnail you can see the size/resolution of the monitor I'm working with. Perhaps going into uni to work is something I should have always done!

If you click this thumbnail you can see the size/resolution of the monitor I'm working with. Perhaps going into uni to work is something I should have always done!
3D Work Continues
A bit more stuff done (over two days as opposed to my planned one day - flippin' interruptions).
I've got rid of that ridiculous crease in the lower arse cheek after lots of messing about:
I've got rid of that ridiculous crease in the lower arse cheek after lots of messing about:
I think the lesson from that experience might either be "patience and effort pays off" or "build things better at the beginning and they'll be easier to work with later". The latter is a very common message in my reflection on everything I do, so it's probably the lesson here too.
I have discovered how amazing the 'soft selection' feature of 3DsMax is, as you'll see below. It makes building things which aren't square (like I'm used to building from my 3D playable Unreal Tournament level) much much easier. I find it's more 'artistic', I'll explain...
I think of it as... instead of "you, vertex, I want you there!", 'soft selection' says something more along the lines of "you, and those around you who wish to, up to about this point, can move a bit in this direction if you like".
Also if you deselect the object while the vertices are still sub-selected you can make pretty colours on the turbo-smoothed object. I call this pointless playing during a time out from proper work the 'rasta beenie hat' effect.
I've also now added the bones (but not expanded the fins yet), and controllers for the animation of the walk cycle:
So the geezer is coming along, but I need far more productivity from each session. Essentially I need to WORK FASTER.
Tuesday, February 3
Another Tri-Project Project Update
Hello again, cheers for reading.
Last week I managed to underestimate the time it would take to design, tweak and integrate a new front end (including a new audio track too), for my Flash game research project. Unfortunatly I've not therefor been able to present any results form the testing of this first artefact as it's not finished yet.
This hasn't made my head go down though! I'm now a little wiser and a little more urgent in my thinking about work. You must start something always with the aim to finish it. Schedules help of course, but making better schedules with more detail helps even more; and planing for the unexpected is an invaluable addition to the schedule (errors etc). This is where I messed up. ERRORS TAKE TIME to solve.
Back to the client project side of work. I'm creating the 3D businessman avatar which will replace the 'red boxy' placeholder in the previous 3D test renders. I'm now using 3DsMax 2009 using the uni machines as my laptop has been grinding to an inevitable halt for the past few weeks and has finally pushed my patience to the max, and I simply cannot work with it on big production projects like this. So it's off to work I go now, every day into uni, (hi ho hi ho), untill I find the funding to replace my system at home.
Here what I finished day 1 with (again, click to enlarge and get full detail, not that there's much of that stuff yet!):

On a technical note, I found that turbosmooth take out a lot of basic detail I wanted to keep. To solve the 'flat bottom of shoe' challenge you make another set of edges on the sole of the foot; but how can I keep the detail of the collar/neck shape I wonder? Maybe create the figure in seperate shapes: body & head, then I can apply the same method as the shoes. Well that's the challenge for day 2 anyway.
Onward and upward!
This hasn't made my head go down though! I'm now a little wiser and a little more urgent in my thinking about work. You must start something always with the aim to finish it. Schedules help of course, but making better schedules with more detail helps even more; and planing for the unexpected is an invaluable addition to the schedule (errors etc). This is where I messed up. ERRORS TAKE TIME to solve.
Back to the client project side of work. I'm creating the 3D businessman avatar which will replace the 'red boxy' placeholder in the previous 3D test renders. I'm now using 3DsMax 2009 using the uni machines as my laptop has been grinding to an inevitable halt for the past few weeks and has finally pushed my patience to the max, and I simply cannot work with it on big production projects like this. So it's off to work I go now, every day into uni, (hi ho hi ho), untill I find the funding to replace my system at home.
Here what I finished day 1 with (again, click to enlarge and get full detail, not that there's much of that stuff yet!):

On a technical note, I found that turbosmooth take out a lot of basic detail I wanted to keep. To solve the 'flat bottom of shoe' challenge you make another set of edges on the sole of the foot; but how can I keep the detail of the collar/neck shape I wonder? Maybe create the figure in seperate shapes: body & head, then I can apply the same method as the shoes. Well that's the challenge for day 2 anyway.
Onward and upward!
The audio stream player I'm working on for my uni's student radio station now looks a little nicer. After messing about with some layer styles in photoshop I wrapped a text frame in some coloured stripes which somewhat resemble the current station's branding. I think it looks pretty nice. What do you reckon?
Friday, January 23
A Tri-Project Update!
Firstly, Happy New year you masses of people who read my blog!
I am hard at work on two university projects and an extra one on the side - a little optemistic I know, but that's how I like to work; aim high and you'll shoot high.
I'm working on a viral advertising project for an external client, in the form of a Flash game designed to both showcase the company's product and get sent around potential clients, as all good digital viral advertising material should.
I've been playing around, in an attempt to again better the visual side of my work, by experimenting with exporting frames from a 3DsMax animated model into single frames in a Flash movie clip with the appropriate ActionScript to control the illusion of a 3D avatar.
I am hard at work on two university projects and an extra one on the side - a little optemistic I know, but that's how I like to work; aim high and you'll shoot high.
I'm working on a viral advertising project for an external client, in the form of a Flash game designed to both showcase the company's product and get sent around potential clients, as all good digital viral advertising material should.
I've been playing around, in an attempt to again better the visual side of my work, by experimenting with exporting frames from a 3DsMax animated model into single frames in a Flash movie clip with the appropriate ActionScript to control the illusion of a 3D avatar.
I've experimented with both potential types of viewpoint and control set I planned for on paper for the game. Click on each icon for the respective test renders:
Project #2 is a research project, again for university coursework. As you know from my previous posts, I'm looking into the use of humourous tools in viral games design.
For this practical part of the project I'm using the basic game engine from 'Platform 1', which I made last year. I'm stripping the graphics and improving some of the functionality, such as making the balance variable into continuous number (i.e. the value could be any real number within a certai range as opposed to simply integers). The HUD functionality will also have to be changed to accomodate this change, calculating the .rotation property of the guage needle from the balance variable with respect to the maximum and minimum values, (which will be quite straight forward as I've created similar algorithms for the speedo needles in my 'Low Rev's' game!).
This game will then be ready to apply 6 different 'humour profiles' or 'themes' to. I'll also create a fake brand to incorporate into the game to simulate the viral advertising functionality of the game. I will then show it to a range of people and analyse their reactions and to what extent the branded messages are conveyed to them, in an attempt to find out what the trends in humour appreciationare in the current cultural climate, and what effect the type of humour used has on branded message communication.
Finally, as a side project I'm building a Flash audio streaming applet for my uni's student radio station: Fly FM, entitled... yes it FlyPlayer, although obviously I may change this. All is going well, in fact after much messing around with different streaming methods and searching for the correct location of the audio data, (i.e. the next time I see any kind of playlist file extention I may punch my screen through) I've cracked it, and FlyPlayer officially works.
I still have to add the functionality of playing old shows and displaying information which I'm not phased about. The archive will be made up of mp3s (AT A URI OF MY CHOOSING THIS TIME), and the information input I'll control with an XML file.

Project #2 is a research project, again for university coursework. As you know from my previous posts, I'm looking into the use of humourous tools in viral games design.
For this practical part of the project I'm using the basic game engine from 'Platform 1', which I made last year. I'm stripping the graphics and improving some of the functionality, such as making the balance variable into continuous number (i.e. the value could be any real number within a certai range as opposed to simply integers). The HUD functionality will also have to be changed to accomodate this change, calculating the .rotation property of the guage needle from the balance variable with respect to the maximum and minimum values, (which will be quite straight forward as I've created similar algorithms for the speedo needles in my 'Low Rev's' game!).
This game will then be ready to apply 6 different 'humour profiles' or 'themes' to. I'll also create a fake brand to incorporate into the game to simulate the viral advertising functionality of the game. I will then show it to a range of people and analyse their reactions and to what extent the branded messages are conveyed to them, in an attempt to find out what the trends in humour appreciationare in the current cultural climate, and what effect the type of humour used has on branded message communication.
Finally, as a side project I'm building a Flash audio streaming applet for my uni's student radio station: Fly FM, entitled... yes it FlyPlayer, although obviously I may change this. All is going well, in fact after much messing around with different streaming methods and searching for the correct location of the audio data, (i.e. the next time I see any kind of playlist file extention I may punch my screen through) I've cracked it, and FlyPlayer officially works.
I still have to add the functionality of playing old shows and displaying information which I'm not phased about. The archive will be made up of mp3s (AT A URI OF MY CHOOSING THIS TIME), and the information input I'll control with an XML file.
Here's a glimpse of what the player may look like. For now you're going to have to take it from me, it IS streaming FlyFM at the time of the screenshot! Happy Days:

Subscribe to:
Posts (Atom)











