This site requires JavaScript, please enable it in your browser!
Greenfoot back
vtn2@calvin.edu
vtn2@calvin.edu wrote ...

2014/7/24

Accessing World from Actor constructor

vtn2@calvin.edu vtn2@calvin.edu

2014/7/24

#
One of the (few) irritating things about greenfoot, in my opinion, is that you cannot access the World object from the Actors' constructors. I understand why this is -- the World constructor is where you put the calls to the object constructors and call addObject(). But, I find this irritating. Is there another model that would work better that would allow Actors' constructors to call getWorld() and not get null back? I would like this because I think an Actor ought to be able to do stuff like ask the World what its size is, and then place itself where it should go. E.g., an Actor may want to place itself in the center of the screen, no matter what size the World is. So, I'm looking for an alternative to do doing stuff like this in the World constructor: addObject(new Boy1(), 300, 200); Thanks. Vic
erdelf erdelf

2014/7/24

#
there is the overridable method addedToWorld in the Actor class u could place ur code there
lordhershey lordhershey

2014/7/24

#
You can add a new constructor, example a new Boy1 constructor can be:
1
2
3
4
5
6
public Boy1(World w)
{
    //This creates a new Boy Object
    //and I have a world reference
    w.addObject(this,whereEverX,whereEverY);
}
This is not the best solution, a static factory method would probably be better:
1
2
3
4
5
6
7
8
//Somewhere in the Boy1 class
 
public static void BoyFactory(World w)
{
  Boy1 b = new Boy1();
  //Query w object to get x,y
  w.addObject(b,x,y);
}
Then you can add these from things from world object just by saying Boy1.BoyFactory(this);
NikZ NikZ

2014/7/24

#
Would using getWidth() and getHeight() help?
lordhershey lordhershey

2014/7/24

#
erdelf's suggestion of overriding the addedToWorld is the best one.
danpost danpost

2014/7/24

#
Instead of
1
addObject(new Boy1(), 300, 200);
you could just use this:
1
addObject(new Boy1(), getWidth()/2, getHeight()/2);
This will always place a new boy object in the center of the world no matter what size it is (unless your world has an even number of cells horizontally or vertically and the cell size is substantially large). To clarify, if your world was (4, 4, 60) or (10, 15, 30), the actor would not be placed very near the center, but, 30 or 15 pixels from the center. Even in worlds that are (600, 600, 1), it would not be placed in the exact center, because the exact center is in between the four centermost pixels; but, it is not as apparent as in a gridded world with an even dimension, as it will only be a half a pixel off of dead-center.
joeybbb joeybbb

2014/7/24

#
"One of the (few) irritating things about greenfoot, in my opinion, is that you cannot access the World object from the Actors' constructors. " like this buddy: public static CLASSNAME Instance; then in your actor classes: CLASSNAME.Instance. whatever
joeybbb joeybbb

2014/7/24

#
oh and make sure this is in the world class constructor: Instance = this;
danpost danpost

2014/7/24

#
vtn2@calvin.edu wrote...
"One of the (few) irritating things about greenfoot, in my opinion, is that you cannot access the World object from the Actors' constructors. "
This quote can only place limitation on what you can learn instead of opening your mind to greater possibilities. Please note that greenfoot is not the cause of this slight inconvenience; and that there are multiple ways to make the world object accessible to your Actor subclass constructors. Also, it is very rare for an actor instance to need access to a world which it is not yet in. BTW, what other irritating things are included in '(few)'?
NikZ NikZ

2014/7/25

#
danpost wrote...
Instead of
1
addObject(new Boy1(), 300, 200);
you could just use this:
1
addObject(new Boy1(), getWidth()/2, getHeight()/2);
This will always place a new boy object in the center of the world no matter what size it is (unless your world has an even number of cells horizontally or vertically and the cell size is substantially large). To clarify, if your world was (4, 4, 60) or (10, 15, 30), the actor would not be placed very near the center, but, 30 or 15 pixels from the center. Even in worlds that are (600, 600, 1), it would not be placed in the exact center, because the exact center is in between the four centermost pixels; but, it is not as apparent as in a gridded world with an even dimension, as it will only be a half a pixel off of dead-center.
Yes, this is what I meant.
davmac davmac

2014/7/25

#
One of the (few) irritating things about greenfoot, in my opinion, is that you cannot access the World object from the Actors' constructors
You can pass the world to an actor's constructor as a parameter.
1
2
3
4
5
public Boy1(World world)
{
    // World is in 'world'; do not use getWorld()
    // ...
}
vtn2@calvin.edu vtn2@calvin.edu

2014/7/25

#
All, thanks for the feedback. (danpost: I think I must have struck a nerve with you...) The best solution suggested above, for me, was to use addedToWorld(), which I knew about, but had not investigated. With this code, my wishes are fulfilled:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    public Boy() {
        System.out.println("Boy constructor.  World object is " + getWorld());  // should be null.
    }
     
    public void addedToWorld(World w)
    {
        System.out.println("Boy: addedToWorld().  World object is " + w);
        System.out.println("Boy: width of world is " + w.getWidth());
        setLocation(400, 50);
    }
 
//  From MyWorld class:
 
    public MyWorld()
    {   
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(600, 400, 1);
        System.out.println("MyWorld: constructor start");
         
        addObject(new Boy(), 200, 200);
        System.out.println("MyWorld: called Boy constructor");
        System.out.println("MyWorld: constructor done");
    }
The output I get when I compile this code is now: MyWorld: constructor start Boy constructor. World object is null Boy: addedToWorld(). World object is MyWorld@7dbc345a Boy: width of world is 600 MyWorld: called Boy constructor MyWorld: constructor done So, it shows that I can get the World object handle in Boy before act() is called the first time. That's really what I was after. Danpost: mostly I love Greenfoot. I wish GreenfootImage had a setPenWidth() method -- get that added to 2.4 quick, ok? :-) I wish there was a way to set the "rotational center" of an image so you could rotate it around that point. And, I wish there was a way to programmatically set the speed in terms of frames per second. I know that would be tough, as Greenfoot runs on many computers of different speeds... but it would be nice anyway... :-) Thanks.
danpost danpost

2014/7/25

#
No nerves struck here.
So, it shows that I can get the World object handle in Boy before act() is called the first time. That's really what I was after
Like I said, there are multiple ways to accomplish this.
I wish GreenfootImage had a setPenWidth() method -- get that added to 2.4 quick, ok? :-)
Do not hold your breath. Try implementing your own.
I wish there was a way to set the "rotational center" of an image so you could rotate it around that point.
You can accomplish this programmatically by drawing the image on a larger image base with the rotational pivot point in the center.
I wish there was a way to programmatically set the speed in terms of frames per second.
This can also be done programmatically by controlling the calls to the various act methods (renamed, of course; so they are not executed automatically) from the world class act method based on time.
You need to login to post a reply.