Reputation: 950
I am using the following code to generate a sine wave:
The speed of this animation is slow-fast-slow.
Code:
public static final double SINE_TO_180 = 114.58865012930961, TIMES = 180, SINE_OF_90 = Math.sin(Math.toRadians(90));
public static void main(String[] args) throws Exception{
float velc = 200;
float angle = 45;
float resistance = 0f;
double multiple = (velc * 2.5 / SINE_TO_180);
int offset = 0;
double y = 0;
double x = 0;
double h = 0;
double cos = Math.cos(Math.toRadians(angle));
double sin = Math.sin(Math.toRadians(angle));
for(int i = offset; i < TIMES + 1 + offset; i ++){
y += ((Math.sin(Math.toRadians(i * 2)))) * multiple * sin;
if(y >= h)
h = y;
x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
// x += multiple * cos;
// if(i + offset < TIMES / 2){
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
// }else{
// x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
// }
}
y = Math.round(y);
//do round x?
x = Math.round(x);
System.out.println("X: " + x);
JFrame frm = new JFrame("Projectile!");
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage b = new BufferedImage((int)x + 1, (int)h + 1, BufferedImage.TYPE_INT_RGB);
Graphics g = b.getGraphics();
y = 0;
x = 0;
JLabel l = new JLabel(new ImageIcon(b));
frm.add(l);
frm.pack();
frm.setVisible(true);
for(int i = offset; i < TIMES + 1 + offset; i ++){
y += ((Math.sin(Math.toRadians(i * 2)))) * multiple * sin;
x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
// x += multiple * cos;
// if(i + offset < TIMES / 2){
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
// }else{
// x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
// }
g.setColor(Color.red);
g.drawLine((int)x, (int)(h - y), (int)x, (int)(h - y));
l.setIcon(new ImageIcon(b));
frm.repaint();
Thread.sleep((int)(1000.0 / 24.0));
}
ImageIO.write(b, "png", new File("C:\\proj.png"));
}
Now I would like to change the sine animation to fast-slow-fast where it is slow at its peak so I tried the following result and got this:
I would expect it to be the same just the animation speed different. Code:
public static void main(String[] args) throws Exception{
float velc = 200;
float angle = 45;
float resistance = 0f;
double multiple = (velc * 2.5 / SINE_TO_180);
int offset = 0;
double y = 0;
double x = 0;
double h = 0;
double cos = Math.cos(Math.toRadians(angle));
double sin = Math.sin(Math.toRadians(angle));
for(int i = offset; i < TIMES + 1 + offset; i ++){
y += (1 - Math.sin(Math.toRadians(i * 2))) * multiple * sin;
if(y >= h)
h = y;
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
x += 2;
// x += multiple * cos;
// if(i + offset < TIMES / 2){
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
// }else{
// x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
// }
}
y = Math.round(y);
//do round x?
x = Math.round(x);
System.out.println("X: " + x);
JFrame frm = new JFrame("Projectile!");
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage b = new BufferedImage((int)x + 1, (int)h + 1, BufferedImage.TYPE_INT_RGB);
Graphics g = b.getGraphics();
y = 0;
x = 0;
JLabel l = new JLabel(new ImageIcon(b));
frm.add(l);
frm.pack();
frm.setVisible(true);
for(int i = offset; i < TIMES + 1 + offset; i ++){
y += (1 - Math.sin(Math.toRadians(i * 2))) * multiple * sin;
x += 2;
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5) * Math.abs(cos);
// x += multiple * cos;
// if(i + offset < TIMES / 2){
// x += Math.sin(Math.toRadians(i)) * multiple * ((1 - resistance) * 1.5);
// }else{
// x += Math.sin(Math.toRadians(TIMES / 2)) * multiple * (1 - resistance);
// }
g.setColor(Color.red);
g.drawLine((int)x, (int)(h - y), (int)x, (int)(h - y));
l.setIcon(new ImageIcon(b));
frm.repaint();
Thread.sleep((int)(1000.0 / 24.0));
}
ImageIO.write(b, "png", new File("C:\\proj2.png"));
}
Anyone know what I am doing wrong because I expect the result to be the same as the first just different animation speeds?
Upvotes: 2
Views: 4030
Reputation: 3454
if you want to have a smooth animation i would seperate the data and the animation;
first create your data - it is a (mathematical) function [meaning f(x)->y], so you can simply use an array for data
private int endOfX = 100; //adjust as you wish
private int[] data;
public void calculateData(){
data = new int[amendOfX ountPixels];
for(int x = 0; x < endOfX ; x++){
y = x*x; //this is an example, use your mathematical function here
}
}
so - now you can easily use this data to provide a smooth animation
public class AnimationOfFunction(){
public static void main(String[] args){
new AnimationOfFunktion().createAndShowGui(); //as from java tutorials
}
private BufferedImage img;
private Graphics gr;
private void createAndShowGui(){
calculateData(); first of all we create the data!
JFrame frame = new JFrame();//then create your frame here
JPanel panel = createContent(); //create your drawing panel here
frame.add(panel);//adding drawing panel
frame.pack(); //setting the proper size of frame
frame.setVisible(true); //show frame
startAnimation(panel); //this is important - after showing the frame you start your animation here!
}
}
so - this would be the start of you application, what to do now? first create a proper drawing panel:
private JPanel createContent(){
//create a anonym class
@surpress serial
JPanel panel = new JPanel(){
@override
public void paintComponent(Graphics gr){
super.paintComponent(gr);
gr.drawImage(img, 0,0, null);
}
}
panel.setPreferredSize(new Dimension(img.getWidth(), img.getHeight() ));
return panel;
}
and most important - you have to start the animation:
private void startAnimation(final JPanel panel){
//create a anonym class
Runnable r = new Runnable(){
private int py = 0; //previous values
private int py = 0; //previous values
@overrdie
public void run(){
for(int x = 0; x < endOfX ; x++){
int y = data[x];
//now we have x and y, so you can plot your function;
gr.drawLine(px, py, x,y); //you can scale here
int sleeptime = calculateSleepTime(px,py, x,y);
Thread.sleep(sleeptime);
//set the previouse values;
px = x;
py = y;
//important - repaint your panel to create an 'animation'
panel.repaint();
}
}
}
//having that runnable we must start that runnable within an thread
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.start();
}
so whats left to do? we must calculate the sleep time: if the distance between two points is 'big' we sleep longer, if the distance is short, we sleep less...
public int calculateSleeptime(int px, int py, int x, int y){
int distance = (y-py)*(y-py)+(x-px)*(x-px);
distance = (int)(Math.sqrt(distance);
int sleepTime = distance*100; //play with this value!
return sleeptime;
}
I have written that code all out of my head, i didn't have any IDE to check if it contains any spelling errors or compiling errors, please do that for yourself, as well as i didn't initiate the BufferedImage img ang Graphics gr. but obvious you can do that already!
Upvotes: 3