How can I fix touch lag in Flash? - actionscript-3

I've encountered strange behavior when using AS3's TouchEvents to handle multi-touch. The touch lags considerably in certain situations, but Flash's frame rate isn't affected. It's as though the touches are getting buffered and the events just aren't dispatched until several seconds after the touch.
I've uploaded a demonstration here: https://youtu.be/omkCDqljfio
I've only managed to reproduce this touch lag in the ActiveX version of Flash Player, but I've reproduced it in both Windows 10 and Windows 7. So what I have here is a C# application that's hosting my AS3 test suite, but it can also be observed if the swf is viewed in Internet Explorer.
Since my application already involves hosting the SWF in a WPF window, I've been attempting to create a solution where touch is received in C# and then communicated to the AS3. It would work perfectly but it seems my WPF window isn't receiving touch frames when the touch is on a WindowsFormsHost. So there's another problem that I have to solve.
FlashDevelop project: https://drive.google.com/file/d/0BxC2eCzurT9rd0gzSGc4TUdQLTQ/view
Visual Studio solution: https://drive.google.com/file/d/0BxC2eCzurT9rUThmRHBKWHZmbzA/view
AS3 touch events:
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
stage.addEventListener(TouchEvent.TOUCH_BEGIN, stage_touchBegin);
stage.addEventListener(TouchEvent.TOUCH_MOVE, stage_touchMove);
stage.addEventListener(TouchEvent.TOUCH_END, stage_touchEnd);
Creating the display objects that contribute to the lag, presumably because of the touch event capture phases:
for (var i:int = 0; i < 500; i++)
{
Dotter.createBGDot(_bgLayer, _shapesOn ? Shape : Sprite);
}
...
static public function createBGDot(bgLayer:Sprite, dotClass:Class):void
{
var dot:* = new dotClass();
var color:Color = new Color();
color.brightness = Math.random();
dot.graphics.beginFill(color.color);
dot.graphics.drawCircle(0, 0, Math.random() * 400 + 40);
dot.x = Math.random() * bgLayer.stage.stageWidth;
dot.y = Math.random() * bgLayer.stage.stageHeight;
bgLayer.addChild(dot);
}
I know this is sort of an unusual situation, but I appreciate any advice about how to resolve these issues.

Now that I've used Adobe Scout I think it is a rendering issue after all. The frame rate still shows 30fps because the processing time just barely manages to hit the 30fps mark. Lowering the frame rate fixes the problem.
It is still strange that the touch events would have such a long delay when the frame rate is just barely falling short, though.

Related

Phaser sound stops working only on Chrome for Android

The sound works for the first few minutes but after a while .play() doesn't play any sound. It seems like if there is a huge duration where no sound has played the sound stops working.
It works fine on Desktop, iOS and the generic android browser. I'm just running into this problem specifically on android devices using mobile chrome as the browser.
This turns out to be a Chrome bug that causes web audio to stop playing sounds if no sound has played for something like 30 seconds.
https://code.google.com/p/chromium/issues/detail?id=518863
The fix seems to be to watch
audioContext.currentTime
and when it gets stuck after 30 secs create a new audioContext.
The solution I ended up using is as follows:
Note I am using the phaser library - so this exact solution wont work for you - but it will give you the general idea
//This is run using a timer event every second
//this.game.time.events.loop(1000, this.checkAudioContext, this);
evil.AudioManager.prototype.checkAudioContext=function(){
//work out when the audio context has stopped
if(this.game.sound.context.currentTime-this.last_context_time===0){
//close out the existing context and create a new one
//you will also need new gain nodes if you are using them
this.game.sound.context.close();
this.game.sound.context=new AudioContext();
this.game.sound.masterGain= this.game.sound.context.createGain();
this.game.sound.masterGain.gain.volume=this.volume;
this.game.sound.masterGain.connect(this.game.sound.context.destination);
//now go through every sound and connect them to the new context
//creating gain nodes as we go.
for(var key in this.tracks){
var snd=this.tracks[key].snd;
snd.context=this.game.sound.context;
snd.masterGainNode = this.game.sound.masterGain;
snd.gainNode=this.game.sound.context.createGain();
snd.gainNode.gain.value = snd.volume * this.volume;
snd.gainNode.connect(snd.masterGainNode);
}
}else{
//update out time variable
this.last_context_time=ctx.currentTime;
}
}
What version of phaser and android do you have? For me it seems to play without issues for a 4-minute song i tried. Even if the screen goes of, it continues without any problem when it is resumed. A dirty solution will be to add an loop that plays a silent sound every 2 minutes for example just to "refresh" the sound manager if that solves your problem.

What should i use to load audio in as3 instead of load()?

I have a setup of 4x4 drum pads which are essentially buttons or movie clips with 3 states to show visual feedback (like the lighting up of the pads when they are pressed). I have tested this setup on an android tablet as well as a windows 7 touch-enabled laptop. Obviously the windows 7 laptop is more powerful and thus more responsive.
But not responsive enough.
I am wondering how I should be approaching the loading of audio files which are short drum-kit sample sounds in mp3 format stored in an assets folder next to the swf file.
Is there a better way, such as a way to cache the sounds so that I don't have to reload them each time the sound event is triggered?
Any help on this is greatly appreciated. (I just am not aware of how else, right now, to approach loading sounds other than calling a new sound each time the pad is pressed, thus not really caching the sound)
var kickc_03:Sound=new kickc_03_mp3(); // not sure whether to use Sound() or kickc_03 here..
// or
var kickc_03:kickc_03_mp3=new kickc_03_mp3();
// they will both work because kickc_03_mp3 subclasses Sound.
if i were you i would do something like:
// execute this once
var drumNum:int = 16;
var soundArray:Array = [null];
var C:Class;
init();
function init():void{
for(var i:int=1;i<=drumNum;i++){
C = Class(getDefinitionByName("kickc_"+formatF(i)+"_mp3");
soundArray.push(new C());
}
function formatF(n:int):String{
var s:String=n.toString();
while(s.length<2){
s="0"+s;
}
return s;
}
//////////////////////////////////////////////
now anytime you want to generate a kickc_somenum_mp3 sound, use:
soundArray[somenum].play();

Having trouble with 2D texture movement

I'm having trouble with smooth character movement for a 2d game I'm making.
It looks like the character is double when moving. Kinda like this (its just one pixel though):
( ()
/ /{}\ ==>
| ||
The game runs on a solid 60 FPS and my monitor is not the problem (I have tested this on several monitors).
I'm using starling at the moment, but I've had this since I first stared making games (using openGL). I was hoping someone could tell me what I'm missing. Here is my code:
private var _x:Number = 20, _y:Number;
public function update(delta:Number):void
{
if(gravity){
_y += delta * 120;
}
if(_y + skin.image.height > game.stage.stageHeight){
_y = game.stage.stageHeight - skin.image.height;
gravity = false;
}
if(right && left){
skin.playAnimation("none");
}else if(left){
_x -= delta * speed;
skin.playAnimation("left");
}else if(right){
_x += delta * speed;
skin.playAnimation("right");
}
//update skin
skin.update(delta, Math.round(_x), Math.round(_y));
}
skin update method:
public function update(delta:Number, x:int, y:int):void
{
image.x = x;
image.y = y;
if(currentAnimation){//this is texture switching (I tried without, still happens)
currentAnimation.update(delta);
}else{
image.texture = textures[4];
}
}
Here is the game.
Based on my own experimentation, as well as all the data in the comments, I think the ghosting is dependent on the frame rate and the computer itself.
First, and most importantly, when I tried the game in the link, it had the described ghosting at the full frame rate of 60. However, when I tried to film a screencast for further analysis, that occupied some CPU, dropping the frame rate down to around 35 or 40. At that point, the ghosting stopped.
Second, because different people are reporting different experiences with the described ghosting, I'd also think that it has a little to do with the individual computers themselves, probably rooted in their available memory and CPU, though that's just a theory, as I don't have any benchmarks to go off of.
Third, I think part of it is also rooted in neuroscience, as different people perceive animation differently.
People always talk about wanting a higher frame rate, but honestly, to fix this, I would recommend LOWERING the frame rate. Flash Professional CS6 has a default frame rate of 24 FPS, and I have never experienced a ghosting problem to my memory. It is worth mentioning that Flash animators usually work in 24 FPS.
Then again, appearance-wise, it really isn't a major deal. It is one of those graphics flaws that people tend to ignore, similar to the motion blur you get on 24 FPS films, until they changed it to 48.
It seems to be something that all games have (I actually never noticed it on some games where I do notice it now) and I just have to live with it. Its not my hardware, its not my monitor. I tried it on a lot of computers (good to bad hardware) and it looks the same on all computers. It looks worse on the computers with bad hardware, but there is not a huge difference.

Smooth scrolling on Flash AS3

Is it possible to do completely smooth scrolling in Flash (ActionScript 3)? In the following test I am creating a bitmap consisting of random noise, then moving it to the left periodically. I have no heavy tasks running in the background. What I am looking for is smoothness that would be on par with my Amiga 500 from 1987 :-)
package {
import flash.display.*;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Game extends Sprite {
var noiseBitmap;
public function Game() {
var noiseBitmapData = new BitmapData(stage.stageWidth * 3, stage.stageHeight);
noiseBitmapData.noise(0, 0, 255, 7, true);
noiseBitmap = new Bitmap(noiseBitmapData);
addChild(noiseBitmap);
var t = new Timer(1000/30, 999999);
t.addEventListener("timer", function (e:TimerEvent) {
noiseBitmap.x--;
});
t.start();
}
}
}
The "rendering code" takes <1 millisecond to run on my computer (2.4 GHz Mac), but still the movement will occasionally get stuck for a frame or two, making the movement appear jerky.
FPS is set to 30 in Flash. I have tried running it both using "test movie" and in the browser (Chrome). Target is Flash Player 11.2. I have also tried calling e.updateAfterEvent() to force a redraw. I have Also played around setting the delay and FPS to slightly different values, but no improvement.
This is different from not smooth scrolling in AS3 because I am already using a BitmapData. Also I have tried using the ENTER_FRAME event instead of a timer as suggested in a reply to that question, but it did not help.
When using a timer, you will not be exactly synced with the frame rate. As you mention, the frame rate fluctuates a little making your timer sometimes fire twice during one frame or skipping a frame. To be sure to be more in sync with the frame rate, you should listen to the Event.ENTER_FRAME event.
An example:
this.addEventListener(Event.ENTER_FRAME, updateFrame);
⋮
function updateFrame(e:Event):void {
noiseBitmap.x--;
}
I suggest you try out Greensock's TweenLite. It is a highly optimized engine to do all sorts of tweening through code and is available for AS2 and AS3. You can find it here.
Walkietokyo's solution is still frame based and would not eliminate the issues you run into. Instead use time-based animation (which TweenLite actually implements). For more info refer to this article.

Pausing issue with flash webcam recording

I'm building a webcam recording app in CS5 and I'm having some seemingly random issues with the recorded flv. Currently I'm publishing a stream to Wowza Media Server using the standard _netstream.publish("movieName", "record") command. Everything regarding this works fine and I can play the file back but sometimes there's a 3 to 4 second pause at the beginning or end of the video. There will be a still frame and the time will sit at 0 and then snap to 4. I've explored bandwidth options and I've turned the resolution and quality down considerably and it doesn't seem to have any effect and the rest of the video will play back smoothly. Here are my current camera and mic settings.
_cam.setMode(160, 120, 30, false);
_cam.setQuality(0, 88);
_cam.setKeyFrameInterval(30);
_mic.rate = 11;
I'm also flushing the buffer before closing out the publish stream
_netstream.publish('null');
Could there be something going on with camera initialization/deactivation that causes the lag?
Any help would be greatly appreciated. Let me know if you need more details
I believe this has something to do with the way that the Flash plugin itself initializes and displays the camera.
If you set up a simple test to try setting and unsetting the video stream:
var cam:Camera = Camera.getCamera();
var webcam:Video = new Video(500, 375);
addChild(webcam);
var isPaused:Boolean = false;
function showWebcam():void {
if (!isPaused) {
cam = null;
} else {
cam = Camera.getCamera();
}
webcam.attachCamera(cam);
isPaused = !isPaused;
}
pausingButton.addEventListener(MouseEvent.CLICK, showWebcam);
You'll notice a definite pause as it switches between the two states.
From what I've seen, every time I call attachCamera() with a video object, there is a noticeable pause of the Flash Player itself (including all tweens, interactions, everything) when the method is called, even if the object I'm attaching is null.
Four seconds seems like an excessive lag, but I have noticed that the larger the input/video render and with smoothing = true set on the video object can affect the length of the delay.
As for a solution; I'm not sure if there is one achievable via pure Actionscript, since the delay appears to be down to how the Flash Player itself initializes and renders the live video object.