Using a CountDownTimer and Queue together - java

I am working on a "Simon Says" pattern game. The player must repeat an increasingly long pattern till they mess up.
The game consists of a 2x2 grid of colors, each with a darker one behind it. By changing the alpha from 1--->0---->1. I give the effect of clicking.
Below is the code I am using to display the pattern as it increases, it's called whenever the pattern resets or increases. But currently it always skips the last value in the pattern, and if the same color is repeated it does not flash again, it simply remains dark, what am I doing wrong?
Helpful Information:
Pattern is the arraylist where I am storing the pattern the user must repeat.
getColorById returns the corresponding ImageView for each color [0-3]
TLDR:
I need to flash every single item in an arrayList called pattern, so the player can see it and repeat it, yet currently it skips the last item and if the same item is repeated it simply stays flashed versus flashing twice.
EDIT: Sometimes, the last item in the sequence does show, but it is very random on whether it shows or not.
public void flashPattern(View view){
final Queue<Integer> queue = new LinkedList<>(pattern);
final int timeBetweenSteps = 500;
new CountDownTimer(pattern.size() * timeBetweenSteps, timeBetweenSteps) {
private ImageView lastLight = null;
#Override
public void onTick(long millisUntilFinished) {
if (lastLight != null) {
lastLight.animate().alpha(1f).setDuration(250);
}
lastLight = getColorById(queue.remove());
lastLight.animate().alpha(0f).setDuration(250);
}
#Override
public void onFinish() {
if (lastLight != null) {
lastLight.animate().alpha(1f).setDuration(250);
}
}
}.start();
}

Related

How do I change alpha of an image view multiple times using thread.sleep?

I am trying to create an animation for my game. I am trying to make an animation of a coin flip that will stop under certain conditions.
So far I have tried to change an image view multiple times within one method and using thread.sleep to delay the transition between the pictures.
Using 12 different images I am now trying to make it so the alpha of the first image will set to 0 and the second image will set to one, the the second image will set to 0 and the third will set to 1, etc...
The way I am currently trying to do it is by putting images inside of an array of ImageViews and then calling them sequentially.
setContentView(R.layout.coin_flip_screen);
for(int i = 0; i < 4; i++){
headsTails[i].animate().alpha(0).setDuration(100);
headsTails[i+1].animate().alpha(1).setDuration(100);
try {
Thread.sleep(100);
} catch (Exception e) {
}
}
final int size = imageView.length;
final int animTime = 300;
final Handler animationHandler = new Handler();
Runnable animationRunnable = new Runnable() {
int i = 0;
#Override
public void run() {
if(i == size-1){
animationHandler.removeCallbacks(this);
return;
}
imageView[i++].animate().alpha(0f).setDuration(animTime).start();
imageView[i].animate().alpha(1f).setDuration(animTime).start();
animationHandler.postDelayed(this, animTime);
}
};
animationHandler.post(animationRunnable);
This code will iterate through all your imageviews in the array and stop itself once all the images are consumed.
Play along with your animTime variable until you get the perfect animation effect. Ideally it should be around 300 to 500 ms.
I will personally not use array of imageviews to create this effect as
it will eat up the memory. There are many more efficient ways to do
the coin flip animation, which you can google when you get time.
This should fix it
headsTails[i].animate().alpha(0).setDuration(100).start();

How to make each ImageView of list to start animation one by one?

I'm new to Android and I have 9 ImageViews that I want to make transparent. I'm using AlphaAnimation to make them fade. They fade indeed but I want to make them fade one by one. Unfortunately they all fade together and I don't know why.
I tried to use various ways to do it(including CountDownTimer,Thread.sleep(),new Handler().postDelayed()), but there is no change. All of the ImageViews fade simultaneously, not one by one. I know they are capable of doing it because animation on one works, but iteration throught list of this views ends up with all of them being animated at the same time.
Important methods(I guess):
private void fadeImageTiles(List<ImageView> ivs) {
Collections.shuffle(ivs);
for (ImageView iv : ivs) {
//maybe there's problem with iteration?
gradientFade(iv);
}
}
private void gradientFade(ImageView iv){
AlphaAnimation animation = new AlphaAnimation(1f,0f);
animation.setDuration(2000);
iv.startAnimation(animation);
iv.setVisibility(View.INVISIBLE);
}
Final effect is to make them fade randomly revealing image behind
You can use void setStartOffset (long startOffset) to specify after how many milliseconds the view should be animated.
For example:
private void fadeImageTiles(List<ImageView> ivs) {
Collections.shuffle(ivs);
for (int i = 0; i < ivs.size(); i++) {
//maybe there's problem with iteration?
gradientFade(ivs.get(i), i);
}
}
private void gradientFade(ImageView iv, int index){
AlphaAnimation animation = new AlphaAnimation(1f,0f);
animation.setDuration(2000);
animation.setStartOffset(index * 500);
iv.startAnimation(animation);
iv.setVisibility(View.INVISIBLE);
}
Or you can use ViewPropertyAnimator without writing much code. Replace your code inside your gradientFade method with this:
iv.animate().alpha(0).setDuration(2000).setStartDelay(index * 500);

Incremental values how to show one value at a time

I am making a simple sequence from randomly generated numbers. Each number will show an image linked to it.
for example,
the value 1 will show a picture of a cat.
value 2 a dog
and value 3 a mouse.
Each image has it's own dedicated imageview, the layout looks like this by default, i.e image views that store black until it's number is called:
Each time the sequence increments. so on the second run two images will show, on the third 3 will show and so on.
The problem I am having is that all the images show at once. So for sequence one just the one image flashes (which is what I want). but on the second run both images show at once together instead of showing the first image then the second.
So to clarify let's say on the four runs the stored array is 1,2,3,3 I would want
image 1 to show, and disappear.then
image 2 show and disappear. then
image 3 show and disappear
and then image 3 to show and disappear.
But what I actually get is on the fourth run 1,2&3 will show at once and disappear at the same time together. How can I break this up to achieve what I want. I have tried many methods and the same result happens. I can't get my head around this problem.
Here is my code:
ArrayList<Integer> stored_vals = new ArrayList<Integer>();
public void Gen() {
int i=0 ;
Random rand = new Random();
int rndInt = rand.nextInt(3)+ 1 ;
list.add(rndInt);
int totalElements = list.size();
Log.d("LOOK", Integer.toString(rndInt));
Log.i("VALUE LIST ", list.toString()+" <<<<LIST HERE");
while(i < totalElements) {
retval =list.get(i);
Log.d("RETVAL", Integer.toString(retval));
String imgName = "flash" + retval;
int id = getResources().getIdentifier(imgName, "drawable", getPackageName());
if (retval==1){
Cat.setImageResource(id);
Reset_View();
}
else if (retval==2){
Dog.setImageResource(id);
Reset_View();
}
else if (retval==3){
Mouse.setImageResource(id);
Reset_View();
}
i++;
}
}
To try and delay the images showing at one at a time and to reset to it's default after showing for a few seconds I call Reset_View(); which is the following code:
CountDownTimer Reset_View = new CountDownTimer(1000 , 0010){
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
Centre.setImageResource(R.drawable.i1);
upperRight.setImageResource(R.drawable.i2);
lowerRight.setImageResource(R.drawable.i3);
lowerLeft.setImageResource(R.drawable.i4);
upperLeft.setImageResource(R.drawable.i5);
}
};
So how can I achieve what I want. I have been stuck on this idea for weeks.
This is a high level idea of what you could do.
Put all the showing and hiding in the countdowntimer. So basically you would need to handle the 'onTick' and hide or show the images when needed. Something like 'time > 0 and < 1000' hide all but the first image. 1000 to 2000, show only second image. 2000 to 3000, show only third image. On finish, hide all.
When you instantiate the timer after the for loop, if retval is 1 - then 1000 would be how long to run, retval = 2, then 2000, retval = 3, then 3000.
There is probably a better way to do it but this is the first thing that comes to my mind.
One problem might be that Reset_View(); is not a method. The line even states public CLASS Reset_View(); extends CountDownTimer. ( I don't know ho that can be a valid class name but whatever) Therefore, calling Reset_View(); will not actually do anything.
You need to change the name of the class to something else, I suggest ResetTimer. Then to reset the Views you must create an instance of ResetTimer and use its start() method like this:
new ResetTimer(1000, 1000).start();
Note: the first number in the constructor is the total time (in milliseconds) until the timers onFinish() is called. The second one it the time between the onTick()s. Since you don't use this method, the number you put in there doesn't matter.

Focus ScrollView to selected position programmatically - Android

I have a ScrollView with a lot buttons. Each button is enabled when the user unlocks that button/level. I would like to focus the ScrollView on the latest unlocked button/level. See the screenshot below.
I found some functions like scrollTo() that could focus the ScrollView either at top, button or something like that but I would like to focus the ScrollView at certain places like the button ID that says Level 8 in the screenshot below. How would I go about doing this?
I think this should be good enough :
yourButtonView.getParent().requestChildFocus(yourButtonView,yourButtonView);
public void RequestChildFocus (View child, View focused)
child - The child of this ViewParent that wants focus. This view will contain the focused view. It is not necessarily the view that actually has focus.
focused - The view that is a descendant of child that actually has focus
First you need to know the position of item in scroll that has to get focus once you know that you can use following code to make that item focus
final int x;
final int y;
x = rowview[pos].getLeft();
y = rowView[pos].getTop();
yourScrollView.scrollTo(x, y);
refer this question
I agree with the benefits of previous answers. However, by experience, I have found this to be more complex than this. The setSelectionFromTop is very sensitive and often breaks if it is executed too early. This may depend on different reasons but the two primary reasons are that
If executed from within Activity lifecycle methods the views have not been loaded/configured yet.
View modifications triggered after the list move action seems to break the move. Probably overwriting some value before the move has been finalized due to a recalculation of the views.
The reasoning seems to apply for both setSelectionFromTop and setSelection() methods although
I tested mostly with setSelectionFromTop. smoothScrollToPosition() seems to be more robust, probably because it by definition changes the list position delayed whn doing the smooth scrolling.
Look at this example source code:
// Wee need to pospone the list move until all other view setup activities are finished
list.post(new Runnable(){
#override
public void run() {
list.setSelectionFromTop(selectedPosition, Math.max(0, Math.round(list.getHeight() / 3))); // Make sure selection is in middle of page, if possible.
// Make sure you do not modify (this or other) parts of the view afterwards - it may break the list move
// activityButtons.setVisibility(View.GONE);
}});
see: http://developer.android.com/reference/android/widget/ListView.html#setSelectionFromTop(int, int)
'int selectedLevel' holds the currently selected level, information is held in a Level class.
'values' is a list with all your levels, displayed by the list.
Example:
ListView lv = (ListView)findViewById(android.R.id.list);
int i = 0;
for (Level l : values) {
i++;
if (l.level == selectedLevel) {
lv.setSelectionFromTop(i, 200);
break;
}
}
try this
sc.post(new Runnable() {
public void run() {
sc.smoothScrollTo(x, y);
}
});
x the position where to scroll on the X axis
y the position where to scroll on the Y axis
Use this code, taken from this answer
private final void focusOnView(){
new Handler().post(new Runnable() {
#Override
public void run() {
your_scrollview.scrollTo(0, your_EditBox.getBottom());
}
});
}
Use this code, taken from my another answer
scrollViewSignup.post(new Runnable() {
#Override
public void run() {
int scrollY = scrollViewSignup.getScrollY();
scrollViewSignup.scrollTo(0, 0);
final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight());
view.requestRectangleOnScreen(rect, true);
int new_scrollY = scrollViewSignup.getScrollY();
scrollViewSignup.scrollTo(0, scrollY);
scrollViewSignup.smoothScrollTo(0, new_scrollY);
}
});
This code tries to smooth scroll and uses the standard behaviour of system to position to an item. You can simply change smoothScrollTo with scrollTo if you don't want the system to smooth scroll to the item. Or, you can use the code below only.
scrollViewSignup.post(new Runnable() {
#Override
public void run() {
scrollViewSignup.scrollTo(0, 0);
final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight());
view.requestRectangleOnScreen(rect, true);
}
});
Use the desired code block after trying, or, according to the need.

How to start a number of moving Sprite objects on different time?

I created a live wallpaper service using AndEngine library. On screen there are a number of bird Sprite objects that flying repeatedly from the left to right started in random y-coordinate (I'm using LoopEntityModifier and PathModifier for this, see my previous question if you're curious). The birds shouldn't start flying in same time, but there is a gap/interval about 3 seconds before another bird showed up from left most screen.
The question is what technique that I have to use to achieve that?
I had created array of Sprites to hold the bird sprites. The code is like this...
public class MyLiveWallpaperService extends BaseLiveWallpaperService {
private BirdSprite[] birdSprites; // BirdSprite is actually an extension class from AnimatedSprite
...
#Override
public Scene onLoadScene() {
...
birdSprites= new BirdSprite[4];
for (int i=0; i<4; ++i) {
birdSprites[i] = new BirdSprite(0, 0, birdTextureRegion);
scene.getChild(LAYER_FRONT).attachChild(birdSprites[i]);
}
}
}
The above code produces four birds that show-up on left screen in same time. I tried by adding Thread.sleep(3000) before calling attachChild, but it affects whole application. The live wallpapaper application become hanged for several seconds when started.
This is the solution I found by using TimerHandler:
scene.registerUpdateHandler(new TimerHandler(3, true, new ITimerCallback() {
#Override
public void onTimePassed(TimerHandler pTimerHandler) {
// your code here will be executed every 3 seconds (see 1st argument of TimerHandler)
...
scene.getChild(LAYER_FRONT).attachChild(birdSprites[i]);
}
}));
Please let me know if you have better solution.

Categories

Resources