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

2023/1/12

Getting Neighbours with Certain Traits?

Foofoo99 Foofoo99

2023/1/12

#

My Problem

I am attempting to recreate the board game "Stratego" but I am having trouble getting the available spots for each piece to show up. So far I have pieces on teams that take turns moving, and after the pieces move they snap to the spot and it becomes the other teams turn. I would like to make it so that when you are holding a piece and getting ready to drop it, only certain spots are visible. The criteria for these spots to be visible are:
  • The spot does not currently have a piece on it.
  • The spot is one "space" on the board away from the currently moving piece's original location. (not diagonal)

My Code

Code for the spots that the pieces snap to
private GreenfootImage invisible = new GreenfootImage("OneWhitePixel.png");
    private GreenfootImage visible = new GreenfootImage("Spot.png");
    private int touching;
    
    /**
     * Act - do whatever the AvailableSpot wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        checkTouching();
        checkInvisible();
    }
    
    public void checkTouching()
    {
        if(isTouching(RedPiece.class))
        {
            touching = 1;
        }
        else if(isTouching(BluePiece.class))
        {
            touching = 2;
        }
        else
        {
            touching = 0;
        }
    }
    
    public void checkInvisible()
    {
        if(PieceMover.getTurn() && PieceMover.getPieceColor() && touching == 1)
        {
            getNeighbours(30, false, AvailableSpot.class).get(0).setImage(visible);
        }
    }
The Piece Mover Class
private static boolean redTurn = true;
    private static boolean pickedRedPiece;
    
    public PieceMover()
    {
        
    }
    
    /**
     * Act - do whatever the PieceMover wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        decideToDrag();
    }
    
    public void decideToDrag()
    {
        if(this instanceof RedPiece && redTurn)
        {
            dragPiece();
            pickedRedPiece = true;
        }
        if(this instanceof BluePiece && !redTurn)
        {
            dragPiece();
            pickedRedPiece = false;
        }
    }
    
    public void dragPiece()
    {
        if(Greenfoot.mouseDragged(this))
        {
            MouseInfo mouse = Greenfoot.getMouseInfo();
            setLocation(mouse.getX(), mouse.getY());
        }
        if(Greenfoot.mouseDragEnded(this))
        {
            Actor choice = getOneIntersectingObject(AvailableSpot.class);
            if(choice != null)
            {
                setLocation(choice.getX(), choice.getY());
                redTurn = !redTurn;
            }
        }
    }
    
    public static boolean getPieceColor()
    {
        return pickedRedPiece;
    }
    
    public static boolean getTurn()
    {
        return redTurn;
    }
All help is appreciated.
danpost danpost

2023/1/13

#
Foofoo99 wrote...
I am attempting to recreate the board game "Stratego" but I am having trouble getting the available spots for each piece to show up. So far I have pieces on teams that take turns moving, and after the pieces move they snap to the spot and it becomes the other teams turn. I would like to make it so that when you are holding a piece and getting ready to drop it, only certain spots are visible. The criteria for these spots to be visible are:
  • The spot does not currently have a piece on it.
  • The spot is one "space" on the board away from the currently moving piece's original location. (not diagonal)
<< Code Omitted >>
Line 35 of the AvailableSpot class only deals with one spot to make visible. You need to loop through all the neighbors in the list and make all of them visible:
for (Object obj : getNeighbours(30, false, AvailableSpot.class))
{
    ((Actor)obj).setImage(visible);
}
To add the other restraint, you might try:
for (Object obj : getNeighbours(30, false, AvailableSpot.class))
{
    AvailableSpot spot = (AvailableSpot)obj;
    if (spot.touching == 0) spot.setImage(visible);
}
But you will still need a way to have them become invisible once the piece has moved.
danpost danpost

2023/1/13

#
There may be other problems with the code provided by you. I am particularly confused about line 33 in the AvailableSpot class. The conditions given seem somehow not to fit what you are looking for. Somewhere you need to track the dragging status and retain in a field which piece is being dragged, if any. Well, the field can give the dragging status if you use null when no piece is being dragged. The AvailableSpot class can then use that to determine if they should make themselves visible or not (allowing them to become invisible again, when needed).
Foofoo99 Foofoo99

2023/1/15

#
danpost wrote...
To add the other restraint, you might try:
for (Object obj : getNeighbours(30, false, AvailableSpot.class))
{
    AvailableSpot spot = (AvailableSpot)obj;
    if (spot.touching == 0) spot.setImage(visible);
}
But you will still need a way to have them become invisible once the piece has moved.
I agree with all of this. I tried replacing line 35 in the AvailableSpot class with what you provided and it worked. Also,
danpost wrote...
I am particularly confused about line 33 in the AvailableSpot class.
I understand the confusion here. It is quite redundant and I should fix that up. However, I am confused about how I could possibly keep a state (like dragging) stored in a field, as well as knowing which piece is being dragged. Because I only have one drag method in one class, I don't see how I could differentiate which piece is being dragged without making two separate methods for each color being dragged.
danpost danpost

2023/1/16

#
Foofoo99 wrote...
I am confused about how I could possibly keep a state (like dragging) stored in a field, as well as knowing which piece is being dragged. Because I only have one drag method in one class, I don't see how I could differentiate which piece is being dragged without making two separate methods for each color being dragged.
Something like this (untested) might work:
private static PieceMover mouseActor;
private static int fromX, fromY;

public void act()
{
    drag();
}

public void drag()
{
    if (mouseActor == null && (redTurn == (this instanceof RedPiece)) && Geenfoot.mousePressed(this))
    {
        mouseActor = this;
        fromX = getX();
        fromY = getY();
    }
    if (this = mouseActor && Greenfoot.mouseDragged(this))
    {
        MouseInfo mi = Greenfoot.getMouseInfo();
        setLocation(mi.getX(), mi.getY());
    }
    if (this = mouseActor && Greenfoot.mouseClicked(null)
    {
        Actor spot = getOneIntersectingObject(AvailableSpot.class);
        if (spot == null) setLocation(fromX, fromY);
        else setLocation (spot.getX(), spot.getY());
        mouseActor = null;
    }
}
Foofoo99 Foofoo99

2023/1/16

#
Thank you danpost, I am so close to getting this to work. The only issue I have now which I cannot figure out is that when I drag a red piece, the available spots only show up if they are beneath or to the left of the spot and the blue pieces seem to trigger spots without a pattern. (I would show images but I don't know where to upload them to) I updated some code in the AvailableSpot and PieceMover class, respectively:
public void checkInvisible()
    {
        if(PieceMover.getTurn() && touching == 1 || !PieceMover.getTurn() && touching == 2)
        {
            for(Object obj : getNeighbours(30, false, AvailableSpot.class))
            {
                AvailableSpot spot = (AvailableSpot)obj;
                if(spot.touching == 0)
                {
                    spot.setImage(visible);
                }
            }
        }
        else
        {
            setImage(invisible);
        }
    }
private static boolean redTurn = true;
    private static PieceMover mouseActor;
    private static int fromX, fromY;
    
    /**
     * Act - do whatever the PieceMover wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        dragPiece();
    }
    
    public static boolean getTurn()
    {
        return redTurn;
    }
 
    public void dragPiece()
    {
        if(mouseActor == null && Greenfoot.mousePressed(this))
        {
            if(redTurn && this instanceof RedPiece || !redTurn && this instanceof BluePiece)
            {
                mouseActor = this;
                fromX = getX();
                fromY = getY();
            }
        }
        if(this == mouseActor && Greenfoot.mouseDragged(this))
        {
            MouseInfo mi = Greenfoot.getMouseInfo();
            setLocation(mi.getX(), mi.getY());
        }
        if(this == mouseActor && Greenfoot.mouseClicked(null))
        {
            Actor spot = getOneIntersectingObject(AvailableSpot.class);
            if(spot == null)
            {
                setLocation(fromX, fromY);
            }
            else
            {
                setLocation (spot.getX(), spot.getY());
                mouseActor = null;
                redTurn = !redTurn;
            }
        }
    }
I apologize for bothering you so much, I am not an experienced programmer yet but you are helping me out a lot here.
danpost danpost

2023/1/18

#
Foofoo99 wrote...
The only issue I have now which I cannot figure out is that when I drag a red piece, the available spots only show up if they are beneath or to the left of the spot and the blue pieces seem to trigger spots without a pattern. (I would show images but I don't know where to upload them to) << Code Omitted >>
I think all you need to do is to make line 2 in PieceMover class public and then have the AvailableSpot objects control their own state with:
public void act()
{
    boolean touching = isTouching(PieceMover.class);
    if (touching)
    {
        if (getImage() == visible)
        {
            setImage(invisible);
        }
        return;
    }
    if (getImage() == invisible && getNeighbors(30, false, PieceMover.class).contains(PieceMover.mouseActor))
    {
        setImage(visible);
    }
    else if (getImage() == visible && PieceMover.mouseActor == null)
    {
        setImage(invisible);
    }
}
Foofoo99 Foofoo99

2023/1/19

#
Thank you so so much danpost! You have worked wonders in the progression of my remake of Stratego and I wish you a good night. I will try to let you know when the game is done.
You need to login to post a reply.