I've drawn a tentacle on the screen with ik bones that I want to bend against the player when he's close enough. I have gotten this to work, but the animation is happening too fast, and even though I throw all kinds of:
myMover.limitByTime = true;
myMover.timeLimit = 4000;
myMover.limitByIteration = true;
myMover.iterationLimit = 1;
myMover.limitByDistance = true
myMover.distanceLimit=1000;
code I think might slow it down, it doesn't slow down at all. How do I fix this? :S Im not sure if this is good form but I also have a somewhat related question: How do i get flash to recognize the armature if I don't have it set to runtime as opposed to authortime? Because if I set it to authortime then the following code returns null:
tentacle = IKManager.getArmatureByName("tentacle");
trace(tentacle);
Now the problem with runtime is that some clever users might be able to manipulate my tentaclemonster with the mouse :|
As I understand the IKMover limits, they're intended to control maximum processing time, not the animation. You can adjust the speed of each bone by selecting it in the IDE and looking under the "Location" properties.
I'd suggest leaving the speed at 100% and removing the limits though, then animating the target point directly (and calling moveTo on each frame). That way you have more precise control over the speed.
Related
Ok so I currently have a very simple steering behaviour on my game. One object chases another. The problem is that the chasing object ends up orbiting the other object indefinitely. Is there any way of solving this in box2d? Right now all I've got is linear damping, which slows it down when it gets close which kind of helps but I really want to kill the momentum so it can immediately change direction kind of like on Step 7 of this tutorial: http://code.tutsplus.com/tutorials/hit-the-target-with-a-deadly-homing-missile--active-8933 ... except in Box2D.
Maybe something like this:
if(//on target area){
setLinearVelocity(0f,0f);
setAngularVelocity(0f);
steeringBehavior = null;
}
P.S. Probably, you may use Arrive behavior instead (it has a drag to stop on target)
I used the setLinearDamping() method in the end which slowed the chaser as it got closer.
After asking a question regarding animation speed a few days ago, the stackoverflow gang once again solved my problem. However, this has led to another question. [The more you know, the more you realise you don't know.]
Basically the fewer state changes to my canvas, the faster things will go. If I am just changing the fillStyle, then using ctx.save and ctx.restore is overkill, as all states are restored. Overkill = Slow. Instead just keep the oldvalue of fillStyle somewhere and put just that back in once you have finished.
So how do you do this for ctx.translate(x, y), ctx.rotate(angle) and ctx.clip()?
How can I restore these guys to their states before my changes WITHOUT having to use ctx.restore?
Your can untransform by using negative values.
ctx.translate(100,100);
// draw lots of stuff
ctx.translate(-100,-100);
ctx.scale(.75,.50);
// draw stuff
ctx.scale(-.75,-.50);
ctx.rotate(Math.PI/4);
// draw stuff
ctx.rotate(-Math.PI/4);
If you do multiple transforms, you must undo them in reverse order
ctx.translate(100,100);
ctx.scale(.75,.50);
ctx.rotate(Math.PI/4);
// draw lots of stuff
ctx.rotate(-Math.PI/4);
ctx.scale(-.75,-.50);
ctx.translate(-100,-100);
But when translating (moving) a few items, it's faster to use an offset instead of a transform.
strokeRect(20+100,20+100,50,30);
fillRect(20+100,20+100,50,30);
Clipping is semi-permanent so you must save/restore the entire context state to undo clip:
context.save();
// define a clipping path
context.clip();
// draw stuff
context.restore();
Transforms are done using a transformation matrix. Canvas gives you access to that matrix using the context.setTransform method.
scaleX=.75;
scaleY=.50;
skewX=0;
skewY=0;
translateX=100;
translateY=100;
context.setTransform(scaleX, skewX, skewY, scaleY, translateX, translateY);
// draw stuff
context.setTransform(-scaleX, -skewX, -skewY, -scaleY, -translateX, -translateY);
To also set the matrix for rotation, you must set a combination of the scale & skew values like this:
var radianAngle=Math.PI/4;
var cos=Math.cos(radianAngle);
var sin=Math.sin(radianAngle);
context.setTransform(cos,sin,-sin,-cos,0,0);
// draw stuff
context.setTransform(-cos,-sin,sin,cos,0,0);
To do rotation along with other transforms, just add the rotation values to the scale and skew values.
context.setTransform(scaleX+cos, skewX+sin, skewY-sin, scaleY-cos, translateX, translateY);
// draw stuff
context.setTransform(-scaleX-cos, -skewX-sin, -skewY+sin, -scaleY+cos, -translateX, -translate);
Just to correct the assumption of the question :
False : • The whole context state is saved/restored when using save()/restore() methods.
Let's be modest : An idea that comes to mind in 30 seconds is most likely to be found (and improved) by the developers of major Browsers. So truth is :
True : • Saving the context does almost nothing, and restore applies only on what just occurred.
If in doubt, you can look at the code, but it takes quite some time to be familiar with it (i did it with webKit's canvas => confirmed for this one ).
But it's much easier to look at the various jsperf made on the subject : they show that the gain when hand-saving/restoring one or two properties is moderate to small ==> only what changes is restored.
When hand-saving/restoring more things, then save and restore becomes faster because of Javascript's overhead.
(http://jsperf.com/save-restore-vs-translate-twice/4)
Another thing : talking about 'overkill' seems very exaggerated. Not only because, as seen before, context's save might be faster, but also because, best win is 2X, so we are talking about proudly taking 2ns instead of 4ns for the save. This has to be compared to the time taken for the draw, and might very well not be worth it.
Two last things :
• the bug risk induced by manually saving/restoring ('oops ! i forgot to restore that in that function !').
• the rounding errors that might occur (scale(x,x) => then scale(1/x, 1/x) )
In fact you can save time with no risk is by :
1) batching commands : whenever possible (it all depends on your app, really), batch all commands that expects a given context state.
2) similarly, you can define conventions/rules that prevents you to save/restore the context. For instance : 'always set fillStyle just before filling'. This way you never have to worry about current fillSyle. What you can do here also greatly depends on your app (and wether it's using external APIs or not), but can save a great deal of time for numerous draws.
So my advice would be to use the manual save/restore only for obvious simple case (ex: you just change globalAlpha), and to use conventions/rules to reduce the context state changes to a minimum.
For a long time I've been searching for a solution to this problem, so I decided to post a tread instead when the search didn't clarify anything.
I have a textfield that is supposed to move across the screen. I've solved this by adding a speed to its x-value dynamically through an "enter-frame function". However, the movement is very "laggy" and consists of sudden "jumps" in the movement. I've tried a couple of possible solutions to this, all of them without luck.
embedding fonts
changing the textfield's antiAliasType
using BitmapData like this:
bmd = new BitmapData (myTextField.width, myTextField.height, true, 0);
bmd.draw (myTextField);
bm = new Bitmap (bmd);
bm.x = myTextField.x;
bm.y = myTextField.y;
bm.cacheAsBitmap = true;
bm.smoothing = true;
this.addChild(bm);`
And then moving the "bm" instance
None of these methods worked.
EDIT: By request, I am adding the relevant code for the actual movement of the text.
stage.addEventListener(Event.ENTER_FRAME, time);
private function time(evt:Event):void
{
bm.x-= textSpeed;
}
The variable textSpeed is defined as a public static var. Its value is 2.
*EDIT2: I've prepared a clean fla-file with nothing but moving text. The same lag occurs for me also here. The code is in the actions panel. Download link
the way Flash IDE works, is that setting the framerate is actually the 'maximum' framerate. That is, it doesn't force the animation to run at that rate - it can vary depending on the machine and available resources.
As far as I know, there's no way to force Flash to run at a certain framerate - the best way to make animations 'smooth' is to use Tween classes like TweenLite.
If you NEED to animate by incrementing position values, then I suggest making it time based instead, for example:
var fps = 24;
var moveTimer:Timer = new Timer(1000/fps);
moveTimer.addEventListener(TimerEvent.TIMER, onMoveTimer);
moveTimer.start();
function onMoveTimer(e:TimerEvent){
bm.x -= 1;
}
Again, this doesn't solve the smoothness of the animation, but it will be much more reliable across different machines than using enter frame.
Try increasing the framerate. Because you naturally try to read text as it animates, you can generally notice the gaps between frames at 24fps. Try setting stage.frameRate to 30, 48, or 60 (60 being the max) and see if that solves your issues. I've had similar issues with animating text in the past and increasing frame rate has fixed them.
I would also recommend only increasing it as needed. You are much more likely to drop frames with a higher frame rate (makes logical sense; each frame has less time to calculate as frame rate increases), so you might want to do something like:
stage.frameRate = 48;
// run animations here
stage.frameRate = 24; // in an Event.COMPLETE handler
That will make sure your animations are smooth while giving the rest of your application the best shot of running well on lesser devices. If you are running a lot of animations, you might consider keeping it elevated permanently.
You should also look into using the Greensock animation library (TweenLite/TweenMax) instead of Flash's built-in tweening. Greensock has a vastly superior API, both in terms of features and performances, especially on mobile.
I simply added a sprite in AS3:
Sprite myspr = new Sprite();
myspr.addChild(mybitmap);
addChild(myspr);
Then I added an event. I did hitTestPoint for checking mouse is over my sprite or not.
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseCheck);
private function mouseCheck(evt:MouseEvent):void {
var xx:int = stage.mouseX;
var yy:int = stage.mouseY;
if(myspr.hitTestPoint(xx, yy, true)) {
...
// I'm checking mouse over here.
}
evt.updateAfterEvent();
}
Problem is: hitTestPoint gives true when mouse comes to full boundary box. But it should give true only if mouse comes on transparent isometric sprite.
Is there a solution for this, thanks in advance.
this should help. You need pixel perfect detection.
Actionscript 3 pixel perfect collision. How to? (learning purposes)
http://www.freeactionscript.com/2011/08/as3-pixel-perfect-collision-detection/
http://www.anotherearlymorning.com/2009/07/pixel-perfect-collision-detection-in-actionscript-3/
http://old.troygilbert.com/2009/08/pixel-perfect-collision-detection-revisited/
There's a few ways I usually do hit testing.
1) The easiest way is to use a an already made class that you can find online. Some people much smarter than me have created complex classes that allow for much better pixel to pixel interaction. The ones listed by Paras are all good. The problem with these is, for newer users, it can be hard to understand all the code and how to implement them. Usually it is simple once you understand what is going on though. You just replace your hit test with the class file and then enter in the correct arguments.
2) Another method is to actually go into the symbol, create a new layer, and then draw a rectangle(just turn the alpha down to 0%) where you want the hit test to work. This may seem like a stupid method, after all we are just confined to a square once again. BUT, it will actually work MUCH better than you'd expect. Just draw the square maybe slightly smaller than the height and width of your character you're detecting the hit test on, and you should be good to go. Give it an instance name (the hit square that is) and then just perform the hitTest with that square instead of the actual sprite. It works wonderfully and is a very simple solution. For what you're explaining though, this sounds like it might not work. This method is more from a gamer standpoint. It looks good when attacking and getting hit by enemies, but isn't necessarily exact. Also, if you want to do this with two characters (maybe a large attack hitting an enemy) simply draw a hit box for both sprites. This is probably a little more basic than using a pre-made pixel perfect hit detection test, but it works extremely well and takes only a few minutes.
I am making a game in Libgdx, in which I want to show and hide a texture for specific interval of time and repeat this process. can I use Timer class for this.
Please give me some example also.
I'm not sure what your trying to do here. You could just have a flag in your rendering loop
Texture texture;
long lastFlip = 0;
long flipTime = 1000;
boolean display = false;
//..In your rendering loop
if(lastFlip+flipTime > System.currentTimeMillis()){
display = !display;
lastFlip = System.currentTimeMillis();
}
if(display){
spriteBatch.draw(texture,0,0);
}
If you want to use the inbuilt actions system in scene2d have a at the following tutorial. Tutorial. The blog is very good and gives you a good idea of how to use a lot of scene2d features. It might be a little bit out of data beacuse of the changes to scene2d but it will give you the idea you need.
I am sure you got the solution now but instead of using System specific time you should use the Gdx graphics delta time which you already have in the render method. Then compare it with the amount of time for which you want to show the textures.
You should definitely use libGDX wrapper function to read time to avoid eventual incompatibility on different platforms. But code it self can be really simple:
if (TimeUtils.millis()%(SHOW_TIME+HIDE_TIME) < SHOW_TIME){
// render it
}
Where SHOW_TIME is number of milliseconds you want your texture displayed and HIDE_TIME is number of milliseconds you want it hidden. No need for extra variables and making it more complicated than this.