Actionscript 3.0 platformer game - actionscript-3

I have an flash game with the following code (http://pastie.org/9248528)
When I run it, the player just falls and doesn't stop when he hits a platform.
I tried debugging it and I had an error with moveCharacter's timer, but I don't know if that is the main problem.
I put the player inside the wall and debugged it using breakpoints and it didn't detect that the player was inside the wall, skipping moving it to outside of the wall.
Anyone has any ideas on what is wrong with my code?

The problem is in this code:
// Check if character falls off any platform
for (var i:int = 0; i < platform.length; i++) {
if (player.x < platform[i].x || player.x > platform[i].x + platform[i].width) {
onPlatform = false;
}
}
Since the player cannot simultaneously be on every platform at once, his x position is pretty much guaranteed to be out of bounds of at least 1 platform, which will set onPlatform to false. Instead you would need to keep a reference to which platform the player is on, like so:
var lastPlatform:Sprite; //holds reference to last platform player was on
// Function to move character
function moveCharacter(evt:TimerEvent):void {
....
// Check if character falls off the platform he was last on
if (lastPlatform != null && (player.x < lastPlatform.x || player.x > lastPlatform.x + lastPlatform.width)) {
onPlatform = false;
}
}
function detectCollisions():void {
// Check for collisions with platforms
for (var p:int = 0; p < platform.length; p++) {
// Adjust character to platform level if with landing depth of the platform
if (!onPlatform && player.hitTestObject(platform[p]) && lastPosY < platform[p].y) {
lastPlatform = platform[p]; //save reference
player.y = platform[p].y;
jumping = false;
onPlatform = true;
dy = 0;
// Prevent character from dropping sideways into platforms
} else if (!onPlatform && player.hitTestObject(platform[p])) {
player.x = lastPosX;
}
}
.....
}
This should work better, though it is still not the most object-oriented way to do this. Hope this helps!

Related

How to hitTest same Objects in one Array?

I want to create a stacking Game. Where when you tap the screen for instance a block falls down and a new one appears where the other one originally was. Now when the User taps the screen again the same block falls down and if aligned correctly stacks on top of the first one so one and so one. Keep stacking until you miss.
I thought creating an array and pushing each new object to that array would be able to hitTest between each new one etc and have them stack on each other. I realized I don't quite understand how to go about doing this. New instances are created so I got that down. Here is my code so far:
private function engineLogic(e:Event):void
{
stackingHandler();
}
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
var currentCat:mcCats = aCatArray[i];
//HIT TEST CATS
}
trace("NUMBER OF CATS: " + aCatArray.length);
}
private function onTap(e:MouseEvent):void
{
//Move Down
TweenLite.to(cats, 1.0, {y:(stage.stageHeight / 2) + 290, onComplete: addCats});
}
private function addCats():void
{
//Create Instance
cats = new mcCats();
//Add Objects
addChild(cats);
//Push to Array
aCatArray.push(cats);
}
I would appreciate any help from you guys. Maybe if you can push me in the right direction. Thank you in advance!
It looks like the cats variable holds the object that is currently falling?
In that case you'd do something like this:
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
if(cats.hitTestObject(aCatArray[i])) {
// collision detected!
// kill the Tween
// set the y position of the `cats` object
// so it appears on top of the object it collided with (`aCatArray[i]`)
// (it may have moved slightly past the object before doing this check)
}
}
}
So you're looping through the array and hit testing cats against every object in the array one at a time.
It might make more sense to use a basic gravity simulation, or just linearly increasing the y value instead of using a Tween, but you didn't ask about that.
You might also want to set a flag for whether or not an object is currently falling and use that to determine whether or not to run the stackingHandler. Otherwise, you'll just be continually hit testing all the objects when nothing is moving.
This is how I was able to fix it. Creating a double for loop. Checking if they are equal to each other continue and check for hitTest:
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
var currentCat:mcCats = aCatArray[i];
for (var j:int = 0; j < aCatArray.length; j++)
{
var newCat:mcCats = aCatArray[j];
if (currentCat == newCat) continue;
//Hit Test between Objects
if (newCat.hitTestObject(currentCat.mcHit) && newCat.bFlag == false)
{
//Stop Moving
newCat.stopMoving();
trace("HIT");
if (highScore == 0)
{
addCats();
trace("ADD CATS 1");
}else
{
TweenLite.delayedCall(0.6, addCats);
trace("ADD CATS 2");
}
//Add Points
highScore ++;
trace(highScore + " Score");
//Set Flag boolean
newCat.bFlag = true
}
}
}
}

AS3 How to hitTest with multiple Movie Clips of the same Instance Name?

Hey everyone so I have a Movie Clip inside my platforms movie clip called mcTaco so platforms.mcTaco. I add the platforms and the player which I check for hitTest collisions to the stage dynamically using code. When I check for the player and platforms.mcTaco collison everything works fine. It's when I duplicate the mcTaco creating multiple instances of them inside the platforms movieclip that I am having the main issues.
I know I have to add them to an array and use a for loop to check for the hitTest of the multiple platforms.mcTaco instances but I don't know how to accomplish this. I am using an IDE Flash Develop for my code and here is what I have so far:
I add my Platforms to the stage like so:
//ADD PLATFORMS AND ENVIRONMENT
private function addPlatForms():void
{
//Add Obstacle Platforms
platforms = new mcPlatforms();
platforms.x = (stage.stageWidth / 2) - 80;
platforms.y = (stage.stageHeight / 2) + 165;
addChildAt(platforms, 1);
aPlatformArray.push(platforms);
//trace(aPlatformArray.length + " NPLATFORMS");
}
and my Player:
//Add Character
player = new mcPlayer();
player.x = (stage.stageWidth / 2) - 80;
player.y = (stage.stageHeight / 2) + 78;
addChildAt(player, 1);
and in my ENTER_FRAME Event Listener I am doing this to test the player and platforms.mcTaco hitTest like so:
private function tacoHitTestHandler():void
{
if (player.hitTestObject(platforms.mcTaco))
{
platforms.mcTaco.visible = false;
trace("HIT TACO");
}
}
I just need some help on figuring out how to go about doing this. I have my Taco Arrayprivate var aTacoArray:Array; instantiated but I just don't know how to push the platforms.mcTaco Movie clips into it to use the for loop to test it. Any help on how to go about doing this would be greatly appreciated. I just don't want to have to do the if (player.hitTestObject(platforms.mcTaco1) || player.hitTestObject(platforms.mcTaco2) etc...)
You need to loop children inside each of the platforms to get all tacos by their class or/and name.
private function tacoHitTestHandler():void
{
// Loop through the list of the platforms.
for (var i:int = 0; i < aPlatformArray.length; i++)
{
// Get a platform instance from the Array.
var aPlatform:mcPlatforms = aPlatformArray[i];
// Loop through the children of a platform.
for (var j:int = 0; j < aPlatform.numChildren; j++)
{
// Get a potential taco.
var aTaco:mcTaco = aPlatform.getChildAt(j) as mcTaco;
// Skip if it is not a taco.
if (!aTaco) continue;
// Ignore invisible objects.
if (!aTaco.visible) continue;
// Ignore wrong tacos by name.
if (aTaco.name != "mcTaco") continue;
// Hit test against taco.
if (player.hitTestObject(aTaco))
{
aTaco.visible = false;
trace("HIT TACO");
}
}
}
}
A few notes.
First, calling a class mcTaco and giving the same instance name mcTaco is asking for headache because there are moments where your code will not be sure, if you are referring a class of a declared instance.
Second, call your classes with uppercase head letter because it's nice. A nice scottish McTaco would suffice.
You push your tacos to the aTacoArray the same way you do it with platforms:
aTacoArray.push(myTacoMC);
Then you can loop trough them and test the collision on each:
private function tacoHitTestHandler():void
{
for(var i:int = 0; i < aTacoArray.length; i++)
{
// get taco from array
var currentTaco:MovieClip = aTacoArray[i];
if (player.hitTestObject(currentTaco))
{
currentTaco.visible = false;
trace("HIT TACO");
}
}
}

How to check if objects position is greater than an array of objects AS3

Hey everyone so I'm trying to figure out how to check if one movie Clips x position which is called ball is greater than an array of objects x position which is called car. So I have an array setup with the car the car's main timeline consist of 4 frames that holds the same movie Clip just different sizes on each frame to make the game harder.
So what I want to do is check whenever the ball has jumped over the current car then add plus one to the score. But I am having trouble trying to figure this out. Here is what I have so far:
In my Enter Frame Game Loop I have the Function checkAddPoints:
private function gameLoop(e:Event):void
{
checkBunnyHitObstacles();
checkAddPoints();
}
Then The function:
private function checkAddPoints():void
{
for (var i:int = 0; i < aCarArray.length; i++)
{
var currentCar:car = aCarArray[i];
if (ball.x > currentCar.x)
{
nScore ++;
updateCurrentScore();
}
}
}
So I am getting the current car in the loop and trying to check if the ball has jumped over it. I thought the most logical thing to do was to check if the ball x position was greater than the car x position then it would work. But it just adds a endless amount of numbers and not just one like I want.
Does anyone know what i need to do?
UPDATE: This seems to work haven't had any errors yet
if (currentcar.x - 15 < ball.x && currentCar.x + 15 > ball.x)
{
trace("AddPoint Success");
nScore++;
updateCurrentScore();
}
Storing flag aboud award status in the car should help in your task. If you add flag to the car, let's say car.isAwarded, by default isAwarded is false, you will be able award only once for every car:
private function checkAddPoints():void {
var i:uint, len:uint = aCarArray.length, currentCar:car;
for (i; i < len; ++i) {
currentCar = aCarArray[i];
//Award only once
if (!currentCar.isAwarded && ball.x > currentCar.x) {
nScore++;
currentCar.isAwarded = true;
updateCurrentScore();
}
}
}

What is causing this glitch?

I am currently coding a game, and have encountered an annoying glitch. Occasionally, when you kill an enemy in game, it will drop extra currency, and another enemy onscreen will be removed from the enemylist. However, this second enemy, the one removed from the enemylist, will still be on screen, and will still shoot at the player. Below are code snippets from the collision formula, the enemies destruction sequence, and the bullet hitcheck sequence.
Collision formula:
public function testCollision(enemy:Entity):Boolean{
var eX:Number = enemy.collision.xPos
var eY:Number = enemy.collision.yPos
var eSL:Number = enemy.collision.SideLength/2
if(eX-xPos<(SideLength/2)+eSL && eY-yPos<(SideLength/2)+eSL && eX-xPos>-(SideLength/2)-eSL && eY-yPos>-(SideLength/2)-eSL){
return true
}else{
return false
}
}
Enemy destruction sequence:
if(deathVar){
view.transparency -= 1/20
if(view.transparency<0.1){
var cur = new PixelCurrency(2)
cur.collision.xPos = collision.xPos
cur.collision.yPos = collision.yPos
entityCreated.dispatch(cur)
destroy()
}
}
Bullet hitcheck:
for each (var enemy:Entity in Game.entities){
if(enemy.allies == Pixapocalypse.EnemyFaction){
if(collision.testCollision(enemy)){
if(enemy.life){
enemy.life.changeHealth(-2)
this.sound.playSound(new basicHitSound())
this.destroy()
break
}
else{
}
}
}
}
If you need any extra info, please tell me, I am greatly appreciative of your help.
What happens when Enemy.life < 0 ?

Detect Game Win State in AS3

I'm trying to come up with a clean function that will perform a check on a 2D Array to verify if a win has occurred in a ConnectFour game. I'm trying to work through the logic but my brain is swiss cheese right now. Here's what I have for checking for a horizontal win. It seems to me like there should be a way to streamline this block to work in all possible directions.
private function checkForHorizontalWin(column:uint, row:uint, grid:Array):Boolean
{
var player:uint = grid[column][row];
var counter:uint = 1;
for(var i:uint = Math.min(0, uint(column-1)); i>=0; i--)
{
if(!grid[i][row] || grid[i][row] != player)
{
break;
}
counter++;
}
for(var j:uint = column+1; j<_columns; j++)
{
if(!grid[j][row] || grid[j][row] != player)
{
break;
}
counter++;
}
if(counter >=4)
{
return true;
}
else
{
return false;
}
}
I actually ended up doing something pretty simple...Converted the grid array to a string then look for 4 in a row...Only tricky part was getting the correct array for the diagonal possibilities but I got that worked out too.