This site requires JavaScript, please enable it in your browser!
Greenfoot back
Çðæyœn
Çðæyœn wrote ...

2019/5/28

Prevent overlap of objects

1
2
Çðæyœn Çðæyœn

2019/5/28

#
I am creating a game where a spaceship that is moving to the right dodges incoming asteroids. Since I want this to go on for an infinite amount of time, an infinite number of asteroids must be generated. I would like the asteroids generated to be in a random location on the screen, but not overlap each other. Although I am still a beginner in programming and greenfoot, I have a rough idea on how to do this. I suspect that a list will be needed, but I'm not sure how it will work out considering that this list will hold an infinite number of asteroids. Since I am not sure where to start, any help using code snippets is preferred. Thank you in advance. Below is a link to a video demonstrating what my current game looks like: https://drive.google.com/file/d/1UWkkj6ftF3zTFF-zouNRCBkwlOLN3IcV/view
Super_Hippo Super_Hippo

2019/5/28

#
Add the asteroid to the world. In the "addedToWorld" method which is called automatically right after the object is added to the world, check if it is touching another asteroid. If so, either remove it from the world or change the location until it isn't touching anything anymore.
Çðæyœn Çðæyœn

2019/5/28

#
I tried using a for loop to generate 5 asteroids on the screen and not have them overlap. It seems to work, but in the line "addObject(test, Greenfoot.getRandomNumber(getWidth() + 100), Greenfoot.getRandomNumber(getHeight() + 100));", removing the "+100s" restricts the spawning of the asteroids to only on the screen, but an error comes up. The size of the asteroids are each 250 by 250 pixels in a 1200 by 800 pixel world. This is the error that shows: Am I generating these asteroids the wrong way? Is an alternative way to do this such as using an arraylist to store the asteroids then remove them once they are not needed? Here is my current code for my world class:
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
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
/**
 * Write a description of class MyWorld here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class MyWorld extends World
{
    /**
     * Constructor for objects of class MyWorld.
     *
     */
    public MyWorld()
    {   
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(1200, 800, 1, false);
         
        Spaceship ship = new Spaceship();
        addObject(ship, 100, getHeight()/2);
         
        for(int i =0; i<=5;i++) {
            Asteroid test = new Asteroid();
            addObject(test, Greenfoot.getRandomNumber(getWidth() + 100), Greenfoot.getRandomNumber(getHeight() + 100));
            test.avoidOverlap();
        }
    }
     
}
Here is my current code for my asteroid class:
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
37
38
39
40
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
/**
 * Write a description of class Asteroid here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class Asteroid extends Scroll
{
    public Asteroid() {
        GreenfootImage img = new GreenfootImage(20, 20);
 
        img = getImage();
        img.scale(25 + Greenfoot.getRandomNumber(250),
            25 + Greenfoot.getRandomNumber(250));
 
        setImage(img);
 
        setRotation(Greenfoot.getRandomNumber(4)*90);
    }
 
    public void avoidOverlap() {
        while(!this.getIntersectingObjects(Asteroid.class).isEmpty())
        {
            int randX = Greenfoot.getRandomNumber(getWorld().getWidth());
            int randY = Greenfoot.getRandomNumber(getWorld().getHeight());
            this.setLocation(randX, randY);
        }
    }
     
    /**
     * Act - do whatever the Asteroid wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        // Add your action code here. 
    }   
}
I'm not sure how to change this.
Super_Hippo Super_Hippo

2019/5/28

#
The code is running fine for me without errors. (Without the spaceship and without the actual image of the asteroid of course.) Btw, instead of the avoidOverlap method, you can use this: (you also don't need to call the method manually then)
1
2
3
4
5
6
7
protected void addedToWorld(World w)
{
    while (isTouching(Asteroid.class))
    {
        setLocation(Greenfoot.getRandomNumber(w.getWidth()), Greenfoot.getRandomNumber(w.getHeight()));
    }
}
Shouldn't really change anything though. The Java Heap Space Error is probably coming from something else. Restarting Greenfoot might help actually. I am not sure what you want to do with the +100. If you want the asteroids to not spawn at the edges of the world, then you need something like this:
1
100+Greenfoot.getRandomNumber(getWidth()-200);
+100 at the beginning to move the possible range to the right. -200 inside the method to decrease the range by 100 for left and right each.
Çðæyœn Çðæyœn

2019/5/29

#
The Java Heap Space Error only seems to come up if either I get rid of the "+100" or continually press the RESET button until this error comes up. Even getting rid of the "+100" sometimes works and the error doesn't come up, but continually pressing the RESET button without the hundreds also brings up the error eventually (quicker since space is more restricted). I imagine that this error is due sometimes the asteroids are too big, and there is no space for some of the asteroids to spawn on the screen, although I'm not entirely sure. Thank you for your help so far. Also, I'm not sure if this error will come up once I change the for loop in the world class to infinite.
nccb nccb

2019/5/29

#
That code all looks fine. What does the Scroll class do? Asteroid extends it, so that may be related.
Çðæyœn Çðæyœn

2019/5/29

#
As part of my game, my background is infinitely scrolling using the scroll class and the world act method. The asteroid class does not need to be a subclass of the scroll class, but I put it there in case I want to incorporate code in the asteroid class related to the scrolling of the screen. You can find a screen recording of my current game here (old): https://drive.google.com/file/d/1UWkkj6ftF3zTFF-zouNRCBkwlOLN3IcV/view
danpost danpost

2019/5/29

#
Çðæyœn wrote...
As part of my game, my background is infinitely scrolling using the scroll class and the world act method. The asteroid class does not need to be a subclass of the scroll class, but I put it there in case I want to incorporate code in the asteroid class related to the scrolling of the screen.
Which scroll class are you using? Most scroll classes (except maybe ScrollActor) are either World subclasses or separate object, not being a subclass of World or Actor. From the looks of it, it is a separate object as you would require a World super call otherwise and you apparently are not getting any errors not having that call. It is probably my Scroll class as I, that I know of, am the only one who has made one that is a separate object. If it is, it should remain a separate object (no classes should extend it).
Çðæyœn Çðæyœn

2019/5/29

#
The alternative way of scrolling I found out about involves making the background image move using a scroll actor class, and calling methods from the scroll class in my world class. I positioned the background image in the world, and a duplicate of the background image to the right edge of world. I made them simultaneously move to make it look like the screen is actually scrolling, although it's just the same image repeating itself by using two of the same image merged together. The code for my scroll class or world class hasn't so far given me any problems and works well. I will move my object subclass of the scroll class so that both the scroll class and the asteroid class are both sub-classes of Actor. I found out about this alternate way to scroll in Greenfoot through Youtube. The current code for my scroll and world class can be found below: Scroll class:
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
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
/**
 * Write a description of class Scroll here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class Scroll extends Actor
{
    /**
     * Act - do whatever the Scroll wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        // Add your action code here.
    }   
     
    public void ActivateScroll() {
        if (getX() < -getImage().getWidth()/2) {
            setLocation(getWorld().getWidth() + 590, getY());
        }
        setLocation(getX() - 10, getY());
    }
}
World Class:
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
37
38
39
40
41
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
/**
 * Write a description of class MyWorld here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class MyWorld extends World
{
    private SpaceBackground Image1, Image2;
    /**
     * Constructor for objects of class MyWorld.
     *
     */
    public MyWorld()
    {   
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(1200, 800, 1, false);
         
        Image1 = new SpaceBackground();
        addObject(Image1, getWidth()/2, getHeight()/2);
        Image2 = new SpaceBackground();
        addObject(Image2, getWidth() + getWidth()/2, getHeight()/2);
         
        Spaceship ship = new Spaceship();
        addObject(ship, 100, getHeight()/2);
         
        for(int i =0; i<=5;i++) {                       //spawning only 6 asteroids for testing
            Asteroid test = new Asteroid();
            addObject(test, Greenfoot.getRandomNumber(getWidth() + 100), Greenfoot.getRandomNumber(getHeight() + 100));
        }
    }
     
     
     
    public void act() {
        Image1.ActivateScroll();
        Image2.ActivateScroll();
    }
}
danpost danpost

2019/5/30

#
Okay. The java heap space is mainly due to the large size of your world and that you need multiple images for scrolling the background in that world. The scrolling method does help either, as it requires extra imaging. That is, other ways do not require as many large images to be held in fields. At minimum, you will have the current world background (held by the World object) and one copy of the scrolling image (which you have multiple copies of -- one in each of Image1 and Image2). I am presuming, however, that they both contain the same image. At any rate, reducing your world (and your images) to a reasonable size would definitely help. I would not go larger than (800, 600), which is still a pretty good size.
Çðæyœn Çðæyœn

2019/5/30

#
1
2
3
4
5
6
7
protected void addedToWorld(World w)            //built-in method, no call needed
{
    while (isTouching(Asteroid.class))          //check if any overlap occurs
    {
        setLocation(Greenfoot.getRandomNumber(w.getWidth()), Greenfoot.getRandomNumber(w.getHeight()));     //random location for asteroids       
    }
}
I put this code in my asteroid class to prevent overlap, but I'm not sure what to state in the "addObject" line in the world class. Changing the location numbers in the addObject part determines how often the Java Space Heap error comes up. I put this code in my world constructor:
1
2
3
4
for(int i =0; i<=5;i++) {                       //spawning only 6 asteroids for testing
    Asteroid test = new Asteroid();
    addObject(test, 0, 0);
}
I will try resizing my world but this error is becoming more common. Thanks for your help.
danpost danpost

2019/5/30

#
An improvement would be the following for line 3 of the addedToWorld method:
1
while (getX() == 0 || isTouching(Asteroid.class))
This will cause all to be randomly set instead of one always spawning in the top-left corner.
Çðæyœn Çðæyœn

2019/5/31

#
I tried play testing my game and pressing the reset button every time my spaceship explodes (usually 3-5 seconds), but even in this case the Java Heap error comes up eventually. Could this error be avoided by reducing space, such as by removing asteroids once they are not needed or removing the explosion GIF after the explosion occurs once? Here is a link to a screen recording of my updated game, showing how the error comes up: https://drive.google.com/file/d/1B4aRuF0Ye8-Km0lRJjtGo3UQ3k_ceCWu/view
danpost danpost

2019/5/31

#
Çðæyœn wrote...
I tried play testing my game and pressing the reset button every time my spaceship explodes (usually 3-5 seconds), but even in this case the Java Heap error comes up eventually. Could this error be avoided by reducing space, such as by removing asteroids once they are not needed or removing the explosion GIF after the explosion occurs once?
Absolutely. Once an actor is not needed, it should be removed.
Çðæyœn Çðæyœn

2019/5/31

#
Just removed the GIF after one cycle, and this has made the memory error a rare occurrence (other than rapidly pressing the RESET button). Thank you for your help!
There are more replies on the next page.
1
2