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

2019/7/2

Jumping

1
2
3
danpost danpost

2019/7/12

#
¿ques♫ wrote...
I tried this, but it doesnt seem to work: << Code Omitted >> I added the else ifs ^ above to prevent Mario from teleporting to the top of objects but this doesn't work.
You should not have to do anything extra to prevent that. Please show all your horizontal movement codes.
¿ques♫ ¿ques♫

2019/7/13

#
Mario class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Mario here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Mario extends Actor
{
    static final int gravity = 2;                   //force of gravity
    static final int jumpAbility = 30;              //the jumping ability of Mario (high he can reach)
    int ySpeed = 0;                                 //the vertical speed of Mario
    boolean onPlatform;                               //checks if Mario is standing on the ground on a platform
    int groundLocation = 655;                       //y-location of top of ground
    /**
     * Greenfoot cycles through the act method at a speed of approximately 60 frames per second.
     * Custom methods and code that need to be constantly checked should be placed here.
     */
    public void act() 
    {
        moveVertically();       //call custom method
        moveHorizontally();     //call custom method
    } 

    public void moveHorizontally() {
        if (Greenfoot.isKeyDown("left")) {
            this.setLocation(this.getX() - 5, this.getY());
        }
        if (Greenfoot.isKeyDown("right")) {
            this.setLocation(this.getX() + 5, this.getY());
        }
    }

    /**
     * Responsible for the vertical movement of Mario,
     * Involving jumping, falling, and platform detection
     */
    public void moveVertically() {
        int worldHeight = getWorld().getHeight();
        int marioHeight = getImage().getHeight();
        boolean onPlatform = false;                         //originally, Mario is in the air

        ySpeed += gravity;                                  //represents acceleration, updates vertical speed accordingly
        setLocation(getX(), getY() + ySpeed);               //updates Mario's location based on vertical speed

        //if Mario is on the ground
        if (getY() > groundLocation) {
            setLocation(getX(), groundLocation);
            ySpeed = 0;
            onPlatform = true;
        }

        //if Mario is on a pipe
        Actor a = getOneIntersectingObject(Actor.class);
        if (a != null) {
            if (this.getY() + this.getImage().getHeight()/2 > a.getY() - a.getImage().getHeight()/2) {
                setLocation(this.getX(), a.getY() - a.getImage().getHeight()/2 - this.getImage().getHeight()/2);
                ySpeed = 0;
                onPlatform = true;
            }
        }

        //if Mario is on top of a platform or the ground and the space bar is pressed, enable jumping
        if (onPlatform && Greenfoot.isKeyDown("space")) ySpeed = -jumpAbility;
    }
}
Here is a link of a video displaying my issue: Mario game The method "moveHorizontally" only contains code that moves Mario which in turn scrolls the screen. I have tried to fix my problem of Mario teleporting to the top of objects when intersecting, but I think it is due to the line
this.getY() + this.getImage().getHeight()/2 > a.getY() - a.getImage().getHeight()/2
because this tests if the y-location of the bottom of Mario becomes more than the top of an object (since y = 0 at the top edge). Thanks for your help so far, I apologize for prolonging this discussion.
danpost danpost

2019/7/13

#
You still need separate collision detection for when moving horizontally (put in the moveHorizontally method).
¿ques♫ ¿ques♫

2019/7/15

#
    public void moveHorizontally() {
        /*Actor a = getOneIntersectingObject(Actor.class);
        if (a != null) {
            if (this.getX() + this.getImage().getWidth()/2 > a.getX() - a.getImage().getWidth()/2) {             //doesnt work
                setLocation(a.getX() - a.getImage().getWidth()/2 - this.getImage().getWidth()/2, this.getY());
            } else if (this.getX() - this.getImage().getWidth()/2 < a.getX() + a.getImage().getWidth()/2) {             //doesnt work
                setLocation(a.getX() + a.getImage().getWidth()/2 + this.getImage().getWidth()/2, this.getY());
            }
        }*/

        if (Greenfoot.isKeyDown("left")) {
            this.setLocation(this.getX() - 5, this.getY());
        }
        if (Greenfoot.isKeyDown("right")) {
            this.setLocation(this.getX() + 5, this.getY());
        }
    }
This doesnt seem to work...but I think it is because of this line: "this.getY() + this.getImage().getHeight()/2 > a.getY() - a.getImage().getHeight()/2" as whenever Mario's boot becomes less than the top of the pipe the location is set to the top of the pipe. This is why I originally put else ifs in that section of the code because Mario can't be intersecting more than one side of the pipe. But this did not work either.
danpost danpost

2019/7/15

#
Move first; then check for obstacles. Move back according to direction moved:
int dx = 0;
if (Greenfoot.isKeyDown("left")) dx--;
if (Greenfoot.isKeyDown("right")) dx++;
if (dx == 0) return;
setLocation(getX()+dx*5, getY());
Actor a = getOneIntersectingObject(Actor.class);
if (a == null) return;
setLocation(a.getX()-dx*(getImage().getWidth()+a.getImage().getWidth())/2+1), getY());
¿ques♫ ¿ques♫

2019/7/15

#
Tried this ^, only works on the right side. Also, you seem to have accidentally put an extra bracket after the +1. This is my current code for the moveHorizontally() method:
    public void moveHorizontally() {
        int dx = 0;
        if (Greenfoot.isKeyDown("left")) dx--;
        if (Greenfoot.isKeyDown("right")) dx++;
        if (dx == 0) return;
        setLocation(getX()+dx*5, getY());
        Actor a = getOneIntersectingObject(Actor.class);
        if (a == null) return;
        setLocation(a.getX()-dx*(getImage().getWidth()+a.getImage().getWidth())/2+1, getY());

        /*if (Greenfoot.isKeyDown("left")) {
        this.setLocation(this.getX() - 5, this.getY());
        }
        if (Greenfoot.isKeyDown("right")) {
        this.setLocation(this.getX() + 5, this.getY());
        }*/
    }
Video demonstration: Mario game
danpost danpost

2019/7/15

#
¿ques♫ wrote...
Tried this ^, only works on the right side. Also, you seem to have accidentally put an extra bracket after the +1.
Well -- no. I have accidentally missed placing the bracket that was to pair with that "extra" bracket. Try:
setLocation(a.getX()-dx*((getImage().getWidth()+a.getImage().getWidth())/2+1), getY());
¿ques♫ ¿ques♫

2019/7/15

#
Thanks, this works really well. Should I use the dy strategy for collision detection under objects? I am trying to modify the moveVertically() method so that if Mario jumps and hits an object above him, he bounces off of it and comes back down. Do you have any suggestions on how to do this, or can I find answers in your "Jump and Run Demo w/Moving Platform" demo?
danpost danpost

2019/7/15

#
¿ques♫ wrote...
Thanks, this works really well. Should I use the dy strategy for collision detection under objects? I am trying to modify the moveVertically() method so that if Mario jumps and hits an object above him, he bounces off of it and comes back down. Do you have any suggestions on how to do this, or can I find answers in your "Jump and Run Demo w/Moving Platform" demo?
Yes. You will find the answers there. It is the part labelled:
//check for and move back off any obstacles
in the moveVertically method.
¿ques♫ ¿ques♫

2019/7/16

#
I tried to fix this problem by looking where you said, but did not change anything. Here is my current code for my Mario class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Mario here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Mario extends Actor
{
    static final int gravity = 2;                   //force of gravity
    static final int jumpAbility = 30;              //the jumping ability of Mario (high he can reach)
    int ySpeed = 0;                                 //the vertical speed of Mario
    boolean onPlatform;                               //checks if Mario is standing on the ground on a platform
    int groundLocation = 655;                       //y-location of top of ground
    /**
     * Greenfoot cycles through the act method at a speed of approximately 60 frames per second.
     * Custom methods and code that need to be constantly checked should be placed here.
     */
    public void act() 
    {
        moveVertically();       //call custom method
        moveHorizontally();     //call custom method
    } 

    public void moveHorizontally() {
        int dx = 0;
        if (Greenfoot.isKeyDown("left")) dx--;
        if (Greenfoot.isKeyDown("right")) dx++;
        if (dx == 0) return;
        setLocation(getX()+dx*5, getY());
        Actor a = getOneIntersectingObject(Pipe.class);
        if (a == null) return;
        setLocation(a.getX()-dx*((getImage().getWidth()+a.getImage().getWidth())/2+1), getY());

        /*if (Greenfoot.isKeyDown("left")) {
        this.setLocation(this.getX() - 5, this.getY());
        }
        if (Greenfoot.isKeyDown("right")) {
        this.setLocation(this.getX() + 5, this.getY());
        }*/
    }

    /**
     * Responsible for the vertical movement of Mario,
     * Involving jumping, falling, and platform detection
     */
    public void moveVertically() {
        int worldHeight = getWorld().getHeight();
        int marioHeight = getImage().getHeight();
        boolean onPlatform = false;                         //originally, Mario is in the air

        ySpeed += gravity;                                  //represents acceleration, updates vertical speed accordingly
        setLocation(getX(), getY() + ySpeed);               //updates Mario's location based on vertical speed

        //if Mario is on the ground
        if (getY() > groundLocation) {
            setLocation(getX(), groundLocation);
            ySpeed = 0;
            onPlatform = true;
        }

        //if Mario is on a pipe
        Actor a = getOneIntersectingObject(Pipe.class);
        if (a != null) {
            if (this.getY() + this.getImage().getHeight()/2 > a.getY() - a.getImage().getHeight()/2) {
                setLocation(this.getX(), a.getY() - a.getImage().getHeight()/2 - this.getImage().getHeight()/2);
                ySpeed = 0;
                onPlatform = true;
            }
        }
        
        /*int dy = (int)Math.signum(ySpeed);
        while (getOneIntersectingObject(null) != null) {            //doesnt change anything but causes collision detection with clouds (dont want)
            setLocation(getX(), getY()-dy);
            if(dy>0) onPlatform = true;
            ySpeed = 0;
        }*/
        
        //if Mario is on top of a platform or the ground and the space bar is pressed, enable jumping
        if (onPlatform && Greenfoot.isKeyDown("space")) ySpeed = -jumpAbility;
    }
}
Video demonstration: Mario game
danpost danpost

2019/7/17

#
Lines 66 and 67 need work. Replace lines 66 thru 70 with the following:
int dy = (int)Math.signum(ySpeed);
setLocation(getX(), a.getY()-dy*((a.getImage().getHeight()+getImage().getHeight())/2+1));
if (dy > 0) onPlatform = true;
ySpeed = 0;
¿ques♫ ¿ques♫

2019/7/17

#
Great, that works! Couple questions although: 1) In my code where I use "getOneIntersectingObject", it noticed that it didn't matter whether I used Actor.class or Pipe.class as the parameter. But when I use Actor.class, collision detection with the clouds in the background occur. I don't want this to happen, so when I say "Actor.class", can I put exceptions, and if yes, where? Otherwise if I use Pipe.class, I will need to paste the same code for the rest of the objects that I want Mario to interact with. 2) I am not very familiar with classes in Greenfoot that are not subclasses of the World class or the Actor class, so how do these separate classes work? 3) To finish the core base of my game, I have yet sprites to finish. Do you have your own sprite demo or suggestions to accomplish this? 4) After I finish this game, I want to make this exact same game in a different IDE called IntelliJ, but the only Java knowledge I have is with Greenfoot. If I wanted to make the exact same game in IntelliJ, would the code be different, and if yes, what would those differences be? Also is there a website or YouTube videos you can reference me to so I game make this Mario game in IntelliJ?
Super_Hippo Super_Hippo

2019/7/17

#
1+2) The parameter is the class to search for. It will look for objects of the given class and all its subclasses. So you could have a superclass for all those classes Mario can interact with (all those classes extend this new superclass instead of Actor directly while the new superclass extends Actor). Or you can create a method which uses several classes as the parameter and then you call the getOneIntersectingObject method on all of them until one is found.
¿ques♫ ¿ques♫

2019/7/17

#
Edit to 1), it is the line "getOneIntersectingObject(null) != null" in my Mario class that causes this. Is there any way to edit this line so that interaction with clouds is not possible? Updated Mario class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Mario here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Mario extends Actor
{
    static final int gravity = 2;                   //force of gravity
    static final int jumpAbility = 30;              //the jumping ability of Mario (high he can reach)
    int ySpeed = 0;                                 //the vertical speed of Mario
    boolean onPlatform;                               //checks if Mario is standing on the ground on a platform
    int groundLocation = 655;                       //y-location of top of ground
    /**
     * Greenfoot cycles through the act method at a speed of approximately 60 frames per second.
     * Custom methods and code that need to be constantly checked should be placed here.
     */
    public void act() 
    {
        moveVertically();       //call custom method
        moveHorizontally();     //call custom method
    } 

    public void moveHorizontally() {
        int dx = 0;
        if (Greenfoot.isKeyDown("left")) dx--;
        if (Greenfoot.isKeyDown("right")) dx++;
        if (dx == 0) return;
        setLocation(getX()+dx*5, getY());
        Actor a = getOneIntersectingObject(Pipe.class);
        if (a == null) return;
        setLocation(a.getX()-dx*((getImage().getWidth()+a.getImage().getWidth())/2+1), getY());

        /*if (Greenfoot.isKeyDown("left")) {
        this.setLocation(this.getX() - 5, this.getY());
        }
        if (Greenfoot.isKeyDown("right")) {
        this.setLocation(this.getX() + 5, this.getY());
        }*/
    }

    /**
     * Responsible for the vertical movement of Mario,
     * Involving jumping, falling, and platform detection
     */
    public void moveVertically() {
        int worldHeight = getWorld().getHeight();
        int marioHeight = getImage().getHeight();
        boolean onPlatform = false;                         //originally, Mario is in the air

        ySpeed += gravity;                                  //represents acceleration, updates vertical speed accordingly
        setLocation(getX(), getY() + ySpeed);               //updates Mario's location based on vertical speed

        //if Mario is on the ground
        if (getY() > groundLocation) {
            setLocation(getX(), groundLocation);
            ySpeed = 0;
            onPlatform = true;
        }

        //if Mario is on a pipe
        Actor a = getOneIntersectingObject(Pipe.class);
        if (a != null) {
            int dy = (int)Math.signum(ySpeed);
            setLocation(getX(), a.getY()-dy*((a.getImage().getHeight()+getImage().getHeight())/2+1));
            if (dy > 0) onPlatform = true;
            ySpeed = 0;
        }

        int dy = (int)Math.signum(ySpeed);
        while (getOneIntersectingObject(null) != null) {            //causes collision detection with clouds (dont want)
            setLocation(getX(), getY()-dy);
            if(dy>0) onPlatform = true;
            ySpeed = 0;
        }

        //if Mario is on top of a platform or the ground and the space bar is pressed, enable jumping
        if (onPlatform && Greenfoot.isKeyDown("space")) ySpeed = -jumpAbility;
    }
}
danpost danpost

2019/7/17

#
¿ques♫ wrote...
Edit to 1), it is the line "getOneIntersectingObject(null) != null" in my Mario class that causes this. Is there any way to edit this line so that interaction with clouds is not possible? << Code Omitted >>
Best would be to do what Hippo suggested. That is, create an Obstacle class extending Actor and have Pipe and other classes creating obstacles extend it. Then use Obstacle.class in the getOneInterectingObject line.
There are more replies on the next page.
1
2
3