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
7
danpost danpost

2016/9/27

#
Terminology: You apparent think that, when you say 'The method "obstructedView" is called from the LineOfSight class', it means that the method is in that class. Literally, however, it means that the code 'obstructedView()' is used to executed the method in that class (which, of course, is not the case). You can say 'The method "obstructedView" is in the LineOfSight class' or 'The method "obstructedView" is a member of the LineOfSight class'. Code: (confirmation) Because the obstructedView' method is a member of the LineOfSight class, you need to call the method on an object of that class. The 'protected static final LineOfSight los' field is the object it needs to be called on. 'los.' does need to be added before any calls to 'obstructedView'.
Parte Parte

2016/9/27

#
After corrections have been made I tested the code for Enemy_Test4 and I have noticed that the Enemy_Test4 only executes the shoot method only when the player has intersected the Enemy_Test4 and when the if statement value has been achieved. I presumed that the Enemy_Test4 would shoot the player when the player was in range and when there were no classes between its line of sight of the player.
danpost danpost

2016/9/27

#
Parte wrote...
After corrections have been made I tested the code for Enemy_Test4 and I have noticed that the Enemy_Test4 only executes the shoot method only when the player has intersected the Enemy_Test4 and when the if statement value has been achieved. I presumed that the Enemy_Test4 would shoot the player when the player was in range and when there were no classes between its line of sight of the player.
At the moment, it looks like the Enemy_Test4 object will shoot at the player only when both in range of the player and no obstructions are found.
Parte Parte

2016/9/27

#
danpost wrote...
Parte wrote...
After corrections have been made I tested the code for Enemy_Test4 and I have noticed that the Enemy_Test4 only executes the shoot method only when the player has intersected the Enemy_Test4 and when the if statement value has been achieved. I presumed that the Enemy_Test4 would shoot the player when the player was in range and when there were no classes between its line of sight of the player.
At the moment, it looks like the Enemy_Test4 object will shoot at the player only when both in range of the player and no obstructions are found.
That's odd because it ain't doing that at all, could the background count as an obstruction? Because that is the only other class that is technically intersecting with the enemy. Should I upload my scenario or provide code of my player and bullet classes as well?
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 (!los.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());
    }
}
danpost danpost

2016/9/27

#
Parte wrote...
could the background count as an obstruction? Because that is the only other class that is technically intersecting with the enemy.
Absolutely, if its class subclasses the Actor class. I was thinking of adding another method to the LineOfSight class that would check for specific type blockers. I would be something like this:
public boolean obstructedView(Actor actor1, Actor actor2, Class... classes)
{
    if (!obstructedView(actor1, actor2) return;
    for (Class cls : classes)
    {
        if (!getIntersectingObjects(cls).isEmpty()) return true;
    }
    return false;
}
Then you could, as an example, have code similar to this:
if (los.obstructedView(this, actorToView, Wall.class, Block.class, Tree.class)
listing any number of classes that create obstructions that you wish to check on.
Parte Parte

2016/9/27

#
danpost wrote...
Parte wrote...
could the background count as an obstruction? Because that is the only other class that is technically intersecting with the enemy.
Absolutely, if its class subclasses the Actor class. I was thinking of adding another method to the LineOfSight class that would check for specific type blockers. I would be something like this:
public boolean obstructedView(Actor actor1, Actor actor2, Class... classes)
{
    if (!obstructedView(actor1, actor2) return;
    for (Class cls : classes)
    {
        if (!getIntersectingObjects(cls).isEmpty()) return true;
    }
    return false;
}
Then you could, as an example, have code similar to this:
if (los.obstructedView(this, actorToView, Wall.class, Block.class, Tree.class)
listing any number of classes that create obstructions that you wish to check on.
I think that could work, however on line 3 "return;" is "incompatible types - missing return value". Are you suggesting I should replace the previous obstructedView method with the one you have given me?
danpost danpost

2016/9/27

#
Parte wrote...
I think that could work, however on line 3 "return;" is "incompatible types - missing return value". Are you suggesting I should replace the previous obstructedView method with the one you have given me?
Do not replace the previous 'obstructedView' method. Just add the new one along with it. Line 3 should be:
if (!obstructedView(actor1, actor2)) return false;
Parte Parte

2016/9/28

#
danpost wrote...
Parte wrote...
I think that could work, however on line 3 "return;" is "incompatible types - missing return value". Are you suggesting I should replace the previous obstructedView method with the one you have given me?
Do not replace the previous 'obstructedView' method. Just add the new one along with it. Line 3 should be:
if (!obstructedView(actor1, actor2)) return false;
I tried to implement the obstructedView method to my Enemy class however the Enemy class still ignores the player class.
public class Enemy_Test3 extends Animal
{
    private SimpleTimer timer = new SimpleTimer();
    private boolean turnPhase;
    private int phaseTimer = -1;
    private Actor pursued;
    private int obstacleTimer;
    private int bulletTimer;
    
    public void act() 
    {
        if (pursued == null)
        {
            if (getObjectsInRange(800, Player_Test1.class).isEmpty())
            {
                randomMovement(); // replace with appropriate code or method call
                return;
            }
            else
            {
                pursued = (Actor)getObjectsInRange(800, Player_Test1.class).get(0);
            }
           
        }
        
        if (pursued != null)
        {
            if (obstacleTimer == 0)
            {   
                if (!los.obstructedView(this, pursued))
                {
                    obstacleTimer = 100;
                }
            
                else
                {
                    pursue(); // replace with appropriate code or method call
                    return;
                }
            }   
        }
        
        if (obstacleTimer > 0)
        {
            if (--obstacleTimer == 0)
            {
                if (!los.obstructedView(this, pursued))
                {   
                    pursued = null;
                }
            }
            else
            {
                if (!los.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()
    {
        
        if (!getObjectsInRange(800,Player_Test1.class).isEmpty())
        {
            int x = getX(), y = getY();
            Player_Test1 player_test1 = (Player_Test1) getWorld().getObjects(Player_Test1.class).get(0);
            turnTowards(player_test1.getX(), player_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))
        {
            int x1 = getX(), y1 = getY();
            setLocation(x1, y1);
        }
    }
    
    public void obstructedMovement()
    {
        Player_Test1 player_test1 = (Player_Test1) getWorld().getObjects(Player_Test1.class);
        if (los.obstructedView(this, player_test1, Walltest1.class, Walltest2.class))
        {
            randomMovement();
        }
    }

    public void shoot()
    {     
        if (timer.millisElapsed() >= 360)
        {
            shootBullet();
            timer.mark();
            Greenfoot.playSound("Pistol Shot.mp3");
        }
    }
     
    public void shootBullet()
    {
        Enemy_Bullet_Test1 enemy_bullet = new Enemy_Bullet_Test1();
        enemy_bullet.setRotation(getRotation());
        getWorld().addObject(enemy_bullet, getX(), getY());
    }
}
Should I be putting a list of all the wall classes in every
!los.obstructedView
or am I missing something else?
Parte Parte

2016/9/28

#
Also another issue I have found with Enemy_Test4 is that although it won't shoot the player when the player is in range and a wall class is obstructing its view however (issue) when the player backs away from the wall class while the Enemy class is on the other side the enemy will execute the shoot method (I presume that the enemy executes the shoot method when the player has hit the 800 value range).
Super_Hippo Super_Hippo

2016/9/28

#
I think you added some '!' when you added the 'los' everywhere so it does the opposite from what it should do now.
Parte Parte

2016/9/28

#
Super_Hippo wrote...
I think you added some '!' when you added the 'los' everywhere so it does the opposite from what it should do now.
Are you implying that I should add or remove the '!' in my class?
Super_Hippo Super_Hippo

2016/9/28

#
I am saying that you added it although it wasn't there before, for example lines 30 and line 47.
Parte Parte

2016/9/28

#
I have found that I am getting 2 noticeable errors now. Error 1) It occurs when Enemy_Test3 shoots a bullet which removes the player off the world this error in the console appears: java.lang.IllegalStateException: Actor not in world. An attempt was made to use the actor's location while it is not in the world. Either it has not yet been inserted, or it has been removed (underlined lines are the errors): at greenfoot.Actor.failIfNotInWorld(Actor.java:711) at greenfoot.Actor.getX(Actor.java:164) at LineOfSight.obstructedView(LineOfSight.java:18) at Enemy_Test3.act(Enemy_Test3.java:38) at greenfoot.core.Simulation.actActor(Simulation.java:604) at greenfoot.core.Simulation.runOneLoop(Simulation.java:562) at greenfoot.core.Simulation.runContent(Simulation.java:221) at greenfoot.core.Simulation.run(Simulation.java:211) Error 2) It occurs when there is more than 1 Enemy_Test3 class and one of those Enemy_Test3 classes gets within range of the player and the Enemy class executes the pursue method (underlined lines are the errors): java.lang.ClassCastException: java.util.ArrayList cannot be cast to Player_Test1 at Enemy_Test3.obstructedMovement(Enemy_Test3.java:150) at Enemy_Test3.act(Enemy_Test3.java:64) at greenfoot.core.Simulation.actActor(Simulation.java:604) at greenfoot.core.Simulation.runOneLoop(Simulation.java:562) at greenfoot.core.Simulation.runContent(Simulation.java:221) at greenfoot.core.Simulation.run(Simulation.java:211) Here is the code for both the Enemy_Test3 class and the LineOfSight class: Enemy_Test3:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Enemy_Test3 here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Enemy_Test3 extends Animal
{
    private SimpleTimer timer = new SimpleTimer();
    private boolean turnPhase;
    private int phaseTimer = -1;
    private Actor pursued;
    private int obstacleTimer;
    private int bulletTimer;
    
    public void act() 
    {
        if (pursued == null)
        {
            if (getObjectsInRange(800, Player_Test1.class).isEmpty())
            {
                randomMovement(); // replace with appropriate code or method call
                return;
            }
            else
            {
                pursued = (Actor)getObjectsInRange(800, Player_Test1.class).get(0);
            }
           
        }
        
        if (pursued != null)
        {
            if (obstacleTimer == 0)
            {   
                if (!los.obstructedView(this, pursued))
                {
                    obstacleTimer = 100;
                }
            
                else
                {
                    pursue(); // replace with appropriate code or method call
                    return;
                }
            }   
        }
        
        if (obstacleTimer > 0)
        {
            if (--obstacleTimer == 0)
            {
                if (!los.obstructedView(this, pursued))
                {   
                    pursued = null;
                }
            }
            else
            {
                if (!los.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()
    {
        
        if (!getObjectsInRange(800,Player_Test1.class).isEmpty())
        {
            int x = getX(), y = getY();
            Player_Test1 player_test1 = (Player_Test1) getWorld().getObjects(Player_Test1.class).get(0);
            turnTowards(player_test1.getX(), player_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))
        {
            int x1 = getX(), y1 = getY();
            setLocation(x1, y1);
        }
    }
    
    public void obstructedMovement()
    {
        Player_Test1 player_test1 = (Player_Test1) getWorld().getObjects(Player_Test1.class);
        if (!los.obstructedView(this, player_test1, Walltest1.class, Walltest2.class))
        {
            randomMovement();
        }
    }

    public void shoot()
    {     
        if (timer.millisElapsed() >= 360)
        {
            shootBullet();
            timer.mark();
            Greenfoot.playSound("Pistol Shot.mp3");
        }
    }
     
    public void shootBullet()
    {
        Enemy_Bullet_Test1 enemy_bullet = new Enemy_Bullet_Test1();
        enemy_bullet.setRotation(getRotation());
        getWorld().addObject(enemy_bullet, getX(), getY());
    }
}
LineOfSight:
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;
    }  
    
    public boolean obstructedView(Actor actor1, Actor actor2, Class... classes)
    {
        if (!obstructedView(actor1, actor2)) return false;
        for (Class cls : classes)
        {
            if (!getIntersectingObjects(cls).isEmpty()) return true;
        }
        return false;
    }

}
danpost danpost

2016/9/28

#
At the beginning of the act method of the enemy classes, add the following:
if (persued != null && persued.getWorld() == null)
{
    persued = null;
}
That should take care of the NullPointerException.
Super_Hippo Super_Hippo

2016/9/28

#
Try to change line 34 to this:
if (pursued != null && pursued.getWorld() != null)
Line 150 should be:
Player_Test1 player_test1 = (Player_Test1) getWorld().getObjects(Player_Test1.class).get(0);
There are more replies on the next page.
1
2
3
4
5
6
7