java - BufferedImage not being cleared before each rendering -


i'm trying learn how build simple game through tutorial i'm watching. fine, when move image previous image doesn't erased or disposed. i'm not sure whats wrong, or why happening. have 3 classes, main class, player class, , bufferimageloader class.

main class:

import java.awt.canvas; import java.awt.graphics; import java.awt.image.bufferstrategy; import java.awt.image.bufferedimage; import java.io.ioexception;  import javax.swing.jframe;  public class main extends canvas implements runnable { private boolean running = false; private thread thread; private bufferedimage player; private player p;  public void init(){ // load , initiliaze     bufferedimageloader loader = new bufferedimageloader();      try {         player = loader.loadimage("/player_shotgun2.png");     } catch (ioexception e) {         // todo auto-generated catch block         e.printstacktrace();     }      p = new player(100, 100, this);  }  private synchronized void start(){ if(running)     return; running = true; thread = new thread(this); thread.start(); }  private synchronized void stop(){     if(!running)         return;     running = false;     try {         thread.join();     } catch (interruptedexception e) {         // todo auto-generated catch block         e.printstacktrace();     }     system.exit(1); }  public void run() {     init();     long lasttime = system.nanotime();     final double amountofticks = 60.0;     double ns = 1000000000 / amountofticks;// 1 second divided 60, run 60 times per second     double delta = 0;     int updates = 0;     int frames = 0;     long timer = system.currenttimemillis();     system.out.println("hi");     while(running){         long = system.nanotime();         delta += (now - lasttime) / ns;         lasttime = now;         if(delta >= 1){// delta = 1 = 1 second             tick();             updates++;             delta--;         }         render();         frames++;         if(system.currenttimemillis() - timer > 1000){             timer+= 1000;             system.out.println(updates + " ticks, fps " + frames);             updates = 0;             frames = 0;         }     }     stop(); }  // thats updated in game private void tick(){     p.tick(); }  // rendered in game private void render(){     bufferstrategy bs = this.getbufferstrategy();     if(bs == null){         createbufferstrategy(3);         return;     }     graphics g = bs.getdrawgraphics();     //////////////////////////////     p.render(g);      //////////////////////////////     g.dispose();     bs.show(); }  public static void main(string[] args) {     // todo auto-generated method stub     main main = new main();     jframe window = new jframe();     window.setsize(500,600);     window.settitle("zombie game");     window.setdefaultcloseoperation(jframe.exit_on_close);     window.setvisible(true);     window.add(main);     main.start(); }  public bufferedimage getplayerimage(){     return player; } 

}

player class:

import java.awt.graphics; import java.awt.image.bufferedimage;  import javax.swing.jpanel;  public class player extends jpanel {      private double x;     private double y;     public bufferedimage player;      public player(double x, double y, main main){         this.x = x;         this.y = y;          player = main.getplayerimage();     }      public void tick(){         x++;     }      public void render(graphics g){         super.paintcomponent(g);         g.drawimage(player, (int)x, (int)y, null);         g.dispose();     } } 

bufferedimageloader class:

import java.awt.image.bufferedimage; import java.io.ioexception;  import javax.imageio.imageio;  public class bufferedimageloader {      private bufferedimage image;      public bufferedimage loadimage(string path) throws ioexception{         image = imageio.read(getclass().getresource(path));         return image;     } } 

this output when start , image moves:

enter image description here

this simple swing application called moving eyes. eyeballs in gui follow mouse cursor move cursor in drawing area of gui.

i realize it's not doing want do. i'm providing code can see how simple swing animation. may use code basis own animation.

here's swing gui.

moving eyes

i used model / view / controller model when creating swing gui. means that:

  1. the view may read values model.
  2. the view may not update model.
  3. the controller update model.
  4. the controller repaint / revalidate view.

basically, model ignorant of view , controller. allows change view , controller swing web site, or android app.

the model / view / controller pattern allows focus on 1 part of swing gui @ time. in general, you’ll create model first, view, , controllers. have go , add fields model.

and here's code:

package com.ggl.testing;  import java.awt.color; import java.awt.dimension; import java.awt.graphics; import java.awt.point; import java.awt.event.mouseevent; import java.awt.event.mousemotionadapter;  import javax.swing.jframe; import javax.swing.jpanel; import javax.swing.swingutilities;  public class movingeyes implements runnable {      private static final int drawingwidth = 400;     private static final int drawingheight = 400;     private static final int eyeballheight = 150;     private static final int eyeballwidthmargin = 125;      private drawingpanel drawingpanel;      private eye[] eyes;      private jframe frame;      public static void main(string[] args) {         swingutilities.invokelater(new movingeyes());     }      public movingeyes() {         this.eyes = new eye[2];         this.eyes[0] = new eye(new point(eyeballwidthmargin, eyeballheight));         this.eyes[1] = new eye(new point(drawingwidth - eyeballwidthmargin,                 eyeballheight));     }      @override     public void run() {         frame = new jframe("moving eyes");         frame.setdefaultcloseoperation(jframe.exit_on_close);          drawingpanel = new drawingpanel(drawingwidth, drawingheight);         frame.add(drawingpanel);          frame.pack();         frame.setlocationbyplatform(true);         frame.setvisible(true);     }      public class drawingpanel extends jpanel {          private static final long serialversionuid = -2977860217912678180l;          private static final int eyeballouterradius = 50;         private static final int eyeballinnerradius = 20;          public drawingpanel(int width, int height) {             this.addmousemotionlistener(new eyeballlistener(this,                     eyeballouterradius - eyeballinnerradius - 5));             this.setbackground(color.white);             this.setpreferredsize(new dimension(width, height));         }          @override         protected void paintcomponent(graphics g) {             super.paintcomponent(g);              g.setcolor(color.black);              (eye eye : eyes) {                 drawcircle(g, eye.getorigin(), eyeballouterradius);                 fillcircle(g, eye.geteyeballorigin(), eyeballinnerradius);             }         }          private void drawcircle(graphics g, point origin, int radius) {             g.drawoval(origin.x - radius, origin.y - radius, radius + radius,                     radius + radius);         }          private void fillcircle(graphics g, point origin, int radius) {             g.filloval(origin.x - radius, origin.y - radius, radius + radius,                     radius + radius);         }      }      public class eye {         private final point origin;         private point eyeballorigin;          public eye(point origin) {             this.origin = origin;             this.eyeballorigin = origin;         }          public point geteyeballorigin() {             return eyeballorigin;         }          public void seteyeballorigin(point eyeballorigin) {             this.eyeballorigin = eyeballorigin;         }          public point getorigin() {             return origin;         }      }      public class eyeballlistener extends mousemotionadapter {          private final double eyeballdistance;          private final drawingpanel drawingpanel;          public eyeballlistener(drawingpanel drawingpanel, double eyeballdistance) {             this.drawingpanel = drawingpanel;             this.eyeballdistance = eyeballdistance;         }          @override         public void mousemoved(mouseevent event) {             point p = event.getpoint();             (eye eye : eyes) {                 point origin = eye.getorigin();                 double theta = math.atan2((double) (p.y - origin.y),                         (double) (p.x - origin.x));                 int x = (int) math.round(math.cos(theta) * eyeballdistance)                         + origin.x;                 int y = (int) math.round(math.sin(theta) * eyeballdistance)                         + origin.y;                 eye.seteyeballorigin(new point(x, y));             }              drawingpanel.repaint();         }      }  } 

model

the eye class java object holds origin of eye (circle) , origin of eyeball. eye class model in simple example.

view

the movingeyes class class defines jframe. movingeyes class part of view. main method of class invokes swingutilities invokelater method ensure swing components defined , modified on event dispatch thread.

we use jframe. not extend jframe. time extend swing component, or java class, when want override 1 of class methods. we’ll see when talk drawingpanel.

the constructor of movingeyes class defines 2 instances of eye class. run method defines jframe. code in run method similar swing guis.

the drawingpanel class makes rest of view. drawingpanel class extends jpanel because want override paintcomponent method. constructor of drawingpanel class sets preferred size of drawing area, , adds mouse motion listener. mouse motion listener controller of swing gui.

the paintcomponent method of drawingpanel class first calls super paintcomponent method. maintains swing paint chain, , should first statement of overwritten paintcomponent method.

the rest of code in paintcomponent method of drawingpanel class draws eyes. have drawing (painting) code in paintcomponent method. control code belongs in controller.

controller

the eyeballlistener class controller class. can have more 1 controller class in more complicated swing gui.

the eyeballlistener class extends mousemotionadapter. can implement mousemotionlistener. i’m overriding 1 method, code shorter when extend mousemotionadapter.

the mousemoved method of eyeballlistener class fires mouseevent when mouse moved. calculate new position center of eyeball finding theta angle center of eye mouse position. theta angle used calculate new center of eyeball.

each eye instance updated separately in loop. after both eyes updated, drawing panel repainted. happens fast there’s no need animation loop in separate thread.

an animation loop updates model, draws view, , waits specified period of time. use separate thread animation loop, gui on event dispatch thread stays responsive. if gui not responsive, you’re doing work on event dispatch thread.


Comments