I am a beginner of AS3. I want to create a simple bouncing ball in a space limited in the canvas of 400*450. But it cannot work when I publish it. Anyone can help me figure this out?
PS: Is there any nice website can help me learn more things about AS3?
Here is my code:
function ballmoving(evt:Event = null):void
{
var vel_x = 5;
var vel_y = 6;
ball.x = -20;
ball.y = 280;
ball.x += vel_x;
ball.y += vel_y;
if (ball.x > stage.stageWidth - ball.width / 2 || ball.x < 0 + ball.width /2)
{
vel_x *= -1;
}
else if (ball.y > 280 || ball.y < 0 + ball.height /2)
{
vel_y *= -1;
}
}
ballmoving();
RecycleButton.addEventListener(MouseEvent.CLICK, reset);
function reset(event:MouseEvent):void
{
ball.x = -20;
ball.y = 280;
ballmoving();
}
Try something like :
var vel_x = 5;
var vel_y = 6;
function ballmoving(evt:Event = null):void
{
ball.x += vel_x;
ball.y += vel_y;
if (ball.x > stage.stageWidth - ball.width / 2 || ball.x < ball.width /2)
{
vel_x *= -1;
}
if (ball.y > 280 || ball.y < ball.height /2)
{
vel_y *= -1;
}
}
stage.addEventListener(Event.ENTER_FRAME, ballmoving);
RecycleButton.addEventListener(MouseEvent.CLICK, reset);
function reset(event:MouseEvent):void
{
ball.x = -20;
ball.y = 280;
}
Related
I know there are alot of posts about this error but im new at AS3 and i can't figure out how to use any of these specific answers to help me.
Im working on a project at school and I keep getting
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at pong_fla::MainTimeline/loop()
I have tried alot of things to try and fix this but it still keeps occuring.
Here is the code with the loop its referring to.
var ballSpeedX: int = -6;
var ballSpeedY: int = -6;
var cpuPaddleSpeed: int = 3;
var playerScore: int = 0;
var cpuScore: int = 0;
var wintotal: int = 1;
init();
function init(): void {
stage.addEventListener(Event.ENTER_FRAME, loop);
}
function calculateBallAngle(paddleY: Number, ballY: Number): Number {
var ySpeed: Number = 5 * ((ballY - paddleY) / 25);
return ySpeed;
}
function updateTextFields(): void {
playerScoreText.text = ("Player Score: " + playerScore);
cpuScoreText.text = ("CPU Score: " + cpuScore);
}
function loop(e: Event): void {
if (playerScore == wintotal) {
gotoAndStop(3);
}
if (cpuScore == wintotal) {
gotoAndStop(4);
}
if (playerPaddle.hitTestObject(ball) == true) {
if (ballSpeedX < 0) {
ballSpeedX *= -1;
ballSpeedY = calculateBallAngle(playerPaddle.y, ball.y);
}
} else if (cpuPaddle.hitTestObject(ball) == true) {
if (ballSpeedX > 0) {
ballSpeedX *= -1;
ballSpeedY = calculateBallAngle(cpuPaddle.y, ball.y);
}
}
if (cpuPaddle.y < ball.y - 10) {
cpuPaddle.y += cpuPaddleSpeed;
} else if (cpuPaddle.y > ball.y + 10) {
cpuPaddle.y -= cpuPaddleSpeed;
}
playerPaddle.y = mouseY;
if (playerPaddle.y - playerPaddle.height / 2 < 0) {
playerPaddle.y = playerPaddle.height / 2;
} else if (playerPaddle.y + playerPaddle.height / 2 > stage.stageHeight) {
playerPaddle.y = stage.stageHeight - playerPaddle.height / 2;
}
ball.x += ballSpeedX;
ball.y += ballSpeedY;
if (ball.x <= ball.width / 2) {
ball.x = ball.width / 2;
ballSpeedX *= -1;
cpuScore++;
updateTextFields();
} else if (ball.x >= stage.stageWidth - ball.width / 2) {
ball.x = stage.stageWidth - ball.width / 2;
ballSpeedX *= -1;
playerScore++;
updateTextFields();
}
if (ball.y <= ball.height / 2) {
ball.y = ball.height / 2;
ballSpeedY *= -1;
} else if (ball.y >= stage.stageHeight - ball.height / 2) {
ball.y = stage.stageHeight - ball.height / 2;
ballSpeedY *= -1;
}
}
I am new to StackOverflow, if i can improve on my question plaese let me know.
Here is the full file:
DropBox Link
it happens because MovieClips don't exist in other frames
removing the listener fixed most of the errors (not all of them, however)
if (playerScore == wintotal) {
//remove the listener when leaving the frame
stage.removeEventListener(Event.ENTER_FRAME, loop);
gotoAndStop(3);
}
if (cpuScore == wintotal) {
//remove the listener when leaving the frame
stage.removeEventListener(Event.ENTER_FRAME, loop);
gotoAndStop(4);
}
//check if MovieClips exist
if(!playerPaddle || !cpuPaddle){
return;
}
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at pong_fla::MainTimeline/loop()
actually this error says what to do. Flash cant find a MC on your stage or MC dont have that property to use ;) Just check your code again and use trace for detect what is cause your error.
This error is thrown when ActionScript can't find an object reference at the current scope. I would double check that both playerPaddle and ball exist on the stage and not inside MovieClips. Remember instance names are case sensitive so Ball wouldn't be the same as ball.
Ok i want my button to only be clickabe once it is visibe, it is invisible til you win the game(1 score of pong)
here is what i have
var buttonsStates:Object = {
"scoreBoard_W" : false
};
function checkVisibility () {
for (var scoreBoard_W:String in buttonsStates) {
if(visible == true)
{
scoreBoard_W.addEventListener(MouseEvent.CLICK, goto3);
function goto3(Event:MouseEvent)
{
gotoAndStop(1,"Menu");
}
and here is the error: Pong, Layer 'Pong', Frame 2, Line 129 1061: Call to a possibly undefined method addEventListener through a reference with static type String.
im not sure what it means, or if im on the right track any help is apperciaed
Here is all of the code
stop();
var buttonsStates:Object = {
"scoreBoard_W" : false
};
var ballSpeedX:int = -3;
var ballSpeedY:int = -2;
var cpuPaddleSpeed:int = 3;
var playerScore:int = 0;
var cpuScore:int = 0;
scoreBoard_W.visible = false;
scoreBoard_L.visible = false;
init();
function init():void
{
stage.addEventListener(Event.ENTER_FRAME, loop);
}
function calculateBallAngle(paddleY:Number, ballY:Number):Number
{
var ySpeed:Number = 5 * ((ballY - paddleY) / 25);
return ySpeed;
}
function updateTextFields():void
{
playerScoreText.text = ("Player Score: " + playerScore);
cpuScoreText.text = ("CPU Score: " + cpuScore);
}
function loop(e:Event):void
{
if (playerPaddle.hitTestObject(ball) == true)
{
if (ballSpeedX < 0)
{
ballSpeedX *= -1;
ballSpeedY = calculateBallAngle(playerPaddle.y, ball.y);
}
}
else if (cpuPaddle.hitTestObject(ball) == true )
{
if (ballSpeedX > 0)
{
ballSpeedX *= -1;
ballSpeedY = calculateBallAngle(cpuPaddle.y, ball.y);
}
}
if (cpuPaddle.y < ball.y - 10)
{
cpuPaddle.y += cpuPaddleSpeed;
}
else if (cpuPaddle.y > ball.y + 10)
{
cpuPaddle.y -= cpuPaddleSpeed;
}
playerPaddle.y = mouseY;
if (playerPaddle.y - playerPaddle.height / 2 < 0)
{
playerPaddle.y = playerPaddle.height / 2;
}
else if (playerPaddle.y + playerPaddle.height/2 > stage.stageHeight)
{
playerPaddle.y = stage.stageHeight - playerPaddle.height / 2;
}
ball.x += ballSpeedX;
ball.y += ballSpeedY;
if (ball.x <= ball.width / 2)
{
ball.x = ball.width / 2;
ballSpeedX *= -1;
cpuScore++;
updateTextFields();
}
else if (ball.x >= stage.stageWidth-ball.width/2)
{
ball.x = stage.stageWidth - ball.width / 2;
ballSpeedX *= -1;
playerScore++;
updateTextFields();
}
if (ball.y <= ball.height / 2)
{
ball.y = ball.height / 2;
ballSpeedY *= -1;
}
else if (ball.y >= stage.stageHeight-ball.height/2)
{
ball.y = stage.stageHeight - ball.height / 2;
ballSpeedY *= -1;
}
if (playerScore >= 1)
{
stage.removeEventListener(Event.ENTER_FRAME, loop);
scoreBoard_W.visible = true;
}
if (cpuScore >= 1)
{
stage.removeEventListener(Event.ENTER_FRAME, loop);
scoreBoard_L.visible = true;
}
}
Mouse.hide();
mywelcome.text = "Good Luck, " + myName;
function checkVisibility () {
for (var scoreBoard_W:String in buttonsStates) {
if(visible == true)
{
scoreBoard_W.addEventListener(MouseEvent.CLICK, goto3);
function goto3(Event:MouseEvent)
{
gotoAndStop(1,"Menu");
}
}
}
}
The problem is in this line
scoreBoard_W.addEventListener(MouseEvent.CLICK, goto3);
As you using for (var scoreBoard_W:String in buttonsStates){...} inside definition of function function checkVisibility () {...} you declare local String-type variable which block your access to button with same name.
Changing
scoreBoard_W.addEventListener(MouseEvent.CLICK, goto3);
to
this.scoreBoard_W.addEventListener(MouseEvent.CLICK, goto3);
will do the trick.
I'm programming a ball game in Adobe Flash, Javascript 3 and I getting a error at line 113( the last line ) that says:
1087: Syntax error: extra characters found after end of program.
package
{
import flash.display.MovieClip
import flash.text.TextField
import flash.events.Event
import flash.events.MouseEvent
public class DocumentMain extends MovieClip
{
public const GRAVITY:Number = 2;
public const BOUNCE_FACTOR:Number = 0.8;
public var _bounces:TextField;
public var _highscore:TextField;
public var _ball:Ball;
private var _vx:Number;
private var _vy:Number;
public function DocumentMain():void
{
_vx = 10;
_vy = 0;
_ball.buttonMode = true;
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
}
private function enterFrameHandler(e:Event):void
{
// gravitate the ball
_vy += GRAVITY;
// move the ball
_ball.x += _vx;
_ball.y += _vy;
// check boundaries for collusion
checkBoundaryCollisions();
}
private function mouseDownHandler(e:MouseEvent):void
{
//hit the ball if it has been clicked
if (e.target == _ball)
{
hit(e.target.mouseX, e.target.mouseY);
}
}
private function checkBoundaryCollisions():void
{
var left:Number;
var right:Number;
var bottom:Number;
var top:Number;
left = _ball.x - (_ball.width / 2);
right = _ball.x + (_ball.width / 2);
bottom = _ball.y + (_ball.height / 2);
top = _ball.y - (_ball.height / 2);
if (left < 0 && _vx < 0)
{
_ball.x = _ball.width / 2;
_vx *= -1;
}
else if (right > stage.stageWidth && _vx > 0)
{
_ball.x = stage.stageWidth - (_ball.width / 2);
_vx *= -1;
}
if (top < 0 && _vy < 0)
{
_ball.y = _ball.height / 2;
_vy *= -1;
}
else if (bottom > stage.stageHeight && _vy > 0)
{
_ball.y = stage.stageHeight - (_ball.height / 2);
_vy *= -BOUNCE_FACTOR;
_vx *= BOUNCE_FACTOR;
if (Number(_bounces.text) > Number(_highscore.text))
{
_highscore.text = _bounce.text;
}
_bounces.text = "0";
}
}
private function hit(hitX:Number, hitY:Number):void
{
//increment bounces
_bounces.text = String.(Number(_bounces.text) + 1);
//adjust the vertical velocity of the ball
if (_vy > 0)
{
_vy *= -BOUNCE_FACTOR / 2 ;
}
_vy -= HIT_FORCE;
//adjust the horizontaly velocity of the ball
if (_vx * hitX > 0)
{
_vx *= -BOUNCE_FACTOR;
}
_vx -= ( 2 * hitX / _ball.width) * HIT_FORCE;
}
}
}
}
get rid of the last curly brace }. You have too many at the end of the file.
I also think you mean Actionscript 3.
I have placed one large ball, "centerBall", in the center of the stage. Then I added in a
bunch of smaller ones, giving them random sizes and velocities. These will move with basic motion code and bounce off the walls. On each frame, did a distance-based collision check between each moving ball and the center ball. If I got a collision, I've calculated an offset spring target based on the angle between the two balls and the minimum distance.
There is still one problem: some of the smaller balls bypass "centerBall" boundaries and then bounce off. You can see that in the attached image. Why is happening this?
Here is the code:
import flash.display.Sprite;
import flash.events.Event;
public class Bubbles extends Sprite
{
private var balls:Array;
private var numBalls:Number = 10;
private var centerBall:Ball;
private var bounce:Number = -1;
private var spring:Number = 0.2;
public function Bubbles()
{
init();
}
private function init():void
{
balls = new Array();
centerBall = new Ball(100, 0xcccccc);
addChild(centerBall);
centerBall.x = stage.stageWidth / 2;
centerBall.y = stage.stageHeight / 2;
for(var i:uint = 0; i < numBalls; i++)
{
var ball:Ball = new Ball(Math.random() * 40 + 5, Math.random() * 0xffffff);
ball.x = Math.random() * stage.stageWidth;
ball.y = Math.random() * stage.stageHeight;
ball.vx = Math.random() * 6 - 3;
ball.vy = Math.random() * 6 - 3;
addChild(ball);
balls.push(ball);
}
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(event:Event):void
{
for(var i:uint = 0; i < numBalls; i++)
{
var ball:Ball = balls[i];
move(ball);
var dx:Number = ball.x - centerBall.x;
var dy:Number = ball.y - centerBall.y;
var dist:Number = Math.sqrt(dx * dx + dy * dy);
var minDist:Number = ball.radius + centerBall.radius;
if(dist < minDist)
{
var angle:Number = Math.atan2(dy, dx);
var targetX:Number = centerBall.x + Math.cos(angle) * minDist;
var targetY:Number = centerBall.y + Math.sin(angle) * minDist;
ball.vx += (targetX - ball.x) * spring;
ball.vy += (targetY - ball.y) * spring;
}
}
}
private function move(ball:Ball):void
{
ball.x += ball.vx;
ball.y += ball.vy;
if(ball.x + ball.radius > stage.stageWidth)
{
ball.x = stage.stageWidth - ball.radius;
ball.vx *= bounce;
}
else if(ball.x - ball.radius < 0)
{
ball.x = ball.radius;
ball.vx *= bounce;
}
if(ball.y + ball.radius > stage.stageHeight)
{
ball.y = stage.stageHeight - ball.radius;
ball.vy *= bounce;
}
else if(ball.y - ball.radius < 0)
{
ball.y = ball.radius;
ball.vy *= bounce;
}
}
}
Click here to see the pic
The problem you have is that you are doing collision detection based on them frames and not the positions.
You need to check where it is now and where it was last frame so you can keep track of its movements. This is why it goes through your center ball because you check in the current frame for a collision.
Here is a link to a time based collision detection of circles.
Timed based collision
Hope this helps ; )
UPDATE
I now have this but only one ball bounces when the flash movie is run
var array:Array = new Array;
var dx:Number = Math.random() * 20;
var dy:Number = Math.random() * 10;
var velX:Number = 5;
var velY:Number = 5;
addEventListener(Event.ENTER_FRAME, movearray);
for (var i:Number = 0; i < 20; i++) {
var ball:Ball = new Ball();
ball.x = Math.random() * 550;
ball.y = Math.random() * 400;
addChild(ball);
array.push(ball);
}
function movearray(evt:Event):void {
ball.x += velX;
ball.y += velY;
if (ball.x > stage.stageWidth - ball.width / 2 || ball.x < 0 + ball.width /2){
velX *= -1;
}
else if (ball.y > stage.stageHeight - ball.height / 2 || ball.y < 0 + ball.height /2){
velY *= -1;
}
}
Thanks any help appreciated.
Of course only one ball moves, that's because in your movearray function you are only referring to one ball instance. Since you are storing are your ball instances in an array, you have to loop through that array to check for every ball. Also, since each ball moves independently, is mandatory to store an array of ball velocities as well.
For example:
import flash.geom.Point;
var numBalls:uint = 20;
var arrayBalls:Array = new Array();
var arrayVels:Array = new Array();
//I don't know what is this for
//var dx:Number = Math.random() * 20;
//var dy:Number = Math.random() * 10;
var initialVelX:Number = 5;
var initialVelY:Number = 5;
addEventListener(Event.ENTER_FRAME, movearray);
for (var i:uint = 0; i < numBalls; i++)
{
var ball:Ball = new Ball();
ball.x = Math.random() * 550;
ball.y = Math.random() * 400;
addChild(ball);
arrayBalls.push(ball);
//use a Point to store velocities in two axis
//you could also set random starting velocities
//so each ball would move differently initially
var vel:Point = new Point(initialVelX,initialVelY);
arrayVels.push(vel);
}
function movearray(evt:Event):void
{
var ball:Ball;
var vel:Point;
for (var i:uint = 0; i < numBalls; i++)
{
ball = arrayBalls[i];
vel = arrayVels[i];
ball.x += vel.x;
ball.y += vel.y;
if (ball.x > stage.stageWidth - ball.width / 2 || ball.x < 0 + ball.width /2)
{
vel.x *= -1;
}
else if (ball.y > stage.stageHeight - ball.height / 2 || ball.y < 0 + ball.height /2)
{
vel.y *= -1;
}
}
}
To move a ball you need to specify velocity for it. Suppose a ball has velocity vx, vy. And the time between successive call of movearray is dt. So the new position of the ball is:
dx = vx * dt;
dy = vy * dt;
xNew = xOld + dx;
yNew = nOld + dy;
When a ball hits top or bottom part of the screen you need to negate vy. When ball hits left or right end you need to negate vx. For example, vx is positive and thus the ball is moving right. When it hits the right end you need to make vx = -vx, so vx is now negative and the ball will start moving left.
So you have to store velocity (may be random, just like the initial positions) for every ball and inside movearray calculate dt and new positions. And if any ball hits the wall then negate the velocity accordingly. To test the hit on wall you need to compare their x, y coordinates with screen width, height etc. To calculate dt you can keep track of calling time of movearray.
dt = currentTime - lastTimeCalled;
lastTimeCalled = currentTime;
Note that, this method will only collide on screen boundary, it won't detect ball-ball collision.