import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
import java.net.*;
import java.awt.image.*;
import java.util.*;
public class Wastem extends Applet implements ActionListener
{
Image bird, logo;
AudioClip Shot_AC, Hit_AC, Empty_AC;
public void init()
{
//Setup color and layout
//null Layout isn't good but it is easier than fooling
//round with the gridbaglayout for such a simple layout
setBackground(Color.black);
setLayout(null);
//We load the audio first as there is no support
//for AudioClips in the mediatracker class
//therefore we hope they load before the images
Shot_AC = getAudioClip(getCodeBase(),"shot.au");
Hit_AC = getAudioClip(getCodeBase(),"crash.au");
Empty_AC = getAudioClip(getCodeBase(),"empty.au");
//We track the loading of images so that when the
//game starts, the player can see all the images
MediaTracker tracker = new MediaTracker(this);
//Get theImages
bird = getImage(getCodeBase(), "ball.gif");
Image blast = getImage(getCodeBase(), "bang.gif");
Image hit = getImage(getCodeBase(), "blast.gif");
//Add Images to media tracker
tracker.addImage(blast, 0);
tracker.addImage(bird, 1);
tracker.addImage(hit, 2);
//Wait for images to load
try
{
tracker.waitForID(0);
tracker.waitForID(1);
tracker.waitForID(2);
}
catch(Exception e)
{
System.out.println("Error in waiting for images: " + e);
}
//Load up a new ShootRange object, the main part of the game
//Applet is setup this way as I have learnt if you run the game
//straight from the applet instead of passing all the images
//and sounds to a different class, the applet wants to keep
//loading the images and sounds from the server.
//This way loads components once as well as making code easier
//to maintain and more portable to application or component of
//other applets.
ShootRange shootrange = new ShootRange(bird,blast,hit,Shot_AC,Hit_AC,Empty_AC,350,100);
shootrange.setBounds(0,0,350,100);
add(shootrange);
//Now I had my logo on the right hand side.
//Clicking on the image is handled in this class
logo = getImage(getCodeBase(),"ScufoLo.gif");
ImageCanvas logocanvas = new ImageCanvas(logo,94,52,"http://www.esearch.com.au/scufo");
logocanvas.addActionListener(this);
logocanvas.setBounds(360,24,100,52);
add(logocanvas);
}
public void actionPerformed(ActionEvent e)
{
String arg = e.getActionCommand();
//redirect browser to my page.
gotourl(new String(arg));
}
//This following code was written by me. It is usefull in
//sending a browser to any given page. Use it at will
void gotourl(String urlstring)
{
try
{
URL url1 = new URL( urlstring );
AppletContext appletcontext1 = getAppletContext();
appletcontext1.showDocument(url1, "_top");
}
catch( MalformedURLException malformedurlexception1 )
{
malformedurlexception1.printStackTrace();
}
//System.out.println(urlstring);
}
}
//Ok now we code the game
class ShootRange extends Canvas implements MouseListener, Runnable
{
int mousex,mousey,Xsize,Ysize; //standard mouse locations and game size
int birdmax = 10;//number of "birds" in a level
int score; //your score
int level; //level
int bullets; //number of bullets or shots left
int waittime; //how long the thread sleeps
double blast = 15.0;// radius allowed from center of shot to
//center of target "bird"
double birdx[] = new double[birdmax];//Birds x coord
double birdy[] = new double[birdmax];//Birds y coord
double birdvx[] = new double[birdmax];//Birds x velocity
double birdvy[] = new double[birdmax];//Birds y velocity
int birdstart[] = new int[birdmax];//starting location of birds
int birddirn[] = new int[birdmax];//direction ie start from left=1, right=-1
boolean wait = false;//displays change of level tag
int fire = -1;//these two are counters for the blast shots. When
int shot = -1;//a target is hot, fire goes on for 4 cycles, shot for 2
boolean gameover = true; // see if game is over
Cursor cursor;
Image Bird, Blast, Hit; //images
Thread thisthread;
AudioClip Shot_AC, Hit_AC, Empty_AC; //audio clips
ShootRange(Image bird, Image blast, Image hit, AudioClip shot_ac, AudioClip hit_ac, AudioClip empty_ac,int xsize, int ysize)
{
int n; //standard counter
Xsize = xsize;
Ysize = ysize;
addMouseListener(this);
//basic setup
setSize(Xsize,Ysize);
setBackground(Color.cyan);
setCursor(cursor.getPredefinedCursor(cursor.CROSSHAIR_CURSOR));
mousex = 0;
mousey = 0;
Bird = bird;
Blast = blast;
Hit = hit;
Shot_AC=shot_ac;
Hit_AC=hit_ac;
Empty_AC=empty_ac;
//call startpositions for new game
startpositions();
//start the thread
thisthread = new Thread(this);
thisthread.start();
}
void startpositions()
{
//This code just resets all the variables to a new game status
waittime=40;
score=0;
bullets=12;
level=0;
}
//Ok this code just checks that the distance from a click to a birds
//centre coords is less than blast distance
boolean checkhit(int x1, int y1 , int x2, int y2, int n)
{
if(Math.sqrt(Math.pow(x1-x2,2) + Math.pow(y1-y2,2))<=blast)
{
//If the bird is hit move it off the screen and stop displaying
//it NB 500 is greater than maximum time of 350 so never is
//shown
birdx[n] = -1;
birdy[n] = -1;
birdvx[n]= -1;
birdvy[n]= -1;
birdstart[n] = 500;
return true;
}
else
{
//System.out.println("Miss");
return false;
}
}
public void update(Graphics g)
{
//This is just your standard double buffering update method
Graphics offgraph;
Image offscreen = null;
Dimension d = getSize();
offscreen = createImage(d.width, d.height);
offgraph = offscreen.getGraphics();
offgraph.setColor(getBackground());
offgraph.fillRect(0, 0, d.width, d.height);
offgraph.setColor(getForeground());
paint(offgraph);
g.drawImage(offscreen, 0, 0, this);
offscreen.flush();
}
public void paint(Graphics g)
{
int n;
//this draw all the birds who should be on screen
for(n=0;n<birdmax;n++)
if(birdx[n]!=-1)
{
g.drawImage(Bird,(int)birdx[n]-5,(int)birdy[n]-5,this);
}
//Check to see if level display is on
if(wait)
g.drawString("Level " + level,90,40);
//check to see if gameover is on
if(gameover)
g.drawString("Game Over. Click to play",90,40);
//if fire is on draw shotgun blast
if(fire>=0)
g.drawImage(Blast,mousex-15,mousey-15,this);
//if a target is hit display explosion
if(shot>=0)
g.drawImage(Hit,mousex-15,mousey-15,this);
//Now we draw the scorecard
g.setColor(Color.black);
g.fillRect(0,0,60,Ysize);
//draw the score values
g.setColor(new Color(189,198,0));
g.drawString("" + score,10,20);
g.drawString("" + level,10,40);
g.drawString("" + bullets,10,60);
g.drawString("" + 8*level,10,80);
//draw the score labels
g.setColor(Color.red);
g.drawString("Score",10,10);
g.drawString("Level",10,30);
g.drawString("Shells",10,50);
g.drawString("Target",10,70);
}
//Ok now we setup the thread
public void run()
{
int n;
double velocityx=4.5; //these are the nominal velocities in x
double velocityy=1.70;//and y dirn
int i;//another counter
while(true)//always cycle
if(!gameover)//game is on
for(n=0;n<350;n++)//level goes for 350 cycles
{
if(fire>=0)//If we are drawing the fire image reduce
fire--;//count by 1
if(shot>=0)//if we are drawing shot image reduce
shot--;//count by 1
if(n==1)//Start of level
{
//now we setup this level
for(i=0;i<birdmax;i++)
{
//first split the bords up as to which
//side of screen they enter from
if(Math.random()>0.5)
birddirn[i]=1;
else
birddirn[i]=-1;
//now vary starting velocities by a
//random number as well as set the
//correct direction
birdvx[i] = birddirn[i] * (velocityx + 2 * Math.random());
birdvy[i] = velocityy + 2 * Math.random();
//Ok now we setup starting coords
//the number below are just to make it
//easier for me to understand the
//effect of the scoreboard (size 60)
//the 10 is to start the birds 10
//pixels offscreen either side.
birdx[i] = (Xsize-60)/2 - birddirn[i]*((Xsize-60)/2+10)+60;
birdy[i] = 70;
//now we vary the start time of each bird
birdstart[i] = (int)(300.00*Math.random());
}
//set bullets to 12
bullets = 12;
//increase level number
level++;
//turn level display on
wait = true;
}
//check if a bird is in flight
for(i=0;i<birdmax;i++)
if(n>=birdstart[i])//started yet
{
//check if bird has made it passed without
//being shot
if(birdy[i]>=Ysize)
{
//set it so it doesn't appear in calcs
//any more
birdstart[i]=500;
birdy[i]=Ysize+20;
}
//ok effect of gravity is -g, g=9.8m/s^2
//but we are far away therefore distance
//is less so by this calc we are 98 m from
//targets in earth gravity.
birdvy[i] = birdvy[i] - 0.1;
//move bird along by vx and vy
birdx[i] = birdx[i] + birdvx[i];
birdy[i] = birdy[i] - birdvy[i];
}
//turn level display off
if(n==10)
wait=false;
//check if we passed the level
if(n>=348 && score>=8*level)
{
//restart counter
n=0;
//Ok this is how we make the game harder
//we run thru exactly the same program, only
//we reduce the sleep time. Therefore
//game goes quicker. Simple yes, but
//effective.
waittime=(int)(waittime * 0.92);
}
//If it makes it this far the game is over
if(n>=349)
{
System.out.println("Game Over");
gameover=true;
}
//Ok now we sleep the thread for waittime milliseconds
try
{
thisthread.sleep(waittime);
}
catch(Exception e)
{
System.out.println("Error on sleep");
}
repaint();
}
//If the game is over we will sleep for longer so as not to tie up
//much cpu resources
else
{
try
{
thisthread.sleep(500);
}
catch(Exception e)
{
System.out.println("Error on sleep");
}
repaint();
}
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}
//Ok this checks if the mouse has been pressed and
//sends the coords for processing
public void mousePressed(MouseEvent e)
{
//If pressed and gameover, must be new game.
if(gameover)
{
gameover=false;
startpositions();
}
//otherwise shot at bird
else
{
//get coords
int x = e.getX();
int y = e.getY();
//set them for image display
mousex=x;
mousey=y;
//if we have bullets left
if(bullets>0)
{
//display fire image
fire = 2;
//play shotgun fire sound
Shot_AC.play();
//decrease bullet count
bullets --;
int n;
//now we check if the shot was near any of the birds
for(n=0;n<birdmax;n++)
{
if(checkhit(x,y,(int)birdx[n],(int)birdy[n],n))
{
//If we get one play hit sound
Hit_AC.play();
shot = 4;//start shot graphic
score++;//increase score by 1
}
}
}
else//if we have no bullets play empty cartridge sound
Empty_AC.play();
}
repaint();
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
}
//Ok this is a class written by me to display images and when
//clicked it returns the string it was given when initiated
class ImageCanvas extends Canvas implements MouseListener
{
private Vector listeners = new Vector();
Image canvasImage;
int Xsize;
int Ysize;
String Name;
Cursor cursor;
public ImageCanvas(Image image, int X, int Y, String name)
{
addMouseListener(this);
canvasImage = image;
Xsize = X;
Ysize = Y;
setSize(Xsize+5,Ysize);
Name = name;
}
public void mousePressed(MouseEvent e)
{
}
public void mouseDragged(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}
public void mouseClicked(MouseEvent e)
{
//System.out.println("Hello");
notifyListeners();
}
public void mouseEntered(MouseEvent e)
{
setCursor(cursor.getPredefinedCursor(cursor.HAND_CURSOR));
}
public void mouseExited(MouseEvent e)
{
cursor.getDefaultCursor();
}
public void addActionListener(ActionListener listener)
{
if(!listeners.contains(listener))
listeners.addElement(listener);
}
public void removeActionListener(ActionListener listener)
{
listeners.removeElement(listener);
}
private void notifyListeners()
{
ActionListener listener;
ActionEvent event = new ActionEvent(this, AWTEvent.RESERVED_ID_MAX+1, Name);
Vector copyOfListeners = (Vector)(listeners.clone());
Enumeration em = copyOfListeners.elements();
while (em.hasMoreElements())
{
listener = (ActionListener)em.nextElement();
listener.actionPerformed(event);
}
}
public void paint(Graphics g)
{
g.drawImage(canvasImage, 5, 0, Xsize, Ysize, this);
}
}
No comments:
Post a Comment