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