Rotation and flicker
by Andrew Douglas · in Torque Game Builder · 06/27/2006 (3:21 pm) · 8 replies
Okay, so here's the scenario - in one of our animation sequences, the character goes from its current mount rotation, and is turned around to a new mount rotation. My animation frames actually have the character turning the exact amount that I want the character's mountrotation to change so that at the end of the sequence the character is already facing exactly the direction I want him to..
Now here's my problem - when I catch that the animation has finished, I change states and set my character back to the standing animation and set the new mountrotation, except randomly the "standing" animation will flicker on the screen as it goes from the old mount rotation to the new mount rotation. Flicker is bad, mmmkay..
So I've tried everything to get rid of the flicker. I've tried pausing, setting enabled to false, playing with the scenegraph, playing with the order of operations, handling the start animation callback, trying to manipulate it frame by frame... and every time I randomly get a flicker.. sometimes more frequently than others, but it eventually will flicker. There has to be a way to essentially get double buffering where I can prep the next frame by both switching to the new animation sequence and setting the rotation for that animation sequence before the next "paint". But I'll be darned if I can get it to work.
Now, I'm going to try and go back to the animation sequence and see if we can get the animation to not rotate the character and instead I'll gradually rotate the sprite as the animation sequence plays out so that when we change to the standing animation, the mountrotation will already by right already.. but it's a situation I wish I could handle in code as I'm sure other similar situations will come up.
So, is there a well defined way of queuing up two or more commands without the screen repainting until all of the commands have completed? Why doesn't startanimation allow me to modify the sprites mountrotation before it actually starts (without causing flicker)?
Thanks!
-Andrew
Now here's my problem - when I catch that the animation has finished, I change states and set my character back to the standing animation and set the new mountrotation, except randomly the "standing" animation will flicker on the screen as it goes from the old mount rotation to the new mount rotation. Flicker is bad, mmmkay..
So I've tried everything to get rid of the flicker. I've tried pausing, setting enabled to false, playing with the scenegraph, playing with the order of operations, handling the start animation callback, trying to manipulate it frame by frame... and every time I randomly get a flicker.. sometimes more frequently than others, but it eventually will flicker. There has to be a way to essentially get double buffering where I can prep the next frame by both switching to the new animation sequence and setting the rotation for that animation sequence before the next "paint". But I'll be darned if I can get it to work.
Now, I'm going to try and go back to the animation sequence and see if we can get the animation to not rotate the character and instead I'll gradually rotate the sprite as the animation sequence plays out so that when we change to the standing animation, the mountrotation will already by right already.. but it's a situation I wish I could handle in code as I'm sure other similar situations will come up.
So, is there a well defined way of queuing up two or more commands without the screen repainting until all of the commands have completed? Why doesn't startanimation allow me to modify the sprites mountrotation before it actually starts (without causing flicker)?
Thanks!
-Andrew
#2
-Andrew
06/28/2006 (4:53 am)
The character animation sprite is mounted onto a static sprite that is used as the team indicator and shows as a "ring of light " under the character. I could certainly change that around if it's most likely setMountRotation that is the problem. I'll see if I can't set up a standalone example of what I'm trying to do and see if I can "fix" it by not using mountrotation. If nothing else I'll have some code I can post that may help pin down what I'm doing wrong. Thanks!-Andrew
#3
06/28/2006 (11:30 am)
It seems like it would be more straight-forward to mount the ring to the player and put it on a lower layer.
#4
-Andrew
06/28/2006 (12:32 pm)
I remember why I'm using the ring and mounting the animated sprite to it - the animated sprite is not square. Previously, I was setting mountrotation and everything rotated the way I wanted it to, but as soon as I tried to just rotate the character, the rotation started moving around the center of the sprite's image which is not what I want it to rotate around. Argh. I don't see an easy way to rotate around an arbitrary center point - am I just missing something silly? The sad thing is that while it's hard to tell with the current rotation issue, I think maybe it will stop the flicker.-Andrew
#5
06/28/2006 (12:46 pm)
No, you're not missing anything. Mount rotation is done around an object's pivot point (the center of a square, for example) and not the mount point. I mentioned this at the end of the mounting tutorial since that is obviously something that will end up confusing people.
#6
1. start a new project
2. you need these two images saved to the image directory
theoreticalgames.com/screenshots/flicker.png
theoreticalgames.com/screenshots/mountimage.png
3. you need to save the level and then close torque and replace the level contents with the following code
4. you need this for your datablocks.cs
4. and then you need to make the following changes to game.cs
add these 3 lines to the end of startGame method:
then add the following code at the end of the file
that should do it. You may also want to go in and remove the torque logo image from the background. When you play the level, you should see the image start to move up and then back down every second or two, and every other rotation or so, it flickers. Note: no solution should, at any point, show the red mount image behind. If you see red, the solution won't work :)
Note: I suppose I can legally send the zip file via email to anyone on this forum if someone would rather me do that. Just let me know.
Thanks!
-Andrew
06/28/2006 (5:24 pm)
Okay, so using mount rotation is definitely the root cause of the flicker but I can't really stop using mount rotation at this point. I've got a sample put together that demonstrates what I'm doing and gets the random flicker.. Suggestions welcome! :) 1. start a new project
2. you need these two images saved to the image directory
theoreticalgames.com/screenshots/flicker.png
theoreticalgames.com/screenshots/mountimage.png
3. you need to save the level and then close torque and replace the level contents with the following code
%levelContent = new t2dSceneGraph() {
canSaveDynamicFields = "1";
cameraSize = "100 75";
cameraPosition = "0 0";
new t2dAnimatedSprite(FlickerAnimation) {
animationName = "Stand";
position = "4.19 -9.5";
size = "12.5 25";
Rotation = "180";
mountID = "2";
};
new t2dStaticSprite(MountMe) {
imageMap = "mountimageImageMap";
position = "-10.5 -9.08";
size = "12.5 25";
Layer = "5";
MountRotation = "180";
mountID = "3";
};
};4. you need this for your datablocks.cs
$managedDatablockSet = new SimSet() {
canSaveDynamicFields = "1";
setType = "Datablocks";
new t2dImageMapDatablock(flickerImageMap) {
canSaveDynamicFields = "1";
imageName = "Flicker/data/images/flicker";
imageMode = "CELL";
frameCount = "-1";
filterMode = "SMOOTH";
filterPad = "1";
preferPerf = "0";
cellRowOrder = "1";
cellOffsetX = "0";
cellOffsetY = "0";
cellStrideX = "0";
cellStrideY = "0";
cellCountX = "-1";
cellCountY = "-1";
cellWidth = "128";
cellHeight = "256";
preload = "1";
allowUnload = "0";
};
new t2dAnimationDatablock(Stand) {
canSaveDynamicFields = "1";
imageMap = "flickerImageMap";
animationFrames = "0 0";
animationTime = "1";
animationCycle = "1";
randomStart = "0";
startFrame = "0";
};
new t2dAnimationDatablock(Rotate) {
canSaveDynamicFields = "1";
imageMap = "flickerImageMap";
animationFrames = "0 0 1 1 1 2 2 3";
animationTime = "0.5";
animationCycle = "0";
randomStart = "0";
startFrame = "0";
};
new t2dImageMapDatablock(mountimageImageMap) {
canSaveDynamicFields = "1";
imageName = "Flicker/data/images/mountimage";
imageMode = "FULL";
frameCount = "-1";
filterMode = "SMOOTH";
filterPad = "0";
preferPerf = "0";
cellRowOrder = "1";
cellOffsetX = "0";
cellOffsetY = "0";
cellStrideX = "0";
cellStrideY = "0";
cellCountX = "-1";
cellCountY = "-1";
cellWidth = "0";
cellHeight = "0";
preload = "1";
allowUnload = "0";
};
};4. and then you need to make the following changes to game.cs
add these 3 lines to the end of startGame method:
FlickerAnimation.mount(MountMe, "0 0", 0, true, true, true, false); FlickerAnimation.playAnimation(Stand); schedule(2000, 0, "startRotate");
then add the following code at the end of the file
function t2dAnimatedSprite::onAnimationEnd(%this)
{
if (%this.getAnimationName() $= "Rotate")
{
MountMe.setMountRotation((MountMe.getMountRotation() + 180) % 360);
FlickerAnimation.playAnimation(Stand);
schedule(1000, 0, "startRotate");
}
}
function startRotate()
{
FlickerAnimation.playAnimation(Rotate);
}that should do it. You may also want to go in and remove the torque logo image from the background. When you play the level, you should see the image start to move up and then back down every second or two, and every other rotation or so, it flickers. Note: no solution should, at any point, show the red mount image behind. If you see red, the solution won't work :)
Note: I suppose I can legally send the zip file via email to anyone on this forum if someone would rather me do that. Just let me know.
Thanks!
-Andrew
#7
That's really quite annoying. I had trying scheduling bits and pieces before.. but not BOTH.. why would BOTH work?? Anyway, I hope this helps someone else someday. Thanks!
-Andrew
06/28/2006 (8:17 pm)
Would you believe that changing/adding this fixed the flicker - why in the world is schedule able to do it when just executing both doesn't?function t2dAnimatedSprite::onAnimationEnd(%this)
{
if (%this.getAnimationName() $= "Rotate")
{
schedule(0, 0, "setStand");
}
}
function setStand()
{
FlickerAnimation.playAnimation(Stand);
MountMe.setMountRotation((MountMe.getMountRotation() + 180) % 360);
schedule(3000, 0, "startRotate");
}That's really quite annoying. I had trying scheduling bits and pieces before.. but not BOTH.. why would BOTH work?? Anyway, I hope this helps someone else someday. Thanks!
-Andrew
#8
Edit: Spelling.
06/29/2006 (1:28 am)
You can't edit the pivot point of an object within TGB, however you can change a pivot point of an image by tweaking the image. Since the pivot is always the center of the image, add blank space on whichever side of the image you want to adjust the pivot towards until the center of the image is where you want the pivot point.Edit: Spelling.
Torque Owner Thomas Buscaglia