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

2012/5/13

Help with a function? :)

Jesse_Orange Jesse_Orange

2012/5/13

#
I am unsure why the below code does not work. Everything is fine asides from the x value. Is there another way to set a random location using x and y? Thanks, help is appreciated.
1
2
3
4
5
6
7
8
9
10
11
12
private void findEatFood()// funcion to eat an actor. Specifically Food
   {
  Actor thisFood=getOneObjectAtOffset(0,0,Food.class); // is there Food in the current square?
  if(thisFood!=null) //there is no Food
  {
  Greenfoot.playSound("Belch.wav"); //play sound file
  getWorld().removeObject(thisFood); //removes an actor from the world once it has been eaten.
  x = Greenfoot.getRandomNumber(20);
  y = Greenfoot.getRandomNumber(20);
  }while(!getObjectsAt(x, y, null).isEmpty());
  addObject(new Food(), x, y);
  }
danpost danpost

2012/5/13

#
The main thing that strikes me, is the lack of a 'do {' (probably after line 7). The other thing is in lines 8 and 9, where x and y need to be declared as 'int'. Code replacing 8 through 11:
1
2
3
4
5
6
do
{
    int x = Greenfoot.getRandomNumber(20);
    int y = Greenfoot.getRandomNumber(20);
} while (!getObjectsAt(x, y, null).isEmpty());
addObject(new Food(), x, y);
Jesse_Orange Jesse_Orange

2012/5/13

#
Oh I see how that works now :) Thanks for that. On that not how do I get an actor to detect the co-ordinates of another actor? After I know how to do that I'm going to code one actor to follow behind another actor. Hopefully I get better at using Greenfoot at some point, you seem to know what you're doing though, do you teach it?
danpost danpost

2012/5/13

#
Jesse_Orange wrote...
how do I get an actor to detect the co-ordinates of another actor? After I know how to do that I'm going to code one actor to follow behind another actor.
The easiest way to accomplish the following thing is to have a reference to the followed in the follower, and have the follower record the location of the followed; when the followed is no longer at that location, move there and record the new location of the followed.
Jesse_Orange wrote...
you seem to know what you're doing though, do you teach it?
I grew up on Basic, Fortran and the like. Did some dabbling in Assembly on my own. Never used Java until a little over a year ago. But what helped me out most, was the Greenfoot tutorials, that you can get to by way of the 'Documentation' link near the top of the page, AND especially the Java trails. The second section on the left, 'Trails Covering the Basics' is the best place to start.
Jesse_Orange Jesse_Orange

2012/5/13

#
Yeah, I see how that would work because you're using the follower to record the movements and then follow the movements. Makes sense however would you say its harder to code entirely through the lead actor? This is because I'm trying to make a Snake type game for a projecty type thing. Oh cool see i started using Greenfoot literally about 2-3 weeks ago...I understand how i want and how things should work, it's just a case of figuring out the code. I shall give those tutorials a look then. Cheers.
danpost danpost

2012/5/13

#
BTW, there are a number of ways to pass the reference of the followed to the follower. One way is to create and add the followed to the world first; then pass a reference to the follower when you create it (you will need to add a constructor that recieves the followed reference). Another way is to create a method in the follower to accept the reference of the followed and save it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// instance variables
Actor following = null;
int followingX = -1;
int followingY = -1;
// setWhatToFollow(Actor) recieves and saves a reference to the actor it is to follow
public void setWhatToFollow(Actor actor)
{
    following = actor;
    saveNextLocation();
}
// saveNextLocation() records the current location of the actor it is following
private void saveNextLocation()
{
    followingX = following.getX();
    followingY = following.getY();
}
Since I do not know the name of your classes, you will have to substitute 'Actor' with the appropriate sub-class name. With this method, you would need to reference both actors in the world class, as follows:
1
2
3
4
5
Followed followed = new Followed();
addObject(followed, 1, 1);
Follower follower = new Follower();
addObject(follower, 0, 0);
follower.setWhatToFollow(followed);
Again the Class names need to be changed to fit your scenario, but the general idea as to what is needed is here.
Jesse_Orange Jesse_Orange

2012/5/13

#
This is my code for the SnakeHead Actor, as you can see everything that happens in the game revolves around this actor as I thought this was an easier method. I have a function called AddSnakeBody and I want it to do the following: function addBody currX = get current x co-ordinate currY = get current y co-ordinate newX = currX + offsetX (used for setting direction) newY = currY + offsetY (used for setting direction) add new snakeBody at newX, newY I want to get the current x and y co-ordinates of SnakeHead and then use an if statement to say if the head moves up, follow but minus one from either x or y so that it is always behind the head. Question is can I do all this from within one actor? I mean everything else works but feel free to make any comments about the code I already have. Again thanks, its good to speak to someone with some understanding.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.List; // import java for lists
 
/**
 * Write a description of class SnakeHead here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class SnakeHead extends Actor
{
 
  int offsetX = 0; //global variable storing the random X direction (1, 0 or -1)
  int offsetY = -1; //global variable storing the random Y direction (1, 0 or -1)
   
  public SnakeHead() // constructor
   {
       setDirection(); //set a direction for the lizard.
   
  
  public void act()
  {
        int currX = getX(); //get current x co-ordinate
        int currY = getY(); // get current y co-ordinate
        processKeys();
        move();
        setDirection();
        findEatFood();
        addSnakeBody();
    }
     
   private void processKeys()
   {
     if(Greenfoot.isKeyDown("left")) //move left
     {
         offsetX=-1;
         offsetY=0;
        }
     if(Greenfoot.isKeyDown("right")) //move right
     {
         offsetX=1;
         offsetY=0;
        }
     if(Greenfoot.isKeyDown("up")) //move up
     {
         offsetX=0;
         offsetY=-1;
        }
     if(Greenfoot.isKeyDown("down")) //move down
     {
         offsetX=-0;
         offsetY=1;
        }
    }
     
  private void move() //
    {
     int currX = getX(); //get current x co-ordinate
     int currY = getY(); // get current y co-ordinate
     if(canMove(currX + offsetX, currY + offsetY))
     setLocation(currX + offsetX, currY + offsetY); //if the snake can move it will move in a direction
    }
     
     private void setDirection() //
    {
        do{ }while(offsetX==0 && offsetY==0);
     
        if(offsetX == -1 && offsetY == 0) //if the snake will go west
            setRotation(180); //set rotation to south
        else if(offsetX == 0 && offsetY == -1) //if the lizard will go north
            setRotation(270); //set rotation to west
        else if(offsetX == 0 && offsetY == 1) //if the lizard will go south
            setRotation(90); //set rotation to east
        else if(offsetX == 1 && offsetY == 0) //if the lizard will go east
            setRotation(0); //set rotation to north
    }
     
    private void findEatFood()// funcion to eat an actor. Specifically Food
       {
      Actor thisFood=getOneObjectAtOffset(0,0,Food.class); // is there Food in the current square?
      if(thisFood!=null) //there is no Food
      {
      Greenfoot.playSound("Belch.wav"); //play sound file
      getWorld().removeObject(thisFood); //removes an actor from the world once it has been eaten.
      int x = Greenfoot.getRandomNumber(29); //random x co-ordinate
      int y = Greenfoot.getRandomNumber(29); //random y co-ordinate
      getWorld().addObject(new Food(), x, y); //add new object at a random co-ordinate
      }
    }
     
    private void addSnakeBody()
    {
 
    }
 
     boolean canMove(int x,int y)    
        {
        List foundWall = getWorld().getObjectsAt(x,y, Wall.class); //canMove is false if a Wall is found
        if(!foundWall.isEmpty  ())return false;   //if Wall found return false and stop otherwise continue
         
        return true;    //this must be at the end – if canMove got this far it didn't find any of the listed objects.
         
    }
}
danpost danpost

2012/5/13

#
The lead actor would need an array of body segments and would control them (the body segments would not have an act() method). Move from the rear up, moving to the location of the next segment, until finally the head will move (keystroke directed). You would make sure the move is valid before moving anything (not passed the edge of the world, not back upon itself, and possibly not into any obstacles). In any of those events, you may or may not want to do something specific to it (some snake games go Game Over for some of those events). BTW, check out my scenario 'Total Infestation'. It is basically a multiple snake game. Just click on my icon to the left, and you can get to the scenario from there.
danpost danpost

2012/5/13

#
First off, I do not like the looks of line 66, at all. If both values are 0 then do nothing, both value will forever be 0, and you are stuck in the loop (you can just remove that statement). Secondly the addSnakeBody method call within the act() method is not being regulated (you do not know if anything has been eaten or not). You could have the findEatFood() method return a boolean to signify that food had been found (or not), and base the addSnakeBody method call on that. Prepare: process keys and set direction before the following 1) move the head only (you could save location (x and y) of head first) 2) check for food, eat if present, and return finding 3) if no food was eaten, then move the rest of the snake; else, add new body segment at saved x-y (or the saved x-y of first body segment, which should be where the head moved from) and adjust 'following' of old first body segment, shift all array entries down one and add new segment to front of list, setting its 'following' to the head. You could instead, do a reverse list, where the last item on the list would be the segment immediately behind the head of the snake; then, you only need to append the segment to the end of the list. You should also have an instance 'int' variable in the SnakeHead class to keep track of how many body segments there are. With the reverse list, the body segments can have an instance 'int' variable to indicate where in the list it resides (and this value will not ever change), so it can find its leader. In the SnakeHead class, the array, or list, of body segments can be declared with:
1
2
SnakeBody[] segments = new SnakeBody[100]; (again, not knowing your class names)
segmentCount = 0;
and you will need a method to add the segments (again, in the SnakeHead class):
1
2
3
4
5
6
7
public SnakeBody addSegment()
{
    SnakeBody segment = new SnakeBody(segmentCount);
    segments[segmentCount] = segment;
    segmentCount++;
    return segment;
}
I have this method return a reference to the new segment so that we can then add it to the world, which could be done in one statement from the SnakeHead class, with:
1
getWorld().addObject(addSegment(), getX(), getY());
A constructor in the SnakeBody class will need to accept the value:
1
2
3
4
5
6
int value = -1;
 
public Snakebody(int val)
{
    value = val;
}
All the 'if's to determine the rotation is not neccessary:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int offsetX = 0;
int offsetY = 0;
// processKeys() processes the keys without bias and retains original direction if key is null or keys cancel each other out
private void processKeys()
{
    int dx = 0, dy = 0;
    if (Greenfoot.isKeyDown("right")) dx++;
    if (Greenfoot.isKeyDown("left")) dx--;
    if (Greenfoot.isKeyDown("down")) dy++;
    if (Greenfoot.isKeyDown("up")) dy--;
    if (dx * dx == dy * dy) return; // one must be 0, and the other 1 or -1
    offsetX = dx;
    offsetY = dy;
}
 
private void setDirection()
{
    int direction = (offsetY != 0 ? 2 - offsetY : 0) + (offsetX != 0 ? 1 - offsetX : 0);
    setRotation(direction * 90);
}
Lines 26 and 27 should probably be reversed (setting the direction before the move).
Jesse_Orange Jesse_Orange

2012/5/17

#
This code in SnakeHead adds a SnakeBody
1
2
3
4
5
6
7
private void addSnakeBody()
 
{
     int currX = getX(); //get current x co-ordinate
     int currY = getY(); // get current y co-ordinate
      
     getWorld().addObject(new SnakeBody(), currX-offsetX, currY-offsetY); //add SnakeBody at location of SnakeHead
This is the SnakeBody
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.List; // import java for lists
 
/**
 * Write a description of class SnakeBody here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class SnakeBody  extends Actor
{
    public int offsetX = 0; //global variable storing the random X direction (0)
    public int offsetY = 0; //global variable storing the random Y direction (0)
   
    public void act()
    {
         growSnake();
         move();
    }   
     
     
    private void growSnake()
    {
         int offsetX=0;
         int offsetY=0;
          
         int currX = getX(); //get current x co-ordinate
         int currY = getY(); // get current y co-ordinate
          
         List getSnakeHead=getWorld().getObjects(SnakeHead.class); //get the SnakeHead actor from the world.
         if(!getSnakeHead.isEmpty  ()) //if there is no SnakeHead
         {
            SnakeHead thisSnakeHead=(SnakeHead)getSnakeHead.get(0); //is there a SnakeHead in the current location?
            offsetX=thisSnakeHead.offsetX; //the x co-ordinate of SnakeHead
            offsetY=thisSnakeHead.offsetY; //the y co-ordinate of SnakeHead
        }
        setLocation(currX+offsetX, currY+offsetY); //
    }
     
     private void move() //
    {
         int currX = getX(); //get current x co-ordinate
         int currY = getY(); // get current y co-ordinate
         if(canMove(currX + offsetX, currY + offsetY))
         setLocation(currX + offsetX, currY + offsetY); //if the snake can move it will move in a direction
    }
     
      boolean canMove(int x,int y)    
        {
        List foundWall = getWorld().getObjectsAt(x,y, Wall.class); //canMove is false if a Wall is found
        if(!foundWall.isEmpty  ())return false;   //if Wall found return false and stop otherwise continue
        
        List foundSnakeHead = getWorld().getObjectsAt(x,y, SnakeHead.class); //canMove is false if a SnakeHead is found
        if(!foundSnakeHead.isEmpty  ())return false;   //if SnakeHead found return false and stop otherwise continue
         
        List foundSnakeBody = getWorld().getObjectsAt(x,y, SnakeBody.class); //canMove is false if a SnakeBody is found
        if(!foundSnakeBody.isEmpty  ())return false;   //if SnakeBody found return false and stop otherwise continue
         
        return true;    //this must be at the end – if canMove got this far it didn't find any of the listed objects.
         
         
    }
}
The growSnake adds a segment behind the head but i want to add to the move function so that the segments follow each other but I dont understand arrarys. Could you please explain them and give me some suggestions? This is because your code looks correct however I do not really understand?
You need to login to post a reply.