Ducky Love

<< Billiards | FinalProjectsTrailIndex | MakeMaze >>

background.gif

bell.wav

Click here for a working demonstration

This shooter game is here to demonstrate how to write your code so the sound and graphics files can be read when placed in a .jar file

The applet is then embedded in a web page with something like this:

duckyLove.html

<html>

    <head>
        <title> Ducky Love Applet</title>
    </head>
    <body>
        <h1>Ducky Love Applet</h1>

        <hr>
        <applet 
            code="DuckyLove.class" 
            archive="duckyLove.jar"
            width=800 
            height=600
         >
        If you see this, your browser is ignoring this awesome Java Applet!      
        </applet>
        <hr>
        <h4><a href="http://apcs.mathorama.com/index.php?n=Main.DuckyLove"> Source Code Here</a></h4>
    </body>
</html>

Heart.java

import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
public class Heart {
	private BufferedImage img;
	private int x,y,w,h, deltaX, deltaY;
	public Heart(double angle, BufferedImage img){
		this.img=img;
		w=200;
		h=200;
		x=400;
		y=450;
		deltaX=(int)Math.round(10*Math.cos(angle));
		deltaY=(int)Math.round(10*Math.sin(angle));
	}
	public boolean touches(Rectangle2D object){
		return object.intersects(x, y, w, h);
	}
	public void move(){
		w=95*w/100;
		h=95*h/100;
		x+=deltaX;
		y-=deltaY;
	}
	public void draw(Graphics g){
		g.drawImage(img, x-w/2, y-h/2, x+w/2, y+h/2, 0, 0, img.getWidth(), img.getHeight(), null);
	}
	public int getY(){
		return y;
	}
	public Rectangle2D area(){
		return new Rectangle2D.Double(x-w/2, y-h/2, w, h);
	}
}

Target.java

import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
public class Target 
{
	private BufferedImage img;
	private int x,y,w,h, deltaX;
	public Target(BufferedImage img){
		this.img=img;
		x=400;
		y=25;
		w=75;
		h=70;
		deltaX=randomInt(3,8);
	}
	public boolean touches(Rectangle2D object){
		if(deltaX>0)
			return object.intersects(x-w, y, w, h);
		return object.intersects(x, y, w, h);
	}
	public int randomInt(int min, int max){
		return min+(int)(max*Math.random());
	}
	public void move(){
		x+=deltaX;
		if (x+w>800){
			deltaX=-1*randomInt(3,8);
			x=800-w;
		}
		if (x<0){
			deltaX=randomInt(3,8);
			x=w;
		}
	}
	public void draw(Graphics g){
		int rightSide=x-w;
		if (deltaX<0)
			rightSide=x+w;		
		g.drawImage(img, x, y, rightSide, y+h, 0, 0, img.getWidth(), img.getHeight(), null);
	}
	public int getSpeed(){
		return Math.abs(deltaX);
	}
}

Crossbow.java

import java.awt.Color;
import java.awt.Graphics;
public class Crossbow {
	private int[] xPoints, yPoints;
	int x;
	public Crossbow(){
		x=400;
		xPoints=new int[3];
		yPoints=new int[3];
		xPoints[0]=400;xPoints[1]=x-20;xPoints[2]=x+20;
		yPoints[0]=450;yPoints[1]=600;yPoints[2]=600;
	}
	public void setX(int x){
		if (x>=0 && x<=800)
			this.x=x;
		xPoints[1]=x-20;
		xPoints[2]=x+20;
	}
	public void draw(Graphics g){
		g.setColor(new Color (200, 20, 200));
		g.fillPolygon(xPoints, yPoints, 3);
	}
	public double getAngle(){
		return Math.atan2(600-200, 400-x);
	}
}

DuckyLove.java

import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.Timer;

@SuppressWarnings("serial")
public class DuckyLove extends Applet implements ActionListener,MouseMotionListener, MouseListener
{
	private Crossbow bow;
	private Target target;
	private ArrayList<Heart> hearts;
	private int score, hits, miss;
	private Timer timer;
	private AudioClip bell;
	private Image background;
	private BufferedImage heartImg, duckImg;
	private Font font;
	private Image virtualMem;
    private Graphics gBuffer;
	public void init(){
		timer = new Timer(10,this);
		score = 0;
		hits = 0;
		miss = 0;
		bow=new Crossbow();
		//We load the large files once to save time,
		//getting the resource from the jar file
		background = getImage( getClass().getResource("/background.gif"));
		try {
			heartImg = ImageIO.read( getClass().getResource("/heart.png"));
			duckImg = ImageIO.read( getClass().getResource("/ducky.gif"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		target=new Target(duckImg);
		hearts = new ArrayList<Heart>();
		timer.start();
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		bell = getAudioClip(getClass().getResource("/bell.wav"));
		bell.play();


		virtualMem = createImage(getWidth(),getHeight());
        gBuffer = virtualMem.getGraphics();
        font = new Font("Helvetica", Font.BOLD,  18);       
	}
	public void paint(Graphics g){

		gBuffer.drawImage(background, 0, 0, null);
		bow.draw(gBuffer);
		target.draw(gBuffer);
		for(Heart h:hearts)
			h.draw(gBuffer);
		gBuffer.setColor(Color.black);
		gBuffer.setFont(font);
		gBuffer.drawString("Hits: "+hits, 715, 560);
		gBuffer.drawString("Misses: "+miss, 690, 585);
		int percent=0;
		if (hits+miss!=0)
			percent=100*hits/(hits+miss);
		gBuffer.drawString("Score: "+score+" ("+percent+"%)", 20, 20);
		gBuffer.drawString("Angle: "+Math.round(180*bow.getAngle()/Math.PI), 20, 580);
		g.drawImage(virtualMem,0,0,this);
	}
	public void update(Graphics g)
    {
        paint(g); //get rid of flicker with this method
    }
	@Override
	public void mouseClicked(MouseEvent arg0) {}
	@Override
	public void mouseEntered(MouseEvent arg0) {}
	@Override
	public void mouseExited(MouseEvent arg0) {}
	@Override
	public void mousePressed(MouseEvent arg0) {}
	@Override
	public void mouseReleased(MouseEvent arg0) {
		// fire a heart
		hearts.add(new Heart(bow.getAngle(), heartImg));
	}
	@Override
	public void mouseDragged(MouseEvent e) {}
	@Override
	public void mouseMoved(MouseEvent e) {
		int x=e.getX();
		bow.setX(x);
		repaint();
	}
	@Override
	public void actionPerformed(ActionEvent arg0) {
		target.move();
		for(Heart h:hearts)
			h.move();
		int i=0;
		while (i<hearts.size()){
			Heart h=hearts.get(i);
			//check for hit
			boolean hit=target.touches(h.area());
			if (hit){
				score+=10*target.getSpeed();
				hits++;
				bell.play();
				hearts.remove(h);
			} 
			if (h.getY()<-50){
				score--; 
				miss++;
				hearts.remove(h);
			}else{
				i++;
			}
		}
		repaint();
	}
}