Applets
Spelprogrammering
Vad jag jobbar med just nu
Spel
Effektapplets
Diverse länkar
Sikta och skjut
Ja, den här appleten bygger egentligen på samma tema som "knuffa bollen med muspekaren". Appleten innehåller en tank, hoppas jag du kan se, som hela tiden ställer in siktet på muspekaren. Om du klickar med höger musknapp, så kommer tanken att avlossa ett skott i riktning mot muspekaren. Om du trycker ner tangent v, så kommer en triangel att visas i appleten. Min förhoppning är att triangeln visualiserar "tänket" i appleten.Lösningen innehåller åtskilligt med trigonometri, och jag tror studiet av källkoden kan tillföra en hel del kunskap och förståelse.
Projektet innehåller tre klasser. TankRunner sätter upp och hanterar appleten samt skapar en instans av klassen Tank. Klassen Tank, som sköter allt som hör en tank till. Tankklassen administrerar ett magasin av kulor. Det gör den med hjälp av en vector.
Klassen Bullet beskriver och hanterar en kula.
Klassen Tank
import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Polygon; import java.awt.geom.AffineTransform; import java.awt.image.ImageObserver; import java.util.Iterator; import java.util.Vector; public class Tank { private double x; private double y; private double vinkel; private Image bild; private ImageObserver observer; private Polygon triangel; private boolean visaTriangel; private Vector<Bullet> magasin; public Tank(Image bild, ImageObserver observer) { this.bild = bild; this.observer = observer; x = (TankRunner.BREDD / 2) - bild.getWidth(this.observer) / 2; y = (TankRunner.BREDD / 2) - bild.getHeight(this.observer) / 2; vinkel = 0; visaTriangel = false; magasin = new Vector<Bullet>(); } public void paintTank(Graphics2D g) { AffineTransform transform = new AffineTransform(); clearAmo(); for (Iterator it = magasin.iterator(); it.hasNext();) { Bullet b = (Bullet) it.next(); b.paintBullet(g); } transform.setToTranslation(x, y); transform.rotate(Math.toRadians(vinkel), (double) bild .getWidth(this.observer) / 2, (double) bild .getHeight(this.observer) / 2); g.drawImage(bild, transform, observer); g.setPaint(new Color(240, 0, 0)); if (visaTriangel && triangel != null) g.drawPolygon(triangel); transform.setToIdentity(); } /* Visst ska en tank kunna skjuta. Innehåller en hel del intressant */ public void skjut(double mx, double my) { double dx = (x + bild.getWidth(observer) / 2) - mx; double dy = (y + bild.getHeight(observer) / 2) - my; double b_vinkel = Math.toDegrees(Math.atan2(dy, dx)); magasin.add(new Bullet((x + bild.getWidth(observer) / 2), (y + bild .getHeight(observer) / 2), b_vinkel)); } /* clearAmo tar bort kulor, som ligger utanför appleten*/ private void clearAmo() { for (Iterator it = magasin.iterator(); it.hasNext();) { Bullet b = (Bullet) it.next(); if(!b.isAlive()) it.remove(); } } /* aim ställer in siktet mot muspekaren. Också intressant */ public void aim(double mx, double my) { double dx = (x + bild.getWidth(observer) / 2) - mx; double dy = (y + bild.getHeight(observer) / 2) - my; vinkel = Math.toDegrees(Math.atan2(dy, dx)) - 90; triangel = new Polygon(); triangel.addPoint((int) mx, (int) my); triangel.addPoint((int) x + bild.getWidth(observer) / 2, (int) y + bild.getHeight(observer) / 2); triangel.addPoint((int) mx, (int) y + bild.getHeight(observer) / 2); } public void visaTriangel() { visaTriangel = true; } public void hideTriangel() { visaTriangel = false; } public boolean visarTriangel() { return visaTriangel; } }
Klassen Bullet
import java.awt.Color; import java.awt.Graphics2D; public class Bullet { private double x, y, vinkel, velocity; private boolean alive; public Bullet(double x, double y, double vinkel) { this.x = x; this.y = y; this.vinkel = vinkel; velocity = -4; alive = true; } public void paintBullet(Graphics2D g) { move(); g.setPaint(new Color(0, 0, 200)); g.fillOval((int) x - 4, (int) y - 4, 8, 8); } /* move sköter förstås kulans framfart. Mycket viktigt metod för kulan. Den anropas från paintBullet */ public void move() { x += velocity * Math.cos(Math.toRadians(vinkel)); y += velocity * Math.sin(Math.toRadians(vinkel)); if (x + 8 > TankRunner.BREDD || x < 0 || y + 8 > TankRunner.BREDD || y < 0) alive = false; } public boolean isAlive() { return alive; } }
Klassen TankRunner
Denna klass påminner väldigt mycket om de andra Runnerklasserna, som har förekommit under rubriken spelprogrammering. Det är inte så konstigt, eftersom dess huvudsakliga uppgift är att sätta upp appleten samt hantera en process. Men låt dig inte luras att tro, att klasserna är precis likadana, så är inte fallet.import java.applet.Applet; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.MediaTracker; import java.awt.RenderingHints; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; public class TankRunner extends Applet implements Runnable { private Tank tank; private Thread thread = null; private BufferedImage bakgrund; private BufferedImage plattor; private Graphics2D g; private Rectangle2D rect; public static int BREDD = 400; public void init() { bakgrund = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB); g = bakgrund.createGraphics(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setFont(new Font("Sans-serif", Font.BOLD, 24)); rect = new Rectangle2D.Double(0, 0, this.getWidth(), this.getHeight()); Image bild = null; try { bild = getImage(getCodeBase(), "tank.gif"); MediaTracker mt = new MediaTracker(this); mt.addImage(bild, 0); mt.waitForAll(); } catch (Exception error) { } tank = new Tank(bild, this); plattor = getBakgrund(); addMouseMotionListener(new MusLyssnare()); addMouseListener(new FireTrigger()); addKeyListener(new TangentHanterare()); } private BufferedImage getBakgrund() { BufferedImage retval = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB); Graphics2D g2d = retval.createGraphics(); int bredd = getWidth() / 50; int x = 0; int y = 0; g2d.setPaint(new Color(123, 143, 180)); for (int i = 0; i < 50; i++) { x = 0; for (int j = 0; j < 50; j++) { g2d.fill3DRect(x, y, bredd, bredd, true); x += bredd; } y += bredd; } return retval; } public void paint(java.awt.Graphics page) { g.drawImage(plattor, 0, 0, this); String str = "För att visa triangeln tryck v"; if (tank.visarTriangel()) str = "För att gömma triangeln tryck h"; g.setPaint(new Color(0, 0, 0)); g.drawString(str, 10, 30); g.drawString("Skjut med höger musknapp", 10, 60); g.setPaint(new Color(200, 0, 0)); g.drawString(str, 9, 29); g.drawString("Skjut med höger musknapp", 9, 59); tank.paintTank(g); page.drawImage(bakgrund, 0, 0, this); } public void update(Graphics page) { paint(page); } public void run() { while (thread != null) { repaint(); try { Thread.sleep(5); } catch (InterruptedException error) { } } } public void start() { if (thread == null) { thread = new Thread(this); thread.start(); } } public void stop() { thread = null; } class MusLyssnare extends MouseMotionAdapter { /* Denna metod underättar tanken om muspekarens position*/ public void mouseMoved(MouseEvent e) { tank.aim(e.getX(), e.getY()); } } class FireTrigger extends MouseAdapter { /*mouseClicked talar om för tanken att skjuta */ public void mouseClicked(MouseEvent e) { if (e.getButton() == 3) { tank.skjut(e.getX(), e.getY()); } } } class TangentHanterare extends KeyAdapter { public void keyPressed(KeyEvent e) { if (e.getKeyChar() == 'v') { tank.visaTriangel(); } if (e.getKeyChar() == 'h') { tank.hideTriangel(); } } } }Ja, sist men inte minst en webbsida och en bild att spara ner.
<html> <body> <applet code=TankRunner.class width="400" height="400"> </applet> </body> </html>
