[SOLVED] Accessing variables (x and y) from Ball object in Pong game


(Oscar) #1

I’m making a Pong game in FlashPunk. In my “Play.as” world-class, I add new Ball, new PlayerPaddle and new EnemyPaddle in the constructor.

In my EnemyPaddle class, I am writing a function to move the paddle after the ball. I need to access the y variable of the ball object for this, but I don’t know how. Basically, my code would look something like this:

private function move():void {

		if (y+height/2 < [ball].y+[ball].height/2) {
			y += speed*FP.elapsed;
		}
	}
}

How do I access the y property of the ball object? It’s not assigned to any variable as far as I’m concerned, all I’m doing is “add(new Ball);”… Any help is greatly appreciated!


(Kevin Graham) #2

You will need to access the x and y from the specific entity that you’ve loaded in the main world. I can explain this better from my computer when I get home, if someone else doesn’t get to it first. :smile:


(Zachary Lewis) #3

A simple way would be to create a new entity for the ball in Play.

public class Play extends World
{
  /** The game's ball. */
  public var theBall:Ball;

  override public function begin():void
  {
    // Save a reference to the ball.
    theBall = Ball(add(new Ball());
  }
}

Now, you can check your paddle’s world for theBall. I’ve also added some error checking for good measure.

public class EnemyPaddle extends Entity
{
  private function move():void
  {
    if (Play(world) != none && Play(world).theBall != none)
    {
      // The world is an instance of Play and theBall exists.
      if (y + halfHeight < Play(world).theBall.y + Play(world).theBall.halfHeight)
      {
        y += speed*FP.elapsed;
      }
    }
  }
}     

(Oscar) #4

Thanks! I tried assigning the ball object to a variable (public var ball:Ball = new Ball;) but I didn’t know what to do next… Can you explain how come it’s “Play(world).theBall”, because that’s the only part which I don’t understand. (I’m sorry if it’s a silly question, I’m new to actionscript, and kind of inexperienced with OOP in general.)

Also, you say it’s a “simple way” to do it… Is this not the correct approach? I couldn’t think of any other way because the ball y and paddle y need to interact somehow at least… I’d love to know if there is a better way of doing it! Thanks :slight_smile:

Edit: Also, what is the difference between assigning the new Ball object to the Ball in the begin function and in the Play constructor?


(Zachary Lewis) #5

I’m typecasting the current world as a Play, since the current world could be any number of worlds (TitleWorld, GameOverWorld, PauseWorld, et cetera). Since we only need to access theBall when the world is Play, we can typecast it to ensure that we can access theBall.

This kinda’ ties in with your first question. I don’t like not knowing if a variable is going to exist or not, and there are lots of ways you can access this. You could use a static variable, you could (my preferred solution) pass the location of theBall to the enemy paddle during your world’s update loop.

The constructor allocates all the data needed for the world. The begin function is called once the world actually begins (surprise), so you can guarantee that when you add entities, they will be properly referenced.


(Oscar) #6

Oh, I see! So I could just as well have typed “(FP.world as Play)” and that would produce the same result, if I understand correctly.

Doing it your preferred way would mean assigning a new Ball to theBall still, but also a new EnemyPaddle to theEnemyPaddle, then instead pass theBall.y into the update function of theEnemyPaddle, like so:

override public function update():void {
    theEnemyPaddle.update(theBall.y)
} 

Right? I will try this as soon as I can!

If it’s alright I have another question. When I make the “lose” part of your game, is it smart/good to make a function in the Ball class which sets a static “lost:Boolean” var to true or false, which the Play.as world-class then checks every update for example? Or should I define a lose-function completely in Play.as (which itself checks the theBall.x var)? I already have a function which checks if the ball goes offscreen. Basically I want the game to stop and an overlay which says “You lost!” (so still rendering the paddles, play-background, etc).


(Zachary Lewis) #7

That’s the basic idea. You can’t use the function name update, though. You might want a function like setTarget(x:int, y:int).

Your second question is actually really great. You’d want to hide theBall but still show the paddles. The easiest way to hide theBall is to remove it from the world. Now, if you remove theBall from Play and theEnemyPaddle is trying to get the x and y values from it each tick, you’re going to be in a bad way come losing time (all the values will be null and theEnemyPaddle will probably lose its shit).

By having Play provide the control of the entire world, this problem is actually rather simple.

override public function update():void
{
  if (theBall.x < 0)
  {
    gameOver(false);
  }
  else if(theBall.x > FP.width)
  {
    gameOver(true);
  }
  else
  {
    theEnemyPaddle.setTarget(theBall.x, theBall.y);
  }
}

protected function gameOver(playerWon:Boolean):void
{
  remove(theBall);
  if (playerWon)
  {
    // Show congratulations.
  }
  else
  {
    // Show no remorse.
  }
}

Make sense?


(Oscar) #8

Yes! Thanks so much, you’ve been extremely helpful! Seriously, I can’t thank you enough :slight_smile:


(Zachary Lewis) #9