Gravity / velocity & jump issue (AS3, platformer) - actionscript-3

I'm currently trying to program a flash game for Android.
I have more or less working gravity & velocity and hit tests - so I don't fall through my platforms.
The problem now is, as soon as I hit "jump", the hit test stops working and i fall through the platforms. If I set my character to a different, higher position I don't even fall down.
Can anyone help me figure this out?
Here is my code:
import flash.events.MouseEvent;
import flash.events.Event;
var gravity:Number = 2;
var velocity:Number = 1.1;
var jumpPower:Number = 0;
var isJumping:Boolean = false;
stage.addEventListener(Event.ENTER_FRAME, touchPlatform);
player.addEventListener(Event.ENTER_FRAME, appeal);
function touchPlatform(e:Event):void
{
if(kurz.hitTestObject(player))
{
hitPlatform = true;
}
else if(kurz2.hitTestObject(player))
{
hitPlatform = true;
}
}
function appeal(e:Event):void
{
gravity *= velocity;
player.y += gravity;
if(hitPlatform == true)
{
velocity = 0;
}
}
jump.addEventListener(MouseEvent.CLICK, doJump);
stage.addEventListener(Event.ENTER_FRAME, update);
function doJump(e:MouseEvent):void
{
if(!isJumping)
{
jumpPower = 30;
isJumping = true;
}
}
function update(e:Event):void
{
if(isJumping)
{
player.y -= jumpPower;
jumpPower -= 2;
}
else
{
isJumping = false;
}
}

Your issue is that once you start jumping, you never stop! No where (that can be reached) do you set isJumping to false. Also, your jumping value and your gravity are currently running in tandem, you only want one OR the other affecting your player at any given time.
Try something like this (see code comments for explainations)
import flash.events.MouseEvent;
import flash.events.Event;
var gravity:Number = 2;
var velocity:Number = 1.1;
var jumpPower:Number = 0;
var isJumping:Boolean = false;
jump.addEventListener(MouseEvent.CLICK, doJump);
function doJump(e:MouseEvent):void {
if(!isJumping){
jumpPower = 30;
isJumping = true;
}
}
//Just one ENTER_FRAME handler is better,
//then you have more control over the order in which code gets run
//I've combined your three into one and called it gameLoop
stage.addEventListener(Event.ENTER_FRAME, gameLoop);
function gameLoop(e:Event):void {
//this is the same, I just combined your 2 if's into one.
if(kurz.hitTestObject(player) || kurz2.hitTestObject(player)){
hitPlatform = true;
}
//you should set the velocity before assigning it to the player
if(hitPlatform == true){
velocity = 0;
gravity = 2; //you probably want to reset gravity to default too
isJumping = false; //SET isJumping to false now that you've hit a platform! <-------------
}else{
velocity = 1.1; //you need to reset velocity when not on a platform
}
//Now that we've determined the velocity and if we're jumping, let's move the player the appropriate amount
if(isJumping){
//Since we're currently jumping, use the jumpPower instead of gravity
player.y -= jumpPower;
jumpPower -= 2;
}else{
if(!hitPlatform){
//Since we're NOT JUMPING, and not on a platform, use gravity.
gravity *= velocity;
player.y += gravity;
}
}
}

Related

Having an issue with Flash Actionscript3

Wondering if you guys can help me. I've used online tutorials to create the following.
I am working on a small flash project and I've hit a wall. Basically, I've got 3 scenes. A home page, and 2 games. My home page and one of the games are programmed on the timeline within an actions layer. The third game is applied to a Main.as. The problem is that I want to apply a button called home to the Flappy game, but since I've used the .as file for this code, I'm unsure how to do it.
Basically, my question is "How do I add a button to the "Flappy" Scene? Each time i try to do it and run a test, It's playing the Flappy Game over the Scene 1.
Main.as ("Flappy" Scene3)
package{
import flash.display.MovieClip;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.events.Event; //used for ENTER_FRAME event
//import flash.events.MouseEvent;
public class Main extends MovieClip{
//These are all of the constants used.
const gravity:Number = 1.5; //gravity of the game. How fast ball falls
const dist_btw_obstacles:Number = 300; //distance between two obstacles
const ob_speed:Number = 8; //speed of the obstacle
const jump_force:Number = 15; //force with which it jumps
//variables
var player:Player = new Player();
var lastob:Obstacle = new Obstacle(); //varible to store the last obstacle in the obstacle array
var obstacles:Array = new Array(); //an array to store all the obstacles
var yspeed:Number = 0; //A variable representing the vertical speed of the bird
var score:Number = 0; //A variable representing the score
public function Main(){
init();
}
function init():void {
//initialize all the variables
player = new Player();
lastob = new Obstacle();
obstacles = new Array();
yspeed = 0;
score = 0;
//add player to center of the stage the stage
player.x = stage.stageWidth/2;
player.y = stage.stageHeight/2;
addChild(player);
//create 3 obstacles ()
createObstacle();
createObstacle();
createObstacle();
//Add EnterFrame EventListeners (which is called every frame) and KeyBoard EventListeners
addEventListener(Event.ENTER_FRAME,onEnterFrameHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, key_up);
}
private function key_up(event:KeyboardEvent){
if(event.keyCode == Keyboard.SPACE){
//If space is pressed then make the bird
yspeed = -jump_force;
}
}
function restart(){
if(contains(player))
removeChild(player);
for(var i:int = 0; i < obstacles.length; ++i){
if(contains(obstacles[i]) && obstacles[i] != null)
removeChild(obstacles[i]);
obstacles[i] = null;
}
obstacles.slice(0);
init();
}
function onEnterFrameHandler(event:Event){
//update player
yspeed += gravity;
player.y += yspeed;
//restart if the player touches the ground
if(player.y + player.height/2 > stage.stageHeight){
restart();
}
//Don't allow the sheep to go above the screen
if(player.y - player.height/2 < 0){
player.y = player.height/2;
}
//update obstacles
for(var i:int = 0;i<obstacles.length;++i){
updateObstacle(i);
}
//display the score
scoretxt.text = String(score);
}
//This functions update the obstacle
function updateObstacle(i:int){
var ob:Obstacle = obstacles[i];
if(ob == null)
return;
ob.x -= ob_speed;
if(ob.x < -ob.width){
//if an obstacle reaches left of the stage then change its position to the back of the last obstacle
changeObstacle(ob);
}
//If the bird hits an obstacle then restart the game
if(ob.hitTestPoint(player.x + player.width/2,player.y + player.height/2,true)
|| ob.hitTestPoint(player.x + player.width/2,player.y - player.height/2,true)
|| ob.hitTestPoint(player.x - player.width/2,player.y + player.height/2,true)
|| ob.hitTestPoint(player.x - player.width/2,player.y - player.height/2,true)){
restart();
}
//If the bird got through the obstacle without hitting it then increase the score
if((player.x - player.width/2 > ob.x + ob.width/2) && !ob.covered){
++score;
ob.covered = true;
}
}
//This function changes the position of the obstacle such that it will be the last obstacle and it also randomizes its y position
function changeObstacle(ob:Obstacle){
ob.x = lastob.x + dist_btw_obstacles;
ob.y = 100+Math.random()*(stage.stageHeight-200);
lastob = ob;
ob.covered = false;
}
//this function creates an obstacle
function createObstacle(){
var ob:Obstacle = new Obstacle();
if(lastob.x == 0)
ob.x = 800;
else
ob.x = lastob.x + dist_btw_obstacles;
ob.y = 100+Math.random()*(stage.stageHeight-200);
addChild(ob);
obstacles.push(ob);
lastob = ob;
}
}
}
Here is the code for my main page called "Scenery" (Scene 1) which is in an actions layer of timeline.
stop();
import flash.events.MouseEvent;
sun1.addEventListener(MouseEvent.CLICK,cloudy);
function cloudy (e:MouseEvent){
cloud1.x = cloud1.x + 10;
cloud2.x = cloud2.x - 10;
}
pong_btn.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler(event:MouseEvent):void {
gotoAndStop(1, "SheepyPong");
}
dodge_btn.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler3);
function mouseDownHandler3(event:MouseEvent):void {
gotoAndStop(1, "Flappy");
}
This is my code for a very simple "SheepyPong" (Scene2) game which is linked to from front page:
var upPressed:Boolean = false;
var downPressed:Boolean = false;
var velocityX:Number = 5;
var velocityY:Number = 5;
movieClip_1.addEventListener(Event.ENTER_FRAME, fl_MoveInDirectionOfKey);
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_SetKeyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, fl_UnsetKeyPressed);
function fl_MoveInDirectionOfKey(event:Event)
{
if (upPressed)
{
movieClip_1.y -= 5;
}
if (downPressed)
{
movieClip_1.y += 5;
}
sheep.x += velocityX;
sheep.y += velocityY;
if(sheep.y + sheep.height/2 > stage.stageHeight || sheep.y - sheep.height/2 < 0){
velocityY *= -1
}
if(sheep.hitTestObject(AI) || sheep.hitTestObject(movieClip_1)){
velocityX *= -1;
}
if (sheep.x < 0) {
score2.text = (int(score2.text) +1).toString();
sheep.x = 275;
sheep.y = 200;
velocityX *= -1;
}
if (sheep.x > stage.stageWidth) {
score1.text = (int(score1.text) +1).toString();
sheep.x = 275;
sheep.y = 200;
velocityX *= -1;
}
AI.y = sheep.y;
}
function fl_SetKeyPressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP:
{
upPressed = true;
break;
}
case Keyboard.DOWN:
{
downPressed = true;
break;
}
}
}
function fl_UnsetKeyPressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP:
{
upPressed = false;
break;
}
case Keyboard.DOWN:
{
downPressed = false;
break;
}
}//end of switch
}//end of function
home_btn.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler1);
function mouseDownHandler1(event:MouseEvent):void {
gotoAndStop(1, "Scenery");
}
I'm also getting this error in output when I run it. It's not actually affecting the outpu
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Main/onEnterFrameHandler()[/Users/mynamehere/Documents/Game/Main.as:91]
//This is line 91 in the Main.as file:
scoretxt.text = String(score);

ActionScript 3, How to get character to jump for longer

I am making a platformer game in Flash (AS3) and the code I have below works. I want my character to jump high enough to allow it time to reach a platform. The only problem with code below is the speed at which it jumps up and down and the height of the jump. Tthe space bar is what triggers the function to run.
Please help as I would much appreciate it! :)
Player.addEventListener(Event.ENTER_FRAME, fl_MoveInDirectionOfKey);
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_SetKeyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, fl_UnsetKeyPressed);
function fl_MoveInDirectionOfKey(event:Event)
{
if (spacePressed){
var gravity:Number = 9.8;
var jumping:Boolean = false;
var jumpVar:Number = 0;
if(jumping != true)
{
jumpVar = -70;
jumping = true;
}
if(jumping)
{
spacePressed = false;
Player.y += jumpVar;
jumpVar += gravity;
}
Player.addEventListener(Event.ENTER_FRAME, drop);
function drop(event:Event)
{
Player.y -= jumpVar;
jumpVar -= gravity;
if(Player.y > 350){
Player.y = 350;
}
}
Player.removeEventListener(Event.ENTER_FRAME, fl_MoveInDirectionOfKey);
Player.addEventListener(Event.ENTER_FRAME, fl_MoveInDirectionOfKey);
/*var frameNumb:Number = 0;
Player.addEventListener(Event.ENTER_FRAME, jumpup);
spacePressed = false;
function jumpup(event:Event)
{
while(frameNumb < 30){
spacePressed = false;
Player.y -= 1;
frameNumb += 0.5;
}
Player.removeEventListener(Event.ENTER_FRAME, jumpup);
Player.addEventListener(Event.ENTER_FRAME, jumpdown);
function jumpdown(){
while(frameNumb > 0){
spacePressed = false;
Player.y += 1;
frameNumb -= 0.5;
}
}
}*/
}
if (leftPressed)
{
Player.x -= speed;
Player.gotoAndStop("left");
}
if (rightPressed)
{
Player.x += speed;
Player.gotoAndStop("right");
}
}
Thanks
Your use of 9.8 for gravity is meters-per-second-per-second. Since drop() is executed every frame, you're going to get some serious fast-forward gravity, unless the program is doing only 1 FPS. So, assuming you want more fluidity than 1 FPS, consider doing
jumpVar += gravity/fps;
However, to get the exact velocity required to lift you to a height, I think the calculation is...
initialVelocityInMetersPerSecond = Math.sqrt( 2 * gravity * metersToJump )
So instead of jumpVar = -70, you would do something like...
// get posititive distance since we'll use to get a square root
var metersToJump:Number = Player.y - platform.y;
jumpVar = -Math.sqrt( 2 * gravity * metersToJump );
...and then in the ENTER_FRAME handler...
Player.y += jumpVar / fps;
jumpVar += gravity / fps;
From your example it's not the case, but if you place the platform below the Player, it won't work as you can't get the root of a negative number!
In my example code I am not fixing the height of the platform, so how you decide on the target platform is a completely separate matter.

Move and Scale a MovieClip smoothly between multiple points

I have a set-up of 3 horizontal rows with a button aligned to each of them and a character (centered to each row) that I want to move between these rows (think of Little Big Planet). I was able to program it so the character moves between the 3 rows and has a set scale when it does, but I want to see the character actually moving between the points; not just watch it teleport to the location. I've tried everything I can think of: Loops, Boolean on/off, some velocity/distance/difference shenanigans, etc., but I'm having no success getting it to move at a button click and continue moving until it reaches its point. I'm also not sure if it can be set-up to scale incrementally until it reaches a desired end scale size or not. I saw a slightly similar problem asked on a site, but solution they gave uses the Point class and a lot of math, and I have never had success getting my Flash to use Points. Any suggestions would be appreciated.
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main_Test_5 extends MovieClip
{
private var cam:MovieClip = new MovieClip();
private var player:Player = new Player();
private var topPosition:uint = 170;
private var centerPosition:uint = 270;
private var bottomPosition:uint = 370;
private var UI:UserInterface = new UserInterface();
private var testBackground:TestBackground = new TestBackground();
public function Main_Test_5():void
{
player.x = 100;
player.y = 370;
cam.addChild(player);
addChild (UI);
// add event listeners
stage.addEventListener(Event.ENTER_FRAME, checkEveryFrame);
UI.topButton.addEventListener(MouseEvent.CLICK, topButtonClick);
UI.centerButton.addEventListener(MouseEvent.CLICK, centerButtonClick);
UI.bottomButton.addEventListener(MouseEvent.CLICK, bottomButtonClick);
addChild (cam);
}
public function checkEveryFrame(event:Event):void
{
cam.x -= player.x - player.x;
cam.y -= player.y - player.y;
}
public function topButtonClick (event:MouseEvent):void
{
trace ("Top Click");
if (player.y > topPosition) // 170, player.y starts at 370
{
player.y -= 100;
}
else if (player.y <= topPosition)
{
player.y = topPosition;
}
if (player.y == topPosition)
{
player.scaleY = 0.8;
player.scaleX = 0.8;
}
else if (player.y != topPosition)
{
player.scaleY = 0.9;
player.scaleX = 0.9;
}
}
public function centerButtonClick (event:MouseEvent):void
{
trace ("Center Click");
if (player.y > centerPosition) // 270
{
player.y -= 100;
}
if (player.y < centerPosition)
{
player.y += 100;
}
if (player.y == centerPosition)
{
player.scaleY = 0.9;
player.scaleX = 0.9;
}
}
public function bottomButtonClick (event:MouseEvent):void
{
trace ("Bottom Click");
if (player.y < bottomPosition) // 370
{
player.y += 100;
}
if (player.y >= bottomPosition)
{
player.y = bottomPosition;
}
if (player.y == bottomPosition)
{
player.scaleY = 1;
player.scaleX = 1;
}
else if (player.y != bottomPosition)
{
player.scaleY = 0.9;
player.scaleX = 0.9;
}
}
}
}
Sounds like you'd like something simple. So I would suggest using a Tweening library. The most prolific of which is Greensocks TweenLite, which is now part of their Animation Platform
Using tweenlite, you would just do the following:
In place of:
player.y += 100;
You would do:
TweenLite.to(player, 1,{y: player.y + 100, ease: Quad.EaseInOut});
This would tween (move gradually over time) your player object from it's current position to the specified y (player.y + 100). It would do it over 1 second and with a nice in and out ease.
You can add more properties to the tween (scaleX/Y, x) anything really.
Do note, there are many Tweening platform alternatives, including one baked into Flash Professional. TweenLite is not free to use if you charge your end users a fee for your application. Be sure to review their license if you use it commercially.

How do I get velocity for my character in as3

im trying to make a teleporter game and my character needs to have some velocity and gravity, does anyone know what sums i need to be able to acomplish this?
This is my code so far:
var char = this.addChild(new Char());
char.width = 20;
char.height = 20;
char.x = startPos.x; //startPos is an invisible movieclip that I can move around to make the starting position
char.y = startPos.y; // accurate
var vx:Number = 0;
var vt:Number = 0;
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
function keyDownHandler (e:KeyboardEvent):void {
switch (e.keyCode) {
case Keyboard.UP:
char.y = char.y - 5
}
}
If your char only needs to go up then the following code will do the job.
But if it needs to move in all direction then much advanced code is required.
Follow Moving Character in all directions.
This is a quick solution to your need.
var gravity:Number = 2;
var velocity:Number = 1.1;
var move:Boolean = false;
function moveChar(e:Event):void
{
if(move)
{
gravity *= velocity;
char.y -= gravity; // move char
}
}
char.addEventListener(Event.ENTER_FRAME, moveChar, false, 0, true);
//Keyboard events
function keyDownHandler (e:KeyboardEvent):void
{
switch (e.keyCode)
{
case Keyboard.UP:
move = true;
}
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
function keyUpHandler (e:KeyboardEvent):void
{
move = false;
gravity = 2;
}
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);

Hit Test bounce

I'm trying to make sort of a Balloon fight game for flash. I have a ceiling at the top of the screen, so when the player hits it, it should bounce off of it. Problem is, I don't know how to go about doing that. Here is the code.
I was messing around with numbers. In the upBumping variable, where the problem lies, I wanted to have the character bounce down once it hits, but it only does this once. After, it just goes through the ceiling. Perhaps I'm going about this the wrong way?
//gravity and stuff
var gravity:Number = 0.3;
var fall:Number = 0.3;
var downBumping:Boolean = false;
var upBumping:Boolean = false;
//direction I guess
var leftKeyDown:Boolean = false;
var upKeyDown:Boolean = false;
var rightKeyDown:Boolean = false;
var spaceKeyDown:Boolean = false;
//character movement ya'll
var mainSpeed:Number = 6;
stage.addEventListener(Event.ENTER_FRAME, game);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
function game(e:Event): void{
//if certain keys are down then move dat fool
if(leftKeyDown){
Monkey.x -= mainSpeed;
}
if(rightKeyDown){
Monkey.x += mainSpeed;
}
if(upKeyDown){
fall = fall-0.9;
gravity = 0.3;
}
if(Floor.hitTestObject(Monkey)){
downBumping = true;
trace("downBumping");
}
if(Ceiling.hitTestObject(Monkey)){
upBumping = true;
trace("upBumping");
trace(Monkey.y);
}
if(upBumping){
Monkey.y += 20;
}
Monkey.y = Monkey.y+fall;
gravity = gravity*1.0;
fall = fall+gravity;
}
Here's how I would do jumping and bouncing - this does not include other code like moving left to right since you already got that
function game(e:Event):void {
if(jumping){
yVelocity += 0.1; //gravity
Monkey.y += yVelocity;
if(Floor.hitTestObject(Monkey)){
jumping = false;
while(Floor.hitTestObject(Monkey)){
y--;
}
}
if(Ceiling.hitTestObject(Monkey)){
yVelocity = 0;
while(Ceiling.hitTestObject(Monkey)){
y++;
}
}
}
if(upKeyDown && !jumping){
jumping = true;
yVelocity = -3;
}
}
Obviously, declare the variables used in this example.