Smooth scrolling on Flash AS3 - actionscript-3

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.

Related

Flash AS3 | Looping sound for each animation set

with University done I've finally had time to go back to practicing my Flash work, and I need some help with getting sound to loop and change depending on what part of the animation is playing.
This is also partly a follow up question to an older one I asked, so look here to get more detail as to where I'm coming from if you don't understand! (I've solved that issue, the current one relates to following up on it!)
Flash AS3 | Finishing current animation set before code is executed
The situation is basic: I have two different scenes, one of a man walking and one of a man running. It loops seamlessly of the man walking until you hit a button, where it finishes the animation then starts looping the run animation. Likewise, hitting the button again, finishes the loop before going back to the looping walk animation. The code for the button is below.
import flash.events.MouseEvent;
Next2.addEventListener(MouseEvent.CLICK, Change_2);
function Change_2(event: MouseEvent): void
{
addEventListener(Event.ENTER_FRAME, enterFrame);
function enterFrame(e:Event):void {
if (currentFrame == 30) {
gotoAndPlay(31);
removeEventListener(Event.ENTER_FRAME, enterFrame);
}
}
}
My issue is trying to get a footstep sound to match up with these animations. So while the man is walking, the 'walking footsteps' sound clip will play and loop alongside the animation, and when the button is pushed and the animation moves into the running animation, the 'running footsteps'' sound will play.
Any help on this would be much appreciated. I'm terrible when it comes to anything audio/code based.
Well u can check about soundChannel. soundChannel can stop() and play() ur audio.
So import ur external sound or use internal one. ur code probably seems like this.
var mySound:Sound = new Sound(new URLRequest("YourSoundPath"));
var sc:SoundChannel = new SoundChannel();
//when u wanna play
sc = mySound.play();
//when u wanna stop
sc = mySound.stop();
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/SoundChannel.html
also look this link for more info
If you want to really MATCH the footsteps to the animation (for example, the step sound should play when the player have put his feet down) the only sure way to do that is to place the sound on a different layer where your animation is and set the sound to play as "stream" (if i remember correctly).
Otherwise the animation might be out of sync because of different computer capabilities, current computer or graphics card load etc.
When the sound is set to play as "stream" the flash player is orienting on the sound and drop frames if the graphics are slow to keep the sound and animation in sync

How drag a Sprite smoothly on-screen in actionscript

First of all, my question is basically the same as this one:
How to drag an image to move it smoothly on screen, with ActionScript?
I want my dragged Sprites to keep up with the mouse on-screen, smoothly, without lagging behind.
And I notice that in the old ActionScript 3 Cookbook from way-back-when that they used a similar solution for their DraggableSprite as was used in the above link. Namely, use the stage instance to listen for the MouseMove event and then read from the event.stageX and stageY properties.
I've done that.
But my Sprite still doesn't stay locked with the mouse cursor. It lags behind. I feel like I must be missing something. However, if the solution posted above (ie listen for stage's MouseMove and use event.stageX/Y) is still current and the problem I'm describing should not be occurring, please also let me know. Even though it's not supposed to work, I've tried event.updateAfterEvent() and it also doesn't seem to have any positive effect.
Any help or advice would be greatly appreciated.
Here's a simple example of how I've written the handlers. It should work as-is if pasted into a new project.
I should also add that I'm compiling this as a desktop application using Adobe AIR. Would the run time be a factor???
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
[SWF(width="1280", height="720", frameRate="30")]
public class test_drag extends Sprite {
private var testDragSprite:TestDragSprite;
public function test_drag() {
super();
graphics.clear();
graphics.beginFill(0x0000FF);
graphics.drawRect(0, 0, 1280, 720);
graphics.endFill();
testDragSprite = new TestDragSprite();
addChild(testDragSprite);
testDragSprite.addEventListener(MouseEvent.MOUSE_DOWN, testDragSprite_mouseHandler);
testDragSprite.addEventListener(MouseEvent.MOUSE_UP, testDragSprite_mouseHandler);
}
private function testDragSprite_mouseHandler(e:MouseEvent):void {
switch (e.type) {
case MouseEvent.MOUSE_DOWN: {
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
break;
}
case MouseEvent.MOUSE_UP: {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
break;
}
}
}
private function mouseMoveHandler(e:MouseEvent):void {
//-20 to keep the sprite centered on the mouse
testDragSprite.x = e.stageX - 20;
testDragSprite.y = e.stageY - 20;
//e.updateAfterEvent(); //strange effect, but doesn't solve the problem.
}
}
}
import flash.display.Sprite;
internal class TestDragSprite extends Sprite {
public function TestDragSprite() {
super();
graphics.lineStyle(1, 0xDDDDDD);
graphics.beginFill(0xFF0000);
graphics.drawRoundRect(0, 0, 40, 40, 12);
graphics.endFill();
}
}
There is always going to be a little lag, but:
The first two suggestions will make the most noticeable change to your code/performance.
Enable hardware graphics acceleration; edit your AIR application
descriptor file (xml) and set renderMode to Direct (or GPU). Consult
the Adobe Air help for details.
<!-- The render mode for the app (either auto, cpu, gpu, or direct). Optional. Default auto -->
<renderMode>direct</renderMode>
Use startDrag and endDrag to bypass your manual assignments in your mouseMoveHandler.
Replace :
testDragSprite.addEventListener(MouseEvent.MOUSE_DOWN, testDragSprite_mouseHandler);
testDragSprite.addEventListener(MouseEvent.MOUSE_UP, testDragSprite_mouseHandler);
With :
testDragSprite.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
testDragSprite.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
Add the new handlers:
private function mouseDown(e:MouseEvent):void {
testDragSprite.startDrag();
}
private function mouseUp(e:MouseEvent):void {
testDragSprite.stopDrag();
}
Increase your frame rate, but watch your CPU usage as your application/game becomes more complicated as you may need to lower it to allow your game logic enough time to complete between frames (otherwise you end up with what is called long frames, you can use the free Adobe Scout profiling tool to watch for these and lots of other things).
Add a frame rate HUD to your display so you can monitor when your actual framerate is lower than the requested framerate (this is for debugging)
If your game is 2d based, consider using the open-source Starling framework as all content is rendered directly by the GPU vs Flash's standard display list objects.
Just try the member function startDrag.
The Feathers UI library includes a drag-and-drop module. The answers above all use the 'old' display list which is not mobile-ready. If you want your code to work cross-platform you need a GPU framework (most popular is Starling on which Feathers is based, as well as most Adobe AIR games and Apps).

How to code a play and pause button in flash AS3

I have made a simple game in flash. It includes a timer, falling objects and an object controlled by using swipe. So is there a way to stop every activity with the pause button and start it back again with the play button. Basically I want the whole stage to pause and play using buttons.
There is no way to do it automaticaly. You could base your entire game on a timer (even for animations and physics) and pause this timer. But this is a feature you have to think about during the very design of your game. Now I guess you just have to pause every movieclip, cancel your listeners to ENTER_FRAME and pause your timer.
Many game engines such as Flixel or FlashPunk include this feature
The way I do this in as3 is to run two timers, one that always runs at about 500ms and another that runs at framerate that varies with the speed of the game. Something like
public var speedControl:int = 15;
public var tick:Timer;
public function timers():void{
tick = new Timer(1000/speedControl);
tick.addEventListener(TimerEvent:TIMER,tickd);
tick.start();
}
public function tickd(t:TimerEvent):void{
// the timer has ticked
}
public function pause():void{
tick.stop();
}
public function play():void{
tick.start();
}
This is a basic example of course created on the fly, but you can call the pause or play button with a standard event listener. If your whole stage runs off of the timer, it will all stop. I use a second timer however that doesnt get stopped and started with the functions also. You really do want some things to run all the time.
If you wouldn't mind using the FP 11.8 Beta, it has that feature nativly to stop all movieclips recursively. Check it out here:
http://labs.adobe.com/technologies/flashruntimes/flashplayer/

AS3 Game loop and draw frame

I am building a game for school in AS3. I made a game loop with a timer so this game can run faster.
private var updateTimer:Timer;
updateTimer = new Timer(0);
updateTimer.addEventListener(TimerEvent.TIMER, update);
updateTimer.start();
private function update(e:TimerEvent):void { }
This is working, but my teacher did show me a function/command how I can draw/render a frame.
Because of that the frame rate will go up. Unfortunately, I lost that code and I ca'nt find that function anywhere. Does anyone know that function? Yes, I know this way is very unstable.
Thanks a lot.
Are you thinking of TimerEvent.updateAfterEvent()? This causes Flash to render a new frame immediately independent of the movie frame rate in response to a timer or mouse event.
e.updateAfterEvent();
If you want to just change the frame rate of a game without messing with timers, you can always use stage.frameRate and go from there. So if you want to increase the frame rate, just use stage.frameRate++;.

Simulating a MovieClip in pure as3

I am looking for a way to make a Flash movie clip (animation, like the ones created with Flash Pro CS), but purely in as3 - so I can import them into Prezi.
I have done a lot of as3 programming in Flash Builder with Flex projects and I have no background in how MovieClips work.
What I have already tried is extending a MovieClip class and trying to base the animation on Timers, this failed so I tried with ENTER_FRAME event (because flash animations are based on frames - so I thought...). But all this fails, only graphics drawn in the constructor are displayed - no animation happens. (As I wrote in the first paragraph I am testing this importing the swf into Prezi, opening it in a browser works as expected)
Is there any way to do it? Like listening to specific events?
Give sprite sheet a try. It's the best solution for animation in AS3, and also pretty simple to implement. for changing drawing, there are Timer and ENTER_FRAME event to do this.
Funny thing happened. I wanted to show you a sample code I was trying out (I already tried Sprite with ENTER_FRAME), that was not working. By accident I found a solution. It looks like you need to draw something in the first frame, or else the other frames won't work (in Prezi at least).
So here is the working code:
public class PreziTest extends Sprite{
private var radius:uint = 10;
public function PreziTest(){
addEventListener(Event.ENTER_FRAME, onEnterFrame);
onEnterFrame(null); // WITHOUT THIS IT WON'T WORK - YOU NEED TO DRAW SOMTHING IN THE FIRST FRAME
}
private function onEnterFrame(event:Event):void{
radius += 10;
if(radius > 200)
radius = 10;
graphics.clear();
graphics.beginFill(0xff0000);
graphics.drawCircle(radius, radius, radius);
}
}
Thanks for all your help!