In my platformcollision function, when the player is checking for collision on his left side everything is fine. My player doesnt go through, he can move the opposite way. However, when I put the warMage on the left and its checking if theres collision with the platform on his right side, the player immediately teleports next to the platform. I dont understand why as all I did was flip the arithmetic signs in that if statement from the other for the player to check its right side.
import flash.events.Event;
import flash.display.MovieClip;
var Key:KeyObject = new KeyObject(stage);//Help the stage checks for keypressed objects //Initialized variable integers
var hsp:Number = 0;// horizontal speed
var vsp:Number = 0;// vertical speed
var grav:Number = 2;//Gravity
var fric:Number = .5;//Friction
var floor:int = 800;//Bottom of the stage
//All Booleans
var lDown:Boolean = false;
var rDown:Boolean = false;
var jumped:Boolean = false;
var attacking:Boolean = false;
warMage.gotoAndStop("idleWarmage");//Initially starts at idle state
stage.addEventListener(Event.ENTER_FRAME, keyPressed);//Listens for buttons pressed
stage.addEventListener(Event.ENTER_FRAME, gameloop);// The physics applied to character
stage.addEventListener(Event.ENTER_FRAME, platformCollision);
function keyPressed(e:Event):void
{
if(Key.isDown(Key.LEFT))//If we pressed the left arrow button
{
lDown = true;//Condition to check if player is in running state
if(lDown = true)//If we are running left
{
hsp -= 15;//Move left
warMage.gotoAndStop("RunWarmage");//Play the running animation
warMage.scaleX = -1;//Flip the image scale
}
}else if(Key.isDown(Key.RIGHT))//If we pressed the right arrow button
{
rDown = true;//Condition to check if player is in running state
if(rDown = true)//If we are moving right
{
hsp += 15;//Move the position right
warMage.gotoAndStop("RunWarmage");//Play the animation
warMage.scaleX = 1//Face right
}
}else if(Key.isDown(Key.SPACE))//If we press the spacebar
{
warMage.gotoAndStop("AttackWarmage");//Play teh attack animation
warMage.x += 5; //Lunge right
if(warMage.scaleX == -1)//If we are initially facing left
{
warMage.x -= 10;//Lunge left
}
}else if(Key.isDown(Key.DOWN))
{
warMage.gotoAndStop("CrouchWarmage");
}else if(Key.isDown(Key.UP) || jumped == true)//If we press the up arrow or we've jumped
{
warMage.y -= 60;//vertical speed goes up to 20
jumped = true;//We know that player has jumped
warMage.gotoAndStop("JumpWarmage");//Play teh jump animation
}else if(jumped == false)//If we're not jumping
{
warMage.gotoAndStop("idleWarmage");//Return to idle position
}
}
function gameloop(e:Event):void
{
warMage.y += grav;//Apply gravity to the player
hsp *= fric;//Friction is applied to hsp to prevent infinite acceleration
warMage.x += hsp;//The plater moves horizontal position
if(warMage.x - warMage.width/2 < 0)//If the player goes past the left side
{
warMage.x = warMage.width/2;
}
if(warMage.x + warMage.width/2 > 1400)//If the player goes past right
{
warMage.x = 1400 - warMage.width/2;//Player cant go past
}
if(warMage.y < floor)//If we are above the floor
{
// warMage.y += grav;//Apply gravity to the player
grav++;//Accelerate gravity in the process
warMage.gotoAndStop("JumpWarmage");//Play the jump animation
} else //if(warMage.y - warMage.height/2 > floor)
{
jumped = false;//If we are on the floor then we're not jumping
grav = 0;//Gravity can no longer be applied
warMage.y = floor;//Player sits on top of the floor
}
}
function platformCollision(e:Event):void
{
//If the player.x is less then the left side and the player can go into the box and if the warMage.y is equal to the height
if(warMage.x - warMage.width/2 < platform.x + platform.width/2 + 2 && warMage.y - platform.y == platform.height/2)
{
warMage.x = platform.x + platform.width/2 + warMage.width/2;
//Player.x is equal to the left side of the platform
}
if(warMage.x + warMage.width/2 > platform.x - platform.width/2 - 2 && warMage.y - platform.y == platform.height/2)
{
rDown = false;
warMage.x = platform.x - platform.width/2 - warMage.width/2;
//Player.x is equal to the left side of the platform
}
}
Don't you need if/ else if in here instead of 2 ifs?
If this bit is true:
if(warMage.x - warMage.width/2 < platform.x + platform.width/2 + 2 && warMage.y - platform.y == platform.height/2)
and you set
warMage.x = platform.x + platform.width/2 + warMage.width/2;
Then the 2nd if would be true right away.
Now warMage.x is platform.x + platform.width/2 + warMage.width/2;
So checking 2nd if:
if(warMage.x + warMage.width/2 > platform.x - platform.width/2 - 2 && warMage.y - platform.y == platform.height/2)
So warMage.x (which is now platform.x + platform.width/2 + warMage.width/2) + warMage.width/2 is definitely greater than platform.x - platform.width/2 - 2 and that's why you set
warMage.x = platform.x - platform.width/2 - warMage.width/2;
right after.
Looks like platformCollision needs rethinking.
Related
I have a really interesting problem, associated with the animation of my main character in the development of my mobile game.
I have one movieclip, of my players arm/attackArm, attached to a moving animation of his body [on frame 1 of HERO]
I also have another movieclip of an arm/attackArm, attached to his jumping and falling movieclips [on frame 2 + 3 of HERO]
I need cross-communication between the two, through a variable or variables of THROWframe / CurrentThrowFrame. To be able to fix a certain bug.
The bug is that, when i throw the spear, and jump (mid throw animation) he continues where he left off in the throwing animation. HOWEVER,,,
When I jump, then throw [regardless of if hes on Frame 2 or 3, falling or proceeding upward, because both share the same ARM] ;;; upon hitting the ground, his throw animation resets back to frame 0, regardless if he was in mid throw whilst in the air.
Can anyone help? This is very specific, I Know.
Any and all Help welcome.
Here is a smidgen of code.
// PLAYER : SHOOT (OVERALL)
public function playerShoot(m:MouseEvent):void
{
//Running Shoot
///////////////
if (JungleBob.player.currentFrame == 1 && JungleBob.player.runBody.runBody2.playerWeaponArm.currentFrame == 1)
{
var angle_in_radF1:Number = Math.atan2(mouseY - (JungleBob.player.y + JungleBob.player.runBody.runBody2.playerWeaponArm.y - (36)), mouseX - (JungleBob.player.x + JungleBob.player.runBody.runBody2.playerWeaponArm.x + (32)));
var heroBullet_mcF1:MovieClip = new projectile_spear();
Heros_Bullets_Array.push(heroBullet_mcF1);
heroBullet_mcF1.x = (JungleBob.player.x + (JungleBob.player.runBody.runBody2.playerWeaponArm.x) + (32));
heroBullet_mcF1.y = (JungleBob.player.y + (JungleBob.player.runBody.runBody2.playerWeaponArm.y) - (36));
heroBullet_mcF1.rotation = angle_in_radF1 * 180/Math.PI;
JungleBob.player.runBody.runBody2.playerWeaponArm.rotation = angle_in_radF1 * 180/Math.PI + (10);
addChild(heroBullet_mcF1);
JungleBob.mainClass.randomThrowSoundTraffic();
JungleBob.player.runBody.runBody2.playerWeaponArm.gotoAndPlay(2);
(new Tween(JungleBob.Vcamera,'x',Strong.easeOut,630,625,0.5,true));
}
//Jumping and Falling Shoot
///////////////////////////
if (JungleBob.player.currentFrame >= 2 && JungleBob.player.playerWeaponArm.currentFrame == 1)
{
var angle_in_rad:Number = Math.atan2(mouseY - (JungleBob.player.y + JungleBob.player.playerWeaponArm.y - (36)), mouseX - (JungleBob.player.x + JungleBob.player.playerWeaponArm.x + (32)));
var heroBullet_mc:MovieClip = new projectile_spear();
Heros_Bullets_Array.push(heroBullet_mc);
heroBullet_mc.x = (JungleBob.player.x + (JungleBob.player.playerWeaponArm.x) + (32));
heroBullet_mc.y = (JungleBob.player.y + (JungleBob.player.playerWeaponArm.y) - (36));
heroBullet_mc.rotation = angle_in_rad * 180/Math.PI;
JungleBob.player.playerWeaponArm.rotation = angle_in_rad * 180/Math.PI + (10);
addChild(heroBullet_mc);
JungleBob.mainClass.randomThrowSoundTraffic();
JungleBob.player.playerWeaponArm.gotoAndPlay(2);
(new Tween(JungleBob.Vcamera,'x',Strong.easeOut,630,625,0.5,true));
}
}
// PLAYER : SHOOT (LISTENERS)
//
//Other Throw Frame Listener
public function otherListener(e:Event):void
{
if ((hero_mc.canJump == true) && ThrowFrame == 0)
{
stage.addEventListener(Event.ENTER_FRAME, throwFrameListener);
}
}
//Throw Frame Listener
public function throwFrameListener (e:Event):void
{
if (JungleBob.player.currentFrame == 1)
{
ThrowFrame = JungleBob.player.runBody.runBody2.playerWeaponArm.currentFrame;
}
if ( (JungleBob.player.currentFrame >= 2) && (ThrowFrame >= 2) && (hero_mc.yVelocity <= 0) )
{
JungleBob.player.playerWeaponArm.gotoAndPlay(ThrowFrame);
stage.removeEventListener(Event.ENTER_FRAME, throwFrameListener);
}
}
BEST OF LUCK
&&
THANKS IN ADVANCE
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;
}
}
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;
}
I am working on a platform game and I am having issues with some collision detection. The game is set up with many blocks that are next to each other or spaced out so the player jumps from one block to the next. Right now the player is able to jump on top of the blocks, run into the side of the blocks and get stopped if jumping into the bottom of the blocks. The issues that I am having right now is that if I get in a rare scenario where the player falls on top of a certain part of the block, the game recognizes it as the side of the block for the block next to it and the player falls through the block. So if I am jumping onto the very edge of blocks[3] and blocks[4] is right next to it, the game recognizes that the player has jumped into the side of blocks[4]. Any idea how I can go about fixing this? Below is the code for my collision detection.
function checkBlockCollisions() {
// If a player collides with a block, their motion should be stopped.
for(var i = 0; i < blocks.length; i ++) {
var angle = blocks[i].angleTo(player);
var thisTop = blocks[i].y - blocks[i].height / 2;
var thisBottom = blocks[i].y + blocks[i].height / 2;
var playerTop = player.y - player.height / 2;
var playerBottom = player.y + player.height / 2;
if(blocks[i].collidesWith(player)) {
if((angle >= 55 && angle <= 360) && player.falling) {
// If the player is above the block, then they should stop falling.
player.falling = false;
player.onBlock = true;
player.setDY(0);
// Make sure the player is not inside the block.
player.setPosition(player.x, thisTop - player.height / 2);
}
//top of block is lower than the middle of the player to the top and bottom of block is higher than the middle of the player to the bottom
if(thisTop > (player.y - player.height / 2) && thisBottom < (player.y + (player.height / 2 ))) {
// If the player runs into the side of a block, only stop the sideways motion.
player.setPosition(player.x - player.dx, player.y);
player.setDX(0);
} // end if
else if(player.falling) {
// If the player is below the block, then they should keep falling but stop accelerating upwards and sideways.
player.setDY(0);
player.setDX(0);
player.setPosition(player.x, thisBottom + player.height / 2 + 1);
} // end if
} // end if
} // end for
} // end checkBlockCollisions
Check out my engine, it's an engine written entirely for collisions and is very simple to use: https://github.com/Murplyx/AAE---Axis-Aligned-Engine
I am having trouble with testing if a rectangle has collided with another rectangle and where the collision is in relation to each object (Left, right, Top, Bottom).
My code works well in theory but there are logical issues, there are false positives when an object enters the left side of another object. The parameters I have set mean that both the top collision and left collision become true when in truth only the left should be true.
image of problem
How can I stop a double positive happening in my code, I only need basic rectangle collision and nothing more. Thank you.
//Col on top?
if (Obj1.getRect(this).bottom - vSpeed < Obj2.getRect(this).bottom &&
Obj1.getRect(this).bottom - vSpeed > Obj2.getRect(this).top)
{
if (Obj1.getRect(this).right + hSpeed > Obj2.getRect(this).left &&
Obj1.getRect(this).left + hSpeed < Obj2.getRect(this).right)
{
Obj1.y = Obj2.y - Obj1.height;
vSpeed = 0;
colTop = true;
}
}
//Col on Bottom?
else if (Obj1.getRect(this).top - vSpeed > Obj2.getRect(this).top &&
Obj1.getRect(this).top - vSpeed < Obj2.getRect(this).bottom)
{
if (Obj1.getRect(this).right + hSpeed > Obj2.getRect(this).left &&
Obj1.getRect(this).left + hSpeed < Obj2.getRect(this).right)
{
Obj1.y = Obj2.y + Obj2.height;
vSpeed = 0;
colBot = true;
}
}
//Col on left side?
if (Obj1.getRect(this).right + hSpeed > Obj2.getRect(this).left &&
Obj1.getRect(this).right + hSpeed < Obj2.getRect(this).right)
{
if (Obj1.getRect(this).bottom - vSpeed > Obj2.getRect(this).top &&
Obj1.getRect(this).top - vSpeed < Obj2.getRect(this).bottom)
{
Obj1.x = Obj2.x - (Obj2.width * 0.5);
hSpeed = 0;
colLeft = true;
}
}
//Col on right side?
else if (Obj1.getRect(this).left + hSpeed > Obj2.getRect(this).left &&
Obj1.getRect(this).left + hSpeed < Obj2.getRect(this).right)
{
if (Obj1.getRect(this).bottom - vSpeed > Obj2.getRect(this).top &&
Obj1.getRect(this).top - vSpeed < Obj2.getRect(this).bottom)
{
Obj1.x = (Obj2.x + Obj2.width) + (Obj1.width * 0.5);
hSpeed = 0;
colRight = true;
}
}
You need to separate top collision from left collision by parsing the objects' relative speed. You cannot parse top/left collision using coordinates only because they are really both true if one rectangle's top left point goes inside another rectangle. So, move your Obj1 and velocity altering code out of your array of if statements, and leave the rest of the code as is. Then you check for velocities like this:
if (colTop)
if (Obj1.getRect(this).bottom > Obj2.getRect(this).top)
colTop=false;
Etc., for other collision vars. This code means: "If the bottom of Obj1 already was under the top of Obj2, then in this frame we are not hitting the top side". So, only the left side collision flag should remain. And only then you check for resultant collision vars and adjust coordinates and velocities
The starling library provides great collision detection, including simple rectangle collision. Are your methods being called on every frame?
All you would need for Starling collision detection
is:
var bounds1:Rectangle = image1.bounds;
var bounds2:Rectangle = image2.bounds;
if (bounds1.intersects(bounds2))
trace("Collision!");
collision detection