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

2016/12/12

Create solid blocks (Jump n run)

JoGie_ JoGie_

2016/12/12

#
Hello, I am currently trying to programme a Jump n Run Game in Greenfot. Unfortunately I'm having problems with creating solid blocks. Currently I am using this code:
1
2
3
4
5
6
public boolean onGround()
{
    Actor above = getOneObjectAtOffset (0, 30, Block_solid.class);
    return above != null;
 
}
(30 is half the size of my image height). This code now only causes the actor to stay on top of the blocks. But how do I make all four sides of the block solid? Thanks in advance!
danpost danpost

2016/12/12

#
Instead of using 'getOneObjectAtOffset', use 'isTouching'. You can determine which side was approached by the direction that the actor moved.
Nosson1459 Nosson1459

2016/12/13

#
danpost wrote...
You can determine which side was approached by the direction that the actor moved
You told that to me once, but what if I'm moving up and right at the same time (
1
setLocation(getX()+5, getY()-5);
) then it's possible to hit the bottom or the left side of a block without knowing which side you hit (it could be the top of me hit the bottom of the block, or my right side hit the block's left).
danpost danpost

2016/12/13

#
Nosson1459 wrote...
danpost wrote...
You can determine which side was approached by the direction that the actor moved
You told that to me once, but what if I'm moving up and right at the same time (
1
setLocation(getX()+5, getY()-5);
) then it's possible to hit the bottom or the left side of a block without knowing which side you hit (it could be the top of me hit the bottom of the block, or my right side hit the block's left).
Separate the horizontal movement from the vertical movement:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// move horizontally
int dx = 5;
setLocation(getX()+dx, getY());
int dir = (int)Math.signum(dx);
while (isTouching(Block_solid.class)
{
    setLocation(getX()-dir, getY());
}
 
// move vertically
int dy = -5;
setLocation(getX(), getY()+dy);
int dir = (int)Math.signum(dy);
while (isTouching(Block_solid.class)
{
    setlocation(getX(), getY()-dir);
}
JoGie_ JoGie_

2016/12/13

#
danpost wrote...
Separate the horizontal movement from the vertical movement: // move horizontally int dx = 5; setLocation(getX()+dx, getY()); int dir = (int)Math.signum(dx); while (isTouching(Block_solid.class) { setLocation(getX()-dir, getY()); } // move vertically int dy = -5; setLocation(getX(), getY()+dy); int dir = (int)Math.signum(dy); while (isTouching(Block_solid.class) { setlocation(getX(), getY()-dir); }
I tried using your code as an example for my moveRight() method, but when the actor is standing on the solid blocks, he is unable to move
1
2
3
4
5
6
7
8
9
10
11
12
13
public void moveRight()
{
    //setLocation ( getX() + speed, getY() );
     
    // move horizontally
    int dx = 5;
    setLocation(getX()+dx, getY());
    int dir = (int)Math.signum(dx);
    while (isTouching(Block_solid.class))
    {
        setLocation(getX()-dir, getY());
     }
}
While this code works fine
1
2
3
4
public void moveLeft()
{
    setLocation ( getX() - speed, getY() );
}
What's the problem here? Thanks!
JoGie_ JoGie_

2016/12/13

#
And also I'm not quite sure how I replace my boolean onGround()
1
2
3
4
5
6
7
public boolean onGround()
{
 
            Actor above = getOneObjectAtOffset (0, 30, Block_solid.class);
            return above != null;
         
}
with the "isTouching" method. I'd also need some help here :3
danpost danpost

2016/12/13

#
JoGie_ wrote...
And also I'm not quite sure how I replace my boolean onGround()
1
2
3
4
5
6
7
public boolean onGround()
{
 
            Actor above = getOneObjectAtOffset (0, 30, Block_solid.class);
            return above != null;
         
}
with the "isTouching" method. I'd also need some help here :3
Actually, you can remove that method. Set a local variable for the on-ground state before the vertical movement code to false. Accelerate and move. If found moving down and finding obstacle, set it to true. Place your jumping code after the vertical movement code (where the on-ground state is known). Basically, it would be something like this:
1
2
3
4
5
6
7
8
9
10
11
12
// vertical movement
boolean onGround = false;
vSpeed += gravity;
setLocation(getX(), getY()+vSpeed);
int direction = (int)Math.signum(vSpeed);
while (isTouching(Block_solid.class))
{
    setLocation(getX(), getY()-direction);
    if (vSpeed > 0) onGround = true;
    vSpeed = 0;
}
if (onGround && Greenfoot.isKeyDown("up")) jump();
JoGie_ JoGie_

2016/12/13

#
Hi, thanks for the code. I've actually been trying to implement it as best as I could, but it doesn't seem to work for me, as the actor doesn't perform a jump but is rather "teleportet" on a block when he "collides" with it. I'm actually kind of desperate because I have to hand this school project in and it just doesn't seem work.. Can you spot any errors in this class? Thank you so much!
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
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
/**
 * Write a description of class Ojekte here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class Player extends Actor
{    /**
     * Act - do whatever the PeterP wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
       private int speed = 3; //speed (seitlich/sideways)
       private int vSpeed = 0; //speed (Fallend/falling)
       private int FallAcceleration = 2; //Fallbeschleunigung
       private int jumpStrength = 20; //Sprungstärke
        
       public void act()
       {
            
       }                   
         
        public void jump()
        {
            vSpeed = -jumpStrength;
            fall();
        }
         
      //  public void checkFall()
      //  {
      //      if(onGround())
       //     {
       //         vSpeed = 0;
        //    }
        //    else
        //    {
       //         fall();
       //     }
      //  }
                    
         
       public void fall()
       {
           setLocation ( getX(), getY() + vSpeed );
           vSpeed = vSpeed + FallAcceleration;
       }
         
       public void moveRight()
       {
           //Working movement code: setLocation ( getX() + speed, getY() );
            
           // vertical movement
           boolean onGround = false;
           vSpeed += FallAcceleration;
           setLocation(getX() +speed, getY() );
           int direction = (int)Math.signum(speed);
           while (isTouching(Block_solid.class))
           {
               setLocation(getX(), getY()-direction);
               if (vSpeed > 0) onGround = true;
                       vSpeed = 0;
                    }
                    if (onGround && Greenfoot.isKeyDown("w")) jump();
       }
        
       public void moveLeft()
       {
           //Working movement code: setLocation ( getX() - speed, getY() );
            
                      // vertical movement
           boolean onGround = false;
           vSpeed += FallAcceleration;
           setLocation(getX() -speed, getY() );
           int direction = (int)Math.signum(speed);
           while (isTouching(Block_solid.class))
           {
               setLocation(getX(), getY()-direction);
               if (vSpeed > 0) onGround = true;
                       vSpeed = 0;
                    }
                    if (onGround && Greenfoot.isKeyDown("w")) jump();
       }
}
danpost danpost

2016/12/13

#
Why do you have vertical movement code in the moveLeft and moverRight method (vSpeed should not be mentioned in either of these classes)? and you do not have anything at all in the act method. You only need call two methods from the act method, one to move horizontally and one to move vertically. You have a horizontal speed for the player and two methods to move left and right (before you ruined them with excess code), but I do not see any control for moving sideways. What is supposed to direct the horizontal movement of the actor? To start: * remove lines 54 and 55 * remove lines 61 through 64 * remove lines 72 and 73 * remove lines 79 through 82 * add the vertical movement code to the fall method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void fall()
{
    boolean onGround = false;
    vSpeed += FallAcceleration;
    setLocation(getX(), getY()+vSpeed);
    int direction = (int)Math.signum(vSpeed);
    while (isTouching(Block_solid.class))
    {
        setLocation(getX(), getY()-direction);
        if (vSpeed > 0) onGround = true;
        vSpeed = 0;
    }
    if (onGround && Greenfoot.isKeyDown("w")) vSpeed = -jumpStrength;
}
* remove lines 24 through 41 * add method calls to the act method
1
2
3
4
5
6
7
public void act()
{
    int dx = < determine direction to move (left=-1, right=1 and none=0) >;  // code unknown for your project (you decide)
    if (dx > 0) moveRight();
    if (dx < 0) moveLeft();
    fall();
}
JoGie_ JoGie_

2016/12/14

#
Hi, I've just made the changes to the source code. Left/Right Movement works, but jumping & gravity doesn't work. The actor gets teleportet on it when he hits a block and stays on that level when you move him left/right. What could be the problem?
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
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
 
/**
 * Write a description of class Ojekte here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class Player extends Actor
{    /**
     * Act - do whatever the PeterP wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
       private int speed = 3; //speed (seitlich/sideways)
       private int vSpeed = 0; //speed (Fallend/falling)
       private int FallAcceleration = 2; //Fallbeschleunigung
       private int jumpStrength = 20; //Sprungstärke
        
       public void act()
       {
               int dx = 0 ; //determine direction to move (left=-1, right=1 and none=0) >;  // code unknown for your project (you decide)
               if (dx > 0) moveRight();
               if (dx < 0) moveLeft();
               fall();
       }                                       
         
       public void fall()
       {
              boolean onGround = false;
              vSpeed += FallAcceleration;
              setLocation(getX(), getY()+vSpeed);
              int direction = (int)Math.signum(vSpeed);
              while (isTouching(Block_solid.class))
              {
                setLocation(getX(), getY()-direction);
                if (vSpeed > 0) onGround = true;
                vSpeed = 0;
              }
              if (onGround && Greenfoot.isKeyDown("w")) vSpeed = -jumpStrength;
       }
         
       public void moveRight()
       {
           //Working movement code: setLocation ( getX() + speed, getY() );
            
           // vertical movement
           setLocation(getX() + speed, getY() );
           int direction = (int)Math.signum(speed);
           while (isTouching(Block_solid.class))
           {
               setLocation(getX(), getY()-direction);            
           }
          }
           
        
       public void moveLeft()
       {
           //Working movement code: setLocation ( getX() - speed, getY() );
            
                      // vertical movement
           setLocation(getX() - speed, getY() );
           int direction = (int)Math.signum(speed);
           while (isTouching(Block_solid.class))
           {
               setLocation(getX(), getY()-direction);
           }
       }
      }     
//EDIT The problem was that I forgot to add fall(); to the act class of my actor itself - the jumping and falling is now working, but the actor gets nevertheless teleportet, when he hits a block/obstacle. I don't know what's the problem here.
danpost danpost

2016/12/14

#
I can see a problem with the left/right code; but, I do not see anything wrong with the vertical movement code. Gravity should work as well as stopping outside the edges of Block_solid objects. The problem with left/right is that the direction is already known. Replace the following methods:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void moveRight()
{
    setLocation(getX()+speed, getY());
    while(isTouching(Block_solid.class))
    {
        setLocation(getX()-1, getY());
    }
}
 
public void moveLeft()
{
    setLocation(getX()-speed, getY());
    while(isTouching(Block_solid.class))
    {
        setLocation(getX()+1, getY());
    }
}
This change may just fix your issue mentioned in the last post.
JoGie_ JoGie_

2016/12/14

#
Thank you so much! This just fixed the problem. :)
You need to login to post a reply.