this is an algorithm/data structure question about making different animations at the same time. For example, a ball is falling down one pixel in a millisecond, a bullet is moving 5 pixels in a ms, and a man is moving 1 pixel in 20 milliseconds. And think that there are hundreds of them together. What is the best way of putting all animations together, moving what we need to move in one function call, and removing the ones whose animation is completed? I don't want to create a thread for each one. What I want to do is to create one thread moving all items and sleeping until an object needs to be moved.
Note: I'm using Java/Swing, printing objects and images in JPanel.
I recently did something similar in Python. I don't know if this is the best method, but here's what I did.
Create an abstract Event class with the following public interface:
tick - calculates how much time has passed since the last tick. Perform work proportional to that time span. This should be called frequently to create the illusion of smooth movement; maybe sixteen times a second or so.
isDone - returns true when the Event has finished occuring.
Make a subclass of Event for anything that takes more than one frame to finish. Rotating, scaling, color changing, etc. You might create a TweenEvent subclass of Event if you want to move an image from one part of the screen to another. During each tick, redraw the image in a position farther away from the original position, and farther towards the destination position.
You can run many Events concurrently, like so:
Array<Event> events = new Array<Event>();
//add a bunch of TweenEvents here - one for a bullet, one for a ball, etc.
while(True){
Sleep(1/16);
for(Event e in events){
e.tick();
if (e.isDone()){events.remove(e);}
}
}
Related
I cannot figure out how to apply multiple animatedupdate 'tour steps' in KML. Please help. All data is linked here to demonstrate the problem. In this example.. first open the link to the rail model - this has the snap shot that takes you (the user) to the project area. Zoom in on the northern most rail curve. Then open the other KMZ - named DOC02 ... DOC02 provides the animation (Tour) ... play the tour (part 2) and ... the hopper goes a short way around the curve, although the tour data has enough steps to almost complete the entire curve - Why are only the first 3 animated updates applied? ... At first I tried to use the guides referred to by countless other stack overflow posts on this topic. But that result was even worse. The 3d model has a location ID of t1 and an orientation ID of t2. When I use these as target ID in the animated updates - Yuck! the animation is totally incorrect, model goes directly to the end of the curve. So. I added ID's at every transform change. This idea provided better animation but the animation only uses the first 2 animated updates. If all this text just gives people a headache, just let me know and I will provide a video ... I probably will make one later today anyway. Thanks for your patience.
overhead rail model in KMZ Google Earth
3d hopper model set go move around curve in KMZ Google Earth
https://developers.google.com/kml/documentation/touring#gxanimatedupdate-and-the-tour-timeline
The above link will take you to the kml documentation page which specifically states that:
"Animated updates run parallel to the timeline - that is, the tour continues directly to the next tour primitive in the playlist, while the animated update is taking place. The gx:duration controls the length of time it takes for the update to occur, but doesn't delay the next tour primitive. To allow an animated update to complete before the next action takes place, insert a gx:Wait, with a duration equal to the duration of the update, between the animated update and the following tour primitive. In addition, an animated update will be truncated if its duration extends beyond that of the last gx:FlyTo or gx:Wait element. You can either change the appropriate gx:duration values, or insert an additional gx:Wait element at the end of the playlist to give the animated update time to complete.
Which essentially is telling you that AnimatedUpdate will not keep the tour going. Only flyTo and Wait will prolong the tour. The reason why your tour ends after the first 2 animations is because that is all the animations it can get through within the tour length.
Basically, to fix your issue, insert a gx:wait with a duration >= your AnimatedUpdate's duration after EACH AnimatedUpdate. This will prolong the tour and allow your animations time to complete before the tour ends. (because the gx:wait prolongs the tour)
(Alternatively, add a long enough Wait at the beginning, much like you did with the end.)
Also see: https://developers.google.com/kml/documentation/touring#tour-timelines
I have a game that requires the player to roll two die. As this is a multiplayer game, the way I currently do this is have 6 animations (1 for each die's outcome). When the player clicks a button, it sends a request to my server code. My server code determines the die's outcome and sends the results to the client. The client then plays the corresponding animations.
This works ok, but has some issues. For instance, if the server sends back two of the same values (two 6's, for example) then the animations don't work correctly. As both animations are the same, they overlay each other, and it looks like only one die was rolled.
Is there a better way to do this? Instead of animations, using "real" dice? If that's the case, I always need to be sure to "pre-determine" the outcome of the dice roll, on the server. I also need to make sure the dice don't fall off the table or jostle any of the other player pieces on the board.
thanks for any ideas.
The server only needs to care about the value result, not running physics calculations.
Set up 12 different rolling animations:
Six for the first die
Six for the second die
Each one should always end with the same modeled face pointing upwards (the starting position isn't relevant, only the ending position). For the latter steps you'll probably want to adjust the model's UV coordinates to use a very tall or very wide texture (or just a slice of a square one). So not like this but rather all in a line 1-2-3-4-5-6.
The next step is picking a random animation to play. You've already got code to run a given animation, just set it to pick randomly instead of based on the die-roll-value from the server:
int animNum = Mathf.Floor(Random.Next()*6);
Finally, the fun bit. Adjusting the texture so that the desired face shows when the animation is done. I'm going to assume that you arrange your faces along the top edge of your square texture. Material.SetTextureOffset().
int showFace = Mathf.Floor(Random.Next()*6); //this value should come from the server
die.renderer.material.SetTextureOffset(1f/6 * showFace,0);
This will set the texture offset such that the desired face will show on top. You'll even be able to see it changing in the inspector. Because of the UVs being arranged such that each face uses the next chunk over and because textures will wrap around when reaching the edge (unless the texture is set to Clamp in its import settings: you don't want this here).
Note that this will cause a new material instance to be instantiated (which is not very performant). If you want to avoid this, you'll have to use a material property block instead.
You could simulate the physics on the server, keep track of the positions and the orientations of the dice for the duration of the animation, and then send the data over to the client. I understand it's a lot of data for something so simple, but that's one way you can get the rolls to appear realistic and synced between all clients.
If only Unity's physics was deterministic that would be a whole lot easier.
I'm making a snake game and on every tick the snake moves. because the snake is moving a whole unit on each tick the animation is jumpy. The game is on an invisable grid so the snake can only change directions at specific points.
Would it be considered better practice to have a timer that will move the snake a pixels at a time counting it with a variable, and on every n tick run the code to change direction. Or is it better to have two separate timers; one for move the snake a pixel at a time and another for changing the snakes direction?
Essentially, you're creating a "game-loop" to update the displayList (in Actionscript) and re-draw your view. When the game gets complex, Timers and listening for ENTER_FRAME events will be constrained to the flashplayer settings for screen refresh (i.e. it's FPS) and the CPU's rendering based on what it is tasked to process.
For frame-rate independent animation, you should probably use a combination of ENTER_FRAME to track milliseconds and GetTimer() calls to more accurately (to the millisecond) call animations and normalize the experience across a variety of platforms.
Basically, listen for the ENTER_FRAME event, check the current milliseconds since the last update and if it exceeds your refresh-rate (in terms of milli's), fire off the animation/state update: check for snake collision detection with a "direction-block" - handle if true, then update the snake's movement / position / state.
Flash updates the Display List at whatever it's settings, and CPU / machine-dependent issues are. The key, I've found, is to make sure you're normalizing the speed of updates to make the experience consistent. Timer's have their usage, but can cause memory performance issues. ENTER_FRAME is synced to the main timeline / frame-rate settings.
For a dated, but interesting discussion 3 years ago, check out this post from actionscript.org.
I am implementing a turn based game, there are two sides and each side has several units, at each specific moment only one unit can move across the board.
Since only one unit can move at a time, after i figure out where it should go, as far as the simulation is concerned it Can instantly be teleported there, but playing the game you would want to see the unit moving so that you realise who moved and where he went.
The question is, would you put the movement algorithm (eg interpolating between 2 points in N seconds) in the model and then have the view show the unit in the interpolated position without even knowing that it is moving, or teleport the unit and notify the view that it should show the unit moving as best as it wants.
If you would take the second approach, how would you keep the simulation from running too far ahead of the view, would you put the view in command of resuming the simulation after the movement ended?
Thanks in advance, Xtapodi.
Ah, yet another example that reminds us that MVC was never originally designed for real-time graphics. ;)
I would store the current position and the previous position in the model. When the object moves, the current position is copied into the previous position, the new position is copied into the current position, and a notification is sent to the view that the model has changed. The view can then interpolate between the old and the new position accordingly. It can speed up, slow down, or even remove the interpolation entirely based on the specific view settings, without requiring any extra data to be stored within the model.
Rather than storing the current position and the previous position, you could instead just store the last move with each unit, and the move itself contains the previous position. This is probably more versatile if you ever need to store extra information about a move.
What you probably want is to have the unit image move each frame. How far to move the image each frame is similar to your interpolation.
unitsPerSecond = totalUnits / (framesPerSecond * totalSeconds)
So if I want to move an image from position 0 to position 60 in 2 seconds and my framerate is 30, I need to move 60 units in 60 frames, therefore my speed is 1. So each frame, I move the image 1 unit, and if moving the unit will take me beyond my destination, simply set my location to my destination.
The data model in my program has a number of discrete states, but I want to animate the transition between these states. While the animation is going on, what the user sees on the screen is disconnected from what the underlying data is like. Once the animation is complete, they match up again.
For example, let's say we have a simple game where Snuffles the bunny hops around on a 2D grid. The model of Snuffles contains integer x/y coordinates. When the player tells Snuffles to hop north, his y-coordinate is decremented by one immediately. However, on the screen, Snuffles should at that point still be in his old location. Then, frame by frame, Snuffles proceeds to hop over to his new location, until he is shown in the location his model states.
So usually, when we draw Snuffles, we can just look up his coordinates in his model. But when he's hopping, that coordinate is wrong.
If there is only ever one thing moving on the screen, I can just about get away with freezing the entire game state and not allowing the user to do anything until Snuffles has finished hopping. But what if there is more than one bunny on the screen?
It gets worse if elements interact, merge or split. If Snuffles magically merges with a hat to become a potato, at which point does the data model delete the bunny and the hat, and add the potato? If it does so immediately, the view instantly loses access to information about Snuffles and the potato which it still needs to draw the animation of the magical merger.
I have come across this problem multiple times while implementing animated GUIs, especially games, and have found no satisfactory solution.
Unsatisfactory ones include:
Do the changes immediately, but then suspend any further changes in the model until the animation has resolved. Makes things unresponsive and doesn't work if more than one thing can move or things interact in complex ways.
Merge the model and the view - Snuffles gains floating-point coordinates, and probably a z-coordinate to indicate how far up he is. The model's rules become massively more complex as a result, as the model can no longer make concise statements like "you cannot hop north if there is a wall at (x, y - 1)". Any change to the rules takes much longer, and development slows to a crawl.
Keep what amounts to a duplicate of the data in the view. SnufflesModel has integer coordinates, but SnufflesSprite has floating-point ones. End up duplicating some of the model rules in the view and having to keep them in sync. Spend lots of time debugging to make sure that SnufflesModel and SnufflesSprite don't de-sync under some rare circumstance.
My best bet at the moment is option 3, but it hardly strikes me as elegant. Thoughts?
You would need a stronger model to account for the time component of changes:
Each sprite needs to maintain a queue of animation actions it is supposed to carry out. Adding animations to the queue should be a zero-time action (game time). Queued animations proceed on a frame-by-frame basis when they get a tick from the animation clock. Queuing lets you separate the model from the graphics subsystem and the animations.
Each animation in the queue carries with it a model action to perform when the animation is complete. Some languages make that easier, e.g. with anonymous functions in C# or JavaScript. In other languages, you could use a callback instead. The model action lets you specify how the model would change when the animation completes.
Sprites can carry high resolution coordinates (e.g. floating point), while the model stays with integer ones. Sprites don't need to know anything about the game rules though -- the queued animation-completion model-actions deal with that.
Model entities should be able to account for a transitional states: appearing, disappearing, and moving. This lets you avoid checking the rules for objects in transition.
To implement Snuffle's quest, you could then:
User asked to move Snuffle north? -(1) check that the rules allow the move, (2) queue a move animation on Snuffle's sprite, coupled with a landing model action. Put the bunny's model into a transitional moving state.
Snuffle's landing model action brings the bunny's model back to a normal state, and checks the landing spot and the rules. Finding a hat, it queues a potato appearance animation (the "merger") and two disappearance animations for the bunny and hat.
The model actions for the disappearance animations delete the bunny and hat when complete.