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

2016/9/18

Random timed movement, ranged player detection and camera tracking

1
2
3
4
5
6
danpost danpost

2016/9/24

#
The following is an untested template for what you wanted. Again, there are places that are abbreviated where I used method calls to simplify the code into a summary format.
// instance fields
private Actor pursued;
private int obstacleTimer;

// in act or a method it calls
if (persued == null)
{
    if (getObjectsInRange(800, Gun_Test1.class).isEmpty())
    {
        randomMovement(); // replace with appropriate code or method call
        return;
    }
    else
    {
        persued = (Actor)getObjectsInRange(800, Gun_Test1.class).get(0);
    }
}
if (persued != null)
{
    if (obstacleTimer == 0)
    {
        if (obstructedView(this, persued))
        {
            obstacleTimer = 100;
        }
        else
        {
            persue(); // replace with appropriate code or method call
            return;
        }
    }
    if (obstacleTimer > 0)
    {
        if (--obstacleTimer == 0)
        {
            if (obstructedView(this, persued))
            {
                persued = null;
            }
        }
        else
        {
            if (obstructedView(this, persued))
            {
                obstructedMovement(); // replace with appropriate code or method call
                return;
            }
            else
            {
                obstacleTimer= 0;
                persue(); // replace with appropriate code or method call
                return;
            }
        }
    }
    else
    {
        persue(); // replace with appropriate code or method call
    }
}
Parte Parte

2016/9/25

#
danpost wrote...
Parte wrote...
I would like an opinion as to how I should approach the if at range and if there are no objects between the player and the AI the AI will follow the player.
Basically, you would start by adding the following to the Animal class (yes, add the LineOfSight class inside the Animal class):
protected static final LineOfSight los = new LineOfSight();

private class LineOfSight extends Actor
{
    public LineOfSight()
    {
        setImage(new GreenfootImage(1, 1));
    }
    
    public boolean obstructedView(Actor actor1, Actor actor2)
    {
        int xOffset = actor2.getX()-actor1.getX();
        int yOfffset = actor2.getY()-actor1.getY();
        int lineLength = (int)Math.hypot(xOffset, yOffset);
        int lineRotation = (int)(Math.atan2(yOffset, xOffset)*180/Math.PI);
        if (getWorld() != actor1.getWorld()) actor1.getWorld().addObject(this, actor1.getX(), actor1.getY());
        setLocation(actor1.getX(), actor1.getY());
        setRotation(lineRotation);
        getImage().scale(lineLength, 2);
        move(lineLength/2);
        return getIntersectingObjects(null).size() > 2;
    }
}
Now with this, any of the objects of any subclass of Animal can check its line of sight to any other actor in the world. For the IA, you could do something like the following (although, this does not allow random movement when the view is obstructed):
if (!getObjectsInRange(800,Gun_Test1.class).isEmpty())
{
    Gun_Test1 gun_test1 = (Gun_Test1) getWorld().getObjects(Gun_Test1.class).get(0);
    if (!obstructedView(this.gun_test1)
    {
        int x = getX(), y = getY();
        turnTowards(gun_test1.getX(), gun_test1.getY());
        move(10);
        shoot();
    }
}
I tried to add this:
public class Animal extends Actor
{
    private static final int WALKING_SPEED = 5;

    protected static final LineOfSight los = new LineOfSight();
 
    private class LineOfSight extends Actor
    {
        public LineOfSight()
        {
            setImage(new GreenfootImage(1, 1));
        }
     
        public boolean obstructedView(Actor actor1, Actor actor2)
        {
            int xOffset = actor2.getX()-actor1.getX();
            int yOfffset = actor2.getY()-actor1.getY();
            int lineLength = (int)Math.hypot(xOffset, yOffset);
            int lineRotation = (int)(Math.atan2(yOffset, xOffset)*180/Math.PI);
            if (getWorld() != actor1.getWorld()) actor1.getWorld().addObject(this, actor1.getX(), actor1.getY());
            setLocation(actor1.getX(), actor1.getY());
            setRotation(lineRotation);
            getImage().scale(lineLength, 2);
            move(lineLength/2);
            return getIntersectingObjects(null).size() > 2;
        }
    }
However these lines:
int lineLength = (int)Math.hypot(xOffset, yOffset);
            int lineRotation = (int)(Math.atan2(yOffset, xOffset)*180/Math.PI);
The yOffset cannot find symbol - variable yOffset and:
protected static final LineOfSight los = new LineOfSight();
new LineOfSight(); says it's non-static variable this cannot be referenced from a static context
Super_Hippo Super_Hippo

2016/9/25

#
For the first error, remove one 'f' in line 17.
Parte Parte

2016/9/25

#
Super_Hippo wrote...
For the first error, remove one 'f' in line 17.
Thanks.
danpost danpost

2016/9/25

#
For the other one, I was not thinking it through very well. The LineOfSight class needs to be a separate Actor subclass (not within the Animal class; but, the 'protected static final' field has no problem and should remain in the Animal class.
Parte Parte

2016/9/25

#
danpost wrote...
Parte wrote...
I would like an opinion as to how I should approach the if at range and if there are no objects between the player and the AI the AI will follow the player.
Basically, you would start by adding the following to the Animal class (yes, add the LineOfSight class inside the Animal class):
protected static final LineOfSight los = new LineOfSight();

private class LineOfSight extends Actor
{
    public LineOfSight()
    {
        setImage(new GreenfootImage(1, 1));
    }
    
    public boolean obstructedView(Actor actor1, Actor actor2)
    {
        int xOffset = actor2.getX()-actor1.getX();
        int yOfffset = actor2.getY()-actor1.getY();
        int lineLength = (int)Math.hypot(xOffset, yOffset);
        int lineRotation = (int)(Math.atan2(yOffset, xOffset)*180/Math.PI);
        if (getWorld() != actor1.getWorld()) actor1.getWorld().addObject(this, actor1.getX(), actor1.getY());
        setLocation(actor1.getX(), actor1.getY());
        setRotation(lineRotation);
        getImage().scale(lineLength, 2);
        move(lineLength/2);
        return getIntersectingObjects(null).size() > 2;
    }
}
Now with this, any of the objects of any subclass of Animal can check its line of sight to any other actor in the world. For the IA, you could do something like the following (although, this does not allow random movement when the view is obstructed):
if (!getObjectsInRange(800,Gun_Test1.class).isEmpty())
{
    Gun_Test1 gun_test1 = (Gun_Test1) getWorld().getObjects(Gun_Test1.class).get(0);
    if (!obstructedView(this.gun_test1)
    {
        int x = getX(), y = getY();
        turnTowards(gun_test1.getX(), gun_test1.getY());
        move(10);
        shoot();
    }
}
Alright I am a bit lost now and I am not sure if I am heading in the right direction, here's what I got so far:
public class Enemy_Test3 extends Animal
{
    private SimpleTimer timer = new SimpleTimer();
    private boolean turnPhase;
    private int phaseTimer = -1;
    private Actor pursued;
    private int obstacleTimer;
    
    public void act() 
    {
        if (pursued == null)
        {
            if (getObjectsInRange(800, Gun_Test1.class).isEmpty())
            {
                randomMovement(); // replace with appropriate code or method call
                return;
            }
            else
            {
                pursued = (Actor)getObjectsInRange(800, Gun_Test1.class).get(0);
            }
           
        }
        
        if (pursued != null)
        {
            if (obstacleTimer == 0)
            {   
                if (obstructedView(this, pursued))
                {
                    obstacleTimer = 100;
                }
            
                else
                {
                    pursue(); // replace with appropriate code or method call
                    return;
                }
            }   
        }
        
        if (obstacleTimer > 0)
        {
            if (--obstacleTimer == 0)
            {
                if (obstructedView(this, pursued))
                {   
                    pursued = null;
                }
            }
            else
            {
                if (obstructedView(this, pursued))
                {
                    obstructedMovement(); // replace with appropriate code or method call
                    return;
                }
                else
                {
                    obstacleTimer= 0;
                    pursue(); // replace with appropriate code or method call
                    return;
                }
            }
        }
            else
            {
                pursue(); // replace with appropriate code or method call
            }
    
        }   
    
    
    public void randomMovement()
    {
        // control code (when out of range of or path obstructed toward player)
        int sign = (int)Math.signum(phaseTimer); // '1' means moving or turning and '-1' means stopped after moving or turning
        phaseTimer -= sign; // step toward zero
        if (phaseTimer == 0)
        {
            if (sign == -1)
            {
                if (turnPhase) phaseTimer = 20+Greenfoot.getRandomNumber(150);
                else phaseTimer = 1;
                turnPhase = !turnPhase;
            }
            else
            {
                if (turnPhase) phaseTimer = -(20+Greenfoot.getRandomNumber(360));
                else phaseTimer = -(20+Greenfoot.getRandomNumber(50));
            }
        }
             
        if (sign > 0)
        {
            if (turnPhase) turn(Greenfoot.getRandomNumber(360)); else move(6);
        }

        if (atWorldEdge() || isTouching(Walltest1.class) || isTouching(Walltest2.class))
        {
            turn(160+Greenfoot.getRandomNumber(180)-90);
        }
         
        int x1 = getX(), y1 = getY();
        
        if (isTouching(Walltest1.class) || isTouching(Walltest2.class))
        {
            setLocation(x1, y1);
        }
    }
    
    public void pursue()
    {
        int x1 = getX(), y1 = getY();
        
        if (!getObjectsInRange(1000,Bullet_Test1.class).isEmpty() && (timer.millisElapsed() >= 2000))
        {
            if (!getObjectsInRange(10000,Gun_Test1.class).isEmpty())
            {
               int x = getX(), y = getY();
               Gun_Test1 gun_test1 = (Gun_Test1) getWorld().getObjects(Gun_Test1.class).get(0);
               turnTowards(gun_test1.getX(), gun_test1.getY());
               move(10);
               shoot();
            }
        }
        
        if (atWorldEdge() || isTouching(Walltest1.class) || isTouching(Walltest2.class))
        {
            turn(160+Greenfoot.getRandomNumber(180)-90);
        }
         
        if (isTouching(Walltest1.class) || isTouching(Walltest2.class))
        {
            setLocation(x1, y1);
        }
    }
    
    public void obstructedView()
    {
        if (!getObjectsInRange(800,Gun_Test1.class).isEmpty())
        {
            Gun_Test1 gun_test1 = (Gun_Test1) getWorld().getObjects(Gun_Test1.class).get(0);
            if (!obstructedView(this.gun_test1))
            {
                int x = getX(), y = getY();
                turnTowards(gun_test1.getX(), gun_test1.getY());
                move(10);
                shoot();
            }
        }
    }
    
    public void obstructedMovement()
    {
        
    }

    public void shoot()
    {     
        if (timer.millisElapsed() >= 400)
        {
            shootBullet();
            timer.mark();
        }
    }
     
    public void shootBullet()
    {
        Enemy_Bullet_Test1 enemy_bullet = new Enemy_Bullet_Test1();
        enemy_bullet.setRotation(getRotation());
        getWorld().addObject(enemy_bullet, getX(), getY());
    }
}
In the
public void obstructedView()
method the line
if (!obstructedView(this.gun_test1))
highlights gun_test1 as "cannot find variable gun_test1 In the
public void act() 
method all "obstructedView" says that "method obstructedView in Enemy_Test3 cannot be applied to given types; required: no arguments found: Enemy_Test3.greenfoot.Actor reason: actual and formal argument lists differ in length".
danpost danpost

2016/9/25

#
Okay, remove the 'obstructedView' method from the Enemy_Test3 class (and any other class you may have put it in. That method is already located in the LineOfSight clas. Then, where you got the 'cannot find variable gun_test1':
// change this
if (!obstructedView(this.gun_test1))
// to this
if (!los.obstructedView(this, gun_test1))
Prefix all calls to 'obstructedView' with 'los.'. They should start 'los.obstructedView(this, ', followed by the other actor.
Parte Parte

2016/9/25

#
danpost wrote...
Okay, remove the 'obstructedView' method from the Enemy_Test3 class (and any other class you may have put it in. That method is already located in the LineOfSight clas. Then, where you got the 'cannot find variable gun_test1':
// change this
if (!obstructedView(this.gun_test1))
// to this
if (!los.obstructedView(this, gun_test1))
Prefix all calls to 'obstructedView' with 'los.'. They should start 'los.obstructedView(this, ', followed by the other actor.
Thanks that works. After changes suggested have been made I have noticed 2 problems with my code is that my Enemy_Test3 class will not pursue (pursue method) my player when the player enters specified range, 800. The second problem is that I don't have any idea on how I am going to implement the obstruction detection code to my Enemy class (note I want it so that when any of the wall classes are obstructing random movement will continue). Thanks again.
danpost danpost

2016/9/25

#
Parte wrote...
my Enemy_Test3 class will not pursue (pursue method) my player when the player enters specified range, 800.
Remove 116, 117 and 126 from the Enemy_Test3 class code shown above. To what end were you trying to get a range on a Bullet_Test1 object?
The second problem is that I don't have any idea on how I am going to implement the obstruction detection code to my Enemy class
With the code above (with the last suggested changes), what are you wanting that it is not doing? and what is it doing that you do not want to happen?
Parte Parte

2016/9/25

#
danpost wrote...
Parte wrote...
my Enemy_Test3 class will not pursue (pursue method) my player when the player enters specified range, 800.
Remove 116, 117 and 126 from the Enemy_Test3 class code shown above. To what end were you trying to get a range on a Bullet_Test1 object?
The second problem is that I don't have any idea on how I am going to implement the obstruction detection code to my Enemy class
With the code above (with the last suggested changes), what are you wanting that it is not doing? and what is it doing that you do not want to happen?
I wanted to get a range on Bullet_Test1 so that when Bullet_Test1 is within range for x amount of seconds the AI would pursue the player (my idea was to have the enemy react to being shot at by chasing down the shooter, in this case that is the player). I also wanted the AI to pursue the player when the player was within x amount of range. However at the moment the AI only pursues the player when the player and the bullet are within range. What I want the AI to do that it is not doing is that if the player is within a certain range and there are no Wall classes (there are more than 1 wall class) obstructing its view (so no wall classes between the AI and the player) the AI will pursue the player, if anything else (so if the player is out of range or has a wall class obstructing its view it will instead do random movement.
danpost danpost

2016/9/25

#
After doing the suggest removing from my last post, one of your issues should have cleared up. Then, to implement the near-bullet actions, you will need another int timer. Unfortunately, this will complicate the code quite a bit (mainly the first part, where 'persued == null'). You will have to control the value of the field and use it to check the condition of things going into the method (a '0' value would mean no bullet has been near recently and a positive value would mean that the actor is currently chasing the player due to a near bullet and not due to the player being in range). A check for the player being in range should be done while to field is positive in the chance that a range-persuit is in order instead of a near-bullet one. In that case the 'persued' field should be set to the player and the near-bullet timer int field should be zeroed.
Parte Parte

2016/9/27

#
danpost wrote...
Now with this, any of the objects of any subclass of Animal can check its line of sight to any other actor in the world. For the IA, you could do something like the following (although, this does not allow random movement when the view is obstructed):
if (!getObjectsInRange(800,Gun_Test1.class).isEmpty())
{
    Gun_Test1 gun_test1 = (Gun_Test1) getWorld().getObjects(Gun_Test1.class).get(0);
    if (!obstructedView(this.gun_test1)
    {
        int x = getX(), y = getY();
        turnTowards(gun_test1.getX(), gun_test1.getY());
        move(10);
        shoot();
    }
}
I have tried this:
public class Enemy_Test4 extends Animal
{
    private SimpleTimer timer = new SimpleTimer();
    
    public void act() 
    {
        if (!getObjectsInRange(800,Player_Test1.class).isEmpty())
        {
            Player_Test1 player_test1 = (Player_Test1) getWorld().getObjects(Player_Test1.class).get(0);
            if (!obstructedView(this.player_test1))
            {
                int x = getX(), y = getY();
                turnTowards(player_test1.getX(), player_test1.getY());
                move(10);
                shoot();
            }
        }
    }    
    
    public void shoot()
    {     
        if (timer.millisElapsed() >= 360)
        {
            shootBullet();
            timer.mark();
        }
    }
     
    public void shootBullet()
    {
        Enemy_Bullet_Test1 enemy_bullet = new Enemy_Bullet_Test1();
        enemy_bullet.setRotation(getRotation());
        getWorld().addObject(enemy_bullet, getX(), getY());
    }
}
However this:
if (!obstructedView(this.player_test1))
"player_test1" "cannot find symbol - variable player_test1" even though I have already made it into a variable. And yes I am using another class just to experiment with the code and see how it works.
Super_Hippo Super_Hippo

2016/9/27

#
Shouldn't it be a ',' and not a '.'?
if (!obstructedView(this, player_test1))
If I see it correctly, the method needs two actors as the parameters.
Parte Parte

2016/9/27

#
Super_Hippo wrote...
Shouldn't it be a ',' and not a '.'?
if (!obstructedView(this, player_test1))
If I see it correctly, the method needs two actors as the parameters.
Of course... I feel silly now... thanks. However now "!obstructedView" says " cannot find symbol - method (!obstructedView(Enemy_Test4, Player_Test1)" The method "obstructedView" is called from the LineOfSight class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class LineOfSight here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class LineOfSight extends Actor
{
    public LineOfSight()
    {
        setImage(new GreenfootImage(1, 1));
    }
     
    public boolean obstructedView(Actor actor1, Actor actor2)
    {
        int xOffset = actor2.getX()-actor1.getX();
        int yOffset = actor2.getY()-actor1.getY();
        int lineLength = (int)Math.hypot(xOffset, yOffset);
        int lineRotation = (int)(Math.atan2(yOffset, xOffset)*180/Math.PI);
        if (getWorld() != actor1.getWorld()) actor1.getWorld().addObject(this, actor1.getX(), actor1.getY());
        setLocation(actor1.getX(), actor1.getY());
        setRotation(lineRotation);
        getImage().scale(lineLength, 2);
        move(lineLength/2);
        return getIntersectingObjects(null).size() > 2;
    }  
}
Super_Hippo Super_Hippo

2016/9/27

#
Correct. Since you already have this line in your Animal class
protected static final LineOfSight los = new LineOfSight();
you should be able to just write this:
if (!los.obstructedView(this, player_test1))
There are more replies on the next page.
1
2
3
4
5
6