Platformer game hit test - actionscript-3

Ok, so I have an object on the stage that moves on the "world" movieclip. I'm trying to make it so that when you're moving right. If the movieclip inside the moving movieclip("dude") called hitD collides with the walls in world, the dude stops moving forward.
Screen shots if it might help.
General stage dude object selected
http://prntscr.com/5bgjfq the world is everything but the ball
http://prntscr.com/5bgjuh
hitD
If anyone has any way they can modify these collision physics since my current code is sketchy as hell, all suggestions and ideas are welcome.
var started:Boolean;
const NUMLEVELS = 3;
var status:String;
stage.focus = stage;
if (! started)
{// Only ever do this once!
status = "falling";
started = true;
var speedX:Number = 5;
var speedY:Number = 0;
var topSpeedY:Number = 50;
var start_x:Number = dude.x;
var start_y:Number = dude.y;
var keysDown:Object = new Object();
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener( Event.DEACTIVATE, appDeactivate );
dude.addEventListener(Event.ENTER_FRAME, moveDude);
var W:Number = 15;
var snows:Array = new Array();
}
for (var b:int = 0; b < 50; b++)
{
var snow:Snow = new Snow();
snows.push(snow);
addChild(snow);
}
function cleanup()
{
stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.removeEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.removeEventListener( Event.DEACTIVATE, appDeactivate );
dude.removeEventListener(Event.ENTER_FRAME, moveDude);
}
function keyIsDown(key:uint):Boolean
{
return Boolean(key in keysDown);
}
function keyPressed(e:KeyboardEvent):void
{
keysDown[e.keyCode] = true;
}
function keyReleased(e:KeyboardEvent):void
{
delete keysDown[e.keyCode];
}
function appDeactivate( event:Event ):void
{
// Get rid of all keypress info when app loses focus
keysDown=new Object();
}
function moveDude(e:Event):void
{
var obj:Object = e.target; //setting dude as object
// for now, if you get off the top of the screen you win
if (obj.y < 0)
{
cleanup();
nextScene();
return;
}
// if character dies, restart
if (obj.y > stage.stageHeight + 100)
{
gotoAndStop(1);
obj.x = start_x;
obj.y = start_y;
}
if (death!=null)
{
if (obj.hitTestObject(death))
{
trace("Dead");
}
}
if (status=="falling")
{
speedY++;
if (speedY>topSpeedY)
{
speedY = topSpeedY;
}
for (i = 0; i<2*speedY; i++)
{
obj.y++;
if (world.hitTestPoint(obj.x - obj.width / 2,obj.y,true) || world.hitTestPoint(obj.x + obj.width / 2,obj.y,true))
{
status = "ground";
break;
}
}
}
else if (status == "jumping")
{
speedY--;
for (i = 0; i<2*speedY; i++)
{
obj.y--;
if (world.hitTestPoint(obj.x - obj.width / 2,obj.y - obj.height,true) || world.hitTestPoint(obj.x + obj.width / 2,obj.y - obj.height,true))
{
speedY = 0;
break;
}
}
if (speedY==0)
{
status = "falling";
}
}
else if (status == "ground")
{
if (! world.hitTestPoint(obj.x - 8,obj.y,true) && ! world.hitTestPoint(obj.x + 8,obj.y + 4,true))
{
speedY = 0;
status = "falling";
}
if (keyIsDown(Keyboard.UP))
{
status = "jumping";
speedY = 10;
}
}
if (keyIsDown(Keyboard.DOWN)&&status=="ground")
{
dude.gotoAndStop("duck");
}
else
{
if (keyIsDown(Keyboard.SHIFT))
{
speedX = 10;
}
else
{
speedX = 5;
}
if (keyIsDown(Keyboard.LEFT))
{
for (i = 0; i<speedX; i++)
{
obj.x--;
dude.ball.rotation--; //dude.ball is a movieclip similar to dude.hitD, it spins when you move.
if (world.hitTestPoint(obj.x - obj.width / 2 + 4,obj.y - 8,true) || world.hitTestPoint(obj.x - obj.width / 2,obj.y - obj.height + 8,true))
{
dude.ball.rotation++;
obj.x++;
break;
}
}
}
else if (keyIsDown(Keyboard.RIGHT))
{
//dude.gotoAndStop("right");
//obj.scaleX = 1;
for (i = 0; i<speedX; i++)
{
obj.x++;
dude.ball.rotation++;
// The number in obj.y-4 affects the climbing ability
if (status == "ground")
{
//dude.height+= 0.1;
//dude.width += 0.1;
}//so here I'm checking if it hits the lower corner or top right corner or hitD
if (world.hitTestPoint(dude.hitD.x + obj.hitD.width/2 , obj.hitD.y,true) || world.hitTestPoint(obj.hitD.x + obj.hitD.width/2,obj.hitD.y - obj.hitD.height ,true))
//if (world.hitTestObject(obj))
{
dude.ball.rotation--;
obj.x--;
break;
}
}
}
dude.gotoAndStop(1);
}
while (status == "ground" && (world.hitTestPoint(obj.x-8, obj.y-1, true) || world.hitTestPoint(obj.x+8, obj.y-1, true)))
{
obj.y--;
}
const BORDER = 50;
var diff:int;
// Check right border:
diff = obj.x + BORDER - stage.stageWidth;
if (diff>0 && world.x>=stage.stageWidth-world.width)
{
obj.x -= diff;
world.x -= diff;
background1.x -= diff;
if (death != null)
{
death.x -= diff;
}
}
// Check left border:
diff = obj.x - BORDER;
if (diff<0 && world.x<=0)
{
obj.x -= diff;
world.x -= diff;
background1.x -= diff;
if (death != null)
{
death.x -= diff;
}
}
// Check bottom border:
diff = obj.y + BORDER - stage.stageHeight;
if (diff>0)
{
obj.y -= diff;
world.y -= diff;
background1.y -= diff;
if (death != null)
{
death.y -= diff;
}
}
// Check top border:
diff = obj.y - BORDER;
if (diff<0)
{
obj.y -= diff;
world.y -= diff;
background1.y -= diff;
if (death != null)
{
death.y -= diff;
}
}
if (obj.x > stage.stageWidth - 25)
{
if (currentFrame<NUMLEVELS)
{
gotoAndStop(currentFrame+1);
obj.x = 25;
}
else
{
obj.x = stage.stageWidth - 25;
}
}
else if (obj.x<25)
{
if (currentFrame>1)
{
gotoAndStop(currentFrame-1);
obj.x = stage.stageWidth - 25;
}
else
{
obj.x = 25;
}
}
}
Thanks in advance for any help you can provide :)

For player physics, it's more clear approach to make a central ENTER_FRAME handler function that just for calculating the transformations to be applied to player.
You can still get information from out, but you just process the final output there. Else, it could be problematic, especially when things gets more complex and when you want to add some more feature.(e.g. Imagine in the future, you wanted to add fans on the ground that blows air up, and player have to rise when on them. There you have a lot to change, and probably with many problems.
For collision detection, this function will provide you this information: to which direction(s) the player can't go with variables 'UpColl', 'DownColl', 'Right Coll' and 'LeftColl'.
Then you can refer to this information from your main function that applies the transformation to your player. I'll give example to that also below.
function collEveryFrame(event:Event):void
{
// capture player positions
player_x = WORLD.player.x;
player_y = WORLD.player.y;
// the movie clip object where you store your solid objects. Remember, ALL MovieClip objets inside this MovieClip will taken as solid objects in your game, and regardless their shape, their boundingBox will be taken as collison. So they will all be square.
collContainer = WORLD.cW;
// your player's collision object
playerColl = WORLD.player;
// RIGHT SQUARE COLLISION DETECTION
for (var i:int; i < collContainer.numChildren; i++)
{
// Check if any collision object colliding with player
if (playerColl.hitTestObject(collContainer.getChildAt(i)))
{
// One collision detected. Check 'from which side' does the player colliding with the object;
if (collContainer.getChildAt(i).y > playerColl.y + playerColl.height - p1MoveSpeed)
{
playerColl.y = collContainer.getChildAt(i).y - playerColl.height;
DownColl = true;
}
else if (collContainer.getChildAt(i).y + collContainer.getChildAt(i).height < playerColl.y + p1MoveSpeed)
{
playerColl.y = collContainer.getChildAt(i).y + collContainer.getChildAt(i).height;
UpColl = true;
}
else if (collContainer.getChildAt(i).x + collContainer.getChildAt(i).width < playerColl.x + p1MoveSpeed)
{
playerColl.x = + collContainer.getChildAt(i).x + collContainer.getChildAt(i).width;
LeftColl = true;
}
else if (collContainer.getChildAt(i).x > playerColl.x + playerColl.width - p1MoveSpeed)
{
playerColl.x = + collContainer.getChildAt(i).x - playerColl.width;
RightColl = true;
}
}
}
// RIGHT SQUARE COLLISION DETECTION [End]
}
Transformation function;
function playerMovement(event:Event):void
{
// (apply this for all sides)
// if nothing keeps player from going right;
if (! RightColl)
{
// Apply everything currently pushing the player to right
if (keyIsDown(Keyboard.RIGHT))
{
movement_Right = 15;
}else{
movement_Right = 0;
}
// example fictional wind function returns wind speed
windSpeed = getWindSpeed();
player.x += movement_Right + windSpeed + etc + etc;
// say windSpeed is -5 (Wind is coming from right, so pushing the player to left)
// so if user pressing right arrow key, player will move to right 10px for every frame, else 5px to left, etc.
}
}
In this way, everything about physics will be easy to implement.
For example, when calculating the movement to down, add gravity and jump etc.

Related

ActionScript3: What code should I use to stop the player controlled sprite from moving?

I'm very new to ActionScript3 and am making an asteroids-type game. Right now, the ship continues floating in a straight line when you let go of the movement buttons, and I want to be able to stop that from happening. I'm thinking either a dedicated button for braking, like the b key, or if the keys are not pressed to stop movement, whichever would be easier. Like I said I'm really new to AS3 so not even sure what part of my code is making them keep flying in a straight line. Here is the code to control movement for reference:
// register key presses
public function keyDownFunction(event:KeyboardEvent) {
if (event.keyCode == 37) {
leftArrow = true;
} else if (event.keyCode == 39) {
rightArrow = true;
} else if (event.keyCode == 38) {
upArrow = true;
//Add event listener for down arrow
} else if (event.keyCode == 40) {
downArrow = true;
// show thruster
if (gameMode == "play") ship.gotoAndStop(2);
} else if (event.keyCode == 32) { // space
var channel:SoundChannel = shootSound.play();
newMissile();
} else if (event.keyCode == 90) { // z
startShield(false);
var channel:SoundChannel = shieldSound.play();
}
}
// register key ups
public function keyUpFunction(event:KeyboardEvent) {
if (event.keyCode == 37) {
leftArrow = false;
} else if (event.keyCode == 39) {
rightArrow = false;
} else if (event.keyCode == 38) {
upArrow = false;
//Add listener for down arrow
} else if (event.keyCode == 40) {
downArrow = false;
// remove thruster
if (gameMode == "play") ship.gotoAndStop(1);
}
}
// animate ship
public function moveShip(timeDiff:uint) {
// rotate and thrust
if (leftArrow) {
ship.rotation -= shipRotationSpeed*timeDiff;
} else if (rightArrow) {
ship.rotation += shipRotationSpeed*timeDiff;
} else if (upArrow) {
shipMoveX += Math.cos(Math.PI*ship.rotation/180)*thrustPower;
shipMoveY += Math.sin(Math.PI*ship.rotation/180)*thrustPower;
//Added down arrow movement to allow player to move backwards
} else if (downArrow) {
shipMoveX -= Math.cos(Math.PI*ship.rotation/180)*thrustPower;
shipMoveY -= Math.sin(Math.PI*ship.rotation/180)*thrustPower;
}
// move
ship.x += shipMoveX;
ship.y += shipMoveY;
I agree that there is a little logic problem in your code. Your ship will move on 'til
judgement day because the two variables responsible for the speed of it's motion - shipMoveX
and shipMoveY - aren't automatically degraded over time.
Now there are literally thousands of ways of how this could be achieved but let's keep things
simple.
You are using a class variable called thrustPower - make sure to set it to 0.1 and that the value of both shipMoveX & shipMoveY is 0.
Additionally add these class variables:
private var thrustHorizontal:Number = 0;
private var thrustVertical:Number = 0;
private var speed:Number = 0;
private var maxSpeed:Number = 5;
private var decay:Number = 0.97;
Replace the moveShip function with this:
public function moveShip(timeDiff:uint):void
{
thrustHorizontal = Math.sin(Math.PI * ship.rotation / 180);
thrustVertical = Math.cos(Math.PI * ship.rotation / 180);
// rotate and thrust
if (leftArrow)
{
ship.rotation -= shipRotationSpeed * timeDiff;
}
else if (rightArrow)
{
ship.rotation += shipRotationSpeed * timeDiff;
}
else if (upArrow)
{
shipMoveX += thrustPower * thrustHorizontal;
shipMoveY += thrustPower * thrustVertical;
}
else if (downArrow)
{
shipMoveX -= thrustPower * thrustHorizontal;
shipMoveY -= thrustPower * thrustVertical;
}
if (!upArrow && !downArrow)
{
shipMoveX *= decay;
shipMoveY *= decay;
}
speed = Math.sqrt((shipMoveX * shipMoveX) + (shipMoveY * shipMoveY));
if (speed > maxSpeed)
{
shipMoveX *= maxSpeed / speed;
shipMoveY *= maxSpeed / speed;
}
ship.x += shipMoveX;
ship.y -= shipMoveY;
}
As you can see, there is this new if-block:
if (!upArrow && !downArrow)
{
shipMoveX *= decay;
shipMoveY *= decay;
}
Here we're handling the case, if the player neither pressed up nor down and multiply
the spaceships horizontal/vertical speed by decay. If you scroll back a bit, you notice
it's value is 0.97.
You can generally say, if you multiply a positive number x by 0 < y < 1, x will become smaller.
So if you're spaship is currently moving horizontally at 3 pixels per frame (shipMoveX=3 ; shipMoveY=0)
it will become 2.91 the next frame. The next frame it will be 2.8227, then 2.738019 ... and so on before it will finally reach zero in infinity.

Actionscript 3 error 1009: Cannot access a property or method of a null object reference

I'm trying to make a simple game on Animate CC. Everything seems to work fine except when I look in the output, I get the following error:
TypeError: Error #1009: Cannot access a property or method of a null
object reference.
at _2D_CW2_Game_v10_8_fla::MainTimeline/move()
at _2D_CW2_Game_v10_8_fla::MainTimeline/updateOb()
So I know where the issue might be, and I've been trying tweaking the code for days, googling possible solutions, but to no avail...
My entire source code is as below. Any feedback/suggestions will be greatly appreciated.
import flash.ui.Keyboard;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.MovieClip;
import flash.net.URLRequest;
import flash.media.Sound;
import flash.media.SoundMixer;
//==================================================
// Variable declaration
//==================================================
// defines the variables for boundaries
var left:Number = 0;
var top:Number = 0;
var right:Number = stage.stageWidth;
var bottom:Number = stage.stageHeight;
var velX:Number = 0;
var velY:Number = 0;
var gravity:Number = 1;
var friction:Number = 0.8;
var bounce:Number = -0.5;
var score:Number = 2;
var cv:Number = 0;
var curCount:Number = 30; // countdown 30s
var rightKeyDown:Boolean = false;
var leftKeyDown:Boolean = false;
var upKeyDown:Boolean = false;
var touchGround:Boolean = false;
// create and place player object on stage
var player:Player = new Player();
player.x = 110;
player.y = 460;
addChild(player);
// create obstacle array
var obstacles:Array = new Array();
var numOb:Number = 3;
// create and place enemies on stage
for (var i:Number = 0; i < numOb; i++) {
var ob:Npc = new Npc();
ob.x = 800;
ob.y = 470;
ob.scaleX = -1;
ob.vx = Math.random() * 20 + 1;
addChild(ob);
obstacles.push(ob);
}
//==================================================
// Event handlers
//==================================================
stage.addEventListener(Event.ENTER_FRAME, EntFrame);
addEventListener(Event.ENTER_FRAME, updateOb);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUp);
//==================================================
// Functions
//==================================================
function keyDown(e:KeyboardEvent):void {
if (e.keyCode == Keyboard.RIGHT) {
rightKeyDown = true;
}
if (e.keyCode == Keyboard.LEFT) {
leftKeyDown = true;
}
if (e.keyCode == Keyboard.UP) {
// if player isn't already jumping and is on the ground
if (!upKeyDown && touchGround) {
// then start jumping
isJumping();
}
upKeyDown = true;
}
}
function keyUp(e:KeyboardEvent):void {
if (e.keyCode == Keyboard.RIGHT) {
rightKeyDown = false;
}
if (e.keyCode == Keyboard.LEFT) {
leftKeyDown = false;
}
if (e.keyCode == Keyboard.UP) {
upKeyDown = false;
}
}
function EntFrame(e:Event):void {
player.x += velX;
player.y += velY;
velX *= friction;
velY += gravity;
if (player.y >= 450) {
touchGround = true;
player.y = 450;
}
// boundary checks
if (player.x + player.width/2 > right) {
player.x = right - player.width/2;
player.velX *= bounce;
} else if (player.x - player.width/2 < left) {
player.x = left + player.width/2;
player.velX *= bounce;
}
// make player move left or right
controls();
if (curCount > 0) {
cv++;
if (cv >= 30) {
curCount--;
cv = 0;
timertext.text = String(curCount);
if (curCount == 0) {
restart();
gotoAndStop("gameOverWon");
}
}
}
}
function updateOb(e:Event):void {
// make obstacles move
for (var i:Number = 0; i < numOb; i++) {
var ob:Npc = obstacles[i];
move(ob);
if (player.hitTestObject(obstacles[i])) {
/*if (obstacles[i].hitTestPoint(player.x + player.width/2, player.y + player.height/2, true)
|| obstacles[i].hitTestPoint(player.x + player.width/2, player.y - player.height/2, true)
|| obstacles[i].hitTestPoint(player.x - player.width/2, player.y + player.height/2, true)
|| obstacles[i].hitTestPoint(player.x - player.width/2, player.y - player.height/2, true))*/
bumpOb(obstacles[i]);
}
}
scoretext.text = String(score);
if (score == 0) {
restart();
gotoAndStop("gameOverLost");
}
}
// applies basic velocity to enemies
function move(moveOb) {
moveOb.x -= moveOb.vx;
if (moveOb.x + moveOb.width/2 > right) {
moveOb.x = right - moveOb.width/2;
moveOb.vx *= bounce;
moveOb.scaleX = -1;
}
if (moveOb.x - moveOb.width/2 < left) {
moveOb.x = left + moveOb.width/2;
moveOb.vx *= bounce;
moveOb.scaleX = 1;
}
}
function bumpOb(p) {
if (p) {
p.removeEventListener(Event.ENTER_FRAME, updateOb);
if (p.parent) {
removeChild(p);
score--;
}
}
}
function restart() {
if(contains(player)) {
removeChild(player);
}
for (var i:int = 0; i < numOb; i++) {
if (contains(obstacles[i]) && obstacles[i] != null) {
removeChild(obstacles[i]);
obstacles[i] = null;
}
}
// returns a new array that consists of a range of elements from the original array,
// without modifying the original array
obstacles.slice(0);
}
function controls() {
if (rightKeyDown) {
velX += 3;
player.scaleX = 1;
}
if (leftKeyDown) {
velX -= 3;
player.scaleX = -1;
}
}
function isJumping() {
touchGround = false;
velY = -15;
}
//==================================================
// Sound control for background music
//==================================================
btnMute.addEventListener(MouseEvent.CLICK, mute);
function mute(e:MouseEvent):void {
SoundMixer.soundTransform = new SoundTransform(0);
btnMute.removeEventListener(MouseEvent.CLICK, mute);
btnMute.addEventListener(MouseEvent.CLICK, unmute);
}
function unmute(e:MouseEvent):void {
SoundMixer.soundTransform = new SoundTransform(1);
btnMute.removeEventListener(MouseEvent.CLICK, unmute);
btnMute.addEventListener(MouseEvent.CLICK, mute);
}
I had the same problem when I created interactive elements for animation. Check which layer the interactive object is on. A similar error occurred when the object overlapped something that was located on the layer above.
You can try...
1) Your Npc is a class/library object, right?
Give the source MC/Sprite, the instance name of moveOb or p.
2) or else try... Use function parameters (this is a better coding style):
(2a) Since you say..
var ob:Npc = obstacles[i];
move(ob);
ps: why not simplify (without var) as : move( obstacles[i] ); ...?
(2b) Your move function should specify a data type together with your parameter name...
//# applies basic velocity to enemies
//# Wrong...
//function move(moveOb) {
//# Better...
function move( moveOb : Npc ) {
//# Aso fix as...
function bumpOb(p : Npc ) {
By using function parameters, you can now give unique names to the (function's) input parameters but stay referencing the same (or compatible) data type.
Let me know how it goes.
The obstacles array may have null elements in the middle. What if you add a condition to continue if it's null?
function updateOb(e:Event):void {
// make obstacles move
for (var i:Number = 0; i < obstacles.length; i++) {
var ob:Npc = obstacles[i];
if(!ob) continue;
move(ob);
if (player.hitTestObject(ob)) {
/*if (obstacles[i].hitTestPoint(player.x + player.width/2, player.y +
player.height/2, true)
|| obstacles[i].hitTestPoint(player.x + player.width/2, player.y -
player.height/2, true)
|| obstacles[i].hitTestPoint(player.x - player.width/2, player.y +
player.height/2, true)
|| obstacles[i].hitTestPoint(player.x - player.width/2, player.y -
player.height/2, true))*/
bumpOb(obstacles[i]);
}
}
scoretext.text = String(score);
if (score == 0) {
restart();
gotoAndStop("gameOverLost");
}
}

In AS3 how would i add 2 buttons that would enable the player to move on press instead of using the arrow keys?

I got this code off the internet for the game Pong to work on my AS3 document for my assignment. However i'm pretty much a beginner at code and i'm trying to get this game to work on mobile as the assignment needs a game to work on it.
Because it uses arrow keys, i would like to basically just replace them with buttons instead, one for going up and one for going down. I just don't know the type of code that would allow me to do that.
Something like, when button is pressed, player moves up or down depending which button, but im not sure where to replace the code and what to get rid of.
Here's the "Pong" class file:
package {
import flash.display.MovieClip;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.events.Event;
public class Pong extends MovieClip {
//constants
private var pongUp:MovieClip = new PongUp ;
private var pongDown:MovieClip = new PongDown ;
const ballspeed:int = 10;
const playerspeed:int = 7;
const computerspeed:int = 10;
const computerIntelligence:int = 7;//intelligence is 7 out of 10
//global variables
var vx:int = - ballspeed;// x component of velocity of ball (velocity is speed with direction)
var vy:int = ballspeed;// y component of velocity of ball
var v1:int = 0;// initial velocity of player
var v2:int = 0;// initial velocity of computer
var playerScore:int = 0;
var computerScore:int = 0;
var player:MovieClip = new PongPlayer ;
var computer:MovieClip = new PongComputer ;
var ball:MovieClip = new PongBall ;
public function Pong() {
//init();
addEventListener(Event.ADDED_TO_STAGE,init);
}
//this function will add all event listeners
function init(e:Event):void {
stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP,KeyUp);
stage.addEventListener(Event.ENTER_FRAME,EnterFrame);
addChild(player);
addChild(computer);
addChild(ball);
player.x = 23;
player.y = 300;
computer.x = 637;
computer.y = 311;
ball.x = 308;
ball.y = 328;
addChild(pongUp);
pongUp.x = 25;
pongUp.y = 700;
addChild(pongDown);
pongDown.x = 530;
pongDown.y = 700;
}
// this function resets the game
function reset():void {
player.y = stage.stageHeight / 2;
computer.y = stage.stageHeight / 2;
ball.x = stage.stageWidth / 2;
ball.y = stage.stageHeight / 2;
if (Math.abs(Math.random() * 2) > 1)
{
vx = - ballspeed;
}
else
{
vx = ballspeed;
}
if (Math.abs(Math.random() * 2) > 1)
{
vy = - ballspeed;
}
else
{
vy = ballspeed;
}
}
//pongDown.addEventListener ( MouseEvent.MOUSE_DOWN,moveDown );
//function moveDown ( e:MouseEvent ): void
//{
//}
//this function sets the velocity of player when key is pressed
function KeyDown(event:KeyboardEvent):void {
if (event.keyCode == Keyboard.UP)
{
v1 = - playerspeed;
}
else if (event.keyCode == Keyboard.DOWN)
{
v1 = playerspeed;
}
}
//this function sets the velocity of player to 0 if key is released
function KeyUp(event:KeyboardEvent):void {
if (event.keyCode == Keyboard.UP || event.keyCode == Keyboard.DOWN)
{
v1 = 0;
}
}
//This function is executed when a frame changes
function EnterFrame(event:Event):void {
//variable decleration
var pHalfHeight = player.height / 2;// half height of player(used for collisions)
var pHalfWidth = player.width / 2;// half width of player (used for collisions)
var bHalfHeight = ball.height / 2;// half height of ball(used for collisions)
var bHalfWidth = ball.width / 2;// half width of ball (used for collisions)
//moving the player
player.y += v1;
//limiting the motion of player (it should not move beyond the stageheight)
if (player.y + pHalfHeight > stage.stageHeight)
{
player.y = stage.stageHeight - pHalfHeight;
}
else if (player.y - pHalfHeight < 0)
{
player.y = 0 + pHalfHeight;
}
//moving the ball
ball.x += vx;
ball.y += vy;
//moving the computer automatically
if (Math.abs(Math.random() * 10) < computerIntelligence)
{
var d:int = computer.y - ball.y;
if (Math.abs(d) > pHalfHeight)
{
if ((d > 0))
{
v2 = - computerspeed;
}
else
{
v2 = computerspeed;
}
}
}
computer.y += v2;
//limiting the motion of computer (it should not move beyond the stageheight)
if (computer.y + pHalfHeight > stage.stageHeight)
{
computer.y = stage.stageHeight - pHalfHeight;
}
else if (computer.y - pHalfHeight < 0)
{
computer.y = 0 + pHalfHeight;
}
//collision with horizontal walls
if (ball.y + bHalfHeight >= stage.stageHeight || ball.y - bHalfHeight <= 0)
{
vy *= -1;
}
//collision with player and computer
if (ball.x - bHalfWidth <= player.x + pHalfWidth)
{
if (Math.abs(ball.y - player.y) <= pHalfHeight)
{
vx = ballspeed;
if ((v1 != 0))
{
vy = 2 * v1;
}
}
}
else if (ball.x + bHalfWidth >= computer.x - pHalfWidth)
{
if (Math.abs(ball.y - computer.y) <= pHalfHeight)
{
vx = - ballspeed;
if ((v2 != 0))
{
vy = v2;
}
}
}
//collision with vertical walls & updating scores
if (ball.x + bHalfWidth >= stage.stageWidth)
{
playerScore += 1;
reset();
}
else if (ball.x - bHalfWidth <= 0)
{
computerScore += 1;
reset();
}
//display the score on the textfield
//txtPlayer.text = String(playerScore);
//txtComputer.text = String(computerScore);
}
}
}
For mobile, you'll want to compile using AIR for Android or iOS. You can then replace:
//this function sets the velocity of player when key is pressed
function KeyDown(event:KeyboardEvent):void {
if (event.keyCode == Keyboard.UP)
{
v1 = - playerspeed;
}
else if (event.keyCode == Keyboard.DOWN)
{
v1 = playerspeed;
}
}
//this function sets the velocity of player to 0 if key is released
function KeyUp(event:KeyboardEvent):void {
if (event.keyCode == Keyboard.UP || event.keyCode == Keyboard.DOWN)
{
v1 = 0;
}
}
with:
function KeyDown(event:TouchEvent):void {
if (event.stageY < player.y){
v1 = - playerspeed;
}else if (event.stageY > player.y){
v1 = playerspeed;
}
}
function KeyUp(event:TouchEvent):void {
v1 = 0;
}
Then replace:
//this function will add all event listeners
function init(e:Event):void {
stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP,KeyUp);
with:
//this function will add all event listeners
function init(e:Event):void {
stage.addEventListener(TouchEvent.TOUCH_BEGIN, KeyDown);
stage.addEventListener(TouchEvent.TOUCH_END, KeyUp);
And make sure to use TouchEvent instead of KeyboardEvent by replacing:
import flash.events.KeyboardEvent;
with:
import flash.events.TouchEvent;
Now when you hold your finger down on the screen, the "player" will move towards that Y location. If your game is using the X axis, just change the Ys to Xs!
Hope this helps!

AS3 indexof array object property

I'm trying to complete background in kind of Space Invaders game. I want to generate stars at a random location, scroll them to the bottom of the stage and then add new star after each one is gone. I guess that the problem lies on the indexOf method, which I tried to use to find star y proprety.
I know this may be a stupid mistake, i'm a beginner :)
My current main class:
public class Main extends Sprite
{
private var ship:Ship = new Ship();
private var numStars:int = 80;
private var starArray:Array = new Array();
public function Main():void
{
stage.addChild(ship);
ship.x = stage.stageWidth / 2 - ship.width / 2;
ship.y = stage.stageHeight / 2 - ship.height / 2;
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
for (var i:int = 0; i < numStars; i++)
{
createStar();
}
}
public function createStar():void
{
var newStar:Star = new Star();
starArray.push(newStar);
stage.addChildAt(newStar,1);
newStar.x = Math.random() * stage.stageWidth;
newStar.y = Math.random() * stage.stageHeight;
newStar.alpha = Math.random();
newStar.rotation = Math.random()*360;
newStar.scaleX = Math.random();
newStar.scaleY = Math.random();
}
public function keyDownHandler(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.UP)
{
ship.accelerationY = -0.3;
}
if (e.keyCode == Keyboard.DOWN)
{
ship.accelerationY = 0.3;
}
if (e.keyCode == Keyboard.LEFT)
{
ship.accelerationX = -0.3;
}
if (e.keyCode == Keyboard.RIGHT)
{
ship.accelerationX = 0.3;
}
}
public function keyUpHandler(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.UP || e.keyCode == Keyboard.DOWN)
{
ship.accelerationX = 0;
ship.accelerationY = 0;
}
if (e.keyCode == Keyboard.LEFT || e.keyCode == Keyboard.RIGHT)
{
ship.accelerationY = 0;
ship.accelerationX = 0;
}
}
public function enterFrameHandler(e:Event):void
{
//acceleration
ship.vx += ship.accelerationX;
ship.vy += ship.accelerationY;
//friction
ship.vx *= ship.friction;
ship.vy *= ship.friction;
if (Math.abs(ship.vx) < 0.1)
{
ship.vx = 0;
}
if (Math.abs(ship.vy) < 0.1)
{
ship.vy = 0;
}
ship.rotation = ship.vx * 2;
//set speed limit
if (ship.vx > ship.speedLimit)
{
ship.vx = ship.speedLimit;
}
if (ship.vx < -ship.speedLimit)
{
ship.vx = -ship.speedLimit;
}
if (ship.vy > ship.speedLimit)
{
ship.vy = ship.speedLimit;
}
if (ship.vy < -ship.speedLimit)
{
ship.vy = -ship.speedLimit;
}
//set stage boundaries
if (ship.x < 0)
{
ship.x = 0;
}
if (ship.y < 0)
{
ship.y = 0;
}
if (ship.x + ship.width > stage.stageWidth)
{
ship.x = stage.stageWidth - ship.width;
}
if (ship.y + ship.height > stage.stageHeight)
{
ship.y = stage.stageHeight - ship.height;
}
ship.x += ship.vx;
ship.y += ship.vy;
//star enter frame code
for (var i:int = 0; i < numStars; i++)
{
starArray[i].y += 0.5 + Math.random() * 2;
}
if (starArray.indexOf(starArray.y) > stage.stageHeight) //if y property of any star is higher than stage height, create a new star
{
createStar();
}
}
}
i recommend looking into tween utilities like TweenLite which do time based animations: (http://www.greensock.com/tweenlite/)
also recommend looking into object pooling, reused objects instead of creating new ones. Good thing to learn as a new programmer.
you are correct about where your issue lies
i got your program working correctly with the following change:
---------change these lines-------------
//star enter frame code
for (var i:int = 0; i < numStars; i++)
{
starArray[i].y += 0.5 + Math.random() * 2;
}
if (starArray.indexOf(starArray.y) > stage.stageHeight) //if y property of any star is higher than stage height, create a new star
{
createStar();
}
---------to this-------------
//star enter frame code
for (var i:int = 0; i < numStars; i++)
{
var star:Star = starArray[i];
star.y += 0.5 + Math.random() * 2;
if (star.y>stage.stageHeight){
//dont create a new star -- memory leak
//move the same star to a new random location
star.y = 0;
}
}
Instead of just creating a new star, why not just replace it at the top outside of the screen?
As for indexOf, it only returns the index in an array of the object being passed. And in this case you're passing the y value of an array, which doesn't have that property.
Instead, move your position checking code to your for loop in the game loop. That way, you already have an index (your i variable) of the star that's outside the boundaries and if it is, just reposition it and save some memory!
for (var i:int = 0; i < numStars; i++)
{
starArray[i].y += 0.5 + Math.random() * 2;
if(starArray[i].y > stage.stageHeight)
{
// Repositions the star between x: 0 to stageWidth, y: -5 to -15
starArray[i].y = Math.random() * -10 - 5;
starArray[i].x = Math.random() * stage.stageWidth;
}
}

Game Rotation Collision Problems

Im attempting to make a basic maze game with a slight twist. At set intervals (set by a timer event) the maze rotates 90%. The problem I'm having is in regards to the hitTestPoint. The hit test works prior to the maze roataion and works after a full 360% rotation but stops working during the 90%, 180% and 270% rotation points. I have exhausted all my knowledge (As limited as a 5 month AS3 programmer) in AS3 to resolve this problem and am at my wits end.
The maze is in a container and the container is rotating, this is so that the maze in effect has a secondary moving pivot point that continually follows the player around tha maze. additionally the container is moving on key press not the player.
Could anyone please halp me by explaining what is causing the problem, how I can fix it and if possible show me an example of the code I should be using.
Here is what I have so far.
stop();
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.sensors.Accelerometer;
var speed:Number = 5;
var northSpeed = speed;
var southSpeed = speed;
var eastSpeed = speed;
var westSpeed = speed;
var upPressed:Boolean = false;
var downPressed:Boolean = false;
var leftPressed:Boolean = false;
var rightPressed:Boolean = false;
var Orientation:int = 0;
var count:int = 0;
var timer:Timer = new Timer(1000,60);
var time = 60;
player.addEventListener(Event.ENTER_FRAME, MovePlayer);
containBox.maze.addEventListener(Event.ENTER_FRAME, hitWalls);
stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, KeyDepressed);
containBox.maze.addEventListener(Event.ENTER_FRAME, spin);
timer.start();
timer.addEventListener(TimerEvent.TIMER, timerHandle);
function timerHandle(e:TimerEvent):void
{
txt_time.text = time;
time--;
}
function hitWalls(event:Event):void
{
if (upPressed==true && containBox.maze.hitTestPoint(player.x,player.y,true))
{
northSpeed = 0;
player.y = player.y+=2;
}
else
{
northSpeed = speed;
}
}
function spin(event:Event):void
{
if (time <= 0)
{
txt_time.text = "TIMES UP!";
}
if (time <= 54)
{
containBox.rotation = 90;
Orientation = 1;
}
if (time <= 50)
{
containBox.rotation = 180;
Orientation = 2;
}
if (time <= 48)
{
containBox.rotation = 270;
Orientation = 3;
}
if (time <= 46)
{
containBox.rotation = 0;
Orientation = 0;
}
}
function MovePlayer(event:Event):void
{
if (Orientation == 0)
{
if (upPressed)
{
containBox.maze.y += northSpeed;
}
if (downPressed)
{
containBox.maze.y -= southSpeed;
}
if (leftPressed)
{
containBox.maze.x += westSpeed;
}
if (rightPressed)
{
containBox.maze.x -= eastSpeed;
}
}
else if (Orientation == 1)
{
if (upPressed)
{
containBox.maze.x += 5;
}
if (downPressed)
{
containBox.maze.x -= 5;
}
if (leftPressed)
{
containBox.maze.y -= 5;
}
if (rightPressed)
{
containBox.maze.y += 5;
}
}
else if (Orientation == 2)
{
if (upPressed)
{
containBox.maze.y -= 5;
}
if (downPressed)
{
containBox.maze.y += 5;
}
if (leftPressed)
{
containBox.maze.x -= 5;
}
if (rightPressed)
{
containBox.maze.x += 5;
}
}
else if (Orientation == 3)
{
if (upPressed)
{
containBox.maze.y += 5;
}
if (downPressed)
{
containBox.maze.y -= 5;
}
if (leftPressed)
{
containBox.maze.x += 5;
}
if (rightPressed)
{
containBox.maze.x -= 5;
}
}
}
function KeyPressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP :
{
upPressed = true;
break;
};
case Keyboard.DOWN :
{
downPressed = true;
break;
};
case Keyboard.LEFT :
{
leftPressed = true;
break;
};
case Keyboard.RIGHT :
{
rightPressed = true;
break;
}
}
}
function KeyDepressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP :
{
upPressed = false;
break;
};
case Keyboard.DOWN :
{
downPressed = false;
break;
};
case Keyboard.LEFT :
{
leftPressed = false;
break;
};
case Keyboard.RIGHT :
{
rightPressed = false;
break;
}
}
}
Many thanks,
Reece.
You need to do 2D coordinate system transformation to do a proper comparison. See, the player basically stands on a fixed point, thus (player.x, player.y) is fixed, and hitTestPoint() uses the coordinates supplied as local to the this object, in your case the maze. To get the player's coordinates in the maze's system, you need first get global position, then derive local position, there are functions for that, localToGlobal() and globalToLocal() respectively.
function hitWalls(event:Event):void
{
var p:Point=new Point(player.x,player.y);
var dp:Point=containBox.maze.globalToLocal(player.parent.localToGlobal(p));
// now test vs dp instead of player.
if (upPressed==true && containBox.maze.hitTestPoint(dp.x,dp.y,true))
{
northSpeed = 0;
player.y = player.y+=2;
}
else
{
northSpeed = speed;
}
}