AS3 removing event listener before child still causing null object reference - actionscript-3

I made a game of Pong with external classes, it's currently configured so that when the playerScore/cpuScore == 1, the player, CPU and ball is removed from the stage. These are removed by the main.as file calling removePlayer(), removeBall() and removeCPU() e.g.
public function removePlayer(): void
{
removeEventListener(Event.ENTER_FRAME, loop);
parent.removeChild(this);
}
The event listener gets rid of the main loop for the element before the child is removed from stage. This works fine for both the player and CPU, but for the ball I'm getting the following error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.classes::ball/loop()
Commenting out parent.removeChild(this); gets rid of the error, but obviously the ball stays visible. removeEventListener seems to have worked as the ball stops moving when called, but I'm at a loss as to why I would get the null object reference if the loop has been removed. Here is the code for my ball:
package com.classes
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.URLRequest;
public class ball extends MovieClip
{
private var theBackground:bg;
private var bounce:Sound = new Sound();
private var point:Sound = new Sound();
private var channel:SoundChannel = new SoundChannel();
public var ballSpeedX:int = -3;
public var ballSpeedY:int = -2;
public function ball(score:bg)
{
theBackground = score;
bounce.load(new URLRequest("com/sounds/sfxBounce.mp3"));
point.load(new URLRequest("com/sounds/sfxScore.mp3"));
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e:Event)
{
x += ballSpeedX;
y += ballSpeedY;
if (x <= width/2)
{
x = width/2;
ballSpeedX *= -1;
theBackground.cpuScore++;
theBackground.updateScores();
channel = point.play();
}
else if (x >= stage.stageWidth - width/2)
{
x = stage.stageWidth - width/2;
ballSpeedX *= -1;
theBackground.playerScore++;
theBackground.updateScores();
channel = point.play();
}
if (y <= height/2)
{
y = height/2;
ballSpeedY *= -1;
channel = bounce.play();
}
else if (y >= stage.stageHeight - height/2)
{
y = stage.stageHeight - height/2;
ballSpeedY *= -1;
channel = bounce.play();
}
}
public function removeBall(): void
{
removeEventListener(Event.ENTER_FRAME, loop);
parent.removeChild(this);
}
}
}
Any help or pointers would be greatly appreciated!

You can add a if (!stage) return; statement in the beginning of the loop function. Apparently you are trying to call removeBall() while processing another Event.ENTER_FRAME listener, maybe on the clock or the player or elsewhere, this hits an issue with event's listener sequence already cached inside Flash. That is, if you are removing an event listener for a certain event type from within another listener of the very same event (enter frame event qualifies), the listener still gets called for that event. You should either call removeBall() from elsewhere, not from an enterframe listener, or just have a null check in that listener to avoid weird errors popping up.
EDIT: Apparently your removeBall() is called while you do theBackground.updateScores(), and after you do this, the ball that processes the event is already removed, thus further processing of the listener is useless. Place a return statement after your sound is triggered to play in all clauses that call theBackground.updateScores() and you should be fine.
if (x <= width/2)
{
x = width/2;
ballSpeedX *= -1;
theBackground.cpuScore++;
theBackground.updateScores();
point.play();
return; // here
}
else if (x >= stage.stageWidth - width/2)
{
x = stage.stageWidth - width/2;
ballSpeedX *= -1;
theBackground.playerScore++;
theBackground.updateScores();
point.play();
return; // and here
}

Related

stop() caller not working properly

I am making a brick breaker game with three frames. The first frame is the start screen, the second frame is the game itself, and the third frame is the "game over" screen (with a try again button). When I hit "Start game" the program jumps to the second frame and stops. If you fail to hit the ball with the racket, the program jumps to frame three.
My problem occurs here, because the program instantly jumps to the second frame again. Any idea why the stop(); caller fails to work? I have tried to remove all content from the last frame (except for the stop(); caller), but it still just skips back to frame 2.
I really can't figure out why this is happening. I am using Adobe Flash Professional CC. The only actionscript on frame 3 are "stop();". This is the entire code block on frame 2:
import flash.events.KeyboardEvent;
import flash.display.Stage;
import flash.events.Event;
import flash.ui.Keyboard;
import fl.transitions.Tween;
import fl.transitions.easing.*;
trace(currentFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
this.addEventListener(Event.ENTER_FRAME, moveBall);
var rackert: bar = new bar();
rackert.name = "rackert";
rackert.y = 740;
rackert.x = 640;
addChild(rackert);
var ball: circle = new circle();
ball.y = 80;
ball.x = 640;
addChild(ball);
var ballXSpeed: Number = 12; //X Speed of the Ball
var ballYSpeed: Number = 12; //Y Speed of the Ball
function keyDown(e: KeyboardEvent) {
var key: uint = e.keyCode;
var step: uint = 35;
switch (key) {
case Keyboard.LEFT:
if (rackert.x > 0) {
var myTween: Tween = new Tween(rackert, "x", Regular.easeOut, rackert.x, rackert.x - step, 0.2, true);
} else rackert.x = 0;
break;
case Keyboard.RIGHT:
if (rackert.x + rackert.width < 1000) {
var myTween2: Tween = new Tween(rackert, "x", Regular.easeOut, rackert.x, rackert.x + step, 0.2, true);
} else rackert.x = 1000 - rackert.width;
break;
}
}
var gameOver: Boolean = false;
function moveBall(event: Event): void {
ball.x += ballXSpeed;
ball.y += ballYSpeed;
if (ball.x >= 1000 - (ball.width / 2)) {
ballXSpeed *= -1;
}
if (ball.x <= 0 + (ball.width / 2)) {
ballXSpeed *= -1;
}
if (ball.y >= stage.stageHeight) {
if (gameOver == false) {
gotoAndStop(3);
this.removeEventListener(Event.ENTER_FRAME, moveBall);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyDown);
gameOver = true;
rackert.visible = false;
}
}
if (ball.y <= 22) {
ballYSpeed *= -1;
}
if (ball.hitTestObject(rackert)) {
calcBallAngle();
}
}
function calcBallAngle(): void {
var ballPosition: Number = ball.x - rackert.x;
trace("Position: " + ballPosition);
var hitPercent: Number = (ballPosition / (rackert.width - ball.width)) - .7;
trace("percent: " + hitPercent);
ballXSpeed = hitPercent * 10;
ballYSpeed *= -1;
}
function getRandom(min: Number, max: Number): Number {
return min + (Math.random() * (max - min));
}
Change this:
if (gameOver == false) {
gotoAndPlay(3); //gotoAndPlay(); caller
gameOver = true;
rackert.visible = false;
}
To:
if (gameOver == false) {
gotoAndStop(3); //gotoAndPlay(); caller
gameOver = true;
rackert.visible = false;
}
Difference is goToAndStop(). The default behavior is to "loop" an animation, so you tell it to go to frame 3 (last frame) and it "plays" through that frame back around to 1, then 2, where you most likely have a frame script that calls stop(); to stop the play head.
Update
I believe you that you're calling stop(); in frame 3. It seems like it should work and indeed it actually is, it's just not working on the object that you're expecting it to work on. Since you're using a frame script, stop(); is being called on the InteractiveObject who's scope the frame script is inside of. Let me clarify.
Frame 3 Of Stage
-> Child on frame three called FrameScriptsArePITA
-> Double click FrameScriptsArePITA and write a frame script "stop()", the script will do nothing but stop FrameScriptsArePITA from playing.
Watch your scope. That's part of why frame scripts are... best to avoid. Using your own DocumentClass and hooking everything in your design view into corresponding classes will make things easier to solve in AS3.
I finally found the issue. I had a timer event on frame 1, which caused the bug. I simply used removeEventListener for the timer function where i skip to frame 2. As Technick Empire said, you should always be cleaning up anything including even listeners as they can even interfere with the garbage collector and cause memory leaks.

AS3 Projectile moves incorrectly

So I'm currently attempting to make a prototype for a Bullet Hell game and I've run into a bit of a dead end.
So far I can move my player perfectly, the boss moves back and forth as he is supposed to, however the projectiles have some funny behaviour. Basically, when the boss moves left/right, so do the projectiles as if they are stuck to him. They move on the y as they are supposed to, except they stop just short of the player and move no further, so I'm hoping anyone can take a look at my code and give me a hand with what's going on.
Note: Ignore the rotation stuff, that's for later implementation, I was just laying the ground work.
Projectile.as
package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
public class Projectile extends MovieClip
{
private var stageRef:Stage;
private var _xVel:Number = 0;
private var _yVel:Number = 0;
private var rotationInRadians = 0;
private const SPEED:Number = 10;
public function Projectile(stageRef:Stage, x:Number, y:Number, rotationInDegrees:Number)
{
this.stageRef = stageRef;
this.x = x;
this.y = y;
this.rotation = rotationInDegrees;
this.rotationInRadians = rotationInDegrees * Math.PI / 180;
}
public function update():void
{
this.y += SPEED;;
if(x > stageRef.stageWidth || x < 0 || y > stageRef.stageHeight || y < 0)
{
//this.removeChild(this); <- Causing a crash, will fix later
}
}
}
}
Boss.as
package
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class Boss extends MovieClip
{
private var stageRef:Stage;
private var _vx:Number = 3;
private var _vy:Number = 3;
private var fireTimer:Timer;
private var canFire:Boolean = true;
private var projectile:Projectile;
public var projectileList:Array = [];
public function Boss(stageRef:Stage, X:int, Y:int)
{
this.stageRef = stageRef;
this.x = X;
this.y = Y;
fireTimer = new Timer(300, 1);
fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true);
}
public function update():void
{
this.x += _vx;
if(this.x <= 100 || this.x >= 700)
{
_vx *= -1;
}
fireProjectile();
projectile.update();
}
public function fireProjectile():void
{
if(canFire)
{
projectile = new Projectile(stageRef, this.x / 200 + this._vx, this.y, 90);
addChild(projectile);
canFire = false;
fireTimer.start();
}
}
private function fireTimerHandler(event:TimerEvent) : void
{
canFire = true;
}
}
}
Edit: Current suggestions have been to do the following:
stage.addChild(projectile); and this.parent.addChild(projectile); both which have the projectile firing from the top left corner (0, 0) and not constantly firing from the current center of the Boss.
The other issue, which has been untouched, is the fast that the projectile stops moving after a certain point and remains on the screen.
Another Edit:
After commenting out the code with the timer I have found that the projectile stops moving entirely. The reason why it was stopping after a certain amount of time was due to the timer, when the timer elapsed the projectile stopped and another would fire.
So now I need the projectile to constantly fire and move until it hits the edge of the screen, any ideas?
The problem is you are 'addChild'ing your projectiles to your Boss as opposed the stage (or the same display level as your Boss). When your Boss moves, your projectiles will move relative to him (ie, when he moves sideways, so will they).
When your boss fires a projectile, use a custom event to trigger a fireProjectile method in the Class that is your Boss' display parent. Instantiate your projectiles there and addChild them to the same object to which you addChild your Boss (possibly the stage?).
Alternatively, if you don't want to use a custom event, in your current fireProjectile method change the addChild line to:
this.parent.addChild(projectile);
This will add projectiles to the parent object of your Boss. Although that line seems, slightly, like cheating to me.

Problems getting keyboard input in AS3

So I'm workin on a flash project where I want keyboard input. In the stage there's an instance "Car" seen from above which is supposed to be rotate and drive direction of rotation. This is what I've put together so far in AS3:
//Required stuff
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.display.Stage;
import flash.display.MovieClip;
Car.addEventListener(Event.ENTER_FRAME, this.RunGame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
//Variables
var keys:Array = []
var vDrive:Number = 3; //Car's current base speed
var vx:Number = 0; //Speed along x axis
var vy:Number = 0; //Speed along y axis
var vMax:Number = 30; //Top speed
var vRot:Number = 3; //Rotation speed
var vAcc:Number = 1.1; //Factor for acceleration
var vDeAcc:Number = 0.90; //Factor for de-acceleration
//Game Loop
RunGame();
function RunGame():void
{
// Drive forwards
if (keys[Keyboard.UP])
{
if (vDrive < vMax)
vDrive += vAcc;
}
// Reverse
if (keys[Keyboard.DOWN])
{
if (vDrive > vMax)
vDrive *= vAcc;
}
// Turn right
if (keys[Keyboard.RIGHT])
{
Car.rotation += vRot;
}
// Turn left venstre
if (keys[Keyboard.LEFT])
{
Car.rotation -= vRot;
}
//Movement
// Friction
vDrive *= vDeAcc;
//Calculating movement vector
vx = vDrive * Math.cos(toRad(Car.rotation));
vy = vDrive * Math.sin(toRad(Car.rotation));
//Update car position
Car.x -= vx ;
Car.y -= vy;
}
However, when I run the program, the arrow keys don't seem to do anything.
I also get the following compiler warnings for both "onKeyDown" and "onKeyUp":
Migration issue: The onKeyDown event handler is not triggered
automatically by Flash Player at run time in ActionScript 3.0. You
must first register this handler for the event using addEventListener
( 'keyDown', callback_handler)
Trying to add what it suggested just makes errors saying callback_handler ain't defined.
I'm now stuck trying to figure out how to make the keyboard input work. Anyone know?
You are currently missing the functions for the key listeners. You have added the listeners to the stage here:
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
Now you just need to create the functions:
function onKeyDown( e:KeyboardEvent ):void {
//add our key to the keys array
keys[e.keyCode] = e.keyCode;
}
function onKeyUp( e:KeyboardEvent ):void {
//if the key is in the keys array, set the value to null
keys[e.keyCode] = null;
}
But there is another problem here:
Car.addEventListener(Event.ENTER_FRAME, this.RunGame);
You do not need the this.RunGame, just RunGame will do, but you should get an error this method needs a parameter of type Event, so your RunGame() definition should look like this:
function RunGame(e:Event):void
Then you wouldn't call RunGame(), it is called each frame while tied to the event listener.
Edit: Please note that there are many ways to handle key events, my answer will work with your current implementation.

ActionScript 3, handling MOUSE_UP outside stage

I'm new to ActionScript 3.0. I tried a tutorial at http://www.senocular.com/flash/tutorials/as3withmxmlc/ . The demo program animates a ball and allows it to be dragged.
There was a problem with the program as written. When you drag the mouse outside the stage and release the mouse button, the ball wouldn't get the MOUSE_UP event. The code, therefore would never call stopDrag(). I searched stackoverflow for suggestions, and one suggestion was to listen to MOUSE_UP with the stage as well as the ball and add some logic for dealing with it.
I added some code to do this. I also refactored the program as written because it was pretty disorganized. Here's what I have now:
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
public class BallToss extends Sprite {
private var ball:TossableBall;
// mouse position at last call to trackMouseMvt()
private var lastMousePos:Point = new Point();
// delta mouse movement from frame L-1 to frame L, where L is last frame
private var lastDeltaMouse:Point = new Point();
public function BallToss() {
var stageBounds:Rectangle = new Rectangle(0, 0, stage.stageWidth,
stage.stageHeight);
ball = new TossableBall(50, stageBounds);
ball.x = stageBounds.width/2;
ball.y = stageBounds.height/2;
addChild(ball);
ball.addEventListener(MouseEvent.MOUSE_DOWN, grabBall);
// however I order the next two calls to addEventListener(), it seems
// that the ball's MOUSE_UP gets handled before the stage's MOUSE_UP
stage.addEventListener(MouseEvent.MOUSE_UP, handleStageMouseUp);
ball.addEventListener(MouseEvent.MOUSE_UP, releaseBall);
// initialize 'lastMousePos' and set up 'trackMouseMvt' to be called on
// every frame
lastMousePos = new Point(mouseX, mouseY);
ball.addEventListener(Event.ENTER_FRAME, trackMouseMvt);
}
private function grabBall(evt:MouseEvent):void {
trace("in grabBall");
// set ball 'glideVector' to (0,0) so it will stop moving
ball.setGlideVector(new Point(0,0));
ball.startDrag();
}
private function releaseBall(evt:MouseEvent):void {
trace("in releaseBall");
ball.stopDrag();
// set up the ball to glide at the rate of 'lastDeltaMouse'
ball.setGlideVector(lastDeltaMouse);
}
private function trackMouseMvt(evt:Event):void {
var currMouse:Point = new Point(mouseX, mouseY);
lastDeltaMouse = currMouse.subtract(lastMousePos);
lastMousePos = currMouse;
}
private function handleStageMouseUp(evt:Event):void {
trace("in handleStageMouseUp");
ball.stopDrag();
var stageBounds:Rectangle = new Rectangle(0, 0, stage.stageWidth,
stage.stageHeight);
if (ball.x > stageBounds.right - 0.5)
ball.x = stageBounds.right - 0.5;
else if (ball.x < 0)
ball.x = 0;
if (ball.y > stageBounds.bottom - 0.5)
ball.y = stageBounds.bottom - 0.5;
else if (ball.y < 0)
ball.y = 0;
}
}
}
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
import flash.geom.Rectangle;
class TossableBall extends Sprite {
private var stageBounds:Rectangle;
private var glideVector:Point = new Point();
private var friction:Number = .95;
public function TossableBall(size:Number, stageBoundsIn:Rectangle) {
stageBounds = stageBoundsIn;
graphics.lineStyle(1);
graphics.beginFill(0xFF8000);
graphics.drawCircle(0, 0, size/2);
addEventListener(Event.ENTER_FRAME, glide);
}
public function setGlideVector(glideVectorIn:Point):void {
glideVector = glideVectorIn;
}
private function glide(evt:Event):void {
x += glideVector.x;
y += glideVector.y;
var shapeBounds:Rectangle = getBounds(parent);
if (shapeBounds.left < stageBounds.left) {
glideVector.x = Math.abs(glideVector.x);
} else if (shapeBounds.right > stageBounds.right) {
glideVector.x = -Math.abs(glideVector.x);
}
if (shapeBounds.top < stageBounds.top) {
glideVector.y = Math.abs(glideVector.y);
} else if (shapeBounds.bottom > stageBounds.bottom) {
glideVector.y = -Math.abs(glideVector.y);
}
glideVector.x *= friction;
glideVector.y *= friction;
}
}
I don't like this code very much. The problem comes down to not being able to detect all the cases in one place. I would like to write something like this:
if (..ball and stage both got MOUSE_UP..) {
..handle it..;
else if (..only stage got MOUSE_UP..) {
..handle it..;
}
This logic would let me write more foolproof, simpler case handling and clearer logic. As things stand, there is a lot of complex behavior that emerges from this way of organizing the code.
The event listening model doesn't seem to make this possible. The response to events must happen individually, or must it? Is there a way to detect events that are "in the queue"?
Alternatively, I could avoid using startDrag(), i.e. avoid making the ball Sprite draggable, and have only the stage listen to MOUSE_UP, then handle all the drag logic myself. That would also let me better handle questions like where I want the ball to be positioned when the user drags outside the stage. I wonder if that is better overall.
To track object being dragged this works good for me:
ball.addEventListener(MouseEvent.MOUSE_DOWN, onBallMouseDown)
var _stage:Stage;
private function onBallMouseDown(e:MouseEvent):void
{
_stage = stage;
stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp)
stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove)
ball.startDrag();
}
private function onStageMouseMove(e:MouseEvent):void
{
// track ball coordinates
}
private function onStageMouseUp(e:MouseEvent):void
{
ball.stopDrag();
_stage.removeEventListener(MouseEvent.MOUSE_UP, onStageMouseUp)
_stage.removeEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove)
}
What about that, after years of Flash programming only now have I discovered the joys of MouseEvent.RELEASE_OUTSIDE. No more ugly hacks needed.

Pong: How to pass position of ball on the stage to the cpu paddle? -AS3

I am a beginner with AS3 and I am trying to make a basic Player vs CPU pong game(using a tutorial as reference). I apologize if this sounds stupid or obvious. I have a document class and individual classes for Ball, Player and CPU. My problem is that I don't know how to make CPU class use the co-ordinates of the movie clip ball on the stage so that it can move with respect to the ball as required to form the AI. The tutorial I have been referring has all the code for ball, player and cpu in the document class only but I have written code for everything in their respective classes.
The tutorial link http://as3gametuts.com/2011/03/19/pong-1/
My version of code. Currently the ball is bouncing off the walls but HitTest has not been applied to anything. The player paddle is moving with the arrow keys. No warnings or errors are being displayed.
Main
public class Main extends MovieClip
{
public function Main()
{
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
trace("Initialized");
}
}
Ball
public class Ball extends MovieClip
{
public var ballSpeedX:int = 5;
public var ballSpeedY:int = 6;
public function Ball()
{
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage)
}
public function onAddedToStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage)
this.x = stage.stageWidth / 2;
this.y = stage.stageHeight / 2;
this.addEventListener(Event.ENTER_FRAME, loop)
}
public function loop(e:Event):void
{
this.y += ballSpeedY;
this.x += ballSpeedX;
if ((this.y <= 0 + this.height/2) || (this.y >= stage.stageHeight - this.height/2))
{
ballSpeedY *= -1;
}
else if ((this.x <= 0 + this.width/2) || (this.x >= stage.stageWidth - this.width/2))
{
ballSpeedX *= -1;
}
}
}
TheCpu
public class TheCpu extends MovieClip
{
public var cpu:TheCpu;
public var ball:Ball;
private var vx:Number = 5;
public function TheCpu()
{
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
this.x = 240;
this.y = 10;
this.addEventListener(Event.ENTER_FRAME, loop);
}
private function loop(e:Event):void
{
/*if (this.x < ball.x - 10)
{
this.x += vx;
}
else if (this.x > ball.x + 10)
{
this.x -= vx;
}*/
}
}
I added this to my main class
private function onAddedToStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
trace("It's Alive!");
addBall();
addCPU();
}
public function addBall():void
{
var ball:MovieClip = stage.getChildByName("ball") as MovieClip
stage.addChild(ball);
}
public function addCPU():void
{
var cpu:MovieClip = stage.getChildByName("cpu") as MovieClip
stage.addChild(cpu);
}
}
but now it is giving error
TypeError: Error #2007: Parameter child must be non-null.
at flash.display::DisplayObjectContainer/addChild()
at flash.display::Stage/addChild()
at src::Main/addBall()
at src::Main/onAddedToStage()
and if I use
var ball:Ball = new Ball();
var cpu:TheCpu = new TheCpu();
I get
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at src::TheCpu()
at src::Main/addCPU()
at src::Main/onAddedToStage()
I think I am being really dumb now.
As a simpler solution.
Basically when you create the ball you could pass the instance of the ball to the CPU so that the CPU can just check where the ball is on each update/enter frame. Something like this:
var ball:Ball = new Ball();
var cpu:CPU = new CPU(ball);
I think ideally you would have an update loop that just tells each part to update itself in sequence and passes along any important information between the objects so they can update themselves appropriately (and the main update loop can track things like ball out of region/point scored etc.)
EDIT
If I understand you correctly you've placed symbols on the stage in Flash and have assigned these code blocks to each of them. So your issue is you don't know how to reference each of the instances. You could use this method to retrieve the instances you put on the stage by naming them and referring to them by name:
How do I access a movieClip on the stage using as3 class?
Alternatively you could create the instances in the Main class in the added to Stage handler by creating instances as shown in the code block above then calling:
stage.addChild(cpu);
stage.addChild(ball);
Just be sure to use the MovieClip symbol name from the library in place of CPU and Ball.
In your commented-out code in the TheCpu class, you put "ball.y" when I think you meant "ball.x".