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

2023/5/18

Trying to get the physics in my platformer right

1
2
Nextonic Nextonic

2023/5/18

#
I need help figuring out how to tell if my actor hit the bottom of the Ground Class as well as the sides. I'd appreciate some help! public class character extends Actor { public double vSpeed = 0; public double acc = .6; public int jumps = -15; public int Left = -4; public int Right = 4; public void isFalling() { if(onGround() == false) { Gravity(); } if(onTop() == true) { vSpeed += (-1*vSpeed + 4); } if(onGround() == true) { vSpeed = 0; } } public void Jump() { if(Greenfoot.isKeyDown("Up") && onGround() == true) { vSpeed = jumps; Gravity(); } } public void Gravity() { setLocation(getX(),getY() + (int)vSpeed); vSpeed += acc; } public void moving() { if(Greenfoot.isKeyDown("Right")) { if(onGround() == false) { move(Right); } else { move(Right); } } if(Greenfoot.isKeyDown("Left")) { if(onGround() == false) { move(Left); } else { move(Left); } } } public boolean onGround() { Actor under = getOneObjectAtOffset(0,getImage().getHeight()/2,Ground.class); return under != null; } public boolean onLeft() { Actor isLeft = getOneObjectAtOffset(0,getImage().getWidth()/2,Ground.class); return isLeft != null; } public boolean onRight() { Actor isRight = getOneObjectAtOffset(0,getImage().getWidth()*2,Ground.class); return isRight != null; } public boolean onTop() { Actor isTop = getOneObjectAtOffset(0,getImage().getHeight()*2,Ground.class); return isTop != null; } public void act() { Jump(); moving(); isFalling(); } }
Nextonic Nextonic

2023/5/18

#
The Problem is with the onLeft(), onRight(), onTop()
danpost danpost

2023/5/18

#
Nextonic wrote...
The Problem is with the onLeft(), onRight(), onTop()
There are more problems than that. Those methods only lets the calling method know whether a Ground object has been touched. It does not allow the calling method any more information than that; that is, which Ground object was touched. This is important if you want to move the actor so it is not overlapping the object. Also, to move the object as such, the calling method needs to know the direction it was moved to begin with. I have found it best to do things in the following order: (1) move horizontally; then check for "hitting" ground (if so, move back) off; (2) move vertically (add gravity, and fall); then check for "hitting" ground; if so, move back off and check jumping If jumping, the vertical speed must be set to jump speed, otherwise set to zero. It would look something like this:
final int jumps = -15;
final double acc = 0.6;
final int hSpeed = 4;

double vSpeed;

public void act() {
    moveHorizontally();
    moveVertically();
}

private void moveHorizontally() {
    int dx = 0;
    if (Greenfoot.isKeyDown("right")) dx++;
    if (Greenfoot.isKeyDown("left")) dx--;
    move(dx*hSpeed);
    Actor ground = getOneIntersectingObject(Ground class);
    if (ground == null) return;
    while (intersects(ground)) move(-dx);
}

private void moveVertically() {
    vSpeed += acc;
    setLocation(getX(), getY()+vSpeed);
    Actor ground = getOneIntersectingObject(Ground.class);
    if (ground != null) {
        while (intersects(ground)) setLocation(getX(), getY()-Math.signum(vSpeed));
        vSpeed = vSpeed > 0 && Greenfoot.isKeyDown("up") ? jumps : 0;
    }
}
danpost danpost

2023/5/18

#
Although it may not amount to much of a difference, the adding of a fractional value to the vertical speed does lose a little bit of accuracy when moving, as the fractional part will be ignored. This is because the location is stored as an int value in the Actor class. This can be fixed by retaining the exact value in your class:
// additions
double exactY;

protected void addedToWorld(World world) {
    exactY = getY();
}

// change
private void moveVertically() {
    vSpeed += acc;
    exactY += vSpeed;
    setLocation(getX(), (int)exactY);
    Actor ground = getOneIntersectingObject(Ground.class);
    if (ground != null) {
        while (intersects(ground)) setLocation(getX(), getY()-Math.signum(vSpeed));
        exactY = getY();
        vSpeed = vSpeed > 0 && Greenfoot.isKeyDown("up") ? jumps : 0;
    }
}
Nextonic Nextonic

2023/5/19

#
Just a quick question on understanding this, could you explain the moveVertically() class? I just dont understand it specifically the "vSpeed = vSpeed > 0 && Greenfoot.isKeyDown("up") ? jumps : 0;" It doesn't work as well but I might have implemented it wrong
danpost danpost

2023/5/19

#
Nextonic wrote...
Just a quick question on understanding this, could you explain the moveVertically() class? I just dont understand it specifically the "vSpeed = vSpeed > 0 && Greenfoot.isKeyDown("up") ? jumps : 0;" It doesn't work as well but I might have implemented it wrong
That line of code basically assigns a value to vSpeed depending on the conditions that the vertical speed is positive, meaning the actor was going downward (landing or maintaining ground level) and the "up" key is being pressed. If both conditions are true, then the actor jumps, otherwise the vertical speed of the actor becomes zero. The actor has already been determined to have "hit" some ground vertically, so, since it was falling, the ground must have been below the actor; hence, it is "on ground" and "jump enabled". As far as "doesn't work as well", how so? What does or doesn't it do that is not wanted AND how do you want what is wanted to occur?
danpost danpost

2023/5/19

#
This might be easier for you (remember, the actor has already been determined to have hit something while moving vertically; so, it did one of 3 things: bops its head, landed on ground, or is maintaining an "on ground" state):
boolean onGround = vSpeed > 0;
boolean wantsToJump  = Greenfoot.isKeyDown("up");
if (onGround && wantsToJump) {
    vSpeed = jumps;
}
else {
    vSpeed = 0;
}
This does the exact same as the one liner being discussed.
Nextonic Nextonic

2023/5/19

#
This is amazing! thank you so much. It was fun reading and understanding this. I want to ask you though. I don't know if its greenfoot or not, but the ground class objects boundaries on the left and right are a little bigger than the picture.
danpost danpost

2023/5/19

#
Nextonic wrote...
This is amazing! thank you so much. It was fun reading and understanding this. I want to ask you though. I don't know if its greenfoot or not, but the ground class objects boundaries on the left and right are a little bigger than the picture.
You can use my Image Transparency Adder/Trimmer scenario to remove the unwanted excess edges. Download it and open it in greenfoot. You can use it directly in greenfoot or use your file directory system to extract the executable jar file included with the project. Just load the image and then simply save it. The excess transparency will automatically be removed.
Nextonic Nextonic

2023/5/19

#
when i load it keeps saying failed to load as well as the saved. Is it bugged atm? Or did I not use it correctly
danpost danpost

2023/5/19

#
Nextonic wrote...
when i load it keeps saying failed to load as well as the saved. Is it bugged atm? Or did I not use it correctly
You may have to use the executable jar file included in the project.
Nextonic Nextonic

2023/5/20

#
Completely unrelated question, but I'm using gifs to animate my character running. I keep getting a runtime exception and when I try to create a new world it keeps highlighting and bringing me to
/**
         * Reads GIF file from specified file/URL source (URL assumed if name contains
         * ":/" or "file:")
         * 
         * @param name
         *          String containing source
         * @return read status code (0 = no errors)
         */
        public int read(String name) {
            status = STATUS_OK;
            InputStream resource = this.getClass().getResourceAsStream(name);
            if (resource == null) {
                name = "images/" + name;
                resource = this.getClass().getResourceAsStream(name);
                if (resource == null) {
                    throw new RuntimeException("The gif file \"" + name + "\" doesn't exist.");
                }
            }
            in = new BufferedInputStream(resource);
            status = read(in);

            return status;
        }
its saying the file doesn't exist. I put the file in the image folder
danpost danpost

2023/5/21

#
Nextonic wrote...
Completely unrelated question, but I'm using gifs to animate my character running. I keep getting a runtime exception and when I try to create a new world it keeps highlighting and bringing me to << Code Omitted >> its saying the file doesn't exist. I put the file in the image folder
That is what the code made it say, but that may not be what is wrong. Try this:
public int read(String name) {
    status = STATUS_OK;`
    try {
        InputStream resource = this.getClass().getResourceAsStream(name);
        if (resource == null) {
            name = "images/" + name;
            resource = this.getClass().getResourceAsStream(name);
        }
        in = new BufferedInputStream(resource);
        status = read(in);
    }
    catch (java.lang.Exception e) {
        System.err.pringln(e.getMessage());
        Greenfoot.stop();
    }
    finally {
        if (in != null) in.close;
        if (resourse != null) resource.close();
    }
    return status;
}
That should give you the actual error.
Nextonic Nextonic

2023/5/21

#
i replaced the old read method, but it says pringln is not a declared method and resource is not a declared variable.
danpost danpost

2023/5/21

#
Nextonic wrote...
i replaced the old read method, but it says pringln is not a declared method and resource is not a declared variable.
Sorry, one was a typing error and should be "println", and as far as 'resource', it does not have scope to the finally clause (my bad). Try this:
public int read(String name) {
    status = STATUS_OK;`
    InputStream resource = null;
    try {
        resource = this.getClass().getResourceAsStream(name);
        if (resource == null) {
            name = "images/" + name;
            resource = this.getClass().getResourceAsStream(name);
        }
        in = new BufferedInputStream(resource);
        status = read(in);
    }
    catch (java.lang.Exception e) {
        System.err.println(e.getMessage());
        Greenfoot.stop();
    }
    finally {
        if (in != null) in.close;
        if (resourse != null) resource.close();
    }
    return status;
}
There are more replies on the next page.
1
2