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

2013/10/20

Making enemy behaviour (Stubborn Switch)

Tavi Tavi

2013/10/20

#
Hello Everyone :) , Im trying to create an enemy, and i have a few randomisers which work surprisingly well :) however, i have 2 major issues with this. 1. i have some platforms on which the enemies walk, but i need them to turn back when they are on the edge. i might be able to make this work BUT my enemy has to be able to make some random jump, and not turn. 2. ( the biggest problem) I have a few randomisers, ; - 1 , Determine howlong a random action is performed ( idle, walking left or right.) - 2 , which action it will perform. This works fine ! :) however, when let's say moveRight(); is called in the switch, it will only work for one "act", and it will move a few pixels instead of keeping the moveRight active unless it's told otherwise. When my game is done , i will be happy to post it :) .. And im just starting with greenfoot / programming in general, so please :) not too technical with the explanations ! And ofcourse to clear up, here's my code; Thank you in advance :) , yes, you !
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class RibbonPig here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class RibbonPig extends Mob
{
    private int richting = 1;
    private int speed = 4;

    //Behaviour
    private int richtingRandomiser = 1;
    public int behaviourTimer = 10;
    public int actionRandomiser = 1;
   
    
    /**
     * SPRITES INLADEN
     **/
     //Idle left
    GreenfootImage[] idleLeft = new GreenfootImage[]
        {
            new GreenfootImage("ribbonPig_left_stand_0.png"),
            new GreenfootImage("ribbonPig_left_stand_1.png"),
            new GreenfootImage("ribbonPig_left_stand_2.png")
        };
        
     //Idle right   
    GreenfootImage[] idleRight = new GreenfootImage[]
        {
            new GreenfootImage("ribbonPig_right_stand_0.png"),
            new GreenfootImage("ribbonPig_right_stand_1.png"),
            new GreenfootImage("ribbonPig_right_stand_2.png")
        };   
        
    //Naar links lopen
    GreenfootImage[] animateLeft = new GreenfootImage[]
        {
            new GreenfootImage("ribbonPig_left_move_0.png"),
            new GreenfootImage("ribbonPig_left_move_1.png"),
            new GreenfootImage("ribbonPig_left_move_2.png")
        };
    //naar Rechts lopen    
    GreenfootImage[] animateRight = new GreenfootImage[]
        {
            new GreenfootImage("ribbonPig_right_move_0.png"),
            new GreenfootImage("ribbonPig_right_move_1.png"),
            new GreenfootImage("ribbonPig_right_move_2.png")
        };
    
    /**
     * Act - do whatever the RibbonPig wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        super.checkFall();
        super.timer();
        animate(sequence);
        checkTimer(behaviourTimer);
        behaviourTimer--;
        System.out.println("Behaviour Timer  = " + behaviourTimer);
        System.out.println("sequence  = " + sequence);
        System.out.println("Speed  = " + speed);
        System.out.println("Richting  = " + richting);
        System.out.println("Swtich   = " + actionRandomiser);
    }    
    
        public void animate(int sequence) {
        switch(sequence)
        {
            case 0:
            idle(richting);
            break;
            case 1:
            animateLeft();
            break;
            case 2: 
            animateRight();
            break;
            default:
            break;
        }
    }
    
    
    
    /*************
           *Richting Checker
               **********/
    private void idle(int richting)
    {
        if(richting == 1)
        {
            animateIdleLeft();
        }
        if (richting == 2)
        {
            animateIdleRight();
        }
    }
    
    /*************
       *
        *
         *
          *
           *ANIMATIONS
            *
             *
              *
               **********/
               
               
    public void animateIdleLeft()
    {
        if(frame == 1)
        {
            setImage(idleLeft[0]);
        }
        else if (frame == 2)
        {
            setImage(idleLeft[1]);
        }
        else if(frame == 3)
        {
            setImage(idleLeft[2]);
            frame = 0;
            return;
        }
    }
    
    public void animateIdleRight()
    {
        if(frame == 1)
        {
            setImage(idleRight[0]);
        }
        else if (frame == 2)
        {
            setImage(idleRight[1]);
        }
        else if(frame == 3)
        {
            setImage(idleRight[2]);
            frame = 0;
            return;
        }
    }
    
    public void animateRight()
    {
        if(frame == 1)
        {
            setImage(animateRight[0]);
        }
        else if (frame == 2)
        {
            setImage(animateRight[1]);
        }
        else if(frame == 3)
        {
            setImage(animateRight[2]);
            frame = 0;
            return;
        }
    }
    
    public void animateLeft()
    {
        if(frame == 1)
        {
            setImage(animateLeft[0]);
        }
        else if (frame == 2)
        {
            setImage(animateLeft[1]);
        }
        else if(frame == 3)
        {
            setImage(animateLeft[2]);
            frame = 0;
            return;
        }
    }
    
    
     /*************
       *
        *
         *
          *
           *BEHAVIOUR
            *
             *
              *
               **********/
     
     public void checkTimer(int behaviourTimer) 
     {
         if(behaviourTimer == 0)
         
         {
             behaviourTimer();
         }
     }
               
               
     public void  behaviourTimer()
     {        
         behaviourTimer =  Greenfoot.getRandomNumber(50) + 10;
         actionRandomiser = Greenfoot.getRandomNumber(3);
         actionRandomiser(behaviourTimer, actionRandomiser);
     }
     
     public void actionRandomiser(int behaviourTimer, int actionRandomiser)
     {
         switch (actionRandomiser)
         {
           case 0:
                speed = 0;
                sequence = 0;
                break;
           case 1:
                speed = 4;
                sequence = 2;
                moveRight();
                richting = 2;
                break;
           case 2:
                speed = 4;
                sequence = 1;
                moveLeft();
                richting = 1;
                break;
         }
     }
               
    public void moveRight()
    {
        setLocation(getX()+speed, getY());
    }
    
    public void moveLeft()
    {
        setLocation(getX()-speed, getY());
    }

}
i Really hope you guys can help me out :) ! !
danpost danpost

2013/10/20

#
With a '10' in line 214, your actor will change behavior about 6 times a second. Use a larger number here. Also you are not calling 'actionRandomizer' every act cycle to let the actor continue. You are checking the timer and that method is calling the 'behaviourTimer' method which calls this method. But the timer always at zero when 'behaviourTimer' is called. Another thing is this, you do not have to pass around field declared in the class between method in the same class. The following is sufficient for replacing lines 202 through 240:
public void checkTimer() 
{
    if(behaviourTimer == 0)
    {
        behaviourTimer();
    }
    actionRandomizer();
}

public void behaviourTimer()
{
    behaviourTimer =  Greenfoot.getRandomNumber(50) + 10; //  you may want a larger number here
    actionRandomiser = Greenfoot.getRandomNumber(3);
}

public void actionRandomiser()
{
    switch (actionRandomiser)
    {
        case 0:
            speed = 0;
            sequence = 0;
            break;
        case 1:
            speed = 4;
            sequence = 2;
            moveRight();
            richting = 2;
            break;
        case 2:
            speed = 4;
            sequence = 1;
            moveLeft();
            richting = 1;
            break;
    }
}
Tavi Tavi

2013/10/21

#
Thank you! :) Awsome, it's nearly working ! The small numbers were on purpose though for testing, but yes.. that was too small of a number ! :) One more thing, i have small blocks called "platform.class", which the actor stands on, but when they get to the edge, they just keep on running and fall off.. If there any way to detect an edge of a platform, and turn moveLeft() into moveRight and vice versa ?
danpost danpost

2013/10/21

#
What code do you have for the platform class?
Tavi Tavi

2013/10/21

#
Well my platform class is currently empty, however.. There are phycics in a super class called mob.. I Also use these on my playable character :) . EDIT ( Different class, just same code in a way :) )
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Mobs here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Mob extends Mover
{
    
    
     //Vertical speed & Acceleration
    public int vSpeed = 0;
    public int acceleration = 1;
    //Jumping
    public boolean jumping;
    public int jumpStrength = -15;
    //Walking
    public int speed = 4;
    //Frame float
    public float frame = 0;
    long lastAdded = System.currentTimeMillis(); 
    // init sequence
    public int sequence = 0;
    //Direction
    public int richting = 2;
    
    
    
    /**
     * Act - do whatever the Mobs wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        checkFall();
        timer();
    }  
    public void timer()
    {  
        long curTime  = System.currentTimeMillis();  
        if (curTime >= lastAdded + 150) //5000ms = 5s  
        {  
            frame++;
            lastAdded  = curTime;  
        }  
    }  

    public void fall() 
    {
        setLocation (getX(), getY() +vSpeed);
        if (vSpeed <=10)
        {
            //Every pixel the actor falls, the speed will increase
            vSpeed = vSpeed + acceleration;
        }
        jumping = true;
    }
    //Check if character is onground
    public boolean onGround() 
    {
        //Calculate Sprite heiht
        int spriteHeight = getImage().getHeight();
        //Calculate sprite bottom
        int lookForGround = (int)(spriteHeight/2) + 5;
        //Look for ground
        Actor ground = getOneObjectAtOffset(0, lookForGround, platform.class);
        //If there's nothing underneath the actor, false.. if there is something underneath him..  True
        if (ground == null)
        {
            jumping = true;
            return false;
        }
        else 
        {
            moveToGround(ground);
            return true;
        }

    }
    
        //Places char on ground
    public void moveToGround (Actor ground)
    {
        int groundHeight = ground.getImage().getHeight();
        int newY = ground.getY() - (groundHeight + getImage().getHeight()) / 2;
        //Placing 
        setLocation(getX(), newY);
        //Prepare for jumping
        jumping = false;
    }
    //Sets character on the floor when he hit's the ground.
    public void checkFall() 
    {
        if(onGround())
        {
            vSpeed =0;
        }
        else
        {
            fall();
        }
    }
}
danpost danpost

2013/10/21

#
The x location at left and right edges are '0' and 'getWorld().getWidth()'. To not have your platform even go half of its length into an edge, you will have to add and subtract 'getImage().getWidth()/2' from the edge coordinates. Finally, you will need to know which direction the platform is moving to avoid toggling of the direction changes. This is simply 'speed > 0' and speed < 0'. Altogether, we have this:
if (speed < 0 && getX() < getImage().getWidth()/2) speed = -speed;
if (speed > 0 && getX() > getWorld().getWidth()-getImage().getWidth()/2) speed = -speed;
Put the code in the act method of the platform class (or in a method that the act method calls).
Tavi Tavi

2013/10/21

#
Thank you for your quick reply :) .. For movement i use a moveRight(); and a moveLeft(); Like this :
public void actionRandomiser()  
{  
    switch (actionRandomiser)  
    {  
        case 0:  
            speed = 0;  
            sequence = 0;  
            break;  
        case 1:  
            speed = 4;  
            sequence = 2;  
            moveRight();  
            richting = 2;  
            break;  
        case 2:  
            speed = 4;  
            sequence = 1;  
            moveLeft();  
            richting = 1;  
            break;  
    }  
}  
               
    public void moveRight()
    {
        setLocation(getX()+speed, getY());
    }
    
    public void moveLeft()
    {
        setLocation(getX()-speed, getY());
    }
The sequence controls the animation ( 0 == idle , and richting == direction left and right (1 and 2 ) ) I Also have everything covered underneath the Mover class. my platform does not recognize the speed variable, i feel like there is missing a link between my piglets and my platform class. The following code is placed in my Platform, which does nothing at this moment.
public class platform extends Mover
{
    public int speed;
    /**
     * Act - do whatever the platform wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        turnMob();
    }   
    
    public void turnMob(){
    if (speed < 0 && getX() < getImage().getWidth()/2) speed = -speed;  
    if (speed > 0 && getX() > getWorld().getWidth()-getImage().getWidth()/2) speed = -speed; 
    }
     
}
Once again, the speed is not recognized. I Hope someone can help !
Tavi Tavi

2013/10/21

#
Anyone :( ?
danpost danpost

2013/10/21

#
All you really need to do is to give 'speed' a value. Change line 3 to 'public int speed = 5; or for various speeds 'public int speed = Greenfoot.getRandomNumber(4)+2;'.
Tavi Tavi

2013/10/22

#
i Guess it's me, but even when i pass on a value,, let's say int speed = 5.. it will still not respond.. I Think something is missing somewhere, but i can't seem to figure it out. My piglets will keep on walking off the platforms, and where there is a stairs they just fall to the bottom of the map. At this point if i put that code in my platform class, i feel like there is no connection to the pigs.
danpost danpost

2013/10/22

#
I do not know exactly what is the Mover class, but you need either (1) a 'super.act()' statement (if there is an act method in the mover class that performs a 'move' or 'setLocation', (2) code in the act method of the platform class that 'move's or 'setLocation's the platforms. So far all you have in that class is a speed field and directive to turn at the edges.
Tavi Tavi

2013/10/22

#
http://www.greenfoot.org/support_classes/Mover.java This is my mover class :)
danpost danpost

2013/10/22

#
There is no 'act' method in the Mover class, so you will have to add one to the platform class to create the movement.
public void act()
{
    move(speed);
}
You need to login to post a reply.