refreshing of canvas is happening only after touch - android

I am using ViewPagerparallax class,(for parallax view ) and I am setting the background using pager.setbackgroundAsset(....);
everything works fine....but I have a situation,what i want to achieve is that whenever the fragments go in a pause state and whenever it is resumed,the background should change and hence i am changing the background in the onResume method but seems like change is only visible whenever i try to swipe between fragments ...
this is my code
public void onResume()
{
Activity_Fragments ab = (Activity_Fragments) this.getActivity();
ViewPagerParallax pager=ab.hi();
int arr[]={R.raw.a1,R.raw.a2,R.raw.a3,R.raw.a4,R.raw.a5,R.raw.a6,R.raw.a7,R.raw.a8,
R.raw.a9,R.raw.a10,R.raw.a11,R.raw.a12,R.raw.a13,R.raw.a14,R.raw.a15,R.raw.a16,
R.raw.a17,R.raw.a18,R.raw.a19,R.raw.a20,R.raw.a21,R.raw.a22,R.raw.a23,
R.raw.a24,R.raw.a25,R.raw.a26,R.raw.a27,R.raw.a28,R.raw.a29};
int x=(int)(Math.random() * ((28 ) + 1));
pager.setBackgroundAsset(arr[x]);

A few notes.
First of, I am assuming you are using this: https://github.com/MatthieuLJ/ViewPagerParallax/blob/master/src/com/matthieu/ViewPagerParallax.java
When looking at the source it appears to be that you are doing things correctly.
I few things I can see that could be happening
The max number of pages set is 0, which is the default
The width or height is 0
The background hasn't changed from last time
The application has run out of memory (They say they don't want to use more then 1/5th of the memory
An exception was thrown while creating the bitmap of the image
A few things you could try
For point number 1, if you haven't already, call the set_max_pages with a number you see fit.
Point 2, Is the ViewPager in the activity with width and height set?
Point 3, confirm that you generator is working. (Already done, logic works perfect)
int arr[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
18,19,20,21,22,23,24,25,26,27,28,29};
for(int i = 0; i < 100; i++){
Log.d("TEST", String.valueOf(arr[(int)(Math.random() * ((28 ) + 1))]));
}
This returns the desired output, no problem there.
Point 4 & 5, Check logcat, it could say some errors, the tag should say ViewPagerParallax
I would say point 1 could be it, it will draw the background if it hasn't already once you set it.

I'm not really sure how setBackgroundAsset works, but try a call to invalidate(); at the end of onResume(). That will insure that your onDraw() method will be called ASAP and the new background will be redrawn.

Related

Libgdx for loop lag

I have problems with my game. The game runs ok until the time where I have to reposition the objects, which happens every frame. For example here I have to reposition some parked cars (around 6 cars on each side of the road), the cars are constantly moving down in the screen, then they reset and reposition at the top again. I have used Poolable to save resources. However, the game is still very jumpy when it comes to running these lines of code. Is there any way I could improve the code to prevent lag? Maybe a new thread? If so how would be the right way of creating a new thread and updating it every frame.
private void updateParkedVehicles(float delta){
for (int i = 0; i < parkedCarLeft1Array.size; i++){
parkedCarLeft1Array.get(i).update(delta);
for (int c = 0; c < parkedCarLeft1Array.size; c++){
if (c != i){
if (Intersector.overlaps(parkedCarLeft1Array.get(i).bounds, parkedCarLeft1Array.get(c).bounds)){
parkedCarLeft1Array.get(i).reset();
}
}
}
}
for (int i = 0; i < parkedCarRight1Array.size; i++){
parkedCarRight1Array.get(i).update(delta);
for (int c = 0; c < parkedCarRight1Array.size; c++){
if (c != i){
if (Intersector.overlaps(parkedCarRight1Array.get(i).bounds, parkedCarRight1Array.get(c).bounds)){parkedCarRight1Array.get(i).reset();
}
}
}
}
}
One way to handle items in your game is through the use of the Scene2d.
Scene2D allows you to step out from having to move yourself the items. Instead you give them instructions (as a director would) if and when you need to move them instead of having to handle yourselve every frame update.
in a nutshell, to add an Action you would do this:
if(SomeCondition){
MoveToAction moveCar = new MoveToAction();
moveCar.setPosition(anX,anY);
moveCar.setDuration(aDuration);
myCarActor.addAction(moveCar);
}
That way, the only thing you need to check for is the occurence of the event and you call your function to move the car only once (when the event occurs).
LibGdx will take care of updating your actor each frame.
The only thing you will need to do in your loop is to check the collision. If they occur then you will assign a new Action to your actor.
Another thing to keep in Mind, if you use Scene2D is that you can use the Camera. This means that if you need to scroll, instead of moving each item, you simply move the camera (which has all the convenience method you need to zoom etc).
For more information on Scene2D check out: https://github.com/libgdx/libgdx/wiki/scene2d
For more information specifically on Actions check this out:
https://github.com/libgdx/libgdx/wiki/Scene2d#actions
Hope it helps.
It seems to me that the problem is with double looping through arrays --> O(n^2) complexity!!
It's not clear for me why you need to check overlapping of each car with each car except this car if "the cars are constantly moving down in the screen, then they reset and reposition at the top again". For the described behaviour the simplest way would be to check is the current y position is less that 0 and rest position if so:
for (Car car : parkedCarLeft1Array){
car.update(delta);
if (car.getY <= 0) {
car.reset();
}
}
I assume that you update car position in update() method.

How to display a larger image in a smaller ImageView with a sliding effect in Android?

i am having a image of size 1000X400px. Assuming the screen width of the target android device to be 320px. i want to slide that image from right to left. actually i want to do this for a sliding 2d scrolling platformer that i was trying to make. so please help as i am just a beginner(only 2 weeks into android dev.)
i was thinking if i could somehow make the program sleep for some time and i did this:
int START_X = 0;
int START_Y = 0;
final int WIDTH_PX = 320;
final int HEIGHT_PX = 400;
Bitmap SOURCE_BITMAP = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.background);
Bitmap img = Bitmap.createBitmap(SOURCE_BITMAP, START_X, START_Y, WIDTH_PX, HEIGHT_PX, null, false);
bg=(ImageView)findViewById(R.id.imageView1);
bg.setImageBitmap(img);
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
img = Bitmap.createBitmap(SOURCE_BITMAP, START_X+100, START_Y, WIDTH_PX, HEIGHT_PX, null, false);
bg.setImageBitmap(img);
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
img = Bitmap.createBitmap(SOURCE_BITMAP, START_X+200, START_Y, WIDTH_PX, HEIGHT_PX, null, false);
bg.setImageBitmap(img);
but it directly executes the last statements after waiting for 4000ms i.e.
img = Bitmap.createBitmap(SOURCE_BITMAP, START_X+200, START_Y, WIDTH_PX, HEIGHT_PX, null, false);
bg.setImageBitmap(img);
First of all: the reason why you only see the effect of the last setImageBitmap(img) is because the method doesn't actually stop everything and draw the bitmap. It just sets the "drawing process" in a queue and it takes care of it a little bit later.
The reason why it didn't render the bitmap even with the Thread.sleep call, is because you we're freezing the thread which renders the screen. :) The code you write (unless you write it in a separate thread) runs on the same thread as the code that handles the screen drawing. If you freeze that ... you basically block the entire app.
Second: As mentioned, Thread.currentThread().sleep(2000) is not a good approach to stop the thread. The main thread of an Android app is called the UI thread. If you freeze that, your ENTIRE app will freeze. So don't do it, whatever the case. :) Use AsyncTasks instead ... or the postDelayed method of the Handler or some other way. There are a couple more.
Now, to get back to the matter at hand:
If you want to create an Android game, I suggest looking over the libGDX game development framework.
But if you don't want to go right into that, the easiest way of doing what you've described above would be to use an Animation. See this guy's answer.
Another approach could be to use a ValueAnimator, see this . What it does is ... you set a start and end value, i.e. screenWidth and 0 and you set a duration in miliseconds. Some "magic" happens in the back and a method onAnimationUpdate is called periodically with values between the start and end values you entered . You can take that value and set it as the left position of the ImageView. This might move the View from right to left and obtain the effect you want.
A more "advanced" method of doing it
Now ... a good way of doing it, which comes to mind, could be to:
create a class that overrides the ImageView class.
Set that in the .xml file of your layout and make it match_parent.
In its constructor you could load the Bitmap value into memory and keep it in a Bitmap local attribute.
Now .. the next thing you could do is override the onDraw method of the ImageView.
In it, you could use the drawBitmap method of the Canvas object. It accepts a srcRect and destRect which basically describesc what chunk from the original image goes where on the ImageView's canvas.
You could have a separate thread to keep the duration by which the image moves along the screen and that thread could call the invalidate method of your ImageView thus forcing the onDraw method to be called and thus redrawing the bitmap a little bit more to the left.

Detach child, update, and attach? AndEngine, Android

engine.registerUpdateHandler(new TimerHandler(0.2f,
new ITimerCallback() {
public void onTimePassed(final TimerHandler pTimerHandler) {
pTimerHandler.reset();
Rectangle xpRect = new Rectangle(30, 200,
(float) (((player.getXp()) / (player
.getNextLevelxp())) * 800), 40, vbom);
HUD.attachChild(xpRect);
}
}));
I have this so far in my createHUD method. It's pretty simple, it creates a rectangle showing the player's xp in relation to the xp needed for the next level and attaches it to the HUD. The only problem is that the old rectangle is never deleted. How can I have a rectangle like that one that updates itself and removes old ones?
If you use the detachChild() or any other detach method too regularly, you might run into problems sooner or later. Especially because the detaching can only be made on an update thread. You'll never know when exactly your rectangle will be detached again. So, to save you a lot of attaching and detaching, reuse the rectangle:
i) Save a reference of the Rectangle somewhere (as a global variable for example in your Playerclass).
ii) At the beginning when you load your stuff also initialize the rectangle:
Rectangle xpRect = new Rectangle(30, 200, 0, 40, vbom); // initialize it
HUD.attachChild(xpRect); // attach it where it belongs
xpRect.setVisible(false); // hide it from the player
xpRect.setIgnoreUpdate(true); // hide it from the update thread, because you don't use it.
At this point it doesn't matter where you put your rectangle or how big it is. It's only important that it is there.
iii) Now when you want to show the player his XP you only have to make it visible
public void showXP(int playerXP, int nextXP){
float width= (float) ((playerXP / nextXP) * 800); // calculate your new width
xpRect.setIgnoreUpdate(false); // make the update thread aware of your rectangle
xpRect.setWidth(width); // now change the width of your rectangle
xpRect.setVisible(true); // make the rectangle visible again
}
iv) When you no longer need it: In order to make it invisible again just call
xpRect.setVisible(false); // hide it from the player
xpRect.setIgnoreUpdate(true); // hide it from the update thread, because you don't
Of course you can now use the showXP() method in anyway you like and use it in your TimerHandler. If you want a more effect full appearance you do something like this instead:
public void showXP(int playerXP, int nextXP){
float width= (float) ((playerXP / nextXP) * 800); // calculate your new width
xpRect.setIgnoreUpdate(false); // make the update thread aware of your rectangle
xpRect.setWidth(width); // now change the width of your rectangle
xpRect.setVisible(true);
xpRect.registerEntityModifier(new FadeInModifier(1f)); // only this line is new
}
It's actually the same as the above method with just a little change in the last line, that makes the rectangle appear a little more smoothly...
To detach a child from a HUD ,you can write
aHUD.detachChild(rectangle);
To clear all children from HUD
aHUD.detachChildren();
To to clear all HUD from camera , you can write
cCamera.getHUD().setCamera(null);
After using one of above, You can create a HUD & also attach as usual.

Window already focused, ignoring focus gain of For raising height of sprite the preferences

I know this has been asked before and I went through all the answers and nope this ain't that, and yes I have the activity named in the manifest so it's not that.
Here's my problem:
I have a sprite moving across the screen and when in the window where you choose the livewallpaper, I have a preference that lets the user choose the height (so they can move the sprite up or down) the only problem is the sprite is constantly moving so when they use the seekbar to move the sprite up or down I get the old 'Window already focused, ignoring focus gain of" Now if I go out and come back in again of course this stop and restarts it and the new preference hight is already in their so it moves to the new height then but not in the live preview.
Here is the sprite code:
private void addShipOne() {
int heightPosition = (screenSized / 2) - (screenSized / /*this.bigShipHeight*/gettheFreakingHeight());
int widthPosition = 0;
Point startPoint = new Point(widthPosition, heightPosition);
this._shipone.add(new SpaceShipOne(this._context, this, startPoint, 125));
(sorry about the method name I was using to test a quick version I was a bit frustrated at that point) lol
It then goes into an OnDraw method then into the render to render it all.
public void render(){
Canvas canvas = null;
try{
canvas = this._surfaceHolder.lockCanvas(null);
synchronized (this._surfaceHolder) {
this.onDraw(canvas);
}
}finally{
if(canvas != null){
this._surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
I have another preference that allows the user to choose the frequency of the ships appearing it works fine but it goes from left to right and changes ships then so it updates the frequency then, but the height one doesn't work, I tested the log to make sure the height int goes through and it does so its not that, the only thing I can come up with is the maybe add this when the ship turns left or right, but it does not work while its moving by the looks of it.
this.bigShipHeight is where the new height value goes into ( I was just testing it another way with the gettheFreakingHeight() (I used an if else statement for that method that used the frquency preference instead which does work nicely.
Just to add the full code part.
In the onDraw(Canvas canvas)
I render the _shipone as such
for (Renderable renderable : this._shipone) {
renderable.render(canvas);
}
Any help would be appreciated.
Thanks in advance
Sam
Ok I should of looked into the my sprite class first, sorry about this I answered my own question once again and it was too obvious, that's what I get for looking at the code way to long, I should walk away then come back it always is clearer then.
Just in case others run into this issue I'll put the answer.
In my sprite class which SpaceShipOne runs from I just added this
this.getSprite().setYPos(this._blimp.gettheFreakingHeight());
This updates right away with no window already focused.
I don't know why I didn't see this last night because it is the only place it can be added and be updated right away, all I had to do was set the Y position to the preference instead.
It works like a charm.
Hope this helps someone else out
Sam

How to reset AnimationDrawable

I have to animate a circular count down timer and I'm doing it by animating the background of an ImageView using AnimationDrawable (each image has the according slice of the circle removed). The problem is that the user has the ability to pause this animation, so I have to reload the animation but then a problem appears. I've tried setting the the animation to null, setting the background of the ImageView to null, setting the visibility of the animation, but practically nothing helped, because number of frames remains the same. I have to find a workaround for deleting all frames and adding new ones or to reset the whole animation to the default state.
Step 1 - initializing the animation (starting frame index is 0)
timerView.setBackgroundResource(R.drawable.timer_switch);
timerAnimation = (AnimationDrawable)timerView.getBackground();
System.out.println("Number of frames: " + timerAnimation.getNumberOfFrames());
for (int frameIndex = startingFrameIndex; frameIndex < 60; frameIndex++) {
if (frameIndex < 10) {
uri = "drawable/timer_0000" + frameIndex;
} else {
uri = "drawable/timer_000" + frameIndex;
}
imageResourceId = getResources().getIdentifier(uri, null, getPackageName());
timerAnimation.addFrame(getResources().getDrawable(imageResourceId), timerImageFrameDuration);
}
Step 2 - here's the tricky part where I don't know what to do. Things that I've tried:
timerAnimation.stop();
timerAnimation.setCallback(null);
timerAnimation.setVisibility(true, false);
timerAnimation = null;
Step 3 - after calling step 2 I call step 1 again, but the Sys.out still displays 60 as the current number of frames. (starting index here is set to the last hidden frame when pause button was tapped.)
Any idea is welcomed.
Thanks
This will send the (AnimationDrawable) timerAnimation to the first frame as soon as stop() has been called:
timerAnimation.stop();
timerAnimation.selectDrawable(0);
I had the same problem where stopping the animation would stop on the current frame. I wanted it to behave like iOS, where stopping would go back to the first frame. This solution works for me:
((AnimationDrawable)(someButton.getBackground())).stop();
someButton.setBackgroundDrawable(null);
someButton.setBackgroundResource(R.drawable.animation);
This first stops it (probably not necessary). Then it kills the background animation. Finally, it recreates the background.
Another possible solution would be to have the same image for the first frame and last frame and do the following instead of calling the stop() method.
((AnimationDrawable)(someButton.getBackground())).setOneShot(true);
if anyone does look into this any further. There is also a method called setVisible(boolean visible, boolean restart). However, that did not work for myself.
You can try public boolean setVisible (boolean visible, boolean restart) and it will play the animation once. For example:
animationDrawable.setVisible(false, true);
I would setVisibility(true, true):
timerAnimation.stop();
timerAnimation.setVisibility(true, true);
visible boolean: true if visible, false otherwise
restart boolean:
when visible, true to force the animation to restart from the first frame
android.view.animation.Animation.reset() doesnt work?

Categories

Resources