Here's my code that, upon a click of the "menu" button, slides 'menubtm' in or out of view. Is there a way to make it pause for a few milliseconds at every loop, so that it would be viable, how the menubtm moves?
Thanks!
#Override
public boolean onKeyDown(int keycode, KeyEvent event ) {
if(keycode == KeyEvent.KEYCODE_MENU){
if ( menuBtmVisable == true )
{
menuBtmVisable = false;
int xnow = menuBtmTopLimit;
while (xnow<menuBtmTopLimit+120)
{
xnow+=1;
AbsoluteLayout.LayoutParams lp = new AbsoluteLayout.LayoutParams(480, 120, 0, xnow);
menubtm.setLayoutParams(lp);
}
}
else
{
menuBtmVisable = true;
int xnow = menuBtmTopLimit+120;
while (xnow>menuBtmTopLimit)
{
xnow-=1;
AbsoluteLayout.LayoutParams lp = new AbsoluteLayout.LayoutParams(480, 120, 0, xnow);
menubtm.setLayoutParams(lp);
}
}
}
return super.onKeyDown(keycode,event);
}
EDIT:
Thanks to your advice, I did it with animations.
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromYDelta="0"
android:toYDelta="120"
android:duration="500"
/>
This animation has to make the menu slide 120 px down... it does so ok, but then springs back into the old place. Is there a way to make it stay in the new location?
EDIT2 : got it!
android:fillEnabled="true"
android:fillAfter="true"
Instead of hacking it yourself, use Android Animations, which is designed exactly for this sort of thing. It will be much more stable and probably look much better in the end.
To answer the title: Thread.sleep will make a thread sleep.
That said, you probably don't want to do that here. If I'm understanding your snippet, onKeyDown is being called from the UI thread. You don't want to delay the UI thread either by sleeping or by doing processing that will take a while. Instead you should start an animation and return as fast as you can. See View Animation and Property Animation in the Android Dev Guide for two ways of doing animation. (Note that the latter requires 3.x or higher.)
Related
I am making a game and I would like to play an intro picture for 3 seconds and then call the methods to start the game. I have tried using Thread.sleep but I know thats probably not a great way and it didnt work. Anyone know a good way to do this?
Here is my code:
ImageView intro = new ImageView(new Image("/Resources/Intro.png"));
root.getChildren().add(intro);
if (startGame) {
InitializeGame.InitGame();
InitializeGame.StartGame();
}
}
Thanks!
Use a PauseTransition. It's not clear from your code what parts you want to execute after the pause, but something like:
ImageView intro = new ImageView(new Image("/Resources/Intro.png"));
root.getChildren().add(intro);
PauseTransition pause = new PauseTransition(Duration.seconds(3));
pause.setOnFinished(e -> {
InitializeGame.InitGame();
InitializeGame.StartGame();
});
pause.play();
I'm creating a game like flappy bird where the bird flaps his wings only when the screen is touched, but I'm having a problem activating the animation when the screen is touched.
batch.draw(animation.getKeyFrame(myTimeState, false), x, y); //the myTimeState is 0 to render the 1st frame only.
Then when the screen is touched I do this:
//myTimeStep is just basically a controllable timeState for the animation only
if(Gdx.input.justTouched){
myTimeState = timeState;
}else if(Gdx.input.justTouched == false && animation.isAnimationFinished(timeState)){
myTimeState = 0;
}
I don't think the animation is able to play all the frames because myTimeStep become 0 immediately after finishing to touch the screen. Also I don't think this is the right way of doing it, if you guys have better ideas or solution please help. Thanks in advance.
There are probably several ways to achieve this. You'll need to increment your timeState, of course, and also it depends how long your animation is and if you want it to loop.
If you've created your animation to play only once, and then stop (until the screen is touched again), you could simply set your myTimeState to 0 when the screen is touched, and then increment it every frame. The animation will run through and then "stop" on its own when it reaches the end (as you said no loop). The next time someone touches the screen, your myTimeState is set back to 0 and the animation starts again.
Firstly, you have to ensure your animation's playmode is set to Animation.PlayMode.NORMAL. It's a default setting, but if you set it somewhere to LOOPED, nothing would work as expected.
Secondly, I wouldn't use Input.justTouched() in this case. Instead, a listener in your input processor would be a great fit. Here's an example with Stage. If you have no idea what input processor is, here's tutorial on event handling and class documentation.
stage.addListener(new ClickListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if(button == Input.Buttons.LEFT) {
timeState = 0;
}
return super.touchDown(event, x, y, pointer, button);
}
});
You can pick what's going to be displayed (animation's keyframe or sprite) based on result of animation.isAnimationFinished()
if(animation.isAnimationFinished(timeState)) {
//draw some sprite
} else {
//draw animation keyframe
}
I haven't checked it but there's a possibility, that this could lead to the last frame being cut out, because as soon as it gets displayed, animation.isAnimationFinished() will return true. I may be wrong, so you'll have to check it. If it becomes an issue, you can add your sprite as the last frame of your animation. When animation ends, it frezzes on the last frame, which would be your static sprite.
In both cases you'll get your animation played at the beginning of game because timeStep equal to 0. I see 2 solutions, I advise you to take the second:
Set timeStep to a large number, that is for sure larger than your animation's duration. Animation.isAnimationFinished() will then return true.
Introduce boolean variable isAnimationPlayed that:
is initialized with false,
gets set to true in your click listener,
gets set to false during isAnimationFinished(), which is called each frame only when isAnimationPlayed is true,
is used in draw() method to determine what to display.
You could just set your timeState to the duration of the animation.
I'm a beginner in Java programming and have come across an issue (probably an easy one to solve).
I am experimenting with Java GUI and wish to create a window in which the colours of an array are cycled through until there are no more colours. I believe I can do this using a for loop and cycling through the array, however I do not know how to loop through the background colour.
Any help and explanation would be appreciated.
public void flashColor() {
Color [] color = { Color.red,Color.orange,Color.green };
int i = 0;
for(i=0;i<color.length;i--){
getContentPane().setBackground(Color(i));
}
}
This line tells me:
getContentPane().setBackground(Color(i));
that yours appears to be a Swing GUI (a key bit of information that you left out of your question!), and so you need to take Swing threading into consideration. Your current code will in fact loop through all the colors, but it will do so immediately, and on the Swing thread so that the GUI will have no way to paint any of the colors other than the last one. The solution: use a Swing Timer and not a for loop. Inside the timer advance an index int variable and use it to show the color.
Something like:
getContentPane().setBackground(colorArray[0]);
int delay = 1000; // for 1 second
Timer myTimer = new Timer(delay, new ActionListener() {
int index = 0;
public void actionPerformed(ActionEvent e) {
index++;
if (index >= colorArray.length) {
((Timer)e.getSource()).stop(); // stop the timer
} else {
getContentPane().setBackground(colorArray[index]);
}
}
});
myTimer.start();
The code has not been tested, and you'll want to read the Swing Timer tutorial for the details.
Note the key here is that yes you need to loop, and to pause (so that the color can be seen) but you need to do your looping and pausing in a thread thread is off of the Swing event dispatch thread (or EDT). Yes you could do this using a SwingWorker, but that is a way more difficult way to do this. It is far easier to use a Swing Timer to do this for you. Note that it uses a background thread invisibly for you.
I'm trying to create a loop using Java Swing Timer to constantly cycle through a set of images (i1, i2, i3....in where n is total number of images).
Each of the images is exactly the same size and must be displayed on a Label (say, l1).
There must be a delay of ten seconds between each image being displayed.
Any idea how I can go about this without using the Java TumbleItem applet> It's seems much too complicated for a simple implementation such as mine. (Displaying special deals posters on an online storefront application for school).
I am open to this being achieved in any other way.
Help would be greatly appreciated. Thanks in advance!
I'm trying to create a loop using Java Swing Timer to constantly cycle through a set of images
When you use a Timer you don't use a loop. When the Timer fires you just change the image. So somewhere you would need to keep a List of the images to display and an index of the currently displayed image.
Any idea how I can go about this without using the Java TumbleItem applet> It's seems much too complicated for a simple implementation such as mine
How is it complicated? It displays a series of images, which is close to what you want.
Yes, there is some extra code that loads the images and doesn't start the animation until all the images are loaded. So you could easily simplify the code by not worry about that. Also, there is code that does animation from from left-to-right and then right-to-left. You also don't need that part of the code. Also, there is code that configures the animation speed. Again you can hard code that.
So if you start with that example and then simplify the code you will have a simple solution. Give it a try and then post your code when you encounter a problem.
This is very simple. Use a timer like this:
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
//codehere
}
}, 0, delayInMillis)
Use can use an integer to specify in image.
public int image = 1;
in the run() function, use this to switch between the image
if(image = 1) {
image = 2;
} else if(image = 2) {
image = 3;
} if(image = 3) {
image = 0;
}
Now, wherever you are drawing your images, use this:
if(image == 1) {
//draw first image
} else if(image == 2) {
//draw second image
} else if(image == 3) {
//draw third image
}
I have been steaming over this one a few days now. I try to have a selector for a big range of numbers... within int-limits. You ought to hold down a button and the value should change slow and the longer you press the more rapid it changes. You all know that kind of button, don't you?! :D
It has to be precise, yet fast to enter the number. I use a OnTouchListener. The event allows to .getDownTime().
I tried a lot, but always only got it to skip numbers (not really but too fast to use) or not repeatingly increase the value while holding down the button. If run without changes it is pretty fast, but it would be nice, if it starts to make 10 100 or 1000-jumps if it is held down long enough.
I prepared a little SSCCE looking like this:
public class ValueChangerSSCCE extends Activity implements OnTouchListener {
Button plusButton;
TextView valueView;
Button minusButton;
int value;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
plusButton = new Button(this);
plusButton.setText("+");
plusButton.setTextSize(120f);
plusButton.setOnTouchListener(this);
layout.addView(plusButton);
valueView = new TextView(this);
valueView.setGravity(Gravity.CENTER_HORIZONTAL);
valueView.setTextColor(Color.WHITE);
valueView.setText(value + "");
valueView.setTextSize(120f);
layout.addView(valueView);
minusButton = new Button(this);
minusButton.setText("-");
minusButton.setTextSize(120f);
minusButton.setOnTouchListener(this);
layout.addView(minusButton);
setContentView(layout);
}
/*
* Called when a button is pressed
*/
#Override
public boolean onTouch(View v, MotionEvent event) {
if (v == plusButton) {
value++;
} else if (v == minusButton) {
value--;
}
valueView.setText(value + "");
return false;
}
}
For devices with low resolution one might have to decrease the text-sizes.
Thanks in advance!
Have a look at the NumberPicker source code. This is a widget from the SDK that does exactly what you are describing, except without the acceleration. Using post calls to a Handler as is done here is the best way to handle the timing events. The only addition you would need to make to this class is to vary the mSpeed value in the post callbacks (and perhaps the increment) based on the down time.
HTH.
The way I might try and tackle this is as follows:
Pressing + or - will start a Thread. The thread updates the number at a set interval by an offset value, if the number has changed more than 20 times then decrease the interval so the number updates faster, if the number is still changing a lot then the offset value would be made larger to skip numbers. Remember all this is happening in a thread.
When the user lifts their finger the thread is killed and the offset, interval is reset.
Use the value of getDownTime() to compute how big the counter increment should be.
First, design the response curve you would like. (That is, determine a function that defines how the value should change as a function of touch time and, perhaps, starting value. It does not — should not, from the way you describe it — be a straight line function.)
Then just make your increment follow the curve. It will probably help to store the button value and down time at the last event.