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

2016/9/18

#
Hello, I am having difficulty as to how I would be able to have my AI move forward for a randomly selected amount of seconds then to stop for a random amount of seconds to then turn at a random angle and then to stop for a random amount of seconds (I want this to be in a loop and when I say "random" I mean that the value for that action has a set range to which it selects an amount of time to do the action within that set amount of time). My second issue that I have ran into is that I want my AI to move towards the player when the player is within a set range to the AI and when there are no "wall classes" obstructing its view, however I still want the AI to maintain a set distance away from the player so it may shoot the player. My third (and hopefully my last) issue that I have ran into is that I want to have camera tracking of the player so that only a portion of the world is revealed however I want the world to be larger than 1920x1080 however when I try to change the image size of the background via Greenfoot or editing the image it does not work. Please help and thanks in advance.
danpost danpost

2016/9/18

#
For the first issue, you could use two instance fields -- one for the timing and the other for the phase (turn-stop/move-stop:
// instance fields
private boolean turnPhase;
private int phaseTimer = -1;

// 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 = <move minimum value>+Greenfoot.getRandomNumber(<move range value>);
        else phaseTimer = <turn minimum value>+Greenfoot.getRandomNumber(<turn range value>);
        turnPhase = !turnPhase;
    }
    else
    {
        if (turnPhase) phaseTimer = -(<stop minimum value after turn>+Greenfoot.getRandomNumber(<stop range value after turn>));
        else phaseTimer = -(<stop minimum value after move>+Greenfoot.getRandomNumber(<stop range value after move>));
    }
}
This first part could be the 'else' part of the condition for moving toward the player. Obviously, you have two conditions that must be met to move toward the player: (1) in range (2) path not obstructed. The condition of being too close can be dealt with after moving (move back if minimum distance is surpassed). To check the path, I would add a temporary line actor into the world to check for obstructions. Just add a method to its class to return the number of intersecting objects. If the line is placed properly in the world (located at the mid-point between the player and the AI, a length equal to the distance between the two and at a rotation of the angle the two make), then there should only be two intersectors; if more are found, then it/they must be between the player and AI, and therefore the path is obstructed. For camera tracking, please supply the world class code you were trying to use. However, you wrote 'change the image size'and 'editing the image'; but, I wonder why you would want to change the size of or edit the image when you just need to redraw the large image onto the background image at some x and y offsets.
Parte Parte

2016/9/20

#
danpost wrote...
For the first issue, you could use two instance fields -- one for the timing and the other for the phase (turn-stop/move-stop:
// instance fields
private boolean turnPhase;
private int phaseTimer = -1;

// 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 = <move minimum value>+Greenfoot.getRandomNumber(<move range value>);
        else phaseTimer = <turn minimum value>+Greenfoot.getRandomNumber(<turn range value>);
        turnPhase = !turnPhase;
    }
    else
    {
        if (turnPhase) phaseTimer = -(<stop minimum value after turn>+Greenfoot.getRandomNumber(<stop range value after turn>));
        else phaseTimer = -(<stop minimum value after move>+Greenfoot.getRandomNumber(<stop range value after move>));
    }
}
1) I tried to use this and it just comes up full of errors all through out the code. Also from the way you worded yourself I think you may of mistaken my intention of the first part of what I wanted to achieve. I wanted to have the AI to turn, stop, move forward, stop while having this loop and having set ranges of time for it to stop and set ranges of time it moves forward and the angle of which it will turn. 2) With the player detection part which I want the AI to shoot the player when the player is within a certain range and for it to stop randomly moving (refer to part 1) I have no idea on what methods I should be using and how I should use them (please provide some sort of example for me if that is not too much trouble thank you). 3) For the camera tracking I already fixed the enlargement of the background and all I want now is for the screen to have the player to be in the centre of the screen while only revealing only part of the world (note that this will be a birds eye view type of game). Thank you for helping so far it is greatly appreciated.
danpost danpost

2016/9/20

#
For (1) for error correction, please post the code for the class where you tried to implement my code. I believe I had understood you correctly as far a what you wanted. For (2), the control code I gave should be placed in your act method in a manner similar to the following:
if ('player in range')
{
    turnTowards('player coordinates');
    move('move distance');
    if ('newly calculated distance' < 'minimum range to player') move(-'move distance');
    shootTimer++;
    if (shootTimer == 'shoot delay value') shoot();
}
else
{
    // control code
    if (sign > 0)
    {
        if (turnPhase) wanderTurn(); else wanderMove();
    }
}
BTW, none of the code I am giving can be directly added to your code and run. It is given as pseudo-code (code that needs to be turned into absolute java code before it can run properly. In the first code-set I supplied, anything enclosed like this, < **** >, needs to be converted to some value. In the second code-set, I enclosed them in single quotes (thinking it might get confusing along with 'if' condition requiring 'greater than' or 'less than'). Also, some method calls were used that methods need to be written for ('shoot', 'wanderTurn' and 'wanderMove'). For (3), I already stated that you will need offset values for where to redraw the larger image onto the background image of the world. Have the player move as normal and have the world act method move the player back to the middle (and all other actors the same direction and distance) while re-drawing the background with offsets adjusted by the axial distances the player was moved. Before moving anything, however, make sure that the offsets to not exceed their limits.
Parte Parte

2016/9/20

#
1)
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 SmoothMover
{
    // instance fields
    private boolean turnPhase;
    private int phaseTimer = -1;
 
    // 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 = 3+Greenfoot.getRandomNumber(10);
            else phaseTimer = 10+Greenfoot.getRandomNumber(180);
            turnPhase = !turnPhase;
        }
        else
        {
            if (turnPhase) phaseTimer = -(10+Greenfoot.getRandomNumber(180));
            else phaseTimer = -(3+Greenfoot.getRandomNumber(10));
        }
    }
}
danpost danpost

2016/9/20

#
1) Lines 15 though 31, the control code, needs to be placed inside a method:
public void act()
{
    // code here
}
Parte Parte

2016/9/20

#
1) After corrections stated above no errors appear however the object does not move at all in the world.
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 SmoothMover
{   
    public void act()
    {
        RandomMovement();
    }
    
    // instance fields
    private boolean turnPhase;
    private int phaseTimer = -1;
    
    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 = 3+Greenfoot.getRandomNumber(10);
                else phaseTimer = 10+Greenfoot.getRandomNumber(180);
                turnPhase = !turnPhase;
            }
            else
            {
                if (turnPhase) phaseTimer = -(10+Greenfoot.getRandomNumber(180));
                else phaseTimer = -(3+Greenfoot.getRandomNumber(10));
            }
        }
    }
}
danpost danpost

2016/9/20

#
Parte wrote...
1) After corrections stated above no errors appear however the object does not move at all in the world.
Please see my reply on (2) above. Line 11 of the code given in that reply should be replaced by the code within your RandomMovement method. The RandomMovement method is incorrectly named (at the moment). Currently, the code in it just controls the values of your fields ('phaseTimer' and 'turnPhase'). You could add lines 12 through 15 of the (2) code to the end of the method. That would make the method conform more to its name. After that, you can replace line 9 through 15 of the (2) code with 'else RandomMovement();'. Finally that (2) code should replace lines 13 in your act method. Lines 3 through 7 of my (2) code could also be placed in a separate method, called something like 'followPlayer' and those lines replaced with a call to that method. Then, your act method would simply be:
public void act()
{
    if ('player in range') followPlayer(); else randomMovement();
}
Parte Parte

2016/9/21

#
danpost wrote...
Parte wrote...
1) After corrections stated above no errors appear however the object does not move at all in the world.
Please see my reply on (2) above. Line 11 of the code given in that reply should be replaced by the code within your RandomMovement method. The RandomMovement method is incorrectly named (at the moment). Currently, the code in it just controls the values of your fields ('phaseTimer' and 'turnPhase'). You could add lines 12 through 15 of the (2) code to the end of the method. That would make the method conform more to its name. After that, you can replace line 9 through 15 of the (2) code with 'else RandomMovement();'. Finally that (2) code should replace lines 13 in your act method. Lines 3 through 7 of my (2) code could also be placed in a separate method, called something like 'followPlayer' and those lines replaced with a call to that method. Then, your act method would simply be:
public void act()
{
    if ('player in range') followPlayer(); else randomMovement();
}
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Enemy_Test2 here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Enemy_Test2 extends SmoothMover
{
    public void act()
    {
        if (!getObjectsInRange(800,Gun_Test1.class).isEmpty()) FollowPlayer(); else RandomMovement();
    }
    
    private boolean turnPhase;
    private int phaseTimer = -1;
    private SimpleTimer timer = new SimpleTimer();
    
    public void RandomMovement()
    {
        int sign = (int)Math.signum(phaseTimer);
        phaseTimer -= sign;
        if (phaseTimer ==0)
        {
            if (sign == -1)
            {
                if (turnPhase) phaseTimer = 3+Greenfoot.getRandomNumber(10);
                else phaseTimer = 10+Greenfoot.getRandomNumber(180);
                turnPhase = !turnPhase;
            }
            
            else
            {
                if (turnPhase) phaseTimer = -(10+Greenfoot.getRandomNumber(180));
                else phaseTimer = -(3+Greenfoot.getRandomNumber(10));
            }
        }
        
    }
    
    
    public void FollowPlayer()
    {
        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 (!getObjectsInRange(250,Gun_Test1.class).isEmpty())
        {
            move(-10);
        }
       
    }
    
    public void shoot()
    {     
        if (timer.millisElapsed() >= 500)
        {
            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());
    }
    
    
}
Extremely sorry but I have utterly confused myself because I rearranged certain parts and have a layout that partly differs from yours, this is because I have inputted some methods which allow for the enemy to move towards the player and to shoot at the player while maintaining a minimum distance from the player. However I am still having trouble using the values given from the random number statements to use as values for the distance the enemy moves, the pause length it takes before proceeding to change angle it is facing and the pause length it takes before looping again until player is within range. The help and patience and help you have given so far is greatly appreciated.
danpost danpost

2016/9/21

#
At line 39, you need to add the (random) movement or turning code, for when the value of 'phaseTimer' is greater than zero.
Parte Parte

2016/9/21

#
danpost wrote...
At line 39, you need to add the (random) movement or turning code, for when the value of 'phaseTimer' is greater than zero.
How would I be able to make reference/call the values gained from the random numbers statements to my if (phaseTimer > 0) block? E.g. of what I mean: move('randomnumber') for ('randomnumber') amount of milliseconds. Thanks.
danpost danpost

2016/9/21

#
Parte wrote...
How would I be able to make reference/call the values gained from the random numbers statements to my if (phaseTimer > 0) block? E.g. of what I mean: move('randomnumber') for ('randomnumber') amount of milliseconds.
The random part is already done -- the 'phaseTimer' field contains the random value for all phases. Move or turn a single step for each time the value of the field counts down. For each step that the value counts up (when the field contains a negative value), do nothing to create the pause between moving and turning. See lines 12 though 15 (which is shown after where the control code goes) of my (2) explanation above.
Parte Parte

2016/9/21

#
danpost wrote...
Parte wrote...
How would I be able to make reference/call the values gained from the random numbers statements to my if (phaseTimer > 0) block? E.g. of what I mean: move('randomnumber') for ('randomnumber') amount of milliseconds.
The random part is already done -- the 'phaseTimer' field contains the random value for all phases. Move or turn a single step for each time the value of the field counts down. For each step that the value counts up (when the field contains a negative value), do nothing to create the pause between moving and turning. See lines 12 though 15 (which is shown after where the control code goes) of my (2) explanation above.
Still confused, here is what I got so far:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Enemy_Test2 here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Enemy_Test2 extends SmoothMover
{
    public void act()
    {
        if (!getObjectsInRange(800,Gun_Test1.class).isEmpty()) FollowPlayer();
        else
        {
            if (sign > 0)
            {
                
            }
        }
        
        if (!getObjectsInRange(1200,Gun_Test1.class).isEmpty() && Greenfoot.mouseClicked(null)) FollowPlayer();
        else
        {
            if (sign > 0)
            {
                if (turnPhase) wanderTurn(); else wanderMove();
            }
        }
        
    }
    
    private boolean turnPhase;
    private int phaseTimer = -1;
    private SimpleTimer timer = new SimpleTimer();
    
    public void randomMovementValues()
    {
        int sign = (int)Math.signum(phaseTimer);
        phaseTimer -= sign;
        if (phaseTimer == 0)
        {
            if (sign == -1)
            {
                if (turnPhase) phaseTimer = 3+Greenfoot.getRandomNumber(10);
                else phaseTimer = 10+Greenfoot.getRandomNumber(180);
                turnPhase = !turnPhase;
            }
            
            else
            {
                if (turnPhase) phaseTimer = -(10+Greenfoot.getRandomNumber(180));
                else phaseTimer = -(3+Greenfoot.getRandomNumber(10));
            }
        }
        
    }
    
    public void wanderTurn()
    {
        
    }
    
    public void wanderMove()
    {
        
    }
    
    public void FollowPlayer()
    {
        
        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 (!getObjectsInRange(250,Gun_Test1.class).isEmpty())
        {
            move(-10);
        }
       
    }
    
    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());
    }
    
    
}
danpost danpost

2016/9/21

#
It is getting harder and harder for me to explain what to do because you are doing half of what I suggest, then change other things, and then have to go back and try and implement the other half -- which no longer can be done as I had suggested because of the new stuff. On top of that, I see that you posted a different class midway through (Enemy_Test2 instead of Enemy_Test1). Please go back to the last Enemy_Test1 class code post and start again from there. Of course, when referring back to the (2) code, where it says in the act method, it will now be in the 'randomMovement' method (although I said act, I had no clue at that point about where any code was being placed as you only gave code clips (blocks of code from within a method).
Parte Parte

2016/9/22

#
danpost wrote...
It is getting harder and harder for me to explain what to do because you are doing half of what I suggest, then change other things, and then have to go back and try and implement the other half -- which no longer can be done as I had suggested because of the new stuff. On top of that, I see that you posted a different class midway through (Enemy_Test2 instead of Enemy_Test1). Please go back to the last Enemy_Test1 class code post and start again from there. Of course, when referring back to the (2) code, where it says in the act method, it will now be in the 'randomMovement' method (although I said act, I had no clue at that point about where any code was being placed as you only gave code clips (blocks of code from within a method).
Alright I have returned to the other class and I believe I have got it now
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 SmoothMover
{   
    private SimpleTimer timer = new SimpleTimer();
    
    // instance fields
    private boolean turnPhase;
    private int phaseTimer = -1;
    
    
    
    public void act()
    {
        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 = 3+Greenfoot.getRandomNumber(10);
                    else phaseTimer = 10+Greenfoot.getRandomNumber(180);
                    turnPhase = !turnPhase;
                }
                else
                {
                    if (turnPhase) phaseTimer = -(10+Greenfoot.getRandomNumber(180));
                    else phaseTimer = -(3+Greenfoot.getRandomNumber(10));
                }
            }
            
            if (sign > 0)
            {
                if (turnPhase) wanderTurn(); else wanderMove();
            }
        }
    }
    
    
    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());
    }

}
However I do not know what the 'wanderTurn' and 'wanderMove' methods should contain (I know that the action to move and turn goes in these methods but the specific methods, statements and their arrangement they should be in these methods I do not know). Please help, thanks.
There are more replies on the next page.
1
2
3
4