My page transitions looking clunky - how should I do page to page animations? - windows-phone-7

I have a an app that has several pages. When I move between pages (using the NavigationService) I have an animation that makes the text fly out - think standard WP animations or Zune Client.
The animations themselves look reasonable but the problem seems to be the gap between when the animation finishes and the new page is loaded. There seem to be a slight delay when all the elements have completed the fly out and when the new page is shown.
It's making my page transitions feel a little clunky.
How can I make the target page appear the instant the transitions have completed to avoid this?
fwiw - i'm just using the navigation service to navigate between pages.
this.NavigationService.Navigate(new Uri("/SomePage.xaml", UriKind.Relative));

I recently was trying to solve the same problem in one of my applications. My solution involved two main pieces:
Shifting a large chunk of work from page navigation time to app startup time.
Hiding the unavoidable work that couldn't be moved to app startup time by using smoke and mirrors in my page transition animations.
Moving work from page transition time to app startup time
In my app, I have a main page that contains a long list of items, and then a details page that contains a lot of rich detail on a particular item. Navigating forward from my main page to the details page was taking a long time and looked really unpolished. The main problem was that it was taking a substantial amount of time (ie: well over one full second) just to parse the XAML and instantiate the new page. To get around this, I took the entire contents of my details page and moved it into a UserControl and I instantiate a global instance of this control on application startup. The actual details page is now an empty shell containing the minimal XAML required to instantiate the page. In the code behind for that page, I handle adding the singleton UserControl as the sole child element of the page, and then in the OnNavigatedFrom handler, I remove the UserControl from the page. This allows me to shift the XAML parsing and scene initialization logic from page navigation time to app startup time. Now obviously this makes my application take longer to startup, but given the usage pattern of my app that tradeoff is well worth it.
Using animation trickery to hide the unavoidable work
The previous steps didn't completely solve the problem however as there was still some time needed to bind/set all the actual content of the details page, as well as the time required on the compositor thread to do the initial layout and rendering of the page. Unfortunately, there isn't a whole lot you can do about this. I attempted to work around it as much as possible with smoke and mirrors by playing with my page transition animations. For instance, I originally had an animation that would rotate the contents of the page off the screen using a full 90 degree rotation, and then rotate on the contents of the new page using another 90 degree rotation. I changed those to only rotate part way while simultaneously fading the opacity to/from 0. If this animation is performed quickly enough, the human brain then does an amazing job of filling in the blanks and tricks the viewer into believing that the page rotated all the way. My ForwardOut animation actually only rotates by 50 degrees, but the viewer doesn't really notice that, and in their mind they are still extrapolating the rest of the animation long after the real animation has completed. This helps mask the unavoidable work required during the page navigation.

Related

EaselJS and multi layered canvas system: performance tuning, game developing, event handling

I'm an engineer and we are currently porting our Red5 + Flash game into a Node.js + Easeljs html5 application.
Basicly: it's a board game, not an rpg. The layer system means we have multiple canvasses, based on functionally. For example there is a static background stage, with images. There is a layer for just the timers.
At default, all canvas size is 1920x1080, if needed we downscale to fit to the resolution.
The first approach used kinetic.js, but the performance fallen when the game got complex. Then we switched to easel, because it's abstraction level is lower, so we can decide how to implement some more function, not just use the provided robust one.
I was optimistic, but now it's starting to show slowness again, that's why I want to look deeper inside and do fine performance tuning. (Of course everything is fine in Chrome, Firefox is the problem, but the game must run smoothly on all modern browser).
The main layer (stage) is the map, contains ~30 containers, in each there is a complex custom shape, ~10 images. The containers are listening to mouse events, like mouseover, out, click. Currently, for example on mouseover I refill the shape with gradient.
Somehow, when I use cache, like the way in the tuts the performance get even worse, so I assume I'm messing up something.
I collected some advanced questions:
In the described situation when can I use cache and how? I've already tried cache on init, cacheUpdate after fill with other color or gradient, then stage.update(). No impact.
If I have a static, never changing stage cache doesn't make sense on that layer, right?
What stage.update() exactly do? Triggering the full layer redraw? The doc mentions some kind of intelligent if changed then redraw effect.
If I want to refill a custom shape with new color or gradient I have to completely redraw its graphics, not just use a setFill method, right?
In easel there is no possibility to redraw just a container for example, so how can I manage to not update the whole stage, but just the one container that changed? I thought I can achieve this with caching, cache all containers the just update the one that changed, but this way didn't work at all for me.
Does it make sense to cache bitmap images? If there are custom shapes and images in a container what is better? Cache the container or just the shape in container.
I found a strange bug, or at least an interesting clue. My canvas layers totally overlapping. On the inferior layers the mouseover listening is working well, but the click isn't on the very same container/object.
How can I produce a click event propagation to overlapped layers those have click listeners? I've tried it with simple DOM, jquery, but the event objects were far away from what canvas listeners wanted to get.
In brief, methods and props I've already played with bare success when tried tuning: cache(), updateCache(), update(), mouseEnabled, snapToPixel, clear(), autoClear, enableMouseOver, useRAF, setFPS().
Any answer, suggestion, starting point appreciated.
UPDATE:
This free board game is a strategy game, so you are facing a world map, with ~30 territories. The custom shapes are the territories and a container holds a territory shape and the icons that should be over the territory. This container overlapping is minimal.
An example mouse event is a hover effect. The player navigate over the territory shape then the shape is getting recolored, resized, etc and a bubble showing up with details about the place.
Basically, maximum amount of 1-3 container could change at once (except the init phase -> all at this time). Not just the animations and recoloring slow in FF, but the listener delay is high too.
I wrote a change handler, so I only stage.update() up on tick the modified stages and the stages where an animation is running (tweenjs).
In my first approach I put every image to the container that could be needed at least once during the game, so I only set visible flags on images (not vectors).
Regarding caching:
There are some strange caching-issues, somehow the performance can drop with certain sizes of the caching rectangle: CreateJS / EaselJS Strange Performance with certain size shapes
(2) Depending on how often you call stage.update();
(3)
Each time the update method is called, the stage will tick any
descendants exposing a tick method (ex. BitmapAnimation) and render
its entire display list to the canvas. Any parameters passed to update
will be passed on to any onTick handlers.
=> Afaik it rerenders everything if not cached
(4) Yes.
(5) No. (I don't know of any)
(6) If the content's of the container don't change often, I'd cache the whole container, otherwise the container will be reconstructed every frame.
I have a question though: Why do you use multiple canvases? How many do you use? I could imagine that using multiple canvases might slow down the game.
How many sprites do you use in total?
2: if your layer or stage doesn't change, don't call stage.update() for that layer (so it doesn't gets rerendered, gives me a much lower cpu!)
For example, keep a global "stagechanged" variable and set this to true when something has changed:
createjs.Ticker.addEventListener("tick",
function() {
if (stagechanged)
{
stagechanged = false;
stage.update();
}
});
(or do you already use this, as stated in your "update"?)
4: I found a way to update for example the fill color :)
contaier1.shape1.graphics._fillInstructions[0].params[1] = '#FFFFFF';
(use chrome debugger to look at the _fillInstructions array to see which array position contains your color)
5: I found a way to just paint one container :)
//manual draw 1 component (!)
var a = stage.canvas.getContext("2d");
a.save();
container1.updateContext(a); //set position(x,y) on context
container1.draw(a);
a.restore();

hiding movieclip, rendering performance

I'm developing a rendering engine for a game i am currently building..
I have a main camera (rectangle) that determines what needs to be rendered (thing within it's boundaires)
I am using a bitmap rendering method for the background and that all works fine.
but for the character i am using a movieclip over the top.
when the character goes out of the camera's view is it 100% neccesary to set visible=false?
atm the game is running at 30 FPS (as intended) and everything is sweet, i just wanted to ask out of curiosity.
Is flash clever enough to not bother with movieclip outside of the scene boundaires?
Thanks in advance,
Rory
According to http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e3e.html Flash won't render if an object is outside of Stage boundaries:
Display list
The hierarchy of display objects that will be rendered as visible
screen content by Flash Player and AIR. The Stage is the root of the
display list, and all the display objects that are attached to the
Stage or one of its children form the display list (even if the object
isn’t actually rendered, for example if it’s outside the boundaries of
the Stage).
In my experience display objects added to the stage cause a performance hit even if they are not rendered.
Setting visible to false causes a much lower performance hit, but still a small hit.
Removing unnecessary display objects from the display list is a documented performance tip from adobe as well.
Of course, if you only have a few dislay objects it might not be worth the effort, but if we talk about large amounts of display objects I strongly recommend removing them from the display list.

webkit slide in and slide out a page

I'm new to webkit animations and I have been trying out to do this kind of animation
http://demo.jeffrey-way.com/tutsMobile/#site.php?siteName=psdtuts
If you click the list element you will see page sliding in and sliding out.
I want to implement this animation to my app which is built with backbone.js, underscore.js, zepto.js
I could use jqTouch or jquery mobile but I would like to make it as light weight as possible, because I'm building it only for IOS. So thats way I wan't to implement it by my self.
Any hints to make this implementation or should I go with jqTouch?
In this example, there is some sort of (I hate to be vague...) ajax based content loading system. Take a look at the source:
<div data-role="page" id="article.php?siteName=psdtuts&origLink=http%3A%2F%2Fpsd.tutsplus.com%2F%3Fp%3D15026" class="ui-page ui-body-c">
When you first visit, that div doesn't exist. It's created by javascript when content is required, then filled with that content, then translated (animated) into the viewport.
Here is a step by step, deduced from a quick look at the page:
Base page is loaded, including css, javascript, nav list
Script is waiting for a nav item to be clicked.
Upon clicking, an ajax request is made to the content corresponding to the clicked item; determined by href="article.php?siteName=psdtuts&origLink=http://psd.tutsplus.com/?p=15081". My guess? This ajax request is getting content from the same place as psdtuts.com, likely in a database.
While that stuff is loading, javascript shows a loading animation. When loading is complete, it's hidden again.
Once the new content-filled div is created, it is given a default position with its left edge placed right outside of the right edge of the screen. Upon the event of being positioned, javascript then determines the view's dimensions and translates the div across the horizontal dimension. At the same time, the nav list is moved the same direction and distance.
When back is clicked, the view's dimensions are determined again (In case the window size changed) and the nav and content are translated to the right, hiding the content and showing the navigation again.
Repeat
I could be off from how this exact sample is being done, but... Well, this would work.
You wouldn't be that crazy to use a framework for something like this, but I can understand wanting to do a custom job. It would certainly be faster for users, but slower for you. Depending on your intent, that would be just fine.
edit: If you're only serving this to users with webkit, using a framework is even less necessary... If you're not worrying about cross browser support, there's really not a lot going on here that you couldn't accomplish easily with raw javascript.
The only reason I use jQuery for example, most of the time, is to ensure things work alright in most use cases. It just smooths so many things out... Even if 95% of the framework isn't being utilized, it's worth it when you've got a deadline.
I founded out one good example
http://andrew.hedges.name/blog/2009/05/29/animating-your-iphone-web-application

CALayer flickering when adding a foreground layer to IKImageBrowserView items with garbage collection on

I'm trying to implement a technique similar to the one in the ImageBrowserViewAppearance sample code from Apple (located here: http://developer.apple.com/library/mac/#samplecode/ImageBrowserViewAppearance/Introduction/Intro.html ), where CALayers are generated on top of the items in the IKImageBrowserView to customize the appearances of the objects in the image browser.
However, I'm getting a weird problem when I turn on garbage collection, and I can reproduce it in the Apple sample code. Simply turn on Garbage Collection in the target, and build and launch the ImageBrowserAppearance sample app. Then, add some photos to the image browser using the "Add Photos..." button.
Now, click on an empty portion of the IKImageBrowserView, and click and drag to start selecting multiple items in the browser view. As you drag the selection box around, you should notice that sometimes the pin and gloss overlay for some of the items flicker and briefly appear in the bottom-left corner of the IKImageBrowserView. All of the CALayers seem to do this occasionally, I've seen the white surrounding slide area flicker down into the bottom-left corner as well.
When I mimic the technique in my own code, I (not surprisingly) also can reproduce this badge flickering. However, this problem disappears when garbage collection is off.
Anybody have a clue what could be going wrong here? I'd like to use garbage collection in my app in conjunction with this technique, but the flickering is kind of annoying.
I bookmarked this a while back but Apple's changed the URL and the text. Fortunately I quoted it when I bookmarked it:
The Core Graphics APIs (Quartz 2D) see an approximately 25% reduction in drawing performance for applications compiled to use garbage collection.
That "25% reduction in drawing performance" text has been rewritten into a "slight overhead in code execution" and that was for 10.5. Perhaps Apple fixed it for 10.6. And you're talking Core Animation, not Core Graphics.
Still, Core Animation eventually has to talk to Core Graphics, and perhaps that performance issue hasn't gone away, and you're being bitten by it.
I fooled around with this a bit and can confirm I get the same behavior running the project with GC turned on. In fact, if you're patient enough and slowly change the selection one image at a time using the arrow keys, eventually it'll trigger the behavior and you can see the layers from one image in the view are displayed in the lower left corner instead of on top of the image. I haven't been able to find any sort of pattern as to when it happens, or any relation between which image is selected and which image has its layers missing. I'm assuming that for whatever reason, those layers are getting their frame origin set to {0, 0}, but heck if I know why.

How do I perform my own redraw in the Paint event of a VB6 PictureBox?

A coworker is encountering an error when he tries to run a VB6 app we're working on. The error is, "480: Can't create AutoRedraw image". Microsoft's documentation says this is because "There isn't enough available memory for the AutoRedraw property to be set to True. Set the AutoRedraw property to False and perform your own redraw in the Paint event procedure or make the PictureBox control or Form object smaller..."
Making the PictureBox smaller isn't an option. I'd be glad to "...perform my own redraw in the Paint event procedure...", but I'm not sure how to go about it. Can someone show me the way?
Without details this will be a simplistic answer. In general most beginning VB6 programmers use AutoRedraw=True draw in responds to some input. Fill out some data, click draw, and it appears in the picture box.
The click event in the Draw Button is linked do your drawing code. The first step is move the call to the drawing code to the paint event of the picture. The second step is to replace all calls to the drawing code with MyPictureBox.Refresh. Refresh forces the paint event of that picture box to fire.
The main problem you will have to be concerned with is that the paint event is going to be fired everytime the form needs refreshed. Like if a window covering it is moved. This means that any speed issue in your drawing code will be exposed. AutoRedraw=True takes what you drew and puts in a hidden bitmap that the PictureBox uses to display what you drew.
The Paint event will execute each step of your drawing process so you have to make sure you are as fast as possible. Depending on how dynamic your application is the worse slowdown issues will become. If you are displaying a static image then the problem isn't as bad.
Making the PictureBox smaller isn't an option. I'd be glad to "...perform my own redraw in the Paint event procedure...", but I'm not sure how to go about it. Can someone show me the way?
That is easy. You just implement the _Paint()-Event of your Form or PictureBox and draw.
Because you are asking, i think i should clarify what the AutoRedraw-Propeprty does. If it is set to true, you can "just draw your image" any way you want. In multiple steps. Whatever. If it needs to be redrawn, for example, because another windows was on top it, it will be magically done. The down site is, that is slow, for the drawing part.
If AutoRedraw is false, no magic will happen. The Paint()-Event will be fired and you are responsible to draw your image again. This will be much faster, if your window is not "invalidated" (e.g. "covered") often. Or you are doing a lot of drawing.
Or you are running out of memory for the "magic space" ;-)
If you don't mind rewriting your graphics code to use the GDI API - this could be a fairly big task - I found this thread from 2006 in the VB6 discussion group, where Mike Sutton said in answer to a similar problem:
VB's back-buffer implementation uses a
Device Dependant Bitmap (DDB) to store
the image data, which is quite limited
in how large it can be made. On older
OS' this used to be ~16mb uncompressed
data size, on later OS this has been
expanded but is still quite
restrictive.
A workaround for this is to use a
Device Independent Bitmap (DIB) and
manage the GDI resources yourself,
have a look at the DIB article on my
site for an example of how to work
with them.
I haven't tried it myself.
There's usually a drop-down box of events for your control in the forms code window. You need to pick the paint event:
Private Sub object_Paint()
and fill in your your code for drawing on the PictureBox.

Resources