How do I use implemented Animation in LibGDX? I know, that the documentation can be found here, but when I want to get a frame out of the Animation, I need to use stateTime, which isn't explained anywhere in the documentation. So the question is, what is stateTime in terms of LibGDX's Animation?
There is some more doc on the getKeyFrame method documentation:
Returns a TextureRegion based on the so called state time. This is the amount of seconds an object has spent in the state this Animation instance represents, e.g. running, jumping and so on.
(This documentation doesn't really make any sense to me either.)
But, the Animation.java source is readable. It looks like it boils down to
getKeyFrameIndex
which divides the stateTime by frameDuration (which is a parameter of the constructor -- how long each frame lasts) to compute an array index. getKeyFrameIndex does different things for looping or non-looping sequences, but basically it takes the array index to look up the right key frame in the sequence to display.
So the "stateTime" is the input to pick a key frame from your Animation. The documentation is assuming you have one Animation instance for "running" and another for "jumping" (these are the "states" its referring to). To find the right key frame within an Animation, you tell it how long you've been in this "state". So, if you've been in the "running" Animation instance for 1.2 seconds, it does some math to figure out which key frame to show (say you've initialized the instance with 30 frames that show for 0.0333 seconds and loop -- it picks the 6th frame).
The wiki https://github.com/libgdx/libgdx/wiki/2D-Animation has some more details and an example, but doesn't address this directly, either.
animationFrames = walkSheetArray[moveDirection];
animation = new Animation(1f / 5f, animationFrames);
myAnimatedActor = new AnimatedActor(animation);
stage.addActor(myAnimatedActor);
public class AnimatedActor extends Image {
private float stateTime = 0;
Animation animation;
public AnimatedActor(Animation animation) {
super(animation.getKeyFrame(0));
this.animation = animation;
}
#Override
public void act(float delta) {
((TextureRegionDrawable) getDrawable()).setRegion(animation.getKeyFrame(stateTime += delta, true));
super.act(delta);
}
}
Related
I'm quite new to Processing.
I'm trying to make Processing randomly play a video after I clear the screen by mouseclick, so I create an array that contain 3 videos and play one at a time.
Holding 'Spacebar' will play a video and release it will stop the video. Mouseclick will clear the screen to an image. The question is how can it randomize to another video if I press spacebar again after clear the screen.
I've been searching all over the internet but couldn't find any solution for my coding or if my logic is wrong, please help me.
Here's my code.
int value = 0;
PImage photo;
import processing.video.*;
int n = 3; //number of videos
float vidN = random(0, n+1);
int x = int (vidN);
Movie[] video = new Movie[3];
//int rand = 0;
int index = 0;
void setup() {
size(800, 500);
frameRate(30);
video = new Movie[3];
video[0] = new Movie (this, "01.mp4");
video[1] = new Movie (this, "02.mp4");
video[2] = new Movie (this, "03.mp4");
photo = loadImage("1.jpg");
}
void draw() {
}
void movieEvent(Movie video) {
video.read();
}
void keyPressed() {
if (key == ' ') {
image(video[x], 0, 0);
video[x].play();
}
}
void mouseClicked() {
if (value == 0) {
video[x].jump(0);
video[x].stop();
background(0);
image(photo, 0, 0);
}
}
You have this bit of logic in your code which picks a random integer:
float vidN = random(0, n+1);
int x = int (vidN);
In theory, if you want to randomise to another video when the spacebar is pressed again you can re-use this bit of logic:
void keyPressed() {
if (key == ' ') {
x = int(random(n+1));
image(video[x], 0, 0);
video[x].play();
}
}
(Above I've used shorthand of the two lines declaring vidN and x, but the logic is the same. If the logic is harder to follow since two operations on the same line (picking a random float between 0,n+1 and rounding down to an integer value), feel free to expand back to two lines: readability is more important).
As side notes, these bit of logic look a bit off:
the if (value == 0) condition will always be true since value never changes, making both value and the condition redundant. (Perhaps you plan to use for something else later ? If so, you could save separate sketches, but start with the simplest version and exclude anything you don't need, otherwise, in general, remove any bit of code you don't need. It will be easier to read, follow and change.)
Currently your logic says that whenever you click current video resets to the start and stops playing and when you hit the spacebar. Once you add the logic to randomise the video that the most recent frame of the current video (just randomised) will display (image(video[x], 0, 0);), then that video will play. Unless you click to stop the current video, previously started videos (via play()) will play in the background (e.g. if they have audio you'll hear them in the background even if you only see one static frame from the last time space was pressed).
Maybe this is the behaviour you want ? You've explained a localised section of what you want to achieve, but not overall what the whole of the program you posted should do. That would help others provide suggestions regarding logic.
In general, try to break the problem down to simple steps that you can test in isolation. Once you've found a solid solution for each part, you can add each part into a main sketch one at a time, testing each time you add something. (This way if something goes wrong it's easy to isolate/fix).
Kevin Workman's How To Program is a great article on this.
As a mental excercise it will help to read through the code line by line and imagine what it might do. Then run it and see if the code behaves as you predicted/intended. Slowly and surely this will get better and better. Have fun learning!
So I am animating an avatar, and this avatar has its own animator with states and such.
When interacting with props, the props itself has an animator with states in it. In both case, I transition to some animations through parameters in the animator (bool type).
For example, for a door, the character will have "isOpeningDoor", while the door will have "isOpen".
Now the question: when I change the value on an animator on GO1, and then change the bool on GO2; do the first animation finish and then the second start? Because in my case, it does not happen; they start almost at the same time.
void OnTriggerEnter (collider door)
{
if (door.gameObject.tag=="door")
{
GOAnimator1.SetBool("isOpeningDoor", true);
GOAnimator2.SetBool("isOpen", true);
}
}
I believe that I am doing it wrong, since I change the parameter on the animator, but I do not check for the animation to end; is this even possible or am I doing something not kosher?
I really think it might be doable!
As you have it in your code now, the animations on GO1 and GO2 start at almost the same time because that's how it's written. The OnTriggerEnter() function will complete the execution in the frame it is called, and return the control to Unity.
What I think that might help you are coroutines and sendMessage between gameobjects:
http://docs.unity3d.com/Manual/Coroutines.html
http://docs.unity3d.com/ScriptReference/GameObject.SendMessage.html
The idea is to:
Create a coroutine in GO2 that waits an amount of time until it sets the GOAnimator2 variable to activate the door animation.
Create a function in GO2 that calls the aforementioned coroutine
From the OnTriggerEnter() send a message to GO2 to execute the newly created function
It reads complicated, but it's fairly simple. The execution would be like this:
1.Code for the coroutine:
function GO2coroutine(){
float timeToWait = 0.5f; //Tweak this
for ( float t = 0f; t < timeToWait; t+=time.deltaTime)
yield;
GetComponent<Animator>().SetBool("isOpen",true);
}
Code for the function calling it:
function callCoroutine() {
StartCoroutine("Fade");
}
And the code modification for your OnTriggerEnter():
void OnTriggerEnter (collider door)
{
if (door.gameObject.tag=="door")
{
GOAnimator1.SetBool("isOpeningDoor", true);
GO2.SendMessage("callCoroutine");
}
}
I didn't have a chance to test the code, so please don't copy paste it, there might be slight changes to do.
There is another way, but I don't like it much. That is making the animation longer with an idle status to wait for the first game object animation to end... but it will be a hassle in case you shorten the animation because you have to, or have any other models or events.
Anyway, I think the way to go is with the coroutine! Good Luck!
I'm a new in Unity and making my first 2D game. I seen several topics on this forum in this issue, but I didn't found the solution.
So I have a lovely shooting animation and the bullet generation. My problem, I have to generate the bullet somewhere at the middle of the animation, but the character shoots the bullet and the animation at the same time, which killing the UX :)
I attached an image, about the issue, this is the moment, when the bullet should be initialized, but as you can see it's already on it's way.
Please find my code:
The GameManager update method calls the attackEnemy function:
public void Awake(){
animator = GetComponent ();
animator.SetTrigger ("enemyIdle");
}
//if the enemy pass this point, they stop shooting, and just go off the scren
private float shootingStopLimit = -6f;
public override void attackPlayer(){
//animator.SetTrigger ("enemyIdle");
if (!isAttacking && gameObject.transform.position.y > shootingStopLimit) {
isAttacking = true;
animator.SetTrigger("enemyShoot");
StartCoroutine(doWait());
gameObject.GetComponentInChildren ().fireBullet ();
StartCoroutine (Reload ());
}
}
private IEnumerator doWait(){
yield return new WaitForSeconds(5);
}
private IEnumerator Reload(){
animator.SetTrigger ("enemyIdle");
int reloadTime = Random.Range (4,7);
yield return new WaitForSeconds(reloadTime);
isAttacking = false;
}......
My questions:
- How can I sync the animation and the bullet generation ?
Why not the doWait() works ? :)
Is it okay to call the attackPlayer method from the GameManager update ?
The enemies are flynig from the right side of the screen to the left, when they reach the most right side of the screen, they became visible to the user. I don't know why, but they to a shooting animation (no bullet generation happen )first, only after it they do the idle. Any idea why ?
Thanks,
K
I would suggest checking out animation events. Using animation events, you can call a method to instantiate your bullet.
To use Mecanim Animation Events you need to write the name of the function you want to call at the selected frame in the "Function" area of the "Edit Animation Event" window.
The other boxes are for any variables that you want to pass to that function to trigger whatever you have in mind.
Triggering/blending between different animations can be done in many different ways. The event area is more for other things that you want to trigger that are not related to animation (e.g. audio, particle fx, etc).
I'm trying to make a game with the XNA library. I want a sprite to throw a fireball to hit falling asteroids. But I have a problem with pressing the concrete key: I want to throw fireballs, for example, with one second between throws.
I want to measure the time difference between creating instances. How can I do that?
UYou can use the ElapsedGameTime property of the gameTime variable passed to the Update method like this:
const float shootTimer = 1.0f;
float elapsedTime = 0f;
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
elapsedTime += gameTime.ElapsedGameTime.TotalSeconds;
if(elapsedTime >= shootTimer && /* Your logic to see if you should shoot a fireball */ )
{
// Shoot the fireball!
elapsedTime = 0f;
}
base.Update(gameTime);
}
Basically, what you are doing in the above code is setting a minimum value (seconds) that need to pass between each shot.
Then you create a variable that will store the amount of time that has passed between each shot.
In the Update method, you add the time between each Update call and then check if it is bigger than the timer, and if it is, then you shoot and reset the elapsed time.
Note: I wrote that piece of code out of the top of my mind so it may have some minor issue.
Each call to Update of your main Game class or any GameComponent receives an instance of GameTime as an argument. Its property ElapsedGameTime can be used to accumulate the passage of time.
I've been trying to add an animation to my bubble chart in my UI but have ran into some issues. I'm trying to increase the size of the bubble at different stages to show a gradual change but its just drawing it at its full size instead of at every stage.
Here's the timeline code
tl.getKeyFrames().add(
new KeyFrame(Duration.seconds(30),
new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
//for (XYChart.Series<Number, Number> series : liveDemoBubbleChart.getData()) {
for(int i = 10; i>0; i--) {
series1.getData().add(new XYChart.Data(5,5, ProjectProperties.getInstance().getSportsTweetsCount()/i));
}
The sport tweet count is the final value for the bubble and I'm dividing it by different amounts to show the build up to the final value.
Does anyone have any ideas as to why this isn't working as I expect?
The KeyFrame taking a Duration and an EventHandler<ActionEvent> simply executes the EventHandler's handle(...) method after the time specified by the Duration. So your code causes the entire for loop to be executed after a pause of 30 seconds.
You probably want to supply a KeyValue instead, providing a property to be set and the target value after 30 seconds. The value will then be interpolated at times in between. Have a look at the tutorial to see if it helps.