Ducky Love
<< Billiards | FinalProjectsTrailIndex | MakeMaze >>


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();
}
}
