Decreasing a timer over time in Adobe Flash - actionscript-3

So basically my ball moves to a random location on the screen once it hears the (3000) tick. How can I make the timer slowly decrease so that the ball moves faster and faster over time?
var timmyTimer:Timer = new Timer(3000)
timmyTimer.addEventListener(TimerEvent.TIMER, tick)
timmyTimer.start();
function tick(t:TimerEvent):void {
mcBall.x = Math.floor(Math.random() *(stage.stageWidth - mcBall.width));
mcBall.y = Math.floor(Math.random() *(stage.stageHeight - mcBall.height));
mcBall.nextFrame();

About your question now, 3000 milliseconds is your Timer object's delay, so to decrease that value, you can, for example, write :
function tick(t:TimerEvent):void
{
t.target.delay -= 100;
// ...
}

Related

How to define the position of a movieclip in relation to that of another of movieclip

I am trying to make a movieclip follow a custom mouse pointer (which is a movieclip) but always stay at a defined postion (in terms of coordinates), a distance away from the mouse pointer on easing to where the mouse pointer is. Below is the code:
import flash.display.MovieClip;
import flash.events.Event;
Mouse.hide();
var mouseCounter:int = 0;
var mouseDelay:int = 5;// how many frames the mouse must stay still before the follow code is run.
var speed:Number = 5;
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
stage.addEventListener(Event.ENTER_FRAME,follow);
// set counter back to zero whenever the mouse is moved.
function mouseMove(e:MouseEvent):void
{
wand.x = stage.mouseX;
wand.y = stage.mouseY;
e.updateAfterEvent();
mouseCounter = 0;
}
function follow(e:Event):void
{
// increment the counter each frame
mouseCounter++;
// now run the follow block if the mouse has been still for enough frames.
if (mouseCounter >= mouseDelay)
{
orb_mc.x -= (orb_mc.x - mouseX) / speed;
orb_mc.y -= (orb_mc.y - mouseY) / speed;
orb_mc.x = mouseX + 46.5;
orb_mc.y = mouseY +50.95;
}
}
The last two lines of codes (26 & 27), is what I used to define the orb_mc's position in relation to the custom mouse pointer which is "wand" however it seems to have resulted in the ease movement of the orb been hampered, so dont know if the positioning code I used is wrong
function follow(e:Event):void
{
// increment the counter each frame
mouseCounter++;
// now run the follow block if the mouse has been still for enough frames.
if (mouseCounter >= mouseDelay)
{
// Do this:
orb_mc.x -= (orb_mc.x - mouseX + 46.5) / speed;
orb_mc.y -= (orb_mc.y - mouseY + 50.95) / speed;
// OR this:
//orb_mc.x = orb_mc.x - (orb_mc.x - mouseX + 46.5) / speed;
//orb_mc.y = orb_mc.y - (orb_mc.y - mouseY + 50.95) / speed;
// but not both.
}
}
You see, once you use one of the increment assignment operators (-=,+=,/=,*=), immediately following that by a regular assignment operator will obviously override any value it had before. You understand that actionscript gets "read" by the computer (this is probably the wrong verbiage but you get my drift) and it reads each block (an area inside a curly brace set { }) from top to bottom. So the very first time that your follow method is called, it is doing 4 things, in order:
increment the counter
evaluate if mouseCounter >= mouseDelay
increments orb_mc x/y coords
assigns orb_mc x/y coords to final destination
It is doing this on the very first time the follow block is read. This is why both acceptable bits of code in my answer do 2 things:
they increment the x/y coords (don't set them to a final value)
they change based on a variable factor (speed)
Glad it's working!

Actionscript - Make movieclip move towards another movieclip

Hi guys I'm trying to make a FPS game, I'd like some help to get a 'baddie' movieclip to randomly spawn off stage and move towards the 'Player' movieclip, I'd also like it to allow several instances of that movieclip to be on the stage at the same time and to increase the amount of them over time i.e 1 extra 'Baddie' per 30 seconds.
I can also post my current code if needed?
Thanks in advanced.
Code
I need 10 rep to post more than two links so I've put the links into one.
I put my code on to PasteBin to minimise the post.
Links to my code
For movement, add an ENTER_FRAME Event to baddie that moves right if the enemy is on the left, left if right, down if up, up if down, etc:
baddie.addEventListener(Event.ENTER_FRAME, moveTowardsPlayer);
function moveTowardsPlayer(e:Event):void
{
var speed = 5;
if(e.currentTarget.x > char.x)
{
e.currentTarget.x -= speed;
}else
{
if(e.currentTarget.x < char.x)
{
e.currentTarget.x += speed;
}else
{
//...so on...
}
}
}
Also, you can make a timer with a delay of how much milliseconds you want to spawn (30,000 for 30 seconds) an enemy, and if you want multiple enemies, you can add the Event to all of them through an Array loop:
for(var i = 0; i < enemyArray.length; i++)
{
var baddie:Baddie = new Baddie; addChild(baddie);
enemyArray.push(baddie);
//...so on...
}
Also, Math.random() could be used for a random location of the enemy, like enemy.x = Math.random() * widthMax and enemy.y = Math.random() * heightMax

Is this a good implementation of the gameloop

I have implemented a gameloop in Flash/Actionscript/Starling and I want to throw it at you to see if this is a valid implementation.
I wanted to have a variable time step approach.
private var _deltaTime:Number = 0;
private var _lastTime:Number = 0;
private var _speed = 1000 / 40;
private function onEnterFrame() {
var now = new Date().getTime();
var delta = now - _lastTime;
_deltaTime += delta - _speed;
_lastTime = now;
//skip if frame rate to fast
if (_deltaTime <= -_speed) {
_deltaTime += _speed;
return;
}
update();
}
private function update() {
updateGameState();
if (_deltaTime >= _speed) {
_deltaTime -= _speed;
update();
}
}
What I got sofar is that I have a constant speed (more or less).
My question is is there a better approach so that the movements will appear even
smoother.
What is really surprising to me is that even thou the FPS is pretty much constant (60FPS)
the movement is sometimes bumpy yet smoother than with the naive gameloop.
Youre on the right track - assuming that onEnterFrame is triggered in some way by Event.ENTER_FRAME - instead of skipping update, call it on every frame but pass in the time elapsed:
private function onEnterFrame() {
var now = new Date().getTime();
var delta = now - _lastTime;
_lastTime = now;
updateGameState(delta/1000);//divide by 1000 to give time in seconds
}
In updateGameState, you can utilise 'delta' to calculate movement etc, eg:
function updateGameState(timeElapsed:Number):void {
myAlien.x += myAlienSpeedPerSecond*timeElapsed;
}
This way you get smooth movement even when frame rate varies.
from the Starling introduction pages, it shows that time elapsed is built into the EnterFrameEvent class.
// the corresponding event listener
private function onEnterFrame(event:EnterFrameEvent):void
{
trace("Time passed since last frame: " + event.passedTime);
enemy.moveBy(event.passedTime * enemy.velocity);
}
http://wiki.starling-framework.org/manual/animation#enterframeevent

How to only execute something every 30 frames

My question is this, I want to add a rock every second (30 frames per second), I have different levels, this means I have different amounts of rocks in each level and I have different amount of speeds, so I want to add 10 rocks in a total of 30 seconds in level 1
in level 2 it's 20 rocks in a total of 20 seconds etc. I'm open to completly changing it, I just want the best solution. I want it to be dynamic so I can make a lot of levels. How should I got about doing this
I don't want to keep a counter and every time it's at 30 then add a rock and reset it.
Thank you in advance
switch(difficulty)
{
case 1:
timer = 30;
numberOfRocks = 10;
break;
case 2:
timer = 20;
numberOfRocks = 20;
break;
case 3:
timer = 10;
numberOfRocks = 30;
break;
case 4:
timer = 5;
numberOfRocks = 40;
break;
}
addEventListener(Event.ENTER_FRAME, loop)
}
private function loop(e:Event):void
{
for (var i:int = 0; i < (timer * 30); i++)
{
a_bitmap = new a_class();
a_bitmap.x = 750;
a_bitmap.y = Math.ceil(Math.random() * (600 - a_bitmap.height));
a_bitmap.height = 35;
a_bitmap.width = 35;
addChild(a_bitmap);
a_bitmap.name = "astroid" + i + "";
myArray.push(true);
}
}
A Timer may work better for you're needs than a frame handler. I'd recommend using math to calculate your level parameters instead of hard-coded switch statements, then you can add as many levels as you'd like (or have your game go indefinitely)
var rockLoadTimer:Timer;
function gameInit():void {
//your games initialization code here
//create a timer that fires every second when running
rockLoadTimer = new Timer(1000);
//the function to call every time the timer fires. You could also listen for TIMER_COMPLETE is wanted to run a function once all rocks are loaded
rockLoadTimer.addEventListener(TimerEvent.TIMER, addNextRock);
}
function startLevel(difficulty:int = 1):void {
//your code here to clear the level
//repeat count is used as the amount of rocks to load this level - level number times 10
rockLoadTimer.repeatCount = difficulty * 10;
//the delay time is how quickly you want the rocks to load. this is 5 seconds divided by the difficulty level
//so the first level would be every 5 seconds, second would be every 2 and a half seconds, third level would be every second and two thirds. etc.
rockLoadTimer.delay = Math.round(5000 / difficulty);
rockLoadTimer.reset();
rockLoadTimer.start();
}
function addNextRock(e:Event = null):void {
//your rock creation code here
}
You can use a Timer, and create an instance of a_class during each tick:
var timer:Timer = new Timer(1000, 30); // One per second for 30 seconds
timer.addEventListener(TimerEvent.TIMER, addAsteroid);
timer.start();
function addAsteroid():void {
a_bitmap = new a_class();
// etc.
}
The timer delay is "asteroids per millisecond", so if you want to create 10 over 30 seconds you would set it to 30000/10 = 3000.
However, this approach works best when there is a smooth framerate- it will execute once per second, but the number of frames of animation can vary if Flash is running at less than 30fps. If your game works how I think it does, this could result in asteroids being "bunched up". So, keeping a counter might be the better solution here, unless you plan on handling the rest of your game logic (i.e. asteroid movement speed) in a way that can account for variations in frame rate.
If you want to use a counter:
var creationCounter:Number = 0; // put this at class level
// Then in the ENTER_FRAME event:
creationCounter += asteroids_per_second / 30;
while (creationCounter-- >= 1) {
a_bitmap = new a_class();
// etc.
}
You can also use flash.utils.setInterval function .
setInterval(trace , 1000 , "trace message once per second");
If you use TweenLite, you can use the delayedCall function, it can use time or frames,
// delayedCall(delay:Number, onComplete:Function, onCompleteParams:Array = null, useFrames:Boolean = false):TweenMax
TweenLite.delayedCall(30, addAstroid, null, true);
More info, see the docs: http://www.greensock.com/as/docs/tween/com/greensock/TweenMax.html#delayedCall()

How to reduce the timer's time while timer is running (ActionScript 3.0)

In my case, the timer I make doesn't reduce its time whenever a function is called. What code will I change or add in order to reduce the time in my timer?
Timer code:
var count:Number = 1200;
var lessTime:Number = 180;
var totalSecondsLeft:Number = 0;
var timer:Timer = new Timer(1000, count);
timer.addEventListener(TimerEvent.TIMER, countdown);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, timesup);
function countdown(event:TimerEvent) {
totalSecondsLeft = count - timer.currentCount;
this.mainmc.time_txt.text = timeFormat(totalSecondsLeft);
}
function timeFormat(seconds:int):String {
var minutes:int;
var sMinutes:String;
var sSeconds:String;
if(seconds > 59) {
minutes = Math.floor(seconds / 60);
sMinutes = String(minutes);
sSeconds = String(seconds % 60);
} else {
sMinutes = "";
sSeconds = String(seconds);
}
if(sSeconds.length == 1) {
sSeconds = "0" + sSeconds;
}
return sMinutes + ":" + sSeconds;
}
function timesup(e:TimerEvent):void {
gotoAndPlay(14);
}
At this point the timer.start(); is placed on a frame so that the timer starts as it enters the frame.
The delay property on Timer is what you are looking for. In your handler, change the timer's delay:
function countdown(event:TimerEvent)
{
totalSecondsLeft = count - timer.currentCount;
this.mainmc.time_txt.text = timeFormat(totalSecondsLeft);
//change the timer delay
timer.delay -= lessTime;
}
I assumed by your code sample that you wanted to subtract lessTime from the timer delay on each timer interval. If you want to change the delay to something else, then just adjust the code accordingly.
UPDATE
The above code is for decreasing the interval (delay) between each timer fire. If what you'd like to do instead is decrease the the amount of intervals (repeatCount) it takes for the timer to reach TIMER_COMPLETE, then you want to change the repeatCount property on Timer:
//set the timer fire interval to 1 second (1000 milliseconds)
//and the total timer time to 1200 seconds (1200 repeatCount)
var timer:Timer = new Timer(1000, 1200);
//reduce the overall timer length by 3 minutes
timer.repeatCount -= 300;
ANOTHER UPDATE
Keep in mind that when you alter the repeatCount, it doesn't affect the currentCount. Since you are using a separate count variable and timer.currentCount to calculate the displayed time remaining, it doesn't look like anything is changing. It actually is though - the timer will complete before the displayed time counts down to zero. To keep your time left display accurate, make sure to subtract the same amount from count as you are from repeatCount:
timer.repeatCount -= 300;
count -= 300;