I tried to create a game in the style of Super Mario Bros, but everytime the world scrolles, the fps drop to 1 per second. I dont have any idea why tho.
import greenfoot.*; /** * * * */ public class Waluigi extends Actor { final int jSpeed = 10; // the initial 'jump' speed int ySpeed = 0, xSpeed = 0; // the initial vertical and horizontal speeds int richtung = 1; int animZaehler; boolean aboutFace; // the direction (left or right) the actor is facing boolean onGround; // the state of the actor being set on an object or not private GreenfootImage bildL, bildR, bildLs, bildRs, bild1L, bild2L, bild3L, bild4L, bild1R, bild2R, bild3R, bild4R; public Waluigi() { bildL = new GreenfootImage("WaluigiL.png"); bildR = new GreenfootImage("WaluigiR.png"); bildLs = new GreenfootImage("WaluigiLS.png"); bildRs = new GreenfootImage("WaluigiRS.png"); bild1L = new GreenfootImage("WaluigiLL1.png"); bild2L = new GreenfootImage("WaluigiLL2.png"); bild3L = new GreenfootImage("WaluigiLL3.png"); bild4L = new GreenfootImage("WaluigiLL4.png"); bild1R = new GreenfootImage("WaluigiRL1.png"); bild2R = new GreenfootImage("WaluigiRL2.png"); bild3R = new GreenfootImage("WaluigiRL3.png"); bild4R = new GreenfootImage("WaluigiRL4.png"); } public void act() { getDirection(); move(); animationen(); richtung(); } private void move() { ySpeed++; // adds gravity animZaehler++; if (Greenfoot.isKeyDown("D")&&!Greenfoot.isKeyDown("M"))move(4); if (Greenfoot.isKeyDown("A")&&!Greenfoot.isKeyDown("M"))move(-4); if (Greenfoot.isKeyDown("D")&&Greenfoot.isKeyDown("M"))move(8); if (Greenfoot.isKeyDown("A")&&Greenfoot.isKeyDown("M"))move(-8); setLocation(getX(), getY()+ySpeed/2); // check for change in horizontal direction if (isTouching(ground1.class))onGround=true; if (!isTouching(ground1.class))onGround=false; while (getOneObjectAtOffset(0, getImage().getHeight()/3+1, Actor.class) != null) { setLocation(getX(), getY()-1); ySpeed = 0; } // check above the actor while (getOneObjectAtOffset(0, -getImage().getHeight()/2-1, Actor.class) != null) { setLocation(getX(), getY()+1); ySpeed = 0; } // check to right of actor while (getOneObjectAtOffset(getImage().getWidth()/3+1, 0, Actor.class) != null&&isTouching(ground2.class)) { setLocation(getX()-1, getY()); xSpeed = 0; } // check to left of actor while (getOneObjectAtOffset(-getImage().getWidth()/3-1, 0, Actor.class) != null&&isTouching(ground2.class)) { setLocation(getX()+1, getY()); xSpeed = 0; } } public void richtung() { if (Greenfoot.isKeyDown("D"))richtung= 1; if (Greenfoot.isKeyDown("A"))richtung= 2; } /** * Determines any changes in horizontal and vertical speeds for the actor. */ private void getDirection() { // if (!onGround) return; // if not mid-air changes allowed // sets requested direction of move, or continues in current direction if (Greenfoot.isKeyDown("a") && xSpeed > -50) xSpeed -= 2; // check left if (Greenfoot.isKeyDown("d") && xSpeed < 50) xSpeed += 2; // check right if (Greenfoot.isKeyDown("space") && onGround)ySpeed -= jSpeed; } public void animationen() { if (!onGround) { if (richtung==1)setImage(bildRs); if (richtung==2)setImage(bildLs); animZaehler=0; } if (onGround) { if (!Greenfoot.isKeyDown("A")&&!Greenfoot.isKeyDown("D")) { if (richtung==1)setImage(bildR); if (richtung==2)setImage(bildL); animZaehler=0; } if (Greenfoot.isKeyDown("M")) { if (animZaehler==1) { if (Greenfoot.isKeyDown("A"))bildWechselnL(); if (Greenfoot.isKeyDown("D"))bildWechselnR(); } if (animZaehler==3) { if (Greenfoot.isKeyDown("A"))bildWechselnL(); if (Greenfoot.isKeyDown("D"))bildWechselnR(); } if (animZaehler==4)animZaehler=0; } else if (!Greenfoot.isKeyDown("M")) { if (animZaehler==1) { if (Greenfoot.isKeyDown("A"))bildWechselnL(); if (Greenfoot.isKeyDown("D"))bildWechselnR(); } if (animZaehler==6) { if (Greenfoot.isKeyDown("A"))bildWechselnL(); if (Greenfoot.isKeyDown("D"))bildWechselnR(); } if (animZaehler==10)animZaehler=0; } } if (animZaehler==21)animZaehler=1; } private void bildWechselnL() { if (getImage() == bild1L) { setImage(bild2L); } else setImage(bild1L); } private void bildWechselnR() { if (getImage() == bild1R) { setImage(bild2R); } else setImage(bild1R); } private void bildWechselnK() { if (getImage() == bild1L) { setImage(bild1R); } else setImage(bild1L); } }
import greenfoot.*; import java.util.List; import java.util.ArrayList; /** * SWorld is a super-class for a scrolling world (horizontal, vertical, or both).<br><br> * Author: danpost<br>Version: May 22, 2016 (v2.1)<br> * <br> * To implement this super-class: * <l><li>(1) create a sub-class of this class</li> * <li>(2) use a <i>super(....)</i> call to one of the constructors in this class</li> * <li>(3) create the main actor (one that always stays in view) and call the <i>setMainActor</i> method</li> * <br> * NOTE: if placing the main actor to a location where scrolling will end up taking place before moving it, * place a call the the 'act' method of this class at the end of the constructor of its subclass * using 'super.act();'<br><br> * <li>(4) (optional) set a scrolling background image using a call to <i>setScrollingBackground</i> or <i>fillScrollingBackground</i></li></l> * <br> * NOTE: the order of steps above is very important<br> * <br> * There are two methods to add other objects into the world: * <l><li>the standard method <i>addObject(Actor, int, int)</i> can be used to add a scrollable actor into the world</li> * <li>a secondary method <i>addObject(Actor, int, int, boolean)</i> which is equivalent to the standard method, except * that the boolean will indicate the scrollable state of the object.</li></l> * * The width and height dimensions for both the world and the universe of scenarios with a cell size greater than one * will be raised to the nearest odd values to center the main actor.<br> * <br> * SPECIAL NOTE: if you decide to override the 'act' method of this class with an 'act' method in your sub-world, you will * need to follow the format below to run the scrolling of the scenario: * * <pre> public void act() * { * // possibly some code here * super.act(); * // possibly some more code here * }<pre> */ public class SWorld extends World { private int scrollingWidth, scrollingHeight; // dimensions of scrolling area private int actorMinX, actorMaxX, actorMinY, actorMaxY; // limits for main actor within world coordinates private int scrolledX, scrolledY; // horizontal and vertical scrolled amounts private int scrollType; // indicates scrolling directions (0=none, 1=horizontal, 2=vertical, 3=both) Actor mainActor = null; // the actor that always stays visible private List<Actor>genActors = new ArrayList(); // lists all generic scrolling actor objects private GreenfootImage background = null; /** * The constructor for a universal scroller. * Creates an unbounded world and sets the size of the scrollable area. * * @param wide the window width * @param high the window height * @param cellSize the size of each cell * @param scrollWide the scrollable width (minimum value is window width) * @param scrollHigh the scrollable height (minimum value is window height) */ public SWorld(int wide, int high, int cellSize, int scrollWide, int scrollHigh) { super(cellSize == 1 ? wide:(wide/2)*2+1, cellSize == 1 ? high : (high/2)*2+1, cellSize, false); scrollType = (scrollWide > wide ? 1 : 0)+(scrollHigh>high?2:0); scrollingWidth = scrollType%2 == 1 ? scrollWide : wide; scrollingHeight = scrollType/2 == 1 ? scrollHigh : high; } /** * The constructor for a horizontal (side) scroller. * Calls the universal scroller constructor with scrollHigh equal to the window height parameter. * * @param wide the window width * @param high the window height * @param cellSize the size of each cell * @param scrollWide the scrollable width (minimum value is window width) */ public SWorld(int wide, int high, int cellSize, int scrollWide) { this(wide, high, cellSize, scrollWide, high); } /** * Adds the main actor into the world at the center of the window and * sets the range in movement within the window for the actor,<br> * <br> * NOTE: this method must be called prior to calling <i>setScrollingBackground</i> * <br> * NOTE 2: if placing the main actor to a location where scrolling will end up taking place before moving it, * place a call the the 'act' method of this class at the end of the constructor of its subclass * using 'super.act()'.<br> * * @param main the actor that is to always stay in view * @param xRange the horizontal range of movement within the window * @param yRange the vertical range of movement within the window */ public void setMainActor(Actor main, int xRange, int yRange) { if (main == null) { System.out.println("A main actor MUST be supplied."); System.out.println(""); return; } super.addObject(main, getWidth()/2, getHeight()/2); mainActor = main; xRange = (int)Math.min(xRange, getWidth()); yRange = (int)Math.min(yRange, getHeight()); actorMinX = getWidth()/2-xRange/2; actorMaxX = getWidth()/2+xRange/2; actorMinY = getHeight()/2-yRange/2; actorMaxY = getHeight()/2+yRange/2; } /** * Adds a scrolling background to the world; see method description for notes on unwanted results.<br> * <br> * NOTE: for this method to work, the main actor must have previously been set with <i>setMainActor</i>. The image will then * be scaled to the appropriate size and is centered in the scrollable world. * * @param scrollingBackground the image to be used for the scrolling background of the world */ public void setScrollingBackground(GreenfootImage scrollingBackground) { if(mainActor==null) { System.out.println("'setMainActor' MUST be called prior to calling 'setScrollingBackground'."); System.out.println(""); return; } background = new GreenfootImage(scrollingBackground); background.scale(scrollingWidth*getCellSize(), scrollingHeight*getCellSize()); scrollBackground(); } /** * Fills the background of the scrolling area with the <i>fillImage</i>.<br> * <br> * NOTE: for this method to work, the main actor must have previously been set with <i>setMainActor</i>. The image will then * be used to fill the background of the scrolling area and is centered in the scrollable world. * * @param fillImage the image to fill the background of the scrolling area with */ public void fillScrollingBackground(GreenfootImage fillImage) { if(mainActor==null) { System.out.println("'setMainActor' MUST be called prior to calling 'fillScrollingBackground'."); System.out.println(""); return; } if (fillImage.getWidth() < getWidth() && fillImage.getHeight() < getHeight()) { setBackground(new GreenfootImage(fillImage)); fillImage = getBackground(); } background = new GreenfootImage(scrollingWidth*getCellSize(), scrollingHeight*getCellSize()); for (int x=0; x<background.getWidth(); x+=fillImage.getWidth()) for (int y=0; y<background.getHeight(); y+=fillImage.getHeight()) background.drawImage(fillImage, x, y); scrollBackground(); } /** * Adds an object into the world, listing it in an the Actor array if it is a scrollable object * * @param obj the object to add to the world * @param xLoc the x-coordinate to place the object * @param yLoc the y-coordinate to place the object * @param scroller a flag indicating whether this object is of scrollable type or not */ public void addObject(Actor obj, int xLoc, int yLoc, boolean scroller) { super.addObject(obj, xLoc, yLoc); if (scroller) genActors.add(obj); } /** * Adds a scrollable object into the world, listing them in the Actor array. * * @param obj the scrollable object to add to the world * @param xLoc the x-coordinate to place the object * @param yLoc the y-coordinate to place the object */ public void addObject(Actor obj, int xLoc, int yLoc) { addObject(obj, xLoc, yLoc, true); } /** * Removes an object from the world, re-defining fields as neccessary * * @param obj the object to be removed from the world */ public void removeObject(Actor obj) { if (obj == null) return; if (obj.equals(mainActor)) mainActor = null; else genActors.remove(obj); super.removeObject(obj); } /** * Removes a collection of objects from the world, calling <i>removeObject(Actor)</i> for each one in the list * * @param objs the collection or list of objects to be removed from the world */ public void removeObjects(List<Actor>objs) { for (Actor obj : objs) removeObject(obj); } /** * Runs the scrolling. */ public void act() { scrollObjects(); scrollBackground(); } /** * Scrolls the background image. */ private void scrollBackground() { if (background == null) return; int w = getWidth(), h = getHeight(), c = getCellSize(); int bw = background.getWidth(), bh = background.getHeight(); getBackground().drawImage(background, (w*c-bw)/2-scrolledX*c, (h*c-bh)/2-scrolledY*c); } /** * Scrolls all scrollable object. Determines how far outside boundary limits the main actor is, and moves all neccessary * objects in the same direction, moving the main actor back within boundary limits. A background can be * made up of scrollable actor object(s) to produce a scrolling background; however, determining intersectors with object * will have to include the background object as being one or more of them when using <i>null</i> for the class of intersector. */ private void scrollObjects() { if (mainActor==null) return; // determine how far the main actor is outside its standard window limits int dx=0, dy=0; if (mainActor.getX() < actorMinX) dx = actorMinX-mainActor.getX(); if (mainActor.getX() > actorMaxX) dx = actorMaxX-mainActor.getX(); if (mainActor.getY() < actorMinY) dy = actorMinY-mainActor.getY(); if (mainActor.getY() > actorMaxY) dy = actorMaxY-mainActor.getY(); if (dx == 0 && dy == 0) return; // not outside window limits // ** outside standard window limits ** int dxSum = dx, dySum = dy; // hold changes in scroll amount scrolledX -= dx; scrolledY -= dy;// track scroll amount // move main actor back within standard window limits mainActor.setLocation(mainActor.getX()+dx, mainActor.getY()+dy); // determine how far the background is inside the world limits dx=0; dy=0; if (scrolledX > scrollingWidth/2-getWidth()/2) dx = scrolledX-(scrollingWidth/2-getWidth()/2); if (scrolledX < getWidth()/2-scrollingWidth/2) dx = scrolledX-(getWidth()/2-scrollingWidth/2); if (scrolledY > scrollingHeight/2-getHeight()/2) dy = scrolledY-(scrollingHeight/2-getHeight()/2); if (scrolledY < getHeight()/2-scrollingHeight/2) dy = scrolledY-(getHeight()/2-scrollingHeight/2); // ** background does not completely cover world limits dxSum += dx; dySum += dy; // keep running sum of changes in scroll amount scrolledX -= dx; scrolledY -= dy; // adjust scroll amount // move all objects so background covers the world mainActor.setLocation(mainActor.getX()+dx, mainActor.getY()+dy); for (Object obj : genActors) { Actor actor = (Actor)obj; actor.setLocation(actor.getX()+dxSum, actor.getY()+dySum); } // determine how far main actor is outside universal limits dx = 0; dy = 0; if (mainActor.getX() < 0) dx = 0-mainActor.getX(); if (mainActor.getX() > getWidth()-1) dx = (getWidth()-1)-mainActor.getX(); if (mainActor.getY() < 0) dy = 0-mainActor.getY(); if (mainActor.getY() > getHeight()-1) dy = (getHeight()-1)-mainActor.getY(); if (dx == 0 && dy == 0) return; // ** outside universal limits // move main actor back within world limits mainActor.setLocation(mainActor.getX()+dx, mainActor.getY()+dy); } /** * Returns the horizonal offset from the left edge of the scrolling world to the * left edge of the world window * * return the amount of scrollable background off the left edge of the world window */ public int getScrolledX() { return scrolledX; } /** * Returns the vertical offset from the top edge of the scrolling world to the * top edge of the world window * * return the amount of scrollable background off the top edge of the world window */ public int getScrolledY() { return scrolledY; } /** * Returns the width of the scrolling area of the universe * * @return the width of the visible scrolling area */ public int getScrollingWidth() { return scrollingWidth; } /** * Returns the height of the scrolling area of the universe * * @return the height of the visible scrolling area */ public int getScrollingHeight() { return scrollingHeight; } }