I have an animation using Lottie that works fine, the problem is, let's say that my animation is a ball that grows and shrinks (like if it's beating), when the user press the ball, I need it to 'grow to be at its maximum size' so I'd need to set my animation progress to 1 (right?).
This works fine, but the problem is that I want the ball to 'grow' until it gets to its maximum size, not just go from 0 to 1 in a fraction of a second, does anyone know how to do this? (sorry if my question is kind of not well formulated...)
Here's the code that I tried to write: (this code makes the ball go from 0 to 1 in a fraction of a second and not like if it's growing)
LottieAnimationView unclickedAnimation = ...
unclickedAnimation.pauseAnimation();
float currentProgress = unclickedAnimation.getProgress();
for(float i = currentProgress; i < 1.0f; i += 0.01f) {
unclickedAnimation.setProgress(i);
}
Thanks already
With your currect code you just set the animation to show a specific frame. You want to set the maxProgress and then play the animation.
So if you want it to go from half size to full size you would start with a maxProgress(0.5f); and pause it there. When the users clicks you set the new parameters:
unclickedAnimation.setMaxProgress(1f);
unclickedAnimation.resumeAnimation();
If I am able to understand your question correctly, I think all you need to do is play your Lottie animation on click of the LottieAnimationView. The following code may help you understand.
Say your animation json goes from smallest ball size to largest, then -
unclickedAnimation.setOnClickListener(v -> {
unclickedAnimation.playAnimation();
});
Furthermore if you want to loop or set the max frame/ min frame for your animation, you can use -
unclickedAnimation.loop(true);
unclickedAnimation.setMaxProgress(/*value here*/);
Related
Hello everyone,
I am quite new to Flutter and wanted to build an application that detects multiple touches and if that touch lasts longer sets a circle there for example.
Similar to this there is the app "Chwazi Finger Chooser" in the PlayStore. This is how the whole thing should look like in the end.
Can you help me and tell me which components I need? Or if possible suggest some code?
I have not found an answer through my research so far and am hoping for you now!
Please help me :)
check the GestureDetector widget
and those available events https://flutter.dev/docs/development/ui/advanced/gestures
however Using OnGestureListener to detect multitouch gestures does not seem to be implemented by default.
The first thing you may have tried is reading event.pointerCount to get the count of fingers on the screen. However, this will be equal to 1. This is because you will (quite likely) never be able touch the screen with both fingers in exactly the same millisecond.
Fixing it
You have to buffer pointerCount (the amount of fingers on screen). First add those variables somewhere in the context that you intend to track gestures in:
// track how many fingers are used
var bufferedPointerCount = 1
var bufferTolerance = 500 // in ms
var pointerBufferTimer = Timer()
Then, in the onTouchEvent(event: MotionEvent) function, you add this:
// Buffer / Debounce the pointer count
if (event.pointerCount > bufferedPointerCount) {
bufferedPointerCount = event.pointerCount
pointerBufferTimer = fixedRateTimer("pointerBufferTimer", true, bufferTolerance, 1000) {
bufferedPointerCount = 1
this.cancel() // a non-recurring timer
}
}
Essentially this tracks the maximum amount of fingers on the display and keeps it valid for bufferTolerance milliseconds (here: 500).
Good evening. I am trying to smoothly move rectangle shape across the screen with glTranslatef. The concept is Windows 10 notifications. You know that they appear from right bottom of the screen, ease in-out animation and so on. I am trying to recreate it. But I dont know how can I achieve it.
Here is a basic requirement:
Move slowly, not in one frame. For example Windows 10 notifications. They move slowly, ease in-out (if possible).
I would appreciate any help, any tip, so thanks in advance!
You could start by finding the height (or width, as needed) define and initialize a variable (say, x) at half the height (again, or width) and move the notif x pixels up, divide x by 2, and raise the notif by 2 again, and repeat a number of times so that the notif doesn't take to long to appear, or look awkward, and finally move to the final desired position. (If you don't like how it looks, you can subtract x by 1 or some other number instead.)
I am making a simple game.
I have 6 buttons and i want to shuffle them each time on different locations.
So i've made a simple method to achieve this.
private void changeButtonPlace(ImageView button) {
Random r = new Random();
int newXloc = r.nextInt(getScreenWidth() - (2 * button.getLayoutParams().width));
int newYloc = r.nextInt(getScreenHeight() - (3 * button.getLayoutParams().height));
button.setX(newXloc);
button.setY(newYloc);
}
It works pretty well, but sometimes the buttons override each other which means that it goes on the almost the same location. I want each button to be on a unique location and don't touch other buttons.
Any idea how i can achieve this?
Thanks in advance!
What you are looking for is collision detection, and my answer will greatly simplified this process. I suggest searching for collision detection algorithms to learn more.
So, for super simple starts, we can compare the position, length, and height of 2 boxes. For my example, I am going to assume the origin of these to boxes are their upper left corner.
if((boxA.xPos + boxA.length ) < boxB.xPos || boxA.xPos > (boxB.xPos + boxB.length))
That will check if the two boxes are touching along the x-axis, and we can change the values for the y-axis as well
if((boxA.yPos + boxA.height ) < boxB.yPos || boxA.yPos > boxB.yPos + boxB.height)
Now, this is not a very efficient way of doing this. There are lots and lots of better ways to simplified this logic, and save on resources. But, it is quick and dirty, and probably good enough for a small application like your simple game involving only 6 buttons.
So, with these two equations, you can either nest them then run your collision code inside, or you can OR them together to one equation like this:
if(((boxA.yPos + boxA.height) < boxB.yPos || boxA.yPos > (boxB.yPos + boxB.height)) || ((boxA.xPos + boxA.length ) < boxB.xPos || boxA.xPos > (boxB.xPos + boxB.length)))
That is a lot to read for one line, and if you just starting out, I would suggest nesting them so you can better see the flow of logic through the equations. But, keep in mind for the future, if you ever need to squeeze those few extra bits of performance, OR them together to one if statement is alright place to start.
One way would be to make a grid and instead of a random location on the screen use a random point on the grid. That way you can check if the current grid location has a button on it already.
If you want them to be more scattered you could add each button to an array and check that the new doesn't touch the other buttons. Loop infinitely creating random locations and another loop to check they don't hit the other buttons in the array. Once a new location is found add the button and break out of the infinite loop.
You should take in account the width of the button , and before setting the location of the button make sure no button intersect with a simple if, if they do just randomize the intersecting buttons, should be easy to programm
Edit :
Lets make it a bit simpler an assume you have 3 buttons an assuming they are located on a 2d axis with these coordinates
A : 1,0
B : 2,0
C : 5,0
button width : X=2 Y=2
As you can see in this example at first glance it seems as though no button intersects with each other yet if you add the width to B you understand that is real location is B [1,3] ,[-1,1] intersects with the real location of C [4,6],[-1,1] assuming the coordinates are the center of the button
first [,] represents X axis second [,] represents Y axis
therefore your check will be something like so:
For each Button x
For each button x
calculate real coordinates of button x and y check intersection
if exists recalculate the coordinates and start the loop over
this solution is a bit expensive when talking about running time but once you get the idea you will be able to find something easier.
I want to launch projectiles from the bottom-right corner of the screen towards the left side of the screen. Now, I want the projectiles to fly with random velocities and angles according to the screen dimensions, just like that. Now, I know this is very simple but from some reason I can't manage to make this work.
Here is what I have tried so far:
My first try - Launch function
private void launchProjectile() {
projectiles.peek().getBody().applyForce(projectiles.peek().getBody().getWorldVector(new Vector2(MathUtils.random(-20,-1*SCALAR_HEIGHT),
MathUtils.random(2*SCALAR_HEIGHT,8*SCALAR_HEIGHT)).scl(MathUtils.random(3*SCALAR_HEIGHT,5*SCALAR_HEIGHT))),
projectiles.peek().getBody().getWorldCenter(), true);
Gdx.app.log("System", String.valueOf(SCALAR_HEIGHT));
}
Here is my second try - Launch function
private void launchProjectile() {
float xVelocity;
float yVelocity;
xVelocity = (float) MathUtils.random(0,0)*SCALAR_WIDTH/2;
yVelocity = (float) MathUtils.random(20,20)*SCALAR_HEIGHT;
velocityProjectile.set(xVelocity,yVelocity); // Sets the velocity vector to the above values
velocityProjectile.sub(projectiles.peek().getBody().getPosition());
velocityProjectile.nor(); // Normalize the vector - Now it's fine and ready!
// Sets the start velocity of the projectile Trajectory to the current velocity
projectiles.peek().getBody().setLinearVelocity(velocityProjectile.scl(18+SCALAR_HEIGHT));
}
In both tries, the projectile flies way more than I need and it doens't take in consideration the screen size like it should.
Can you guys please tell me what is the right way to do this?
Thanks!!
Start with this page: http://www.iforce2d.net/b2dtut/projected-trajectory
In the "How fast should it be launched to reach a desired height?" section, you can see how much vertical velocity will be required to make the projectile reach the top of the screen. So you would pick a random number less than that, to make sure it doesn't go off the top of the screen.
Next, in the "How high will it go?" section, you can see the formula to find out how many time steps it will take for the projectile to reach maximum height. It will then take the same amount of time to come back down to the starting height. For example, let's say it would take 60 time steps to reach maximum height. That means it would take 120 time steps to fall down again to the same height as it started. Then you can set the horizontal part of the launch velocity so that it cannot go outside the screen in 120 time steps.
Basically I have a game where I want to play an explosion gif whenever the player (or an enemy) dies, but I want the gif to just play once.
I have everything set up in a class and I have an ArrayList that gets explosions added to it when I need it to, and I currently have it set up to remove them once the gif's duration has been reached (using System.currentTimeMillis()). The only problem there is that it isn't exact, and sometimes the gif stops early and disappears, and sometimes it rolls over, both situations causing the next one to start where the other one left off.
Is there some sort of method, class, listener of some sort, or anything I can use to tell what frame my gif is on, or how many times it has looped? My code can do the rest of the work, I just need something better to put in my if statement than this:
g2D.drawImage(explosion, x - 150, y - 150, null);
if(System.currentTimeMillis() - startingTime > 520){
System.out.println(System.currentTimeMillis());//for testing accuracy
Game.explosions.remove(this);
explosion = null;
}
The usual solution to this is to not use a gif :)
Most games will store each 'frame' of the gif separately, and display them in order, instead of trying to get gif rendering to work.
System.currentTimeMillis() is not terribly accurate, plus there can be tons of stuff going on in the background between calls to your draw function (all of which affects the framerate) so I would recommend against relying on that in general.