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

2015/1/23

Set the size of the world to an amount from a variable

jimboweb jimboweb

2015/1/23

#
I'm trying to make a world that constructs itself based on info written in a file. So it would read its width and height from file, assign them to variables, such as worldWidth and worldHeight, and then call the super, as in:
1
2
3
4
5
public MyWorld(String worldBuilderFile)
    {   
       [...reads the file and assigns the variables worldWidth and worldHeight from it...]
       super(worldWidth, worldHeight, 1);
    }
(This is a simplification; I took out all the parts that says throws IOException bla bla bla. ) But the problem is that Greenfoot does not seem to like variables in the super constructor (even if I just declare them at the beginning of the class), and it also doesn't like anything to come before the super constructor in the world constructor. So is there any way to do this without actually going in and rewriting the World class in Greenfoot itself? I hope so, or else this project I'm working on will take much longer than I thought! Also, I'm sure someone would ask why I would do it this way, why not just write the size of the world in myself. It's because I am trying to make a scrolling world builder that allows a person to place actors outside of the world and define the amount you can scroll the world.
danpost danpost

2015/1/23

#
You can create a start-up world to do that. It should be of the largest possible world size that could be read in if it is to be shared in any way. Although the sizes are read from a file, you might look at the code of the Level class of my Super Level Support Class demo which is a multi-purpose class.
lordhershey lordhershey

2015/1/23

#
What about something like so: Something.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public abstract class Something {
 
    private int width;
    private int height;
    private boolean bounded;
     
    public Something()
    {
        System.out.println("Something() Called");
    }
     
    public Something(int width, int height, boolean bounded)
    {
        this.width = width;
        this.height = height;
        this.bounded = bounded;
    }
     
    public void dumpvars()
    {
        System.out.println("My Width " + width);
        System.out.println("My am I High " + height);
        System.out.println("Bounded " + bounded);
    }
}
SomethingElse.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class WorldDim
    {
        public int width;
        public int height;
        public boolean bounded;
         
        public WorldDim(String Filename)
        {
            //Do File IO Stuff
            width = 500;
            height = 400;
            bounded = true;
        }
    }
 
public class SomethingElse extends Something {
 
     
    public SomethingElse(String filename)
    {
        this(new WorldDim(filename));
    }
     
    public SomethingElse(WorldDim wd)
    {
        super(wd.width,wd.height,wd.bounded);
    }
     
     
    public static void main(String[] args) {
         
        SomethingElse se = new SomethingElse("flubbity.flub");
        se.dumpvars();
    }
 
}
produces this output: My Width 500 My am I High 400 Bounded true this might be something useful.
NDS NDS

2015/1/23

#
public class TestWorld extends World { static int W, H; //static initializer static { // read data from file W = ... H = ... } public TestWorld() { super(W, H, 1); ... } ... }
davmac davmac

2015/1/23

#
But the problem is that Greenfoot does not seem to like variables in the super constructor (even if I just declare them at the beginning of the class), and it also doesn't like anything to come before the super constructor in the world constructor.
That's not Greenfoot's issue, it's Java's. One way to work around it is to use only static fields and methods as parameters to the super constructor call. However, this probably won't help much if you need to read both the height and width of the world, due to the interdependency in how you retrieve them (both from the same file). A more general way is to use the factory method pattern. To apply this pattern, you would give your constructor width and height parameters (and optionally make it private). You would write a static method - the factory method - which reads the width and height, and which then creates and returns the object.
1
2
3
4
5
6
7
8
9
10
11
public static createTestWorld()
{
    int w = ...;
    int h = ...;
    return new TestWorld(w,h);
}
 
private TestWorld(int w, int h)
{
    super(w, h, 1);
}
This is similar to what NDS posts above, but avoids creating unnecessary static variables, and it allows you to pass arguments to the factory method (and potentially allows thread-safe object creation). For more options/information, see this stackoverflow post: http://stackoverflow.com/questions/2303604/is-it-possible-to-do-computation-before-super-in-the-constructor
jimboweb jimboweb

2015/1/24

#
Thanks davmac, that's what I was looking for. I said Greenfoot, but I knew it was a Java issue. Glad to know there's a way around this.
jimboweb jimboweb

2015/1/24

#
Thanks to everyone else too; those are all great suggestions.
NDS NDS

2015/1/26

#
davmac: I am beginer in Greenfoot. Please tell me where the method "createTestWorld" is called. Thanks
davmac davmac

2015/1/26

#
NDS: it's called wherever you call it ;) To use it you would write 'TestWorld.createTestWorld()' (instead of 'new TestWorld()'). One disadvantage of this technique which I should have mentioned is that Greenfoot won't know how to call this method, meaning that it won't be able to automatically create your world. There is another solution which can resolve this, though it's a little more complicated so I won't explain it here, unless someone really needs it. The simplest solution is to have two world classes, and have the first one create the second and immediately switch to it using Greenfoot.setWorld(...).
jimboweb jimboweb

2015/1/27

#
Yes, davmac, that is exactly how I did it once I saw your suggestion. I had a subclass of the world call the factory method, and it worked great. You have the advantage of a different subclass for every world, with all the features of the superclass. Thanks for the suggestion.
You need to login to post a reply.