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

2017/2/22

How to send an actor to another actor

1
2
DPK DPK

2017/2/22

#
I'm making a Portal game and I couldn't figure out how to do what is titled. For example if the character touches Portal1, they're sent to the X and Y of Portal2.
danpost danpost

2017/2/22

#
The portals should each keep a reference to its counterpart. That is, a sending portal should "know" what its receiving portal is (or, where to send the actor). This can be done by using two constructors in your portal class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// instance field for paired Portal object
private Portal linkedPortal;
 
public Portal() {} // for creating the first of two linked portals
 
public Portal(Portal counterpart) // for creating the second of two linked portalss
{
    linkedPortal = counterpart;
    counterpart.linkedPortal = this;
}
 
public Portal getLinkedPortal()
{
    return linkedPortal;
}
Now, when adding objects to your world, you can create and link portals with code like this:
1
2
3
Portal portal = new Portal();
addObject(portal, 50, 50);
addObject(new Portal(portal), 550, 350);
Then, when an actor touches a portal, it can be transferred to that portal's counterpart. One issue will now be what will happen when it now touches the counterpart. We do not want the actor to bounce back and forth between the two portals. The actor will need to know whether the transfer can be made or not. So, we need a boolean field in the class of the actor to indicate this state:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/** in class of character */
// instance field for transfer flag
private boolean transferred;
 
// in act (or method called by act)
if (isTouching(Portal.class))
{
    if ( ! transferred ) // (read as 'if not transferred' --  same as ' if (transferred == false) '
    {
        Portal portal = ((Portal)getOneIntersectingObject(Portal.class)).getPairedPortal();
        setLocation(portal.getX(), portal.getY());
        transferred = true;
    }
}
else transferred = false;
Super_Hippo Super_Hippo

2017/2/22

#
I would probably do it like this: - have one portal class - when creating a portal, give each portal a reference to the other portal so that it can get the others x/y. - then, when the character is touching a portal, the portal let the character know where to go Nvm, someone was faster :)
DPK DPK

2017/2/23

#
Thanks a lot, although I'm receiving an error at setLocation(portal.getX(), portal.getY());. The error isn't syntax, but I get a nullPointerException error every time I touch a portal with the character.
Nosson1459 Nosson1459

2017/2/23

#
Show the code that has to do with the NullPointerException (Portal class at least).
DPK DPK

2017/2/23

#
This is the Portal class (Portal1)
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
private Portal1 linkedPortal;
    private boolean transferred;
    public void act()
    {
        shootPortal1();
        limit();
    }
     
    public Portal1()
    {
         
    }
     
    public Portal1(Portal1 counterpart)
    {
        linkedPortal = counterpart;
        counterpart.linkedPortal = this;
    }
     
    public Portal1 getLinkedPortal()
    {
        return linkedPortal;
    }
     
    private void limit()
    {
        int n = getWorld().numberOfObjects();
        if(n > 16)
        {
            getWorld().removeObject(this);
        }
    }
     
    public void shootPortal1()
    {
        Portal1 portal = new Portal1();
        MouseInfo mouse = Greenfoot.getMouseInfo();
        if(Greenfoot.mouseClicked(this))
        {
           getWorld().addObject(portal, Greenfoot.getMouseInfo().getX(), Greenfoot.getMouseInfo().getY());
           if (mouse.getButton() == 3)
            {
                getWorld().addObject(new Portal1(portal), Greenfoot.getMouseInfo().getX(), Greenfoot.getMouseInfo().getY());
            }
        }
    }
The error is in my character class (TestSubject) here:
1
2
3
4
5
6
7
8
9
10
if (isTouching(Portal1.class))
        {
            if ( ! transferred )
            {
                Portal1 portal = ((Portal1)getOneIntersectingObject(Portal1.class)).getLinkedPortal();
                setLocation(portal.getX(), portal.getY());
                transferred = true;
            }
        }
         else transferred = false;
Super_Hippo Super_Hippo

2017/2/23

#
I think the 'shootPortal' method should go into the user's class, so 'TestSubject' and not into the Portal class.
DPK DPK

2017/2/23

#
I've put the shootPortal method in the user's class, and I'm receiving the same error.
danpost danpost

2017/2/23

#
Your 'limit' method could possibly remove one of the paired portals. So at times, you will have one portal in the world without the other. What are your rules as far as having portals in this world?
Super_Hippo Super_Hippo

2017/2/23

#
The problem is that you add one Portal (without a linked portal) whenever you click on the player (after you moved the code now) and if the click was done with the right mouse button, you add another Portal at the same position and link both portals. If you only create one (with the left mouse button), 'getLinkedPortal' returns null when touching it and the 'getX' call gives you the error. I think that you don't want to create both portals at the same position. Also only execute lines 6 and 7 in the last code snippet if 'getLinkedPortal' did not return null.
DPK DPK

2017/2/23

#
danpost wrote...
Your 'limit' method could possibly remove one of the paired portals. So at times, you will have one portal in the world without the other. What are your rules as far as having portals in this world?
My rules are 2 portals is the limit, one spawned from left mouse click and the other from right mouse click.
DPK DPK

2017/2/23

#
So I attempted to separate the mouse clicks so that the portals won't spawn at the same position, and it did not work. I'm assuming you have yo use a different Greenfoot.mouseClicked().
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void shootPortal1()
    {
        Portal1 portal = new Portal1();
        MouseInfo mouse = Greenfoot.getMouseInfo();
        if(Greenfoot.mouseClicked(this))
        {
            if (mouse.getButton() == 1)
            {
                getWorld().addObject(portal, Greenfoot.getMouseInfo().getX(), Greenfoot.getMouseInfo().getY());
            }
        }
        if(Greenfoot.mouseClicked(this))
        {
            if (mouse.getButton() == 3)
            {
                getWorld().addObject(new Portal1(portal), Greenfoot.getMouseInfo().getX(), Greenfoot.getMouseInfo().getY());
            }
        }
    }
danpost danpost

2017/2/23

#
You should never create a portal without creating its counterpart. Then, when a click to add one occurs, just add the linkedPortal object into the world at the location of the mouse. You may need to ensure it is not in the world first. If it is, then, if desired, you can use 'setLocation' to move it to the location of the mouse or just ignore the click.
Super_Hippo Super_Hippo

2017/2/23

#
Another idea: I think I would place it into the world:
1
2
3
4
5
6
7
8
private Portal[] portals = {new Portal(0), new Portal(1)};
 
public void addPortal(int i, int x, int y)
{
    addObject(portals[i], x, y);
}
 
public Portal getPortal(int i) {return portals(i);}
1
2
3
4
5
6
7
8
9
10
private int index;
public Portal(int i)
{
    index = i;
}
 
public Portal getLinkedPortal()
{
    return ((MyWorld) getWorld()).getPortal((index+1)%2);
}
For the "shooting":
1
2
3
4
5
6
if (Greenfoot.mousePressed(null))
{
    MouseInfo me = Greenfoot.getMouseInfo();
    if (me.getButton() == 1) ((MyWorld) getWorld()).addPortal(0), me.getX(), me.getY());
    else if (me.getButton() == 3) ((MyWorld) getWorld()).addPortal(1), me.getX(), me.getY());
}
To move from one to the other:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Portal portal = (Portal) getOneIntersectingObject(Portal.class);
if (portal != null)
{
    if (!transferred)
    {
        Portal linked = portal.getLinkedPortal();
        if (linked.getWorld() != null)
        {
            setLocation(linked.getX(), linked.getY());
            transferred = true;
        }
    }
}
else transferred = false;
danpost danpost

2017/2/23

#
DPK wrote...
My rules are 2 portals is the limit, one spawned from left mouse click and the other from right mouse click.
Do not create and add portals from the Portal class. Create the portals in your world constructor and keep references to them in the World object:
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
// instance field in World subclass
private Portal portal;
 
// in World subclass constructor
portal = new Portal();
new Portal(portal);
 
// in 'act' method of World subclass
if (Greenoot.mouseClicked(null))
{
    MouseInfo mouse = Greenoot.getMouseInfo();
    if (mouse.getButton() == 1)
    {
        if (portal.getWorld() != this)
        {
            addObject(portal, mouse.getX(), mouse.getY());
        }
        else // (optional)
        {
            portal.setLocation(mouse.getX(), mouse.getY());
        } // (end optional)
    }
    if (mouse.getButton() == 3)
    {
        Portal p = portal.getLinkedPortal();
        if (p.getWorld() != this)
        {
            addObject(p, mouse.getX(), mouse.getY());
        }
        else // (optional)
        {
            p.setLocation(mouse.getX(), mouse.getY());
        } // (end optional)
    }
}
There are more replies on the next page.
1
2