Friday, 18 July 2014

Dog Poop Pinching

I just ran across this...


But, this was no prank, this happened to me last night... The wife and I were out with all four dogs, the three little (young ones) and the wife, whilst I walked quietly with our 12 year old Labrador... So Dude and I are just down a grass bank, and we're going to come back that way, so when Dude does his thing I bag it and leave it against the side of this slope, so I can head back up and out once with him...

We walk along a little way, not far, and as we stop to turn around and meet the wife with the other three dogs this old fellow passes by me and he's got my poop in his hand.

At first I thought, he's going to tell me I left it, and I'm going to have to show him the five other bags from the other dogs and point out how old Dude is and that he comes out once and back so as not to knacker his joints...

But...

But the guy just goes straight past me and the wife, without saying a word... Not a word, not a "I'm just taking it to the bin, no sweat"... not a "I think you left this"... Nothing, he just drilled right on by us... Like he's won a prize or something.

Bit weird.

Monday, 14 July 2014

Gaming Update - WarThunder, World of Tanks, CivV and MechWarrior

I slept like a log last night, I think finally having picked to support a Team in Germany and their winning a match satisfied me... I did actually shout out when they scored... Though I didn't like the propensity of the commentators on both BBC and ITV to support Argentina because they apparently like Messi... But, each to their own I suppose, I don't think he was worthy of "player of the tournament", I actually think his performance looked somewhat lacklustre over all.  I don't doubt there were bursts of brilliance, but the radiant glow out of his backside didn't shine so bright as to eclipse others.

Anyway, football aside, I played games... I played World of Tanks, I played WarThunder, I played Civilization V and I played MechWarriorOnline...

WarThunder
I spent the most of my time in WarThunder, initially I got my Track IR4 and my Seitek X45 out and set about setting up the simulator standard controls.  I've got to be honest, I still find setting up the controls in WarThunder to feel very soppy, its not a clean interface... There are ways to slide and slip "yes" to "no", but to my eye the indicators point backwards, and the axis auto-detect was okay, but I kept second guessing what I was doing... "Put your axis...bla"... And you're looking and wondering is that "bla" or "bla"... but Bla was BLA!... Just doesn't sit right, I'd have to say perhaps a native English speaker should have a trawl through the process there and give Gaijin a flow chart to improve it for English speakers... As I have spoken to a native Russian speaker and they informed me that it made perfect sense to them... One can only say it's a culture thing perhaps?

One thing I am certain of however, and its something SideStrafe mentioned in his latest Strafing Run that Gaijin don't like to be told there are problems with their product... I'd love to know what SideStrafe found issue with and reported to them, but I have a fair few items sent their way - both privately and openly on the moderated bug forums - and the more I see such issues, and the more evidence of them I seem to have sent, the less feedback I get.


It is rather strange to have a group so eager to talk to you, but the moment you find fault they sent you into Coventry.  I'd call it rude, but then I'm English and what we consider rude seems to engulf half of modern day fashion & life styles.  But having spoken to a few peeps it seems to perhaps be an Eastern European thing... Folks working on the Witcher didn't like criticism... WarGaming don't like it... and it seems Gaijin don't either.

So, what of the games I've played, well first of all, the latest patch to WarThunder, allowing queuing on specific servers has cured one problem.  I used to play the game set to "Any Available" server, now I can set it to use five different servers and I'm getting a whole lot more games a whole lot faster.

For a long time queues in the client looked like this:




As you can see the American bent on the nations being queues was obvious.  Now however numbers are much higher in all tiers and nations, and one can pick and choose to play however one wants, which is very much a welcome sight.

I've also spent a lot of time playing Arcade Ground Forces, to unlock and skill up my Russians.  I've pushed right up the T34 line and really enjoyed playing!

I have to say there's a huge difference in the fire power of Russian to German Tanks, the Russians are much more fun to play in the low tiers, and it was not until I got hold of the 50mm L11 gun on the Panzer III did I have as much fun with the Germans.  Though I do love to jump out in a Panzer II with its 20mm and kill Stugs which other players are battering over and over to no avail... Just shoot the optics folks!


Another issue has been the number of players who are just seemingly inert to the positions around them, above you see me in one of my T34's taking the conquest point... We actually won this game... because I stopped and took the point and then held it... The chap there in the other T34, he had been sat by the side of the cap - even with enemy tanks in the cap circle - and was just sniping over at any enemy approaching... GET IN THE CAP CIRCLE PEOPLE!

Another activity I partook of was in test flight mode, trying to land various aircraft on carriers:


Like a Spitfire IX... bring them in low and slow, almost at the stall, and then drop them onto the deck, it worked most of the time, and proves you could reload some of the most unexpected aircraft on a carrier (at least in realistic mode, I doubt its possible in Simulator)...


Sometimes it went a bit wrong, but a repair is a repair, and off you go again... (Note: You don't have to take off from the deck, it puts you about 5km behind the ship going at full speed around 1000ft).

Another WarThunder item was the magic bullet, yet there's more ricochets sometimes than in an episode of the A-Team, here we see my T70... The indicator says I'm getting shot from my right... I'm already burning... So why am I not looking right?...


Well, firstly, I find the feedback system for tank damage in WarThunder to be wholly inadequate, it gives too little feel for where the damage it coming from, and though the sound effects are good they're not very directional - I've sat in a tank being hit with a 12lb lump hammer - you can tell which direction the hammer blows are coming from, it is not; as modelled in the game; like being in a bell chamber with reverberation all around.

But, here the red indicator is enough I know where the enemy is, so why is my camera looking the other way?...

Well, first of all, I was trying to see HOW the guy to my right was shooting me... well he was shooting me through a rock and a piece of ground... But worse still the animation for the shot was not coming from the right of my tank, it was coming out of that black pock marked rock to my left!...


I checked my replay, and it did not show this, it must have been a quirk at the time of playing in the actual engine... But it damned annoyed me.

World Of Tanks
Enough of WarThunder, I also played some World Of Tanks... I played two games... You know what, I don't think I'm going to play that game much more... Compared to ground forces its not very good, there's too elitist an undertow, you have to know the maps, you have to grind like crazy... and it doesn't leverage the full power of my machine to play, plus to have any hope of getting along decently you have to have memorised maps of the terrain in your minds eye, and a bunch of mods added which should be there by default... All in All, I think WarGaming need to improve dramatically as I'm swinging wildly towards playing WarThunder almost exclusively for my Air and Ground battles...

Civilization V
When I bought Civ5 (digitial pre-release) I was so excited, but I didn't get along with it... I think Civ2 remains the best in the series... and I liked Civ3 a lot too... But Civ5, I simply do not like, the hex's are okay I lived with that... The graphics are good, but the whole experience seems .. I dunno... Spongy to me... Don't like it, and I think the controls are a step too far away from the older series - I know a lot of them are common - but city controls are different.


However, I came back to play again try the game on maximum graphics settings and DirectX11 mode on my new Graphics card... Meah, still not impressed... So parked that one.

MechWarrior Online
The next title I dropped my eyes across, and which I've left installed, is MechWarrior Online. 


I came across this game from SideStrafe's coverage on YouTube, and I was always a big fan of MWO - played them years ago on my 486!  But this update was online, multiplayer and free to play!


I signed up and soon found myself in battle - more about that later.


My initial impressions are promising, I like the game, I like the look... And the battles are fairly easy to get into...I have a bone to pick with the interface again, in the hangar it is really complex, I've yet to find out how to customise a mech, and the myriad (literally hundreds) of mechs listed I'm not entirely sure what's going on.

I've roughly figured how to pick a mech and get playing, but I've no idea really what's going on... I need to investigate further.

My other problem with the game is that someone else has the name "Xelous"... I am Xelous, who the hell are they?!?!?!?!?!  So I had to sign up as "LordXelous" in that game.  I hate when my username is taken like that.

Sunday, 13 July 2014

Germany v Argentina - Who does an Englishman Support?

Its agony, total agony, who to support for the World Cup Final?!??!



I'd of course started off the cup supporting England, I knew the fall was coming so was not surprised when they lazed their way out of contention, at least we weren't drubbed like Spain or Brazil.

I set my sights on supporting our near neighbours then, so I supported Belgium, the Netherlands and even France against Germany... All to fall at their respective hurdles.

I thought the Netherlands loosing on penalties was very stinging, I'm convinced they played the better game, and I really don't like the Argentine attitude, either on the pitch or off.

But both Argentina and Germany have history with us here in Britain, Wars mainly, and both are still pains in our political backside, most recently Germany with the PM loosing his case against J C Junkers getting into office, and their interminable economic dominance of the continent they tried to take by force in the 40's.

But then the scars of that conflict are old, and played as computer games, and if not forgotten they've been forgiven.

Its the centenary of the first world war too, so we're not forgetting that great conflict at German hands either, but still I'm more riled by the Argentines.

Their attitude over the Falkland islands has not gone unmentioned on this blog before, their politicians use of that topic to distract from home affairs problems they have, and their general blinkered approach to the islanders themselves voting to be part of the UK protectorate... It just beggars belief that the rest of the world doesn't look at them a bit more lob sided when they start sounding "Viva las Malvidas" or what ever they call them... Because if you've ever met a Falkland Islander (and I have) they have a slight Norfolk style twang to their very English/British accents!

They have red letter boxes, and red telephone boxes, even the Argentine soldiers who landed in 1981 said "we landed and took a look around, and realised this was nothing like back home", "we'd been taught the island was part of Argentina, taken from us, but there was no sign of home here, it looked like London on the postcards", "we knew we were a long way from home when we saw the people, for some reason we expected them to speak Spanish, then there was the car crashes as they drove on the left".

It all said it all really, but those accounts get ignored, and I think quite strangely when the British forces had cleared up they offered to return the Argentine dead to their homes, but they refused, they refused those grieving families the chance to bury their Sons, Brothers, Fathers and Uncles.  Instead making the political statement that the dead should be buried on the Falklands, as it was "part of Argentina", this from an illegal government who "disappeared" millions of innocent civilians and orchestrated and illegal war, nice moral high ground there lads.

I can tell you now folks, we British have buries so very many of our forefathers, Ruper Brooke said it best:

IF I should die, think only this of me;  
  That there's some corner of a foreign field  
That is for ever England. There shall be  
  
In his poem "The Soldier", he spoke of the first world war, but it fits so aptly with our British experience in the middle east, the far east, India, Malasia, across the battlefields of the ages the British Empire stuck its ugly nose.

So we know when you're not wanted, and not liked, and the Falklands are an area where Argentina bark up the very wrong tree...

So, with all that said, I'll just have to support Germany for the Final...

Saturday, 12 July 2014

Aircraft Graveyard Photographed

I saw this one on the Telegraph, and found it strangely compelling, I'm going to go look up that young photographer, see what else he has in his back pocket.



Friday, 11 July 2014

Reckless HIV Mother

I was just reading about the "cured HIV" baby case, the "Mississippi baby" as she's known her mother with HIV, she was the basis of a study of importance to the whole world, giving early powerful retro-viral drugs to stop HIV reservoirs forming...


Unfortunately the reservoirs were there and HIV returned to the child.  So the study is a bust... Or is it?

You see, read the story, and the real story here apart from the medical one is a human one, this child in what we all know to be a struggling part of the US, was not present for all the study...

The report says it all, she was given the powerful treatment at birth, continued for 18 months... Then doctors could not locate her... This is a baby.. so the mother took this child away from potential life saving treatment, away from a study important to the whole world... and then 10 months later okay she reappeared with no sign of infection, but the infection has returned at age 4.

Whether, because the mother took the child away, or because of a re-emergence, or simply because she was likely living with her mother whom had HIV and reacquired it, we will never know for this child, the world stands pretty much now with a more complex study to perform, through the apparent apathy and departure of that parent.

This problem is then further emphasised with the second case in LA where that child appears to be cleared of the virus, but has received ongoing treatment.

The "Mississippi baby" is 4 now, if that child makes it to 16 or 21 and can comprehend their position in this study, I hope they see the actions of their mother as reckless as I do.


Thursday, 3 July 2014

Pseudologia Fantastica (Pathological liar)

I've been doing a little reading on a couple of areas of Psychology.  I'm no psychologist, but I'd love one of my readers to be one, because I'm interested in describing a character to them; a member of my wife's family in fact; and seeing what they think about their character traits.

The reason being that this person has been unable to function in society for the last few months, so I along with my wife's family have been supporting them.  However, they're finally coming to the situation where they'll be returning to society.

It's therefore time to hand their affairs back to them, and systematically the important items this person is ignoring.  They're not in the midst of a break down, they're not mentally deficient, they're simply refusing to see reality and normal standards of living, they want to life and do things their way, and to hell with the consequences.

They're full able to comprehend the situation and the items on the itinerary, but they are wilfully and systematically ignoring everything which needs sorting, and then making up diatribes trying to make things true from their perspective.

True... An interesting word, important for us programmers, and psychologists a like... Because it contains a flip side, its binary opposite, false...

And this boolean logic, this simple state of black or white, on or off, right or wrong is pretty much a dance this person is running themselves through, they sit like the needle of a record player whirling around on the turn table of life, and they play the same old platitudes, they say the same old things, but they're lying.

I've found out this person has been a liar since childhood, since before the age of five in fact.

I've found they were not really pulled up on the act of lying, it was pointed out to them, but never punished, never nipped in the bud, and so as their life has unfolded they've always got on, but always been ready to lie.

Either to save their own skin, or to get out of tricky situations, but mostly to always turn a situation around so as they looked more favourable, so that they could play on your heart strings and pretty much so they looked a victim.

I'm from a very rough part of Nottingham, much rougher than were this person grew up, and much rougher even than we'd like to admit... But it hardened me to liars, spotting them and pointing them out for what they are.  Not that I jumped to adversely judge this person.

But with carolling their spiralling personal affairs, with chasing around dozens (yes dozens) of different points of paper work for them - DVLA, HMRC, Banks, Insurance, Advertising, Business, Rent, Electricity Bills, Gas Bills, Telephone contracts and a myriad of other official documents - it was obvious something was not right.

So with their returning to society soon they need to know the state of play, they need to know all these balls are being juggled and they need to leap in and take over, this is how you run your life... Their reaction...

"You're a drama queen, fill your boots, you're only making things worse"

Never in my life as a more thorough insult, a more thorough brushing over of the dozens of issues I've handled for someone, the tens of hours spent sorting things for them been more thoroughly and abjectly thrown out and ignored.

This wilful self destruction beggared the question of "Why", why put yourself through the stress of everything going wrong?  Why put yourself out there for the fall?  Why not just run your day to day affairs?

And it dawned on me, this person doesn't run anything, they don't try to run their own life, they don't bother, they life in a little pocket of reality where they do their own thing... Except they don't, they have to pay taxes, and pay rent, pay the bills and exist like the rest of us, they choose to have a car, they choose to live in a house, so they have to pay...

But they fantasise that none of this affects them, that it'll all be all right... And they lie to themselves and everyone around them that "it'll be all right", and this is where they find themselves, so I'd love to speak to a psychologist about them.  I mean, I'm not dumb, but I don't profess to know about mental health all that much - though my wife has some mental health nurse experience & training - and I can read between the lines of their behaviour and that of expected, decent, society and I see a person suffering from "Pseudologia Fantastica"; however, since I've been so thoroughly relegated in their minds eye as a fool, they can frankly go fuck themselves.

Wednesday, 2 July 2014

Java - Game Development - Series 1 - Bubbles

Here we go folks, this is hopefully an interesting - if long winded - series of videos of my live coding you a game in Java.


Game Idea
The game is a pretty simple idea, its just bubbles on a screen, when you click on them and they have a matching colour neighbour they "pop", the columns drop down and then the empty columns shuffle to the right.

Scoring is each bubble is worth 2 to the power of the number of bubbles popped... so 2 + 4 + 8 + 16 etc for each bubble... and then when there are no more moves its game over.

There's no menu, no reset, no confusion... We just need to double buffer the frame and loop the game around based on the mouse clicking...

Our development environment is the Java Development Kit, so you can pretty much get this set up for ANY platform - your PC, your Mac, on your tablet, your phone - so give it a try...

Video Play List
You can watch the whole - silent (I hope) video series here - just throw on tunes of your choice and let the play list run away with you.

Video Series
Individually, with my explanations...


That's of course for Linux, my chosen operating system for my development series...

Once built I can carry the .class file to ANY machine able to run Java and run it, pretty neat!


So that's "Hello World"...


That's the double buffering on the Frame, and the loop.


Right the first iteration we have the grid data and we draw it with rectangles...


Now we need to create the images, load them, and draw them because lets face it, Bubbles are round, not square!


Interacting with the mouse means mapping the click point to the bubble being pressed on.


Once we click on something, we really need to pop the bubbles around it of the same colour... This leaves a gap...


So now we move the Bubbles down in each column as they leave gaps.


This is a bit of debugging, but we shuffle the empty columns from left to right.


Finally, we score each bubble popped in a scaling factor and we add a check for no more moves which sets game over.

Summing Up
In our code we have created a lot of functions, and you could see in the one code file by the end I was moving around the code a lot, but had no structure, functions could be anywhere.  I'd perhaps go back and order the functions alphabetically, or into regions in other languages (C++ or C#) just to make things easier to maintain and move around.

The code itself is not bad, it's not great, but it is a lot better than other code I've seen created on the fly like this, and I've added the minimalist comments just to help guide people through the code.

During the development you saw my use of "System.out.println", I used this to help debug because I was just coding with an editor & the compiler, if I had an IDE (eclipse perhaps) set up with a debugger I'd not have used that development hack to get into the look of things.

I'd also have to say the code is not thread safe, I could be processing the grid whilst a click comes in on platforms which thread differently... So beware of that.

Your Development
If you've got this far, and got the code, then you can follow along how the current code was built up... But what could  you do to improve the code?

Well, I'd like to see you guys and gals come back to me with improved versions of this tackling the following:

i) Adding a Restart Button - when game over flags up - add a button/image to the bottom right to reset the game back to the start... Difficulty Easy.

ii) When each bubble pops, animate it popping... Difficulty Hard.

iii) Add an animation for the Score each "pop" summing up... Difficulty Medium.

iv) Add a high score chart, which saves the player name as 3 initials input by the user... Difficulty Easy/Medium.

v) Turn the game into an Applet to embed in a web page!... Difficulty Medium.

Please Note: iv and v above are not compatible, you can't save to disk from an applet.

Source Code
import java.*;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Cursor;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.*;
import java.util.Random;
import java.util.ArrayList;
import java.lang.Math;
import java.io.*;
import javax.imageio.*;

public class bubbles
extends Canvas
implements MouseListener, WindowListener
{
// The maximum number of colours
// we're going to handle
private final int c_MaxColours = 5;

// The screen size we're working to
private final int c_ScreenWidth = 450;
private final int c_ScreenHeight = 320;

// master running flag
private boolean m_GameRunning;

// Drawing strategy
private BufferStrategy m_Strategy;

// We need a score!
private long m_Score;
private int m_PoppedThisCycle;
private boolean m_GameOver;

// Our game has bubbles, which you click to pop
// and the bubbles move down in the heap... you
// can only click and pop bubbles with at least
// one neighbour the same colour...

// We need a grid of bubbles, and need to know
// the size of the bubbles...

private final int c_BubbleSize = 30;
private final int c_GridWidth = c_ScreenWidth / c_BubbleSize;
private final int c_GridHeight = c_ScreenHeight / c_BubbleSize;

// The live grid data
private int[][] m_Grid;
private int m_GridWidth, m_GridHeight;

// The images of our bubbles
private ArrayList<BufferedImage> m_Images;

/// Constructor
public bubbles ()
{
// The score & game over reset
m_Score = 0;
m_GameOver = false;

// Create the container frame for this
// application
JFrame l_container = new JFrame("Bubbles");

// Get a panel from the container
JPanel l_Panel = (JPanel)l_container.getContentPane();
l_Panel.setPreferredSize(new Dimension(c_ScreenWidth, c_ScreenHeight));
l_Panel.setLayout(null);

// Set up the canvas
this.setBounds(0, 0, c_ScreenWidth, c_ScreenHeight);
l_Panel.add(this);

// Set to self repaint, in order to speed up
// the drawing process
this.setIgnoreRepaint(true);

// Finally, make the window visible
l_container.pack();
l_container.setResizable(false);
l_container.setVisible(true);

// Add this as the close handler
l_container.addWindowListener(this);

// Add this to listen to its own
// mouse events
this.addMouseListener(this);

// Create double buffering
this.createBufferStrategy(2);
m_Strategy = this.getBufferStrategy();

if ( LoadImages() )
{
InitGrid();
}
else
{
//System.out.println ("Error, unable to load images");
}
}

// Draw the score
private void DrawScore(Graphics2D p_g)
{
p_g.setColor(Color.black);
p_g.drawString("Score: " + String.valueOf(m_Score), 10, c_ScreenHeight - 5);
}

// Draw the game over
private void DrawGameOver(Graphics2D p_g)
{
if ( m_GameOver )
{
p_g.setColor(Color.black);
p_g.drawString("GAME OVER", (c_ScreenWidth / 2) - 30, c_ScreenHeight - 5);
}
}

// Load all the images in order of the colour
// 0 = red
// 1 = blue
// 2 = yellow
// 3 = green
// 4 = pink
private boolean LoadImages()
{
boolean l_result = false;

ArrayList l_tempImages = new ArrayList();
if ( AddImageToArray(l_tempImages, LoadImage("red.png")))
{
if ( AddImageToArray(l_tempImages, LoadImage("blue.png")))
{
if ( AddImageToArray(l_tempImages,LoadImage("yellow.png")))
{
if ( AddImageToArray(l_tempImages, LoadImage("green.png")))
{
if ( AddImageToArray(l_tempImages, LoadImage("pink.png")))
{
l_result = true;
m_Images = l_tempImages;
}
}
}
}
}

return l_result;
}

// Add an image to the array
// if none are null, so its
// safe to add things
private boolean AddImageToArray(ArrayList p_ImageArray, BufferedImage p_Image)
{
boolean l_result = false;
if ( p_Image != null &&
p_ImageArray != null )
{
p_ImageArray.add(p_Image);
l_result  = true;
}
return l_result;
}

// load the buffered image
private BufferedImage LoadImage(String p_Filename)
{
BufferedImage l_result = null;
try
{
l_result = ImageIO.read(new File("./images/" + p_Filename));
}
catch (IOException ioe)
{
//System.out.println("File not found [" + p_Filename + "] in images folder");
}
return l_result;
}

// Initialise the grid with random colours
private void InitGrid()
{
// The grid itself
m_GridWidth = c_GridWidth;
m_GridHeight = c_GridHeight;
m_Grid = new int[m_GridHeight][m_GridWidth];

// Random number gen
Random l_Rand = new Random();
// Randomize the start position
for (int y = 0; y < m_GridHeight; ++y)
{
for (int x = 0; x < m_GridWidth; ++x)
{
int l_RandomColour = l_Rand.nextInt(c_MaxColours);
m_Grid[y][x] = l_RandomColour;
}
}
}

private void DrawGrid (Graphics2D l_g)
{
for (int y = 0; y < m_GridHeight; ++y)
{
for (int x = 0; x < m_GridWidth; ++x)
{
if ( m_Grid[y][x] != -1 ) // not a blank
{
DrawBubble(l_g, x, y);
}
}
}
}

private void DrawBubble (Graphics2D l_g, int p_x, int p_y)
{
if ( m_Grid[p_y][p_x] != -1 )
{
l_g.drawImage(
(BufferedImage)m_Images.get(m_Grid[p_y][p_x]),
(c_BubbleSize * p_x),
(c_BubbleSize * p_y),
null);
}
}

/// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**
/// The window listener events
// Exit the game loop
public void windowClosing(WindowEvent e)
{
m_GameRunning = false;
}

public void windowOpened(WindowEvent e)
{
}

public void windowClosed(WindowEvent e)
{
}

public void windowActivated(WindowEvent e)
{
}

public void windowDeactivated(WindowEvent e)
{
}

public void windowIconified(WindowEvent e)
{
}

public void windowDeiconified (WindowEvent e)
{
}
/// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-**

// Function to sleep the system
// for an amount of time - this is
// very rough and ready fornow
private void Yield ()
{
try
{
Thread.sleep(10);
}
catch (Exception e)
{
// Throw away
}
}

// Draw the time on screen
private void DrawTime (Graphics2D l_g)
{
l_g.setColor(Color.black);
l_g.drawString(String.valueOf(System.currentTimeMillis()), 10, 50);
}

// The function to draw something
private void Draw(Graphics2D l_g)
{
//DrawTime (l_g);
DrawGrid(l_g);
DrawScore(l_g);
DrawGameOver(l_g);
}

// Drops one column down
private boolean DropColumn (int p_Col)
{
boolean l_HasDropped = false;
for (int i = 0; i < m_GridHeight-1; ++i)
{
if ( m_Grid[i][p_Col] != -1 &&
m_Grid[i+1][p_Col] == -1 )
{
m_Grid[i+1][p_Col] = m_Grid[i][p_Col];
m_Grid[i][p_Col] = -1;
l_HasDropped = true;
}
}
return l_HasDropped;
}

// Now we need to shuffle bubbles down, whenever
// there is a gap below them....
private void ProcessDrop()
{
boolean l_flagged = false;
for (int i = 0; i < m_GridWidth; ++i)
{
if ( DropColumn(i) )
{
l_flagged = true;
}
}

if ( l_flagged )
{
ShuffleColumns();

if ( !CheckForMoves() )
{
m_GameOver = true;
}
}
}

private boolean IsColumnEmpty(int p_Col)
{
boolean l_empty = true;
for (int i = 0; i < m_GridHeight; ++i)
{
if ( m_Grid[i][p_Col] != -1 )
{
l_empty = false;
break;
}
}
if ( l_empty )
{
//System.out.println ("WE HAVE AN EMPTY COLUMN!");
}
return l_empty;
}

private void ShuffleColumnsFromLeftOf(int p_Col)
{
//System.out.println ("Shuffling columns left of " + p_Col);
if ( p_Col > 0 )
{
for (int i = p_Col; i > 0; --i)
{
for (int y = 0; y < m_GridHeight; ++y)
{
m_Grid[y][i] = m_Grid[y][i-1];
m_Grid[y][i-1] = -1;
}
}
}
}

// Empty columns, we'll collapse to the right
private void ShuffleColumns()
{
for (int i = 0; i < m_GridWidth; ++i)
{
if ( IsColumnEmpty(i) )
{
ShuffleColumnsFromLeftOf(i);
}
}
}

// The function to perform the game loop
public void Run()
{
m_GameRunning = true;

// Game timing/update delta
long l_lastLoopTime = System.currentTimeMillis();
long l_now;
long l_delta;

while ( m_GameRunning )
{
// Update the time
l_now = System.currentTimeMillis();
l_delta = l_now - l_lastLoopTime;
l_lastLoopTime = l_now;

// Now we need to draw?....
Graphics2D l_Graphics = (Graphics2D)m_Strategy.getDrawGraphics();

// Clear the graphics
l_Graphics.setColor(Color.white);
l_Graphics.fillRect(0, 0, c_ScreenWidth, c_ScreenHeight);

// Draw the game?
Draw(l_Graphics);

// Flip the buffer to show what's been draw
l_Graphics.dispose();
m_Strategy.show();

Yield();

ProcessDrop();
}
System.exit(0);
}

// Handle clicking on a bubble
private void ClickAt(int p_x, int p_y)
{
////System.out.println ("ClickAt " + p_x + "   " + p_y);


// Only process popping when we are NOT
// in game over
if ( !m_GameOver )
{
if ( p_x > 0 && p_y < (c_BubbleSize * m_GridWidth))
{
if ( p_y > 0 && p_y < (c_BubbleSize * m_GridHeight))
{
int l_px = (p_x / c_BubbleSize);
int l_py = (p_y / c_BubbleSize);

// Check whether this bubble can be popped
if ( CheckPop(l_px, l_py) )
{
// Now we can process the pop, and chose later to
// not "check pop" first, as you wish.
ProcessPop(100, l_px, l_py);
}

}
}
}
}

// Rather than just blank the target
// lets "pop" it and propagate the
// pops over to each neighbour
private void ProcessPop (int p_Colour, int p_x, int p_y)
{
// The tartget colour tells us whether
// we;re the start pop, or a follow up
int l_match = -1;
if ( p_Colour == 100 )
{
l_match = m_Grid[p_y][p_x]; // Get the colour target from the grid
m_PoppedThisCycle = 0; // First possible pop
}
else
{
l_match = p_Colour; // Take the input colour as our target
}

// Now, we've already checked pop, so technically
// don't need to do this, but we'll check, and let you
// carry on... to change the code as you want later
if ( l_match == m_Grid[p_y][p_x] )
{
// The neighbour index
int l_up = p_y - 1;
int l_down = p_y + 1;
int l_left = p_x - 1;
int l_right = p_x + 1;

// Pop the current position
m_Grid[p_y][p_x] = -1;

// Score the pop
++m_PoppedThisCycle;
m_Score += (2 * m_PoppedThisCycle);

// Pop up
if ( l_up > -1 )
{
ProcessPop(l_match, p_x, l_up);
}
// Pop down
if ( l_down < m_GridHeight )
{
ProcessPop(l_match, p_x, l_down);
}
// Pop left
if ( l_left > -1 )
{
ProcessPop(l_match, l_left, p_y);
}
// Pop right
if ( l_right < m_GridWidth )
{
ProcessPop(l_match, l_right, p_y);
}
}
}

// Function to check whether the
// bubble in the location can be
// popped, which means that its not
// already blank, and has a neighbour
// of the same colour.
private boolean CheckPop(int p_x, int p_y)
{
//System.out.println("CheckPop " + p_x + "  " + p_y);

boolean l_result = false;

int l_targetColour = m_Grid[p_y][p_x];

//System.out.println ("TargetColour is " + l_targetColour);

if ( l_targetColour != -1 )
{
// Get the indices for the neighbours
int l_up = p_y - 1;
int l_down = p_y + 1;
int l_left = p_x - 1;
int l_right = p_x + 1;

// Check upwards
if ( l_up > -1 )
{
if ( m_Grid[l_up][p_x] == l_targetColour )
{
l_result = true;
//System.out.println ("UP!");
}
}
// check down
if ( !l_result && l_down < m_GridHeight )
{
if ( m_Grid[l_down][p_x] == l_targetColour )
{
l_result = true;
//System.out.println ("DOWN!");
}
}
// Check left
if ( !l_result && l_left > -1 )
{
if ( m_Grid[p_y][l_left] == l_targetColour )
{
l_result = true;
//System.out.println ("LEFT!");
}
}
// check right
if ( !l_result && l_right < m_GridWidth )
{
if ( m_Grid[p_y][l_right] == l_targetColour )
{
//System.out.println ("RIGHT!");
l_result = true;
}
}
}

return l_result;
}

///************************************************
/// Mouse listener handlers
///************************************************
public void mouseClicked(MouseEvent e)
{
if ( e.getButton() == MouseEvent.BUTTON1 )
{
ClickAt(e.getX(), e.getY());
}
}

public void mousePressed(MouseEvent e)
{
}

public void mouseReleased(MouseEvent e)
{
}

public void mouseEntered(MouseEvent e)
{
}

public void mouseExited(MouseEvent e)
{
}
///************************************************

// This function checks the grid
// for a single move being available
private boolean CheckForMoves()
{
boolean l_result = false;

for (int y = 0; y < m_GridHeight; ++y)
{
for (int x = 0; x < m_GridWidth; ++x)
{
int l_colour = m_Grid[y][x];

// doh forgot the blanks!
if ( l_colour != -1 )
{
int l_up = y - 1;
int l_down = y + 1;
int l_left = x - 1;
int l_right = x + 1;

if ( l_up > 0 )
{
if ( m_Grid[l_up][x] == l_colour )
{
//System.out.println ("Move Remains [" + x + ", " + y + "] to up");
l_result = true;
break;
}
}
if ( l_down < m_GridHeight )
{
if ( m_Grid[l_down][x] == l_colour )
{
//System.out.println ("Move Remains [" + x + ", " + y + "] to down");
l_result = true;
break;
}
}
if ( l_left > 0 )
{
if ( m_Grid[y][l_left] == l_colour )
{
//System.out.println ("Move Remains [" + x + ", " + y + "] to left");
l_result = true;
break;
}
}
if ( l_right < m_GridWidth )
{
if ( m_Grid[y][l_right] == l_colour )
{
//System.out.println ("Move Remains [" + x + ", " + y + "] to right");
l_result = true;
break;
}
}
}
}

if ( l_result )
{
break;
}
}

return l_result;
}

/// The main entry point, creates
/// a copy of the game and starts it
/// running
public static void main (String[] p_args)
{
bubbles l_Instance = new bubbles();
l_Instance.Run();
}

}