L
Luc The Perverse
First - this class is not done. Right now it moves the unit right through
walls just to simulate some kind of animation. This is my first animation
of any kind that wasn't copied straight from a book. (Still pretty close.)
1 - I was trying to get the size of the image, but the page $Page states
that Image.getWidth( . . .) asks for an ImageObserver object. But I cannot
figure out what an ImageObserver is. I am concerned that I am missing the
bigger picture here (no pun intended.) Is an image not considered simply a
collection of pixels? Can someone explain to me not only how to get the
image, but why I need an ImageObserver object?
2 - I have a sneaking suspicion that the way I am loading the images is the
wrong way to do it. Other code snippets I have found use a Toolkit object
inexplicably. Is this Toolkit related to running the app as an applet - or
does it give you the "flexibility" to load from a JAR file if that is where
you files are located. I am using a MediaTracker object after I resize, but
not after I load, because AFAIK the ImageIcon class constructor is a
blocking call. In this case I don't know enough about what I'm supposed to
be doing to know what to ask.Can some advise me?
Here is are the two classes.
Discrete2DMaze and Positioner are just two classes which define a maze and
maze geometry on the screen. They are quite simple - any use of them
should be pretty obvious from context. I did not paste them in because they
are poorly structured, in need of revisions, and not directly related to my
question. My maze generation algorithm came from an old C function I wrote.
class JavaMazePanel extends javax.swing.JPanel{
Discrete2DMaze MyMaze; //abstract parent defines
Positioner DrawingAssistant;
public void paintComponent(Graphics comp) {
//to do: Make color dynamic, include "defaults" in constructor with
seperate constructor to allowing passing
if(MyMaze == null || MyMaze.X <1 || MyMaze.Y < 1) //something is wrong
return;
Graphics2D comp2D = (Graphics2D)comp;
int he = getHeight();
int wi = getWidth();
comp2D.setColor(Color.black);
comp2D.fillRect(0, 0, wi, he);
comp2D.setColor(Color.white);
DrawingAssistant=new Positioner(MyMaze.X, MyMaze.Y, wi, he, 0 ,0);
comp2D.setColor(Color.white);
int i, j;
for(i=0;i<MyMaze.X;i++){
if(MyMaze.isHorizWall(i, 0))
comp2D.drawLine(DrawingAssistant.X(i, MyMaze.Y), DrawingAssistant.Y(i,
MyMaze.Y), DrawingAssistant.X(i+1, MyMaze.Y), DrawingAssistant.Y(i+1,
MyMaze.Y));
for(j=0;j<MyMaze.Y;j++){
if(MyMaze.isVertWall(i, j))
comp2D.drawLine(DrawingAssistant.X(i, j), DrawingAssistant.Y(i, j),
DrawingAssistant.X(i, j+1), DrawingAssistant.Y(i, j+1));
if(MyMaze.isHorizWall(i, j))
comp2D.drawLine(DrawingAssistant.X(i, j), DrawingAssistant.Y(i, j),
DrawingAssistant.X(i+1, j), DrawingAssistant.Y(i+1, j));
}
}
for(j=0;j<MyMaze.Y;j++)
if(MyMaze.isVertWall(0, j))
comp2D.drawLine(DrawingAssistant.X(MyMaze.X, j), DrawingAssistant.Y(i,
j), DrawingAssistant.X(MyMaze.X, j+1), DrawingAssistant.Y(MyMaze.X,j+1));
}
}
class Walkable2DMaze extends JavaMazePanel implements Runnable{
Thread runner;
Image ScaledSprite;
Image UnscaledWalkerSprite;
Image[] UnscaledWalkerSprites;
float posX; //Maze position of walker
float posY;
//Positioner DrawingAssistant maintained and controlled by parent class
Walkable2DMaze(){
super();
UnscaledWalkerSprites = new Image[4];
for(int i=1;i<=4;i++)
UnscaledWalkerSprites[i-1] = new
ImageIcon("./img/Drone"+i+".GIF").getImage();
UnscaledWalkerSprite=UnscaledWalkerSprites[0];
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}
protected void finalize() throws Throwable{
runner = null;
super.finalize();
}
public void paintComponent(Graphics comp) {
Graphics2D comp2D = (Graphics2D)comp;
super.paintComponent(comp); //draw maze background
if (UnscaledWalkerSprite != null){ //If a picture has been
specified
if(ScaledSprite == null/* ||
ScaledSprite.getWidth()!=DrawingAssistant.CellWidth*/)
ScaledSprite =
UnscaledWalkerSprite.getScaledInstance(DrawingAssistant.CellWidth ,
DrawingAssistant.CellHeight , 0);
MediaTracker track = new MediaTracker(this);
track.addImage(ScaledSprite, 0);
try{
track.waitForAll();
//to do: Make a "getCenterPoint" function in Positioner class
int PixelLoc_X = DrawingAssistant.X(posX + 0.5f, posY + 0.5f) -
DrawingAssistant.CellWidth/2;
int PixelLoc_Y = DrawingAssistant.Y(posX + 0.5f, posY + 0.5f) -
DrawingAssistant.CellHeight/2;
comp2D.drawImage(ScaledSprite, PixelLoc_X, PixelLoc_Y, this); }
catch(InterruptedException e){} //didn't work
}
}
public void run() {
int g=0;
while(runner!=null){
walk();
pause(1500);
g++;
if(g>3)
g=0;
UnscaledWalkerSprite = UnscaledWalkerSprites[g];
ScaledSprite = null;
}
}
public void walk() {
for (float i = 0; i < 10; i += .01) {
posX = i;
repaint();
pause(11);
}
}
public void pause(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) { }
}
}
walls just to simulate some kind of animation. This is my first animation
of any kind that wasn't copied straight from a book. (Still pretty close.)
1 - I was trying to get the size of the image, but the page $Page states
that Image.getWidth( . . .) asks for an ImageObserver object. But I cannot
figure out what an ImageObserver is. I am concerned that I am missing the
bigger picture here (no pun intended.) Is an image not considered simply a
collection of pixels? Can someone explain to me not only how to get the
image, but why I need an ImageObserver object?
2 - I have a sneaking suspicion that the way I am loading the images is the
wrong way to do it. Other code snippets I have found use a Toolkit object
inexplicably. Is this Toolkit related to running the app as an applet - or
does it give you the "flexibility" to load from a JAR file if that is where
you files are located. I am using a MediaTracker object after I resize, but
not after I load, because AFAIK the ImageIcon class constructor is a
blocking call. In this case I don't know enough about what I'm supposed to
be doing to know what to ask.Can some advise me?
Here is are the two classes.
Discrete2DMaze and Positioner are just two classes which define a maze and
maze geometry on the screen. They are quite simple - any use of them
should be pretty obvious from context. I did not paste them in because they
are poorly structured, in need of revisions, and not directly related to my
question. My maze generation algorithm came from an old C function I wrote.
class JavaMazePanel extends javax.swing.JPanel{
Discrete2DMaze MyMaze; //abstract parent defines
Positioner DrawingAssistant;
public void paintComponent(Graphics comp) {
//to do: Make color dynamic, include "defaults" in constructor with
seperate constructor to allowing passing
if(MyMaze == null || MyMaze.X <1 || MyMaze.Y < 1) //something is wrong
return;
Graphics2D comp2D = (Graphics2D)comp;
int he = getHeight();
int wi = getWidth();
comp2D.setColor(Color.black);
comp2D.fillRect(0, 0, wi, he);
comp2D.setColor(Color.white);
DrawingAssistant=new Positioner(MyMaze.X, MyMaze.Y, wi, he, 0 ,0);
comp2D.setColor(Color.white);
int i, j;
for(i=0;i<MyMaze.X;i++){
if(MyMaze.isHorizWall(i, 0))
comp2D.drawLine(DrawingAssistant.X(i, MyMaze.Y), DrawingAssistant.Y(i,
MyMaze.Y), DrawingAssistant.X(i+1, MyMaze.Y), DrawingAssistant.Y(i+1,
MyMaze.Y));
for(j=0;j<MyMaze.Y;j++){
if(MyMaze.isVertWall(i, j))
comp2D.drawLine(DrawingAssistant.X(i, j), DrawingAssistant.Y(i, j),
DrawingAssistant.X(i, j+1), DrawingAssistant.Y(i, j+1));
if(MyMaze.isHorizWall(i, j))
comp2D.drawLine(DrawingAssistant.X(i, j), DrawingAssistant.Y(i, j),
DrawingAssistant.X(i+1, j), DrawingAssistant.Y(i+1, j));
}
}
for(j=0;j<MyMaze.Y;j++)
if(MyMaze.isVertWall(0, j))
comp2D.drawLine(DrawingAssistant.X(MyMaze.X, j), DrawingAssistant.Y(i,
j), DrawingAssistant.X(MyMaze.X, j+1), DrawingAssistant.Y(MyMaze.X,j+1));
}
}
class Walkable2DMaze extends JavaMazePanel implements Runnable{
Thread runner;
Image ScaledSprite;
Image UnscaledWalkerSprite;
Image[] UnscaledWalkerSprites;
float posX; //Maze position of walker
float posY;
//Positioner DrawingAssistant maintained and controlled by parent class
Walkable2DMaze(){
super();
UnscaledWalkerSprites = new Image[4];
for(int i=1;i<=4;i++)
UnscaledWalkerSprites[i-1] = new
ImageIcon("./img/Drone"+i+".GIF").getImage();
UnscaledWalkerSprite=UnscaledWalkerSprites[0];
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}
protected void finalize() throws Throwable{
runner = null;
super.finalize();
}
public void paintComponent(Graphics comp) {
Graphics2D comp2D = (Graphics2D)comp;
super.paintComponent(comp); //draw maze background
if (UnscaledWalkerSprite != null){ //If a picture has been
specified
if(ScaledSprite == null/* ||
ScaledSprite.getWidth()!=DrawingAssistant.CellWidth*/)
ScaledSprite =
UnscaledWalkerSprite.getScaledInstance(DrawingAssistant.CellWidth ,
DrawingAssistant.CellHeight , 0);
MediaTracker track = new MediaTracker(this);
track.addImage(ScaledSprite, 0);
try{
track.waitForAll();
//to do: Make a "getCenterPoint" function in Positioner class
int PixelLoc_X = DrawingAssistant.X(posX + 0.5f, posY + 0.5f) -
DrawingAssistant.CellWidth/2;
int PixelLoc_Y = DrawingAssistant.Y(posX + 0.5f, posY + 0.5f) -
DrawingAssistant.CellHeight/2;
comp2D.drawImage(ScaledSprite, PixelLoc_X, PixelLoc_Y, this); }
catch(InterruptedException e){} //didn't work
}
}
public void run() {
int g=0;
while(runner!=null){
walk();
pause(1500);
g++;
if(g>3)
g=0;
UnscaledWalkerSprite = UnscaledWalkerSprites[g];
ScaledSprite = null;
}
}
public void walk() {
for (float i = 0; i < 10; i += .01) {
posX = i;
repaint();
pause(11);
}
}
public void pause(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) { }
}
}