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

2013/1/31

Getting location of an actor from an actor

1
2
3
student101 student101

2013/1/31

#
I've been trying to get an actor of mine to get the location of another actor. I've attempted to use the getX() and getY() commands but it hasn't been working. I read somewhere that first the the actor that I want the location of has to be initialised, but I don't know what that means exactly. This is the code that I have so far:
public class FalsePopup extends BattleArrow
{
    /**
     * Act - do whatever the FalsePopup wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        setImage(new GreenfootImage("FALSE!", 35, Color.WHITE, Color.BLACK));
        setTransparency();
        
        }
     public void setTransparency()
     {
        getImage().setTransparency(0);   
     }
    public void setTransparencyCheck()
    {
        if (BattleArrow.getX()==325 && BattleArrow.getY()==335 && "enter".equals(Greenfoot.getKey()))
        {
            getImage().setTransparency(0); //I'm trying to set the text to be invisible if the above condition is met
            Wait for a few seconds //Still trying to work out this part of the code
        }
    }
}
danpost danpost

2013/1/31

#
On line 19, you are trying to get the location of a Class name, not an actor. If you want to get a BattleArrow object from within the world, use:
if(!getWorld().getObjects(BattleArrow.class).isEmpty())
{
    Actor arrow = getWorld().getObjects(BattleArrow.class).get(0);
    if (arrow.getX()==325 && arrow.getY()==335 &&
        "enter".equals(Greenfoot.getKey()))
    {
        setTransparency();
    }
}
Remove the outer 'if' block if there is always a BattleArrow object in the world. To wait for a few seconds, you will need to add a (int) counter to the class. When made transparent, set the counter to 180 or so. In the act method, you will need the following:
if (counter>0)
{
    counter--;
    if(counter==0) getImage().setTransparency(255);
}
This could also be written as:
if(counter>0) if(--counter==0) getImage().setTransparency(255);
I guess it could also be written as:
if(counter>0 && --counter==0) getImage().setTransparency(255);
student101 student101

2013/1/31

#
Thank you for your prompt replies danpost. I've been trying to implement your code into mine and it keeps saying that it's an incompatible type in the 'Actor arrow = getWorld().getObjects(BattleArrow.class).get(0);' part of the code.
import greenfoot.*;
import java.awt.Color;   // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class FalsePopup here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class FalsePopup extends BattleArrow
{
    /**
     * Act - do whatever the FalsePopup wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        int counter = 180;
        setImage(new GreenfootImage("FALSE!", 35, Color.WHITE, Color.BLACK));
        setTransparency();
        if (counter>0)  
        {  
            counter--;  
            if(counter==0) getImage().setTransparency(0);  
        }  

        
        }
     public void setTransparency()
     {
        getImage().setTransparency(0);   
     }
    public void setTransparencyCheck()
    {
        
        
            Actor arrow = getWorld().getObjects(BattleArrow.class).get(0);
            if (arrow.getX()==325 && arrow.getY()==335 && "enter".equals(Greenfoot.getKey()))
            {  
                setTransparency(255);
                
            }
        
    }
}
   
danpost danpost

2013/1/31

#
Sorry, forgot to cast the return. Change line 37 to:
Actor arrow = (Actor)getWorld().getObjects(BattleArrow.class).get(0);
student101 student101

2013/1/31

#
Thanks danpost, it's working! But the 'false' text only flashes on the screen for a split second. I've set the counter value to 180, but what units is that in? I'd like the text to show up on the screen for 2-3 seconds before disappearing.
danpost danpost

2013/1/31

#
That value should be sufficient, provided you do not have your speed set way above average (around the middle of the scenario speed slidebar). The units is in frames (or, it counts act cycles). At average speed, 60 cycles is approximately one second. The faster you scenario is running, the higher that number has to be (and vise versa).
student101 student101

2013/1/31

#
The speed slider was a little bit past the middle, but even when I set it at its default speed the text only flashed on the screen. I even made the counter to be at a ridiculously high value like 5000 and it still only flashed on the screen. Here's my code, maybe I did something wrong at some point:
import greenfoot.*;
import java.awt.Color;   // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class FalsePopup here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class FalsePopup extends BattleArrow
{
    /**
     * Act - do whatever the FalsePopup wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        
        setImage(new GreenfootImage("FALSE!", 35, Color.WHITE, Color.BLACK));
        setTransparency();
        setTransparencyCheck();
                
        }
     public void setTransparency()
     {
        getImage().setTransparency(0);   
     }
      
    public void setTransparencyCheck()
    {
        
        
            Actor arrow = (Actor)getWorld().getObjects(BattleArrow.class).get(0); 
            if (arrow.getX()==325 && arrow.getY()==335 && "enter".equals(Greenfoot.getKey()))
            {  
                int counter = 5000;
                getImage().setTransparency(255);
                if (counter>0)  
                {  
                    counter--;  
                    if(counter==0) getImage().setTransparency(0); 
              
           }
        
    }
}
}
   
danpost danpost

2013/1/31

#
The simplest way is usually the best way.
import greenfoot.*;
import java.awt.Color;

public class FalsePopup extends BattleArrow
{
    int counter; // this variable persists as long as the object exists

    public FalsePopup()
    { // initial setup of object goes here
        setImage(new GreenfootImage("FALSE!", 35, Color.WHITE, Color.BLACK));
        getImage().setTransparency(0);
    }

    public void act() 
    { // run the counter and check for start
        if (counter>0)  
        {  
            counter--;  
            if(counter==0) getImage().setTransparency(0); 
            return;
        }
        Actor arrow = (Actor)getWorld().getObjects(BattleArrow.class).get(0); 
        if (arrow.getX()==325 && arrow.getY()==335 && "enter".equals(Greenfoot.getKey()))
        {  
            getImage().setTransparency(255);
            counter = 180;
        }
    }
}
student101 student101

2013/2/1

#
Thanks danpost! It worked.
student101 student101

2013/2/1

#
I'm trying to create a conditional statement where the actor would check if it has been in a battle or not (the value 1 would mean it has, 0 would mean it hasn't) and also check the world it is in. If the conditions are met then it would set the location of actor where the player last left it, since the player was transported to another world prior. I've been trying to implement the conditional in the 'CheckCollision' method. The name of the world that I want the actor to check is whether it is in 'GameWorld'
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)



/**
 * Write a description of class Mouse here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Mouse extends Actor
{
    /**
     * Act - do whatever the Mouse wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
  
    
    public void act() 
    {
        checkKeys();
        CheckCollision();   
       
    }  
    private void checkKeys()
    { 
         if (Greenfoot.isKeyDown("left"))
           {setImage("mouse-flipped.jpg");     
           moveLeft();
        }
         if (Greenfoot.isKeyDown("right"))
         {   setImage("mouse.png");
             moveRight();
        }
        if (Greenfoot.isKeyDown("up"))
            moveUp();
        
        if (Greenfoot.isKeyDown("down"))
            moveDown();
    }
    public void moveLeft()
    {           
           setLocation(getX()-1, getY());
        }
    public void moveRight()
    {              
      setLocation(getX()+1, getY()); 
            }
    public void moveUp()
    {
        setLocation(getX(), getY()-1);
    }
    public void moveDown()
    {
        setLocation(getX(), getY()+1);
    }
    public void CheckCollision()
    {
        Actor snake = getOneObjectAtOffset(0, 0, Snake.class);
        if (snake != null)
        {
            int battle = 1;
            Greenfoot.setWorld(new BattleWorld());
            World world = getWorld();
            Actor mouse = (Actor)getWorld().getObjects(Mouse.class).get(0);
            if (battle == 1 && world == GameWorld)
            {
                Actor snake = getOneObjectAtOffset(391, 209), Snake.class);
                world.removeObject(snake);
                mouse.setLocation(391,209);
            }
        }
        
        
                       
      }
         
        
    }
      


danpost danpost

2013/2/1

#
Line 63 creates a new world (and after the execution of the current act cycle will become the current world). Line 64 returns the world in with the actor is currently in (not the new world yet). Line 65 returns the equivalent of 'this' (the object which this act method is being executed for). Line 66 checks to see if (a) batle == 1 (which will always be 'true', as it is set to one a few steps earlier) and (b) world == GameWorld (which should be coded as 'world instanceof GameWorld' which I believe will also always be 'true'). Lines 63 and 70 are showing two different uses of the same values; in line 63 they are being used as offsets. and in line 70 they are being used as absolute coordinates. This will not work as you may think (as offsets are distances from the current coordinate of the mouse actor who is being 'act'ed on). It appears from the above that you do not understand how to work with different World objects as yet. First, if you are to be returning to this GameWorld after BattleWorld has finished, then BattleWorld will need to keep a reference to this GameWorld object. You will most probably want the Mouse object and the Snake object passed to the BattleWorld class as well (that is, you probably do not want new instances of them in the BattleWorld class; especially if they hold pertinent fields, like health, score, etc. that are needed in that class). Having a reference in the BattleWorld class does not remove them from the GameWorld class, but if you add the actor object into the BattleWorld world (you do not need the references if you add them into the BattleWorld world), you will lose them in the GameWorld class (when returning from BattleWorld, add those objects back into the GameWorld world). You can either create method(s) to pass the objects, or pass them in the constructor call (new BattleWorld(world, mouse, snake)'; a constructor to recieve the objects will have to be coded into your BattleWorld class. If using the method calls, line 63 above would have to be broke down to:
BattleWorld battleWorld = new BattleWorld();
Greenfoot.setWorld(battleWorld());
// with the following as examples of passing the objects (for setting references)
battleWorld.setWorldObject(world);
battleWorld.setMouseObject(mouse);
battleWorld.setSnakeObject(snake);
//  OR, if adding the actor object into the world (references for actor objects not needed)
battleWorld.setWorldObject(world); // still needed or passed in constructor
battleWorld.addObject(mouse, 0, 0);
battleWorld.addObject(snake, 100, 100); 
If setting references, the methods to recieve the objects will need to be encoded in the BattleWorld class (using instance object fields that will be set by these methods). You can use individual methods as shown above, or you can combine them into one method, if you so choose. Hope this helps in your understanding of how changing worlds works.
student101 student101

2013/2/1

#
I think I understand how changing worlds work now, and how you have to carry over the actor into the new worlds if you want to preserve actor data. It's just that, with all of that in mind, it makes me wonder whether I'd have to recreate my worlds and instead make them subclasses rather than separate classes, because I've been trying to figure out how to carry over actors into other worlds and I came across this greenfoot scenario: Multi Level Design In its code it uses 'this(new Pengu()); to carry over the actor I think. If I'm wrong please correct me.
davmac davmac

2013/2/1

#
'this(new Pengu())' creates a 'new Pengu', it doesn't carry an existing one into a new world.
student101 student101

2013/2/1

#
Then how would I carry an existing actor into a new world? I'm finding it difficult to find how to do so on the internet.
davmac davmac

2013/2/1

#
You need a reference to the actor you want to carry across in a variable (say 'actor'). Then, after you create the new world, you can just add the actor to it in the usual way.
World nextWorld = new Level2World();  // or whatever
nextWorld.addObject(actor, 50, 50);  // choose appropriate coordinates
Greenfoot.setWorld(nextWorld);
There are some variations on this, but this is basically the idea.
There are more replies on the next page.
1
2
3