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

2017/11/21

Changing hitbox

NielsV5B NielsV5B

2017/11/21

#
I'm trying to make a forcefield in my game which will destroy incoming Bullets and will stop incoming Enemies from walking. When the forcefield is spawned, it begins small, grows very fast, and then it's getting smaller again. Now there are 2 problems with the forcefield's hitbox - The hitbox is a square. - The hitbox doesn't grow/get smaller when the image does so. Here's the code of the forcefield-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
42
43
44
45
46
47
48
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
public class ForceField extends Actor
{
    private int afmetingen = 1;
    private int maxAfmetingen = 200;
    private int i = 0;
    private boolean scaledUp = false;
 
    protected void addedToWorld()
    {
        getImage().scale(maxAfmetingen, maxAfmetingen);
    }
 
    public void act()
    {
        imageChanger();
    }
     
    private void imageChanger()
    {
        if (scaledUp == false)
        {
            afmetingen = afmetingen + 10;
            setImage("Krachtveld2.png");
            getImage().scale(afmetingen, afmetingen);
            if ( afmetingen > 200 )
            {
                scaledUp = true;
            }
        }
        if (scaledUp == true)
        {
            if ( i == 10 )
            {
                setImage("Krachtveld2.png");
                getImage().scale(afmetingen, afmetingen);
                afmetingen--;
                i = 0;
            }
            if ( afmetingen <= 1 )
            {
                getWorld().removeObject(this);
            }
            i++;
        }
    }
}
And the code removing the bullet if it's touching the forcefield:
1
2
3
4
else if (getOneIntersectingObject(ForceField.class) != null && mySender != "Man")
            {
                hasToRemove = true;
            }
And if hasToRemove == true, it will remove itself. I've also tried to do it with the next statement: getObjectsInRange(afmetingen, Bullet.class) But the problem with this is that the bullets can be send by the Man or an Enemy, and the forcefield should only remove the ones which are coming from an Enemy. So I made the next method in the Bullet class:
1
2
3
4
public String getSender()
    {
        return mySender;
    }
And the next method in the Forcefield class:
1
2
3
4
5
6
7
8
9
10
private void removeIncomingBullets()
    {
        if (getObjectsInRange(afmetingen, Bullet.class) != null)
        {
            if (getObjectsInRange(afmetingen, Bullet.class).getSender() == "Enemy")
            {
                getWorld().removeObjects(getObjectsInRange(afmetingen, Bullet.class));
            }
        }
    }
But I can't call the public method getSender from the Bullet in the Forcefield. Did I make a mistake or are there other solutions to my problems?
danpost danpost

2017/11/21

#
NielsV5B wrote...
I'm trying to make a forcefield in my game which will destroy incoming Bullets and will stop incoming Enemies from walking. When the forcefield is spawned, it begins small, grows very fast, and then it's getting smaller again. Now there are 2 problems with the forcefield's hitbox - The hitbox is a square. - The hitbox doesn't grow/get smaller when the image does so.
Just from this, I can say that it will need to be the forcefield that determines intersection using 'getObjectsInRange'. A bullet of proper source can first check for an intersecting forcefield and, if one exists, have it (the forcefield) check to see if this bullet is in range. This will not only override the square hitbox, but also avoid the size issue as the range is given (not derived from the image0. A helpful method in the ForceField class might be:
1
2
3
4
public boolean isInRange(Actor actor)
{
    return getObjectsInRange(afmetingen, Actor.class).contains(actor);
}
In the Bullet class, when checking for a forcefield:
1
2
ForceField field = (ForceField)getOneIntersectingObject(ForceField.class);
if (field != null && field.isInRange(this)) hasToRemove = true;
NielsV5B NielsV5B

2017/11/26

#
Thanks, that's working. But could you tell me what exactly the .contains() does do?
danpost danpost

2017/11/26

#
The 'getObjectsInRange' method returns a List object, upon which the 'contains' method is called on. The 'contains' method just asks if a certain object is contained within the list (or, is 'actor' referenced by one of the elements of the list). So, when the bullet detects an intersecting force field, it then asks the force field if it detects that specific bullet (which is passed to it using 'this', setting it to 'actor') within a certain radius of its center. Reviewing API documentation of classes are a big help in both finding out what a method does as well as finding out what methods are available to execute on the objects of a class. See 'contains' documentation.
NielsV5B NielsV5B

2017/11/26

#
Thanks. I've found out the hitbox isn't working properly. It's because I am setting the dimensions of the forceField to 1,1 in the constructor, and now it only removes the bullet when it's in that exact location. Here's my code: ForceField code:
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
public class ForceField extends Movers
{
    private int dimensions = 1;
    private int maxDimensions;
    private int timer = 0;
    private int timerMax;
    private boolean scaledUp = false;
     
    public ForceField()
    {
        maxDimensions = 200;
        timerMax = 10; //every [timerMax] acts, it will scale down
        getImage().scale(1,1);
    }
 
    public void act()
    {
        imageChanger();
    }
     
    private void imageChanger()
    {
        if (scaledUp == false)
        {
            dimensions = dimensions + 10;
            setImage("Krachtveld2.png");
            getImage().scale(dimensions, dimensions);
            if ( dimensions > maxDimensions )
            {
                scaledUp = true;
            }
        }
        if (scaledUp == true)
        {
            if ( timer == 10 )
            {
                setImage("Krachtveld2.png");
                getImage().scale(dimensions, dimensions);
                dimensions--;
                timer = 0;
            }
            timer++;
            if ( dimensions <= 1 )
            {
                getWorld().removeObject(this);
            }
        }
    }
 
     
     
    /**
     * Methods for other classes:
     */
     
    public boolean isInRange(Actor actor)
    {
        return getObjectsInRange(dimensions, Actor.class).contains(actor);
    }
}
Bullet code:
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
public class Bullet extends Movers
{
    private int speed;
    private int destinationX;
    private int destinationY;
    private String myTarget;
    private String mySender;
     
    private boolean isTouchingBlock = false;
    private boolean hasToRemove = false;
     
    private int margin = 10;
    private boolean passedGoTo = false;
     
    public Bullet(int targetX, int targetY, String senderClass, String targetClass)
    {
        destinationX = targetX;
        destinationY = targetY;
        mySender = senderClass;
        myTarget = targetClass;
         
        setImage("Bullet" + senderClass + ".png");
        getImage().scale(25,5);
         
        speed = 3;
    }
     
    protected void addedToWorld(World MyWorld)
    {
        turnTowards(destinationX, destinationY);
    }
     
    public void act()
    {
        move(10);
        keepTurning();
        checkTouching();
    }
     
    private void checkTouching()
    {
        if (canGetWorldManEnemy())
        {
            ForceField field = (ForceField)getOneIntersectingObject(ForceField.class);
            if ( isTouching(Enemy.class) && myTarget == "Enemy" )
            {
                Enemy enemy = getWorld().getObjects(Enemy.class).get(0);
                enemy.hitEnemy();
                hasToRemove = true;
            }
            else if ( isTouching(Man.class) && myTarget == "Man" )
            {
                Man man = getWorld().getObjects(Man.class).get(0);
                man.hitMan();
                hasToRemove = true;
            }
            else if (getOneIntersectingObject(Block.class) != null || getOneIntersectingObject(Door.class) != null || isAtEdge() || isTouching(Bullet.class) || getOneIntersectingObject(Weapon.class) != null)
            {
                hasToRemove = true;
            }
            else if (isTouching(Bullet.class))
            {
                removeTouching(Bullet.class);
                hasToRemove = true;
            }
            else if (field != null && field.isInRange(this) && mySender != "Man")
            {
                hasToRemove = true;
            }
            else
            {
                hasToRemove = false;
            }
        }
        if (hasToRemove == true)
        {
            getWorld().removeObject(this);
        }
    }
     
     
     
    /**
     * Methods to make the bullet keep turning to the destination:
     */
     
    private void keepTurning()
    {
        if (isNearbyX() && isNearbyY())
        {
            passedGoTo = true;
        }
        if (passedGoTo == false)
        {
            turnTowards(destinationX, destinationY);
        }
    }
     
    public boolean isNearbyX()
    {
        if ( getX() < destinationX + margin && getX() > destinationX - margin )
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    public boolean isNearbyY()
    {
        if ( getY() < destinationY + margin && getY() > destinationY - margin )
        {
            return true;
        }
        else
        {
            return false;
        }
    }
     
     
     
    /**
     * Methods for other classes:
     */
     
    public String getSender()
    {
        return mySender;
    }
}
danpost danpost

2017/11/26

#
I guess you need another way to determine how 'field' on line 46 in the Bullet class is derived. Either by getting any ForceField object in the world or getting one within the maximum range (200, I believe) (using 'getNeighbours'' possibly??).
NielsV5B NielsV5B

2017/11/27

#
I've made the following code. First, it checks whether there is a ForceField in the range of 200 (which is the maximum dimension of the ForceField class), and if there is one, it gets the current dimensions of the focefield in range and checks whether the forcefield is within that range of the bullet. The dimensions in which the forcefield spawns, and which is automatically the hitbox is 1,1.
1
2
3
4
5
6
7
8
9
if (!getObjectsInRange(200, ForceField.class).isEmpty())
        {
            ForceField field = (ForceField)getObjectsInRange(200, ForceField.class);
            int distance = field.dimensions;
            if (!getObjectsInRange(distance, ForceField.class).isEmpty() && mySender != "Man")
            {
                hasToRemove = true;
            }
        }
But I constantly get the following error: java.lang.ClassCastException: java.util.ArrayList cannot be cast to ForceField at Bullet.checkTouching(Bullet.java:79) at Bullet.act(Bullet.java:39) at greenfoot.core.Simulation.actActor(Simulation.java:604) at greenfoot.core.Simulation.runOneLoop(Simulation.java:562) at greenfoot.core.Simulation.runContent(Simulation.java:221) at greenfoot.core.Simulation.run(Simulation.java:211) PS: the code is in the method checkTouching
danpost danpost

2017/11/27

#
You are missing the ''get(0)' at the end of line 3.
NielsV5B NielsV5B

2017/11/27

#
Thanks, that's working now!
You need to login to post a reply.