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

2016/12/25

mousePressed(this) -- deselecting?

ZoeF ZoeF

2016/12/25

#
I am trying to make a visual change when a mousePressed is used on a object. this by itself is working fine but when i select something else it should be removed again. And that seems a diffrent kind of problem.
TowerRadius showRadius = new TowerRadius(this);
            if(Greenfoot.mousePressed(this) && selected == false)
            {
                selected = true;
                getWorld().addObject(showRadius, getX(), getY());
            }

            if(!Greenfoot.mousePressed(this))
            {
                getWorld().removeObject(showRadius);
                //selected = false;
            }
The towerRadius code is from someone else
import greenfoot.*;
import java.awt.Color;

/**
 * Displays the radius of a tower.
 * 
 * @author (Kevin Huber) 
 * @version (1.0)
 */
public class TowerRadius extends Actor
{
    public TowerRadius(Towers tower)
    {
        GreenfootImage im = new GreenfootImage((int) (tower.getRadius()*1.8), (int) (tower.getRadius()*1.8));
        setImage(im);
        
        // Fill the circle
        im.setColor(new Color (46, 46, 46, 180));
        im.fillOval(0, 0, (int) (tower.getRadius()*1.8), (int) (tower.getRadius()*1.8));
        
        setImage(im);
    }
}
danpost danpost

2016/12/25

#
You have it set up where EACH tower has its own selected state independent of what the state of other towers are. What you want is that only one of ALL the towers is to have a true selected state. An instance field is for EACH object of a class; a class field (one designated as 'static') is for ALL of the objects of the class. Obviously, then, a simple boolean type field will not be sufficient; but, you can have an object reference field to hold the selected object of the class:
// instead of 
private boolean selected = false; // or something like that

// you would have
private static Towers selected = null;
Then, on mouse press:
selected = this;
To deselect, instead of mouse press, which is only true at the instance the mouse button goes down (not while held down, which you have found out), just use mouse clicked (which is true the instance the mouse button goes up). I would suggest not using the TowerRadius class objects and just have two images for the towers -- one without and one with the radius. Then, you only need to change the image when needed. The code for that could look like this:
// with references to images
private GreenfootImage normImage; // set in constructor 
private GreenfootImage radImage; // created and set in constructor

// in act
setImage(selected == this ? radImage : normImage);
ZoeF ZoeF

2016/12/25

#
Ok i am at a loss here. I tried it several times and i do understand your logic but i just can't seem to get it to work properly. I tried setting the static value in my Towers class but ended up placing it in my Map class as i could then use it later on when working with upgrades for specific towers. But as i have boosts in the game wich in the end could mean i need to change the radius on a image i realy need to have the Radius code. I did however remove the class for that code. My code can be downloaded from https://www.dropbox.com/sh/8c29gqx2o734ng7/AABYi0HP3IPQqMQAIA4s4n3ya?dl=0 . When watching this code consider i am only programming for 3-4 months while taking a coarse. The issue curently is that the original image of the subclass gets changed by nothing :P and that i don't seem to be able to select things.
ZoeF ZoeF

2016/12/26

#
Ok after some more testing i came to the conclusion that the issue lies deeper then i tought. It has to do with the images loaded in in my subclasses cannon , turret , launcher. Now i have to rework a hole bunch to get it to work propperly. Or i have to find a way to call a method of the subclass without creating a new class.
danpost danpost

2016/12/26

#
ZoeF wrote...
I tried setting the static value in my Towers class but ended up placing it in my Map class as i could then use it later on when working with upgrades for specific towers.
If towers are the only thing to be selected, then thee Towers class IS the place for the static value.
But as i have boosts in the game wich in the end could mean i need to change the radius on a image i realy need to have the Radius code. I did however remove the class for that code.
Changing the radius is not an issue. You can have a method to change the radius that creates a new 'radImage' object. Oh, and while we are discussing images -- you should be setting them in the class constructors (particularly in the Text, MapPiece and Place classes) -- not in the 'act' method.
My code can be downloaded from https://www.dropbox.com/sh/8c29gqx2o734ng7/AABYi0HP3IPQqMQAIA4s4n3ya?dl=0 .
I took a look. Too many unnecessary fields -- some duplicate ones as well. And, they are all 'private'. They, as well as getter and setter methods, could easily be reduced in number to simplify your code. Most of your subclassing looks good. However, I am not sure if I would have had the Boost class extend the Tower class (but, I would have to experiment to see what might work best).
The issue curently is that the original image of the subclass gets changed by nothing :P and that i don't seem to be able to select things.
This may be due to the back and forth between the Map class 'selected' field and the Towers class 'selected field. I will investigate.
danpost danpost

2016/12/26

#
ZoeF wrote...
Or i have to find a way to call a method of the subclass without creating a new class.
You can declare the method in the superclass first, having the subclass override it. Then you can call that method from the superclass. This is precisely what greenfoot does with the 'act' method of the Actor class and why it is able to call it in the subclass even though it had no idea what you were going to name any of its subclasses. The Actor class has this:
public void act() { }
and calls it from some other private method, using simply:
actor.act();
where 'actor' refers to one of the actors in your scenario. If you placed some code within the act method (overriding the 'act' method of the Actor class) for that actor, it will execute.
ZoeF ZoeF

2016/12/26

#
danpost wrote...
I took a look. Too many unnecessary fields -- some duplicate ones as well. And, they are all 'private'. They, as well as getter and setter methods, could easily be reduced in number to simplify your code.
Yeah i know but our instructor told us to never make a field public and only make methods public as to secure the variables stored in there. The duplicates might indeed be a issue, but i clean up the code once in a while and find those duplicates. But for the moment i am strugeling with this issue. Tnx for the comments i wil be taking them to hearth and work towards beatifieing the code.
danpost danpost

2016/12/26

#
ZoeF wrote...
our instructor told us to never make a field public and only make methods public as to secure the variables stored in there.
That is good advise, in general terms. That does not, however, secure the variables stored when you have public methods that allow changing of their values from anywhere (public 'setter' methods).
The duplicates might indeed be a issue, but i clean up the code once in a while and find those duplicates. But for the moment i am strugeling with this issue.
"this issue" being getting the selection of a Towers object. Keep it simple. One field for the selected object in the class whose objects will be referenced in the field. You will not be getting a selected Map object; but, a selected Towers object. Because the field will be 'static', your getter/setter methods can also be static:
// with class field (in Towers class)
private static Towers selected = null;

// you can have these methods
public static void setSelected(Towers tower)
{
    selected = tower;
}

public static Towers getSelected()
{
    return selected;
}
Any class at any time can then set or get the selected tower using:
// to get the selected tower from any class
Towers selectedTower = Towers.getSelected();

// to set the selected tower from any class (referenced by 'tower')
Towers.setSelected(tower);

// to clear the selection from any class
Towers.setSelected(null);
ZoeF ZoeF

2016/12/26

#
Figured out a solution to my issue.
private void amSelected()
    {
        Map map = (Map) getWorld();
        selected = map.getSelected();

        if(Greenfoot.mousePressed(this))
        {
            map.setSelected(this);
        }

        if(selected == this )
        {
            if(towerRadPresent == false)
            {
                towerRadius = new TowerRadius(this);
                getWorld().addObject(towerRadius, getX(), getY());
                towerRadPresent = true;
            }
        }
        else
        {
            getWorld().removeObject(towerRadius);
            towerRadPresent = false;
        }
    }
danpost danpost

2016/12/26

#
Obviously, there will be a bit more to the 'setSelected' methods than just setting the reference. It would be more like this:
public static void setSelected(Towers tower)
{
    if (selected != null) selected.deselect();
    selected = tower;
    if (tower != null) tower.select();
}
Now, you can put methods in the Towers class to add and remove the TowerRadius objects:
private void deselect()
{
    getWorld().removeObject(towerRadius);
}

private void select()
{
    getWorld().addObject(towerRadius = new TowerRadius(this), getX(), getY());
}
ZoeF ZoeF

2016/12/27

#
I did the following in my Map.class extends World No need for the static value as there is only one instance of the Map running at the moment. If need be i can change it to a static value.
public class Map extends World
{
private Towers selected;

public Map()
    {
        selected = null;
    }
/**
     * Return het geselecteerde object
     * 
     * @return waarde Towers selected
     */
    public Towers getSelected()
    {
        return selected;
    }

    /**
     * Zet de waarde selected naar de huidige selectie
     */
    public void setSelected(Towers tower)
    {
        selected = tower;
    }

And in my Towers.class extends Actor
public abstract class Towers extends Actor
{
    private Towers selected;

    public Towers()
    {
        selected = null;
    {

private void amSelected()
    {
        Map map = (Map) getWorld();
        selected = map.getSelected();

        if(Greenfoot.mousePressed(this))
        {
            map.setSelected(this);
        }

        if(selected == this )
        {
            if(towerRadPresent == false)
            {
                towerRadius = new TowerRadius(this);
                getWorld().addObject(towerRadius, getX(), getY());
                towerRadPresent = true;
            }
        }
        else
        {
            getWorld().removeObject(towerRadius);
            towerRadPresent = false;
        }
    }
And then i use the TowerRadius.class extends Actor
public class TowerRadius extends Actor
{
    /**
     * Maak een cirkel met een straal van 180*1.8 en zet deze in een int value
     */
    public TowerRadius(Towers tower)
    {
        GreenfootImage im = new GreenfootImage((int) (tower.getRadius()*1.8), (int) (tower.getRadius()*1.8));
        setImage(im);
        
        // Fill the circle
        im.setColor(new Color (46, 46, 46, 75));
        im.fillOval(0, 0, (int) (tower.getRadius()*1.8), (int) (tower.getRadius()*1.8));
        
        setImage(im);
    }
}
This seems by far the best way.
You need to login to post a reply.