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

2020/8/15

A method that is called whenever an actor get's removed

RcCookie RcCookie

2020/8/15

#
I am working on custom colliders for actors, but they need to be seperate objetcs. So, if the actor gets removed, the collider should do so, too. Unfortunatly there is on "removeFromWorld(World w)" method like there is a "addedToWorld(World w)" method that would be executed whenever an object is removed. Does anyone have an idea how to fix this?
danpost danpost

2020/8/15

#
RcCookie wrote...
I am working on custom colliders for actors, but they need to be seperate objetcs. So, if the actor gets removed, the collider should do so, too. Unfortunatly there is on "removeFromWorld(World w)" method like there is a "addedToWorld(World w)" method that would be executed whenever an object is removed. Does anyone have an idea how to fix this?
Need to see how actor and collider are coded. Post entire class codes.
RcCookie RcCookie

2020/8/15

#
If you really want:
import greenfoot.*;
import packages.twoD.Vector;
import packages.twoD.Point;
import packages.tools.Time;
public abstract class AdvancedActor extends Actor{
    private Transform transform;
    private Collider collider;
    
    protected final Time time;
    
    private boolean defaultCollider;
    
    public AdvancedActor(){
        this(null);
    }
    public AdvancedActor(Collider collider){
        time = new Time();
        transform = new Transform(0);
        setCollider(collider);
    }
    @Override
    protected final void addedToWorld(World w){
        transform.location = getLocation();
        w.addObject(collider, getX(), getY());
        addedIntoWorld(w);
    }
        
    public void setCollider(Collider collider){
        this.collider = collider;
        useDefaultCollider(collider == null);
        this.collider.host = this;
    }
    public void useDefaultCollider(boolean defaultCollider){
        this.defaultCollider = defaultCollider;
        if(defaultCollider) this.collider = new Collider(this);
    }
    
    @Override
    public void setImage(GreenfootImage image){
        super.setImage(image);
        if(defaultCollider || collider == null) collider = new Collider(this);
    }
    
    
    public final void act(){
        internalAct();
        earlyUpdate();
        update();
        lateUpdate();
    }
    
    protected void addedIntoWorld(World w){}
    
    public void earlyUpdate(){}
    public void update(){}
    public void lateUpdate(){}
    
    protected void onPress(){}
    protected void onRelease(){}
    
    protected boolean onStep(int stepNumber){return true;}
    
    private void internalAct(){
        time.act();
        
        if(Greenfoot.mousePressed(getCollider())) onPress();
        else if(Greenfoot.mouseClicked(collider)) onRelease();
    }
    
    
    //colliding
    @Override
    protected <A> java.util.List<A> getIntersectingObjects(Class<A> cls){
        return getCollider().getIntersectingObjects(cls);
    }
    @Override
    protected Actor getOneIntersectingObject(Class<?> cls){
        return getCollider().getOneIntersectingObject(cls);
    }
    @Override
    protected boolean isTouching(Class<?> cls){
        return getCollider().isTouching(cls);
    }
    @Override
    protected void removeTouching(Class<?> cls){
        getCollider().removeTouching(cls);
    }
    
    
    
    
    
    
    
    
    
    //fixed movement
    
    public void fixedMove(Vector movement){
        move(movement.scale(time.deltaTime()));
    }
    public void fixedMove(double distance){
        fixedMove(new Vector(transform.rotation, distance, true));
    }
    
    public void fixedMoveX(double distance){
        fixedMove(new Vector(0, distance, true));
    }
    public void fixedMoveY(double distance){
        fixedMove(new Vector(90, distance, true));
    }
    
    public boolean fixedMoveInSteps(Vector movement, double stepSize){
        return moveInSteps(movement.scale(time.deltaTime()), stepSize);
    }
    public boolean fixedMoveInSteps(double distance, double stepSize){
        return fixedMoveInSteps(new Vector(transform.rotation, distance, true), stepSize);
    }
    
    public void fixedTurn(double angle){
        turn(angle * time.deltaTime());
    }
    
    
    
    
    
    
    //smooth movement
    
    public void move(Vector movement){
        setLocation(transform.location.add(movement));
    }
    public void move(double distance){
        move(new Vector(transform.rotation, distance, true));
    }
    @Override
    public void move(int distance){
        move((double)distance);
    }
    
    public void moveX(double distance){
        move(new Vector(0, distance, true));
    }
    public void moveY(double distance){
        move(new Vector(90, distance, true));
    }
    
    public boolean moveInSteps(Vector movement, double stepSize){
        for(double i=0; i<movement.abs()-stepSize; i+= stepSize){
            move(movement.normalized().scale(stepSize));
            if(!onStep((int)(i / stepSize))) return false;
        }
        move(movement.normalized().scale(movement.abs() % stepSize));
        if(!onStep((int)(movement.abs() / stepSize))) return false;
        return true;
    }
    public boolean moveInSteps(double distance, double stepSize){
        return moveInSteps(new Vector(transform.rotation, distance, true), stepSize);
    }
    
    
    public void setX(double x){
        setLocation(new Point(x, transform.location.Y));
    }
    public void setY(double y){
        setLocation(new Point(transform.location.X, y));
    }
    
    @Override
    public void setLocation(int x, int y){
        setLocation((double)x, (double)y);
    }
    public void setLocation(double x, double y){
        setLocation(new Point(x, y));
    }
    public void setLocation(Vector location){
        setLocation(location.getPoint());
    }
    public void setLocation(Point location){
        transform.location = location;
        updateTransform();
    }
    private void updateTransform(){
        super.setLocation((int)(transform.location.X + 0.5), (int)(transform.location.Y + 0.5));
        getCollider().setLocation((int)(transform.location.X + 0.5), (int)(transform.location.Y + 0.5));
        super.setRotation((int)(transform.rotation + 0.5));
        getCollider().setRotation((int)(transform.rotation + 0.5));
    }
    
    
    @Override
    public void setRotation(int angle){
        setRotation((double)angle);
    }
    public void setRotation(double angle){
        transform.rotation = angle;
        updateTransform();
    }
    
    @Override
    public void turn(int angle){
        turn((double)angle);
    }
    public void turn(double angle){
        setRotation(transform.rotation + angle);
    }
    
    
    
    @Override
    public int getX(){
        return (int)X();
    }
    @Override
    public int getY(){
        return (int)Y();
    }
    public double X(){
        return transform.location.X;
    }
    public double Y(){
        return transform.location.Y;
    }
    public Point getLocation(){
        return new Point(transform.location);
    }
    public Vector locationVector(){
        return transform.location.toVector();
    }
    
    @Override
    public int getRotation(){
        return (int)getAngle();
    }
    public double getAngle(){
        return transform.rotation;
    }
    
    public Transform getTransform(){
        return new Transform(transform);
    }
    
    public Collider getCollider(){
        if(collider == null) setCollider(null);
        if(collider.getWorld() != getWorld()){
            if(collider.getWorld() != null)
                collider.getWorld().removeObject(collider);
            if(getWorld() != null)
                getWorld().addObject(collider, getX(), getY());
        }
        return collider;
    }
}
And the collider...
import greenfoot.*;
import packages.twoD.Vector;
public class Collider extends Actor{
    public Actor host;
    
    public final Vector offset;
    public final int rotationOffset;
    
    private boolean debug = false;
    
    public Collider(Actor host, int width, int height, Vector offset, int rotationOffset){
        this.host = host;
        this.offset = offset;
        this.rotationOffset = rotationOffset;
        setImage(new GreenfootImage(width, height));
    }
    public Collider(int width, int height, Vector offset, int rotationOffset){
        this(null, width, height, offset, rotationOffset);
    }
    public Collider(Actor host){
        this(host, host.getImage().getWidth(), host.getImage().getHeight(), new Vector(), 0);
    }
    protected void addedToWorld(World w){
        if(host != null && host.getWorld() == w)
            setRotation(host.getRotation());
        else setRotation(0);
    }
    
    public void setImage(GreenfootImage image){
        super.setImage(image);
        
        //debug
        
        if(debug){
            image.setColor(new Color(255, 0, 0, 100));
            image.fill();
        }
    }
    
    public void setBounds(int width, int height){
        setImage(new GreenfootImage(width, height));
    }
    
    public Actor getOneIntersectingObject(Class<?> cls){
        try{
            return (Actor)getIntersectingObjects(cls).get(0);
        }catch(IndexOutOfBoundsException e){
            return(null);
        }
    }
    public <A> java.util.List<A> getIntersectingObjects(Class<A> cls){
        java.util.List<A> intersecting = super.getIntersectingObjects(cls);
        intersecting.remove(host);
        return intersecting;
    }
    public boolean isTouching(Class<?> cls){
        return super.isTouching(cls);
    }
    public void removeTouching(Class<?> cls){
        super.removeTouching(cls);
    }
    public boolean intersects(Actor a){
        return super.intersects(a);
    }
    
    @Override
    public void setLocation(int x, int y){
        Vector angularOffset = new Vector(
            getRotation() - rotationOffset + offset.getAngle(),
            offset.abs(),
            true
        );
        super.setLocation(x + (int)angularOffset.getX(), y + (int)angularOffset.getY());
    }
    
    @Override
    public int getX(){
        Vector angularOffset = new Vector(
            getRotation() - rotationOffset + offset.getAngle(),
            offset.abs(),
            true
        );
        return super.getX() - (int)angularOffset.getX();
    }
    @Override
    public int getY(){
        Vector angularOffset = new Vector(
            getRotation() - rotationOffset + offset.getAngle(),
            offset.abs(),
            true
        );
        return super.getY() - (int)angularOffset.getY();
    }
    
    @Override
    public void setRotation(int angle){
        int x, y;
        try{
            x = getX();
            y = getY();
            super.setRotation(angle + rotationOffset);
            setLocation(x, y);
        }catch(IllegalStateException e){
            super.setRotation(angle + rotationOffset);
        }
    }
    @Override
    public int getRotation(){
        return super.getRotation() - rotationOffset;
    }
    @Override
    public void turn(int angle){
        setRotation(getRotation() + angle);
    }
    
    
    
    public void debug(boolean state){
        debug = state;
        setImage(getImage());
    }
}
Right now I am using a workaround where the collider is removed once you try to use it, but without doing so it is giong to stay in the world
RcCookie RcCookie

2020/8/15

#
I guess lines 97 until 242 are kinda irrelevant for this
danpost danpost

2020/8/15

#
In world class, you could override removeObject:
@override
public void removeObject(Actor a)
{
    if (a instanceof AdvancedActor && a.getCollider() != null)
    {
        removeObject(a.getCollider());
    }
    super.removeObject(a);
}
RcCookie RcCookie

2020/8/15

#
Yeah, but I'd like to have the AdvancedActor and the collider be like a standalone, without having to edit the world
danpost danpost

2020/8/15

#
RcCookie wrote...
Yeah, but I'd like to have the AdvancedActor and the collider be like a standalone, without having to edit the world
Okay. How about putting the following in the Collider class:
public void act()
{
    if (host.getWorld() == null) getWorld().removeObject(this);
}
You need to login to post a reply.