0

For a Greenfoot final class project, I decided to make a game called "Doggie the Super Catcher". What this game basically does is that the actor, Doggie, will try his best to catch the clovers and special treats that seems to be falling from the trees by running back and forth across the screen (through the user's left and right arrow keyboard input, of course). However, the thing is that I want to create multiple levels, and that I kind of want what I have for the first world (named GameWorld) to appear in level 1, which is in a different world. How am I supposed to do that? In other words, I can't seem to transfer the same things from GameWorld to Level1, which includes the clovers, candies, and score board, when a certain condition is met (i.e., a specific number of points is reached)? FYI: I've used a separate actor for the score board (hope this helps...). Does any of you know of a way? Thanks.

import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

public class Doggie extends Actor
{

// Declare arrays of Greenfoot images for animation
private GreenfootImage[] runningLeft;
private GreenfootImage[] runningRight;

// Declare Greenfoot images for standing still facing left and right
private GreenfootImage standingStill;
private GreenfootImage standingLeft;
private GreenfootImage standingRight;

// 
boolean facingLeft;

// Integers that help control the speed of movement and animation
private int animationCounter;
private int animationDelay;
private int animationDelayCounter;
private int animationSpeed;

Clover c;
SpecialTreat1 c1;
SpecialTreat2 c2;

public Doggie()
{
    String fileName;
    String fileNamePrefix = "left0";
    String fileNameSuffix = ".png";

    runningLeft = new GreenfootImage[3];
    runningRight = new GreenfootImage[3];

    for (int imageCounter = 0; imageCounter < runningLeft.length; imageCounter++)
    {
        fileName = fileNamePrefix + (imageCounter + 1) + fileNameSuffix;
        runningLeft[imageCounter] = new GreenfootImage(fileName);
        runningRight[imageCounter] = new GreenfootImage (runningLeft[imageCounter]);
        runningRight[imageCounter].mirrorHorizontally();
    }

    standingStill = new GreenfootImage ("still01.png");
    standingLeft = new GreenfootImage ("left01.png");
    standingRight = new GreenfootImage (standingLeft);
    standingRight.mirrorHorizontally();

    facingLeft = true;

    animationSpeed = 5;

    animationDelay = 6;

    animationDelayCounter = 0;

    animationCounter = 0;
}

/**
 * Act - do whatever the Doggie wants to do. This method is called whenever
 * the 'Act' or 'Run' button gets pressed in the environment.
 */
public void act() 
{
    animationDelayCounter++;
    if (animationDelayCounter == animationDelay)
    {
        animationCounter++;
        animationDelayCounter = 0;
    }

    if (animationCounter > runningRight.length - 1)
        animationCounter = 0;

    c = (Clover)getOneIntersectingObject(Clover.class);
    c1 = (SpecialTreat1)getOneIntersectingObject(SpecialTreat1.class);
    c2 = (SpecialTreat2)getOneIntersectingObject(SpecialTreat2.class);

    if (c != null)
    {
        c.collect();
        GameWorld gW = (GameWorld)getWorld();
        gW.showPoints();
    }

    if (c1 != null)
    {
        c1.collect();
        GameWorld gW = (GameWorld)getWorld();
        gW.showPoints();
    }

    if (c2 != null)
    {
        c2.collect();
        GameWorld gW = (GameWorld)getWorld();
        gW.showPoints();
    }
}

public void runLeft()
{
    if (!(facingLeft))
        animationCounter = 0;

    facingLeft = true;

    setImage (runningLeft[animationCounter]);
    setLocation (getX() - animationSpeed, getY());
}

public void runRight()
{
    if (facingLeft)
        animationCounter = 0;

    facingLeft = false;

    setImage (runningRight[animationCounter]);
    setLocation (getX() + animationSpeed, getY());
}

public void standStill()
{
    if (facingLeft)
    {   
        setImage(standingLeft);
    }
    else
        setImage(standingRight);
    animationCounter = 0;
    animationDelayCounter = 0;
}

}
Melody Li
  • 3
  • 3

1 Answers1

0

In Greenfoot, levels are usually implemented by having different worlds. So you might have:

class Level1 extends World
{
    ...
}

And

class Level2 extends World
{
     ...
}

They will both appear directly beneath World in the class diagram. If you want to share code between your levels (e.g. they both spawn clovers) then you probably want a shared parent class. So you might have:

class DoggieWorld extends World
{
    public void spawnClovers(int speed)
    {
        if (Greenfoot.getRandomNumber(1000) < speed)
            addObject(new Clover(), Greenfoot.getRandomNumber(getWidth()), 0);
    }
}

Then you have two level classes, each of which extends DoggieWorld (not just plain World), allowing you to call the spawnClovers method from each:

class Level1 extends DoggieWorld
{
    public void act()
    {
        spawnClovers(20);
    }
}

class Level2 extends DoggieWorld
{
    public void act()
    {
        spawnClovers(50);
    }
}

I don't want to make this answer too long, but hopefully that gives the general idea: have a shared parent world class which both level classes inherit from (using extends), and then both level classes can call methods from the shared parent.

Edit: sorry, I think I just understood more clearly that you also want to transfer the actors between the worlds when switching level. You can do this by going through all the actors of the type you are interested in, and removing them from the existing world and adding them to the new world. E.g. include this sort of method in Level1:

public void changeLevel()
{
    World nextLevel = new Level2();
    for (Clover c : getObjects(Clover.class))
    {
        // Must ask for position before removing from world:
        int x = c.getX();
        int y = c.getY();
        removeObject(c);
        nextLevel.addObject(c, x, y);
    }
    Greenfoot.setWorld(nextLevel);
}

Hope that helps

Neil Brown
  • 3,558
  • 1
  • 27
  • 36
  • OK. Thanks for the quick reply, but I've got one more question. Does it mean that all private variables declared in DoggieWorld as well as its constructor will be inherited directly by its subclasses, Level1 and Level2? If so, it means that I don't need to put any constructors or variables into Level1 and Level2, right, assuming that I transfer all the actors exactly the way they were to the new world(s)? – Melody Li Jun 12 '16 at 17:00
  • Oh, wait. I kind of fixed that myself, but for some reason, I don't know why my public variable "score" (declared in DoggieWorld) is ignored by the program when I tried to use it in a condition in Level1.... :( – Melody Li Jun 12 '16 at 20:45
  • Oh, never mind. Worked around your idea for a few hours, and now, I finally got it! Many thanks!!! :P – Melody Li Jun 12 '16 at 21:29