I am trying to create a simple game like whack a mole, what I want is for instead of mole make rectangle appear and disappear quickly on screen and the player has to click it more rectangles he click more his score increases.
I think it's a fairly simple game but my problem is:
How do I make the rectangles appear and disappear on screen at random position also at increasing speeds as the timer is decreasing? i.e speed of rectangles appearing and disappearing increases as the time reduces, there is a countdown time as player gets to play for 30 sec.
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event;
var inc:Number = 1;
var gogo:Timer = new Timer(inc*1000);
var val:Number = 30;
var counter = val;
var time2:Timer = new Timer(1000+speed);
var speed:Number = 50;
timee.text = counter;
box.addEventListener(MouseEvent.CLICK, st);
function st(event:MouseEvent):void
{
gogo.start();
time2.start();
}
gogo.addEventListener(TimerEvent.TIMER, res);
function res(ev:TimerEvent):void
{
if(counter == 0){
gogo.stop();
}else{
val = val - inc;
counter = val;
timee.text = counter;
}
}
stage.addEventListener(Event.ENTER_FRAME, yea);
function yea(e:Event):void{
speed += 50;
}
It seems to me that you need a math.random() method.
explained here
I'd personally have every successful 'hit' lower a "blinkSpeed" variable by either a set fraction of a second or a percentage and use that variable as my random input "max" number. That way it would decrease the time it could be available for automatically as they play.
Hello
Well, that wouldn't be much hard! Here's a clue.
Step1 : Create a new movieclip.
Step2 : Right click on your movie clip in the library. Click properties. Check the "Export for ActionScript" checkbox. Name the class MyEnemy (for example).
Step3 : Go to the frame and pull the Actions window.
Now put this code in it :
var mc:MyEnemy= new MyEnemy() // creates a instance of the movieclip.
addChild(mc); // adds the movie clip to the stage.
Step 4 : Now that we have added a new movieclip to the stage. To add it at a random x location in the stage, you need to make use of mc's x and y fields and the Math.random() function.
Example of Math.random() :
var randomThing:Number = Math.random() * 100 // returns a number between n, where 0 <= n < 100
Now, for example, we need both x and y values relative to the stage you must multiply Math.random() with the stage's width instead. As follows :
var randomX:Number = Math.random() * stage.stageWidth // returns a number between n, where 0 <= n < stage.stageWidth
var randomY:Number = Math.random() * stage.stageWidth // returns a number between n, where 0 <= n < stage.stageWidth
And! The magic final code would be :
mc.x = randomX;
mc.y = randomY;
Edit 1 : To add multiple "mc" movieclips to stage, we would use loops, do the follow :
stage.addEventListener(Event.ENTER_FRAME, doSimple);
function doSimple (ev:Event) {
var mc:MyEnemy = new MyEnemy();
var randomX:Number = Math.random() * stage.stageWidth // returns a number between n, where 0 <= n < stage.stageWidth
var randomY:Number = Math.random() * stage.stageWidth // returns a number between n, where 0 <= n < stage.stageWidth
for (var i:Number=1; i<=10;i++){ //i is a number, you can discard the 'i<=10' if you want an infinite loop.
addChild(mc);
}
mc.x = randomX;
mc.y = randomY;
trace("yes");
}
Conclusion : I look forward for your feedback!
Related
I am drawing a circular line to varying degrees. I wish the animation to last about 0.5 seconds. For reasons I can not work out its running very slowly.
What is weird is that if I skip the tween and call the function tweenToNext it renders instantly.
var degrees:int;
var posX:int = 102;
var posY:int = 102;
var rad:int = 100;
var mc:MovieClip = new MovieClip();
addChild(mc);
mc.graphics.lineStyle(5, 0xFF0000, 1);
mc.graphics.moveTo(posX, posY - rad)
mc.i = -Math.PI / 2;
tweenToNext();
function tweenToNext(per:Number = 360):void {
degrees += 1;
if (mc.i <= (3 * Math.PI / 2) && degrees < per) {
var x:Number = posX + Math.cos(mc.i) * rad;
var y:Number = posY + Math.sin(mc.i) * rad;
mc.graphics.lineTo(x, y);
mc.i += Math.PI / 180;
TweenLite.to(mc, 0.001, {onComplete:tweenToNext});
}
}
I have tried Timer and setTimeout but these produce the same slow speed.
Flash application runs on frame-to-frame basis: frame render - script execution - frame render - script execution - frame render - script execution - and so on. That also means that whatever smallest delay you're putting there, the next call will not happen before next script execution phase, basically, next frame. Thus - guess what - your circle drawing takes 360 frames. 12 seconds if you have 30 FPS, for example.
If you want to make something synchronize with the real time, you need a different approach. I didn't check if this works, but I hope you'll get the idea and fix the mistakes if any.
var degrees:int;
var posX:int = 102;
var posY:int = 102;
var rad:int = 100;
var mc:MovieClip = new MovieClip;
addChild(mc);
mc.graphics.lineStyle(5, 0xFF0000, 1);
mc.graphics.moveTo(posX, posY + rad);
// Now, magic time.
// Save time since app start (in milliseconds).
var startTime:int = getTimer();
// 1000 milliseconds = 1 second.
var drawingTime:int = 1000;
// Store the maximum degree to draw.
var degreeLimit:int = 360;
// Call it every frame.
mc.addEventListener(Event.ENTER_FRAME, onDraw);
function onDraw(e:Event):void
{
// Now we need to check how much time passes since last frame
// and update the drawing accordingly.
var timeProgress:Number = (getTimer() - startTime) / drawingTime;
var drawingProgress:Number = degrees / degreeLimit;
// When the drawing progress catches the time progress
// the loop will end. It will resume on the next frame.
while (drawingProgress < timeProgress)
{
degrees += 1;
// It's better than a property on target canvas,
// which could be Sprite or Shape, they wouldn't take random fields.
var anAngle:Number = degrees * Math.PI / 180;
var tox:Number = posX + Math.cos(anAngle) * rad;
var toy:Number = posY + Math.sin(anAngle) * rad;
mc.graphics.lineTo(tox, toy);
// We should know when to stop it.
if (dergees >= degreeLimit)
{
mc.removeEventListener(Event.ENTER_FRAME);
return;
}
// Update the drawing progress.
drawingProgress:Number = degrees / degreeLimit;
}
}
I'm in the process of creating a simple Flash game using ActionScript 3.0 and have come across an issue when spawning my obstacles onto the scene. My aim is to have approximately 10 points across the x axis (remaining at the same y axis) and when spawning the obstacles into my scene it will pick 2-4 of those points randomly and spawn them on them.
I've got the obstacles to spawn randomly but cannot figure out how to make them spawn at random set points, from a list. If anyone could help, I would be much appreciative. Thanks
EDIT:
The code I have so far:
var a:Array = new Array();
for (var count=0; count< 5; count++) {
a[count] = new asteroidOne();
a[count].x = 100 * count + (Math.floor(Math.random() * 200));
a[count].y = 100;
addChild(a[count]);
}
// Asteroid obstacle spawning 2.0
player.addEventListener(Event.ENTER_FRAME, obstacleMove);
function obstacleMove(evt:Event):void {
for (var i=0; i< 5; i++) {
a[i].y += 5;
if (a[i].y == 480) {
a[i].y = 0;
}
if (player.hitTestObject(a[i])) {
trace("HIT");
}
}
}
Assuming you have your spawn points in an array, you could do the following:
var spawnPoints:Array = [100,200,250,300,450,500,600,800]; //your list of spawn x locations
spawnPoints.sort(randomizeArray); //lets randomize the spwanPoints
function randomizeArray(a:*, b:*):int {
return ( Math.random() < .5 ) ? 1 : -1;
}
var a:Vector.<asteroidOne> = new Vector.<asteroidOne>(); //the array for your astroids - changed to vector for possible performance and code hint improvement (basically the same as Array but every object has to be of the specified type)
for (var count:int=0; count < 5; count++) {
a.push(new asteroidOne());
a[count].x = spawnPoints.pop(); //pop removes the last element from the array and returns it
a[count].y = 100;
addChild(a[count]);
}
EDIT
To address you comments, here is a decent example:
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
var spawnTimer:Timer = new Timer(10000); //timer will tick every 10 seconds
spawnTimer.addEventListener(TimerEvent.TIMER, spawn, false, 0, true); //let's run the spawn function every timer tick
spawnTimer.start();
var spawnPoints:Array = [100,200,250,300,450,500,600,800]; //your list of spawn x locations
var spawnAmount:int = 5; //how many asteroids to have on the screen at once (you could increase this over time to make it more difficult)
var asteroids:Vector.<asteroidOne> = new Vector.<asteroidOne>(); //the array for your asteroids - changed to vector for possible performance and code hint improvement (basically the same as Array but every object has to be of the specified type)
spawn(); //lets call it right away (otherwise it will won't be called until the first timer tick in 10 seconds)
//calling this will spawn as many new asteroids as are needed to reach the given amount
function spawn(e:Event = null):void {
if(asteroids.length >= spawnAmount) return; //let's not bother running any of the code below if no new asteroids are needed
spawnPoints.sort(randomizeArray); //lets randomize the spwanPoints
var spawnIndex:int = 0;
var a:asteroidOne; //var to hold the asteroid every loop
while (asteroids.length < spawnAmount) {
a = new asteroidOne();
a.x = spawnPoints[spawnIndex];
spawnIndex++; //incriment the spawn index
if (spawnIndex >= spawnPoints.length) spawnIndex = 0; //if the index is out of range of the amount of items in the array, go back to the start
a.y = 100;
asteroids.push(a); //add it to the array/vector
addChild(a); //add it to the display
}
}
player.addEventListener(Event.ENTER_FRAME, obstacleMove);
function obstacleMove(evt:Event):void {
//this is the same as a backwards for loop - for(var i:int=asteroids.length-1;i >= 0; i--)
var i:int = asteroids.length;
while(i--){ //since we are potentially removing items from the array/vector, we need to iterate backwards - otherwise when you remove an item, the indices will have shifted and you'll eventually get an out of range error
asteroids[i].y += 5;
if (asteroids[i].y > stage.stageHeight || asteroids[i].x > stage.stageWidth || asteroids[i].x < -asteroids[i].width || asteroids[i].y < -asteroids[i].height) {
//object is out of the bounds of the stage, let's remove it
removeChild(asteroids[i]); //remove it from the display
asteroids.splice(i, 1); //remove it from the array/vector
continue; //move on to the next iteration in the for loop
}
if (player.hitTestObject(asteroids[i])) {
trace("HIT");
}
}
}
function randomizeArray(a:*, b:*):int {
return ( Math.random() < .5 ) ? 1 : -1;
}
I am trying to launch a cannonball from a cannon and have it follow a realistic path. The angle of fire changes depending on the orientation of the cannon (automatically orientates to mouse pointer). So what I'm trying to figure out, is how to move a cannonball along a parabolic path, when given an angle, and a set velocity.
I've read that this can be done without complicated trigonometry (never listened to it in highschool), and can be calculated simply by adding gravity to the yVelocity every tick. However, at this moment, I don't know how to calculate the initial yVelocity (again, depending on cannon orientation).
You can see the current animation here: http://kate.ict.op.ac.nz/~welfajw1/portfolio/videos/task3-assignment2.swf
This is all done in AS3, and the code I have is as follows:
Main timeline code:
import flash.display.*;
import flash.events.*;
import flash.geom.*;
var cannonball:ball_mc;
var angleDegree;
myCannon.addEventListener(Event.ENTER_FRAME, cannonEnterFrame);
function cannonEnterFrame(pEvt)
{
var mc = myCannon;
var mg = myCannon.myGun;
//find angle for orientation
var angleRadian = Math.atan2(mouseY - mc.y, mouseX - mc.x);
//convert to degrees
angleDegree = angleRadian * 180 / Math.PI;
//limit rotation
if(angleDegree > -63 && angleDegree < 20)
mg.rotation = angleDegree;
}
stage.addEventListener(Event.ENTER_FRAME, stageRefresh);
function stageRefresh(pEvt)
{
if (cannonball)
{
//move every "tick"
cannonball.move();
}
}
stage.addEventListener(MouseEvent.CLICK, mouseClicked);
function mouseClicked(pEvt)
{
//starting position of the ball
cannonball = new ball_mc(100, 475);
//SEND IN INITIAL x, y VELOCITIES
cannonball.fire(20, angleDegree);
//add to stage
stage.addChild(cannonball);
}
ball_mc code:
package
{
import flash.display.MovieClip;
import flash.sensors.Accelerometer;
import flashx.textLayout.formats.Float;
public class ball_mc extends MovieClip
{
//constant gravity
public static const g:Number = 2;
//starting velocities
private var ux:Number;
private var uy:Number;
public function ball_mc(startX:int, startY:int)
{
x = startX;
y = startY;
}
public function fire(vx:Number, vy:Number):void
{
ux = vx;
uy = vy;
}
public function move():void
{
//distance moved in x dir
var sx:Number = ux;
//new velocity in y dir
var vy:Number = uy + g;
//distance moved in y dir
var sy:Number = uy + g/2;
//apply movement
x += sx;
y += sy;
//save new y velocity
uy = vy;
}
}
}
You need a little bit of physics.
Initial speed must be calculated by using some criteria that you add on your own. One example is to calculate initial speed by using the distance between the mouse and the cannon, at the time the mouse is pressed. If the distance is greater the projectile will have a bigger speed, and if the distance is smaller the projectile will have smaller speed.
The you add an Event Listener with type ENTER_FRAME.
I guess it's 2 dimensional animation so you have to find the current x and y at any point in time.
Here's a little bit of code:
var TimeperFrame:Number = 1/fps //fps is not a constant, here you should add a number, a value that you previously added in fla. document properties. I usualy use 60 fps
var Time:Number = 0;
addEventListener(ENTER_FRAME, movingCannonBall);
function movingCannonBall(e:Event):void
{
Time += TimeperFrame;
}
Now here's the equitation for trajectory of projectile.
x = xo + vxo·t
y = yo + vyo·t - 0.5·g·t^2
yo = initial height of your cannon ball
vyo = initial y velocity; vyo = vo·sin θ
t = time passed, we conrol that by upper code
g = acceleration (9,81 m/s^2) at Earth's surface
xo = initial distance for the start
vxo = initial x velocity; vxo = vo·cos θ
Now in the upper code we add these equitations and it should look like this:
var TimeperFrame:Number = 1/fps
var Time:Number = 0;
var initx: Number = cannonball.x;
var inity: Number = cannonball.y;
var initVelocity: Number = (you define initial Velocity by your criteria)
var G: Number = 9.81;
addEventListener(ENTER_FRAME, movingCannonBall);
function movingCannonBall(e:Event):void
{
Time += TimeperFrame;
cannonball.x = initx + Math.cos(angle) * initVelocity * Time;
cannonball.y = inity + Math.sin(angle) * initVelocity * Time - G * Time * Time * 0.5
}
This should work. I have use this code many times and it's effiecient and also it's simple.
I have a sprite in a movie symbol that I would like to hover back and forth within a 360 radius. I was hoping to make it smooth and random. Never really venturing from its original xy cordinates.
I've tried to create some stipulations with if statements and a starting momentum. Like this:
var num = 2;
stage.addEventListener(Event.ENTER_FRAME, hover);
function hover(evt:Event):void{
//start it moving
cloudWhite.y += num;
cloudWhite.x += num;
//declare these variables
var cX = cloudWhite.x;
var cY = cloudWhite.y;
// object travels 10 pixels
var cXP = cX + 10;
var cXN = cX - 10;
var cYP = cY + 10;
var cYN = cY - 10;
// if object goes 10 pixels reverse direction of momentum (maybe)
if (cX >= cXP) {
num = -2;
}
if (cX <= cXN){
num = 2;
}
if (cY >= cYP) {
num = 2;
}
if (cY <= cYN){
num = 2;
}
Clearly this is super wrong because when it runs the object just either goes to 0,0 or to some place that only the math gods know of.
I am clearly a noob at this kind of math so i apologize but I am very excited to learn the trig behind this.
Thank you for your help and thank you for reading.
You are setting all your variables inside the ENTER_FRAME loop, so none of your conditions ever evaluates to true. On every single frame you are doing this:
cloudWhite.x += 2;
cX = cloudWhite.x;
cXP = cX + 10; // Must == cloudWhite's previous x + 10 + 2;
cXN = cX - 10; // Must == cloudWite's previous x -10 + 2;
if(cX > cXP)... // Can never be true.
if(cX < cXN)... // Can never be true.
What you need to do is:
1) Store the original position of cloudWhite somewhere outside the loop, and store it before the loop begins.
2) Define your bounds relative to the original position of cloudWhite, again before your loop begins. Also define the amount you are going to change the position with each iteration.
3) Start your loop.
4) Increment the current position of cloudWhite on each iteration. Add a little random in here if you want the shape to move in a random manner.
5) Check if the new position of cW is outside your bounds and adjust the direction if it is.
The sample below is crude and jerky but I don't know exactly what effect you're looking for. If you want smoother, longer movements in each direction, consider using the Tween class or a Tween library such as the popular Greensock one, instead of incrementing / decrementing the position manually. There's a useful discussion of this here: http://www.actionscript.org/forums/archive/index.php3/t-163836.html
import flash.display.MovieClip;
import flash.events.Event;
// Set up your variables
var original_x:Number = 100; // Original x
var original_y:Number = 100; // Original y
var x_inc:Number = 5; // X Movement
var y_inc:Number = 5; // Y Movenent
var bounds:Number = 50; // Distance from origin allowed
// Doesn't take into account width of object so is distance to nearest point.
// Create an MC to show the bounds:
var display:MovieClip = addChild(new MovieClip()) as MovieClip;
display.graphics.lineStyle(1, 0x0000FF);
display.graphics.beginFill(0x0000FF, 0.5);
display.graphics.drawRect(0-bounds, 0-bounds, bounds * 2, bounds *2);
display.x = original_x;
display.y = original_y;
addChild(display);
// Create our moving mc:
var mc:MovieClip = addChild(new MovieClip()) as MovieClip;
mc.graphics.beginFill(0xFF0000, 1);
mc.graphics.drawCircle(-10, -10, 20);
// Position it:
mc.x = original_x;
mc.y = original_y;
addChild(mc);
// Loop:
function iterate($e:Event = null):void
{
// Move the mc by a random amount related to x/y inc
mc.x += (Math.random() * (2 * x_inc))/2;
mc.y += (Math.random() * (2 * y_inc))/2;
// If the distance from the origin is greater than bounds:
if((Math.abs(mc.x - original_x)) > bounds)
{
// Reverse the direction of travel:
x_inc == 5 ? x_inc = -5 : x_inc = 5;
}
// Ditto on the y axis:
if((Math.abs(mc.y - original_y)) > bounds)
{
y_inc == 5 ? y_inc = -5 : y_inc = 5;
}
}
// Start the loop:
addEventListener(Event.ENTER_FRAME, iterate);
This should get you started. I'm sure there are any number of other ways to do this with formal trig, but this has the benefit of being very simple, and just an extension of your existing method.
I have this code that I found online that does an infinite rotating gallery, now my problem is that on enter frame it jumps and too fast. I want it to be as fast at after you hover out of the logo.
Here is the code:
//Import TweenMax
import com.greensock.TweenMax;
//Save the horizontal center
var centerX:Number = stage.stageWidth / 2;
//Save the width of the whole gallery
var galleryWidth:Number = infiniteGallery.width;
//Speed of the movement (calculated by the mouse position in the moveGallery() function)
var speed:Number = 0;
//Add an ENTER_FRAME listener for the animation
addEventListener(Event.ENTER_FRAME, moveGallery);
function moveGallery(e:Event):void {
//Calculate the new speed
speed = -(0.02 * (mouseX - centerX));
//Update the x coordinate
infiniteGallery.x+=speed;
//Check if we are too far on the right (no more stuff on the left edge)
if (infiniteGallery.x>0) {
//Update the gallery's coordinates
infiniteGallery.x= (-galleryWidth/2);
}
//Check if we are too far on the left (no more stuff on the right edge)
if (infiniteGallery.x<(-galleryWidth/2)) {
//Update the gallery's coordinates
infiniteGallery.x=0;
}
}
and here is the demo »
The speed of the scroller is based on three things:
1- The frame rate. The ENTER_FRAME event handler gets called on every frame, thus is directly influenced by the frame rate.
2- The speed damping number. In your case this is equal to 0.02. If you want to slow down the scrolling, make this a smaller number. Try 0.01 for half the speed.
3- The distance of the mouse pointer to the center x coordinate of your stage. The difference between the mouse pointer and the center of your stage is multiplied by your speed damping number. If you want the movement to stop when you are at or around the center change you code as follows:
var buffer:Number = 50;
function moveGallery(e:Event):void {
var diff = mouseX - centerX;
if (Math.abs(diff) > buffer)
speed = -(0.02 * (diff + (diff > 0 ? -buffer : buffer)));
else
speed = 0;
AS REQUESTED:
var centerX:Number = stage.stageWidth / 2;
var galleryWidth:Number = infiniteGallery.width;
var speed:Number = 0;
addEventListener(Event.ENTER_FRAME, moveGallery);
var buffer:Number = 100;
function moveGallery(e:Event):void {
var diff = mouseX - centerX;
if (Math.abs(diff) > buffer)
speed = -(0.02 * (diff + (diff > 0 ? -buffer : buffer)));
else
speed = 0;
infiniteGallery.x += speed;
if (infiniteGallery.x>0) {
infiniteGallery.x = -galleryWidth / 2;
}
if (infiniteGallery.x < -galleryWidth / 2) {
infiniteGallery.x = 0;
}
}