Animated MovieClip jumps around screen randomly - actionscript-3

I have an animated MovieClip of a fly that spawns at a random location and moves across the screen by bouncing off the walls. But every time the animation starts over, it seems to "jump" to a random location. Here is the code I have for when it spawns:
private function beginClass(e:Event):void{
_root = MovieClip(root);
do {
xRandom = Math.floor(Math.random() * 500);
yRandom = Math.floor(Math.random() * 350);
this.x = xRandom;
this.y = yRandom;
} while (Math.abs(xRandom - mouseX) > 20 && Math.abs(yRandom - mouseY) > 20);
}
And this is the code for its movement:
//Bouncing the fly off of the walls
if(this.x >= stage.stageWidth-this.width){
//if the fly hits the right side
//of the screen, then bounce off
flyXSpeed *= -1;
}
if(this.x <= 0){
//if the fly hits the left side
//of the screen, then bounce off
flyXSpeed *= -1;
}
if(this.y >= stage.stageHeight-this.height){
//if the fly hits the bottom
//then bounce up
flyYSpeed *= -1;
}
if(this.y <= 0){
//if the fly hits the top
//then bounce down
flyYSpeed *= -1;
}
How do I fix it so that the fly continues moving in its appropriate path every time the animation starts over?

If I understand the problem correctly, when starting the animation you have to check if it has already been started before.
A simple boolean variable would do:
private var hasStarted:Boolean = false;
private function beginClass(e:Event):void{
_root = MovieClip(root);
if (!hasStarted) {
hasStarted = true;
do {
xRandom = Math.floor(Math.random() * 500);
yRandom = Math.floor(Math.random() * 350);
this.x = xRandom;
this.y = yRandom;
} while (Math.abs(xRandom - mouseX) > 20 && Math.abs(yRandom - mouseY) > 20);
}
}
This way it'll only execute the random placing code once.

Related

How can I code an object to spawn onto the stage in the Actions panel?

I am trying to introduce a new ball into my pong game, sort of like a power up. I am writing all of my code in the Actions panel in the first frame. The new ball should appear on the stage and start moving around randomly like the original ball. Although I am using a code snippet and not .as file. So all of my code is in the Actions panel(Accessed by pressing f9).
I would also like my dynamic text box to merge with the stage colour so that you can't see the white background.
I can't show you what the fla looks like because I have less than 10 reputation, but the dynamic text box will not merge into the background and instead has a white surrounding. This hides the ball when the ball goes up.
import flash.events.Event;
import flash.ui.Mouse;
//hide mouse
Mouse.hide();
init(); //initialises everything
var bSpeedX:int = -3.5;
var bSpeedY:int = -2.5;
// assign a maximum speed to the AI
var compPaddleSpeed:int = 3.5;
var pScore:int = 0;
var cScore:int = 0;
// Updates the score
function scoreUpdate():void {
playerScore.text = ("Player Score: " + pScore);
computerScore.text = ("AI Score: " + cScore);
}
function init():void //tells flash not to return values
{
stage.addEventListener(Event.ENTER_FRAME, loop);
}
/*we want the ySpeed to be larger if there
is a greater difference between the y
positions of the ball and paddle, so I started with
(gameBallY-padY). To convert this difference
into a number between -1 and 1, I divided
this number by 25, which
is half the height of the paddle. Finally, I wanted
the ySpeed to be more powerful than
just -1 to 1, and after a bit of trial and error
I decided to times by 5 at the end
to change the total magnitude of the new ySpeed.*/
//defying the laws of Physics
function calculategameBallAngle(padY:Number, gameBallY:Number):Number
{
var ySpeed:Number = 5 * ((gameBallY-padY) / 25 );
return ySpeed;
}
//main loop
function loop(e:Event):void
{
//makes the paddle track the mouse
playerPaddle.y = mouseY;
//paddle AI
if(compPaddle.y < gameBall.y - 10){
compPaddle.y += compPaddleSpeed;//make it go up
} else if(compPaddle.y > gameBall.y + 10){
compPaddle.y -= compPaddleSpeed;//make it go down
}
//Collisions
if( playerPaddle.hitTestObject(gameBall) == true ){
if(bSpeedX < 0){
bSpeedX *= -1;
bSpeedY = calculategameBallAngle(playerPaddle.y, gameBall.y);
}
} else if(compPaddle.hitTestObject(gameBall) == true ){
if(bSpeedX > 0){
bSpeedX *= -1;
bSpeedY = calculategameBallAngle(compPaddle.y, gameBall.y);
}
}
//makes the gameBall move
gameBall.x += bSpeedX; //each frame, we add the bSpeedX to the ball's x position.
gameBall.y += bSpeedY; //same for the bSpeedY to the ball's y postion.
// checks to see if the ball misses the paddle
if(gameBall.x <= gameBall.width/2){
gameBall.x = gameBall.width/2;
bSpeedX *= -1;
cScore ++;
scoreUpdate();
//keeps the ball within the stage
} else if(gameBall.x >= stage.stageWidth-gameBall.width/2){
gameBall.x = stage.stageWidth-gameBall.width/2;
bSpeedX *= -1;
pScore ++;
scoreUpdate();
}
if(gameBall.y <= gameBall.height/2){
gameBall.y = gameBall.height/2;
bSpeedY *= -1;
}
else if(gameBall.y >= stage.stageHeight-gameBall.height/2){
gameBall.y = stage.stageHeight-gameBall.height/2;
bSpeedY *= -1;
}
//-------------------------------------------------------
//keeps the player paddle within the stage
//check if paddle is above top of the screen
if(playerPaddle.y - playerPaddle.height/2 < 0){
playerPaddle.y = playerPaddle.height/2;
} else if(playerPaddle.y + playerPaddle.hieght/2 > stage.stageHeight){
playerPaddle.y = stage.stageHeight - playerPaddle.height/2;
//check if paddle is below bottom of the screen
} else if(playerPaddle.y + playerPaddle.height/2 > stage.stageHeight){
playerPaddle.y = stage.stageHeight - playerPaddle.height/2;
}
}
If you only want your ball to be replaced with new one which has diffrent grphics and/or speed you can for example export your ball class to action script:
Library>RMB on your symbol>Properties>ActionScript Linkage>Export for ActionScript
Type your class name under Class: field like "MyBallClass" and hit OK.
Now you can construct this ball in your code and replace old one like this:
var newBall:MyBallClass = new MyBallClass();
addChild(newBall);
newBall.x = gameBall.x; newBall.y = gameBall.y;
gameBall = newBall;
Additionally you can define new variable like var speedModifier:Number = 1; to use with:
gameBall.x += bSpeedX * speedModifier;
gameBall.y += bSpeedY * speedModifier;
And change that also when you change the ball.
If You want to have multiple balls at same time You really should consider build this in OOP. For simplest example in addition to previous one
You can create MyBallClass.as file and write in it something like:
package
{
import flash.display.Sprite;
import flash.geom.Point;
public class MyBallClass extends Sprite
{
public var speedFactor:Number;
public var speed:Point = new Point(-3.5, -2.5);
public function MyBallClass(x:Number, y:Number, speedFactor:Number = 1)
{
this.x = x; this.y = y;
this.speed = speed;
}
}
}
Now you can create container for all the balls in yor game.
var balls:Vector<MyBallClass> = Vector<MyBallClass>([]);
and run your physics for all of them in a loop.
Generally main code would look something like this:
var balls:Vector.<MyBallClass> = Vector.<MyBallClass>([]);
addBall(...)//place first ball.
function loop(e:Event):void {
processBalls();
if(wantToAddNewSuperSpeedBall) addBall(x,y,3);
...
}
function processBalls() {
for (var i:int = 0; i < balls.length; i++) {
detecCollision(balls[i]);
moveBall(balls[i]);
//any code that process a single ball...
}
}
function addBall(x:Number, y:Number, speedFactor:Number = 1) {
var newBall:MyBallClass = new MyBallClass(x,y, speedFactor);
addChild(newBall);
balls.push(newBall);
}
function moveBall(ball:MyBallClass) {
ball.x += ball.speed.x * ball.speedFactor;
ball.y += ball.speed.y * ball.speedFactor;
}
So you should modify all functions which affect ball behavior to work with ball passed as argument, not only one specific instance and then use them for all balls.
There are more to cover in this topic and this isn't maybe the best approach but I've tried to make it easy to understend. There a lot of guides for OOP so you can get better idea about what is going on if you read them.
I hope that helped you somehow.

AS3 Character jumping/falling problems

I am having problems with getting the character to jump/fail when the up arrow is pressed. I'm trying to make it so when the up arrow key is pressed once it will jump a certain height then fall.
Here is my movement code:
public var gravity:int = 2;
public function fireboyMovement(e:KeyboardEvent):void
{
if (e.keyCode == 37) //right
{
fireboy1.x = fireboy1.x -5;
checkBorder()
}
else if (e.keyCode == 39) //left
{
fireboy1.x = fireboy1.x +5;
checkBorder()
}
if (e.keyCode == 38) //up
{
fireboy1.y = fireboy1.y -20;
fireboy1.y += gravity;
checkBorder()
}
Your issue is you need to increment the players position over time (and not all at once).
You can either use a tweening engine (like tweenlite), or roll your own timer or enter frame handler.
Here is an example of the latter:
if (e.keyCode == 38) //up
{
if(!isJumping){
isJumping = true;
velocity = 50; //how much to move every increment, reset every jump to default value
direction = -1; //start by going upwards
this.addEventListener(Event.ENTER_FRAME,jumpLoop);
}
}
var isJumping:Boolean = false;
var friction:Number = .85; //how fast to slow down / speed up - the lower the number the quicker (must be less than 1, and more than 0 to work properly)
var velocity:Number;
var direction:int = -1;
function jumpLoop(){ //this is running every frame while jumping
fireboy1.y += velocity * direction; //take the current velocity, and apply it in the current direction
if(direction < 0){
velocity *= friction; //reduce velocity as player ascends
}else{
velocity *= 1 + (1 - friction); //increase velocity now that player is falling
}
if(velocity < 1) direction = 1; //if player is moving less than 1 pixel now, change direction
if(fireboy1.y > stage.stageHeight - fireboy1.height){ //stage.stageheight being wherever your floor is
fireboy1.y = stage.stageHeight - fireboy1.height; //put player on the floor exactly
//jump is over, stop the jumpLoop
this.removeEventListener(Event.ENTER_FRAME,jumpLoop);
isJumping = false;
}
}

AS3: Swipe Gesture With Velocity

So I would like to add velocity to my swipe gesture. Currently I have it moving 10 px on swipe, but I want it to move with a velocity so the user can toss the object around on the screen. Here's the code I am currently using with the object moving the 10 px.
function onSwipe (e:TransformGestureEvent):void{
player_mc.gotoAndStop(5);
if (e.offsetX == 1) {
//User swiped towards right
player_mc.x += 10;
}
if (e.offsetX == -1) {
//User swiped towards left
player_mc.x -= 10;
}
if (e.offsetY == 1) {
//User swiped towards bottom
player_mc.y += 10;
}
if (e.offsetY == -1) {
//User swiped towards top
player_mc.y -= 10;
}
if(collision(player_mc.cp, level_mc))
{
player_mc.x = player_mc.prevX;
player_mc.y = player_mc.prevY;
}
}
Thanks for the help
Here is a way you can do this: (you'll want to swap the mouse events for touch events if using on mobile)
player_mc.addEventListener(MouseEvent.MOUSE_DOWN,startSwipe);
player_mc.addEventListener(MouseEvent.MOUSE_UP,endSwipe);
var velocity:Point = new Point(); //this stores the current velocity of the object
var previous:Point = new Point(); //this stores the previous frames x/y of the object.
var isDragging:Boolean = false;
var friction:Number = .85; //this how quickly to slow down the object once the mouse is released - smaller the number (must be less than 1) the quicker the object will slow/stop
function startSwipe(e){
isDragging = true;
player_mc.startDrag(false);
this.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
}
function enterFrameHandler(e):void {
if(isDragging){
velocity.x += player_mc.x - previous.x; //we're adding the new velocity to the old one, then dividing in half to average the value - this makes it seem smoother
velocity.y += player_mc.y - previous.y;
velocity.x *= .5; //dividing in half
velocity.y *= .5;
previous.x = player_mc.x;
previous.y = player_mc.y;
}else{
velocity.x *= friction; //gradually slow down the object
velocity.y *= friction;
player_mc.x += velocity.x;
player_mc.y += velocity.y;
if(velocity.x < .05 && velocity.y < .05){ //once it gets slow enough, stop the enter frame handler
this.removeEventListener(Event.ENTER_FRAME,enterFrameHandler);
}
}
trace(velocity);
}
function endSwipe(e){
player_mc.stopDrag();
isDragging = false;
}

Resetting a players x position (Flash As3)

private function scrollStage():void
{
if (lastPosX != lastPosX)
{
canScrollStage = false;
}
else
if (lastPosX == lastPosX)
{
canScrollStage = true;
}
if (canScrollStage)
{
if (rightKey)
{
//move background left
//something.x +=(stage.stageWidth * 0.5) - character.x * 2;
}
else
if (leftKey)
{
//move backgrounf Roight
}
for (var b:int = 0; b < childrenOnStage; b++)
{
if (getChildAt(b).name == "enemy")
{
getChildAt(b).x +=(stage.stageWidth * 0.5) - character.x
}
}
ground.x += (stage.stageWidth * 0.5) - character.x
}
else
{
//move the background
}
// do this last, everything moves around object
character.x = stage.stageWidth * 0.5;
lastPosX = character.x;
}
Someone told me to move the objects around the player and then update the players x position.
This is what I've done by looking at a tutorial ("Cartoon Smart");
In my player class I have a reset function.
private var xSpeed:int;
private var resetPos:Point;
public function player()
{
addEventListener(Event.ADDED_TO_STAGE, onAdd)
}
private function onAdd(e: Event): void
{
xSpeed = 3;
resetPos = new Point(x, y);
}
public function reset():void
{
x = resetPos.x;
y = resetPos.y;
//trace(resetPos);
//trace(resetPos + "player");
}
When the player falls to death this function is called
private function playerFalls():void
{
if (character.y > stage.stageHeight)
{
//take life away and go back to check point or back to reset
character.x = stage.stageWidth * 0.5;
character.y = 20;
//goblin1.reset();
//goblin2.reset();
//goblin3.reset();
//stage.x = stage.stageWidth * 0.5;
//canScrollStage = false;
}
}
if I use
character.x = stage.stageWidth * 0.5;
Then my character ends up in the middle, but it will end up in the middle since the scroll function dictates the player to be in the center always.
character.x = (stage.stageWidth * 0.5) - 400;// moves him back
but if character falls off left of the screen then he is moved back.
Any one have a solution for this please?
My question is, I want to reset the player's x position to 300 and y position to 10;
But I can't do this because the stage shifts and the co ordinate system changes.
In order for the player to go back to the original coordinate of the stage, the stage must scroll.
That's my idea, or perhaps the ground and enemies must do the opposite?
I sincerely apologize for the late answer. Okay, so your saying that when the character falls you don't want the screen to scroll all the way back to the character's start position. What you need to do is find the start positions of your character and ground (as well as any other layers such as backgrounds etc). Then wherever your fall function comes into place simply set the character and background positions to their starting coordinates.
function fall(){
char.x=charStartX;
char.y=charStartY;
ground.x=groundStartX;
ground.y=groundStartY;
//etc
}
For example, let's say you have a check point. If player hits check point charResetPoint = 100. If player falls then set it's x pos to charResetPoint
But I can't move the players x position because it will always be stage.stageWidth/2 due to my code.
So in theory it will be difficult to make a resetPoint, because when I add goblin 1.x , it's x pos is 900, if I scroll right goblon1 x pos will change. Everythings x pos changes and so does the stages.
I can't get a grasp on the concept, sortlry

Flash AS3 Snooker Game

So, I'm absolutely useless at Flash and stupidly thought creating a Snooker game wouldn't be too difficult for a school Assignment. I grossly underestimated.
I'm trying to make the cueBall MovieClip move towards the point where the Mouse clicked on the Stage.
So far I have made the cueBall move to the point where the Mouse clicked, but I need it to keep going (unless obstructed).
I think I need to somehow calculate the angle between the cueBall MovieClip and the Mouse and then tell the MovieClip to start moving in that direction.
Suggestions? It's probably something simple, I bet...
Thanks in advance.
addEventListener(Event.ENTER_FRAME, gameSetup);
var VelocityX;
var VelocityY;
var speed = 1;
var shootCount = 0;
var mouseXPos;
var mouseYPos;
function gameSetup(e:Event) {
removeEventListener(Event.ENTER_FRAME, gameSetup);
addEventListener(Event.ENTER_FRAME, aim);
addEventListener(Event.ENTER_FRAME, shoot);
}
function aim(e:Event) {
cueStick.x = cueBall.x;
cueStick.y = cueBall.y;
cueStick.rotation = (Math.atan2(mouseY-cueStick.y, mouseX-cueStick.x))*(180/Math.PI);
if (mouseX > 25.5 && mouseX < 614.5) {
aimBall.visible = true;
aimBall.x = mouseX;
} else if (mouseX < 25.5) {
aimBall.x = 25.5;
} else if (mouseX > 614.5) {
aimBall.x = 614.5;
}
if (mouseY > 25.5 && mouseY < 294.5) {
aimBall.visible = true;
aimBall.y = mouseY;
} else if (mouseY < 25.5) {
aimBall.y = 25.5;
} else if (mouseY > 294.5) {
aimBall.y = 294.5;
}
if (mouseX > 0 && mouseX < 640 && mouseY > 0 && mouseY < 320) {
Mouse.hide();
} else {
Mouse.show();
}
addEventListener(MouseEvent.MOUSE_DOWN, drawCue);
}
function drawCue(e:MouseEvent) {
removeEventListener(Event.ENTER_FRAME, aim);
addEventListener(MouseEvent.MOUSE_UP, shotAnim);
}
function shotAnim(e:MouseEvent) {
mouseXPos = mouseX;
mouseYPos = mouseY;
cueStick.rotation = (Math.atan2(mouseYPos-cueStick.y, mouseXPos-cueStick.x))*(180/Math.PI);
VelocityX = Math.cos(mouseX-cueBall.x) * speed;
VelocityY = Math.sin(mouseY-cueBall.y) * speed;
cueStick.gotoAndPlay(2);
}
function shoot(e:Event) {
if (shootCount == 1) {
cueBall.x += VelocityX;
cueBall.y += VelocityY;
trace(VelocityX);
trace(VelocityY);
cueStick.visible = false;
} else {
cueStick.visible = true;
}
}
Maybe this example is helpful to you:
http://www.emanueleferonato.com/2008/01/05/complete-flash-pool-game-with-highscores/
If I'm understanding you right, you already have it setup so that when the mouse is clicked, the ball teleports to the mouse's location.
What you want is for the ball to move to the mouse's position over a period of time.
To do this, you will use something called an EnterFrame event. EnterFrame calls a function every frame, which you need to get the ball smoothly rolling to the mouse.
addEventListener(Event.ENTER_FRAME,update);
function update(event:Event) {
// move the ball a little bit toward the mouse
}
Then, you need to determine in what direction the ball needs to roll. You will do this with trigonometric functions. In your OnClick handler, write something like:
VelocityX = Math.cos(mouse.x-ball.x) * SPEED;
VelocityY = Math.sin(mouse.y-ball.y) * SPEED;
Then, each frame, move the ball by that amount.
addEventListener(Event.ENTER_FRAME,update);
function update(event:Event) {
ball.x += VelocityX;
ball.y += VelocityY;
}
Hope that helped!