2
\$\begingroup\$

I am making a side-scrolling platformer game in Flash (Actionscript 3.0). I have made lots of progress lately, but I have come across a new problem.

I will give some background first. My game level's terrain (or 'floor') is referenced by a MovieClip variable called 'floor.' My desire is to have the Player and enemy characters walk along the terrain. I have gotten the Player character to move on the terrain just fine; he walks up/down hills and falls whenever there is no ground beneath him.

Here is the code I created to allow the Player to follow the terrain correctly. Much more code is used to control the Player, but only this code deals with the Player character's following of the terrain and gravity.

    // If the Player's not on the ground (not touching the 'floor' MovieClip)... 
    if (!onGround) {
        // Disable ducking
        downKeyPressed = false;
        // Increase the Player's 'y' position by his 'y' velocity
        player.y += playerYVel;
    }

    // Increase the 'playerYVel' variable so that the Player will fall 
        // progressively faster down the screen. This code technically
        // runs "all the time" but in reality it only affects the player
        // when he's off the ground.
    playerYVel += gravity;

    // Give the Player a terminal velocity of 15 px/frame
    if (playerYVel > 15) {
        playerYVel = 15;
    }

    // If the Player has not hit the 'floor,' increase his falling 
        //speed
    if (! floor.hitTestPoint(player.x, player.y, true)) {
        player.y += playerYVel;
        // The Player is not on the ground when he's not touching it
        onGround = false;
    }

Since getting this code to work for the Player, I have created a 'SkullDemon' class, which is one of the planned enemies for my game. I want the 'SkullDemon' objects to move along the terrain like the Player does. With lots of great help, I have already coded the EventListeners, etc. necessary for the 'SkullDemons' to move.

Unfortunately, I am having trouble getting them to move along the terrain. In fact, they do not touch the terrain at all; they move along the top of the boundary of the 'floor' MovieClip! I had a simple text diagram showing what I mean, but unfortunately Stackoverflow does not format it correctly. I hope my problem is clear from my description.

Strangely enough, my code for the Player's movement and the 'SkullDemon's' movement is almost exactly the same, yet the 'SkullDemons' do not move like the Player does. Here is my code for the SkullDemon movement:

    // Move all of the Skull Demons using this method
protected function moveSkullDemons():void {
    // Go through the whole 'skullDemonContainer'
    for (var skullDi:int = 0; skullDi < skullDemonContainer.numChildren; skullDi++) {
        // Set the SkullDemon 'instance' variable to equal the current SkullDemon
        skullDIns = SkullDemon(skullDemonContainer.getChildAt(skullDi));

        // For now, just move the Skull Demons left at 5 units per second
        skullDIns.x -= 5;

        // If the Skull Demon has not hit the 'floor,' increase his falling 
            //speed
        if (! floor.hitTestPoint(skullDIns.x, skullDIns.y, true)) {
            // Increase the Skull Demon's 'y' position by his 'y' velocity
            skullDIns.y += skullDIns.sdYVel;
            // The Skull Demon is not on the ground when he's not touching it
            skullDIns.sdOnGround = false;
        }

        // Increase the 'sdYVel' variable so that the Skull Demon will fall 
            // progressively faster down the screen. This code technically
            // runs "all the time" but in reality it only affects the Skull Demon
            // when he's off the ground.
        if (! skullDIns.sdOnGround) {
            skullDIns.sdYVel += skullDIns.sdGravity;

            // Give the Skull Demon a terminal velocity of 15 px/frame
            if (skullDIns.sdYVel > 15) {
                skullDIns.sdYVel = 15;
            }
        }

        // What happens when the Skull Demon lands on the ground after a fall?
            // The Skull Demon is only on the ground ('onGround == true') when 
                // the ground is touching the Skull Demon MovieClip's origin point,
                // which is at the Skull Demon's bottom centre
        for (var i:int = 0; i < 10; i++) {
            // The Skull Demon is only on the ground ('onGround == true') when 
                // the ground is touching the Skull Demon MovieClip's origin point,
                // which is at the Skull Demon's bottom centre
            if (floor.hitTestPoint(skullDIns.x, skullDIns.y, true)) {
                skullDIns.y = skullDIns.y;
                // Set the Skull Demon's y-axis speed to 0
                skullDIns.sdYVel = 0;
                // The Skull Demon is on the ground again
                skullDIns.sdOnGround = true;
            }
        }           
    }       
} // End of 'moveSkullDemons()' function

It is almost like the 'SkullDemons' are interacting with the 'floor' MovieClip using the hitTestObject() function, and not the hitTestPoint() function which is what I want, and which works for the Player character.

I am confused about this problem and would appreciate any help you could give me. Thanks!

\$\endgroup\$
4
  • \$\begingroup\$ Why do you have an inner for loop where you do the hitTestPoint for your "SkullDemon"? It seems like the "SkullDemons" are children of another container (skullDemonContainer). This could cause your issue, if the container position doesn't align with the container where floor belongs to (because hitTestPoint expects world (stage) coordinates) \$\endgroup\$
    – bummzack
    Commented Oct 30, 2011 at 22:25
  • \$\begingroup\$ @bummzack: When I add the "SkullDemons" to the game, I place them using the project's .fla file. Then I add them to the "skullDemonContainer." I use the container out of convenience; I have another listener that allows Player/Skull Demon interaction. That's why I use the for loop to move every object within the "skullDemonContainer." How do I make sure the "skullDemonContainer" aligns correctly with the "floor?" Someone suggested I use the 'localToGlobal()' function, and I tried that. But that didn't seem to work. The Player object, which moves correctly, is not inside a container. \$\endgroup\$ Commented Oct 30, 2011 at 22:33
  • \$\begingroup\$ @bummzack: I just tried running the same Skull Demon movement code for just one "SkullDemon" object. The results seem to be similar; the "SkullDemon" automatically gravitates toward the top border of the "floor" movie clip. I have tried starting him below and above the border - same result. The 'floor' is added to the 'envContainer,' which also stores the 'skullContainer:' envContainer.addChild(floorL1); and envContainer.addChild(skullDemonContainer);. The 'floor' variable is then made equal to 'floorL1.' \$\endgroup\$ Commented Oct 30, 2011 at 22:40
  • \$\begingroup\$ @bummzack: The reason I add the 'skullDemonContainer' to the 'envContainer' is to ease scrolling, which I code in a Listener. \$\endgroup\$ Commented Oct 30, 2011 at 22:45

2 Answers 2

1
\$\begingroup\$

I also think that the problem is at the line

skullDIns = SkullDemon(skullDemonContainer.getChildAt(skullDi));

I had a similar situation once and found that is better to store the enemies in an Array that has no children and is not added to the stage. Simply add enemy instances to an Array and loop through them. Then your SkullDemons will not have a parent container in the scene tree and will be children of the stage (or some level object).

Make your skullDemonContainer an Array like this:

var skullDemonContainer:Array = new Array();

Then add you SkullDemons to the skullDemonContainer not as children but like this:

skullDemonContainer.push(skullDemon1);

Finally change the loop code in your moveSkullDemons() method

for (var skullDi:int = 0; skullDi < skullDemonContainer.length; skullDi++) 
{
    skullDIns = skullDemonContainer.[skullDi] as SkullDemon;
    ...
\$\endgroup\$
0
\$\begingroup\$

I am not an ActionScript developer. It seems to me that this line

skullDIns = SkullDemon(skullDemonContainer.getChildAt(skullDi));

constructs a new SkullDemon object and assigns it to the skullDIns variable. Subsequently you modify this copy instead of the object in the container.

I think you should have more success doing this:

skullDIns = skullDemonContainer.getChildAt(skullDi);
\$\endgroup\$
4
  • \$\begingroup\$ That's just a way to perform type-casting in Actionscript. Although the more readable form would be skullDemonContainer.getChildAt(skullDi)) as MovieClip \$\endgroup\$
    – bummzack
    Commented Oct 31, 2011 at 8:19
  • \$\begingroup\$ Would that return a copy or a reference to the same object though? \$\endgroup\$
    – jmp97
    Commented Oct 31, 2011 at 9:48
  • \$\begingroup\$ @OP: Can you make sure the y values of the objects in the container are actually changed after you have called the function? \$\endgroup\$
    – jmp97
    Commented Oct 31, 2011 at 10:09
  • \$\begingroup\$ Hey guys, Sorry for my late feedback. I have actually worked around this issue. Instead of using Skull Demon-floor collision to move the characters, I just placed the Skull Demons in places and had them move back and forth. Thanks for the comments! :) \$\endgroup\$ Commented Nov 9, 2011 at 23:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .