AS3: FPS drops down significantly because of innocent mouse moves - performance

I have ~10000 objects in my game and exactly 60 (maximum) FPS when mouse isn't moved. But just when you start moving mouse in circles FPS tries to reach 30 averaging at 45. When you stop mouse it's INSTANTLY 60 (as so program lost it's heartbeat). SWF is run standalone - without any browsers.
I removed any MouseEvent.MOUSE_MOVE listeners and made mouseEnabled=false and mouseChildren=false for the main class.
I increased my FPS one-by-one from 12 to 60 - I gave name to each frame I born and it's really painful watching how 15 of them die just because of nothing...
Sample code:
public class Main extends Sprite
{
private var _periods : int = 0;
/** Idling FPS is 23. Move mouse to drop FPS to 21.*/
public function Main() : void
{
//true if need to drop FPS to 18 instead of 21 moving mouse:
const readyToKill2MoreFrames : Boolean = true;
if ( readyToKill2MoreFrames )
{
var ellipse : Sprite = new Sprite;
ellipse.graphics.beginFill( 0x00FF00 );
ellipse.graphics.drawEllipse( 300, 300, 400, 200 );
ellipse.graphics.endFill();
addChild( ellipse );
//uncomment to fall only to 21 instead of 18:
/*ellipse.mouseChildren = false;
ellipse.mouseEnabled = false;*/
}
var fps : TextField = new TextField;
//uncommenting doesn't change FPS:
//fps.mouseEnabled = false;
addChild( fps );
fps.text = "???";
fps.scaleX = fps.scaleY = 3;
var timer : Timer = new Timer( 1000 );
timer.addEventListener( TimerEvent.TIMER, function( ... args ) : void
{
fps.text = _periods.toString();
_periods = 0;
} );
timer.start();
addEventListener( Event.ENTER_FRAME, function( ... args ) : void
{
//seems like PC is too fast to demonstrate mouse movement
// drawbacks when he has nothing else to do, so let's make
// his attention flow:
for ( var i : int = 0; i < 500000; ++i )
{
var j : int = 2 + 2;
}
++_periods;
} );
}
}

You've probably moved on to more modern problems, but I've recently struggled with this issue myself, so here's an answer for future unfortunates stuck with the problems created by Adobe's decade-old sins.
It turns out legacy support for old-style buttons is the culprit. Quote from Adobe's tutorial on the excellent Scout profiling tool:
"Flash Player has some special code to handle old-style button objects (the kind that you create in Flash Professional).
Independently of looking for ActionScript event handlers for mouse
events, it searches the display list for any of these buttons whenever
the mouse moves. This can be expensive if you have a large number of
objects on the display list. Unfortunately, this operation happens
even if you don't use old-style button objects, but Adobe is working
on a fix for this."
Turns out Adobe never really got around to fixing this, so any large number of DisplayObjects will wreak havoc on your FPS while the mouse is moved. Only fix is to merge them somehow, e.g. by batch drawing them using Graphics. In my early tests, it seems setting mouseEnabled = false has no real effect, either.

Related

CocosSharp game on Android startup takes a long time to draw graphics

We have a somewhat simple game written using CocosSharp. The game is within another Xamarin.Forms app. When the player clicks to play the game, we bring them to a splash screen. On iOS this screen displays immediately but on Android, the screen is just black for about 15 seconds. The music plays pretty much immediately on both platforms.
The following is called from the ViewCreated event of the CocosSharpView.
InitializeAudio();
var scene = new Scenes.SplashScene(GameView);
GameView.RunWithScene(scene);
The hang up seems to be when creating labels. The following take ~10 seconds to complete with 99% of it being in the constructor of the first label. We call our CreateText in the constructor.
private void CreateText()
{
var label = new CCLabel("Text 1", "BD_CARTOON_SHOUT.TTF", 80)
{
PositionX = layer.ContentSize.Width / 2.0f,
PositionY = layer.ContentSize.Height / 1.5f,
Color = CCColor3B.DarkGray
};
layer.AddChild(label);
label = new CCLabel("Text 2", "BD_CARTOON_SHOUT.TTF", 60)
{
PositionX = layer.ContentSize.Width / 2.0f,
PositionY = 50f,
Color = CCColor3B.DarkGray
};
layer.AddChild(label);
}
Keep in mind this only happens on Android.
Thanks in advance!
I had the same issue several weeks ago. The problem was CCLabel constructor
where it didn't know which type of font are you using and therefore trying all other types before finally trying the last one which is correct. You need to specify font type in CCLabel constructor like this:
var label = new CCLabel("Text 1", "BD_CARTOON_SHOUT.TTF", 80, CCLabelFormat.SystemFont);
Hope it helps.

Collision not detecting at high speed

I decided I wanted to learn how to work with the unity2D engine, and started with trying to make pong. This was going pretty good, until I found a problem I couldn't find/didn't understand an answer for on google .
Every time the player/AI hits the ball, I make the ball go a little bit faster. This works fine until the ball goes pretty fast (still playable though) and just passes through the player/AI. I solved this by making the box collider of the player/AI really long, but at really high (and unplayable) speeds it still goes through.
My solution works, but isn't that pretty, and I wonder if there is a better solution for this (make the engine check more often for collisions?).
Here's the script for the ball movement (Javascript):
#pragma strict
var StartSpeed : int;
var speedFactor : float;
function Start () {
yield WaitForSeconds(2);
StartBall();
}
function ResetBall () {
GetComponent.<Rigidbody2D>().velocity.x = 0;
GetComponent.<Rigidbody2D>().velocity.y = 0;
transform.position.x = 0;
transform.position.y = 0;
yield WaitForSeconds(0.5);
StartBall();
}
function StartBall () {
var randomDirection = Random.Range(0f,1f);
var randomAngle = Random.Range(-Mathf.PI/4, Mathf.PI/4);
if(randomDirection < 0.5f){
GetComponent.<Rigidbody2D>().velocity.x = Mathf.Cos(randomAngle) * StartSpeed;
GetComponent.<Rigidbody2D>().velocity.y = Mathf.Sin(randomAngle) * StartSpeed;
}else{
GetComponent.<Rigidbody2D>().velocity.x = - Mathf.Cos(randomAngle) * StartSpeed;
GetComponent.<Rigidbody2D>().velocity.y = Mathf.Sin(randomAngle) * StartSpeed;
}
}
function OnCollisionEnter2D (colInfo : Collision2D) {
if(colInfo.collider.tag == "Player"){
GetComponent.<Rigidbody2D>().velocity.x = speedFactor * GetComponent.<Rigidbody2D>().velocity.x;
if(colInfo.collider.GetComponent.<Rigidbody2D>().velocity.y == 0){
GetComponent.<Rigidbody2D>().velocity.y = speedFactor * GetComponent.<Rigidbody2D>().velocity.y;
}
var vel = GetComponent.<Rigidbody2D>().velocity;
Debug.Log("Speed: " + vel);
}
}
Any other comments on the script that may improve it are welcome!
EDIT: I tried the following (as Andrew suggested):
function OnCollisionEnter2D (colInfo : Collision2D) {
if(colInfo.collider.tag == "Player"){
GetComponent.<Rigidbody2D>().AddForce( Vector2 (speedFactor * GetComponent.<Rigidbody2D>().velocity.x, speedFactor * GetComponent.<Rigidbody2D>().velocity.y));
var vel = GetComponent.<Rigidbody2D>().velocity;
Debug.Log("Speed: " + vel);
}
}
This still causes the problem I had before.
Update your RigidBody settings and set Collision Detection to Continuous (it will probably be set to discrete) and your high speed collision will work fine.
You shouldn't be messing with the velocity directly, try just using AddForce() instead.
Whole physics including collision detection runs on FixedUpdate, so to actually detect any collision colliders must collide when FixedUpdate is called. Let's say one collider isn't moving (wall for example) and another is going right at it, on current call of FixedUpdate collider that is moving is just before the wall, while on the next call of FixedUpdate collider that is moving has passed the wall, because that is it's position step per frame. Visually we see that colliders did collide, but they didn't collide on any call to FixedUpdate. Now, there are two solutions to this, lower the speed or lower the timestep of FixedUpdate ( http://docs.unity3d.com/Manual/class-TimeManager.html ), but this can be bad for framerate, it all depends what machines are you targeting and how hardware hungry your game is.
There is also this open source script which you should look at :
http://wiki.unity3d.com/index.php?title=DontGoThroughThings#C.23_-_DontGoThroughThings.js

Set position not updated when open another tab

I do a growth animation of a fixed number of items, and after growth, i moved it to left.
Make growth by apply matrix
var trans_vector = new THREE.Matrix4().makeTranslation(0, height / 2, 0);
var graphics = new Graphics();
var rectangle = graphics.box(width, height, material);
rectangle.geometry.applyMatrix(trans_vector);
When a new item is added, i remove one from the container that will be added to scene
var children = this.container.children;
if (this.current_number === this.max_number) {
this.container.remove(children[0]);
this.current_number = this.max_number - 1;
}
object.position.copy(this.position); // this is a fixed position
this.container.add(object);
this.current_number++;
I write a function to translate to left, using tweenjs (sole)
animateTranslation : function(object, padding, duration) {
var new_x = object.position.x - padding; // Move to left
console.log(new_x); // Duplicated item here :(
new TWEEN.Tween(object.position).to({
x : new_x
}, duration).start();
},
And I remove all the "previous" items, using for loop
for (var i = 0; i < this.current_number-1; i++) {
this.animateTranslation(this.container.children[i],
this.padding,
this.duration/4)
}
The above code run correctly if we open and keep this current tab.
The problem is when we move to another tab, do something and then move back, some objects have the same position, that cause the translation to the same position. It looks weird.
It appears on both Chrome, Firefox and IE11.
I dont know why, please point me out what happened.
Most modern browsers choose to limit the delay in setInterval and pause requestAnimationFrame in inactive tabs. This is done in order to preserve CPU cycles and to reduce power consumption, especially important for mobile devices. You can find more details about each browser in this answer
That means, while the tab is inactive, your tween animation is not working the way it is normally expected to.
A simple solution would be to halt the main animation loop if the tab is inactive using a variable.
window.onfocus = function () {
isActive = true;
};
window.onblur = function () {
isActive = false;
};

JavaFX: pause transition, not equal times

I have written a small application that performs some long-running tasks. Instead of having the user to wait and seeing just a progress bar, I would like to display some (changing) information about the application.
For that purpose, I wrote the following code within the constructor of an extended Pane:
FadeTransition fadeOutTransition = new FadeTransition(Duration.millis(1000), this);
fadeOutTransition.setFromValue(0.8);
fadeOutTransition.setToValue(0.0);
Similarly the fadeInTransition. And further...
SequentialTransition seqTransition = new SequentialTransition (
new Transition() {
{ setInterpolator(Interpolator.DISCRETE);
setCycleDuration(Duration.seconds(1)); }
protected void interpolate(double frac) {
int nextElement = (int) ((explenations.size() - 1) * Math.random());
Explenation explenation = explenations.get(nextElement);
questionLabel.setText(explenation.getQuestion());
answerLabel.setText(explenation.getAnswer());
}
},
fadeInTransition,
new PauseTransition(Duration.seconds(15)),
fadeOutTransition
);
What I woud like is the text to fade in, stay there for ~15 seconds and then fade out again. Unfortunately, the animation flickers, moves faster and slower - and the PauseTransition never takes 15 seconds! What is wrong about the code? I'm using Java 7, and JavaFX 2.2 on Mac OS X.
The problem seems to be that I called the function
seqTransition.play();
multiple times. From there comes probably the flickering and the unequal waiting time.

Drag and Drop stage scrolling algorithm problems

I have some problems with basic drag and drop scrolling algorithm. Here is my algorithm:
When mouse pressed down i set boolean dragging = true and store the current mouse x and y position in stored_position variable.
When mouse up i set boolean dragging = false.
On each frame i check dragging == true and if it is i calculate the dx = current_mouse.x - stored_position.x and dy = current_mouse.x - stored_position.y. Then i store current mouse position as the new stored_position and scroll my view (it is 2d camera object) by this dx dy, as the Camera.x -= dx, Camera.y -= dy (i need the inversion one because of camera specific).
The problem with this algorithm is that when i drag the camera it starting to blink and move around/shake. I think it is because when i move my mouse from left to right it traces dx like this:
71
-67
69
-68
69
-68
8
-5
So i think it is the mouse twitching(i mean the mouse is jumps back sometimes when we try to draw a line). Any idea of changing algorithm, maybe i miss something?
Here is example of this problem: https://dl.dropbox.com/u/78904724/as_host/buld_build_other.rar (you need to run the index.html chose the level and try to drag the screen).
Updated
Here is the example full source link (this is the random picture, i swear): https://dl.dropbox.com/u/78904724/as_host/scroll_test.rar
And this is the code i used (in example i use native flash events instead of using axgl checks to not confuse someone, i have both examples and it cause the same problems):
//variables with comments
private var dragging:Boolean = false; //dragging flag
private var current_mouse:Array; //stored mouse position array [0] - x, [1] - y
private var d:Array; //dx dy array [0] - x, [1] - y
[Embed(source = "test.jpg")] public static const _sprite:Class; //sprite graphics
private var view_sprite:AxSprite; //some image on the stage to drag it
//this is the class constructor code
view_sprite = new AxSprite(0, 0, _sprite);
add(view_sprite);
current_mouse = new Array();
d = new Array();
Ax.stage2D.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void {
current_mouse[0] = Ax.mouse.x;
current_mouse[1] = Ax.mouse.y;
dragging = true;
});
Ax.stage2D.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void {
dragging = false;
});
Ax.stage2D.addEventListener(MouseEvent.MOUSE_MOVE, function(e:MouseEvent):void {
if (dragging) {
d[0] = Ax.mouse.x - current_mouse[0];
d[1] = Ax.mouse.y - current_mouse[1];
Ax.camera.x -= d[0];
Ax.camera.y -= d[1];
current_mouse[0] = Ax.mouse.x;
current_mouse[1] = Ax.mouse.y;
}
});
I am totally confused but the problem was this two strings(thanks the axgl author for helping me):
current_mouse[0] = Ax.mouse.x;
current_mouse[1] = Ax.mouse.y;
And when i remove them the dragging will work perfectly. But... I swear i tried this before and nothing gonna happed, camera just started to move faster without this and now... it works!
Thank you all for trying to help my. If someone would have the similar problems here is the full worked source: https://dl.dropbox.com/u/78904724/as_host/scroll_test_worked.rar
And this is the thread on axgl.org: http://axgl.org/forums/viewtopic.php?f=12&p=394

Resources