How can I fix the wrong timing of my fade/scroll animation? - actionscript-3

Currently I'm busy with Actionscript. I have a map with diverse worlds. If you click on an arrow icon you will scroll to the other world. The code is:
street.street_market.addEventListener(MouseEvent.CLICK, straat_actie2);
function straat_actie2(evt:MouseEvent) {
market.bringToFront();
MovieClip(root).worldmap.targetX = marktx;
MovieClip(root).worldmap.targetY = markty;
old = "street";
new = "market";
addEventListener(Event.ENTER_FRAME, fade);
}
The worlds are sliding to each other and the other one is fading out. It works like this:
addEventListener(Event.ENTER_FRAME, ballEnterFrame)
function ballEnterFrame (pEvent):void
{
var b = pEvent.currentTarget;
b.x += (b.targetX - b.x) / 16;
b.y += (b.targetY - b.y) / 16;
}
function fade(e:Event)
{
if(new != "")
{
this[new].alpha+=0.03;
if(this[old].alpha >= 0.2)
{
this[old].alpha-=0.05;
}
}
}
It all works fine. Except one thing. The longer you stay on a world map the longer it will take to let the other world fade out. So if I stay on the street map for 10 secs and I scroll to the next one it takes around 10 seconds before the old map fades out.
Does someone know how I can solve this problem?
Thanks.

Try setting up your function like this...
function fade(e:Event)
{
if( new != "")
{
//# add : ONLY if less than 1 (full opacity)
if ( this[new].alpha < 1 )
{ this[new].alpha += 0.03; } //# fade in (increase)
//# minus : if NOT 0 -OR- is NOT less than 0 (transparent)
if ( this[old].alpha != 0 || !( this[old].alpha < 0 ) )
{ this[old].alpha -= 0.05; } //# fade out (reduce)
//# clamp within limits of 0 to 1 range
if ( this[new].alpha > 1 ) { this[new].alpha = 1; } //# never higher than 1
if ( this[old].alpha < 0 ) { this[old].alpha = 0; } //# never less than 0
}
}//# end function fade
Explained :
...if I stay on the street map for 10 secs and I scroll to the next
one it takes around 10 seconds before the old map fades out.
Do you realise that ENTER_FRAME is something that happens every frame according to your SWF's frame rate (FPS)?. If you set 30 FPS in your Document settings, by your code you are adding 0.03 x 30 every second for 10 seconds. The .alpha amount rises higher than 1, now the delay is waiting for it to reduce from 9.0 back to 1 then it fades out as expected. There is no visual benefit to allowing alpha values to become anything higher than 1 or less than 0.

Related

Control timeline with pinchzoom in Actionscript 3.0

I'm using Actionscript 3.0 in Flash. Is there a way to control the timeline with pinching (so instead of zooming out/in you are moving the timeline back/forth)? I'm working on an story app where the player is in control of the story.
You could do something like the following:
import flash.events.TransformGestureEvent;
Multitouch.inputMode = MultitouchInputMode.GESTURE;
stop();
//listen on whatever object you want to be able zoom on
stage.addEventListener(TransformGestureEvent.GESTURE_ZOOM , zoomGestureHandler);
function zoomGestureHandler(e:TransformGestureEvent):void{
//get the zoom amount (since the last event fired)
//we average the two dimensions (x/y). 1 would mean no change, .5 would be half the size as before, 2 would twice the size etc.
var scaleAmount:Number = (e.scaleX + e.scaleY) * 0.5;
//set the value (how many frames) to skip ahead/back
//we want the value to be at least 1, so we use Math.max - which returns whichever value is hight
//we need a whole number, so we use Math.round to round the value of scaleAmount
//I'm multiplying scaleAmount by 1.25 to make the output potentially go a bit higher, tweak that until you get a good feel.
var val:int = Math.max(1, Math.round(scaleAmount * 1.25));
//determine if the zoom is actually backwards (smaller than before)
if(scaleAmount < 1){
val *= -1; //times the value by -1 to make it a negative number
}
//now assign val to the actual target frame
val = this.currentFrame + val;
//check if the target frame is out of range (less than 0 or more than the total)
if(val < 1) val = this.totalFrames + val; //if less than one, add (the negative number) to the totalFrames value to loop backwards
if(val > this.totalFrames) val = val - this.totalFrames; //if more than total, loop back to the start by the difference
//OR
if(val < 1) val = 0; //hard stop at the first frame (don't loop)
if(val > this.totalFrames) val = this.totalFrames; //hard stop at the last frame (don't loop)
//now move the playhead to the desired frame
gotoAndStop(val);
}

Cocos2dx - Unable to set velocity = 0.0

I'm making an pool game with cocos2dx.
First, i setup the edgeBox with this parameters PhysicsMaterial(1.0f, 1.0f, 0.8f)
And then these 2 balls PhysicsMaterial(1.0f, 1.0f, 0.5f)
On the update function, i want slow down balls time by time without gravity (like making ground friction) by adding
physicsBody->setLinearDamping(0.3);
On the update function, i set the minimum velocity, if the velocity of each ball reaches lower than 15, reset velocity to 0,0
auto MV = 15;
auto v1 = player1->getPhysicsBody()->getVelocity();
auto v2 = player2->getPhysicsBody()->getVelocity();
if (v1.x > MV || v1.x < -MV ||
v1.y > MV || v1.y < -MV) {
} else if(v1 != Vec2(0,0)) {
player1->getPhysicsBody()->setVelocity(Vec2(0,0));
CCLOG("sx 1 : %f %f",v1.x,v1.y);
}
if (v2.x > MV || v2.x < -MV ||
v2.y > MV || v2.y < -MV) {
} else if(v2 != Vec2(0,0)) {
player2->getPhysicsBody()->setVelocity(Vec2(0,0));
CCLOG("sx 2 : %f %f",v2.x,v2.y);
}
Everything works fine except when the balls stand next to the wall or each other. I see the small blue glue to these objects, this is when the contact has been made.
And in these situation, i can't set the velocity to 0,0.
I think there is some kind of force constantly changing the velocity. You can see the image below to see the blue glue and keep setting velocity = 0.0 like forever.
Firstly reset forces before setting velocity to zero: player2->getPhysicsBody()->resetForces();
Also gravity can be a cause that bodies continue to move.
So you can set gravity to zero for whole physics world. For example:
auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setGravity(Vec2(0, 0));
or just for one particular body:
player2->getPhysicsBody()->setGravityEnable(false);
or you can customize velocity function:
#include "chipmunk.h"
cocos2d::PhysicsBody * pBody = player2->getPhysicsBody();
pBody->getCPBody()->velocity_func = customVelFunc;
where customVelFunc could be defined as:
void customVelFunc(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
{
cpBodyUpdateVelocity(body, cpvzero, damping, dt);
}

Changing the value of a Number Bug AS3

Hey everyone so I am having some trouble here. Been at it for an hour now and can't find a solution.
So I Have a movie clip named _Bunny added to the stage like so:
_Bunny = new mcBunny;
stage.addChild(_Bunny);
_Bunny.x = (stage.stageWidth / 2) - 225;
_Bunny.y = (stage.stageHeight / 2) - 330;
Now what this _Bunny does is move across the stage horizontally from right to left in a loop which i have set up like so in a Enter_Frame event listener:
private function bunnyView():void
{
_Bunny.x += nBunnySpeed;
if (_Bunny.x >=(stage.stageWidth / 2) + 215)
{
_Bunny.gotoAndStop("leftView");
nBunnySpeed--;
}
if (_Bunny.x <=(stage.stageWidth / 2) - 215)
{
_Bunny.gotoAndStop("rightView");
nBunnySpeed++;
}
}
It's speed is the nBunnySpeed which is equal to 5. Now I have another function that I am trying to change the value of the nBunnySpeed to say 20 whenever the nScore is equal to 1 like so:
private function updateDifficulty():void
{
if (nScore >= 1)
{
//Increase Speed
nBunnySpeed = 20;
}
but the bug that in which is produces is the Bunny shooting off to the right side of the screen which is the "+x" no matter what I do this always happens.
Can anyone see what I might be doing wrong? I don't understand why this is happening. Please help!
You need some kind of a flag that indicates that the difficulty has been already updated. Then, when you call updateDifficulty it first checks if there's a real need to update speed now, if there's none, it just returns. If yes, however, then you update your bunny's speed and set that flag so that the next time the function will not alter the bunny's speed.
var diffUpdated:Boolean=false;
private function updateDifficulty():void
{
if (diffUpdated) return; // here
if (nScore >= 1)
{
//Increase Speed
if (nBunnySpeed<0) nBunnySpeed=-20;
else nBunnySpeed = 20; // retain the direction of bunny's movement
}
diffUpdated=true;
}
Now, whenever you want your difficulty to be updated, you do diffUpdated=false; and voila, bunny's speed will be updated by this. For this, however, you will need more than two levels of speed, maybe one for 10 score, one for 50 and one for say 200.
What you do in this function
private function bunnyView():void
{
_Bunny.x += nBunnySpeed;
if (_Bunny.x >=(stage.stageWidth / 2) + 215)
{
_Bunny.gotoAndStop("leftView");
nBunnySpeed--;
}
if (_Bunny.x <=(stage.stageWidth / 2) - 215)
{
_Bunny.gotoAndStop("rightView");
nBunnySpeed++;
}
}
is check whether the _Bunny is offscreen or not. And if so, the nBunnySpeed will be nBunnySpeed - 1. But since BunnySpeed = 20, it will be 20 + 19 + 18 + 17, still going right. If you'd to turn it to BunnySpeed = -BunnySpeed, it will reverse immediately and go back.

Nape Moving Platform

Okay Im relatively new to nape and Im in the process of making a game, I've made a Body called platform of type KINEMATIC, and I simply want to move it back a forth in a certain range on the stage. Can somebody please see where im going wrong , thanks.
private function enterFrameHandler(ev:Event):void
{
if (movingPlatform.position.x <= 150 )
{
movingPlatform.position.x += 10;
}
if (movingPlatform.position.x >= 260)
{
movingPlatform.velocity.x -= 10;
}
}
First of in one of the if blocks you are incrementing position.x by 10 in the other one you are decrementing velocity.x by 10. I guess you meant position.x in both.
Secondly, imagine movingPlatform.position.x is 150 and your enterFrameHandler runs once. movingPlatform.position.x will become 160 and on the next time enterFrameHandler is called none of the if blocks will execute since 160 is neither less than or equal to 150 or greater than or equal to 260.
You can use the velocity to indicate the side its moving and invert it once you go beyond an edge, something like :
// assuming velocity is (1,0)
private function enterFrameHandler(ev:Event):void {
if (movingPlatform.position.x <= 150 || movingPlatform.position.x >= 260) {
movingPlatform.velocity.x = -movingPlatform.velocity.x;
}
movingPlatform.position.x += movingPlatform.velocity.x;
}
Obviously this might cause problems if the object is already at let's say x=100, it will just keep inverting it's velocity, so either make sure you place it between 150-260 or add additional checks to prevent it from inverting it's direction more than once.
This might be a better way of doing it :
// assuming velocity is (1,0)
private function enterFrameHandler(ev:Event):void {
if (movingPlatform.position.x <= 150) {
movingPlatform.velocity.x = 1;
} else if (movingPlatform.position.x >= 260) {
movingPlatform.velocity.x = -1;
}
movingPlatform.position.x += movingPlatform.velocity.x;
}
In general:
Kinematic bodies are supposed to be moved solely with velocity, if you change their position directly then they are not really moving as much as they are 'teleporting' and as far as the physics is concerned their velocity is still exactly 0 so things like collisions and friction will not work as you might expect.
If you want to still work with positions instead of velocities, then there's the method setVelocityFromTarget on the Body class which is designed for kinematics:
body.setVelocityFromTarget(targetPosition, targetRotation, deltaTime);
where deltaTime is the time step you're about to use in the following call to space.step();
All this is really doing is setting an appropriate velocity and angularVel based on the current position/rotation, the target position/rotation and the amount of time it should take to get there.

removing old tiles in a running game made with as3 and flash

I started to build a run game app for Android. I chose to make it in flash using tiles and Adobe Air. The game is that a player should run automatically to the right and avoid some obstacles by jumping or sliding along the ground.
I have made a function which always takes the first level in the array and uses as the starting level.
private function createLevel()
{
map_level.levell();
level = map_level.level1;
for(var t = 0; t < level.length; t++)
{
for(var u = 0; u < level[t].length; u++)
{
if(level[t][u] != 0)
{
var new_tile:platform_tile = new platform_tile;
addChild(new_tile);
new_tile.gotoAndStop(level[t][u]);
new_tile.x = u * 32;
new_tile.y = t * 32;
tiles.push(new_tile);
}
}
}
total_tile_width += u;
}
Then I create a function that takes a random level in the array of paths.
private function random_level ()
This level is then added at the end of the first track when the player has reached a certain length along the track, then the track seems endless and then made such that the camera follows the player.
private function update_level ()
{
random_level();
for(var t = 0; t < mid_lvl.length; t++)
{
for(u = 0; u < mid_lvl[t].length; u++)
{
if(mid_lvl[t][u] != 0)
{
var new_tile:platform_tile = new platform_tile;
level[t][u + total_tile_width] = mid_lvl[t][u];
addChild(new_tile);
new_tile.gotoAndStop(mid_lvl[t][u]);
new_tile.x = (u + total_tile_width) * 32;
new_tile.y = t * 32;
tiles.push(new_tile);
}
}
}
// Indstiller hvis spilleren skal have en stigende fart
if( movementspeed < 40)
{
movementspeed = movementspeed + 2;
}
else
movementspeed = movementspeed;
total_tile_width += u;
trace ("speed: " + movementspeed);
}
All this works as it should and game function also perfect as a PC, but the phone seems quick to overload it, since I can not figure out how to remove the old levels that have already been played and therefore there's going to be a lot levels in the phone memory.
I need to something like removeChild("old tiles the left the stage again) but got no idear how to only find the tiles that old and not just all tiles.
Anyone able to help me? btw hope you understand my question as im not the best at writing english.
Morten
You must use 2 BitmapData objects.
2 are the size of the screen. We call them screenBuffer1 and screenBuffer2
the other is larger than the screen by at least the width of a tile. We call it terrainBuffer
Then :
Init the terrainBuffer by drawing all visible tiles of the start screen
Copy the currently visible area on screenBuffer1
Draw sprites on screenBuffer1
Attach screenBuffer1 to stage
Now we start scrolling
Copy the currently visible area on screenBuffer2, offset by scroll amount
Draw sprites on screenBuffer2
Attach screenBuffer2 to stage
Continue increasing offset and alternate screenBuffer1 and screenBuffer2 so one is visible while you draw on the other
When offset reach the witdh of a tile :
if(offset>tileWidth){
offset-=tileWidth;
// Move content of terrainBuffer to the left by tileWidth pixels
// Draw a new column of tile on the right
}
Then keep on looping !