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

2021/2/7

Collision detection

Vitalka Vitalka

2021/2/7

#
Hello, I want to program Geometry Dash, but I Have an issue with the collision detection with a Stone. The Character can be on top of a Stone without dying, but when he hit the Stone from the bottom of the left he has to die
import greenfoot.*;

/**
 * Write a description of class FigurEng here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class FigurEng extends Actor
{

    private int Gravity=1; //Variable
    private int FallSpeed; // variable
    public FigurEng() //constructor
    {
        this(45,45);
        FallSpeed = 3; 
    }

    public FigurEng(int width, int height) //image scaling    
    { GreenfootImage image = getImage();
        image.scale(width, height);
        setImage(image);
    }

    public void act() 
    {
        fall();
        jump();
        rotate();
        die();
    }    

    public boolean onSolidGround() //query whether figure is on a block(see below) or on the ground.
    {
        boolean onSolidGround = false;
        if(getY() > getWorld().getHeight() - 108 || onStone())
            onSolidGround= true;
        return onSolidGround;
    }

    public boolean onStone() //query whether figure is on a stone
    {
        int figureWidth = getImage().getWidth();
        int figureHeight = getImage().getHeight();
        boolean onStone = false;  
        if(getOneObjectAtOffset(figureWidth / -2, figureHeight / 2, Stein.class) !=null || 
        getOneObjectAtOffset(figureWidth / 2, figureHeight / 2, Stein.class) !=null) //When the figure touches the stone with the lower right or left edge, onStone is set true 
            onStone = true;
        return onStone;
    }

    public void fall() 
    {
        setLocation(getX(),getY() + FallSpeed);// When falling X stays the same only Y changes with FallSpeed 
        if(onSolidGround())// If on a solid block (stone or ground) the figure should not fall anymore 
        { FallSpeed = 0;
          while(onSolidGround())// method prevents the figure from being on a stone or the ground by corralling the figure upwards until the figure is in the air. 
          {
                setLocation(getX(), getY() - 1); 
          } 
            setLocation(getX(), getY() + 1);//Here the figure is placed back on the stone. 
        }    
        else FallSpeed += Gravity;//When in the air, the FallSpeed accelerates with gravity, each time the act method is executed. 
    }

    public void jump()//Figure can jump if it is not in the air } 
    {
        if(Greenfoot.isKeyDown("space") && onSolidGround())
            FallSpeed = -15; 
    }

    public void rotate()
    {
        if(!onSolidGround())//When not on solid block, it will turn 6 degrees each time the act method is run
            turn(6);
        if(onSolidGround()) //When on solid block, it should straighten (see below)
            straighten();
    }

    public void straighten() { //rotation correction that changes the rotation of the figure. 
        if (getRotation()< 45 && getRotation() >=315) {
            setRotation(0);
        } else
        if (getRotation()< 135 && getRotation() >=45) {
            setRotation(90);
        } else
        if (getRotation() >=135 && getRotation() < 225) {
            setRotation(180);
        } else
        if (getRotation() < 315 && getRotation() >=225) {
            setRotation(270);
        } else {
            setRotation(0);
        }
    }

    public boolean underStone()//query whether the figure has touched the stone with one of the upper corners. 
    {
        int FigureWidth = getImage().getWidth();
        int figureHeight = getImage().getHeight();
        boolean underStone = false;  
        if(getOneObjectAtOffset(FigureWidth / -2, figureHeight / -2, Stein.class) !=null || 
        getOneObjectAtOffset(FigureWidth / 2, figureHeight / -2, Stein.class) !=null) //When the figure touches the stone with the upper right or left edge, stone is set to true and returned
            underStone = true;
        return underStone;
    }

    public void die()//The figure should die if it touches an obstacle or a stone from below. Then the level is reset. 
    {
        if(isTouching(Dreiecke.class) || isTouching(Stacheln.class) || isTouching(kleinesDreieck.class))
            Greenfoot.setWorld(new Level1());
        else if(underStone())
            Greenfoot.setWorld(new Level1());
    }

}

The problem is that the Character teleports on top of the Stone (Where he doesn't die ), because of the while loop in line 58. This loop is important so that the Character cant be "inside" or overcut with the Stone. Also, it's important because sometimes the Character kinda bugged into the Ground, but this while loop prevents this problem. I need a method where the Character is checking if he is touching a stone on his right edge, but I didn't quite get a good solution. Here is the Stone class
public class Stein extends Block
{

    public Stein()
    {
        this(45,45);
    }

    public Stein(int Breite, int Höhe)//Bildskalierung
    {
        GreenfootImage image = getImage();
        image.scale(Breite, Höhe);
        setImage(image);
    }

    public void act() 
    {
        move(-6);
        if(getX() == 0)
            getWorld().removeObject(this);
    }

}
danpost danpost

2021/2/7

#
I am not a fan of the approach you have chosen to code the behavior of FigurEng objects. The many different collision checks make it quite complicated. On top of that, having them actually touching a stone when "on" one (see line 62) actually complicates things even more. I prefer maintaining separation from all objects and, after moving, using the direction of movement to dictate where contact was made with a colliding object. That is, if FallSpeed is negative, then any object would be above it and if it is positive, then below ("on ground" state can be determined here, as well). I presume horizontal motion is created using continuous scrolling to the left, done by your World object. With that, I would, at first in FigurEng act method, check if touching anything. If so, then it must be on the right (from scrolling) and level would need restarted. For example code, at least for vertical movement, please refer to the Who class codes of my Jump and Run Demo w/Moving Platform scenario.
You need to login to post a reply.