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

2017/12/2

Interactions between two classes

MarioLuigi MarioLuigi

2017/12/2

#
I have started writing a program with a jumping character who has to collect items and has to reach the end of a level (like Mario from Nintendo). If he hits a block with a "?", the block has to emit an item. How can give the block the information that he gets activated? Here is my code: MyWorld:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class MyWorld here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class MyWorld extends World
{
    private Actor Player1 = new Mario();
    /**
     * Constructor for objects of class MyWorld.
     * 
     */
    public MyWorld()
    {    
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(1000, 600, 1); 
        setBackground("images/background_sky.png");
        
        generierenDesBodens();
        
        addObject(Player1, 100, 520);
    }
   
    public void act()
    {

    }
        
    public void generierenDesBodens()
    {
        for(int i = 0; i<2; i++){
            for(int j = 0;j < 20; j++)
            {
                addObject(new Floor(),j*32+16,584-32*i);
            }
        }    
    }
    
}


Player:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
/**
 * Write a description of class Player here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Player extends Actor
{
    private int jumpStrength;
    private int speed;
    private int vSpeed;
    private int acceleration;
    private int timerOnGround;
    private boolean triggeredJump;
    private int higherJump;
    /**
     * Act - do whatever the Player wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public Player()
    {
        this.getImage().scale(32,32);
        speed = 2;
        vSpeed = 0;
        jumpStrength = 8;    
        acceleration = 1;
        timerOnGround = 0;
        triggeredJump = false;
        higherJump = 1;
    }
    
    public void act() 
    {

    }  
    
    public void controlls(int Player)   //here are the keybindings, int stands for the Player
    {
        if(Player==1)
        {
            if(Greenfoot.isKeyDown("shift"))
            {
                speed = 4;
            }
            else
            {
                speed = 2;
            }
            if(Greenfoot.isKeyDown("A"))
            {
                moveLeft();
            }
            if(Greenfoot.isKeyDown("D"))
            {
                moveRight();
            }
            if(Greenfoot.isKeyDown("space"))
            {
                higherJump();
            }
            if(Greenfoot.isKeyDown("space")&&onGround())
            {
                jump();
            }
        }        
    }
    
    public boolean isNextToBlock(String Direction)
    {
        if(Direction=="left")
        {
            setLocation(getX() - 1, getY());
            if(isTouching(Blocks.class))
            {
                setLocation(getX() + 1, getY());
                return true;
            }
            else
            {
                setLocation(getX() + 1, getY());
                return false;
            }
        }
        
        if(Direction=="right")
        {
            setLocation(getX() + 1, getY());
            if(isTouching(Blocks.class))
            {
                setLocation(getX() - 1, getY());
                return true;
            }
            else
            {
                setLocation(getX() - 1, getY());
                return false;
            }
        }
        
        return false;
    }
    
    public boolean isBelowCeiling()  //checks if the actor is at the ceiling
    {
       setLocation(getX(), getY() - 1); 
       if(isTouching(Blocks.class))
       {
           setLocation(getX(), getY() + 1); 
           return true;           
       }
       else
       {
           setLocation(getX(), getY() + 1); 
           return false;   
       }
    }
     
    public void higherJump()    //if the actor presses the jump key -> jump gets extended
    {
        if(triggeredJump == true && canExtendJump()){
            vSpeed = vSpeed - higherJump;
        }
    }    
    
    public boolean canExtendJump()  //checks if the actor is able to extend the jump
    {
        if(!onGround())
        {
            timerOnGround++;
        }
        
        if(timerOnGround < 20)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
    public void jump()  //makes the actor jump
    {
        triggeredJump = true;   //jump was made by pressing the key for it -> not normal falling
        vSpeed = -jumpStrength;
        fall();
    }
    
    public boolean onGround()   //checks if the actor is on the ground
    {
       setLocation(getX(), getY() + 1); 
       if(isTouching(Blocks.class))
       {
           setLocation(getX(), getY() -1); 
           return true;           
       }
       else
       {
           setLocation(getX(), getY() -1); 
           return false;   
       }
    }
    
    public boolean onGround2()  //old version of checking if the actor is on the ground
    {
        Actor under = getOneObjectAtOffset(0, getImage().getHeight() / 2, Blocks.class);

        return under != null;
    }
    
    public void checkFall()     //checks if the actor has to fall or jump
    {
        if(onGround())
        {
            vSpeed = 0;
            triggeredJump = false;
        }
        else
        {
            fall();
        }
    }
   
    public void fall()  //jumping and falling
    {
        if(vSpeed < 0)  //actor jumps
        {
            for(int i = 0; i > vSpeed; i--)
            {  
                
                if(isBelowCeiling())
                {
                    vSpeed = -vSpeed;
                }
                else
                {
                    setLocation(getX(), getY() - 1);
                }                
            }
        }
        
        if(vSpeed > 0)  //actor falls
        {
            for(int i = 0; i < vSpeed; i++)
            {
                setLocation(getX(), getY() + 1);
                if(onGround())
                {
                    i = 20000000;
                    timerOnGround = 0;
                }
            }
        }
        
        vSpeed = vSpeed + acceleration; 
    }    
    
    public void safeFall()  //old version of jumping
    {
        setLocation(getX(), getY() + vSpeed);
        vSpeed = vSpeed + acceleration;
    }
    
    public void moveLeft()  //actor moves left
    {
        for(int i = 0; i < speed; i++)
        {
            if(!isNextToBlock("left"))
            {
                setLocation(getX() - 1, getY());
            }            
        }        
    }
    
    public void moveLeftSafe()  //Safe of moveLeft
    {
        setLocation(getX() - speed, getY());
    }
    
    public void moveRight() //actor moves right
    {
        for(int i = 0; i < speed; i++)
        {
            if(!isNextToBlock("right"))
            {
                setLocation(getX() + 1, getY());
            }            
        }        
    }
}
Mario:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Mario here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Mario extends Player
{
    public Mario()
    {
     
    }
    
    /**
     * Act - do whatever the Mario wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    
    public void act() 
    {
        // Add your action code here.
        controlls(1);    
        checkFall();
    }
    
}
Thank your for your help. PS: I am a beginner in Greenfoot / Java so i would be glad to get some pieces of advise to ameliorate my program. ;-)
danpost danpost

2017/12/2

#
The block of code from line 193 to 195 is where the player hits its head on something. This is triggered by the return value of 'isBelowCeiling'. The block of code from line 108 to 111 is what is executed when a true value is returned. This is also where the Blocks object is detected. Now, you first need a way to distinguish between a block actor that can be activated from one that cannot. How do you intend on accomplishing that?
MarioLuigi MarioLuigi

2017/12/2

#
Maybe i could use the method getIntersectingObjects to identify which block is above the player?
danpost danpost

2017/12/2

#
MarioLuigi wrote...
Maybe i could use the method getIntersectingObjects to identify which block is above the player?
Please do tell how that will distinguish between the two.
MarioLuigi MarioLuigi

2017/12/3

#
I can distinguish between activatable and non - activatable blocks with this code:
public boolean isBelowCeiling()  //checks if the actor is at the ceiling -- version 1
    {
       setLocation(getX(), getY() - 1); 
       if(isTouching(Blocks.class))
       {
           if(isTouching(QuestionBlock.class) || isTouching(Brick.class))
           {
               touchingActivatableBlock = true;
           }
           else
           {
               touchingActivatableBlock = false;
           }
           setLocation(getX(), getY() + 1); 
           return true;           
       }
       else
       {
           touchingActivatableBlock = false;
           setLocation(getX(), getY() + 1); 
           return false;   
       }
    }
Of Course i have to reset the variable here:
public void fall()  //jumping and falling
    {
        if(vSpeed < 0)  //actor jumps
        {
            for(int i = 0; i > vSpeed; i--)
            {  
                
                if(isBelowCeiling())
                {
                    vSpeed = -vSpeed;
                }
                else
                {
                    setLocation(getX(), getY() - 1);
                }                
            }
        }
        
        if(vSpeed > 0)  //actor falls
        {
            touchingActivatableBlock = false;
            for(int i = 0; i < vSpeed; i++)
            {
                setLocation(getX(), getY() + 1);
                if(onGround())
                {
                    i = 20000000;
                    timerOnGround = 0;
                }
            }
        }
        
        vSpeed = vSpeed + acceleration; 
    }    
danpost danpost

2017/12/3

#
MarioLuigi wrote...
I can distinguish between activatable and non - activatable blocks with this code: < Code Omitted >
Okay -- all you had to indicate was that of your Block type objects, those that are QuestionBlock objects and those that are Brick objects can be activated. I doubt you need all the code that actually shows that (referring to the 'touchingActivatableBlock' boolean field and the current code from line 6 to line 13. You will need some code there to activate an activatable block, however. The following line should suffice:
((Block)getOneIntersectingObject(Block.class)).activate();
Then, add an 'activate' method to the Block class:
public void activate()
{
}
A boolean field can also be added to the Block class to flag whether a block has been activated or not:
protected boolean activated = false;
Now you are prepared to override the 'activate' method in the QuestionBlock and Brick subclasses. They should start something like this:
public void activate()
{
    if (activated) return;
    activated = true;
and continue with the action is does when activated.
MarioLuigi MarioLuigi

2017/12/3

#
What does this mean? 1.
.activate();
2.
if (activated) return; activated = true;
MarioLuigi MarioLuigi

2017/12/4

#
If
((Block)getOneIntersectingObject(Block.class))
is true the method "activate" gets called? And what does "(Block)" at the beginning mean? Besides, thank you for your replies so far! ;)
danpost danpost

2017/12/4

#
MarioLuigi wrote...
What does this mean? 1.
.activate();
It means to execute the method called 'activate' on the object referred to before the dot ( '.' ).
2.
if (activated) return; activated = true;
The first line basically says that if the actor has already been activated, do nothing (return back to the calling statement -- passing execution back to the line following the line in '1.'. The second line, which is only executed if the actor was not previously activated, sets the boolean flag to indicate that it has now been activated (so, when the first line is executed again, the code following, which will now be executed, is not executed again.
danpost danpost

2017/12/4

#
MarioLuigi wrote...
If
((Block)getOneIntersectingObject(Block.class))
is true the method "activate" gets called?
Not quite -- there is no conditional test performed here that can be 'true' or 'false'. The actor was already found to be touching a Block type object (when you used 'isTouching'). Here we are getting a reference to that object, so we can tell it to activate.
what does "(Block)" at the beginning mean?
The reference returned by 'getOneIntersectingObject' is declared to be of type Actor. It is necessary to declare it as a Block type object so that the 'activate' method, which is in the Block class, can be found to execute on the actor.
MarioLuigi MarioLuigi

2017/12/4

#
Thank you very much!!!
You need to login to post a reply.