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

2014/4/12

Coding a ramp?

1
2
Entity1037 Entity1037

2014/4/12

#
I would like to have ramps in my Megaman EX game, but I have no idea how to make it with my physics engine in mind. Could someone please help me? Here's my Physics Engine, Matter.class (the player is a subclass of Matter):
import greenfoot.*;

public class Matter extends SpriteSheet
{
    public void shadowImagery(boolean s){}
    
    /**Copy everything between this blue comment and the next one to apply
    physics to a class
    
                              Made by Entity1037
    */
    
    int xmove=0;
    int subymove=0;
    int subxmove=0;
    int ymove=0;
    int gravityTimeRateMax = 1; //Amount of cycles until speed increases
    int gravityTimeRate = gravityTimeRateMax;
    int frictionAmountMax = 2; //How many cycles until the object slows
    //down due to friction
    int xFrictionAmount=0;
    int yFrictoinAmount=0;
    String gravityDirection = "down";
    boolean gravity = true; //Just in case you want to switch gravity   ;D
    Class[] objects = {Base.class,SymbolBlock.class,/*Spike.class,SpikeSheet.class,*/BossDoor.class,Box.class,Ramp1.class,null}; //All objects that can be collided with
    
    public void gravity(boolean g){gravity=g;}
    public void gravityDirection(String d){gravityDirection = d;}
    boolean onGround = false;
    
    int xca = 0; //How much xmove changes (Example: "xmove=xca" where "xca=-xmove")
    int yca = 0; //How much ymove changes (Example: "ymove=yca" where "ycs=-ymove")
    /**
       This method must be called every cycle before "physics()" is called!!!
       Protip: place it in the "act()" method!
       Protip#2: If you would like, you can just call this method at the beginning of "physics()".-
       -This will make it the same speed altering values apply to all matter subclasses
    */
    public void setSpeedAlteringValues(int X, int Y){xca=X; yca=Y;} //Lets you set speed altering values
    
    
    int x=getImage().getWidth()/2; //Half of the width of the hitbox
    int y=getImage().getHeight()/2; //Half of the height of the hitbox
    public void setHitBoxHalfValues(int X, int Y){x=X; y=Y;} //Lets you set hit box dimensions
    public int getHitBoxXHalfValue(){return x;} //Allows you to obtain hit box values of actors in "Matter"
    public int getHitBoxYHalfValue(){return y;} //Allows you to obtain hit box values of actors in "Matter"
    
    int xSpeedLimit=9;//This is self explanitory (caps how fast subclasses of matter can travel on the X axis)
    int ySpeedLimit=7;//Again, self explanitory
    public void setSpeedLimits(int xl, int yl){xSpeedLimit=xl; ySpeedLimit=yl;} //Lets you set the speed limit
    
    boolean particals=false;
    boolean wasGrounded=false;
    String collide = "";
    public void particals(boolean p){particals=p;}
    Actor collidedActor;
    boolean movehold=false;
    public void physics(){
        collidedActor=null;
        wasGrounded=onGround;
        int collisionAmount=0;
        boolean xhold=false;
        boolean yhold=false;
        boolean ground=false;
        GreenfootImage image = new GreenfootImage(getImage());
        //Collision detection
        collide="";
        while (collisionAmount<objects.length){
            if (objects[collisionAmount]==null)break;
            int a;
            //Down check
            a=y;
            while (ymove>=0){
                for (int i=-x+3; i<x-3; i++){
                    Actor object = getOneObjectAtOffset(i, a+ymove,objects[collisionAmount]);
                    if (object!=null){
                        if (ymove!=0)collide="down";
                        if (ymove!=0){
                            yhold=true; ymove=yca;
                            setLocation(getX(),object.getY()-object.getImage().getHeight()/2-y);
                            }
                        if (gravityDirection.equals("down")){ground=true; collidedActor=object;}
                        image=new GreenfootImage(object.getImage());
                        break;
                    }
                }
                if (ymove==0||a>=ymove+y){break;}else{a++;}
            }
            //Up check
            a=-y;
            while (ymove<=0){
                for (int i=-x+3; i<x-3; i++){
                    Actor object = getOneObjectAtOffset(i, a+ymove-1,objects[collisionAmount]);
                    if (object!=null){
                        if (ymove!=0)collide="up";
                        if (ymove!=0){
                            yhold=true; ymove=yca;
                            setLocation(getX(),object.getY()+object.getImage().getHeight()/2+y);
                        }
                        if (gravityDirection.equals("up")){ground=true; collidedActor=object;}
                        image=new GreenfootImage(object.getImage());
                        break;
                    }
                }
                if (ymove==0||a<=ymove-y){break;}else{a--;}
            }
            //Left check
            a=-x;
            while (xmove<=0){
                for (int i=-y+3; i<y-3; i++){
                    Actor object = getOneObjectAtOffset(a+xmove-1, i,objects[collisionAmount]);
                    if (object!=null){
                        if (xmove!=0)collide="left";
                        if (xmove!=0){
                            xhold=true; xmove=xca;
                            setLocation(object.getX()+object.getImage().getWidth()/2+x,getY());
                        }
                        if (gravityDirection.equals("left")){ground=true; collidedActor=object;}
                        image=new GreenfootImage(object.getImage());
                        break;
                    }
                }
                if (xmove==0||a<=xmove-x){break;}else{a--;}
            }
            //Right check
            a=x;
            while (xmove>=0){
                for (int i=-y+3; i<y-3; i++){
                    Actor object = getOneObjectAtOffset(a+xmove, i,objects[collisionAmount]);
                    if (object!=null){
                        if (xmove!=0)collide="right";
                        if (xmove!=0){
                            xhold=true; xmove=xca;
                            setLocation(object.getX()-object.getImage().getWidth()/2-x,getY());
                        }
                        if (gravityDirection.equals("right")){ground=true; collidedActor=object;}
                        image=new GreenfootImage(object.getImage());
                        break;
                    }
                }
                if (xmove==0||a>=xmove+x){break;}else{a++;}
            }
            collisionAmount++;
        }
        //Gravity
        if (ground==false&&gravity==true){
            if (gravityTimeRate==0){
                gravityTimeRate=gravityTimeRateMax;
                if (gravityDirection.equals("down"))subymove++;
                if (gravityDirection.equals("up"))subymove--;
                if (gravityDirection.equals("left"))subxmove--;
                if (gravityDirection.equals("right"))subxmove++;
            }else{
                gravityTimeRate--;
            }
        }else{gravityTimeRate=gravityTimeRateMax;}
        onGround=ground;
        image.scale(1,1);
        //Friction
        /**if (ground==true&&xFrictionAmount<frictionAmountMax){
            xFrictionAmount++;
        }
        if (xFrictionAmount==frictionAmountMax&&onGround){
            xFrictionAmount=0;
            if (gravityDirection.equals("up")||gravityDirection.equals("down")){
                if (xmove>0)subxmove--;
                if (xmove<0)subxmove++;
            }
            if (gravityDirection.equals("left")||gravityDirection.equals("right")){
                if (ymove>0)subymove--;
                if (ymove<0)subymove++;
            }
        }*/
        //Sub-move to move conversion
        int m=1;
        if (subxmove<0){subxmove=m; xmove--;}
        if (subxmove>m){subxmove=0; xmove++;}
        if (subymove<0){subymove=m; ymove--;}
        if (subymove>m){subymove=0; ymove++;}
        //Speed Limit
        if (xmove>xSpeedLimit)xmove=xSpeedLimit;
        if (xmove<-xSpeedLimit)xmove=-xSpeedLimit;
        if (ymove>ySpeedLimit)ymove=ySpeedLimit;
        if (ymove<-ySpeedLimit)ymove=-ySpeedLimit;
        //Move commands
        if (movehold==false){
            if (xhold==false)setLocation(getX()+xmove,getY());
            if (yhold==false)setLocation(getX(),getY()+ymove);
        }
        //Partical effects
        if (particals==true){
            int p=ymove;
            if (p<0)p=-p;
            if (p==0)p=1;
            if (collide.equals("down")){
                for (int i=0; i<3*p; i++){getWorld().addObject(new SolidPartical(Greenfoot.getRandomNumber(7)-3,Greenfoot.getRandomNumber(p)-p-1,image),getX()+Greenfoot.getRandomNumber(getImage().getWidth())-getImage().getWidth()/2,getY()+getImage().getHeight()/2);}
            }
            if (collide.equals("up")){
                for (int i=0; i<3*p; i++){getWorld().addObject(new SolidPartical(Greenfoot.getRandomNumber(7)-3,Greenfoot.getRandomNumber(p)+1,image),getX()+Greenfoot.getRandomNumber(getImage().getWidth())-getImage().getWidth()/2,getY()-getImage().getHeight()/2);}
            }
            p=xmove;
            if (p<0)p=-p;
            if (p==0)p=1;
            if (collide.equals("left")){
                for (int i=0; i<3*p; i++){getWorld().addObject(new SolidPartical(Greenfoot.getRandomNumber(p)+1,Greenfoot.getRandomNumber(4),image),getX()-getImage().getWidth()/2,getY()+Greenfoot.getRandomNumber(getImage().getHeight())-getImage().getHeight()/2);}
            }
            if (collide.equals("right")){
                for (int i=0; i<3*p; i++){getWorld().addObject(new SolidPartical(Greenfoot.getRandomNumber(p)-p-1,Greenfoot.getRandomNumber(7)-3,image),getX()+getImage().getWidth()/2,getY()+Greenfoot.getRandomNumber(getImage().getHeight())-getImage().getHeight()/2);}
            }
        }
    }
    
    /**End of code (don't forget to call the "physics" method)!*/
    
    /**
     * Hit box collision detection code (just in case you have no idea
       how to write your own collision detection code)
       P.S.: I do realize that any hit box bigger than the object's
       image will not regi
    */
    public void detectCollision(){
        Actor matter = getOneIntersectingObject(Matter.class);
        if (matter!=null){
            int XX = ((Matter)matter).getHitBoxXHalfValue();
            int XY = ((Matter)matter).getHitBoxYHalfValue();
            for (int w=matter.getX()-XX; w<=matter.getX()+XX; w++){
                for (int h=matter.getY()-XY; h<=matter.getY()+XY; h++){
                    if (w>getX()-x&&w<getX()+x&&h>getY()-y&&h<getY()+y){
                        //Insert code here
                    }
                }
            }
        }
    }
}
danpost danpost

2014/4/12

#
You should be able to code a basic platform and then change its rotation to make a ramp of it.
Entity1037 Entity1037

2014/4/13

#
That doen't work... X just ends up positioning himself against the object's center + half of the objects height +half of X's height, causing him to appear in the air due to the slant. Maybe I'll try changing some things in the engine to see If I can get the same collisions as usual, but always position X against the point of collision instead of based off of the objects x and y coordinates and dimensions.
Entity1037 Entity1037

2014/4/13

#
Wow... trying to change where the player is positioned upon collision to being calculated from the point of collision gives some glitchy results... Any help or ideas? I'm thinking of having the ramp have no left/right detection, and it instead positions you in the air based on where you are on it while touching it (so basically, player detects collision with it's image from below, then makes it think it's on ground, and then the player is positioned in the air against the ramp depending on where he's touching it).
danpost danpost

2014/4/13

#
Use a while loop to raise X onto the ramp:
while (!getIntersectingObjects(Ramp.class).isEmpty()) setLocation(getX(), getY()-1);
Entity1037 Entity1037

2014/4/13

#
It's still being glitchy. I'm almost positive it has to do with this line of code though that's in X.class (the player):
if (gravityDirection.equals("down")){setLocation(getX(),collidedActor.getY()-collidedActor.getImage().getHeight()/2-getImage().getHeight()/2+1);}
This is to allign X against the last collided actor (the ground) when he change's sprites so that you don't get things like x dashing a little off the ground even though he's technically on the ground. I tried changing it to something like what you posted, but it still keeps raising x a little above the hit detection when he touches the sloped ground (and also, the hit box for X does change Height to that of his image-1)
danpost danpost

2014/4/13

#
Maybe you should try it with 'getOneObjectAtOffset' instead as this will only check the point direct in the center at the base of your character (instead of anywhere across the base of the character).
Entity1037 Entity1037

2014/5/4

#
I figured out what to do! I'll make the player move along ramps like Sonic the Hedgehog does (technical wise)! How sonic moves is explained here. Next, I'll rework my engine to detect colored parts of images only, instead of the entire sprite (in fact, I'm almost done with this already; I'm just debugging now). I wrote this code to help me do it:
/**
     * This will return an object at offset (x,y) if its image is colored at the offset
    */
    public Actor getAnObjectAtOffset(int x, int y, Class clss){
        GreenfootImage img=getImage();
        Actor actor = getOneObjectAtOffset(x,y,clss);
        if(actor!=null) {
            int imgx=getX()+x-(actor.getX()-actor.getImage().getWidth()/2);
            int imgy=getY()+y-(actor.getY()-actor.getImage().getHeight()/2);
            if (actor.getImage().getColorAt(imgx,imgy).getAlpha()<=0)actor=null;
        }
        return actor;
    }
@danpost I have to ask, is there a better way to do it? Or is my way good?
danpost danpost

2014/5/4

#
Am I missing something? or is line 5 a hanger?
Entity1037 Entity1037

2014/5/4

#
Oops. Yeah, it's a hanger. I was going to do the coding in a different way, but it was just... well it didn't work.
danpost danpost

2014/5/4

#
Entity1037 wrote...
Oops. Yeah, it's a hanger. I was going to do the coding in a different way, but it was just... well it didn't work.
Other than that, it looks good.
Entity1037 Entity1037

2014/5/4

#
I'm having a problem with this bug. It appears that the player keeps falling into a floor a bit if he approaches it at high speeds, but only sometimes. I can't seem to see the problem. Could you please help? Here's the down collision check for my physics engine. It checks every potential area off collision, starting from where the player is, and going to the end of where he's about to move to.
 int a;
            //Down check
            a=y;
            while (ymove>=0){
                for (int i=-x+4; i<x-4; i++){
                    Actor object = getAnObjectAtOffset(i, a,objects[collisionAmount]);
                    if (object!=null){
                        if (ymove!=0)collide="down";
                        if (ymove!=0){
                            yhold=true; ymove=yca;
                            setLocation(getX(),getY()+a-y);
                        }
                        if (gravityDirection.equals("down")){
                            ground=true;
                            collidedActor=object;
                            collidedGroundX=getX()+i;
                            collidedGroundY=getY()+a;
                        }
                        //image=new GreenfootImage(object.getImage());
                        break;
                    }
                }
                if (ymove==0||a>=ymove+y){break;}else{a++;}
            }
danpost danpost

2014/5/4

#
Without more context, I can only say that it seems a bit odd to have two consecutive 'if' blocks with the same condition (lines 8 and 9). Unless one of the conditions was a mistake, they can be combined.
Entity1037 Entity1037

2014/5/4

#
I'm very scatterbrained today, and it's like 2:22 AM.... I had an idea that needed that separate if statement, but I ended up scrapping it due to it being a little un-needed.
Entity1037 Entity1037

2014/5/7

#
I seem to have fixed the problem mostly, however, it seems that another glitch occurs when Megaman X lands on ground when the screen is scrolling downward, which causes Megaman X to keep moving downward at a constant speed until the screen stops scrolling. I have no idea why. Could you please help me? Here are the related pieces of code. Collision Engine
import greenfoot.*;
import java.util.List;

public class Matter extends SpriteSheet
{
    public void addedToWorld(World world){
        getWorld().addObject(hitBox,getX(),getY()+y);
    }
    public void shadowImagery(boolean s){}
    
    /**Copy everything between this blue comment and the next one to apply
    physics to a class (I will eventually apply elasticity properties so
    it's more realistic)
    
    I would like to note that the physics should prevent the Matter
    from one direction once blocks to the right of the player have been
    detected, and at no point should the matter EVER move if there are
    objects directly next to it in the direction it's trying to move
    (Seems like a duh note, but it's just laying out how the engine should
    function, and it is there to make sure that no one programms something that
    goes against this function)
    
                              Made by Entity1037
    */
    
    int xmove=0;
    int subymove=0;
    int subxmove=0;
    int ymove=0;
    int gravityTimeRateMax = 1; //Amount of cycles until speed increases
    int gravityTimeRate = gravityTimeRateMax;
    int frictionAmountMax = 2; //How many cycles until the object slows
    //down due to friction
    int xFrictionAmount=0;
    int yFrictoinAmount=0;
    String gravityDirection = "down";
    boolean gravity = true; //Just in case you want to switch gravity   ;D
    Class[] objects = {Base.class,SymbolBlock.class,Spike.class,SpikeSheet.class,BossDoor.class,Box.class,Brick.class,TestingBlock.class,Ramp1.class,null}; //All objects that can be collided with
    
    public void gravity(boolean g){gravity=g;}
    public void gravityDirection(String d){gravityDirection = d;}
    boolean onGround = false;
    
    int xca = 0; //How much xmove changes (Example: "xmove=xca" where "xca=-xmove")
    int yca = 0; //How much ymove changes (Example: "ymove=yca" where "ycs=-ymove")
    /**
       This method must be called every cycle before "physics()" is called!!!
       Protip: place it in the "act()" method!
       Protip#2: If you would like, you can just call this method at the beginning of "physics()".-
       -This will make it the same speed altering values apply to all matter subclasses
    */
    public void setSpeedAlteringValues(int X, int Y){xca=X; yca=Y;} //Lets you set speed altering values
    
    
    int x=getImage().getWidth()/2; //Half of the width of the hitbox
    int y=getImage().getHeight()/2; //Half of the height of the hitbox
    public void setHitBoxHalfValues(int X, int Y){x=X; y=Y;} //Lets you set hit box dimensions
    public int getHitBoxXHalfValue(){return x;} //Allows you to obtain hit box values of actors in "Matter"
    public int getHitBoxYHalfValue(){return y;} //Allows you to obtain hit box values of actors in "Matter"
    
    int xSpeedLimit=9;//This is self explanitory (caps how fast subclasses of matter can travel on the X axis)
    int ySpeedLimit=7;//Again, self explanitory
    public void setSpeedLimits(int xl, int yl){xSpeedLimit=xl; ySpeedLimit=yl;} //Lets you set the speed limit
    
    boolean particals=false;
    boolean wasGrounded=false;
    String collide = "";
    public void particals(boolean p){particals=p;}
    Actor collidedActor;
    int collidedGroundX=0;
    int collidedGroundY=0;
    boolean movehold=false;
    
    Actor hitBox = new GroundDetectionVisual();
    public void physics(){
        collidedActor=null;
        wasGrounded=onGround;
        int collisionAmount=0;
        boolean xhold=false;
        boolean yhold=false;
        boolean ground=false;
        GreenfootImage image = new GreenfootImage(getImage());
        //Collision detection
        collide="";
        while (collisionAmount<objects.length){
            if (objects[collisionAmount]==null)break;
            int a;
            //Down check
            a=y;
            while (ymove>=0){
                for (int i=-x+4; i<x-4; i++){
                    Actor object = getAnObjectAtOffset(i, a,objects[collisionAmount]);
                    if (object!=null){
                        if (ymove!=0){
                            if (gravityDirection.equals("down")){
                                collidedGroundX=getX()+i;
                                collidedGroundY=getY()+a;
                            }
                            collide="down";
                            yhold=true;
                            ymove=yca;
                            setLocation(getX(),getY()+a-y);
                        }
                        if (gravityDirection.equals("down")){
                            ground=true;
                            collidedActor=object;
                        }
                        //image=new GreenfootImage(object.getImage());
                        break;
                    }
                }
                if (ymove==0||a>=ymove+y){break;}else{a++;}
            }
            //Up check
            a=-y;
            while (ymove<=0){
                for (int i=-x+3; i<x-3; i++){
                    Actor object = getAnObjectAtOffset(i, a,objects[collisionAmount]);
                    if (object!=null){
                        if (ymove!=0){
                            collide="up";
                            yhold=true;
                            ymove=yca;
                            setLocation(getX(),getY()+a-1+y);
                        }
                        if (gravityDirection.equals("up")){
                            ground=true;
                            collidedActor=object;
                            collidedGroundX=getX()+i;
                            collidedGroundY=getY()+a;
                        }
                        //image=new GreenfootImage(object.getImage());
                        break;
                    }
                }
                if (ymove==0||a<=ymove-y){break;}else{a--;}
            }
            //Left check
            a=-x;
            while (xmove<=0){
                for (int i=-y+3; i<y-3; i++){
                    Actor object = getAnObjectAtOffset(a, i,objects[collisionAmount]);
                    if (object!=null){
                        if (xmove!=0){
                            collide="left";
                            xhold=true;
                            xmove=xca;
                            setLocation(getX()+a+x,getY());
                        }
                        if (gravityDirection.equals("left")){
                            ground=true;
                            collidedActor=object;
                            collidedGroundX=getX()+a-1;
                            collidedGroundY=getY()+i;
                        }
                        //image=new GreenfootImage(object.getImage());
                        break;
                    }
                }
                if (xmove==0||a<=xmove-x){break;}else{a--;}
            }
            //Right check
            a=x;
            while (xmove>=0){
                for (int i=-y+3; i<y-3; i++){
                    Actor object = getAnObjectAtOffset(a, i,objects[collisionAmount]);
                    if (object!=null){
                        if (xmove!=0){
                            collide="right";
                            xhold=true;
                            xmove=xca;
                            setLocation(getX()+a-x,getY());
                        }
                        if (gravityDirection.equals("right")){
                            ground=true;
                            collidedActor=object;
                            collidedGroundX=getX()+a;
                            collidedGroundY=getY()+i;
                        }
                        //image=new GreenfootImage(object.getImage());
                        break;
                    }
                }
                if (xmove==0||a>=xmove+x){break;}else{a++;}
            }
            collisionAmount++;
        }
        //Gravity
        if (ground==false&&onGround==false&&gravity==true){
            if (gravityTimeRate==0){
                gravityTimeRate=gravityTimeRateMax;
                if (gravityDirection.equals("down"))subymove++;
                if (gravityDirection.equals("up"))subymove--;
                if (gravityDirection.equals("left"))subxmove--;
                if (gravityDirection.equals("right"))subxmove++;
            }else{
                gravityTimeRate--;
            }
        }else{gravityTimeRate=gravityTimeRateMax;}
        onGround=ground;
        image.scale(1,1);
        //Friction
        /**if (ground==true&&xFrictionAmount<frictionAmountMax){
            xFrictionAmount++;
        }
        if (xFrictionAmount==frictionAmountMax&&onGround){
            xFrictionAmount=0;
            if (gravityDirection.equals("up")||gravityDirection.equals("down")){
                if (xmove>0)subxmove--;
                if (xmove<0)subxmove++;
            }
            if (gravityDirection.equals("left")||gravityDirection.equals("right")){
                if (ymove>0)subymove--;
                if (ymove<0)subymove++;
            }
        }*/
        //Sub-move to move conversion
        int m=1;
        if (subxmove<0){subxmove=m; xmove--;}
        if (subxmove>m){subxmove=0; xmove++;}
        if (subymove<0){subymove=m; ymove--;}
        if (subymove>m){subymove=0; ymove++;}
        //Speed Limit
        if (xmove>xSpeedLimit)xmove=xSpeedLimit;
        if (xmove<-xSpeedLimit)xmove=-xSpeedLimit;
        if (ymove>ySpeedLimit)ymove=ySpeedLimit;
        if (ymove<-ySpeedLimit)ymove=-ySpeedLimit;
        //Move commands
        if (movehold==false){
            if (xhold==false)setLocation(getX()+xmove,getY());
            if (yhold==false)setLocation(getX(),getY()+ymove);
        }
        //Send Info For ground detection visual
        if (hitBox!=null){
            int ypos=ymove+1;
            if (ypos<1)ypos=1;
            if (!collide.equals("")){
                ((GroundDetectionVisual)hitBox).changeImage(x*2-8,ypos/*,collidedGroundX,collidedGroundY*/);
            }else{
                ((GroundDetectionVisual)hitBox).changeImage(x*2-8,ypos);
            }
            hitBox.setLocation(getX(),getY()+y+(ymove/2));
        }
        //Partical effects
        if (particals==true){
            int p=ymove;
            if (p<0)p=-p;
            if (p==0)p=1;
            if (collide.equals("down")){
                for (int i=0; i<3*p; i++){getWorld().addObject(new SolidPartical(Greenfoot.getRandomNumber(7)-3,Greenfoot.getRandomNumber(p)-p-1,image),getX()+Greenfoot.getRandomNumber(getImage().getWidth())-getImage().getWidth()/2,getY()+getImage().getHeight()/2);}
            }
            if (collide.equals("up")){
                for (int i=0; i<3*p; i++){getWorld().addObject(new SolidPartical(Greenfoot.getRandomNumber(7)-3,Greenfoot.getRandomNumber(p)+1,image),getX()+Greenfoot.getRandomNumber(getImage().getWidth())-getImage().getWidth()/2,getY()-getImage().getHeight()/2);}
            }
            p=xmove;
            if (p<0)p=-p;
            if (p==0)p=1;
            if (collide.equals("left")){
                for (int i=0; i<3*p; i++){getWorld().addObject(new SolidPartical(Greenfoot.getRandomNumber(p)+1,Greenfoot.getRandomNumber(4),image),getX()-getImage().getWidth()/2,getY()+Greenfoot.getRandomNumber(getImage().getHeight())-getImage().getHeight()/2);}
            }
            if (collide.equals("right")){
                for (int i=0; i<3*p; i++){getWorld().addObject(new SolidPartical(Greenfoot.getRandomNumber(p)-p-1,Greenfoot.getRandomNumber(7)-3,image),getX()+getImage().getWidth()/2,getY()+Greenfoot.getRandomNumber(getImage().getHeight())-getImage().getHeight()/2);}
            }
        }
    }
    
    /**End of code (don't forget to call the "physics" method)!*/
}
Scrolling/Level Loading Code
import greenfoot.*;
import java.util.List;
import java.awt.Color;
import javax.swing.JOptionPane;
import java.io.*;

public class XEngine extends World
{
    boolean custom = false;
    String stage=null;
    public XEngine()
    {    
        // Create a new world with 600x400 cells with a cell size of 1x1 pixels.
        super(600, 400, 1, false);
        addObject(new FadeOverlay(),getWidth()/2,getHeight()/2);
        if (!isRunningAsApplet())custom=(JOptionPane.showConfirmDialog(null,"Would you like to play a custom Level?","Notice",JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION);
        if (custom){
            deleteCurrentLevel();
            loadCustomStage();
            ((FadeOverlay)getObjects(FadeOverlay.class).get(0)).fadeIn();
        }else{
            loadStage();
        }
        addObject(new X("XEngine"),xc,yc);
        addObject(new GridCoordinates(),getWidth()/2,40);
        addObject(new MenuSelection("Title Screen","","","MainMenu",30,Color.WHITE,Color.YELLOW),getWidth()/2,getHeight()-20);
        addObject(new Fps(),35,50);
    }
    
    public void loadStage(){
        boolean found=false;
        if (stage==null||stage.equals("")){
            stage = JOptionPane.showInputDialog(null,"Enter the name of the stage you wish to test.\n\nAlpha Stage\nConvert Test Room\nCheckpoint Test Room\nTest Stage\nBoss Test Room\nSpike Fall\nHit Detection Test Room");
            if (stage.equalsIgnoreCase("Spike Fall"))JOptionPane.showMessageDialog(null,"WARNING: THIS STAGE WILL NOT BE AN ACTUAL LEVEL!\nTHIS STAGE IS MOSTLY FOR FUN, AND IS A BIT\nRIDICULOUS.");
        }
        if (stage.equalsIgnoreCase("Convert Test Room")){convertTestRoom(); found=true;}
        if (stage.equalsIgnoreCase("Test Stage")){testStage(); found=true;}
        if (stage.equalsIgnoreCase("Checkpoint Test Room")){checkpointTestRoom(); found=true;}
        if (stage.equalsIgnoreCase("Alpha Stage")){alphaStage(); found=true;}
        if (stage.equalsIgnoreCase("Boss Test Room")){bossTestRoom(); found=true;}
        if (stage.equalsIgnoreCase("Hit Detection Test Room")){hitDetectionTestRoom(); found=true;}
        if (stage.equalsIgnoreCase("Spike Fall")){spikeFall(); found=true;}
        ((FadeOverlay)getObjects(FadeOverlay.class).get(0)).fadeIn();
        if (found)return;
        testStage();
        JOptionPane.showMessageDialog(null,"Unable to find stage.");
    }
    
    public void loadCustomStage()
    {
        if (!custom){testStage(); return;}
        String action = "Load";
        if (true){
            String files="||ALL FILES||";;
            File folder=null;
            File game = null;
            game = new File(System.getProperty("user.dir"));
            folder = new File(game.getParent()+"/Megaman EX Levels");//Set the directory to where ever you want the Megaman EX Levels folder to be
            if (folder!=null&&!folder.exists()){
                if (JOptionPane.showConfirmDialog(null,"In order to save/load levels, a folder needs to be created.\nWould you like to create one?","WARNING",JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION){
                    folder.mkdir();
                    JOptionPane.showMessageDialog(null,"A new folder has been created to store custom made leves\nat this location: "+folder.getAbsolutePath());
                }
            }else if(folder!=null){
                System.out.println("Folder accessed: "+folder.getAbsolutePath());
            }else{JOptionPane.showMessageDialog(null,"Unable to create directory to save levels. Please change the\npath of where you want to save levels. It is in\nXEngine.class on line 49"); return;}
            files+=listAllFiles(folder);
            if (stage==null)stage = JOptionPane.showInputDialog(null,"Enter the name of the level you wish to load.\n\n"+files);
            System.out.println(stage);
            if (stage==null||stage.equals("")){return;}
            
            if(folder!=null){
                try{
                    File locatedLevel = new File(folder.getAbsolutePath()+"/"+stage+".dat");
                    if (!locatedLevel.exists()){
                        System.out.println(locatedLevel.getAbsolutePath());
                        JOptionPane.showMessageDialog(null,"Requested stage does not exist.");
                        testStage();
                        return;
                    }
                    repaint();
                    FileReader readlevel= new FileReader(locatedLevel);
                    BufferedReader level = new BufferedReader(readlevel);
                    String data=level.readLine();
                    int l=Integer.parseInt(data);
                    data=level.readLine();
                    int r=Integer.parseInt(data);
                    data=level.readLine();
                    int u=Integer.parseInt(data);
                    data=level.readLine();
                    int d=Integer.parseInt(data);
                    setScrollingLimits(l,r,u,d);
                    while (true){
                        data=level.readLine();
                        if (data!=null){loadClassData(data);}else{break;}
                    }
                    level.close();
                }catch(Exception e){JOptionPane.showMessageDialog(null,"An error has occured while loading the stage.\nCheck the console output for details."); e.printStackTrace(); testStage(); return;}
            }
        }
    }
    
    //Scrolling Engine and Custom Stage Loading Methods
    private boolean isRunningAsApplet(){
        return null != System.getSecurityManager();
    }
    
    public static String listAllFiles(File folder){
        if (!folder.exists()){
            JOptionPane.showMessageDialog(null,"ERROR, this folder does not exist: "+folder.getAbsolutePath());
            return "";
        }
        String levels="";
        File[] listOfFiles = folder.listFiles();
        for (File f : listOfFiles) {
            if (f.isFile()) {
               levels+="\n"+f.getName().substring(0,f.getName().indexOf("."));
            }
        }
        return levels;
    }
    int respawnWait=0;
    public void act(){
        scrollingEngine();
        setPaintOrder(GroundDetectionVisual.class,Fps.class,MouseButtons.class,GridCoordinates.class,Score.class,FadeOverlay.class,healthPoint.class,HealthMeter.class,XExplosion.class,X.class,BossDoor.class,Enemies.class,xbullets.class,shot3.class,shot2.class,shot1.class,Terrain.class);
        if (Greenfoot.isKeyDown("l"))loadCustomStage();
        if (respawnWait==1){
            if (rx==0){rx=xc;}else{rx=checkpoints[ccp];}
            if (ry==0){ry=yc;}else{ry=checkpoints[ccp+1];}
            addObject(new X("XEngine"),rx,ry);
            try{((FadeOverlay)getObjects(FadeOverlay.class).get(0)).fadeIn();}catch(IndexOutOfBoundsException e){}
        }
        if (respawnWait>0){respawnWait--;}
    }
    
    boolean autoScroll=true;
    public void autoScroll(boolean a){autoScroll=a;}
    int xc=getWidth()/2;//X center of screen
    int yc=getHeight()/2;//Y center of screen
    int xX=xc;//X's X coordinate
    int xY=yc;//X's Y coordinate
    public void getCoordinates(int x, int y){xX=x; xY=y;}
    int xcorrect=0;//How much world needs to be scrolled on the X-axis
    int ycorrect=0;//How much world need to be scrolled on the Y-axis
    int s=25;//How far from center X can stray before the screen scrolls
    int llimit=500;
    int rlimit=500+llimit;
    int ulimit=200;
    int dlimit=200+ulimit;
    int xst=llimit;//How far the screen's x coordinate is away from start
    int yst=ulimit;//How far the screen's y coordinate is away from start
    public void setScrollingLimits(int left, int right, int up, int down){scrollToBeginning(); xst=left; yst=up; rlimit=right+left; llimit=left; ulimit=up; dlimit=down+up;}
    public void scrollingEngine(){scrollingEngine(0,0);}
    /**If you want to scroll the screen in a specific area, then call scrollingEngine(xcorrect,ycorrect), and this will cause the screen to scroll
       accordingingly and ignore all scrollstoppers while doing so.*/
    public void scrollingEngine(int x,int y){
        xcorrect=-x;
        ycorrect=-y;
        if (autoScroll==true){
            //Figure out how far away X is from the scrolling margin, if at all
            if (xX<xc-s){xcorrect=xc-s-xX;}else if (xX>xc+s){xcorrect=xc+s-xX;}
            if (xY<yc-s){ycorrect=yc-s-xY;}else if (xY>yc+s){ycorrect=yc+s-xY;}
        }
        //Test if the scrolling boundries have been reached, and stop scrolling if they have
        List scrollstoppers = getObjects(ScrollStopper.class);
        if (xst+-xcorrect>rlimit)xcorrect=xst-rlimit;
        if (xst+-xcorrect<0)xcorrect=xst;
        if (yst+-ycorrect>dlimit)ycorrect=yst-dlimit;
        if (yst+-ycorrect<0)ycorrect=yst;
        if (!scrollstoppers.isEmpty()&&x==0&&y==0&&autoScroll==true){
            for (int s=0; s<scrollstoppers.size(); s++){
                Actor st = (Actor) scrollstoppers.get(s);
                if (st.getX()+25+xcorrect>=0&&st.getX()-25+xcorrect<=getWidth()&&st.getY()+25+ycorrect>=0&&st.getY()-25+ycorrect<=getHeight()){
                    if (st.getX()+25>0&&st.getX()-25<getWidth()){
                        if (st.getY()>getHeight()/2){ycorrect=-(st.getY()-25-getHeight());}
                        if (st.getY()<getHeight()/2){ycorrect=-(st.getY()+25);}
                    }
                    if (respawnWait>0){
                        if (st.getY()+ycorrect+25>0&&st.getY()+ycorrect-25<getHeight()){
                            if (st.getX()>getWidth()/2){xcorrect=-(st.getX()-25-getWidth());}
                            if (st.getX()<getWidth()/2){xcorrect=-(st.getX()+25);}
                        }
                        if (respawnWait>0&&st.getX()+xcorrect+25>0&&st.getX()+xcorrect-25<getWidth()){
                            if (st.getY()>getHeight()/2){ycorrect=-(st.getY()-25-getHeight());}
                            if (st.getY()<getHeight()/2){ycorrect=-(st.getY()+25);}
                        }
                        if (st.getY()+ycorrect+25>0&&st.getY()+ycorrect-25<getHeight()){
                            if (st.getX()>getWidth()/2){xcorrect=-(st.getX()-25-getWidth());}
                            if (st.getX()<getWidth()/2){xcorrect=-(st.getX()+25);}
                        }
                    }else{
                        if (st.getY()+25>0&&st.getY()-25<getHeight()){
                            if (st.getX()>getWidth()/2){xcorrect=-(st.getX()-25-getWidth());}
                            if (st.getX()<getWidth()/2){xcorrect=-(st.getX()+25);}
                        }
                    }
                }
            }
        }
        //Track the screen's scrolling
        xst-=xcorrect; //x-axis tracking
        yst-=ycorrect; //y-axis tracking
        //Scroll world, if at all
        ((GridCoordinates)getObjects(GridCoordinates.class).get(0)).giveGridCoordinates(xcorrect,ycorrect);
        if (xcorrect==0&&ycorrect==0)return;
        scroll();
    }
    Class[] world = {SpriteSheet.class,Terrain.class};
    public void scroll(){
        //Scroll World
        for (int i=0; i<world.length; i++){
            List objects = getObjects(world[i]);
            if (! objects.isEmpty()){
                for (int o=0; o<objects.size(); o++){
                    Actor object = (Actor) objects.get(o);
                    object.setLocation(object.getX()+xcorrect,object.getY()+ycorrect);
                }
            }
        }
        //Update checkpoint coordinates
        if (checkpoints[0]==null)return;
        for (int i=0; i<=ccp; i+=2){
            if (checkpoints[i]==null){System.out.println("REACHED NULL BEFORE PASSING CCP"); return;}
            checkpoints[i]+=xcorrect;
            checkpoints[i+1]+=ycorrect;
        }
    }
    public void scrollToBeginning(){
        autoScroll=false;
        xcorrect=xst-llimit;
        ycorrect=yst-ulimit;
        xst=llimit;
        yst=ulimit;
        scroll();
        autoScroll=true;
    }
    
    //Level Loading Methods
    
    public void deleteCurrentLevel(){
        List terrain = getObjects(Terrain.class);
        for (int t=0; t<terrain.size(); t++){
            Actor object = (Actor) terrain.get(t);
            removeObject(object);
        }
        List SpriteSheet = getObjects(SpriteSheet.class);
        for (int i=0; i<SpriteSheet.size(); i++){
            Actor object = (Actor) SpriteSheet.get(i);
            removeObject(object);
        }
        List HUD = getObjects(HUD.class);
        for (int i=0; i<HUD.size(); i++){
            Actor object = (Actor) HUD.get(i);
            removeObject(object);
        }
        repaint();
    }
    
    private void loadClassData(String objects){
        if (objects.indexOf(".")==-1)return;
        for (int t=0; t<20; t++){
            String data=objects.substring(0,objects.indexOf("."));
            //JOptionPane.showMessageDialog(null,"objects="+objects+"\ndata="+data);
            int periods=0;
            for (int i=0; i<objects.length(); i++){
                if (objects.substring(i,i+1).equals("."))periods++;
            }
            if (periods>1){objects=objects.substring(objects.indexOf(".")+1);}
            if (data.length()==0)return;
            String o="";
            o=data.substring(0,1);
            data=data.substring(1);
            int x=0, y=0, a=0, b=0, c=0;
            //Get data of objects and add it to the world
            if (o.equals("b")){
                x=getInt(data)*25;
                data=clip(data);
                y=getInt(data)*25;
                addObject(new Box(),x,y);
            }
            if (o.equals("a")){
                x=getInt(data)*25;
                data=clip(data);
                y=getInt(data)*25;
                data=clip(data);
                a=getInt(data)*50;
                data=clip(data);
                b=getInt(data)*50;
                addObject(new Base(a,b),x,y);
            }
            if (o.equals("s")){
                //LEAVE COORDINATES OF SPIKES AS IS!!!
                x=getInt(data);
                data=clip(data);
                y=getInt(data);
                data=clip(data);
                a=getInt(data);
                addObject(new Spike(a*90),x,y);
            }
            if (o.equals("p")){
                //LEAVE COORDINATES AS IS!!!
                x=getInt(data);
                data=clip(data);
                y=getInt(data);
                data=clip(data);
                a=getInt(data)*25;
                data=clip(data);
                b=getInt(data)*25;
                data=clip(data);
                c=getInt(data);
                addObject(new SpikeSheet(a,b,c*90),x,y);
            }
            if (o.equals("c")){
                x=getInt(data)*25;
                data=clip(data);
                y=getInt(data)*25;
                addObject(new ScrollStopper(),x,y);
            }
            if (o.equals("d")){
                x=getInt(data);
                data=clip(data);
                y=getInt(data);
                data=clip(data);
                String name=data.substring(0,data.indexOf(","));
                data=clip(data);
                a=getInt(data);
                data=clip(data);
                b=getInt(data);
                data=clip(data);
                c=getInt(data)*90;
                addObject(new BossDoor(name,a,(b==1),c),x,y);
            }
            if (o.equals("y")){
                x=getInt(data)*25;
                data=clip(data);
                y=getInt(data)*25;
                data=clip(data);
                a=getInt(data);
                addObject(new SymbolBlock(a),x,y);
            }
            if (o.equals("e")){
                x=getInt(data)*25;
                data=clip(data);
                y=getInt(data)*25;
                data=clip(data);
                addObject(new EnemySpawn(data),x,y);
            }
            if (o.equals("t")){
                x=getInt(data);
                data=clip(data);
                y=getInt(data);
                data=clip(data);
                a=getInt(data)*25;
                data=clip(data);
                b=getInt(data)*25;
                addObject(new Checkpoint(a,b),x,y);
            }
            //JOptionPane.showMessageDialog(null,x+"\n"+y+"\n"+a+"\n"+b);
            repaint();
            if (periods<2)break;
        }
    }
    public int getInt(String data){
        int integer=0;
        if (data.indexOf(",")!=-1){
            integer=Integer.parseInt(data.substring(0,data.indexOf(",")));
        }else{
            integer=Integer.parseInt(data);
        }
        return integer;
    }
    public String clip(String data){
        return data.substring(data.indexOf(",")+1);
    }
    
    public void insertEnemy(int x, int y, String e){
        if (e.equals("aw"))addObject(new TestOrb(),x,y);
        if (e.equals("me"))addObject(new Metall(),x,y+6);
        if (e.equals("af"))addObject(new AwesomeFace(),x,y+9);
    }
    
    //Checkpoint Coding
    Integer[] checkpoints = new Integer[100];
    static int ccp=0;
    public void giveCheckpointCoordinates(int x, int y){
        int i=0;
        for (i=i; i<checkpoints.length; i+=2){
            if (checkpoints[i]==null)break;
            if (x==checkpoints[i]&&y==checkpoints[i+1])return;
        }
        ccp=i;
        checkpoints[ccp]=x;
        checkpoints[ccp+1]=y;
    }
    
    public void eraseCheckpoints(){
        for (int i=0; i<checkpoints.length; i++){
            if (checkpoints[i]!=null){
                checkpoints[i]=null;
            }else{
                return;
            }
        }
    }
    int rx=0;
    int ry=0;
    public void respawn()throws NullPointerException{
        try{
            rx=0;
            ry=0;
            deleteCurrentLevel();
            if (custom){loadCustomStage();}else{loadStage();}
            if (checkpoints[0]!=null){
                scrollingEngine(checkpoints[ccp],checkpoints[ccp+1]);
                rx=checkpoints[ccp];
                ry=checkpoints[ccp+1];
                scrollingEngine(rx-xc+1,ry-yc+1);
            }else{
                scrollToBeginning();
            }
            /**
            Record x and y coordinates for checkpoints of where it is on screen everytime x touches the checkpoint, and track it's positions by
            adding xcorrect and ycorrect from the scrolling engine to them. Then, when the player dies, delete/reload the level, then scroll to
            the checkpoint, and get it's exact location (have to use any leftover value from the x and y coordinates in case the screen can't
            scroll all the way so that the checkpoint is in the center of the screen), then teleport Megaman X into the screen based on checkpoint
            coordinates.**/
            respawnWait=5;
        }catch(Exception e){e.printStackTrace();}
    }
Megaman X's animation coding (there's a bit of code that repositions Megaman X and changes his hitbox's half height to half the height of X's current image)
<code ommited>
        //move back during recoil animation
        if (faceLeft&&recoil==true){xmove=1;}else if(recoil==true){xmove=-1;}
        //Fix offset of idle shooting animation in case of shooting left
        if (faceLeft==true&&iplace==31){image[31]=new GreenfootImage(getSprite(sprites,6,167,36,201));}else{image[31]=new GreenfootImage(getSprite(sprites,7,167,36,201));}
        //Mirror Sprite If Facing Left
        GreenfootImage frame = new GreenfootImage(image[iplace]);
        if (recoilTimer>44&&recoilTimer%4==0){frame=new GreenfootImage(frame.getWidth(),frame.getHeight());}
        frame.scale(frame.getWidth()+10,frame.getHeight()+10);
        if (faceLeft==true){frame.mirrorHorizontally();}
        //tint image when charging
        if (chargeAmount>0){
            if (chargetinting>=4){chargetinting=1;}else{chargetinting++;}
            if (chargeAmount==1&&chargetinting%4==0)frame = tint(0,75,0,frame);
            if (chargetinting%2==0){
                if (chargeAmount==2)frame = tint(0,30,100,frame);
                if (chargeAmount==3)frame = tint(125,0,125,frame);
            }
        }
        setImage(frame);
        //((GridCoordinates)getWorld().getObjects(GridCoordinates.class).get(0)).giveAnimationData(iplace);
        if (onGround==false||collidedActor==null||debug==true||(recoilTimer<44&&recoilTimer>0))return;
        if (gravityDirection.equals("down")){
            y=getImage().getHeight()/2;
            if (y>25)y=25;
            setLocation(getX(),collidedGroundY-y);
        }
<code ommited>
There are more replies on the next page.
1
2