Volume control in Greenfoot - java

I am trying to create a simple mp3 player in green foot and use buttons to control the volume. I have some code that I think should be working but it isnt. Im not sure what the problem is. I am trying to increase the volume bu one when the up button is pushed and decrease the volume by 1 when the down button is pushed I am fairly new to programming so any help would be great. Thanks!
public class Play extends Actor
{
public GreenfootSound sound = new GreenfootSound("AdventureOfaLifetime.mp3");
private boolean off = true;
int currentVolume = sound.getVolume();
Up volumeUp;
Down volumeDown;
/**
* Act - do whatever the Play wants to do. This method is called whenever
* the 'Act' or 'Run' button gets pressed in the environment.
*/
public void act()
{
if (Greenfoot.mouseClicked(this) && off)
{
setImage("Pause.png");
sound.play();
off = false;
}
else if(Greenfoot.mouseClicked(this) && !off)
{
setImage("Play.png");
sound.pause();
off = true;
}
if(volumeUp.clicked)
{
if(currentVolume < 100)
{
currentVolume = currentVolume + 1;
sound.setVolume(currentVolume);
}
}
if(volumeDown.clicked)
{
if(currentVolume > 0)
{
currentVolume = currentVolume - 1;
sound.setVolume(currentVolume);
}
}
}
public class Down extends Play
{
static boolean clicked = false;
/**
* Act - do whatever the Down wants to do. This method is called whenever
* the 'Act' or 'Run' button gets pressed in the environment.
*/
public void act()
{
if (Greenfoot.mouseClicked(this))
{
clicked = true;
}
else
{
clicked = false;
}
}
public class Up extends Play
{
static boolean clicked = false;
/**
* Act - do whatever the Up wants to do. This method is called whenever
* the 'Act' or 'Run' button gets pressed in the environment.
*/
public void act()
{
if (Greenfoot.mouseClicked(this))
{
clicked = true;
}
else
{
clicked = false;
}
}

I got something to work. I just set currentVolume equal to 50 then changed my if statement to currentVolume += 1;and currentVolume -= 1;. Probably isn't the best solution but at least its working.

Related

How can I get specific fields from an AnimationTimer object?

I've written a simple game using JavaFX for the GUI and AnimationTimer for the game itself, but I've found that any fields that update within the AnimationTimer object can't be found outside of the object. I've managed to continuously record how long a game runs, and the score of that game, but can't find a way to get these values out of the AnimationTimer object so I can add them to my GUI.
I've already tried java.lang.Reflect, but I can't seem to get it to work.
AnimationTimer animations = new AnimationTimer() //creates animations
{
#Override
public void handle(long now)
{
//update frames
if(jump == 0) //moves the player model to the starting position
{
playerY = 160;
}
else if(jump == 1) //moves the player model up (jumping)
{
playerY = 100;
}
if(shout == 1) //makes player immune while "shouting"
{
player.setFill(Color.GREEN);
}
if(shout == 0) //makes player not immune anymore
player.setFill(Color.BLUE);
if(obstacleX == PLAYER_X) //updates the score
{
points += 10;
score.setText("Score: " + String.valueOf(points));
}
if(player.getBoundsInParent().intersects(obstacle.getBoundsInParent())) //detects if the player model touches an obstacles
{
if(obstacle.getEndY() == 0)
{
if(player.getFill() == Color.BLUE)
player.setFill(Color.RED);
}
else if(obstacle.getEndY() == 130)
player.setFill(Color.RED);
}
if(obstacleX > 0) //moves the obstacles' reference point from the right to the left
obstacleX -= 5;
if(obstacleX == 0)
{
obstacleX = 400;
int[] array = new int[]{0, 0, 130};
Random randomNum = new Random();
int i = randomNum.nextInt(array.length);
random = array[i];
obstacle.setEndY(random);
}
//render frames
player.setCenterY(playerY);
obstacle.setStartX(obstacleX); //this and line 110 move the obstacle across the scene
obstacle.setEndX(obstacleX);
try{ //exception handler for outputs
if(player.getFill() == Color.GREEN)
{
digitalOutput6.setDutyCycle(1); //turns on green LED
digitalOutput0.setDutyCycle(0);
}
if(player.getFill() == Color.BLUE)
{
digitalOutput6.setDutyCycle(0); //turns off LEDs
digitalOutput0.setDutyCycle(0);
}
if(player.getFill() == Color.RED) //stops the animation when the player model reacts to touching an obstacle
{
endTime = System.currentTimeMillis() - startTime;
finalScore = score.getText();
this.stop(); //ends game
gameOver = 1;
digitalOutput0.setDutyCycle(1); //turns on red LED
digitalOutput6.setDutyCycle(0);
gameStage.setScene(gameEnd); //establishing scene
gameStage.setTitle("Game Over");
gameStage.show();
}
} //end of try block
catch(PhidgetException e)
{
System.out.println("Phidget Output Error");
}
} //end of animation handle itself
}; //end of animation method
I tried using
long finalTime = animations.getLong(endTime);
and
String endScore = animations.getField(finalScore);
But no luck. Any help appreciated.
AnimationTimer itself doesn't expose any attributes, make a custom class which wraps an AnimationTimer object in it, and save any attributes you want to access.
When you initialize the custom class, initialize the AnimationTimer object and override the function (as what you've done), also updates whatever attributes you want to expose.
I am not familiar with javafx, there might be other better ways, this is the one quick solution I can think of.
Did a quick search, these examples might be helpful:
https://netopyr.com/2012/06/14/using-the-javafx-animationtimer/
https://tbeernot.wordpress.com/2011/11/12/javafx-2-0-bubblemark/
First of all do not use Reflections on Anonymous classes It will work but will cause a lot of ineffeciency and dirty code.
Second of all, you try to acces fields which are in the Methodscope of
handle(long now) not in the Class scope.
AnimationTimer t = new AnimationTimer() {
int fieldInt = 0; // would be accessible
#Override
public void handle(long now) {
//do something
}
};
AnimationTimer t = new AnimationTimer() {
#Override
public void handle(long now) {
int fieldInt = 0; // is not accessible as regular field
//do something
}
};
What you can do is the following:
Use a class that extends a Animationtimer
public class Scheduler extends AnimationTimer{
private int gameEnd = 42;
private String someValue = "hello";
#Override
public void handle(long now) {
gameEnd += 1;
if(gameEnd >= 1000000) {
someValue ="Bye bye";
}
}
public String getSomeValue() {
return someValue;
}
here you can use:
Scheduler s = new Scheduler();
s.start();
//whatever you want to do
System.out.Println(s.getSomeValue());
or when you want to use the Anonymous class approach, you should create a Property that is outside of AnimationTimer and use it. (Wich is a thing that I would prefer, because you can have a changeListener on the Property and recieve a callback when the value is changed)
public void whateverMethod() {
SimpleIntegerProperty gameEndProp = new SimpleIntegerProperty(42);
AnimationTimer t = new AnimationTimer() {
#Override
public void handle(long now) {
gameEndProp.set(gameEndProp.get()+1);
}
};
t.start();
//Do something
System.out.println(gameEndProp.get());
}

Java Robot clicking is going at 70 clicks per second cannot figure out the math / what is going wrong

volatile private boolean mouseDown = false;
private int max = 0;
private int min = 0;
private Robot robot;
public MouseClickListener()
{
try
{
robot = new Robot();
} catch (AWTException e)
{
e.printStackTrace();
}
}
#Override
public void nativeMouseClicked(NativeMouseEvent nativeMouseEvent)
{
}
#Override
public void nativeMousePressed(NativeMouseEvent nativeMouseEvent)
{
if (nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)
{
max = Native.get().getFrame().getCps().getValue() + Native.get().getFrame().getDev().getValue();
min = Native.get().getFrame().getCps().getValue() - Native.get().getFrame().getDev().getValue();
mouseDown = true;
initThread();
}
}
#Override
public void nativeMouseReleased(NativeMouseEvent nativeMouseEvent)
{
if (nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)
{
mouseDown = false;
}
}
Hi there, so basically I'm trying to make an auto clicker which clicks at values to a JSlider (a random value between say 9 and 13, just for example).
So on mouse click the initThread method is called, and the clicks per second is worked out ( a random number between the JSlider value, which is from a diff. class), and then from that, I click and then sleep the thread for 1 / randomNum (in seconds) so that it clicks that many times per second.
For some reason it's clicking at like 200cps and lagging my computer out. Does anyone see any problem with my code?
Thanks.
NEW CODE FOR CLICKER;
public class ClickMethod implements Runnable
{
#Override
public void run()
{
System.out.println("STARTED");
do
{
System.out.println("RUNNING");
Random r = new Random();
int random = r.nextInt((max - min) + 1) + min;
robot.mousePress(BUTTON1_MASK);
robot.mouseRelease(BUTTON1_MASK);
try
{
Thread.sleep(1000 / random);
} catch (InterruptedException e)
{
e.printStackTrace();
}
} while (mouseDown);
}
}
For some reason this only runs once and then isn't called when the mouseDown variable changes.
If this is intended to be clicked by you every so often then it creates numerous threads which all click away
public void nativeMousePressed(NativeMouseEvent nativeMouseEvent)
{
if (nativeMouseEvent.getButton() == NativeMouseEvent.BUTTON1)
{
max = Native.get().getFrame().getCps().getValue() + Native.get().getFrame().getDev().getValue();
min = Native.get().getFrame().getCps().getValue() - Native.get().getFrame().getDev().getValue();
mouseDown = true;
initThread();
}
}
You need to remove initThread() from there and call it once somewhere , e.g., in the constructor.

Pause Android app until button press

I have two methods: go() and stop(), and a for loop looping through these methods 3 times. go() activates automatically when the loop starts and stop() will only activate once a button is pressed 3 times:
private static int buttonPress;
for (int i = 0; i < 3, i++) {
go();
do {} while(pressCount < 4);
stop();
}
Whenever the button the pressed, pressCount is incremented by 1:
public void button(View v) {
pressCount++;
}
The problem is that with this setup, when the do while loop launches, the app freezes and crashes.
Is there any way to fix this while still having the go() activate before stop(), having stop() activate after pressCount is greater than 3, and looping through 3 times?
Thanks
you cannot block the main thread for more than 5 seconds if that happens then an anr (Application not responding) dialog pops up.
You cannot pause main thread, the app freezes.
private int loopCount = 0;
private int pressCount = 0;
public void button(View v) { /* Runs when button is clicked */
if (loopCount < 4){
pressCount++;
if (pressCount == 3){
pressCount = 0;
loopCount++;
stop();
}
}
}
This code runs stop() when the button is pressed three times, but runs that only three times. (After 9 presses nothing happens)
try this
private boolean isStop = true;
private int buttonPressedCount = 0;
private void goOrStop() {
if(isStop) {
go();
isStop = false;
} else {
stopIfCan(); // :)
}
}
private void stopIfCan() {
if(buttonPressedCount >= 3 ) {
buttonPressedCount = 0;
isStop = false;
stop();
}
}
public void button(View v) {
buttonPressedCount++;
}

Javafx - Can Images in a StackPane be offset and if so what am I doing Wrong?

I just have a very basic question, I am wondering what would be the best way to make a stack of cards where each are offset. In the code below I tried to use a StackPane, the problem is however that it doesn't seem to register the offset coordinates.
In the image below you will see that I tried to deal 2 cards to the dealer and to player1 and yes those are two different stacks (Note: I haven't taken the time to position them correctly yet, also the border around the table is temporary). I tried manually loading the cards and I get the same result, it doesn't offset the cards so it appears as though only one card is on the table:
public class PlayerTableCardPane extends Pane {
// Data Fields
ImageView[] cardBack;
private int cardXOffset;
private int cardHeight;
private int cardCount;
// StackPane for cards
StackPane cardStack;
/** Constructor */
public PlayerTableCardPane() {
this(50, 5);
}
/** Constructor for setting custom height */
public PlayerTableCardPane(int cardHeight, int cardXOffset) {
this.cardStack = new StackPane();
this.cardBack = new ImageView[5];
this.cardXOffset = cardXOffset;
this.cardHeight = cardHeight;
this.cardCount = 0;
for (int index = 0; index < 5; index++) {
Image newImage = new Image("image/cardDownSm.png");
ImageView setCardBack = new ImageView();
setCardBack.setImage(newImage);
setCardBack.setVisible(false);
setCardBack.setFitHeight(cardHeight);
setCardBack.setPreserveRatio(true);
setCardBack.setSmooth(true);
// Offset each card
setCardBack.setX(index * cardXOffset);
this.cardBack[index] = setCardBack;
}
this.cardStack.getChildren().addAll(this.cardBack);
getChildren().add(this.cardStack);
}
/** Get cardXOffset */
public int getCardXOffset() {
return this.cardXOffset;
}
/** Set cardXOffset */
public void setCardXOffset(int cardXOffset) {
this.cardXOffset = cardXOffset;
}
/** Get cardCount */
public int getCardCount() {
return this.cardCount;
}
/** Set cardCount */
public void setCardCount(int cardCount) {
this.cardCount = cardCount;
}
/** Load cards into StackPane */
public void loadCard() {
if (cardCount == 0) {
cardBack[0].setVisible(true);
} else if (cardCount == 1) {
cardBack[1].setVisible(true);
} else if (cardCount == 2) {
cardBack[2].setVisible(true);
} else if (cardCount == 3) {
cardBack[3].setVisible(true);
} else if (cardCount == 4) {
cardBack[4].setVisible(true);
}
this.cardCount++;
}
/** Hide last card() */
public void hideLastCard() {
if (cardCount == 4) {
cardBack[4].setVisible(false);
} else if (cardCount == 3) {
cardBack[3].setVisible(false);
} else if (cardCount == 2) {
cardBack[2].setVisible(false);
} else if (cardCount == 1) {
cardBack[1].setVisible(false);
} else if (cardCount == 0) {
cardBack[0].setVisible(false);
}
this.cardCount--;
}
/** Replace card with FaceUp Image */
public void setCardImg(ImageView card, int cardPos) {
cardBack[cardPos].setImage(card.getImage());
}
}
StackPane lays out its child Nodes according just to the alignment property of the StackPane itself: the layoutX and layoutY of the Node are basically ignored. The default value of the alignment property is CENTER. Your best solution here is just to use a Pane instead of a StackPane.
You could also potentially solve this by setting the translateX property of the images to be placed in the StackPane. However, note that such transforms are not included in layout calculations, so you introduce the possibility of pushing the cards out of the visible bounds of the StackPane.

Java slideshow image delay using paintComponent

I am putting together a slideshow program that will measure a user's time spent on each slide. The slideshow goes through several different magic tricks. Each trick is shown twice. Interim images are shown between the repetition. Transition images are shown between each trick.
On the first repetition of a trick the JPanel color flashes on the screen after a click before the next image is shown. This doesn't happen during the second repetition of the same trick. It's possible that the image is taking too long to load.
Is there an easy way to pre-load the images so that there isn't a delay the first time through?
NOTE: Original code deleted.
EDIT 1/10/2013: This code now works on slower machines. trashgod's second addendum helped the most. The mouseClick control structure periodically asks SwingWorker classes to load 40 images or less of the current trick while also setting the used images to null. I have simplified my code down for this to just two Image[]s and added a main method so it stands alone. Images are still required to run though. This is now pretty bare bones code, and if you're trying to make a slideshow with a lot of images I think it would be a good place to start.
NOTE: I think I figured out how to properly implement SwingWorker while still using multiple Image[]s. trashgod and kleopatra is this implementation in-line with what you were suggesting? I didn't end up using publish and process since I couldn't figure out how to get that to work appropriately with an indexed array, but because the StringWorker doesn't load all images in the array (only 40), and the code calls StringWorker every 20 images, there should be a pretty good buffer.
EDIT 1/10/2013 Changed out MouseListener by instead extending MouseAdapter on my Mouse class. Also fixed my paintComponent method to include a call to super.paintComponent(g).
Added publish/process methods to my SwingWorker class ImageWorker. Added a wrapper class, ArrayWrapper to allow passing imageArray[i] and its corresponding index int i with publish to process.
package slideshow3;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.util.List;
public class SlideShow3 extends JFrame
{
//screenImage will be replaced with each new slide
private Image screenImage;
private int width;
private int height;
//Create panel for displaying images using paintComponent()
private SlideShow3.PaintPanel mainImagePanel;
//Used for keybinding
private Action escapeAction;
//Image array variables for each trick
private Image[] handCuffs; //h
private Image[] cups; //c
//Used to step through the trick arrays one image at a time
private int h = 0;
private int c = 0;
//Used by timeStamp() for documenting time per slide
private long time0 = 0;
private long time1;
public SlideShow3()
{
super();
//Create instance of each Image array
handCuffs = new Image[50];
cups = new Image[176];
//start(handCuffsString);
start("handCuffs");
try
{
screenImage = ImageIO.read(new File("images/begin1.jpg"));
}
catch (IOException nm)
{
System.out.println("begin");
System.out.println(nm.getMessage());
System.exit(0);
}
/******************************************
* Removes window framing. The next line sets fullscreen mode.
* Once fullscreen is set width and height are determined for the window
******************************************/
this.setUndecorated(true);
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this);
width = this.getWidth();
height = this.getHeight();
//Mouse click binding to slide advance control structure
addMouseListener(new Mouse());
//Create panel so that I can use key binding which requires JComponent
mainImagePanel = new PaintPanel();
add(mainImagePanel);
/******************************************
* Key Binding
* ESC will exit the slideshow
******************************************/
// Key bound AbstractAction items
escapeAction = new EscapeAction();
// Gets the mainImagePanel InputMap and pairs the key to the action
mainImagePanel.getInputMap().put(KeyStroke.getKeyStroke("ESCAPE"), "doEscapeAction");
// This line pairs the AbstractAction enterAction to the action "doEnterAction"
mainImagePanel.getActionMap().put("doEscapeAction", escapeAction);
/******************************************
* End Key Binding
******************************************/
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run()
{
SlideShow3 show = new SlideShow3();
show.setVisible(true);
}
});
}
//This method executes a specific SwingWorker class to preload images
public void start(String e)
{
if(e.equals("handCuffs"))
{
new ImageWorker(handCuffs.length, h, e).execute();
}
else if(e.equals("cups"))
{
new ImageWorker(cups.length, c, e).execute();
}
}
//Stretches and displays images in fullscreen window
private class PaintPanel extends JPanel
{
#Override
public void paintComponent(Graphics g)
{
if(screenImage != null)
{
super.paintComponent(g);
g.drawImage(screenImage, 0, 0, width, height, this);
}
}
}
/******************************************
* The following SwingWorker class Pre-loads all necessary images.
******************************************/
private class ArrayWrapper
{
private int i;
private Image image;
public ArrayWrapper(Image image, int i)
{
this.i = i;
this.image = image;
}
public int getIndex()
{
return i;
}
public Image getImage()
{
return image;
}
}
private class ImageWorker extends SwingWorker<Image[], ArrayWrapper>
{
private int currentPosition;
private int arraySize;
private String trickName;
private Image[] imageArray;
public ImageWorker(int arraySize, int currentPosition, String trick)
{
super();
this.currentPosition = currentPosition;
this.arraySize = arraySize;
this.trickName = trick;
}
#Override
public Image[] doInBackground()
{
imageArray = new Image[arraySize];
for(int i = currentPosition; i < currentPosition+40 && i < arraySize; i++)
{
try
{
imageArray[i] = ImageIO.read(new File("images/" + trickName + (i+1) + ".jpg"));
ArrayWrapper wrapArray = new ArrayWrapper(imageArray[i], i);
publish(wrapArray);
}
catch (IOException e)
{
System.out.println(trickName);
System.out.println(e.getMessage());
System.exit(0);
}
}
return imageArray;
}
#Override
public void process(List<ArrayWrapper> chunks)
{
for(ArrayWrapper element: chunks)
{
if(trickName.equals("handCuffs"))
{
handCuffs[element.getIndex()] = element.getImage();
}
else if(trickName.equals("cups"))
{
cups[element.getIndex()] = element.getImage();
}
}
}
#Override
public void done()
{
try
{
if(trickName.equals("handCuffs"))
{
handCuffs = get();
}
else if(trickName.equals("cups"))
{
cups = get();
}
}
catch(InterruptedException ignore){}
catch(java.util.concurrent.ExecutionException e)
{
String why = null;
Throwable cause = e.getCause();
if(cause != null)
{
why = cause.getMessage();
}
else
{
why = e.getMessage();
}
System.err.println("Error retrieving file: " + why);
}
}
}
/******************************************
* End SwingWorker Pre-Loading Classes
******************************************/
//Prints out time spent on each slide
public void timeStamp()
{
time1 = System.currentTimeMillis();
if(time0 != 0)
{
System.out.println(time1 - time0);
}
time0 = System.currentTimeMillis();
}
/******************************************
* User Input Classes for Key Binding Actions and Mouse Click Actions
******************************************/
private class EscapeAction extends AbstractAction
{
#Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
public class Mouse extends MouseAdapter
{
#Override
public void mouseClicked(MouseEvent e)
{
if(!(h<handCuffs.length) && !(c<cups.length))
{
timeStamp();
System.exit(0);
}
else if(h<handCuffs.length)
{
timeStamp();
screenImage = handCuffs[h];
repaint();
System.out.print("handCuffs[" + (h+1) + "]\t");
h++;
//purge used slides and refresh slide buffer
if(h == 20 || h == 40)
{
for(int i = 0; i < h; i++)
{
handCuffs[i] = null;
}
start("handCuffs");
}
if(h == 45)
{
start("cups");
}
}
else if(c<cups.length)
{
timeStamp();
screenImage = cups[c];
repaint();
System.out.print("cups[" + (c+1) + "]\t");
c++;
//purge used slides and refresh slide buffer
if(c == 20 || c == 40 || c == 60 || c == 80 || c == 100 || c == 120 || c == 140 || c == 160)
{
for(int i = 0; i < c; i++)
{
cups[i] = null;
}
start("cups");
}
}
}
}
/******************************************
* End User Input Classes for Key Binding Actions and Mouse Click Actions
******************************************/
}
This example uses a List<ImageIcon> as a cache of images returned by getImage(). Using getResource(), the delay is imperceptible. The next and previous buttons are bound to the Space key by default.
Addendum: You can control navigation by conditioning a button's setEnabled() state using an instance of javax.swing.Timer, for example.
Addendum: Your second example waits until the mouse is clicked to begin reading an image, an indeterminate process that may return a copy immediately or may not complete until after repaint(). Instead, begin reading the images in the background using ImageIO.read(), as shown here. You can process() your List<Image> and show progress, as seen here. The SwingWorker can be launched from the initial thread, running while you subsequently build your GUI on the EDT. You can display the first image as soon as it is processed.

Categories

Resources