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

2012/3/3

Changing the image of Actors from inside the World.

Omniscience Omniscience

2012/3/3

#
The title really says it all. I've got a few actors that need their images to change under certain circumstances. There are multiple iterations of those actors being produced, all the time. At first, I thought to get a list of all the relevant objects in the world, and start from there...
if (!getObjects(Truck.class).isEmpty()){
Truck truck = (Truck) (getObjects(Truck.class));
truck.setImage("cartoon camel.png");
}
if (!getObjects(Trees.class).isEmpty()){
Trees trees = getClass(Trees.class);
trees.setImage("spiky cactus.png");
}
if (!getObjects(Evergreens.class).isEmpty()){
Evergreens evergreens = (Evergreens) (getObjects(Evergreens.class));
evergreens.setImage("spiky cactus.png");
}
However, the Compiler tells me I cannot cast the lists created into new instances of whatever the actor is... :( Anyway, as always, would be really grateful for an alternate method of changing the images of the Actors from within the world. Thanks for all help and feedback in advance! :)
kiarocks kiarocks

2012/3/3

#
getObjects(Class c) returns a new List, not an actor, so you cannot cast the List to the actor
danpost danpost

2012/3/3

#
The following will change the images of all the actors of a specific type:
if (!getObjects(Truck.class).isEmpty())
{
    for (Object truck : getObjects(Truck.class))
    {
        ((Truck) truck).setImage("cartoon camel.png"); 
    }
}
Repeat for the other types.
Omniscience Omniscience

2012/3/3

#
Thanks danpost. Good, reliable help, as always. :)
Omniscience Omniscience

2012/3/3

#
@danpost So, I've implemented the code... but no change in image? Is this because of the for loop? Thanks.
danpost danpost

2012/3/3

#
No. I ran the code myself before I posted.
Omniscience Omniscience

2012/3/3

#
Hmmm... well, let me post what I've got going on, maybe you can see something I can't...
public void act() {
 if (speedIncrease >= speedLimit && !getObjects(car.class).isEmpty()) {
            desertWorld();
        }
}

public void desertWorld() {
        //when the car's speed reaches a particular threshold, the background for the world, the images of the scenery and the obstacles change...
        speedLimit = 14;
        intervalIncrease = 2000;
        locations = 125;
        chanceLimit = 50;
        obstaclesLimit = 1;
        setBackground("Barren Desert.png");
        if (!getObjects(Truck.class).isEmpty()) {
            for (Object truck : getObjects(Truck.class)) {
                ((Truck) truck).setImage("cartoon camel.png"); 
            }
        }
        if (!getObjects(Trees.class).isEmpty()) {
            for (Object trees : getObjects(Trees.class)) {
                ((Trees) trees).setImage("spiky cactus.png"); 
            }
        }
        if (!getObjects(Evergreens.class).isEmpty()) {
            for (Object evergreens : getObjects(Evergreens.class)) {
                ((Evergreens) evergreens).setImage("spiky cactus.png"); 
            }
        }
    }
danpost danpost

2012/3/3

#
Insert at line 9
System.out.println("Entering desert world.");
then, compile and run to see if it makes it into the method at all.
Omniscience Omniscience

2012/3/3

#
It did. Also, the world's background changes to a desert image, giving further evidence that the run time execution reached at least line 14. Oh, and by the way, thanks for responding to me. Sorry for the continuous burden of a learning mind!
danpost danpost

2012/3/3

#
Try replacing lines 15 through 29 with the following:
for (Object truck : getObjects(Truck.class)) ((Truck) truck).setImage("cartoon camel.png"); 
for (Object trees : getObjects(Trees.class)) ((Trees) trees).setImage("spiky cactus.png"); 
for (Object evergreens : getObjects(Evergreens.class))  ((Evergreens) evergreens).setImage("spiky cactus.png");
as the 'if's are not neccessary because a loop will not run if the list is empty.
danpost danpost

2012/3/3

#
I do not think this will change your results, but will reduce what to look at.
Omniscience Omniscience

2012/3/3

#
Figured out the problem. I have a method that scales images from small, up until their original image size. It was constantly swapping the Actor's images for bigger versions of the same image. Therefore, as soon as the code you gave me came into operation, it was completely superseded by that code, giving the illusion that nothing had happened. I made a quick fix to that scale method.
public static int imageNumber = 0;
protected int Amount;

public void act() {
scaleObjects();
}

private void scaleObjects() {
GreenfootImage [] truckSwap = {new GreenfootImage("Truck.png"),new GreenfootImage("cartoon camel.png")};

 if (getClass() == Truck.class) {        
            setImage(truckSwap[imageNumber]);
            getImage().scale(getImage().getWidth()-Amount, getImage().getHeight()-Amount);
        }
}
And so on for all the other images. I then thought, I have to monitor the value Amount, as this controls how small the images start off, and if this value is too small, the getImage().scale() part will fail. So I went into Truck.class, as GreenfootImage("cartoon camel.png") is smaller than GreenfootImage("Truck.png") ...
public Truck(int myXLocate) {
       
        GreenfootImage a = new GreenfootImage("Truck.png"); 
        GreenfootImage b = new GreenfootImage("cartoon camel.png");
     
        if (this.getImage() == a) {
            Amount = 80;
        }
        if (this.getImage() == b) {
            Amount = 40;
        }
    }
(pants for breath)...uhem... but now the only things that don't scale are the Truck.class images. So, to recap: Fixed: Image Swapping. New Problem: Trucks don't scale.
Omniscience Omniscience

2012/3/3

#
But Wait!! problem is fixed! Here's how i opted to fix the "fail to scale" issue, inside the Truck.class:
GreenfootImage b = new GreenfootImage("cartoon camel.png");
        if (this.getImage() == b && !getWorld().getObjects(Truck.class).isEmpty()) {
            Amount = 40;
        }
        else {
            Amount = 80; 
        }
Now, I'm glad everything is working fine. But I'm still interested to see how you would have done it! Thanks danpost!
danpost danpost

2012/3/3

#
As I am not sure as to all the specifics of your scenario, it is hard to say how I would have done it. Do I understand correctly, that the images are changing size to make it appear they are getting closer (or farther) from the observer? If so, I probably would have three variables, two to hold the scale at full size (x and y) and the other to hold the current percentage of full size; then I would have seperate classes for Truck and Camel, putting a public method in the Truck class to call when the object needs swapped
public void turnToCamel()
{
    getWorld().addObject(new Camel(pctSize), getX(), getY());
    getWorld().removeObject(this);
}
and similar methods in the other classes that change. The Camel class needs a constructor to recieve the percent of full size value
public class Camel extends Actor
{
    private int pctSize = 100;
    private int fullSizeX = 30; // whatever width at full size is
    private int fullSize Y = 20; // whatever height at full size is

    public Camel(int pctSize)
    {
        this.pctSize = pctSize;
        GreenfootImage img = getImage();
        img.scale((int) (fullSizeX * pctSize / 100), (int) (fullSizeY * pctSize / 100));
        setImage(img);
    }
}
You need to login to post a reply.