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

2023/5/15

Programing an endless route with 2 gifImages

Ururu Ururu

2023/5/15

#
Hello, I have been trying to program a methode which allows me to generate specific routes for specific objects produced in my world constructor. Since im using a GifImages as subactors im aware that ill need to use 2 objects (original and horizontally mirrorred) in order to create the illusuon of making the object turn 180 degrees. the enemies r supposed to either go up and down or left to right. I plan on placing 3 enemies in seperate positions in my world and then use methodes inorder make them move accordingingly. Here are various approaches i have been trying to realise:
public class Ghost extends Enemy
{
    public GifImage Ghost = new GifImage("Ghost.gif");
    public GifImage Ghost1 = new GifImage("Ghost1.gif");
    int scalePercent = 25;
    int i = 105;
    int a = 2;
    int b = 105+a;
    
    MyWorld myworld = (MyWorld) getWorld();
    public Ghost()
    {
        shrinkInSize();
        setImage(Ghost.getCurrentImage());
    }
    public void act()
    {
        pathway1();
        //addedToWorld(myworld);
    }
    public void shrinkInSize()
    {
        for (GreenfootImage gif : Ghost.getImages())
        {
            int wide = gif.getWidth()*scalePercent/100;
            int high = gif.getHeight()*scalePercent/100;
            gif.scale(wide, high);
        }
    }
    public void pathway3()
    {
        setLocation(getX(),i);
        setImage(Ghost.getCurrentImage());
        if (i == 105)
        {
            getImage().mirrorHorizontally();
            setImage(Ghost.getCurrentImage());
            i++;
        } 
        if(i == 430)
        {
            getImage().mirrorHorizontally();
            setImage(Ghost.getCurrentImage());
            i--;   
        }
    }
    public void pathway2()
    {
        setLocation(getX(),getY());
        for(i=getY();i<=430;i++)
        {
            if((getY() == 430))
            {
                getImage().mirrorHorizontally();
                setImage(Ghost.getCurrentImage());
                i--;
            }
        }
    }
    protected void addedToWorld(World myworld)
    {
        getWorld();
        getWorld().getObjects(Ghost.class);
        //Ghost ghost = getWorld().getObjects(Ghost.class).get(430);
        getY();
        getX();
        setLocation(getX(),getY());
        for(i=getY();i<=430;i++)
        {
            if((ghost.getY() == 430))
            {
                getWorld().removeObjects(getWorld().getObjectsAt(280, 430, null));
                i--;
            }
        }
    }
    public void pathway11()
    {
        setLocation(getX(),i);
        for(i=105;i<=430;i++)
        {
            setImage(Ghost.getCurrentImage());
            i++;
            if((i == 430))
            {
                getWorld().removeObject(this);
                Actor Ghost1 = getOneIntersectingObject(Ghost1.class);
                getWorld().addObject(new Ghost1(),280,430);
            }
        }
    }
    public void pathway1()
    {
        setImage(Ghost.getCurrentImage());
        getX();
        getY();
        setLocation(getX(),getY()+a);
        getY();
        setLocation(getX(),getY()+a);
        if(this.getY()==430)
        {
            getWorld().removeObjects(getWorld().getObjectsAt(280, 430, null));
        }
    }
Pls ignore the horizonally mirrorred image statement. I already know that this can not be applied on gifs. As u can see I named my method as pathway1, 2 ,3 etc since i want to apply these on a single object, not the whole class. I would really appreciate some tips, solutions or ideas on how i can make this work.
Ururu Ururu

2023/5/15

#
Also I what im currently trying to do is remove my original object Ghost once it has reached the end of the path and then add object my mirrorred Ghost1 and make him go back to the start location. I prefere the approach with getY()+a since it sets a certain speed, while int i++ or i-- moves way to fast. Almost instantly
Ururu Ururu

2023/5/16

#
I have now tried to limit it down with this following code. But the issue still lies within the remove statement which in inside the loop. I however cant remove it bc this action need to be excecuted whenever y == endY.
public void pathway()
    {
        for(int y = startY; y <= endY; y += speed)
        {
            setLocation(getX(), y);
            setImage(ghostGif.getCurrentImage());
            if (y == endY) 
            {
                getWorld().removeObject(this);
                Ghost1 ghost1 = new Ghost1();
                ghost1.setLocation(getX(), endY);
                getWorld().addObject(ghost1, 280, endY);
                break;
            }
        }
    }
danpost danpost

2023/5/16

#
Ururu wrote...
I have been trying to program a methode which allows me to generate specific routes for specific objects produced in my world constructor. Since im using a GifImages as subactors im aware that ill need to use 2 objects (original and horizontally mirrorred) in order to create the illusuon of making the object turn 180 degrees. the enemies r supposed to either go up and down or left to right. I plan on placing 3 enemies in seperate positions in my world and then use methodes inorder make them move accordingingly. Here are various approaches i have been trying to realise: << Code Omitted >> Pls ignore the horizonally mirrorred image statement. I already know that this can not be applied on gifs. As u can see I named my method as pathway1, 2 ,3 etc since i want to apply these on a single object, not the whole class. I would really appreciate some tips, solutions or ideas on how i can make this work.
First, let's go over what seems obvious (to me). Line 10 will never have the variable assigned anything but null. The assignment is executed before the actor is placed into a world. A better place for line 14 might be in the addedToWorld(World) method. This is just what my preference would be. I was hoping to work my way down the class; but, I will get back to the pathway3 method later. The for loop in pathway2 method will execute in its entirety in one act step. So the end result will instantly be achieved (not what you want). Not sure what you are trying to achieve with the addedToWorld(World) method (with what code is currently in it). Please provide some insight into this. Also, all lines before the for loop there do absolutely nothing. If confused about the assessment, please say so and I will elaborate. Again, in the pathway11 method, the for loop will execute completely in one act step. You need to program the actor for what it needs to do at one instance of time; not for what it will do throughout its life (but each instance of time throughout its life should be addressed). What it does will depend on its current state (location, direction moving, etc.). In the pathway1 method, you again have some "do nothing" lines; plus, you have a duplicated line. It appears you want all actors be removed from a specific location when the ghost gets to its lowest point. The method you are using to get the actors at that location will include this ghost, which will also be removed from the world (not what you want). Now, back to the pathway3 method. One the variable i is raised from 105 or lowered from 430, I do not see how it will change again. If it is 105 and is raised to 106, then where in the method will it again get raised to 107? Okay, so generally speaking, each ghost will be moving either horizontally or vertically. Plus, they will "pace" back and forth. Plus, they will be animated using gif images -- one set for one way and one set for the other. Do you also have another 2 sets of gif images for moving horizontally? No matter. All your ghosts will be using the same gif image sets, but each ghost, as coded, will have its own copy of those sets. This can be improved upon by letting all your ghosts use the same copy of those images. This is done by using static fields for the GifImage objects. However, it is best not to assign those fields in the declaration lines. I would use the constructor for this, but only assigning the images if the fields are still null. An int direction field might be of some use. Actually, it might be very helpful. The direction could be EAST (0), SOUTH (1), WEST (2) or NORTH (3). The value can be used to index the GifImage set when the sets are put into an array:
private static final GifImage[] gifs;

private int direction;

public Ghost() {
    this(1);
}

public Ghost(int dir) {
    direction = dir;
    if (gifs == null) {
        gifs = new GifImage[4];
        gif[0] = null; // for images facing right
        gif[1] = new GifImage("Ghost.gif");
        gif[2] = null; // for images facing left
        gif[3] = new GifImage("Ghost.gif");
        for (int i=0; i<4; i++) {
            if (gif[i] == null) continue;
            for (GifImage gif : gif[i].getImages()) {
                gif.scale(gif.getWidth()*scalePercent/100, gif.getHeight()*scalePercent/100);
                if (i > 1) {
                    gif.mirrorHorizontally();
                }
            }
        }
    }
    // setImage(gif[direction].getCurrentImage());
}
This will create and load the array, plus resize all images and mirror the appropriate sets. The shrinkToSize method can then be discarded. The addedToWorld(World) method can be discarded also. Now, let's deal with the act method -- move, check direction change and removing actors, and set image.
public void act() {
    setRotation(90*direction);
    move(2);
    setRotation(0);
    if ((direction == 1 && getY() <= 105) ||
        (direction == 3 && getY() >= 430) ||
        (direction == 0 && getX() <= 85) || // adjust the value (85) as needed
        (direction == 2 && getX() >= 715)) {// adjust the value (715) as needed
        direction = (direction+2)%4;
        if (getY() >= 430) {
            for (Object obj : getWorld().getObjectsAt(280, 430, Actor.class)) {
                if (obj == this) continue;
                getWorld().removeObject((Actor)obj);
            }
        }
    }
    setImage(gifs[direction].getCurrentImage());
}
In fact, I think I just gave you all that is needed within the class. That is, you could replace everything within the class with what I gave here. Only change I might make from that is adding an int speed field (which was your field called a). But, that is not necessary if the speed never changes. You just need to add the images for the horizontal movements. One other thing I might do is add an array to hold the limiting x and y values. The entire class would then look something like this:
import greenfoot.*;

public class Ghost extends Enemy {
    private static final GifImage[] gifs;
    
    private int direction;
    private int speed = 2;
    private int[] limits; // coordinate limits { high limit, low limit } 
    
    public Ghost() {
        this(1, new int[] { 430, 105 });
    }
    
    public Ghost(int dir, int[] coords) {
        direction = dir;
        limits = coords;
        if (gifs == null) {
            gifs = new GifImage[4];
            gif[0] = null; // for images facing right
            gif[1] = new GifImage("Ghost.gif");
            gif[2] = null; // for images facing left
            gif[3] = new GifImage("Ghost.gif");
            for (int i=0; i<4; i++) {
                if (gif[i] == null) continue;
                for (GifImage gif : gif[i].getImages()) {
                    gif.scale(gif.getWidth()*scalePercent/100, gif.getHeight()*scalePercent/100);
                    if (i > 1) {
                        gif.mirrorHorizontally();
                    }
                }
            }
        }
        // setImage(gif[direction].getCurrentImage());
    }
    
    public void act() {
        setRotation(90*direction);
        move(speed);
        setRotation(0);
        int sign = direction/2 == 0 ? 1 : -1;
        if ((direction%2 == 0 ? getX() : getY())*sign >= limits[direction/2]*sign ) {
            direction = (direction+2)%4;
            if (getY() >= 430) {
                for (Object obj : getWorld().getObjectsAt(280, 430, Actor.class)) {
                    if (obj == this) continue;
                    getWorld().removeObject((Actor)obj);
                }
            }
        }
        setImage(gifs[direction].getCurrentImage());
    }
}
This is not tested, but should be close to what you want. To create an horizontally moving ghost, use something like (for example):
Ghost ghost = new Ghost(0, new int[] { 715, 85 });
addObject(ghost, 85, 400);
Ururu Ururu

2023/5/16

#
As u noticed line 14 is best suited in the addedToWorld method. I wasnt sure whether to put it in the field or in the method itself. My initial problem, which i tried to solve with addedToWorld was to determine the current coordinate of the ghost i have added in MyWorld constructor so that I could make a if-condition (y==430) which is the position i want my Ghost to be and get replaced by Ghost1. Your explaination regarding the for loop is very helpful! I wasnt aware that it would execute in its entirely. I planned on decreasing it using speed the variable. Regarding pathway1 i tried achieving sth silmilar in fact. Instead of deleting all Objects I tried using "removeOneObject" which unfortunatly didnt work. I read abt a similar issue in a topic discussion and thought it might be a necessary statement. For pathway3 i originally tried determining the Y coordination as get(y)+i and then increase the variable with i++. But the if condition getY()==430 would not make the ghost stop. Therefore i assumed it must be because the Y coordinatrion wouldnt update after increasing it with i. Yey, thats exactly what im trying to program. I have a total of two GifImage. One is facing the left and the other is facing the right side. Im very grateful for this incredible code. Ill also take your tips into consideration and discard any useless methods.
danpost danpost

2023/5/16

#
Ururu wrote...
I have a total of two GifImage. One is facing the left and the other is facing the right side.
So, you do not have one for facing front or one for facing away? Does your scenario use a top-down view of the world? If so, the code can be simplified a bit.
Ururu Ururu

2023/5/16

#
thats right. I managed to simplify it based on whats within my knowledge and it works now :)
danpost danpost

2023/5/17

#
Ururu wrote...
thats right. I managed to simplify it based on whats within my knowledge and it works now :)
Please provide what you simplified it to.
You need to login to post a reply.