Dual Time Analog Clock Not Printing Two Different Times - java

I am passing two different times into two different objects and the time is always the same. Any suggestions as to what I should do?
public class TwoTimeClock extends JFrame {
Clock clockFace;
Clock clockFacetwo;
public static void main(String[] args) {
JFrame windo = new TwoTimeClock();
windo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
windo.setVisible(true);
}
private final Clock clockFaceTwo;
/**
* empty constructor. initializes instance variables, draws the clocks,
* and starts them
*/
public TwoTimeClock() {
Container content = this.getContentPane();
content.setLayout(new BorderLayout());
Time time1 = new Time();
Time time2 = new Time();
clockFace = new Clock(time1);
clockFaceTwo = new Clock(time2);
content.add(clockFace, BorderLayout.WEST); //BorderLayout.WEST and BorderLayout.EAST decide the clocks lie in the left or right of box
//hint if you add another clockFace to the content object above, then the canvas will grow in size
content.add(clockFaceTwo, BorderLayout.EAST);
this.setTitle("Baltimore New Delhi");
this.pack();
clockFace.start();
time2.setHrsOffset(9);
time2.setMinsOffset(30);
clockFaceTwo.start();
}
}
Time time;
private static final int spacing = 10;
private static final float threePi = (float) (3.0 * Math.PI);
// Angles for the trigonometric functions are measured in radians.
// The following in the number of radians per sec or min.
private static final float radPerSecMin = (float) (Math.PI / 30.0);
private int size; // height and width of clock face
private int centerX; // x coord of middle of clock
private int centerY; // y coord of middle of clock
private BufferedImage clockImage;
private javax.swing.Timer t;
/**
* //>>>>>>>>>>>>>>>>> You should modify this constructor to take an object of Time class as parameter
* Constructor. Takes an object of the Time class that it will use for showing the time
* #param
*/
public Clock(Time t1) {
this.time = t1;
this.setPreferredSize(new Dimension(300, 300));
this.setBackground(Color.white);
this.setForeground(Color.black);
t = new javax.swing.Timer(1000,
new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
update();
}
});
}
/**
* Replace the default update so that the plain background doesn't get drawn.
*/
public void update() {
this.repaint();
}
public void start() {
t.start(); // start the timer
}
public void stop() {
t.stop(); // stop the timer
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g); // paint background, borders
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// The panel may have been resized, get current dimensions
int w = getWidth();
int h = getHeight();
size = ((w < h) ? w : h) - 2 * spacing;
size -= 50; //reducing size to make space for text below clock face
centerX = size / 2 + spacing;
centerY = size / 2 + spacing;
// Create the clock face background image if this is the first time,
// or if the size of the panel has changed
if (clockImage == null
|| clockImage.getWidth() != w
|| clockImage.getHeight() != h) {
clockImage = (BufferedImage) (this.createImage(w, h));
// now get a graphics context from this image
Graphics2D gc = clockImage.createGraphics();
gc.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
drawClockFace(gc);
}
time.update();
time.updateOffSet();
//>>>>>>>>>>>>>>>>>>>>>>>
// Draw the clock face from the precomputed image
g2.drawImage(clockImage, null, 0, 0);
// Draw the clock hands
drawClockHands(g);
//Print Clock
g2.drawString(Time.toStandard(), 90, h-15);
g2.drawString(Time.toMilitary(), 90, h-30);
}
/**
* The hour, minute, and second hand
* #param g
*/
private void drawClockHands(Graphics g) {
int secondRadius = size / 2;
int minuteRadius = secondRadius * 3 / 4;
int hourRadius = secondRadius / 2;
// second hand
float fseconds = time.getSecs() + (float) time.getMillis()/ 1000;
float secondAngle = threePi - (radPerSecMin * fseconds);
drawRadius(g, centerX, centerY, secondAngle, 0, secondRadius);
// minute hand clock 1
float fminutes = (float) (time.getMins() + fseconds / 60.0);
float minuteAngle = threePi - (radPerSecMin * fminutes);
drawRadius(g, centerX, centerY, minuteAngle, 0, minuteRadius);
// hour hand clock 1
float fhours = (float) (time.getHrs() + fminutes / 60.0);
float hourAngle = threePi - (5 * radPerSecMin * fhours);
drawRadius(g, centerX, centerY, hourAngle, 0, hourRadius);
}
private void drawClockFace(Graphics g) {
// clock face
g.setColor(Color.lightGray);
g.fillOval(spacing, spacing, size, size);
g.setColor(Color.black);
g.drawOval(spacing, spacing, size, size);
// tic marks
for (int sec = 0; sec < 60; sec++) {
int ticStart;
if (sec % 5 == 0) {
ticStart = size / 2 - 10;
} else {
ticStart = size / 2 - 5;
}
drawRadius(g, centerX, centerY, radPerSecMin * sec, ticStart, size / 2);
}
}
private void drawRadius(Graphics g, int x, int y, double angle,
int minRadius, int maxRadius) {
float sine = (float) Math.sin(angle);
float cosine = (float) Math.cos(angle);
int dxmin = (int) (minRadius * sine);
int dymin = (int) (minRadius * cosine);
int dxmax = (int) (maxRadius * sine);
int dymax = (int) (maxRadius * cosine);
g.drawLine(x + dxmin, y + dymin, x + dxmax, y + dymax);
}
}
public class Time {
private static int hrs = 00;
private static int mins = 00;
private static int secs = 00;
private static int millis = 00;
static int copyHrs;
static int copyMins;
static int copySecs;
static int hrsOffset;
static int minsOffset = 30;
//Empty Constructor
public Time() {
Calendar t1 = Calendar.getInstance();
hrs = t1.get(Calendar.HOUR);
mins = t1.get(Calendar.MINUTE);
secs = t1.get(Calendar.SECOND);
millis = t1.get(Calendar.MILLISECOND);
}
//Alternate Constructor
public Time(int hours, int minutes, int seconds, int millisec) {
hrs = hours;
mins = minutes;
secs = seconds;
millis = millisec;
}
//Copy Constructor
public Time(Time otherClock) {
copyHrs = hrs;
copyMins = mins;
copySecs = secs;
millis = millis;
}
public int getHrs() {
return hrs;
}
public void setHrs(int hrs) {
this.hrs = hrs;
}
public int getMins() {
return mins;
}
public void setMins(int mins) {
this.mins = mins;
}
public int getSecs() {
return secs;
}
public void setSecs(int secs) {
this.secs = secs;
}
public int getMillis() {
return millis;
}
public void setMillis(int millis) {
this.millis = millis;
}
public static int getHrsOffset() {
return hrsOffset;
}
public void setHrsOffset(int hrsOffset) {
this.hrsOffset = hrsOffset;
}
public void printOffset(Time clock, int hrsOffset, int minsOffset) {
hrs = Math.abs(clock.hrs + hrsOffset);
mins = Math.abs(clock.mins + minsOffset);
secs = clock.secs;
if (hrs < 12) {
System.out.printf("%02d:%02d:%02d AM%n", hrs, mins, secs);
} else if (hrs == 24) {
System.out.printf("12:%02d:%02d AM%n", mins, secs);
} else if (hrs == 12) {
System.out.printf("12:%02d:%02d PM%n", mins, secs);
} else {
System.out.printf("%02d:%02d:%02d PM%n", hrs - 12, mins, secs);
}
}
public static int getMinsOffset() {
return minsOffset;
}
public void setMinsOffset(int minsOffset) {
this.minsOffset = minsOffset;
}
public static void printMilitary() {
hrs = hrs % 24;
System.out.printf("%02d:%02d:%02d %n", hrs, mins, secs);
}
public static void printStandard() {
hrs = hrs % 24;
if (hrs < 12) {
System.out.printf("%02d:%02d:%02d AM%n", hrs, mins, secs);
} else if (hrs == 24) {
System.out.printf("12:%02d:%02d AM%n", mins, secs);
} else if (hrs == 12) {
System.out.printf("12:%02d:%02d PM%n", mins, secs);
} else {
System.out.printf("%02d:%02d:%02d PM%n", hrs - 12, mins, secs);
}
}
#Override
public String toString() {
return hrs + ":" + mins + ":" + secs;
}
public boolean equals(Time otherClock) {
if (hrs == otherClock.hrs && mins == otherClock.mins && secs == otherClock.secs) {
return true;
} else {
return false;
}
}
public static int getCopy() {
copyHrs = Time.hrs;
copyMins = Time.mins;
copySecs = Time.secs;
return copyHrs + copyMins + copySecs;
}
public static void advanceSecs() {
secs++;
if (secs > 59) {
mins++;
secs = 00;
}
if (mins > 59) {
hrs++;
secs = 00;
mins = 00;
}
}
public boolean lessThan(Time otherClock) {
if ((hrs < otherClock.hrs) && (mins < otherClock.mins) && (secs < otherClock.secs)) {
return true;
} else {
return false;
}
}
public boolean notEquals(Time otherClock) {
if ((hrs == otherClock.hrs) && (mins == otherClock.mins) && (secs == otherClock.secs)) {
return true;
} else {
return false;
}
}
public boolean lessOrEquals(Time otherClock) {
if ((hrs <= otherClock.hrs) && (mins <= otherClock.mins) && (secs <= otherClock.secs)) {
return true;
} else {
return false;
}
}
public boolean greaterThan(Time otherClock) {
if ((hrs > otherClock.hrs) && (mins > otherClock.mins) && (secs > otherClock.secs)) {
return true;
} else {
return false;
}
}
public static String toMilitary() {
hrs = hrs%24;
String str = String.format("%02d:%02d:%02d", hrs, mins, secs);
return str;
}
public static String toStandard() {
String str = String.format("%02d:%02d:%02d PM", hrs, mins, secs);
if (hrs > 12) {
hrs = hrs - 12;
str = String.format("%02d:%02d:%02d AM", hrs, mins, secs);
} else if (hrs == 12) {
str = String.format("%02d:%02d:%02d AM", hrs, mins, secs);
}
return str;
}
public void update() {
Calendar t1 = Calendar.getInstance();
hrs = t1.get(Calendar.HOUR);
mins = t1.get(Calendar.MINUTE);
secs = t1.get(Calendar.SECOND);
millis = t1.get(Calendar.MILLISECOND);
}
public void updateOffSet() {
Calendar t1 = Calendar.getInstance();
hrs = t1.get(Calendar.HOUR) + hrsOffset;
mins = t1.get(Calendar.MINUTE) + minsOffset;
secs = t1.get(Calendar.SECOND);
millis = t1.get(Calendar.MILLISECOND);
}
}

You've got nothing but static fields in Time, and this will guarantee that Time instances will all share the same state. Don't do this. Make those fields instance (i.e., non-static) fields.
Also, your Time copy constructor doesn't, and in fact completely ignores the otherClock parameter that passes into it.
Your Time class should not have the copyHrs, copyMins, etc... fields as they serve no useful purpose.
Your getCopy() method is a bit absurd. What use is adding all the mins, hours, and seconds together? The number has no meaning. Shouldn't that method return a Time instance, one with the same state as the current Time instance?

Related

Why are there two player speeds in my game?

For some reason there are two player speeds in my game Orange Quest. What I mean by this is when I test my game in eclipse and my headphones are off. The game goes twice as fast as when my headphones are on.
I sent the game to my friend and he also experiences the same problems. I've tried to debug the code to see if there was a something wrong with it, but I didn't see any problem. I also tried to adjust the player speed but that didn't help either, as it was still going twice as fast when my headphones were off.
Here is the code for the game panel
Oh yah, by the way the frame is 700 by 700
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class GamePanel extends JPanel implements ActionListener {
/**
*
*/
private static final long serialVersionUID = 1L;
Player player;
boolean running = true;
CopyOnWriteArrayList<Wall> walls = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList<LavaWall> lavaWalls = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList<Enemy> enemies = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList<Orange> oranges = new CopyOnWriteArrayList<>();
java.util.Timer gameTimer;
int cameraX;
int offset;
int count = 0;
int index = 0;
int set;
int s = 50;
int r = 75;
BufferedImage dirt;
BufferedImage grass;
BufferedImage lava;
BufferedImage cloud;
BufferedImage spike;
BufferedImage undergroundLava;
BufferedImage character;
BufferedImage thumbnail;
JLabel timeLabel = new JLabel();
JLabel orangeLabel = new JLabel(": 0/7");
double orangeCount = 0;
int elapsedTime = 0;
int minutes = 0;
int seconds = 0;
int ms = 0;
String minutesString = String.format("%02d", minutes);
String secondsString = String.format("%02d", seconds);
String msString = String.format("%02d", ms);
java.util.Timer timer = new java.util.Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
elapsedTime += 10;
minutes = (elapsedTime / 60000);
seconds = (elapsedTime / 1000) % 60;
ms = (elapsedTime / 10) % 100;
minutesString = String.format("%02d", minutes);
secondsString = String.format("%02d", seconds);
msString = String.format("%02d", ms);
timeLabel.setText(minutesString + ":" + secondsString + ":" + msString);
}
};
GamePanel() {
if (running) {
player = new Player(400, 300, this);
reset();
setLayout(null);
gameTimer = new java.util.Timer();
add(player.death);
player.death.setBounds(550, 15, 300, 100);
player.death.setFont(new Font("Verdana", Font.PLAIN, 20));
add(orangeLabel);
orangeLabel.setBounds(320, 15, 200, 50);
orangeLabel.setFont(new Font("Verdana", Font.PLAIN, 20));
gameTimer.schedule(new TimerTask() {
#Override
public void run() {
try {
if (walls.get(walls.size() - 1).x < 800) {
offset += 700;
makeWalls(offset);
}
player.set();
for (Wall wall : walls)
wall.set(cameraX);
for (int i = 0; i < walls.size(); i++) {
if (walls.get(i).x < -800)
walls.remove(i);
}for(Enemy enemy : enemies)
enemy.set(cameraX);
for (LavaWall lava : lavaWalls)
lava.set(cameraX);
for (int i = 0; i < lavaWalls.size(); i++) {
if (lavaWalls.get(i).x < -800)
lavaWalls.remove(i);
}
for(Orange orange : oranges)
orange.set(cameraX);
for(int i = 0; i < oranges.size(); i++) {
if(oranges.get(i).x < -800)
oranges.remove(i);
}
repaint();
} catch (Throwable e) {
e.printStackTrace();
}
}
}, 0, 17);
add(timeLabel);
timeLabel.setText(minutesString + ":" + secondsString + ":" + msString);
timeLabel.setBounds(10, 15, 300, 100);
timeLabel.setFont(new Font("Verdana", Font.PLAIN, 25));
timer.scheduleAtFixedRate(task, 0, 10);
} else if (!running) {
System.exit(0);
}
}
public void makeWalls(int offset) {
Random rnd = new Random();
try {
dirt = ImageIO.read(getClass().getResourceAsStream("/art/dirt block.png"));
grass = ImageIO.read(getClass().getResourceAsStream("/art/grass block.png"));
lava = ImageIO.read(getClass().getResourceAsStream("/art/lava block.png"));
cloud = ImageIO.read(getClass().getResourceAsStream("/art/cloud block.png"));
undergroundLava = ImageIO.read(getClass().getResourceAsStream("/art/underground lava.png"));
thumbnail = ImageIO.read(getClass().getResourceAsStream("/art/thumbnail.png"));
} catch (Exception e) {
e.printStackTrace();
}
if (count == 7) {
oranges.add(new Orange(offset + 50, 500, s, s, thumbnail));
for (int i = 1; i <= 14; i++) {
walls.add(new Wall(offset + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + i * 50, 650, s, s, dirt));
}
}
else if(count != 10) {
if (index == 0) {
for (int i = 1; i <= 14; i++) {
walls.add(new Wall(offset + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + i * 50, 650, s, s, dirt));
if(i == 6) {
enemies.add(new Enemy(offset + 350, 550, r, s));
}
}
set = 0;
} else if (index == 1) {
for (int j = 1; j <= 14; j++) {
for (int i = 650; i >= 350; i -= 50) {
if (i == 350)
walls.add(new Wall(offset, i, s, s, grass));
else
walls.add(new Wall(offset, i, s, s, dirt));
}
offset += 50;
set = 1;
}
} else if (index == 2) {
if(set == 0) {
walls.add(new Wall(offset - 50, 500, s, s, cloud));
walls.add(new Wall(offset - 200, 400, s, s, cloud));
walls.add(new Wall(offset, 300, s, s, cloud));
for (int i = 0; i < 9; i++) {
walls.add(new Wall(offset + 300 + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + 300 + i * 50, 650, s, s, dirt));
}
}else {
for (int i = 1; i <= 14; i++) {
walls.add(new Wall(offset + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + i * 50, 650, s, s, dirt));
if(i == 6) {
enemies.add(new Enemy(offset + 350, 550, r, s));
}
}
}
} else if (index == 3) {
for (int i = 1; i <= 2; i++) {
walls.add(new Wall(offset + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + i * 50, 650, s, s, dirt));
}
lavaWalls.add(new LavaWall(offset + 150, 600, s, s, lava));
lavaWalls.add(new LavaWall(offset + 200, 600, s, s, lava));
lavaWalls.add(new LavaWall(offset + 250, 600, s, s, lava));
lavaWalls.add(new LavaWall(offset + 300, 600, s, s, lava));
lavaWalls.add(new LavaWall(offset + 350, 600, s, s, lava));
lavaWalls.add(new LavaWall(offset + 150, 650, s, s, undergroundLava));
lavaWalls.add(new LavaWall(offset + 200, 650, s, s, undergroundLava));
lavaWalls.add(new LavaWall(offset + 250, 650, s, s, undergroundLava));
lavaWalls.add(new LavaWall(offset + 300, 650, s, s, undergroundLava));
lavaWalls.add(new LavaWall(offset + 350, 650, s, s, undergroundLava));
for (int i = 6; i <= 12; i++) {
walls.add(new Wall(offset + 100 + i * 50, 600, s, s, grass));
walls.add(new Wall(offset + 100 + i * 50, 650, s, s, dirt));
}
}
for(Wall wall : walls) {
for(LavaWall lava : lavaWalls) {
if(lava.hitBox.getBounds() == wall.hitBox.getBounds()) {
lavaWalls.remove(lava);
}
}
}
count++;
index = rnd.nextInt(4);
}
}
public void reset() {
count = 0;
index = 0;
player.x = 200;
player.y = 150;
cameraX = 150;
player.xspeed = 0;
player.yspeed = 0;
walls.clear();
enemies.clear();
lavaWalls.clear();
oranges.clear();
offset = -150;
makeWalls(offset);
player.isDed = false;
}
public void paint(Graphics g) {
try {
super.paint(g);
Graphics2D gtd = (Graphics2D) g;
player.draw(gtd);
for(int i = 0; i < walls.size(); i++) {
try {
walls.get(i).draw(gtd);
} catch (Throwable e) {
}
}for(Enemy enemy : enemies)
enemy.draw(gtd);
for(LavaWall lava : lavaWalls)
lava.draw(gtd);
g.drawImage(thumbnail, 270, 15, 50, 50, null);
for(Orange orange : oranges)
orange.draw(gtd);
} catch (Throwable e) {
e.printStackTrace();
}
}
#Override
public void actionPerformed(ActionEvent e) {
}
public void keyPressed(KeyEvent e) {
if (e.getKeyChar() == 'a')
player.keyLeft = true;
if (e.getKeyChar() == 'w' || e.getKeyCode() == 32)
player.keyUp = true;
if (e.getKeyChar() == 's')
player.keyDown = true;
if (e.getKeyChar() == 'd')
player.keyRight = true;
if (e.getKeyChar() == 'h')
Player.keyGlide = true;
if (e.getKeyChar() == 'j')
player.keyMega = true;
if (e.getKeyChar() == 'l')
player.keyRush = true;
}
public void keyReleased(KeyEvent e) {
if (e.getKeyChar() == 'a')
player.keyLeft = false;
if (e.getKeyChar() == 'w' || e.getKeyCode() == 32)
player.keyUp = false;
if (e.getKeyChar() == 's')
player.keyDown = false;
if (e.getKeyChar() == 'd')
player.keyRight = false;
if (e.getKeyCode() == 27)
System.exit(0);
if (e.getKeyChar() == 'h')
Player.keyGlide = false;
if (e.getKeyChar() == 'j')
player.keyMega = false;
if (e.getKeyChar() == 'l')
player.keyRush = false;
}
}
and here is the player code
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.*;
public class Player {
GamePanel panel;
int x;
int y;
int width;
int height;
double xspeed;
double yspeed;
boolean keyLeft;
boolean keyRight;
boolean keyUp;
static boolean keyGlide;
boolean keyDown;
boolean keyMega;
boolean keyRush;
boolean falling;
boolean isDeathSound;
boolean isDed;
Graphics2D gtd;
long time = 0;
Timer timer;
long start;
long stop;
double deaths = 0;
JLabel death = new JLabel("Deaths: 0");
Rectangle hitBox;
long waitTime;
static Clip clip;
static boolean onGround;
Player(){
}
Player(int x, int y, GamePanel panel){
this.panel = panel;
this.x = x;
this.y = y;
width = 50;
height = 100;
hitBox = new Rectangle(x, y, width, height);
}
public void set() throws Throwable{
Iterator<Orange> orangeItr = panel.oranges.iterator();
if(keyLeft && keyRight || !keyLeft && !keyRight) xspeed *= 0.8;
else if(keyLeft && !keyRight)xspeed--;
else if(keyRight && !keyLeft)xspeed++;
if(keyUp && keyGlide) {keyUp = false;}
if(yspeed > 0)onGround = false;
if(keyMega && keyGlide) {keyMega = false;}
if(onGround && keyGlide)keyGlide = false;
if(xspeed > 0 && xspeed < 0.75)xspeed = 0;
if(xspeed < 0 && xspeed > -0.75)xspeed = 0;
if(xspeed > 7 && !keyRush)xspeed = 7;
if(xspeed < -7 && !keyRush)xspeed = -7;
if(xspeed > 12 && keyRush)xspeed = 12;
if(xspeed < -12 && keyRush)xspeed = -12;
if(yspeed < -12.75) yspeed = -12.75;
if(keyUp && onGround) {
jumpSound();
hitBox.y++;
onGround = false;
for(Wall wall : panel.walls) {
if(wall.hitBox.intersects(hitBox)) {
yspeed = -8;
}
}hitBox.y--;
}if(keyMega && onGround) {
megaSound();
onGround = false;
hitBox.y++;
for(Wall wall : panel.walls) {
if(wall.hitBox.intersects(hitBox)) yspeed = -12.75;
}hitBox.y--;
}
yspeed += 0.3;
if(keyGlide && !onGround && yspeed > 1.2) {
glideSound();
yspeed -= 0.25;
}if(keyDown && !onGround) {
yspeed += 0.4;
}
//horizontal collision
hitBox.x += xspeed;
for(Wall wall : panel.walls) {
if(hitBox.intersects(wall.hitBox)) {
hitBox.x -= xspeed;
while(!wall.hitBox.intersects(hitBox))hitBox.x += Math.signum(xspeed);
hitBox.x -= Math.signum(xspeed);
panel.cameraX += x - hitBox.x;
xspeed = 0;
hitBox.x = x;
}
}
for(Orange orange : panel.oranges){
isDed = false;
if(hitBox.intersects(orange.hitBox)) {
isDed = false;
if(panel.orangeCount != 6) {
isDed = false;
keyGlide = false;
hitBox.x -= xspeed;
while(!orange.hitBox.intersects(hitBox))hitBox.x += Math.signum(xspeed);
hitBox.x -= Math.signum(xspeed);
panel.cameraX += x - hitBox.x;
xspeed = 0;
x = hitBox.x;
panel.orangeCount++;
panel.reset();
panel.orangeLabel.setText(": " +(int)panel.orangeCount + "/7");
onGround = true;
isDed = false;
deathSound();
}
else {
keyGlide = false;
hitBox.x -= xspeed;
while(!orange.hitBox.intersects(hitBox))hitBox.x += Math.signum(xspeed);
hitBox.x -= Math.signum(xspeed);
xspeed = 0;
x = hitBox.x;
onGround = true;
panel.orangeCount++;
panel.orangeLabel.setText(": " + (int)panel.orangeCount + "/7");
orangeSound();
System.out.println("Well done");
Thread.sleep(1100);
System.out.print("your time is ");
System.out.println(panel.timeLabel.getText());
System.out.println("you died " + (int)deaths + " time(s)");
System.exit(0);
}
}
}
//vertical collision
hitBox.y += yspeed;
for(Wall wall : panel.walls) {
if(hitBox.intersects(wall.hitBox)) {
keyGlide = false;
hitBox.y -= yspeed;
while(!wall.hitBox.intersects(hitBox))hitBox.y += Math.signum(yspeed);
hitBox.y -= Math.signum(yspeed);
yspeed = 0;
y = hitBox.y;
onGround = true;
}
}
try {
for(LavaWall lava : panel.lavaWalls) {
if(hitBox.intersects(lava.hitBox)) {
isDed = true;
isDeathSound = true;
keyGlide = false;
hitBox.y -= yspeed;
while(!lava.hitBox.intersects(hitBox))hitBox.y += Math.signum(yspeed);
hitBox.y -= Math.signum(yspeed);
yspeed = 0;
y = hitBox.y;
onGround = true;
isDed = true;
die();
}
}
for(Orange orange : panel.oranges){
isDed = false;
if(hitBox.intersects(orange.hitBox)) {
isDed = false;
if(!(panel.orangeCount == 7)) {
keyGlide = false;
hitBox.y -= yspeed;
while(!orange.hitBox.intersects(hitBox))hitBox.y += Math.signum(yspeed);
hitBox.y -= Math.signum(yspeed);
yspeed = 0;
y = hitBox.y;
onGround = true;
panel.orangeCount++;
panel.reset();
panel.orangeLabel.setText(": " +(int)panel.orangeCount + "/7");
isDed = false;
deathSound();
}
else if(panel.orangeCount == 7) {
keyGlide = false;
hitBox.y -= yspeed;
while(!orange.hitBox.intersects(hitBox))hitBox.y += Math.signum(yspeed);
hitBox.y -= Math.signum(yspeed);
yspeed = 0;
y = hitBox.y;
onGround = true;
panel.orangeCount++;
panel.orangeLabel.setText(": " + (int)panel.orangeCount + "/7");
orangeSound();
System.out.println("Well done");
Thread.sleep(1100);
System.out.print("your time is ");
System.out.println(panel.timeLabel.getText());
System.out.println("you died " + (int)deaths + " time(s)");
Thread.sleep(4500);
System.out.println("press v to exit");
}
}
}
}catch(Throwable e) {
}
panel.cameraX -= xspeed;
y += yspeed;
hitBox.x = x;
hitBox.y = y;
//death code
if(y > 800) {
isDed = true;
onGround = true;
die();
}enemyScript();
}void enemyScript() {
for(Enemy enemy : panel.enemies) {
if(hitBox.intersects(enemy.hitBox)) {
isDed = true;
isDeathSound = true;
keyGlide = false;
hitBox.y -= yspeed;
while(!enemy.hitBox.intersects(hitBox))hitBox.y += Math.signum(yspeed);
hitBox.y -= Math.signum(yspeed);
yspeed = 0;
y = hitBox.y;
onGround = true;
isDed = true;
die();
}
}
}
void jumpSound(){
soundEffect("res\\musicAndSoundEffects\\jump.wav");
}void megaSound(){
soundEffect("res\\musicAndSoundEffects\\megajump.wav");
}void glideSound(){
soundEffect("res\\musicAndSoundEffects\\shorterGlide.wav");
}void deathSound(){
if(isDed) {
soundEffect("res\\musicAndSoundEffects\\death.wav");
}else if(!isDed) {
soundEffect("res\\musicAndSoundEffects\\orangeSound.wav");
}
}void notDie(){
stopSound();
}
void orangeSound(){
soundEffect("res\\musicAndSoundEffects\\orangeSound.wav");
}void stopSound(){
clip.stop();
}
void die() {
deathSound();
panel.reset();
deaths++;
death.setText("Deaths: " + (int)deaths);
onGround = true;
}
static void soundEffect(String filePath) {
try {
File file = new File(filePath);
AudioInputStream sound = AudioSystem.getAudioInputStream(file);
clip = AudioSystem.getClip();
if(onGround && !filePath.equals("res\\musicAndSoundEffects\\shorterGlide.wav")) {
clip.open(sound);
clip.setFramePosition(0);
clip.start();
}else if(filePath.equals("res\\musicAndSoundEffects\\shorterGlide.wav")) {
clip.open(sound);
clip.setFramePosition(0);
clip.start();
}
}catch(Exception e) {
JOptionPane.showMessageDialog(null, e.getStackTrace());
}
}
public void draw(Graphics2D g) {
g.setColor(Color.BLACK);
g.fillRect(x, y, width, height);
}
}
for anyone who knows the answer to this. Please comment the problem and not the answer so that I can learn. thanks
In broad strokes:
Because you're using a java.util.Timer and it is just the wrong tool for the job.
Let's say you want a game to run smoothly, but not slam the CPU of even the most powerful machine imaginable, and also to run as well as it can if the system it runs on is insufficient (that last one is important; even if a system is plenty powerful to run the game, sometimes you get a 'blip' of underperformance because of other stuff the computer was doing, such as when you plug in a USB stick and all sorts of driver shenanigans occurs in the background).
To accomplish these things, you need two crucial properties:
Timing related to the gameplay (such as, if one of the players is moving northbound, the amount of movement that occurs) should be based entirely on 'time passed', and be unaffected by the amount of time required to actually redraw parts of the screen, nor should it be affected by how many 'loops' of screen refresh you manage to squeeze into a single second.
Timing related to rendering needs to go fast as possible, but needs a breaking system: BEFORE you begin the task of 'update game state then render the state to the screen', you should calculate the timing at which that should all be done. Then, once you are done with one loop of the game (adjust game state and rendering all that), you check whether you 'beat the clock'. If you did, THEN wait. In other words, instead of asking a timer to wait a fixed amount of time before doing the next game loop, the amount of time to wait needs to take into account you took some time to adjust the game state and render things.
Here's some example code of a basic game loop. Just use it for inspiration, it doesn't fit verbatim into the code you already have.
class Example {
private static final long NANOS_PER_MILLI =
TimeUnit.MILLISECONDS.toNanos(1);
private static final long NANOS_PER_FRAME =
TimeUnit.SECONDS.toNanos(1) / 60;
private static final long ADJUST_EXPECTATIONS_TRESHOLD =
NANOS_PER_FRAME * 5;
private long start = System.nanoTime();
private long frameCounter = 0;
public void run() {
while (running) {
gameLoop();
}
}
void gameLoop() {
frameCounter++;
long target = startTime + NANOS_PER_FRAME * frameCounter;
// target now holds the exact time at which point we should
// be done with this game loop.
recalcGameState();
redrawStuff();
long end = System.nanoTime();
long delta = target - System.nanoTime();
if (delta > 0) {
// We had time to spare!
// Let's sleep most of that away, giving us
// a little bit of leeway (5msec worth) in case the system is
// going to blip on us.
// Also, CPU waiting is generally granularized at millis,
// so let's convert to millis first, and be 5 millis 'early'
long millisToWait = (delta / NANOS_PER_MILLI) - 5;
if (millisToWait > 0) sleep(millisToWait);
else if (-delta > READJUST_EXPECTATIONS_TRESHOLD) {
// Rats - we missed the boat, and by a lot!
// we are over 5 frames behind, let's readjust
// expectations and slow down the game logic, too:
start = end;
frameCounter = 0;
}
}
}
}
The above code will reliably render at 60 gameloops every second, (that 5msec leeway will adjust itself on the next loop, as that would just mean you get there even faster and thus wait longer) - and will 'catch up' on a blip for at most 5 frames (catching up a ton of frames after a long blip is usually not a good idea, so we limit the catchup mechanism).
Usually when you're forced into readjustment you may want to adjust the game logic's clocks as well (it is a bit unfair for a player to slam into a wall that was way ahead of them because their CPU just decided to doze off for a second, unlikely as that is, whilst they couldn't steer or even see anything!) - so, have a ball with gameStart.
NB: nanoTime is used and not System.currentTimeMillis(), because System.CTM represents the system clock, which means it will drastically change when the user resets their time - modern computers update their clocks by way of a network time server, so this happens all the time (heh), and means that looking at it for frame timing is a bad idea. From time to time the game will do mad glitching when the NTP daemon adjusted the clocks. nanoTime is more or less reflecting 'CPU uptime' and does not get modified when the system clock is adjusted.
NB2: If you need 'frameCounter' to represent game turns, you can't just reset it like this; instead, figure out how many frames you want to adjust by, and then add that many NANOS_PER_FRAME to 'start' instead.

Bukkit countdown timer happening after event

I'm trying to make a Bukkit plugin that warps a player randomly every five minutes. I figured out the warp, but my countdown is happening after the player warps and I want to make it happen before.
Does anyone know why it's doing this?
Here's my code:
public class Commands implements Listener, CommandExecutor {
public String cmd0 = "startwarp";
private main plugin = main.getPlugin(main.class);
#Override
#SuppressWarnings("deprecation")
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
Player player = (Player) sender;
if(sender instanceof Player) {
if (cmd.getName().equalsIgnoreCase(cmd0)) {
if(args.length == 0) {
player.sendMessage(ChatColor.GOLD + "Warp timer begun!");
Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable(){
#Override
public void run() {
Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable(){
int countdown;
#Override
public void run() {
if (countdown >= 1) {
Bukkit.getServer().broadcastMessage(ChatColor.RED + " " + countdown + "...");
countdown--;
}
}
}, 0, 1 * 20);
Location loc = player.getLocation();
int randX = (int) (loc.getBlockX() + ((Math.random() * 1000) - 500));
int randZ = (int) (loc.getBlockZ() + ((Math.random() * 1000) - 500));
int randY = (int) ((Math.random() * 240) + 15);
Location randomtp = new Location(player.getWorld(), randX, randY, randZ);
player.teleport(randomtp);
player.sendMessage(ChatColor.DARK_AQUA + "Teleported!");
//warpTimer timer = new warpTimer();
//timer.runTaskTimer(plugin, 0, 1 * 20);
}
}, 5 * 60 * 20, 5 * 60 * 20);
}
return true;
}
}
return false;
}}
Your Timer starts before the player gets teleported, but the code doesnt wait until the timer is finished, before executing the rest of the code. Try this:
int countdown = 10
new BukkitRunnable() {
#Override
public void run() {
if (countdown >= 1) {
Bukkit.getServer().broadcastMesssage(countdown);
countdown--;
} else {
Location loc = player.getLocation();
int randX = (int) (loc.getBlockX() + ((Math.random() * 1000) - 500));
int randZ = (int) (loc.getBlockZ() + ((Math.random() * 1000) - 500));
int randY = (int) ((Math.random() * 240) + 15);
Location randomtp = new Location(player.getWorld(), randX, randY, randZ);
player.teleport(randomtp);
player.sendMessage(ChatColor.DARK_AQUA + "Teleported!");
cancel();
}
}.runRepeatingTask(*instanceOfMainClass*, 0, 20);
}
This code is handwritten and out of my mind, so maybe there are a few mistakes.

Controlling animation speed of a 2d game

I'm making a small asteroids game, and I'm having some trouble controlling the animation speed.
For example, let's say I have 20 asteroids in my game, when I destroy an asteroid, the amount of asteroids goes down (obviously). Because there are fewer objects in the game, the fps goes up and the animation speed of the asteroids is getting faster and faster.
I fixed it by adjusting the animation speed according to the amount of asteroids I have in the game, but I'm also facing another problem with the explosions when I destroy an asteroid. I could do the same thing I did with the asteroids I suppose, but I just think it's not a very wise way to "solve" it and just seems like bad practice to me.
I thought of capping the fps, but I'm not really sure how to do it. I'd like to get some advices and what's the best way to deal with such situations.
I'll post here my main game class including the game loop, and an example of the explosion class so you'll get the general idea of the code.
Game class and loop:
import com.asteroids.view.*;
public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = -8921419424614180143L;
public static final int WIDTH = 1152, HEIGHT = WIDTH / 8 * 5;
private Thread thread;
private boolean isRunning;
private LoadImages loadImages = new LoadImages();
private Player player = new Player();
private AllObjects objects;
private KeyInput keyInput;
private long delay = 80;
private long currentTime = System.currentTimeMillis();
private long expectedTime = currentTime + delay;
public static BufferedImage test;
public Game() {
new Window(WIDTH, HEIGHT, "Asteroids!", this);
objects = new AllObjects();
objects.addObject(player);
for (int i = 0; i < 20; i++) {
objects.addObject(new Rock((int) (Math.random() * (Game.WIDTH - 64) + 1),
(int) (Math.random() * (Game.HEIGHT - 64) + 1)));
}
keyInput = new KeyInput(player);
this.addKeyListener(keyInput);
}
public void run() {
this.requestFocus();
long lastTime = System.nanoTime();
double amountOfTicks = 60.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
long timer = System.currentTimeMillis();
int frames = 0;
// main game loop.
while (isRunning) {
adjustAsteroidsSpeed();
destroyAsteroids();
collisionLoop();
// used to set delay between every bullet(milliseconds)
currentTime = System.currentTimeMillis();
if (KeyInput.shoot && currentTime >= expectedTime) {
// calculates the accurate position of the x,y on the "circumference" of the
// player
float matchedX = player.getX() + 1 + (float) ((player.getRadius() + 32) * Math.cos(player.getRadian()));
float matchedY = player.getY() - 7 + (float) ((player.getRadius() + 32) * Math.sin(player.getRadian()));
objects.addObject(new Bullet(matchedX, matchedY, player));
expectedTime = currentTime + delay;
}
destroyBullets();
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
tick();
delta--;
}
if (isRunning)
render();
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println("FPS: " + frames);
frames = 0;
}
}
render();
stop();
System.exit(1);
}
private void stop() {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(1);
}
private void render() {
BufferStrategy bs = this.getBufferStrategy();
if (bs == null) {
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.drawImage(LoadImages.getbackground(), 0, 0, getWidth(), getHeight(), this);
objects.render(g);
player.render(g);
g.dispose();
bs.show();
}
private void tick() {
player.tick();
objects.tick();
}
// starting thread and game loop.
public void start() {
thread = new Thread(this);
thread.start();
isRunning = true;
}
// minimum and maximum possible position for object.
public static float Bounds(float value, float min, float max) {
if (value >= max) {
return value = max;
}
if (value <= min) {
return value = min;
} else {
return value;
}
}
// detects collision between two objects
public boolean collision(GameObject a, GameObject b) {
return (b.getX() - a.getX() + 10) * (b.getX() - a.getX() + 10)
+ (b.getY() - a.getY() + 10) * (b.getY() - a.getY() + 10) < (a.getRadius() + b.getRadius())
* (a.getRadius() + b.getRadius());
}
// destroys bullets once they go out of the screen
public void destroyBullets() {
for (int i = 0; i < objects.getSize(); i++) {
if (objects.get(i).getId() == ID.BULLET) {
GameObject bullet = objects.get(i);
if (bullet.getX() > Game.WIDTH || bullet.getX() < 0 || bullet.getY() > Game.HEIGHT
|| bullet.getY() < 0) {
objects.removeObject(bullet);
}
}
}
}
// whenever a collision between an asteroid and a bullet occurs, the asteroid and the bullets are destroyed
public void destroyAsteroids() {
GameObject bullet = null;
GameObject bigRock = null;
for (int i = 0; i < objects.getSize(); i++) {
if (objects.get(i).getId() == ID.BULLET) {
bullet = (Bullet) objects.get(i);
for (int q = 0; q < objects.getSize(); q++) {
if (objects.get(q).getId() == ID.BIGROCK) {
bigRock = objects.get(q);
if (bullet != null && bigRock != null) {
if (collision(bigRock, bullet)) {
objects.addObject(new Explosion(bigRock.getX(), bigRock.getY(), objects));
objects.removeObject(bigRock);
objects.removeObject(bullet);
}
}
}
}
}
}
}
// calculates the amount of asteroids in the game and adjust the asteroids speed
public void adjustAsteroidsSpeed() {
int rocksCount = 0;
Rock rock;
for (GameObject object : objects.link()) {
if (object.getId() == ID.BIGROCK) {
rocksCount++;
}
}
for (GameObject object : objects.link()) {
if (object.getId() == ID.BIGROCK) {
rock = (Rock) object;
rock.setAnimSpeed(rocksCount * 0.002f);
}
}
}
Explosion class:
package com.asteroids.model;
import java.awt.Graphics;
import java.awt.Image;
import com.asteroids.controller.*;
import com.asteroids.view.LoadImages;
public class Explosion extends GameObject {
private AllObjects objects;
private Image explosion;
private float frame = 0;
private float animSpeed = 0.09f;
private int frameCount = 48;
public Explosion(float x, float y, AllObjects objects) {
super(x, y, ID.EXPLOSION, 1);
this.objects = objects;
}
public void render(Graphics g) {
explosion(g);
}
public void explosion(Graphics g) {
frame += animSpeed;
if (frame > frameCount) {
frame -= frameCount;
}
explosion = LoadImages.getExplosion().getSubimage((int) frame * 256, 0, 256, 256);
g.drawImage(explosion, (int) x, (int) y, 110, 110, null);
if (frame >= 47.8f) {
objects.removeObject(this);
}
}
public void tick() {
}
public void setAnimSpeed(float animSpeed) {
this.animSpeed = animSpeed;
}
}
Your main loop is generating uneven updates. If I do nothing, I get anywhere between 7799913 and 8284754 fps, however, if I throw in a 8 millisecond delay (to simulate some work), it drops to around 115-120 fps.
Your intention is to try and get the frame rate to be as even as possible, this will ensure that the animation speed remains the same
Personally, I don't like the "free-wheeling" style of game loop, it means that the loop is been allowed to consume CPU cycles without actually doing anything, where those cycles could be been used to do more important work, like update the UI.
In most cases, I just use a Swing Timer set to something like 5 millisecond intervals and then make use of the date/time API to calculate the difference between now and the last update and make choices about what to do, but, this assumes you're using a Swing based painting path. If you're doing a direct painting path (ie BufferStrategy), you could use a similar idea with a "loop" instead...
public void run() throws InterruptedException {
int frames = 0;
Duration threashold = Duration.ofMillis(1000 / 59);
Duration cycle = Duration.ofSeconds(1);
Instant cycleStart = Instant.now();
// main game loop.
while (isRunning) {
Instant start = Instant.now();
// Some update function...
Thread.sleep(rnd.nextInt(32));
Duration processTime = Duration.between(start, Instant.now());
Duration remainingTime = threashold.minusMillis(processTime.toMillis());
long delay = remainingTime.toMillis();
if (delay > 0) {
Thread.sleep(delay);
} else {
System.out.println("Dropped frame");
}
frames++;
// Render the output
Duration cycleTime = Duration.between(cycleStart, Instant.now());
if (cycleTime.compareTo(cycle) >= 0) {
cycleStart = Instant.now();
System.out.println(frames);
frames = 0;
}
}
}
In this example, your update and paint scheduling code simply have 16 milliseconds to get there job done, otherwise it will drop frames. If the work takes less then 16 milliseconds, the loop will "wait" the remaining time in order to provide some breathing room for the CPU to give time to other threads (and not take update unnecessary time on the CPU)
In the example above, I generate a "random" delay of up to 32 milliseconds for testing. Set it back to 16 and you should get (roughly) 60fps.
Now, I know people are extraordinarily passionate about these things, so if using Thread.sleep and Duration make your skin crawl, you "could" use a "free wheeling" loop, something like the one presented in Java Main Game Loop
Below is a sample implementation, I've set the number of updates and frames per second to 60, but you can change those values to suit your needs...
public void run() throws InterruptedException {
double ups = 60;
double fps = 60;
long initialTime = System.nanoTime();
final double timeU = 1000000000 / ups;
final double timeF = 1000000000 / fps;
double deltaU = 0, deltaF = 0;
int frames = 0, ticks = 0;
long timer = System.currentTimeMillis();
while (isRunning) {
long currentTime = System.nanoTime();
deltaU += (currentTime - initialTime) / timeU;
deltaF += (currentTime - initialTime) / timeF;
initialTime = currentTime;
if (deltaU >= 1) {
Thread.sleep(rnd.nextInt(32));
//getInput();
//update();
ticks++;
deltaU--;
}
if (deltaF >= 1) {
Thread.sleep(rnd.nextInt(32));
//render();
frames++;
deltaF--;
}
if (System.currentTimeMillis() - timer > 1000) {
System.out.println(String.format("UPS: %s, FPS: %s", ticks, frames));
frames = 0;
ticks = 0;
timer += 1000;
}
}
}
Again, the Thread.sleep here is just to inject a random amount of "work". Because it allows for more then 16ms of delay, you will also find it "drops" frames. Your job would be to get you work down to under 16ms per pass

Calculate 'interval and increment' for slide in animation in Java Swing

I'm building an application which has a slideshow in its homepage, currently I use Thread.sleep(10) and add/sub the x position of panel I want to slide.
For example: slideIn(30, panel_1, 10) < this will cause panel_1 to slide in with interval of 30ms and subtracts its x by 10 overtime until the panel is in center/occupy the slideshow_panel. But the con of this method is that the sliding animation won't smooth, I want the sliding animation/transition as smooth as Bootstrap Carousel. Is there a way to calculate the speed and increment/decrement value for slide transition speed?
Actually, I've something that's almost perfect for this. I assume you can create a Path2D for your animation path, right? And it also seems like you want a constant speed. There are a couple of references to my project (http://sourceforge.net/p/tus/code/HEAD/tree/) for calculating distance and showing the JPanel for instance, but it shouldn't be hard to remove them and replace with standard java. Try it out
public abstract class PathAnimation {
private Path2D mPath;
private double totalLength;
/**
* Be careful to call path.closePath before invoking this constructor
* #param path
*/
public PathAnimation(Path2D path) {
mPath = path;
totalLength = 0;
PathIterator iterator = mPath.getPathIterator(null);
//Point2D currentLocation;// = path.getCurrentPoint();
double[] location = new double[6];
iterator.currentSegment(location);
while (!iterator.isDone()) {
double[] loc = new double[6];
iterator.next();
iterator.currentSegment(loc);
if (loc[0] == 0 && loc[1] == 0) continue;
double distance = MathUtils.distance(location[0], location[1], loc[0], loc[1]);
totalLength += distance;
location = loc;
}
}
#Override
public Point2D getLocationAtTime(int time) {
return getLocationAtTime(time / (double) getTotalAnimationTime());
}
public Point2D getLocationAtTime(double pctTime) {
double len = totalLength * pctTime;
PathIterator iterator = mPath.getPathIterator(null);
double[] location = new double[6];
iterator.currentSegment(location);
while (!iterator.isDone()) {
double[] loc = new double[6];
iterator.next();
iterator.currentSegment(loc);
double distance= MathUtils.distance(location[0], location[1], loc[0], loc[1]);
if (distance > len) {
double pctThere = len / distance;
double xSpot = location[0] * (1 - pctThere) + loc[0] * pctThere;
double ySpot = location[1] * (1 - pctThere) + loc[1] * pctThere;
return new Point2D.Double(xSpot, ySpot);
}
len -= distance;
location = loc;
}
throw new ArrayIndexOutOfBoundsException("Path is too short or time is too long!");
}
/**
* Number of milliseconds that this animation spans
* #return
*/
public abstract int getTotalAnimationTime();
public static void main(String args[]) {
Rectangle rect = new Rectangle(10,10,20,20);
final Path2D.Double myPath = new Path2D.Double((Shape)rect);
myPath.closePath();
final PathAnimation myAnimation = new PathAnimation(myPath) {
Area star = new Area(PaintUtils.createStandardStar(15, 15, 5, .5, 0));
#Override
public Dimension getSizeAtTime(int time) {
return new Dimension(15,15);
}
#Override
public void paintAtTime(Graphics2D g, int time) {
Area toPaint = star;
if ((time / 150) % 2 == 1) {
Dimension size = getSizeAtTime(0);
toPaint = new Area(toPaint);
PaintUtils.rotateArea(toPaint, Math.PI / 6);
}
g.setColor(Color.YELLOW);
g.fill(toPaint);
g.setColor(Color.RED);
g.draw(toPaint);
}
#Override
public int getTotalAnimationTime() {
return 10000;
}
};
System.out.println(myAnimation.getLocationAtTime(0));
System.out.println(myAnimation.getLocationAtTime(2500));
System.out.println(myAnimation.getLocationAtTime(4000));
System.out.println(myAnimation.getLocationAtTime(5000));
System.out.println(myAnimation.getLocationAtTime(7000));
System.out.println(myAnimation.getLocationAtTime(7500));
System.out.println(myAnimation.getLocationAtTime(9000));
System.out.println(myAnimation.getLocationAtTime(10000));
final JPanel jp = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int time = ((int) System.currentTimeMillis()) % myAnimation.getTotalAnimationTime();
int time2 = (time + myAnimation.getTotalAnimationTime() / 2) % myAnimation.getTotalAnimationTime();
Point2D pt = myAnimation.getLocationAtTime(time);
Point2D pt2 = myAnimation.getLocationAtTime(time2);
Dimension size = myAnimation.getSizeAtTime(time);
g2.translate(pt.getX() - size.width / 2, pt.getY() - size.height / 2);
myAnimation.paintAtTime(g2, time);
g2.translate(- (pt.getX() - size.width / 2), - (pt.getY() - size.height / 2));
g2.translate(pt2.getX() - size.width / 2, pt2.getY() - size.height / 2);
myAnimation.paintAtTime(g2, time2);
g2.translate(- (pt2.getX() - size.width / 2), - (pt2.getY() - size.height / 2));
g2.setColor(Color.BLACK);
g2.draw(myPath);
}
};
WindowUtilities.visualize(jp);
AbstractAction action = new AbstractAction() {
public void actionPerformed(ActionEvent ae) {
jp.repaint();
}
};
javax.swing.Timer t = new javax.swing.Timer(30, action);
t.start();
}
}

why is it only painting one of the components?

package puzzle;
import java.awt.Color;
import javax.swing.*;
import java.util.*;
public class Puzzle {
Integer x = 50;
Integer y = 50;
int x2 = 100;
int y2 = 100;
int vnotx = 0;
int vnoty = 0;
float t = 0;
float t2 = 0;
JFrame frame = new JFrame();
Move m = new Move(x, y,Color.GREEN);
Move n = new Move(x,y,Color.ORANGE);
java.util.Timer timer = new java.util.Timer();
java.util.Timer timer2 = new java.util.Timer();
public Puzzle() {
frame.setUndecorated(true);
frame.setSize(400, 400);
frame.add(m);
frame.add(n);
frame.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
formKeyPressed(evt);
}
});
com.sun.awt.AWTUtilities.setWindowOpacity(frame, 1f);
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
rD();
}
}, 0, 20);
timer2.scheduleAtFixedRate(new TimerTask() {
public void run() {
t2+=.01;
x2 =(int) ((Math.cos(t2)+1)*100);
y2 =(int) ((Math.sin(t2)+1)*100);
System.out.println(x2+", "+y2);
}
}, 0, 2);
}
int z = 0;
public void rD() {
z++;
m = new Move(x, y, Color.GREEN);
n = new Move(x2, y2, Color.ORANGE);
frame.add(n);
frame.add(m);
frame.validate();
}
private void formKeyPressed(java.awt.event.KeyEvent evt) {
int id = evt.getID();
int kC = evt.getKeyCode();
if (kC == 39) {
final java.util.Timer right = new java.util.Timer();
right.scheduleAtFixedRate(new TimerTask() {
public void run() {
t += .01;
int x1 = x;
if (x + 51 < 400) {
x = x1 + (int) (10 * t) + (-1 * ((int) (20 * t * t)));
}
if (t > .5) {
t = 0;
right.cancel();
}
}
}, 0, 10);
}
if (kC == 37) {
final java.util.Timer left = new java.util.Timer();
left.scheduleAtFixedRate(new TimerTask() {
public void run() {
t += .01;
int x1 = x;
if (x - 1 >= 0) {
x = x1 + (int) (-10 * t) - (-1 * ((int) (20 * t * t)));
}
if (t > .5) {
t = 0;
left.cancel();
}
}
}, 0, 10);
}
if (kC == 40) {
final java.util.Timer right = new java.util.Timer();
right.scheduleAtFixedRate(new TimerTask() {
public void run() {
t += .01;
int y1 = y;
if (y + 51 < 400) {
y = y1 + (int) (10 * t) + (-1 * ((int) (20 * t * t)));
}
if (t > .5) {
t = 0;
right.cancel();
}
}
}, 0, 10);
}
if (kC == 38) {
final java.util.Timer left = new java.util.Timer();
left.scheduleAtFixedRate(new TimerTask() {
public void run() {
t += .01;
int y1 = y;
if (y-1 >= 0)
{
y = y1 + (int) (-10 * t) - (-1 * ((int) (20 * t * t)));
}
if (t > .5) {
t = 0;
left.cancel();
}
}
}, 0, 10);
}
if (kC == 32) {
}
if (kC == 67) {
}
if (kC == 77) {
}
}
public static void main(String[] args) {
new Puzzle().frame.setVisible(true);
}
}
why is this not adding both instances of the move class. it only adds the last one called. the class paint is below what should i change in order for it paint both instances of move
package puzzle;
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
public class Move extends JPanel{
int x;
int y;
Color kk;
public Move(int x1, int y1, Color k)
{
x=x1;
y=y1;
kk = k;
}
public void paintComponent(Graphics g)
{Graphics2D g2 = (Graphics2D)g;
super.paintComponent(g2);
g2.setColor(kk);
g2.fill(new RoundRectangle2D.Float(x, y, 50, 50,10,10));
g2.drawString(x+", "+y, 200, 200);
}
}
the class move paints a rectangle with the position and color passed from the puzzle class
Are you taking layout managers into consideration? Do you know about JFrame's contentPane using BorderLayout as its default layout manager, and if you add components to this without constants, they are added BorderLayout.CENTER, and only one of these can be visible at a time (the last added).
I think that you might do better disassociating Move from JPanel, yes making it paintable, but making it more of a logical object rather than a gui component and instead of having it extend JPanel, allow a single drawing JPanel to hold one or more Move objects and then draw the Move objects in this JPanel's paintComponent method.
Also, you seem to be using several java.util.Timers in your code, but since it is a Swing application, it would likely be better served by using javax.swing.Timers instead, in fact perhaps just one Swing Timer that functioned as a game loop.
if (kC == 39) {
Don't use magic numbers.
Instead you should be using:
KeyEvent.VK_???

Categories