2D Change Velocity Based on Distance XY While Moving Parabolic Arc - actionscript-3

What I'm trying to achieve is that the entity moves in a parabolic curve, and no this has nothing to do with gravity before you ask.
I give the entity a target position which it should move to, but not in a straight line, it should move to that target position in a parabolic curve.
I'll Show an example below:
It doesn't matter where the start or target it, I just want the calculate the proper velocity separately for x and y. so that the x, y of the entity arrive at the target position at the exact same time.
My entity can move in 8 directions based on targetXY.
What I do is calculate the middle point for each x ,y I separately between startPositionXY and targetPositionXY. I increase the velocity until the middle point and after the middle point I decrease it. But it the Entity x and y do not reach the intented target at the same time instead one either x or y always gets there before the other depending on which direction it's moving in.
Here is what I have so far.
public function update():void {
if(!_hasInitialized){throw new ReferenceError("Fish.initialize must be called once before calling update");}
determineDirection();
determineVelocityBreakpoint();
determineDistance();
determineVelocity();
move();
}
private function move():void {
switch(this._direction){
case "left":
if(getX() > this.pos_target_x){
this. x -= velocity_x;
}else{
setX(this.pos_target_x);
}
break;
case "right":
if(getX() < this.pos_target_x){
this.x += velocity_x;
}else{
setX(this.pos_target_x);
}
break;
case "up":
if(getY() > this.pos_target_y){
this.y -= velocity_y;
}else{
setY(this.pos_target_y);
}
break;
case "down":
if(getY() < this.pos_target_y){
this.y += velocity_y;
}else{
setY(this.pos_target_y);
}
break;
case "left-up":
if(getX() > this.pos_target_x){
this.x -= velocity_x;
}else{
setX(this.pos_target_x);
}
if(getY() > this.pos_target_y){
this.y -= velocity_y;
}else{
setY(this.pos_target_y);
}
break;
case "left-down":
if(getX() > this.pos_target_x){
this.x -= velocity_x;
}else{
setX(this.pos_target_x);
}
if(getY() < this.pos_target_y){
this.y += velocity_y;
}else{
setY(this.pos_target_y);
}
break;
case "right-up":
if(getX() < this.pos_target_x){
this.x += velocity_x;
}else{
setX(this.pos_target_x);
}
if(getY() > this.pos_target_y){
this.y -= velocity_y;
}else{
setY(this.pos_target_y);
}
break;
case "right-down":
if(getX() < this.pos_target_x){
this.x += velocity_x;
}else{
setX(this.pos_target_x);
}
if(getY() < this.pos_target_y){
this.y += velocity_y;
}else{
setY(this.pos_target_y);
}
break;
case "idle":
break;
}
}
/**
* Determines the Direction
*/
private function determineDirection():void {
if( getX() as int == pos_target_x && getY() as int == pos_target_y){//Idle
this._direction = "idle";
}else{//No Idle
if( getX() != pos_target_x && getY() == pos_target_y ){//Linear X
if(getX() < pos_target_x){//right
this._direction = "right";
}else if(getX() > pos_target_x){//left
this._direction = "left";
}
}else if( getX() == pos_target_x && getY() != pos_target_y ){//Linear Y
if(getY() < pos_target_y){//down
this._direction = "down";
}else if(getY() > pos_target_y){//up
this._direction = "up";
}
}else if(getX() != pos_target_x && getY() != pos_target_y ){//Diagonal
if(getX() < pos_target_x && getY() < pos_target_y){//Right Down
this._direction = "right-down";
}else if(getX() > pos_target_x && getY() > pos_target_y){//Left Up
this._direction = "left-up";
}else if(getX() > pos_target_x && getY() < pos_target_y){//Left Down
this._direction = "left-down";
}else if(getX() < pos_target_x && getY() > pos_target_y){//Right Up
this._direction = "right-up";
}
}
}
}
/**
* Determines when the velocity should be decreased.
*/
private function determineVelocityBreakpoint():void {
_mPointX = (this.pos_old_x + this.pos_target_x) / 2;
_mPointY = (this.pos_old_y + this.pos_target_y) / 2;
}
private function determineDistance():void {
//Distance for x, y combined
this.distance_point = Math.sqrt((getX() - this.pos_target_x) * (getX() - this.pos_target_x) +
(getY() - this.pos_target_y) * (getY() - this.pos_target_y))
this.distance_x = Math.sqrt((getX() - this.pos_target_x) * (getX() - this.pos_target_x));
this.distance_y = Math.sqrt((getY() - this.pos_target_y) * (getY() - this.pos_target_y));
}
/**
* Increases and decreased the velocity.
*/
private function determineVelocity():void {
switch(this._direction){
case "left":
if(getX() <= this._mPointX){
if(this.velocity_x > this.velocity_min){
this.velocity_x -= this.velocity_inc;
}
}else{
if(velocity_x < velocity_max){
this.velocity_x += this.velocity_inc;
}
}
break;
case "right":
if(getX() >= this._mPointX){
if(this.velocity_x > this.velocity_min){
this.velocity_x -= this.velocity_inc;
}
}else{
if(velocity_x < velocity_max){
this.velocity_x += this.velocity_inc;
}
}
break;
case "up":
if(getY() <= this._mPointY){
if(this.velocity_y > this.velocity_min){
this.velocity_y -= this.velocity_inc;
}
}else{
if(velocity_y < velocity_max){
this.velocity_y += this.velocity_inc;
}
}
break;
case "down":
if(getY() >= this._mPointY){
if(this.velocity_y > this.velocity_min){
this.velocity_y -= this.velocity_inc;
}
}else{
if(velocity_y < velocity_max){
this.velocity_y += this.velocity_inc;
}
}
break;
case "left-up":
if(getX() <= this._mPointX){
if(this.velocity_x > this.velocity_min){
this.velocity_x -= this.velocity_inc;
}
}else{
if(velocity_x < velocity_max){
this.velocity_x += this.velocity_inc;
}
}
if(getY() <= this._mPointY){
if(this.velocity_y > this.velocity_min){
this.velocity_y -= this.velocity_inc;
}
}else{
if(velocity_y < velocity_max){
this.velocity_y += this.velocity_inc;
}
}
break;
case "left-down":
if(getX() <= this._mPointX){
if(this.velocity_x > this.velocity_min){
this.velocity_x -= this.velocity_inc;
}
}else{
if(velocity_x < velocity_max){
this.velocity_x += this.velocity_inc;
}
}
if(getY() >= this._mPointY){
if(this.velocity_y > this.velocity_min){
this.velocity_y -= this.velocity_inc;
}
}else{
if(velocity_y < velocity_max){
this.velocity_y += this.velocity_inc;
}
}
break;
case "right-up":
if(getX() >= this._mPointX){
if(this.velocity_x > this.velocity_min){
this.velocity_x -= this.velocity_inc;
}
}else{
if(velocity_x < velocity_max){
this.velocity_x += this.velocity_inc;
}
}
if(getY() <= this._mPointY){
if(this.velocity_y > this.velocity_min){
this.velocity_y -= this.velocity_inc;
}
}else{
if(velocity_y < velocity_max){
this.velocity_y += this.velocity_inc;
}
}
break;
case "right-down":
if(getX() >= this._mPointX){
if(this.velocity_x > this.velocity_min){
this.velocity_x -= this.velocity_inc;
}
}else{
if(velocity_x < velocity_max){
this.velocity_x += this.velocity_inc;
}
}
if(getY() >= this._mPointY){
if(this.velocity_y > this.velocity_min){
this.velocity_y -= this.velocity_inc;
}
}else{
if(velocity_y < velocity_max){
this.velocity_y += this.velocity_inc;
}
}
break;
case "idle":
break;
}
}
/**
* Set the target position and start position
*/
public function setTargetPosition(target_x:int, target_y:int):void {
this.pos_target_x = target_x;
this.pos_target_y = target_y;
this.pos_old_x = getX();
this.pos_old_y = getY();
}

Related

How do I make walls that the character cannot move through in ActionScript 3?

I have a 2D pokemon-style game where I am trying to create a wall that the trainer should not be able to move through (the trees). How would I use hitTestObject to test if the character is touching the tree and then make the character not able to move in that direction?
var upPressed:Boolean = false;
var downPressed:Boolean = false;
var leftPressed:Boolean = false;
var rightPressed:Boolean = false;
var facingDown:Boolean = false;
var noPressedU:Boolean = false;
var noPressedD:Boolean = false;
var noPressedL:Boolean = false;
var noPressedR:Boolean = false;
char.addEventListener(Event.ENTER_FRAME, fl_MoveInDirectionOfKey_2);
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_SetKeyPressed_2);
stage.addEventListener(KeyboardEvent.KEY_UP, fl_UnsetKeyPressed_2);
this.addEventListener( Event.ENTER_FRAME, handleCollision);
function fl_MoveInDirectionOfKey_2(event:Event)
{
if (upPressed && rightPressed)
{
char.y -= 5;
char.x += 5;
char.gotoAndPlay("mright");
}
else if (upPressed && leftPressed)
{
char.y -= 5;
char.x -= 5;
char.gotoAndPlay("mleft");
}
else if (upPressed)
{
char.y -= 5;
char.gotoAndPlay("mup");
}
else if (downPressed && rightPressed)
{
char.y += 5;
char.x += 5;
char.gotoAndPlay("mright");
}
else if (downPressed && leftPressed)
{
char.y += 5;
char.x -= 5;
char.gotoAndPlay("mleft");
}
else if (downPressed)
{
char.y += 5;
char.gotoAndPlay("mdown");
}
else if (leftPressed)
{
char.gotoAndPlay("mleft");
char.x -= 5;
}
else if (rightPressed)
{
char.gotoAndPlay("mright");
char.x += 5;
}
}
function fl_SetKeyPressed_2(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP :
{
upPressed = true;
break;
};
case Keyboard.DOWN :
{
downPressed = true;
break;
};
case Keyboard.LEFT :
{
leftPressed = true;
break;
};
case Keyboard.RIGHT :
{
rightPressed = true;
break;
}
}
}
function fl_UnsetKeyPressed_2(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP :
{
upPressed = false;
noPressedU = true;
lastPressed = 1;
break;
};
case Keyboard.DOWN :
{
downPressed = false;
noPressedD = true;
lastPressed = 2;
break;
};
case Keyboard.LEFT :
{
leftPressed = false;
noPressedL = true;
lastPressed = 3;
break;
};
case Keyboard.RIGHT :
{
rightPressed = false;
noPressedR = true;
lastPressed = 4;
break;
};
case Keyboard.RIGHT && Keyboard.UP :
{
rightPressed = false;
break;
}
}
}
Pardon the messy coding. ;-;

Game character appearing under stage after

I am working on a basic flash platformer game in Adobe Flash using ActionScript 3. I can't seem to get my character to start above the ground in the stage I made. I was able to move my character up into the stage, but after adding gravity and jump mechanics it can't move that high anymore so I am stuck now. I am following this tutorial but I created my own background and player. Any help is greatly appreciated.
here is the code:
import flash.events.KeyboardEvent;
//Variables
var leftPressed:Boolean = false;
var rightPressed:Boolean = false;
var upPressed:Boolean = false;
var downPressed:Boolean = false;
var xSpeed:Number = 0;
var ySpeed:Number = 0;
//variables to keep track of background x and y locations
var scrollX:Number = 0;
var scrollY:Number = 0;
//Constant Variables
var speedConstant:int = 5;
var friction:Number = 0.95;
var jumpConstant:Number = -25;
//Gravity constant
var gravityConstant:Number = 1.5;
//Variables for collission detection
var leftBumping:Boolean = false;
var rightBumping:Boolean = false;
var upBumping:Boolean = false;
var downBumping:Boolean = false;
var leftBumpPoint:Point = new Point(-30, -55);
var rightBumpPoint:Point = new Point(30, -55);
var upBumpPoint:Point = new Point(0, -120);
var downBumpPoint:Point = new Point(0, 0);
//Add listeners
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
stage.addEventListener(Event.ENTER_FRAME, loop);
//Functions for listners
function keyDownHandler(e:KeyboardEvent):void{
if(e.keyCode == Keyboard.LEFT){
leftPressed = true;
}
else if(e.keyCode == Keyboard.RIGHT){
rightPressed = true;
}
else if(e.keyCode == Keyboard.UP){
upPressed = true;
}
else if(e.keyCode == Keyboard.DOWN){
downPressed = true;
}
}
function keyUpHandler(e:KeyboardEvent):void{
if(e.keyCode == Keyboard.LEFT){
leftPressed = false;
}
else if(e.keyCode == Keyboard.RIGHT){
rightPressed = false;
}
else if(e.keyCode == Keyboard.UP){
upPressed = false;
}
else if(e.keyCode == Keyboard.DOWN){
downPressed = false;
}
}
//Main Game Loop
function loop(e:Event):void{
if(back.hitTestPoint(player.x + leftBumpPoint.x, player.y + leftBumpPoint.y, true)){
trace("leftBumping");
leftBumping = true;
} else {
leftBumping = false;
}
if(back.hitTestPoint(player.x + rightBumpPoint.x, player.y + rightBumpPoint.y, true)){
trace("rightBumping");
rightBumping = true;
} else {
rightBumping = false;
}
if(back.hitTestPoint(player.x + upBumpPoint.x, player.y + upBumpPoint.y, true)){
trace("upBumping");
upBumping = true;
} else {
upBumping = false;
}
if(back.hitTestPoint(player.x + downBumpPoint.x, player.y + downBumpPoint.y, true)){
trace("downBumping");
downBumping = true;
} else {
downBumping = false;
}
if(leftPressed){
xSpeed -= speedConstant;
} else if(rightPressed){
xSpeed += speedConstant;
}
/* if(upPressed){
ySpeed -= speedConstant;
} else if(downPressed){
ySpeed += speedConstant;
}*/
if(leftBumping){
if(xSpeed < 0){
xSpeed *= -0.5;
}
}
if(rightBumping){
if(xSpeed > 0){
xSpeed *= -0.5;
}
}
if(upBumping){
if(ySpeed < 0){
ySpeed *= -0.5;
}
}
if(downBumping){ //if we are touching the floor
if(ySpeed > 0){
ySpeed *= -0.5;
}
if(upPressed){ //and if the up arrow is pressed
ySpeed = jumpConstant; //set the y speed to the jump constant
}
}
else { //if we are not touching the floor
ySpeed += gravityConstant; //accelerate downwards
}
xSpeed *= friction;
ySpeed *= friction;
scrollX -= xSpeed;
scrollY -= ySpeed;
back.x = scrollX;
back.y = scrollY;
}

Getting NaN when easing out of a movement

I have a problem. I have made movement with friction and ease out code runs perfectly the first time it runs but doesn't run properly after the first run. I have added trace commands to debug and after the first time it runs the vx value returns NaN.
leftPressed is a Boolean
righPressed is a boolean
vx is the x velocity
friction is the speed of the ease out
public var vy:Number = 30;
public var vyInitial:Number;//This is initialised later
public var gravity:Number = 2.0;
public var vx:Number = 0.4;
public var vxInitial:Number;//This is initialised later
public var friction:Number = 0.4;
Here is the code used: Including the jumping ease code that works fine.
if (leftPressed)
{
if (vx == 0)
{
vx = vxInitial;
}
char.x -= vx;
lastMove = "Left";
}
else if (rightPressed)
{
if (vx == 0)
{
vx = vxInitial;
}
char.x += vx;
lastMove = "Right";
}
else if (rightPressed == false && leftPressed == false)
{
if (lastMove == "Right" && rightPressed == false && leftPressed == false)
{
vx -= friction;
trace(vx);
if (vx < 0)
{
lastMove = "No Move";
trace("lastMove Right");
vx = 0;
}
else if (vx > 0)
{
trace("moving left");
char.x += vx;
}
}
else if (lastMove == "Left" && rightPressed == false && leftPressed == false)
{
vx -= friction;
trace(vx);
if (vx < 0)
{
lastMove = "No Move";
trace("lastMove Left");
vx = 0;
}
else if (vx > 0)
{
trace("moving LEft");
char.x -= vx;
}
}
}
It appears that this line:
if (vx == 0)
{
vx = vxInitial;
}
Would not get called the first time, since vx is initially equal to 0.4 (not zero). During the first run vx is set to zero though:
if (vx < 0)
{
lastMove = "No Move";
trace("lastMove Right");
vx = 0;
}
So the next time it is run vx is set to the value of vxInitial, which appears to have no value:
public var vxInitial:Number;//This is initialised later (Is it?)
Set vxInitial and it shouldn't error.

Gravity only working after a keystoke AS3

Here is my problem, I am new to programming and I am following a tutorial just to learn random things. I have gotten everything to work so far except gravity. When I run the program my player is floating, but when I hit the "down" key only then the gravity takes effect.. I can't figure out why.
if(leftBumping){
if(xSpeed < 0){
xSpeed *= -0.5;
}
}
if(rightBumping){
if(xSpeed > 0){
xSpeed *= -0.5;
}
}
if(upBumping){
if(ySpeed < 0){
ySpeed *= -0.5;
}
}
if(downBumping){
if(ySpeed > 0){
ySpeed *= 0.0;
}
}
else {
ySpeed += gravityConstant;
}
I have a trace on the bumping collisions and they all work properly. If i am in open space it detect no collision, and when touching walls the output shows i am. Iv been reworking these lines for hours. PLease help
this may help also
if(aPressed){
xSpeed -= speedConstant;
} else if (dPressed){
xSpeed += speedConstant;
}
if (wPressed){
ySpeed -= speedConstant;
} else if(sPressed){
ySpeed += speedConstant;
}
if(leftBumping){
if(xSpeed < 0){
xSpeed *= -0.5;
}
}
You need to stick this bit:
ySpeed += gravityConstant;
into a function that is called every frame, like this:
this.addEventListener(Event.ENTER_FRAME, onEnterFrame)
private function onEnterFrame(e:Event):void
{
ySpeed += gravityConstant;
}
if this is happening to quickly, you will either need to reduce your gravity constant, reduce the fps, or use a timer rather than enterframe.

As3 How to flip a movieclip to face movement direction?

Working on a maze game. When the leftkey is pressed the movieclip (char) should turn 90 degrees to the left.
Correct me if i'm wrong but I thought I could use this code;
char.scaleX *= -1;
However, the most important thing is that the character doesnt go through the walls of the maze.
And I think thats my problem for implementing the code above.
Because it doesnt work properly when i put in here;
if(!mazehit) {
char.y += speed;
char.scaleX *= -1;
}
My question to you is, where do I have to put the code to flip the movieclip?
var leftArrow, rightArrow, upArrow, downArrow:Boolean;
var speed:Number = 4;
var charRadius:Number = 10;
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.ENTER_FRAME, everyFrame);
function keyPressed(event:KeyboardEvent):void {
if (event.keyCode == Keyboard.LEFT) {
leftArrow = true;
}
if (event.keyCode == Keyboard.RIGHT) {
rightArrow = true;
}
if (event.keyCode == Keyboard.UP) {
upArrow = true;
}
if (event.keyCode == Keyboard.DOWN) {
downArrow = true;
}
}
function keyReleased(event:KeyboardEvent):void {
if (event.keyCode == Keyboard.LEFT) {
leftArrow = false;
}
if (event.keyCode == Keyboard.RIGHT) {
rightArrow = false;
}
if (event.keyCode == Keyboard.UP) {
upArrow = false;
}
if (event.keyCode == Keyboard.DOWN) {
downArrow = false;
}
}
function everyFrame(event:Event):void {
var mazehit:Boolean = false;
if (leftArrow) {
for(var i:int = 0; i < speed; i++) {
if(bounds.hitTestPoint(char.x - charRadius - i, char.y, true)) {
mazehit = true;
break;
}
}
if(!mazehit) {
char.x -= speed;
}
} else if (rightArrow) {
for(var j:int = 0; j < speed; j++) {
if(bounds.hitTestPoint(char.x + charRadius + j, char.y, true)) {
mazehit = true;
break;
}
}
if(!mazehit) {
char.x += speed;
}
} else if (upArrow) {
for(var k:int = 0; k < speed; k++) {
if(bounds.hitTestPoint(char.x, char.y - charRadius - k, true)) {
mazehit = true;
break;
}
}
if(!mazehit) {
char.y -= speed;
}
} else if (downArrow) {
for(var m:int = 0; m < speed; m++) {
if(bounds.hitTestPoint(char.x, char.y + charRadius + m, true)) {
mazehit = true;
break;
}
}
if(!mazehit) {
char.y += speed;
}
}
}
thank you for your time
I would update the direction depending on the speed:
char.scaleX = (speed > 0) ? 1 : -1;
Or, by the keys that have been pressed:
if(keyLeft && !keyRight)
{
char.scaleX = -1;
}
else if(keyRight && !keyLeft)
{
char.scaleX = 1;
}
else
{
// keep current direction
}