Simple animation through use of paintComponent - animation

I'm trying to make a small square move across the top of the panel. I'm not worried about the seamlessness of the animation or flicker or anything like that. It appears that in the while-loop, repaint() isn't repeatedly calling the paintComponent. Thoughts?
public class NodeMove extends JFrame {
boolean running = true;
public NodeMove() {
widgetNode panel = new widgetNode();
add(panel);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
setVisible(true);
Runnable node = new widgetNode();
Thread thread1 = new Thread(node);
thread1.start();
}
class widgetNode extends JPanel implements Runnable {
private static final long serialVersionUID = 1L;
private int x = 30;
private int y = 30;
public widgetNode() {
}
public void run(){
while(running){
nodeUpdate();
repaint();
try {
Thread.sleep(500);
} catch (InterruptedException e) {}
}
}
public void nodeUpdate(){
x += 4;
}
protected void paintComponent(Graphics g) {
super.paintComponents(g);
g.drawRect(x, y, 30, 30);
}
}
public static void main(String[] args) {
NodeMove frame = new NodeMove();
for(int i = 0; i < 50; i++){
frame.repaint();
}
}
}

Related

how create a simple object animation in processing

QUESTION
I'm trying to create a simple object "car" animation in Processing.
My code is:
Car car;
void setup(){
size(800, 600);
background(#818B95);
frameRate(30);
car = new Car(10,10);
}
void draw(){
//refresh background
background(#818B95);
print("-");
car.drawCar();
}
void mouseClicked() {
car.run();
}
public class Car implements Runnable{
private int pos_x, pos_y;
public Car(int pos_x, int pos_y){
this.pos_x = pos_x;
this.pos_y = pos_y;
}
public void drawCar(){
rect(pos_x,pos_y,10,10);
}
public void run(){
while(true){
pos_x += 10;
print("*");
delay(200);
}
}
}
I'm expecting to see the car/rectangle move right when I click the mouse button, but nothing happens.
I've added the two print in order to see if the draw method and my car.run are executed in parallel showing some * and - printed alternately.
What I see is a sequence of - until I click and then only * are printed.
Is it possible that starting a new object thread will stop the main draw cycle?
SOLUTION
This is just a variant of the suggested solution (by Mady Daby) without using threads.
Car car;
void setup(){
size(800, 600);
background(#818B95);
frameRate(30);
car = new Car(10,10);
}
void draw(){
//refresh background
background(#818B95);
print("-");
car.drawCar();
}
void mouseClicked() {
car.moving = true;
}
public class Car{
private int pos_x, pos_y;
boolean moving = false;
public Car(int pos_x, int pos_y){
this.pos_x = pos_x;
this.pos_y = pos_y;
}
public void drawCar(){
rect(pos_x,pos_y,10,10);
//animation
if(moving){
pos_x += 10;
print("*");
}
}
}
You could make the car move right by just introducing a boolean variable to track whether the car is supposed to be moving right moving and then increment pos_x if moving is true. You can also use the clicks to toggle between moving and not moving.
Car car;
void setup() {
size(800, 600);
background(#818B95);
frameRate(30);
car = new Car(10, 10);
}
void draw() {
//refresh background
background(#818B95);
print("-");
car.drawCar();
}
void mouseClicked() {
car.toggleMoving();
}
public class Car implements Runnable {
private int pos_x, pos_y;
private boolean moving = false;
public Car(int pos_x, int pos_y) {
this.pos_x = pos_x;
this.pos_y = pos_y;
}
public void toggleMoving() {
moving = !moving;
}
public void drawCar() {
if (moving) {
this.run();
}
rect(pos_x, pos_y, 10, 10);
}
public void run() {
pos_x += 10;
print("*");
delay(200);
}
}

VLCJ Equalizer work not correctly

i use VLCJ 3.0.1, Plattform 3.5.2 and JNA 3.5.2 under Ubuntu 14.10.
I would like to create a simple Vlcj Mediaplayer with equalizer.
The problem is, i can play the *.mp3, but when i enable the equalizer and change the gain from any band, i can hear that gain from the band up to max high. I couldn't change it to lower gain. No effect from the Slider. Only when i change the gain to max or min, the effekt is off.
Here is the Code only for testing:
FesterTest.java
public static void main(String[] args) {
Canvas m_surface;
EmbeddedMediaPlayer m_mediaPlayer;
Equalizer m_equalizer;
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
m_surface = new Canvas();
m_surface.setBackground(Color.black);
m_surface.setBounds(0, 0, 1024, 600);
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory();
m_mediaPlayer = mediaPlayerFactory.newEmbeddedMediaPlayer();
m_mediaPlayer.setVideoSurface(mediaPlayerFactory.newVideoSurface(m_surface));
System.out.println(mediaPlayerFactory.isEqualizerAvailable());
m_equalizer = mediaPlayerFactory.newEqualizer();
System.out.println(LibVlcConst.MAX_GAIN);
System.out.println(LibVlcConst.MIN_GAIN);
System.out.println(LibVlcConst.MIN_VOLUME);
System.out.println(LibVlcConst.MAX_VOLUME);
JFrame f = new JFrame();
JPanel p = new JPanel();
f.add(p);
p.add(m_surface);
f.setVisible(true);
m_mediaPlayer.playMedia("/home/patrick/Dev/content/068-becky_g_-_shower.mp3");
EqualizerFrame frame = new EqualizerFrame(mediaPlayerFactory.getEqualizerBandFrequencies(), mediaPlayerFactory.getEqualizerPresetNames(), mediaPlayerFactory, m_mediaPlayer, m_equalizer);
frame.pack();
frame.setVisible(true);
}
and EqualizerFrame:
public class EqualizerFrame extends JFrame implements ChangeListener, ActionListener, ItemListener {
private static final String BAND_INDEX_PROPERTY = "equalizerBandIndex";
private final String dbFormat = "%.2fdB";
private final MediaPlayerFactory mediaPlayerFactory;
private final MediaPlayer mediaPlayer;
private final Equalizer equalizer;
private final SliderControl preampControl;
private final SliderControl[] bandControls;
private final JToggleButton enableButton;
private final JComboBox presetComboBox;
#SuppressWarnings({ "unchecked", "rawtypes" })
public EqualizerFrame(List<Float> list, List<String> presets, MediaPlayerFactory mediaPlayerFactory, MediaPlayer mediaPlayer, Equalizer equalizer) {
super("Equalizer");
this.mediaPlayerFactory = mediaPlayerFactory;
this.mediaPlayer = mediaPlayer;
this.equalizer = equalizer;
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
contentPane.setLayout(new BorderLayout(0, 4));
JPanel bandsPane = new JPanel();
bandsPane.setLayout(new GridLayout(1, 1 + list.size(), 2, 0));
preampControl = new SliderControl("Preamp", (int)LibVlcConst.MIN_GAIN, (int)LibVlcConst.MAX_GAIN, 0, dbFormat);
preampControl.getSlider().addChangeListener(this);
bandsPane.add(preampControl);
bandControls = new SliderControl[list.size()];
for(int i = 0; i < list.size(); i++) {
bandControls[i] = new SliderControl(formatFrequency(list.get(i)), (int)LibVlcConst.MIN_GAIN, (int)LibVlcConst.MAX_GAIN, 0, dbFormat);
bandControls[i].getSlider().putClientProperty(BAND_INDEX_PROPERTY, i);
bandControls[i].getSlider().addChangeListener(this);
bandsPane.add(bandControls[i]);
}
contentPane.add(bandsPane, BorderLayout.CENTER);
JPanel controlsPane = new JPanel();
controlsPane.setLayout(new BoxLayout(controlsPane, BoxLayout.X_AXIS));
enableButton = new JToggleButton("Enable");
enableButton.setMnemonic('e');
controlsPane.add(enableButton);
controlsPane.add(Box.createHorizontalGlue());
JLabel presetLabel = new JLabel("Preset:");
presetLabel.setDisplayedMnemonic('p');
controlsPane.add(presetLabel);
presetComboBox = new JComboBox();
presetLabel.setLabelFor(presetComboBox);
DefaultComboBoxModel presetModel = (DefaultComboBoxModel)presetComboBox.getModel();
presetModel.addElement(null);
for(String presetName : presets) {
presetModel.addElement(presetName);
}
presetComboBox.setRenderer(new DefaultListCellRenderer() {
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if(value != null) {
label.setText(String.valueOf(value));
}
else {
label.setText("--Select--");
}
return label;
}
});
controlsPane.add(presetComboBox);
contentPane.add(controlsPane, BorderLayout.SOUTH);
setContentPane(contentPane);
enableButton.addActionListener(this);
presetComboBox.addItemListener(this);
}
private String formatFrequency(float hz) {
if(hz < 1000.0f) {
return String.format("%.0f Hz", hz);
}
else {
return String.format("%.0f kHz", hz / 1000f);
}
}
#Override
public final void actionPerformed(ActionEvent e) {
boolean enable = enableButton.isSelected();
if(!enable) {
presetComboBox.setSelectedItem(null);
}
mediaPlayer.setEqualizer(enable ? equalizer : null);
}
#Override
public void stateChanged(ChangeEvent e) {
if(e.getSource() instanceof JSlider) {
JSlider slider = (JSlider)e.getSource();
Integer index = (Integer)slider.getClientProperty(BAND_INDEX_PROPERTY);
int value = slider.getValue();
// Band...
if(index != null) {
equalizer.setAmp(index, (value / 100f));
}
// Preamp...
else {
equalizer.setPreamp(value / 100f);
}
if(!applyingPreset) {
presetComboBox.setSelectedItem(null);
}
}
}
boolean applyingPreset;
#Override
public final void itemStateChanged(ItemEvent e) {
String presetName = (String)presetComboBox.getSelectedItem();
if(e.getStateChange() == ItemEvent.SELECTED) {
if(presetName != null) {
Equalizer presetEqualizer = mediaPlayerFactory.newEqualizer(presetName);
if(presetEqualizer != null) {
applyingPreset = true;
preampControl.getSlider().setValue((int)(presetEqualizer.getPreamp() * 100f)); // FIXME
float[] amps = presetEqualizer.getAmps();
for(int i = 0; i < amps.length; i++) {
bandControls[i].getSlider().setValue((int)(amps[i] * 100f));
}
applyingPreset = false;
}
}
}
}
}
I don't know what can i do an hope anybody can help me!!!!
Thanks
Patrick

call method from a method within the same class

I have a platformer class that creates a window and spawns platforms and a "character". It uses another class platform to make platforms. The character is supposed to jump up and land on the platforms. I use the getBounds and getTopY functions for collision detection but they only work for the first platform. How can i get them to work for multiple platforms?
public class Platformer extends JPanel {
Platform platform = new Platform(this);
Character character = new Character(this);
public Platformer() {
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
character.keyTyped(e);
}
#Override
public void keyReleased(KeyEvent e) {
character.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
character.keyPressed(e);
}
});
setFocusable(true);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
platform.Location(150,200);
platform.paint(g2d);
platform.Location(200,120);
platform.paint(g2d);
character.paint(g2d);
}
private void move(){
character.move();
}
public static void main(String args[]){
JFrame frame = new JFrame("Mini Tennis");
//create new game
Platformer platformer = new Platformer();
//add game
frame.add(platformer);
//size
frame.setSize(400, 400);
frame.setVisible(true);
//set close condition
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
platformer.move();
platformer.repaint();
try {
Thread.sleep(10);//sleep for 10 sec
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
public class Platform {
private static final int Height = 10;
private static final int Width = 60;
int x;
int Y;
private Platformer platformer;
public Platform(Platformer platformer) {
this.platformer = platformer;
}
public void Location(int xin, int yin) {
x = xin;
Y = yin;
}
public void paint(Graphics2D g) {
g.fillRect(x, Y, Width, Height);
}
public Rectangle getBounds() {
return new Rectangle(x, Y, Width, Height);
}
public int getTopPlat() {
return Y;
}
}
Actually you have only one platform. And you draw this platform twice in different places (paint function in Platformer):
platform.Location(150,200);
platform.paint(g2d);
platform.Location(200,120);
platform.paint(g2d);
Therefore I suppose you handle only one platform (with coordinates 200 and 120). You must keep all of your platforms and handle each of them separately.

JUnit testing GUI class

I've looked over the stackoverflow and the internet and I couldn't find a clear answer that helped me.
I have an assignment and it includes the following class, which is a GUI. I have Junit tested the other classes but for this I didn't know how.
import java.awt.*;
public class CruiseDisplay extends Canvas {
private int recorded = 0; //recorded speed
private boolean cruiseOn = false; //cruise control state
private final static int botY = 200;
private Font small = new Font("Helvetica",Font.BOLD,14);
private Font big = new Font("Helvetica",Font.BOLD,18);
public CruiseDisplay() {
super();
setSize(150,260);
}
Image offscreen;
Dimension offscreensize;
Graphics offgraphics;
public void backdrop() {
Dimension d = getSize();
if ((offscreen == null) || (d.width != offscreensize.width)
|| (d.height != offscreensize.height)) {
offscreen = createImage(d.width, d.height);
offscreensize = d;
offgraphics = offscreen.getGraphics();
offgraphics.setFont(small);
}
offgraphics.setColor(Color.black);
offgraphics.fillRect(0, 0, getSize().width, getSize().height);
offgraphics.setColor(Color.white);
offgraphics.drawRect(5,10,getSize().width-15,getSize().height-40);
offgraphics.setColor(Color.blue);
offgraphics.fillRect(6,11,getSize().width-17,getSize().height-42);
}
public void paint(Graphics g) {
update(g);
}
public void update(Graphics g) {
backdrop();
// display recorded speed
offgraphics.setColor(Color.white);
offgraphics.setFont(big);
offgraphics.drawString("Cruise Control",10,35);
offgraphics.setFont(small);
drawRecorded(offgraphics,20,80,recorded);
if (cruiseOn)
offgraphics.drawString("Enabled",20,botY+15);
else
offgraphics.drawString("Disabled",20,botY+15);
if (cruiseOn)
offgraphics.setColor(Color.green);
else
offgraphics.setColor(Color.red);
offgraphics.fillArc(90,botY,20,20,0,360);
g.drawImage(offscreen, 0, 0, null);
}
public void drawRecorded(Graphics g, int x, int y, int speed) {
g.drawString("Cruise Speed",x,y+10);
g.drawRect(x+20,y+20,50,20);
g.setFont(big);
g.drawString(String.valueOf(speed+20),x+30,y+37);
g.setFont(small);
}
public void enabled() {
cruiseOn = true;
repaint();
}
public void disabled() {
cruiseOn = false;
repaint();
}
public void record(int speed) {
recorded=speed;
repaint();
}
}
Can somebody help me please?

assigning a value to an image

So I am trying to create a real simple dice game...more like a dice roller game and I have encountered a problem for which I have yet to find an answer. So obviously I have 6 images for the die faces(1-6), but what I am missing somewhere is how to basically assign values to these images when the "dice are rolled". So that when I begin to implement some game logic I can compare what the numbers of the die faces would be. Here is what I have so far, and as usual any assistance would be much appreciated.
public class CrapsGameActivity extends CrapsActivity {
private final int rollAnimations = 50;
private final int delayTime = 15;
private Resources res;
private final int[] diceImages = new int[]{R.drawable.die1, R.drawable.die2,
R.drawable.die3, R.drawable.die4, R.drawable.die5,R.drawable.die6};
private Drawable dice[] = new Drawable[6];
private final Random randomGen = new Random();
private int diceSum;
private int roll[] = new int[] {6,6};
private ImageView die1;
private TextView die1_Total;
private int die1_number;
private ImageView die2;
private TextView die2_Total;
private TextView diceTotal;
private LinearLayout diceContainer;
private Handler animationHandler;
private long lastUpdate = -1;
private float x, y, z;
private float last_x, last_y, last_z;
private boolean paused = false;
private static final int UPDATE_DELAY = 50;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
paused = false;
super.onCreate(savedInstanceState);
setContentView(R.layout.game);
setTitle(getString(R.string.app_name));
res = getResources();
for (int i = 0; i<6; i++){
dice[i] = res.getDrawable(diceImages[i]);
}
diceContainer = (LinearLayout) findViewById(R.id.diceContainer);
diceContainer.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
try{
rollDice();
die1_Total.setText("" + roll[0]);
die2_Total.setText("" + roll[1]);
diceTotal.setText(""+ diceSum);
}catch(Exception e) {};
}//end of onClick
});//end of onClick listener
die1 = (ImageView) findViewById(R.id.die1);
die1_Total = (TextView) findViewById(R.id.TV_die1);
die2 = (ImageView) findViewById(R.id.die2);
die2_Total = (TextView) findViewById(R.id.TV_die2);
diceTotal = (TextView) findViewById(R.id.TV_diceTotal);
animationHandler = new Handler(){
public void handleMessage(Message msg){
die1.setImageDrawable(dice[roll[0]]);
die2.setImageDrawable(dice[roll[1]]);
}//end of handle message
};//end of Handler
}
private void rollDice() {
if(paused) return;
new Thread(new Runnable(){
#Override
public void run(){
for(int i = 0; i < rollAnimations; i++){
doRoll();
}//end of for statement
}//end of run()
}).start();//end of thread
}//end of rollDice()
private void doRoll(){//only does a single roll
roll[0] = randomGen.nextInt(6);
roll[1] = randomGen.nextInt(6);
diceSum = roll[0] + roll[1] + 2;
synchronized(getLayoutInflater()){
animationHandler.sendEmptyMessage(0);
}
try{//delay for smooth animations
Thread.sleep(delayTime);
}catch(final InterruptedException e){
e.printStackTrace();
}
}//end of doRoll()
public void onResume(){
super.onResume();
paused = false;
}//end of onResume()
public void onPause(){
super.onPause();
paused = true;
}//end of onPause()
}//end of activity
I may not be doing it properly but the code (below). When I use this to see the numbers on the emulator, they are random and dont correspond to the face values of the dice. So like if I wanted to total the face values of the dice (just ran it again now) 0 is for 6 face, and 2 is for the 3 face, which should give me a total dice face of 9, but I am getting 2
public void onClick(View v) {
try{
rollDice();
die1_Total.setText("" + roll[0]);
die2_Total.setText("" + roll[1]);
diceTotal.setText(""+ diceSum);
}catch(Exception e) {};
roll[0] = randomGen.nextInt(6);
roll[1] = randomGen.nextInt(6);
There are your values. You don't want the image to contain the data (or at least, I wouldn't bother). Instead, you render the images/animations based on these values, and can then work with those values directly later.
If you wanted to store the values with the images, you could always make an object (GameDie) and store the images and current value in there.

Resources