|
Ping Pong with GameApplet / Alex Zak
As I promised some time ago, I will make a step
by step example on how to use GameApplet
to write games in Java.
Today, I will write a PingPong game, using the three classes I described.
Note: because my hosting will not allow .java files I changed them to
.java.txt
Description of the game
The ping pong game will have two components: a bat and a ball. The bat
will be controlled
with the mouse, while the ball will bounce off the bat and the
boundaries of the applet.
A new Game class
I start by creating a new class, that is called PingPong, and it
extends Game.java.
I will not have a constructor for PingPong, all things that should be
done in the begining are to be placed in init().
In init(), I resize the applet size, by calling resize(300,300).
Now the applet will be 300 pixels wide,
and 300 pixels high (note that most browsers will not resize the
applet, so you must define the width and height of the
applet in the html file). I also call setSleepTime(60);,
so that 60 milliseconds pass between each call to paint().
I would also want the background to be black, so I override getBackgroundColor()
(actualy, the default is also black,
but I add this part to demonstrate how to change backgrounds).
Finaly, I need to override paint(Graphics g)
because it's abstract, so I will make it draw the bat. The code, up
until
now, looks like this:
package pingpong1;
import java.awt.Color; import java.awt.Graphics; import java.awt.Point;
public class PingPong extends Game { public static final int BATWIDTH=60; public static final int BATHEIGHT=20; private int batX=150, batY=200; public void init(){ resize(600,600); setSleepTime(50);
} public Color getBackgroundColor(){ return Color.black; }
public void paint(Graphics g) { g.setColor(Color.red); //To make the bat red Point mp=gp.getMousePosition(); //point mp will hold the coordinates of the mouse if(mp!=null) { //Then, if the mouse is in the game window, it's coordinates are copied to //batX and batY. If the mouse is out of the game window, batX and batY will not change. batX=mp.x; batY=mp.y; } //finaly, to draw the bat, I call the Garphics method fillRect, that draws and fills //a rectangle. g.fillRect(batX-BATWIDTH/2,batY-BATHEIGHT/2,BATWIDTH,BATHEIGHT); } }
Do not forget to change the game class to PingPong
in GameApplet.java:
game=new PingPong();
You can see how the applet should look now here.
By now, you might want to include your applet in a website. To do this,
change the package of your classes to
pingpong1 (to do it in eclipse, right click on the
package name in the Package Explorer, choose refactor,
and rename). Then create a directory called 'pingpong1', and copy there
all the '.class' files. Finaly, put an '.html'
file in the same dirctory where 'pingpong1' directory resides, and put
this code there:
<applet code="pingpong1.GameApplet.class" width=600 height=600> </applet>
The ball
Like the bat, the ball's cordinates will be kept as
two ints:
private int ballX=150, ballY=50;
I will also keep the speed of the ball as two ints:
private int ballSpeedX=0; //the ball speed on the X axis private int ballSpeedY=8; //the ball speed on the Y axis
Note that in Java, an increase in Y means going
down. Therefore, in the begining the ball will go straight down.
I still did not make the ball move, though. So I add this code in the
beggining of paint():
ballX=ballX+ballSpeedX; ballY=ballY+ballSpeedY;
I would also want to draw the ball. So in the end
of paint, I add this:
g.setColor(Color.green); g.fillOval(ballX-BALLRADIUS,ballY-BALLRADIUS,BALLRADIUS*2,BALLRADIUS*2);
Now, the hardest part: making the ball bounce off
the bat and the walls. I will write this part in a method
called checkCollisions, and it will be called from paint()
to make sure that collisions are checked
each time the scene is repainted. Therefore, the paint
method will look like this:
public void paint(Graphics g) { ballX=ballX+ballSpeedX; ballY=ballY+ballSpeedY; checkCollisions(); g.setColor(Color.red); //To make the bat red Point mp=gp.getMousePosition(); //point mp will hold the coordinates of the mouse if(mp!=null) { //Then, if the mouse is in the game window, it's coordinates are copied to //batX and batY. If the mouse is out of the game window, batX and batY will not change. batX=mp.x; batY=mp.y; } //finaly, to draw the bat, I call the Garphics method fillRect, that draws and fills //a rectangle. g.fillRect(batX-BATWIDTH/2,batY-BATHEIGHT/2,BATWIDTH,BATHEIGHT); g.setColor(Color.green); g.fillOval(ballX-BALLRADIUS,ballY-BALLRADIUS,BALLRADIUS*2,BALLRADIUS*2); }
Now, let's implement checkCollisions.
Collisions with bounds will be simpler, so let's start with them.
When the ball hits the top bound, or one of the sides, it should bounce
back, at the same angle it hit. So that if
it hit the top bound, it's x speed will stay the same, while it's y
speed will be reversed:
public void checkCollisions(){ if(ballX-BALLRADIUS<0){ ballSpeedX=-ballSpeedX; } if(ballY-BALLRADIUS<0){ ballSpeedY=-ballSpeedY; } if(ballX+BALLRADIUS>600){ ballSpeedX=-ballSpeedX; } . . . }
What happens when the ball falls down? Lets put it
back in it's initial position:
if(ballY+BALLRADIUS>600){ ballX=150; ballY=50; ballSpeedX=0; ballSpeedY=9; }
Now we must handle the bat hitting the ball. In
real life, the ball should bounce back in the same angle it
came, just like it bounces off walls. However, almost all such games
make a different calculation:
The ball's x speed is greatest when the ball hits the bat near it's
edge, while if the ball hits it exactly in
the middle, it's x speed will be 0. Then y speed is calculated using
Pithagor's theorem (sorry about the math, but it is required here). We
will use this calculation.
In order to find out if the ball hit the bat, I use a java class,
called Ellipse2D.Double
This class describes an oval (in my case, a circle), and I use it's intersects
method to see if it
intersects the bat. So here is the final checkCollisions
method:
public void checkCollisions(){ if(ballX-BALLRADIUS<0){ ballSpeedX=-ballSpeedX; } if(ballY-BALLRADIUS<0){ ballSpeedY=-ballSpeedY; } if(ballX+BALLRADIUS>600){ ballSpeedX=-ballSpeedX; } if(ballY+BALLRADIUS>600){ ballX=150; ballY=50; ballSpeedX=0; ballSpeedY=9; } Ellipse2D.Double ball=new Ellipse2D.Double(ballX-BALLRADIUS,ballY-BALLRADIUS,BALLRADIUS*2,BALLRADIUS*2); if(ball.intersects(batX-BATWIDTH/2,batY-BATHEIGHT/2,BATWIDTH,BATHEIGHT)){ ballSpeedX=(ballX-batX)/5; ballSpeedY=-(int)Math.sqrt(81-ballSpeedX^2); } }
Do not forget to import the required classes:
import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.geom.*;
That's it. The game is ready. Here is the end result.
Did you find the article useful? Please donate here to support
mysuperiorgames.com
If you want to try and play with the code, I have some possible changes
you may want to make, to see
if you understand how the code works:
-
Make the ball change it's color as the game
progresses.
-
Make the ball bounce correctly off the bottom
of the bat (right now it passes through the bat
when it comes from the bottom).
-
Replace the bat with a 60x20 image. You will
want to use the inherited method readBufferedImage.
-
Count the number of times the ball falls down,
and display it somewhere on the screen. You can use g.drawString.
-
Add a computer controled bat, make the ball
stop bouncing from the top bound, and instead reapear at the center.
When this happens the player should get a point.
Questions, complaints and requests? Send them to admin@mysuperiorgames.com
|