Saturday, August 18, 2012

The Skeet Shooting Game

Introduction

We have created a custom shape button that do nothing in the previous post. Now we are going to do some interesting thing. We will create a simple shooting game based on the idea of a custom shape button. We will use the API of Graphics2D extensively. The final playable version is less than 200 line of codes. Yet you would see real examples on how to rotate, scale and translate a image using the Graphics2D API. You would also see how to create a customized JComponent.


Star.svg


We will use a star as a moving target for our shooting game. I have found one on the web:
http://en.wikipedia.org/wiki/File:Star*.svg
The license says that it is in public domain. I would happily use it in my game.


If your browsers support SVG graphics, you will see a star above. If you right click it and view the source, you will see the following :

The above SVG source can be easily converted into a Java program as follows.
Compile it and test it.


Rotating Star

In order to make the game more interesting, we will make a rotating target. The original dimension of the star is 300x275. This is not a square and therefore not very desirable for rotation. So we would first make the dimension to become 300x300. Find the following line: and replace it with: Since we add 25 pixels in the y-dimension, we need to shift down the star by 12.5 pixels to keep the center of the star align with the center of the JComponent. We can add 12.5 to every y-coordinate of the polygon. Or we may just use the translate() method provided by Graphics2D. To implement the rotation, we just need to invoke the rotate method : We don't need the outline of the star, so we remove the last two statements from paint() Finally we want the star to keep rotating. We would use a Swing timer so that it will fire an ActionEvent on every 15ms. Of course we need to handle the timer event. We will just rotate and repaint the component. And finally we have a full source code for the rotating star.
Compile it and test it.


Clickable Star

To make the star clickable, we would use the technique in the previous article. We are going to treat the star as a custom shape button. First we would need to implement the MouseListener interface. We would need to provide implementation of all the five methods even we have nothing to do, just like above.


We would also need to tell our JComponent to listen to the mouse event. Hence the following statement is added to the constructor. We are going to let the star explode whenever it is clicked. I have chosen a simple "beam explosion method" for simplicity. It just need eight line of codes: The idea is to radiate 30 random beams from the explosion center. The length of every beam is random. If the center of explosion is (0,0), then the beam will radiate to a random point (x,y),

where -20 ≤ x < 20 and -20 ≤ y < 20
Note that (xExplode,yExplode) is the real explosion center, hence the coordinates in the drawLine() method are adjusted.
Now we have everything ready. We will rewrite mousePressed() method to start an explosion when the star is clicked. Just look at the source code together with the previous article. It should not be too complicate to understand.
Remember to compile it and test it.

Moving Object

I have written a series on "Moving Objects and Sprite Manager". You may visit the "Featured" page to find the link. A moving object is a object with non-zero velocity. It is simple to define the velocity in terms of pixels per frame. In the sprite manager series, I have used xv and yv to name the velocity in the x and y dimension. However, I am going to use dx and dy here. You may soon see the reason. If you know something about Physics and Calculus, you may know that velocity is actually defined by :
                            dx
velocity in x dimension =  ----
                            dt

                            dy
velocity in y dimension =  ----
                            dt

Since we are defining velocity for a unit time frame, we may treat dt as one, and hence we may just use dx and dy to represent the velocity.

Gravity Effect - Vertical Acceleration

Acceleration is the rate of change in velocity, therefore it is the "delta of delta y" per unit time. Therefore we would name it as ddy. Now we can initialize our moving object.

To move the object, we will update the position of the object for each frame The above background is enough for understanding the following sample.
Remember to compile it and test it.

And finally, The Skeet Shooting Game

We will now implement a skeet shooting game. The rotating star would be our shooting target. The game will finish after 20 targets are launched.


Tuesday, July 31, 2012

Custom Shape Buttons

Buttons of Irregular Shape

In previous post, I have demonstrated how to detect mouse click in a triangular region. That made implementation of a triangular button possible. In this post I will move one step forward. I am going to implement a button with arbitrary shape.


Transparent Image

First you will need a transparent image file to act as the button. It is not difficult to make one yourself. I have prepared one for you:




Download it and save it as "a.png". Place it at the same folder as ImageButton.java.


ImageButton.java

The actual code is simple, we will simulate a button using a JLabel. We will attach a image to the JLabel, then capture the mouse event, and ignore the mouse click if it click on a transparent pixel.

Sunday, July 8, 2012

Mouse Click in a Triangular Region

Introduction

It is relatively easy to test whether a mouse click occurs inside a rectangular region. However, testing mouse click in triangular region is less obvious. In this article, we will draw a cross inside a window to separate the screen into four triangular regions, and then we will write a mouse click handler so that it will report which region is clicked.


Drawing a cross


We will first write a program to draw a cross as shown below:





The drawing code should be simple enough to be understood. To test the code, copy and paste it to a file named RegionClicker.java, then issue:


javac RegionClicker.java
java RegionClicker



Handling Mouse Click with a MouseAdapter


We are now going to handle the mouse click event. First we need to define a event handler. Right now it will just pop up a message box when mouse click occurs.



Then we need to tell Java we are listening to the mouse event of the label by adding the following line in main()



Recognizing the Triangular Region


The next thing we are going to do is let the program report which triangle is clicked. It will say "up","down","left" or "right" according to the region clicked. It seems to be complex at first, but the code is actually simple.



Two Points Form

To derive the above code, we will first find out the equations of the two diagonal. Looking at the line drawing code, we are actually drawing two lines:
line A: (0,0) to (300,300)
line B: (300,0) to (0,300)

Line A is joining the upper left corner to the lower right corner, whereas line B is joining the lower left corner to the upper right corner. The equations of both lines can be determined by the two points form.
line A : (y-0)/(x-0) = (300-0)/(300-0)
line B : (y-0)/(x-300) = (300-0)/(0-300)

Simplification:
line A : y = x
line B : y = 300-x

We know that all points lying in line A satisfy equation A, that is, it satisfy the following condition :
y=x
With a simple observation, all points lying above line A must satisfy :
y<x
and all points lying below line A must satisfy :
y>x
Similarly, we would make the same conclusion to line B:
if (y=300-x), then the point lies on line B
if (y<300-x), then the point is above line B
if (y>300-x), then the point is below line B


Combining the above, we have:

If (y<x) and (y<300-x) then the point is lying above line A and also line B, hence it is in the upper triangular region.

If (y<x) and (y>300-x) then the point is lying above line A but below line B, 
hence it is in the right triangular region,


Generalization


The above code just handle window of 300x300. We can easily generalize the above code to a window of any size. The following program make dimension constants stored in W and H. And this is the completed version for this article.

Friday, July 6, 2012

Displaying Local Image in a JTextPane with HTML

Introduction

This is a question from a member in programmingforums.org. I have posted a quick reply there. I am going to write a step by step guide here.


Preparing a image

To display a image stored in local drive, you should first prepare a image file. We would expect "a.png" to be stored in the same folder as the demonstration program. It is easy to download or create a PNG image. For your convenience, I have prepared one here. Right click the image below and save it as "a.png"


Adding HTML in JTextPane

The following code would display a remote image in a JTextPane


Obtaining a local URL

Displaying remote image is not always desirable. To display a local image, we need a URL pointing to the local hard disk. If you place "a.png" at the same folder as the main program, you would obtain the image URL with the following portable way.


Full source

Friday, June 29, 2012

Minesweeper Applet - Part 2

Introduction

This is part 2 of the series. It is recommended to read part 1 first. If you just want to play the game, you will need Mine.java in part 1 and MineApplet.java in part 2. Put both of them in the same folder and type :
javac *.java
java MineApplet
Part 1 can be found here:

Upload to web server

It is not necessary to have a web server in order to play this applet. Because it is written in such a way that a simple applet container is implemented in the code.

However, if you have a web server you may wish to upload the applet to share it. First you would need to create a jar file.

jar cvf mine.jar *.class
Then create an HTML file to hold the applet.

The user interface

It is almost identical to the Windows version of the MineSweeper. Left click to open a cell, right click to mark a mine, double click to auto-open safe neighbours.

All of the cells are implemented by JButton. I have extended the JButton class to MyButton for the following reasons:

  1. We can provide customize outlook of the button, for example, we may change the font color of the button according to the label. The standard MineSweeper game typically use red "1", green "2", red "3".
  2. We can draw an icon to the button. For example, the "new game" button at the top has a smiling face on it. See the paintComponent() method for details
  3. We can define mouse action listener for left click, right click and even double click. See the mouseClicked() method for details

Understanding the code

The logic of the game was implemented in Mine.java in part 1.
The GUI is implemented in MineApplet.java here.

Mine.java was explained in Part 1. I am not going to write detail explanation of MineApplet.java here. The best way to understand it is to play the game then view the code. It illustrate many useful techniques.

  1. It contains a simple applet container so that it can be run as an java application. If you are searching for "Applet to Application", you may find an example right here. See the main() method for details
  2. It contains JButton with customized look
  3. It contains JButton with customized control. It implements a JButton class with right click and double click support.
  4. It uses the technique of embedding image into source code so that no separated image files are needed. See buildSmileImage() for details.
  5. It implements a timer thread to display the timer. The timer thread conform to the standard of the applet life cycle. See the start(), run() and stop() method.

Full source listing

Minesweeper Applet - Part 1

Introduction

We are going to implement a mine sweeper game in Java. The game can be executed as an applet and as an application.

Text Mode

It is simpler to implement the game in text mode. Not only the code is simpler but also it is much easier to debug. We will implement the game in text mode first, then add a GUI after the game is working.

Data Structure

We will use a simple single dimensional array to represent the mine field. We will use the number 64 to represent a mine. We will hard code the mine field at the moment. Later we will add code to generate a random mine field.

Counting the neighboring mines

What we want :

  0  1  1  1  0  1 64  1  0
  0  1 64  1  0  2  2  2  0
  0  1  1  1  0  2 64  2  0
  0  0  0  0  0  2 64  3  1
  0  0  0  0  0  1  2  3 64
  0  1  1  1  0  0  2 64  3
  0  1 64  1  0  0  2 64  2
  1  2  1  1  0  0  1  2  2
 64  1  0  0  0  0  0  1 64
What we do : Debugging

As previously said, it is easier to debug a text mode program, we will write a simple method to display the mine field. M1.java

This is the first version of our mine sweeper, it just print out a hard code mine field, with the correct neighboring counts. Sample run :

 
javac *.java

java M1
  0  1  1  1  0  1 64  1  0
  0  1 64  1  0  2  2  2  0
  0  1  1  1  0  2 64  2  0
  0  0  0  0  0  2 64  3  1
  0  0  0  0  0  1  2  3 64
  0  1  1  1  0  0  2 64  3
  0  1 64  1  0  0  2 64  2
  1  2  1  1  0  0  1  2  2
 64  1  0  0  0  0  0  1 64
Hiding all the cells

We will hide the mine field by setting bit 7 of all cells to one. We would need to modify printField() as well. Now we have the second version of MineSweeper Sample Run:

 

javac M2.java

java M2

  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
Opening a Cell

For example, to open cell number 2 in the field, add the following in main() Test run:

 

  .  .  1  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
This is a "1". That means one of the neighbouring cell is a mine.

To open cell number 0, use the following Test run:

 


  0  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .
  .  .  .  .  .  .  .  .  .

Since this is zero, we can be sure the three neighbouring cells are safe to open. So we open them automatically. Test run:
 

  0  1  .  1  0  1  .  .  .
  0  1  .  1  0  2  .  .  .
  0  1  1  1  0  2  .  .  .
  0  0  0  0  0  2  .  .  .
  0  0  0  0  0  1  2  .  .
  0  1  1  1  0  0  2  .  .
  0  1  .  1  0  0  2  .  .
  1  2  1  1  0  0  1  2  .
  .  1  0  0  0  0  0  1  .

We are so lucky that most of the cell are automatically opened.

Next we complete the text mode minesweeper. The user can enter any number between 0 to 63 to open a cell. Coming next

Though we have a working mine sweeper, it is quite difficult to play in text mode. We will make an applet version of the game. We won't reinvent the wheel and Mine.java would be completely reused without modification. We will just add a GUI wrapper.

Continue with part 2 here ...