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

2016/9/22

#
You could just replace those method calls ('wanderTurn' and 'wonderMove') with 'turn(1)' and 'move(1)' just to start.
Parte Parte

2016/9/22

#
danpost wrote...
You could just replace those method calls ('wanderTurn' and 'wonderMove') with 'turn(1)' and 'move(1)' just to start.
Alrighty seems as though it is working so far, however just 2 things I would like to know, 1 how would I have it so it turns instantly and 2 how would I have it so it may turn left and right? Thanks again.
danpost danpost

2016/9/22

#
Parte wrote...
just 2 things I would like to know, 1 how would I have it so it turns instantly and 2 how would I have it so it may turn left and right?
They both can be done simply by changing line 39 in your last code-post with:
if (turnPhase) phaseTimer = 1;
and replacing what was 'wanderTurn' to: turn(Greenfoot.getRandomNumber(360));
Parte Parte

2016/9/22

#
danpost wrote...
Parte wrote...
just 2 things I would like to know, 1 how would I have it so it turns instantly and 2 how would I have it so it may turn left and right?
They both can be done simply by changing line 39 in your last code-post with:
if (turnPhase) phaseTimer = 1;
and replacing what was 'wanderTurn' to: turn(Greenfoot.getRandomNumber(360));
Have done changes however the enemy stops moving
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Enemy_Test1 here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Enemy_Test1 extends Animal
{   
    private SimpleTimer timer = new SimpleTimer();
    
    // instance fields
    private boolean turnPhase;
    private int phaseTimer = -1;
    
    
    
    public void act()
    {
        int x1 = getX(), y1 = getY();
        
        if (!getObjectsInRange(800,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();
        }
        else
        {
            // 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);
                    if (turnPhase) 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);
        }
        
        if (isTouching(Walltest1.class) || isTouching(Walltest2.class))
        {
            setLocation(x1, y1);
        }
    }
    
    
    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());
    }

}
I also tried replacing line 38 with
if (turnPhase) phaseTimer = 1;
assuming that saying line 39 may of been a mistake but that results in the object to spin continuously.
danpost danpost

2016/9/22

#
Parte wrote...
I also tried replacing line 38 with
if (turnPhase) phaseTimer = 1;
assuming that saying line 39 may of been a mistake but that results in the object to spin continuously.
Actually, I meant line 44 -- as that is what controls the turning time.
Parte Parte

2016/9/24

#
danpost wrote...
Parte wrote...
I also tried replacing line 38 with
if (turnPhase) phaseTimer = 1;
assuming that saying line 39 may of been a mistake but that results in the object to spin continuously.
Actually, I meant line 44 -- as that is what controls the turning time.
I applied what you have said however it still spins 360 degrees continuously unless I get in range for it to follow the player
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Enemy_Test1 here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Enemy_Test1 extends Animal
{   
    private SimpleTimer timer = new SimpleTimer();
    
    // instance fields
    private boolean turnPhase;
    private int phaseTimer = -1;
    
    
    
    public void act()
    {
        int x1 = getX(), y1 = getY();
        
        if (!getObjectsInRange(800,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();
        }
        else
        {
            // 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 = 10+Greenfoot.getRandomNumber(360);
                    turnPhase = !turnPhase;
                }
                else
                {
                    if (turnPhase) phaseTimer = 1;
                    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);
        }
        
        if (isTouching(Walltest1.class) || isTouching(Walltest2.class))
        {
            setLocation(x1, y1);
        }
    }
    
    
    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());
    }

}
Super_Hippo Super_Hippo

2016/9/24

#
Ok, I am not really into it, but I think I found the problem. The first time the code is executed, line 41 sets 'phaseTimer' to a (high) positive value and the next line sets 'turnPhase' to true. So in the second act cycle, 'sign' is positive (line 51) and 'turnPhase' is true, so it turns. This happens until 'phaseTimer' reaches 0. This should not happen. Then line 46 is executed, 'phaseTimer' is set to 1 and it turns. This step happens for ever (unless line 23 triggers) because with phaseTimer=1 and turnPhase=true, it reaches line 46 again. This should not happen either. I am not really sure, but try the following:
//line 41:
else phaseTimer = 1;

//line 46
if (turnPhase) phaseTimer = -(20+Greenfoot.getRandomNumber(360));
Then the following steps should happen: Step 0: (Start) phaseTimer = -1 turnPhase = false Step 1: line 41+42 phaseTimer → 1 turnPhase → true Step 2: line 46 + line 53 phaseTimer → negative turnPhase still true Object turns Step 3: phaseTimer increasing (getting closer to 0) turnPhase still true Objects waits Step 4: (line 40+42) phaseTimer → positive turnPhase → false Step 5: (line 53) phaseTimer decreasing (getting closer to 0) turnPhase still false Object moves Step 6: (line 47) phaseTimer → negative turnPhase still false Step 7: phaseTimer increasing (getting closer to 0) turnPhase still false Object waits Step 8 = Step 1 ... You should also be able to change line 53 to move(6); and adding the turn(Greenfoot.getRandomNumber(360)); in line 46 (opening an if-block) without changing the result.
danpost danpost

2016/9/24

#
NVM, confused again, I thing Super_Hippo got it right. Yes. If the paused state after a move is ending (sign == -1 && turnPhase == false), then we start the turn phase. So line 41 should set the value of 'phaseTimer' to one.
Parte Parte

2016/9/24

#
Thank you both so very much! It works now! I just gotta fiddle with some of the parameters and it should be perfect, however 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. I remember danpost you said that I should have a temporary line class to be at the midpoint between the AI and the player so that it may detect that there are only 2 objects intersecting it (that being the player and the AI) and if there are more than 2 that it should continue the random movement; however I don't see how I would be able to do this exactly (I imagine I would have to use an image scaling method that would continuously scale the object intersecting detector line as the player and AI moves while adjusting its midpoint so that it is at the midpoint between the AI and player while the ends of the line still stick to the player and AI).
Parte Parte

2016/9/24

#
also a quick question (though slightly unrelated to original question of this topic) how would I have statements within the block associated with an if statement to continue executing if the if statement's value that it is looking for has been achieved only once?
danpost danpost

2016/9/24

#
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();
    }
}
danpost danpost

2016/9/24

#
Parte wrote...
how would I have statements within the block associated with an if statement to continue executing if the if statement's value that it is looking for has been achieved only once?
You could add a boolean field to indicate the conditions were met. However, oftentimes, something you do when it becomes true can be used to determine that the conditions were already met (for example, you might add a specific type object into the world that none were in the world prior to the conditions being met). You should probably show the code in question, so that a better response may be given.
Parte Parte

2016/9/24

#
danpost wrote...
Parte wrote...
how would I have statements within the block associated with an if statement to continue executing if the if statement's value that it is looking for has been achieved only once?
You could add a boolean field to indicate the conditions were met. However, oftentimes, something you do when it becomes true can be used to determine that the conditions were already met (for example, you might add a specific type object into the world that none were in the world prior to the conditions being met). You should probably show the code in question, so that a better response may be given.
public void act()
    {
        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();
            }
        }
Added second if statement within the if statement assuming that the block will loop due to the fact that the player will always be within 10000 units (though obviously that did not work out). Essentially when Bullet class is within x range for x amount of milliseconds once the associated block will continue to execute.
danpost danpost

2016/9/24

#
So...you want that the AI do the random move/pause/turn/pause until the Gun_Test1 object is in range and, from then on, to follow and shoot at it. Yes or no? If no, please be complete and detailed in your explanation of your goal here (including how obstructed view comes into play, throughout).
Parte Parte

2016/9/24

#
danpost wrote...
So...you want that the AI do the random move/pause/turn/pause until the Gun_Test1 object is in range and, from then on, to follow and shoot at the it. Yes or no? If no, please be complete and detailed in your explanation of your goal here (including how obstructed view comes into play, throughout).
a) Essentially I want two getObjectsInRange blocks, 1 of them being that if the player is within range and has no wall classes intersecting the object intersection detection line class, the player will then be pursued. Note that if wall class intersects during pursuit; the AI will stop pursuit and will instead move forward for x amount of seconds in hope that the wall class will still not be in the way (so it won't continue to run in a wall), once x amount of seconds has finished it will continue random movement if the player is not in range and has an intersecting wall, if the wall class stops intersecting the line class and the player is still within range the moving forward movement will cancel and the AI will continue the pursuit. b) The second getObjectsInRange block will make the AI pursue the player if the bullet class is within range for x amount of seconds, however the AI will stop pursuit and instead move forward for x amount of seconds if a wall class does intersect the line class, if the wall class is still intersecting and the player is out of range the AI will do random movement. If the wall class stops intersecting the line class and the player is still within range the moving forward movement will cancel and the AI will continue the pursuit. (note: when I say "pursuit" or any tense of the word I am referring to how the AI will turn towards the player, move forward and shoot which are already within my AI's code).
There are more replies on the next page.
1
2
3
4
5