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*/);
What happened to Codename One animations? I use a lot of them and as of december my app is no longer working. When I left things in June everything was fine (and was so for more than a year).
My app is a draughts (checkers) game and is available in the app stores since 2013. After seeing the CN1 Poker demo, I completely rewrote my GUI as I wanted to add those kind of animations to my app. What happens now is that I suddenly get index out of bound exceptions. I narrowed this down to the following situation:
cont.addComponent(comp);
...
...
cont.getComponent(0); <-- index out of bound exception: 0 out of 0
I already used newVM=true in June, which is now the default, I believe. I tried to fix things by adding a
cont.animateLayoutAndWait(100);
after the addComponent call. This fixed the index out of bound exceptions, but now the app just crashes at random moments after working fine for a short time. I tried but have been unable to find the source of the problem. Something has changed in CN1 so that my code no longer works. (See also the old forum, search for "draughts", where I posted a complete listing of my basic design.)
I studied the new Solitaire demo, which has most of the animation functionality I need. And the app store versions of Solitaire run fine on all my iOS/Android devices. A minor bug is that it is possible to drag a group of cards including some that are facing down, which are facing up during the drag operation. Also it is pretty hard to pick up exactly the right amount of cards. Dragging a group of cards also leaves a white trail on the screen, which doesn't look very nice. This also happens in the Simulator.
As an experiment, I redesigned my GUI layout to exactly resemble that of the Solitaire code: two layers of buttons, the only difference being that I use GridLayout(10,10) where Solitaire uses SolitaireLayout(). This works, except for one thing: if a checker moves DOWN the board it correctly moves OVER other checkers, but if a checker moves UP the board it moves UNDER the other checkers.
My code looks like this:
Button pc = (Button)piecesCnt.getComponentAt(a1);
Button to = (Button)piecesCnt.getComponentAt(a2);
piecesCnt.removeComponent(pc);
piecesCnt.addComponent(a1, createPieceButton(Piece.EMPTY_PIECE, true));
piecesCnt.removeComponent(to);
piecesCnt.addComponent(a2, pc);
piecesCnt.animateLayoutAndWait(1000);
So it seems that the buttons are always drawn in their GridLayout order, while I hoped that the animated (moving) button would be drawn last/on top, just like the moving cards in Solitaire.
Is this a difference between handling animation in SolitaireLayout vs. GridLayout? If so, can this be changed in the animation logic? Otherwise I have to add an extra animation layer and a lot of overhead.
And on Android, the animation (movement) is not working properly. So I decided to also self-build and test the Solitaire demo on my devices with the current CN1 version (plugin 3.2.6, libs 2016-01-11). I changed the animations to be 10x slower, to better see what is happening. In the Simulator, the layout and animations work mostly fine but on my iOS and Android devices there are a lot of problems.
Simulator (Windows 7, NetBeans 8.0.2):
- I replaced the font icons by text since they are missing.
- But how to access the hamburger menu? I don't see the 3 dots and there is even no space for it.
- Sometimes it is possible to drags a groups of cards with some downfacing cards taken; while dragged they are temporarily flipped facing up.
- Autoplay doesn't always seem to work. (Not all moves are played.)
On iOS 9.2 (iPad 4), iOS 8.4 (iPhone 4):
- [?] is shown in the hamburger menu check boxes.
- After startup, the tableau background card-backs jump to the bottom of the container/screen.
- Sometimes, in the deal-from-deck animation, cards in the rightmost tableau are temporarily facing up, and cards already facing up are flipped facing down. The final deal-state is correct, however.
- Undo/Redo: sometimes results in a facing-up card on deck 0 and a facing-down on deck 1.
- Redo sometimes 'jumps' to the new layout instead of animating.
iPhone only:
- A sequence of autoplay moves left an inconsistent foundation state: top cards heart-J, club-10, club-K, diamond-Q; i.e., 2 club-cards on different foundation stacks.
On Android 5.1.1 (Nexus 7) there are more problems.
- The deal-from-deck animation is not a pretty sight. Cards are inserted (slide to) at the bottom of the tableau stacks, so they slide under the other cards. The moving cards should be facing down but are usually facing up, always showing the first card dealt to tableau 1. The cards in rightmost tableau are temporarily facing up. Finally, cards already facing up are flipped facing down and back again. The final deal-state is correct, however.
- Autoplay is also not correct when there are several moves in a row. During the animations, several foundation cards facing up change their card value (front) temporarily. Also the moving cards slide under the foundation card (and sometimes over, but this is the exception).
- After finishing the game, the well-done screen is corrupted since the text seems to be displayed not overlayed but below the cards (in a big white space), which are only partly visible in a tiny portion at the top of the screen.
- Starting a new game often fails because deal-from-deck is not started; the screen shows a deck and four kings on the foundations with the tableau empty. When tapping the deck, a card is dealt and the well done sequence is show. Sometimes repeating this results in successfully starting a new game.
All this has taken a lot of time already and I still don't have my app working again, which is very frustrating. Having so much trouble with this topic, even with a downloaded demo app, building this type of app with Codename One feels like building on quicksand. Please help!
You should have probably just asked once you ran into trouble instead of working so hard on the post. Yes we did make a major somewhat compatibility breaking change as part of a bug fix for long standing animation issues (where animations running in parallel could collide).
This introduced some collisions but reduced inconsistencies between devices/simulator which is always a good thing.
We announced this here: https://www.codenameone.com/blog/new-animation-manager.html
It is actually MUCH simpler to create a portable animation now as everything will get synchronized to avoid animation collisions e.g. if you do Component.removeComponent() while an animation is in progress it will be implicitly added to the animation queue and performed after the animation completes instead of immediately.
To postpone your next action until after the animations we have:
form.getAnimationManager().flushAnimation(() -> doThisAfterAnimation());
Much simpler and no special case global locks.
Its a bit hard to "port" code directly to the new approach but it looks like your animate logic relies on the animation taking 1000ms and that it completely finished when the method returns which might not always be the case (as add/remove calls or other logic might get in the way).
In the past the only way to guarantee an animation was complete was to distance them apart but now you can just use flushAnimation to make sure all animations have completed. Keep in mind that some things that aren't explicitly an animation can now become an animation by accident e.g. an add/remove component will become an animation if there is an animation in progress when you call them...
I'm sorry I missed the blog post on the new animation manager of December 16. The Solitaire demo dates October 8 and I checked the Developer Guide of December 31, so I thought I was up to date. Still, it is not clear to me how to use the new animation manager. The new Developer Guide of Januari 11 says nothing on the topic and your answer/blog post are not very elaborate.
It would also help a lot if the Solitaire demo would be updated to work with the new animation manager.
Now my questions are:
1) How do I rewrite the following code to use the new animation manager? This is a realistic scenario because I have animations with multiple steps that should be performed consecutively.
// simplified code (background layer omitted)
public void start() {
if(current != null){
current.show();
return;
}
Form form = new Form("Draughts 2");
Container piecesCnt = new Container(new GridLayout(10, 10));
for (int i=0; i<100; i++) {
piecesCnt.addComponent(createPieceButton(piece(i), true));
}
form.addComponent(piecesCnt);
form.show();
new UITimer(() -> {
testAnimation(piecesCnt, 0,9 , 9,0); // moves UNDER other pieces
testAnimation(piecesCnt, 9,0 , 0,9); // " OVER " "
testAnimation(piecesCnt, 1,0 , 9,8); // " OVER " "
testAnimation(piecesCnt, 9,8 , 1,0); // " UNDER " "
}).schedule(1500, false, form);
}
private void testAnimation(Container piecesCnt, int x1,int y1, int x2,int y2) {
int a1 = 10 * y1 + x1;
int a2 = 10 * y2 + x2;
Button pc = (Button)piecesCnt.getComponentAt(a1);
Button to = (Button)piecesCnt.getComponentAt(a2);
piecesCnt.removeComponent(pc);
piecesCnt.addComponent(a1, createPieceButton(Piece.EMPTY_PIECE, true));
piecesCnt.removeComponent(to);
piecesCnt.addComponent(a2, pc);
piecesCnt.animateLayoutAndWait(1000);
}
2) Does rewriting this also solve the problem of a piece (checker) moving under instead of over other pieces?
3) How do I pause between two testAnimation calls? (Not by sleeping, obviously.)
Update 2016-01-14 (see also the Comment section):
I tried two things with flushAnimations:
1) Use a function like this:
private void flushAnimations(Form f) {
f.getAnimationManager().flushAnimation(() -> {});
}
and call this between successive animations. This doesn't work.
2) Nested flushAnimations:
testAnimation(piecesCnt, 0,9 , 9,0);
f.getAnimationManager().flushAnimation(() -> {
testAnimation(piecesCnt, 9,0 , 0,9);
f.getAnimationManager().flushAnimation(() -> {
testAnimation(piecesCnt, 1,0 , 9,8);
f.getAnimationManager().flushAnimation(() -> {
testAnimation(piecesCnt, 9,8 , 1,0);
});
});
});
This does seem to work on iOS but not on my Android device: usually after the second animation the screen flickers and jumps to the next state instead of animating. Apart from that it is not a nice solution.
Then I tried the UITimer solution:
blockUI(piecesCnt);
new UITimer(() -> { testAnimation(piecesCnt, 0,9 , 9,0); }).schedule(2000, false, f);
new UITimer(() -> { testAnimation(piecesCnt, 9,0 , 0,9); }).schedule(3500, false, f);
new UITimer(() -> { testAnimation(piecesCnt, 1,0 , 9,8); }).schedule(5000, false, f);
new UITimer(() -> { testAnimation(piecesCnt, 9,8 , 1,0); }).schedule(6500, false, f);
new UITimer(() -> {
unblockUI(piecesCnt);
}).schedule(8000, false, f);
private boolean blocked = false;
private void blockUI(Container piecesCnt) {
blocked = true;
int n = piecesCnt.getComponentCount();
for (int i=0; i<n; i++) {
piecesCnt.getComponentAt(i).setDraggable(false);
}
}
private void unblockUI(Container piecesCnt) {
...
}
This works but is also not a very desirable solution. I have a function 'autoplay' that replays an entire game consisting of >100 moves, each move consisting of 1 or more animation steps. The user can interrupt this process by pressing a stop button.
I would very much like to see how the Poker and Solitaire (Autoplay!) demos should be coded with the new animation handling.
Please take a minute to follow this link to see what kind of functionality I am talking about: http://toernooibase.kndb.nl/opvraag/applet.php?taal=1&kl=46&Id=4579&r=10&jr=16&wed=845502. Just press the autoplay button ('>') below the board. (My app can also play the game, and you can set it to think for say 1 minute per move, during which the GUI is blocked.)
I saw that the Developer Guide was updated Jan 13, and now has a chapter/appendix on Casual Game Programming. This is nice, although the CN1Poker version it lists still doesn't properly work on an Android device: the dealing cards animation shows the cards mostly jumping and sometimes sliding to their positions. (It works fine in the Simulator and on iOS devices.)
How can you say it is 'actually MUCH simpler to create a portable animation now'? I think in my case it actually just became much harder. I need an alternative for the old approach which is also used in the poker and solitaire demos: use animateLayoutAndWait and have no add/remove actions during an animation (also made sure by program logic).
As a basic subscriber (for 3 years now) I have to use the latest CN1 version, but with the current CN1 version I no longer know how to code this. I think this is a quite fundamental issue as all games use functionality like this.
I'm kinda new to the dev scene, I'm in the middle of an Android project.
I am trying to utilise the mobile phone camera flash. I'm trying to make it flash on and off in a repetitive motion. Below is a clip from my .java file.
public void clickGo(View view) {
Bundle newtempo = getIntent().getExtras();
int tempo = newtempo.getInt("tempoData");
int scaledTempo = 60000/tempo;
while (true) {
long futureTime1a = System.currentTimeMillis() + (100);
long futureTime1b = System.currentTimeMillis() + (scaledTempo - 100);
while (System.currentTimeMillis() < futureTime1a) {
setFlashlightOn();
}
while (System.currentTimeMillis() < futureTime1b) {
setFlashlightOff();
}
}
Let me explain what's going on...
So I've gained data from another activity then scaled it to a milleseconds value.
I've put the rest of the algorithm in a while(true) loop, just until I can get it working properly. I set two times, one with 100 milliseconds, and one with the scaled millesecond value MINUS the 100 milliseconds.
I then apply these two timings to turn the flash on then off.
In theory, this should work. I have data inputted from another activity which scales the number into milliseconds as shown. The concept does work, as lower numbers and higher numbers make the flash beat slower and quicker on my phone. However, the precision is my issue. When I play a click beat to the same time of the app, it's easy to tell that some flashes come in slower, or last longer.etc. I was wondering what this could possibly be? I've stripped down most of the code to a completely bare script (as I thought it could be a processing issue). It could also be the way I've implemented the time feature - if anyone else has a more efficient way, I would love to hear it!
As I said at the beginning, I'm relatively new to the dev scene, so I would appreciate it if you could answer with this in mind :)
Thank you very much!
The internal clock for computers is somewhat unreliable in quick successions like what you want. I would recommend using a timer to achieve what you want.
I am in the extremely early stages of designing a game (so early that I haven't even committed to it yet). The idea is an RPG with a Quick Time Event for attacking and defending that relies on precise mouse movements or timed button presses to reduce damage taken or increase the damage of an attack (similar to Mario and Luigi or Paper Mario). I'm wondering the best way to go about programming a class that can handle this. Ultimately, I'd like to be able to write code such as this when I call the attack function, where all of the functionality of the QTE occurs in a single function call;
//Example code.
int attackPower = 23;
double qteSucessPercent = -1;
//more code
if(e.getSource == player.sword()) //when the player chooses to execute a sword attack.
{
qteSucessPercent = QTE.Jump();
if(qteSucessPercent< 0)
throw BadQTEException;
else if(qteSucessPercent>= .9)
player.attack(enemy[0], attackPower*2);
else if(qteSucessPercent>= .75)
player.attack(enemy[0], attackPower*1.5);
else if(qteSucessRate>= .5)
player.attack(enemy[0], attackPower);
else
System.out.println("Attack Failed");
}
This class needs to do several things.
It needs to be able to draw itself.
The QTE class needs to be able to handle key pressing or mouse motion events. I can handle the code for each type of QTE I wish to implement, but they need to be able to detect, on their own, where the mouse is and what buttons are being pressed.
Whatever it is drawing needs to delete itself once the QTE is over.
There will be multiple types of Quick Time Events. Each one will be drawn differently, have different victory conditions (one may require you to hit a sequence of buttons in the correct order, another may make you press a single button in rapid succession as many times as you can, ect), and modify the attack in various ways. The basic design of all QTEs is that they return a double value between 0 and 1, depending on how well the player did (generally, the higher the number, the better; if the attack returns 0, then the QTE received no input at all). In some situations, the QTE may be pass/fail, but the rest of the program is just watching for a non-0 number to be passed from the function call. For the sword, the attack's power is being modified by how well you do.
I know Swing isn't thread-safe (which, to my knowledge, means components won't update properly if you try to activate parts of their code from a thread other than the one you called them with, meaning I can't have two blocks of code executing at the same time if I want both sets of code to display animations), which is why I've written the code the way I have. The main thread gets to line 6, and executes QTE.Sword(). Until QTE.Sword() returns (which could be as long as five seconds), the rest of the program will freeze and not animate. I plan to use this to my advantage to achieve a bullet time effect, where the only thing animating is the QTE and the players and enemies remain stationary - though if I wanted an animation, like for a Mario and Luigi-like jump QTE, I'd set the player's sprite to be an animated gif that only plays once and only for as long as the QTE goes off.
Note that I am NOT ASKING FOR CODE. I'm asking for either pseudo-code or just a paragraph explanation of how I could program this. I think I can find a dead, open-sourced project on Github or Google Code and figure out the basics of the rest of the engine from there, but this is really the sticking point for me. Also, I am not asking for help handling mouse movements or keyboard presses. I have enough knowledge to code these on my own - I'm just not sure how to implement this in the context of an RPG. I know this isn't really stackoverflow's thing, and this question will probably get deleted, but I figure this is the best place to ask this sort of thing.
I've read a few articles about dead reckoning, but it's still a bit confusing to me.
I'm pretty sure I understand the concept of point-and-click movement, but how would I update keystroke movement between the client and server, when the end-point of the movement is unknown?
How would you estimate where the player is going (server-side) if there is no end-point?
Let's start with dead reckoning. Try to think about it on a straight line where there is no left or right movement.
You are at point A and want to get to point B. You know the distance to point B so you can compute how much acceleration and velocity it will take to get there. Dead Reckoning works the other way. You are at point A and will move at a set speed to get near point B.
In the video game world they use this method all the time. So don't think about it as you're moving to point B you're just moving towards point B in increments because in like a FPS your point B will constantly moving. When in fact its really only moving in increments in the direction of point B.
Once you get moving forward then you can start worrying about left/right and up/down which will follow the same principle just in different directions.
As for implementing this you have 2 options.
One way, you could make this calculation on the client side then send the new position to the server. Then update what everyone else sees on screen.
The other way which I think is better you can make all these calculations on the server side and just receive an update where you ended up. X-Box live makes one of the consoles the host so that machine is running all the software and the external users are just firing events. This is why you'll hear people complain about having an unfair host advantage.
Now let's look at some code. This script comes from the Unity Sdk standard install package.
/// This script moves the character controller forward
/// and sideways based on the arrow keys.
/// It also jumps when pressing space.
/// Make sure to attach a character controller to the same game object.
/// It is recommended that you make only one call to Move or SimpleMove per frame.
var speed : float = 6.0;
var jumpSpeed : float = 8.0;
var gravity : float = 20.0;
private var moveDirection : Vector3 = Vector3.zero;
function Update() {
var controller : CharacterController = GetComponent(CharacterController);
if (controller.isGrounded) {
// We are grounded, so recalculate
// move direction directly from axes
moveDirection = Vector3(Input.GetAxis("Horizontal"), 0,
Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButton ("Jump")) {
moveDirection.y = jumpSpeed;
}
}
// Apply gravity
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller
controller.Move(moveDirection * Time.deltaTime);
}
So in this example we have speed which is set to a constant. So when moving in a direction we will travel in that Vector at a constant rate with no care about where point B is located.
Jump speed is how fast will we move in the y axis in the positive direction and gravity in the negative direction stopping at point 0.
So, How can you use this? You could build a server script that executes a move action and have a client side controller that passes the direction information to the server.
So lets say on the client side action is key press down, you send a call to the server to move you in the direction selection and the server will keep you moving you in that direction until action key press up or a change in direction from another input.
I hope this helped.
Let's see... I understand you know how to code, but not what, am I right?
You can feed the keystrokes directly to the server and let it do all the work. The server has no need to know where you are heading, it has your coordinates and direction and that's all it will need, unless you have server-handled AI. In the later case, you can do something similar to raycasting in Unity, start checking what is straight ahead and see if it is anything of interest, if so you know the potential destination.
It is safe to constantly send back to the client all his data, so it is always up to date. If you believe this will strain your connection you can do that every 50ms or as often as you believe is safe, and for smooth function estimate everything on the client side too. Make sure the server does all the collision detection and all the mechanics not related to the UI, or else the game will be prone to client-side malfunction or malicious tampering.
If you do have to look at where the player might be going, you can use a few approaches, you could either have a number of virtual cubes in the world which keep track of what is inside them, which will simplify finding what's ahead in terms of resources, or you could check everything there is, which is rather heavy on the machine, but this adds some other complexities too. In the first case do not forget to stop looking once you hit an obstacle.
You can also calculate the angle between the player's direction and other items of importance to check what else might be on his mind.
The question about UDP has already been answered, plus I'm sure Wikipedia has a helpful book on UDP and TCP, I have nothing to add.
The explanation of dead reckoning was also quite satisfactory, I hope I added other angles to the concept.
I hope I helped, if you need any clarifications or any other help feel free to contact me, if I was less than unhelpful then feel free to downvote, I study computer engineering and am creating my second game for PC so maybe I have ran into some problem already and can share the knowledge.