This site requires JavaScript, please enable it in your browser!
Greenfoot back
SymInvader
SymInvader wrote ...

2019/5/8

Level Progression

SymInvader SymInvader

2019/5/8

#
Hi all, I'm working on improving a platform game and I'm implementing levels into it. If this is the case, how do I modify the code where "game overs" and "game wins" if necessary? (I already know I want to try and put in the line below somewhere in the code):
Greenfoot.setWorld(new DungeonEscape_LV2());

//Or whatever level the player progresses to
(Here's the code for my current world, and below that is the code for the player, though you only need to concern yourself with the UnlockDoor and CoinCollection_MonsterKill_or_KeyCollection methods.)
import greenfoot.*;

public class DungeonEscape_LV1 extends World
{
    int WorldWidth = getWidth();
    int WorldHeight = getHeight();
    private int Score = 0;
    private int Count = 60;
    private int DisplayCount = 60;
        
    public DungeonEscape_LV1() {
        super(950, 750, 1, false);
        
        addObject(new Door(), 50, WorldHeight - 60);
        addObject(new DungeonMonster(), WorldWidth - 330, WorldHeight - 60);
        addObject(new Coin(), 250, WorldHeight - 70);
        addObject(new Coin(), 350, WorldHeight - 70);
        addObject(new Coin(), 450, WorldHeight - 70);
        
        addObject(new Coin(), 700, WorldHeight - 230);
        addObject(new DungeonMonster(), 130, WorldHeight - 230);
        addObject(new Platform(), 180, WorldHeight - 150);
        addObject(new Platform(), 540, WorldHeight - 150);
        
        addObject(new ThePlayer(), (WorldWidth / 2) + 100, WorldHeight - 420);
        addObject(new Platform(), (WorldWidth / 2) + 100, WorldHeight - 340);
        
        addObject(new Platform(), 130, (150 + 70));
        addObject(new Coin(), 50, 145);
        addObject(new Coin(), 150, 145);
        addObject(new Coin(), 250, 145);
        
        addObject(new DungeonMonster(), WorldWidth - 170, 100);
        addObject(new Key(), WorldWidth - 50, 95);
        addObject(new Platform(), WorldWidth - 170, 180);
        
    }
    public void act() {
        UserInfo myInfo = UserInfo.getMyInfo();
        // myInfo.setScore(0);
        // myInfo.store();
        
        showText("Score: " + Score, 50, 25);
        Count--;
        if (Count == 0) {
            DisplayCount--;
            Count = 60;
        }
        
        showText("Timer: " + DisplayCount, WorldWidth - 100, 25);
        showText("Best Time: " + myInfo.getScore(), WorldWidth - 75, 50);
        
        if (DisplayCount <= 0) {
            Greenfoot.stop();
        }
    }
    public void Coin_ScoreIncrease() {
        Score = Score + 50;
    }
    public void MonsterKill_ScoreIncrease() {
        Score = Score + 100;
    }
    public void BestTimes() {
        UserInfo myInfo = UserInfo.getMyInfo();
        if (UserInfo.isStorageAvailable()) {
            if (DisplayCount > myInfo.getScore()) {
                myInfo.setScore(DisplayCount);
                myInfo.store();
            }
        }
        Greenfoot.stop();
    }
}
import greenfoot.*;

public class ThePlayer extends Actor
{
    int VerticalSpeed = 0;
    int Gravity = 1;
    int JumpCount = 0;
    int KeyUnlocks = 0;
    private int HeightToGround = getImage().getHeight()/2; //50
    private int SideWidth = getImage().getWidth()/2; //50
    int PlatformHeight = 50;
    boolean OnGround;
    GreenfootSound CoinPickup = new GreenfootSound("Coin Pickup.mp3");
    
    private GreenfootImage Right = new GreenfootImage("ThePlayer (Facing Right).png");
    private GreenfootImage Left = new GreenfootImage("ThePlayer (Facing Left).png");
    
    public void act() 
    {   
        HorizontalMovement();
        VerticalMovement();
        UnlockDoor();
        CoinCollection_MonsterKill_or_KeyCollection();
    }
    public void HorizontalMovement() {
        int WorldWidth = getWorld().getWidth();
        int X = getX();
        
        int DirectionX = 0;
        setRotation(0);
        
        if (Greenfoot.isKeyDown("Left")) {
            DirectionX--;
        }
        if (Greenfoot.isKeyDown("Right")) {
            DirectionX++;
        }
        
        setLocation (X + (DirectionX * 5), getY());
        if (DirectionX == -1) {
            setImage(Left);
        }
        if (DirectionX == 1) {
            setImage(Right);
        }
        
        if (getX() < SideWidth) {
            setLocation(SideWidth, getY());
        }
        if (getX() > WorldWidth - SideWidth) {
            setLocation(WorldWidth - SideWidth, getY());
        }
        if (getOneIntersectingObject(Platform.class) != null) {
            setLocation(X - DirectionX, getY());
        }
    }
    public void VerticalMovement() {
        int WorldHeight = getWorld().getHeight();
        int Y = getY();
        
        VerticalSpeed += Gravity;
        setLocation (getX(), Y + VerticalSpeed);
        
        int dy = (int)Math.signum(VerticalSpeed);
        if (getOneIntersectingObject(null) != null) {
            if (dy > 0) {
                setLocation (getX(), Y - dy - 1);
                
                OnGround = true;
                VerticalSpeed = 0;
            }
            else if (dy <= 0) {
                setLocation(getX(), Y + dy + 1);
                OnGround = false;
            }
        }
        
        if (getY() > WorldHeight - HeightToGround) {
            setLocation (getX(), WorldHeight - HeightToGround);
            VerticalSpeed = 0;
            OnGround = true;
        }
        if (Greenfoot.isKeyDown("Up") && OnGround == true) {
            VerticalSpeed = -20;
            OnGround = false;
        }
    }
    public void UnlockDoor() {
        if (Greenfoot.isKeyDown("Down")) {
            Actor Door = getOneIntersectingObject(Door.class);
            if (Door != null && KeyUnlocks == 1) {
                DungeonEscape_LV1 myWorld = (DungeonEscape_LV1)getWorld();
                Greenfoot.playSound("Game Win.mp3");
            }
        }
    }
    public void CoinCollection_MonsterKill_or_KeyCollection() {
        DungeonEscape_LV1 myWorld = (DungeonEscape_LV1)getWorld();
        
        Actor Coin = getOneIntersectingObject(Coin.class);
        Actor Key = getOneIntersectingObject(Key.class);
        
        if (Coin != null) {
            CoinPickup.play();
            myWorld.removeObject(Coin);
            myWorld.Coin_ScoreIncrease();
        }
        if (Key != null) {
            CoinPickup.play();
            myWorld.removeObject(Key);
            KeyUnlocks = 1;
        }
        
        Actor Dead_DungeonMonster = getOneObjectAtOffset(0, HeightToGround + 1, DungeonMonster.class); //From above
        Actor Killing_DungeonMonster_1 = getOneObjectAtOffset(0, -(HeightToGround + 5), DungeonMonster.class); //From below
        Actor Killing_DungeonMonster_2 = getOneObjectAtOffset((SideWidth + 5), 0, DungeonMonster.class); //From the left
        Actor Killing_DungeonMonster_3 = getOneObjectAtOffset(-(SideWidth + 5), 0, DungeonMonster.class); //From the right
        if (Dead_DungeonMonster != null) {
            myWorld.removeObject(Dead_DungeonMonster);
            myWorld.MonsterKill_ScoreIncrease();
            VerticalSpeed = -10;
            Greenfoot.playSound("Monster Kill.mp3");
        }
        if (Killing_DungeonMonster_1 != null) {
            getWorld().removeObject(getWorld().getObjects(ThePlayer.class).get(0));
            Greenfoot.stop();
            Greenfoot.playSound("Game Over.mp3");
        }
        if (Killing_DungeonMonster_2 != null) {
            getWorld().removeObject(getWorld().getObjects(ThePlayer.class).get(0));
            Greenfoot.stop();
            Greenfoot.playSound("Game Over.mp3");
        }
        if (Killing_DungeonMonster_3 != null) {
            getWorld().removeObject(getWorld().getObjects(ThePlayer.class).get(0));
            Greenfoot.stop();
            Greenfoot.playSound("Game Over.mp3");
        }
    }
}
SymInvader SymInvader

2019/5/10

#
Another thing I'm working on: I'm adding a SpikeTrap sprite but the player is dying when it's still above where the spikes are (it's about half the height of the player actor). Can someone please help with this? Thanks! Code for the VerticalMovement:
public void VerticalMovement() {
        int WorldHeight = getWorld().getHeight();
        int Y = getY();
        
        VerticalSpeed += Gravity;
        setLocation (getX(), Y + VerticalSpeed);
        
        int dy = (int)Math.signum(VerticalSpeed);
        if (getOneIntersectingObject(null) != null) {
            if (dy > 0) {
                setLocation (getX(), Y - dy - 1);
                OnGround = true;
                VerticalSpeed = 0;
            }
            else if (dy <= 0) {
                setLocation(getX(), Y + dy + 1);
                OnGround = false;
            }
        }
        if (getY() > WorldHeight - HeightToGround) {
            setLocation (getX(), WorldHeight - HeightToGround);
            VerticalSpeed = 0;
            OnGround = true;
        }
        if (Greenfoot.isKeyDown("Up") && OnGround == true) {
            VerticalSpeed = -20;
            OnGround = false;
        }
    }
Code for the SpikeTrap:
Actor SpikeTrap_Above = getOneObjectAtOffset(0, HeightToGround + 1, SpikeTrap.class); //This works, but it's still way above where the spikes of the actor image actually are.
        Actor SpikeTrap_Side = getOneIntersectingObject(SpikeTrap.class);
        if (SpikeTrap_Above != null) {
            getWorld().removeObject(getWorld().getObjects(ThePlayer.class).get(0));
            Greenfoot.stop();
            Greenfoot.playSound("Game Over.mp3");
        }
        if (SpikeTrap_Side != null) {
            getWorld().removeObject(getWorld().getObjects(ThePlayer.class).get(0));
            Greenfoot.stop();
            Greenfoot.playSound("Game Over.mp3");
        }
danpost danpost

2019/5/10

#
You will prrobably need an intermediate class between World and your sub-levels. Maybe my Super Level Support Class Demo scenario can be helpful, here.
SymInvader SymInvader

2019/5/17

#
The Level demo you provided was really helpful (thanks a lot for that), but I'm still not sure how to revise the methods in ThePlayer that depend on me getting the World. Thanks!
    public void UnlockDoor() {
        if (Greenfoot.isKeyDown("Down")) {
            Actor Door = getOneIntersectingObject(Door.class);
            if (Door != null && KeyUnlocks == 1) {
                // DungeonEscape_LV5 myWorld = (DungeonEscape_LV5)getWorld();
                Greenfoot.stop();
                // if (Level != (Final Level)) {
                    //Increase level number
                // }
                Greenfoot.playSound("Game Win.mp3");
            }
        }
    }
    public void CoinCollection_MonsterKill_or_KeyCollection() {
        Level myWorld = ((Level)getWorld()); //This part is what I need help with the most
        
        Actor Coin = getOneIntersectingObject(Coin.class);
        Actor Key = getOneIntersectingObject(Key.class);
        
        if (Coin != null) {
            CoinPickup.play();
            myWorld.removeObject(Coin);
            myWorld.Coin_ScoreIncrease();
        }
        if (Key != null) {
            CoinPickup.play();
            myWorld.removeObject(Key);
            KeyUnlocks = 1;
        }
        
        Actor Dead_DungeonMonster = getOneObjectAtOffset(0, HeightToGround + 1, DungeonMonster.class); //From above
        Actor Killing_DungeonMonster_1 = getOneObjectAtOffset(0, -(HeightToGround + 5), DungeonMonster.class); //From below
        Actor Killing_DungeonMonster_2 = getOneObjectAtOffset((SideWidth + 5), 0, DungeonMonster.class); //From the left
        Actor Killing_DungeonMonster_3 = getOneObjectAtOffset(-(SideWidth + 5), 0, DungeonMonster.class); //From the right
        if (Dead_DungeonMonster != null) {
            myWorld.removeObject(Dead_DungeonMonster);
            myWorld.MonsterKill_ScoreIncrease();
            VerticalSpeed = -10;
            Greenfoot.playSound("Monster Kill.mp3");
        }
        if (Killing_DungeonMonster_1 != null) {
            getWorld().removeObject(getWorld().getObjects(ThePlayer.class).get(0));
            Greenfoot.stop();
            Greenfoot.playSound("Game Over.mp3");
        }
        if (Killing_DungeonMonster_2 != null) {
            getWorld().removeObject(getWorld().getObjects(ThePlayer.class).get(0));
            Greenfoot.stop();
            Greenfoot.playSound("Game Over.mp3");
        }
        if (Killing_DungeonMonster_3 != null) {
            getWorld().removeObject(getWorld().getObjects(ThePlayer.class).get(0));
            Greenfoot.stop();
            Greenfoot.playSound("Game Over.mp3");
        }
        
        Actor SpikeTrap_Above = getOneObjectAtOffset(0, (HeightToGround) + 1, SpikeTrap.class);
        Actor SpikeTrap_Side = getOneIntersectingObject(SpikeTrap.class);
        if (SpikeTrap_Above != null) {
            getWorld().removeObject(getWorld().getObjects(ThePlayer.class).get(0));
            Greenfoot.stop();
            Greenfoot.playSound("Game Over.mp3");
        }
        if (SpikeTrap_Side != null) {
            getWorld().removeObject(getWorld().getObjects(ThePlayer.class).get(0));
            Greenfoot.stop();
            Greenfoot.playSound("Game Over.mp3");
        }
    }
danpost danpost

2019/5/17

#
If all your DungeonEscape_LV# worlds extend a Levels class, then changing line 92 to the following should work:
Levels myWorld = (Levels)getWorld();
SymInvader SymInvader

2019/5/20

#
Thanks for that! Now the biggest problem I have so far is when I test the code out, the player is unable to move. Help? (Next problem below the code for player movement):
    public void HorizontalMovement() {
        int WorldWidth = getWorld().getWidth();
        int X = getX();
        
        int DirectionX = 0;
        setRotation(0);
        
        if (Greenfoot.isKeyDown("Left")) {
            DirectionX--;
        }
        if (Greenfoot.isKeyDown("Right")) {
            DirectionX++;
        }
        
        setLocation (X + (DirectionX * 5), getY());
        if (DirectionX == -1) {
            setImage(Left);
        }
        if (DirectionX == 1) {
            setImage(Right);
        }
        
        if (getX() < SideWidth) {
            setLocation(SideWidth, getY());
        }
        if (getX() > WorldWidth - SideWidth) {
            setLocation(WorldWidth - SideWidth, getY());
        }
        if (getOneIntersectingObject(Platform.class) != null) {
            setLocation(X - DirectionX, getY());
        }
    }
    public void VerticalMovement() {
        int WorldHeight = getWorld().getHeight();
        int Y = getY();
        
        VerticalSpeed += Gravity;
        setLocation (getX(), Y + VerticalSpeed);
        
        int dy = (int)Math.signum(VerticalSpeed);
        if (getOneIntersectingObject(Platform.class) != null) {
            if (dy > 0) {
                setLocation (getX(), Y - dy - 1);
                OnGround = true;
                VerticalSpeed = 0;
            }
            else if (dy <= 0) {
                setLocation(getX(), Y + dy + 1);
                OnGround = false;
            }
        }
        /*(The code below is just to cause a slight delay, since everytime I tried to with the test killing a monster code
         * without this, the player would instantly die.)*/
        if (getOneIntersectingObject(DungeonMonster.class) != null) {
            if (dy > 0) {
                setLocation (getX(), Y - dy - 1);
                OnGround = true;
                VerticalSpeed = 0;
            }
            else if (dy <= 0) {
                setLocation(getX(), Y + dy + 1);
                OnGround = false;
            }
        }
        if (getY() > WorldHeight - HeightToGround) {
            setLocation (getX(), WorldHeight - HeightToGround);
            VerticalSpeed = 0;
            OnGround = true;
        }
        if (Greenfoot.isKeyDown("Up") && OnGround == true) {
            VerticalSpeed = -20;
            OnGround = false;
        }
    }
Second (and easier) point: The enemy for my game has a simple movement pattern: left or right (changing direction when it hits the edges of the world). Now I want it to change direction whenever it hits a barrier, but the code should be non-specific as to whether or not the monster moves left or right. I just need some clarification whether the code below could be improved on or not (and if not, how to improve it). Thanks for the honest feedback!
public class DungeonMonster extends Actor
{
    private int SideWidth = getImage().getWidth()/2; //50
    private int HeightToGround = getImage().getHeight()/2; //50
    private int Direction = 2;
    private int X;
    private int CostumeChangeCount = 0;
    
    private GreenfootImage Right = new GreenfootImage("DungeonMonster (Facing Right).png");
    private GreenfootImage Left = new GreenfootImage("DungeonMonster (Facing Left).png");
    
    public void act() {
        MonsterMovement();
    }
    public void MonsterMovement() {
        int WorldWidth = getWorld().getWidth();
        int WorldHeight = getWorld().getHeight();
        
        move(Direction);
        if ((getX() > WorldWidth - SideWidth)) {
            setImage(Left);
            Direction = -Direction;
        }
        else if (getX() < SideWidth) {
            setImage(Right);
            Direction = -Direction;
        }
        
        if (getOneIntersectingObject(Barrier.class) != null) {
            CostumeChangeCount = CostumeChangeCount + 1;
            if (CostumeChangeCount % 2 == 0) {
                setImage(Right);
            } else {
                setImage(Left);
            }
            Direction = -Direction;
        }
    }
}
Super_Hippo Super_Hippo

2019/5/20

#
For the first problem: Try to comment out line 30. Maybe the player is touching a platform all the time? For the second problem:
private int direction = 2;
private GreenfootImage[] images =
{
    new GreenfootImage("DungeonMonster (Facing Left).png"),
    new GreenfootImage("DungeonMonster (Facing Right).png")
};

public void act()
{
    move(direction);
    if (isTouching(Barrier.class) || getX()>getWorld().getWidth()-getImage().getWidth()/2 || getX()<getImage().getWidth()/2)
    {
        direction = -direction;
        setImage(images[(direction+2)/4]);
    }
}
If the two images are only mirrored, you can also have one image and mirror it whenever it changes direction.
danpost danpost

2019/5/20

#
Use "left" and "right" -- both with all lowercase letters (on lines 8 and 11).
SymInvader SymInvader

2019/5/21

#
The second problem's resolved, but for the first, the player remains frozen even when I start the game with the player in midair.
danpost danpost

2019/5/21

#
SymInvader wrote...
The second problem's resolved, but for the first, the player remains frozen even when I start the game with the player in midair.
There does appear to be an issue with your OnGround field, although I cannot say if it is related to your current issue. You should be setting it to false at the beginning of the VerticalMovement method. You can then remove lines 49 and 62.
SymInvader SymInvader

2019/5/21

#
It doesn't seem to be related after all. Thanks for the quick fix (still struggling with the issue though).
danpost danpost

2019/5/21

#
SymInvader wrote...
It doesn't seem to be related after all. Thanks for the quick fix (still struggling with the issue though).
What is your class structure for the player (trace of parent classes back to Actor)?
SymInvader SymInvader

2019/5/22

#
The Player is an extended subclass of the Actor class (same with the other actors; they're not extensions for any other class). Aside from that, it interacts with the World class the most for methods that aren't movement. (Sorry if this wasn't the answer you were looking for; still getting the hang of this :P) In any case, I still have the same problem with the player movement. Does anyone have other ideas for a fix?
SymInvader SymInvader

2019/5/29

#
I just figured out the problem and it's all resolved now. The last thing I need to help with now is the high score system, because every test where I score higher than the last high score, it still doesn't change. Putting in the code for the high score below, and below that, the code for it to display. Hope somebody replies soon. Thanks!
    public static void adjustScore(int adjustment) {
        Score += adjustment;
        ScoreText.setImage(new GreenfootImage("Score: "+ Score, 24, Color.WHITE, new Color(0, 0, 0, 0)));
    }
    public static int getScore() {
        return Score;
    }
    public void HighScore() {
        if (UserInfo.isStorageAvailable()) {
            UserInfo myInfo = UserInfo.getMyInfo();
            if (Score > myInfo.getScore()) {
                myInfo.setScore(Score);
                myInfo.store();
            }
        }
    }
    public void act() {
        UserInfo myInfo = UserInfo.getMyInfo();
        
        showText("HIGH SCORE: " + myInfo.getScore(), 150, 150);
        showText("FINAL SCORE: "+ Score, 150, 200);
        if (Greenfoot.mouseClicked(null)) startOver();
    }
You need to login to post a reply.