Order and timing..
hi,
im currently trying to program a small animation for my university course, and have run into an issue im really stuck with. We have to use a package called Java Elements, which gives us the ability to use a simple drawing window ,apparently its easier than the AWT. We then have to draw simple shapes and animate them, in a simple way. Ive draw the shapes i want to animate, and i think i can work out how to move them and change their shape, but im not sure how i can implement a timing system to make each change in their shape come up after the previous shape change.
id like to use the code
public static void SecondBy24()
{
long now = System.currentTimeMillis();
long then = now + 42;//one 24th of a second, to get smooth animation (24fps)
while (System.currentTimeMillis() < then)
{} // waits for 41 milliseconds
}
this, i think, should allow me to delay things being shown by 0.042 seconds, which if i pull it off correctly should give 24 frames per second animation! id like to use this in conjunction with a while loop so i dont have to type out the code for how many pixels i want each shape to move, if you see what i mean.. hope its clear!
ive set up my picture so far with each different shape inside a different method, then the main method calls them all. but ive found if i put the time delay method into the shape methods, it delays the whole picture coming up, where as i need each shape to delay its changing state at the same time as each other.. i hope this is clear its very hard to put it into words!
hope someone can shed a bit of light on how i can solve this problem, my brain is aching!
thanks alot if you even read all my text!
Jonny :)
[1765 byte] By [
Jonnexa] at [2007-10-2 5:00:24]

Have a look at Timers:javax.swing.Timer: http://java.sun.com/docs/books/tutorial/uiswing/misc/timer.html(Or java.util.Timer - but then you'll have to be careful with thread safety).
hi again,
thanks for your suggestion, ive had a good look at the link you gave but i cant really work ouut how to implement the swing timer. i couldnt see any code to input to give me a swing timer, and i coudlnt work out how i used it to do my bidding after i had created it.. can anyone give me a few tips?
would be really grateful! thanks alot
Jonny
Hi,
Try this:
public void start( )
{
// applet start function
updateTime( ); // your function to change images
if(timer == null)
{
// 1000 millisecond
timer = new Timer(1000,new TimerHandler( ));
timer.start( );
}
else
{
if(!timer.isRunning( ))
timer.restart( );
}
}
public void stop( )
{
// applet stop function
timer.stop( );
}
private class TimerHandler implements ActionListener
{
public void actionPerformed(ActionEvent actionevent)
{
updateTime( );
}
}
p/s: don't forget to import javax.swing.Timer
Marlini.
Hi,
thanks alot for the code, but i cant really full make sense of it. Im pretty new to java and haven't done a huge amount, if you have time could you go through your code explain what is all doing, and how i need to implement it, or maybe give some pointers?
(also when i put your code into my project each lilne had an error, and i did import javax.swing.Timer.*; so im guessing i need to modify the code in some way..)
The thing ive got is a different method for each part of the face, ill paste my code here now so you can see how i was hoping to achive this animation.
import element.*;
import javax.swing.Timer.*;
import java.awt.Color;
class rushworj_assign1
{
public void start( )
{
// applet start function
updateTime( );
// your function to change images
if(timer == null)
{
// 1000 millisecond
timer = new Timer(1000,new TimerHandler( ));
timer.start( );
}
else
{
if(!timer.isRunning( ))
timer.restart( );
}
}
public void stop( )
{
// applet stop function
timer.stop( );
}
private class TimerHandler implements
ActionListener
{
public void actionPerformed(ActionEvent actionevent)
{
updateTime( );
}
}
public static void main(String [] args)
{
DrawingWindow d = new DrawingWindow(200,200);
head(d);
eye1(d);
eye2(d);
nose(d);
mouth(d);
}
public static void head(DrawingWindow d)
{
d.setForeground(Color.pink);
final int Start = 180, Angle = 180;
Rect face = new Rect(15,-120,115,270);
Arc faceArc = new Arc(face,Start,Angle);
d.fill(faceArc);
d.setForeground(Color.black);
Line hair1 = new Line(10,10,20,20);
Line hair2 = new Line(20,20,30,10);
Line hair3 = new Line(30,10,40,20);
Line hair4 = new Line(40,20,50,10);
d.draw(hair1);
d.draw(hair2);
d.draw(hair3);
d.draw(hair4);
}
public static void eye1(DrawingWindow d)
{
d.setForeground(Color.black);
Oval eye1 = new Oval(30,20,40,50);
d.draw(eye1);
}
public static void eye2(DrawingWindow d)
{
Oval eye2 = new Oval(75,20,40,50);
d.draw(eye2);
}
public static void nose(DrawingWindow d)
{
Line nose1 = new Line(70,70,50,110);
Line nose2 = new Line(50,110,70,110);
d.draw(nose1);
d.draw(nose2);
}
public static void mouth(DrawingWindow d)
{
final int Start = -90, Angle = 50;
Rect arcRect = new Rect(30,80,70,60);
Arc mouth = new Arc(arcRect,Start,Angle);
d.draw(mouth);
}
}
I just pasted your part in at the top hoping it would compile and then id be able to fathom what it was doing.. but i didnt get far!
what im hoping to do is use maybe one more method with will update the positoins of each shape inside the other methods. In side this method id like to use a while loop so that the shapes move and continue moving untill they reach a limit that il put in. if this is possible...
and then the timer would need to be somewhere in that method i suppose. unless anyone else has any good suggestions?
thanks alot again for any help recieved or about to be recieved! much appreciated! :)
thanks
jonny
Hi;
I rearranged your code, unfortunately I could not test it because element.* is not a standard package (or at least it doesn't come with my netbeans).
Here is the code:
/*
* rushworj_assign1.java
*
* Created on November 17, 2005, 8:59 AM
*/
import element.*;
import java.awt.*;
import javax.swing.Timer;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class rushworj_assign1
{
private static Timer timer;
/** Creates a new instance of rushworj_assign1 */
public rushworj_assign1() {
}
public static void main(String[] args)
{
rushworj_assign1 animator = new rushworj_assign1();
animator.run();
timer.stop();
}
public void run( )
{
if(timer == null)
{
// 400 millisecond
timer = new Timer(400,new TimerHandler( ));
timer.start( );
}
else
{
if(!timer.isRunning( ))
timer.restart( );
}
}
public void startAnimation()
{
DrawingWindow d = new DrawingWindow(200,200);
head(d);
eye1(d);
eye2(d);
nose(d);
mouth(d);
}
public void head(DrawingWindow d)
{
d.setForeground(Color.pink);
final int Start = 180, Angle = 180;
Rect face = new Rect(15,-120,115,270);
Arc faceArc = new Arc(face,Start,Angle);
d.fill(faceArc);
d.setForeground(Color.black);
Line hair1 = new Line(10,10,20,20);
Line hair2 = new Line(20,20,30,10);
Line hair3 = new Line(30,10,40,20);
Line hair4 = new Line(40,20,50,10);
d.draw(hair1);
d.draw(hair2);
d.draw(hair3);
d.draw(hair4);
}
public void eye1(DrawingWindow d)
{
d.setForeground(Color.black);
Oval eye1 = new Oval(30,20,40,50);
d.draw(eye1);
}
public void eye2(DrawingWindow d)
{
Oval eye2 = new Oval(75,20,40,50);
d.draw(eye2);
}
public void nose(DrawingWindow d)
{
Line nose1 = new Line(70,70,50,110);
Line nose2 = new Line(50,110,70,110);
d.draw(nose1);
d.draw(nose2);
}
public void mouth(DrawingWindow d)
{
final int Start = -90, Angle = 50;
Rect arcRect = new Rect(30,80,70,60);
Arc mouth = new Arc(arcRect,Start,Angle);
d.draw(mouth);
}
private class TimerHandler implements ActionListener
{
public void actionPerformed(ActionEvent actionevent)
{
startAnimation();
}
}
As I said earlier, I do not know if this would work because I do not know what's in element.* package. You might have to do some modifications to it. I hope this will help you.
Marlini
hi again,
thanks for your efforts but im afraid im pretty lost! i pasted your code in and got errors, and because im really a java noob i dont know how to sort them out.
however i have made some minor progress. I used the original timer i had, and managed to implement a while loop so that 1 of my objects (in the case i did it it was the eye1) moves at a smooth rate across the screen, and stops when the while loop condition is met. It works great, and would work fine if i could just fathom these timers! i tried doing 2 things, none of which worked for the following reasons
1) i tried having the while loop inside the individual methods, so i started with having a while loop inside eye1, which worked, except because eye1s method comes before any of the other methods, the compiler looks at the while loop and runs it through before it shows any of the next methods. So in other words the timer is stopping the rest of the objects coming on screen untill the while loop is satsified
2) i put the while loop into the main method, this didnt work because i was trying to clear an object called eye1(d), but in fact thats a method not an object. and .. now my head really hurts and i cant think of an easy way around. there must be a simple way that doesnt involve the swing timer? or a simple way i can understand that does involve it!
ill paste the code i used for the 1st example while loop, and my timer code again:
public static void eye1(DrawingWindow d)
{
int xcoord = 1;
int eye1x = 30;
d.setForeground(Color.white);
Oval eye1 = new Oval(30,20,40,50);
d.fill(eye1);
while (xcoord <= 20)
{
Timer();
d.clear(eye1);
xcoord++;
eye1.left(eye1x + xcoord);
d.fill(eye1);
}
}
thats the eye1 method with while loop
public static void Timer()
{
long now = System.currentTimeMillis();
long then = now + 41;
while (System.currentTimeMillis() < then)
{
}
}
theres my trusty timer! .. so if i could either have it so that each method has a while loop like eye1 above, and then the main method calls each method at the same time, that might work? or if i could.. i dont know. my brains shutting off! if someone manages to help me ill kiss them!! thanks alot for all your efforts so far MarliniAliasAli, im sure you would be able to do this easily on your own! but maybe what ive just posted will give you an extra bit of insight?
i hope so, i so badly want to crack this!
thanks alot alot
jonny
> 1) i tried having the while loop inside the
> individual methods, so i started with having a while
> loop inside eye1, which worked, except because eye1s
> method comes before any of the other methods, the
> compiler looks at the while loop and runs it through
> before it shows any of the next methods. So in other
> words the timer is stopping the rest of the objects
> coming on screen untill the while loop is satsified
If you want all of them to run simultaneously, you might want to look into multithreading.
> 2) i put the while loop into the main method, this
> didnt work because i was trying to clear an object
> called eye1(d), but in fact thats a method not an
> object.
The problem is, you give the name of your method eye1( ) and another Oval object with the same name :
>public static void eye1(DrawingWindow d)
>{
> int xcoord = 1;
> int eye1x = 30;
> d.setForeground(Color.white);
> Oval eye1 = new Oval(30,20,40,50);< try a different name
> d.fill(eye1);
> while (xcoord <= 20)
> {
> Timer();
> d.clear(eye1);
> xcoord++;
> eye1.left(eye1x + xcoord);
> d.fill(eye1);
> }
>}
>
//java.lang.Thread
public static void sleep(long millis) throws InterruptedException
/*
Causes the currently executing thread to sleep (temporarily cease execution)
for the specified number of milliseconds.
*/
hi,
ok, i changed the name of the object variable inside eye1 from eye1 to eyeLeft and then put this while loop into my main method.. (it still doenst work, but maybe im just missing something small now..?)
public static void main(String [] args)
{
int xcoord = 1;
int eye1x = 30;
int eye2x = 75;
int nose1x = 70;
int nose2x = 50;
int mouthx = 30;
DrawingWindow d = new DrawingWindow(200,200);
head(d);
while (xcoord <= 20)
{
Timer();
d.clear(eyeLeft.eye1());
xcoord++;
eye1.left(eye1x + xcoord);
d.draw(eye1);
}
eye1(d);
eye2(d);
nose(d);
mouth(d);
if this worked id modify the method so that eye2,, nose and mouth were all inside the while loop, whileing away. but theer's an error.. ill paste all my current code here in the hope it will shead some light!
import element.*;
import java.awt.Color;
class rushworj_assign1
{
public static void Timer()
{
long now = System.currentTimeMillis();
long then = now + 41;
while (System.currentTimeMillis() < then)
{
}
}
public static void main(String [] args)
{
int xcoord = 1;
int eye1x = 30;
int eye2x = 75;
int nose1x = 70;
int nose2x = 50;
int mouthx = 30;
DrawingWindow d = new DrawingWindow(200,200);
head(d);
while (xcoord <= 20)
{
Timer();
d.clear(eyeLeft.eye1());
xcoord++;
eye1.left(eye1x + xcoord);
d.draw(eye1);
}
eye1(d);
eye2(d);
nose(d);
mouth(d);
}
public static void head(DrawingWindow d)
{
d.setForeground(Color.pink);
final int Start = 180, Angle = 180;
Rect face = new Rect(15,-120,115,270);
Arc faceArc = new Arc(face,Start,Angle);
d.fill(faceArc);
d.setForeground(Color.black);
Line hair1 = new Line(10,10,20,20);
Line hair2 = new Line(20,20,30,10);
Line hair3 = new Line(30,10,40,20);
Line hair4 = new Line(40,20,50,10);
d.draw(hair1);
d.draw(hair2);
d.draw(hair3);
d.draw(hair4);
}
public static void eye1(DrawingWindow d)
{
d.setForeground(Color.black);
Oval eyeLeft = new Oval(30,20,40,50);
d.draw(eyeLeft);
}
public static void eye2(DrawingWindow d)
{
Oval eye2 = new Oval(75,20,40,50);
d.draw(eye2);
}
public static void nose(DrawingWindow d)
{
Line nose1 = new Line(70,70,50,110);
Line nose2 = new Line(50,110,70,110);
d.draw(nose1);
d.draw(nose2);
}
public static void mouth(DrawingWindow d)
{
final int Start = -90, Angle = 50;
Rect arcRect = new Rect(30,80,70,60);
Arc mouth = new Arc(arcRect,Start,Angle);
d.draw(mouth);
}
}
also, ill check out multithreading, but is it hard? i mean would you be able to explain in a few lines how i could implement it to my problem? if not i bet its too hard for me to understand at this stage.
also what is thte last post about, i cant really make head or tail of it.. sorry.. i feel so stupid there must be an easy answer to this.
thanks to you all again
Jonny
Hi,
It seems like the problem here is that you don't fully understand the concept of OOP. Like for example here:
> d.clear(eyeLeft.eye1());
eyeLeft is an object created within the eye1( ) method. I think I understand what you are trying to do, and I want to suggest you put the head, eye1, eye2, nose and mouth in a separate class so you can create an object of that class that can call those methods, OR (maybe this is easier) you can do this : MyClass face = new MyClass( ) where MyClass is the name of your class, and have this line in main( ) function. This way, you can do d.clear(face.eye1( ));. Within main( ) function, you must use face.something( ) to tell the program that you are working on that face object.
Another thing is,
> eye1.left(eye1x + xcoord);
> d.draw(eye1);
eye1( ) is a method. These two lines won't work. I don't know where that left( ) method came from, MAYBE if you can use face as the object instead of eye1.
And this one:
> eye1(d);
it should work, but I think it would be better if you do face.eye1(d);.
You could also have DrawingWindow d = new DrawingWindow(200,200); as a global object since there would be only one d and you will use the same d during entire process. Therefore, you don't have to keep passing it to your head,eye1,eye2,nose,and mouth methods.
I hope this would help a bit. Java is a very interesting language. Don't give up on it :p~
Marlini
Hi,
When I think about it , I don't think this :
> d.clear(face.eye1( ));
would work. You want to clear the eye object. The problem is, eye1( ) is a method. You can do d.clear(face);, which will clear the whole thing, or if you create an eye object, you can do d.clear(face.eye);
About multithreading, it is a VERY interesting topic. You should look into it AFTER you solve this problem.
Marli.
Hi again!
thank you very much firsty for your continued help, i think something clicked and i have got somewhere, by using much more extensive passing. here is my current code. In order to see it running youl need to download java Elements and mount it. though im not so confident that will even work now, as i just got this version of the code home and it doesnt work properly.. at uni we have netbeans 3.6 on mac, and i have the same here on my mac, but it didnt animate as it had at uni, so tried nb4.1 and that didnt even recognise the line
DrawingWindow d = new DrawingWindow();
maybe i could do what you said and make that global, could that be the issue?
anyway here is my code:
import element.*;
import javax.swing.Timer.*;
import java.awt.Color;
class rushworj_assign1
{
public static void Timer()
{
long now = System.currentTimeMillis();
long then = now + 41;
while (System.currentTimeMillis() < then)
{
}
}
public static void main(String [] args)
{
int xcoord = 1;
int headx = 25;
int eye1x = 40;
int eye1width = 20;
int eye2x = 65;
int eye2width = 40;
int nose1x = 50;
int nose2x = 50;
int nosepos = 0;
int mouthx = 30;
int eyevar = 0;
DrawingWindow d = new DrawingWindow(200,200);
while (xcoord <= 40)
{
Timer();
ClearAll(d);
head(d,xcoord + headx);
eye2(d,xcoord + (xcoord/2) + eye2x, eye2width - xcoord/2);
eye1(d,xcoord + eye1x, eye1width + xcoord/2);
nose(d,xcoord + nose1x, nosepos);
nose2(d,xcoord + nose2x, nosepos);
mouth(d,xcoord + mouthx);
xcoord++;
nosepos+=1;
if (xcoord % 2 == 0)
{
eyevar++;
}
}
}
public static void ClearAll(DrawingWindow d)
{
d.setForeground(Color.white);
Rect ClearAll = new Rect(0,0,200,200);
d.fill(ClearAll);
}
public static void head(DrawingWindow d, int xpos)
{
d.setForeground(Color.pink);
final int Start = 180, Angle = 180;
Rect face = new Rect(25,-120,100,270);
Arc faceArc = new Arc(face,Start,Angle);
faceArc.left(xpos);
d.fill(faceArc);
}
public static void eye1(DrawingWindow d, int xpos, int eyewidth)
{
d.setForeground(Color.black);
Oval eye1 = new Oval(40,20,eyewidth,50);
eye1.left(xpos);
d.draw(eye1);
}
public static void eye2(DrawingWindow d, int xpos, int eyewidth)
{
d.setForeground(Color.black);
Oval eye2 = new Oval(xpos,20,eyewidth,50);
d.draw(eye2);
}
public static void nose(DrawingWindow d, int xpos, int nosepos)
{
d.setForeground(Color.black);
Line nose1 = new Line(25+xpos,70,nosepos+xpos,110);
d.draw(nose1);
}
public static void nose2(DrawingWindow d, int xpos, int nosepos)
{
Line nose2 = new Line(nosepos+xpos,110,20+xpos,110);
d.draw(nose2);
}
public static void mouth(DrawingWindow d, int xpos)
{
final int Start = -90, Angle = 50;
Rect arcRect = new Rect(30,80,70,60);
Arc mouth = new Arc(arcRect,Start,Angle);
mouth.left(xpos);
d.draw(mouth);
}
}
al the parts that refer to the drawing window come up with red lines saying 'cannot resolve symbol' .. i dont know why! it worked like a dream with cream at uni and now its stopped! and on 3.6 it doesnt show any errors but the picture doenst animate! even more frustrating as i dont know what to change to make it work! ahh.. some days java is so cool and works so well but others its so frustrating just to get working what WAS working! nightmare!
anyway, not much needed doing to this code to finalise it ready for submission, but if you could see why it might not be working thatd be great.. i can finish this this weekend itd be so useful and i fully thought itd be able to, but now this unexpected problem is kicking me in my nuts. thats very much for your time, ill send some more of those duke dollars your way (though im damned if i know what advantage they give anyone!)
thanks alotalot! hope to hear from you agian soon!
Jonny
oh wait! no worries, i managed to find the problem after ages! (ages i could have been FINISHING THE WHOLE ASSIGNEMENT! ahhh coding..)
anyway, i think i just need to add to it a small amount to move the mouth and then put in some pupils for the eyes, but its nearly done! thanks alot for your help, and ill post my final code here so you can see it if you want, as you have spent alot of time helping me!
thanks alot!
Jonny
glad you got it done. hope I help you a bit, but it looks like you got it all on your own. anyway, good work!Marlini.