
/**
* CLASS: OpenScrollWorld
*
* DESCRIPTION: creates an unlimited scrolling world;
* a Fish object will be followed or scolling will be key controlled;
* all images used are part of the greenfoot image set;
* their filenames are shown within the code;
* to avoid jumping when changing actors,
* a limit is set on the speed of scrolling
*/
import greenfoot.*;
public class OpenScrollWorld extends World
{
public static final int WIDE = 800; // world width (viewport)
public static final int HIGH = 600; // world height (viewport)
Scroller scroller; // the object that performs the scrolling
Actor scrollActor; // the selected actor to stay in view
// creates an unlimited scrolling world
public OpenScrollWorld()
{
super(WIDE, HIGH, 1, false); // creates an unbounded world
GreenfootImage image = new GreenfootImage("wet-blue.jpg"); // background img
scroller = new Scroller(this, image); // creates Scroller object
scrollActor = new Fish(); // creates and sets an actor to stay in view
scrollActor.setImage("fish3.png"); // sets an image to the actor
addObject(scrollActor, WIDE/2, HIGH/2); // adds the actor in middle of world
Actor fish = new Fish(); // creates a second actor
fish.setImage("fish2.png"); // sets an image to this second actor
addObject(fish, WIDE/2, 100); // adds the second actor into world
fish = new Fish(); // creates a third actor
fish.setImage("fish1.png"); // sets an image to this third actor
addObject(fish, WIDE/2, 500); // adds the third actor into world
scroller.scroll(0, 0); // sets the initial background image
}
public void act()
{
if (scrollActor != null) scroll(); else keyScroll(); // perform scrolling
if (Greenfoot.mouseClicked(this))
scrollActor = null; // actor de-selection
}
// scroll by arrow keys
private void keyScroll()
{
// determine scrolling offsets and scroll
int dsx = 0, dsy = 0;
if (Greenfoot.isKeyDown("right")) dsx++;
if (Greenfoot.isKeyDown("left")) dsx--;
if (Greenfoot.isKeyDown("down")) dsy++;
if (Greenfoot.isKeyDown("up")) dsy--;
int rate = 2; // scroll speed
scroller.scroll(dsx*rate, dsy*rate);
}
// perform speed-governed center screen actor follow scrolling
private void scroll()
{
int rate = 3; // speed limit of scrolling
// determine offsets and scroll
int dsx = scrollActor.getX()-WIDE/2;
int dsy = scrollActor.getY()-HIGH/2;
int signX = (int)Math.signum(dsx), signY = (int)Math.signum(dsy);
dsx = signX*Math.min(Math.abs(dsx), rate);
dsy = signY*Math.min(Math.abs(dsy), rate);
scroller.scroll(dsx, dsy);
}
}
​
​
The following can be used to allow some actor movement before scrolling begins:\
​
// perform speed-governed roaming actor follow scrolling
private void scroll()
{
// roaming limits of actor
int loX = 100;
int hiX = WIDE-100;
int loY = 100;
int hiY = HIGH-100;
// determine offsets and scroll
int dsx = 0;
int dsy = 0;
if (scrollActor.getX() < loX) dsx = scrollActor.getX()-loX;
if (scrollActor.getX() > hiX) dsx = scrollActor.getX()-hiX;
if (scrollActor.getY() < loY) dsy = scrollActor.getY()-loY;
if (scrollActor.getY() > hiY) dsy = scrollActor.getY()-hiY;
int rate = 3; // speed limit of scrolling
int signX = (int)Math.signum(dsx), signY = (int)Math.signum(dsy);
dsx = signX*Math.min(Math.abs(dsx), rate);
dsy = signY*Math.min(Math.abs(dsy), rate);
scroller.scroll(dsx, dsy);
}
​
The code used in my Fish class follows:
​
import greenfoot.*;
​
public class Fish extends Actor
{
public void act()
{
if (((OpenScrollWorld)getWorld()).scrollActor == this) // if selected
{
// turning
if (Greenfoot.isKeyDown("right")) turn(1);
if (Greenfoot.isKeyDown("left")) turn(-1);
// moving
if (Greenfoot.isKeyDown("up")) move(2);
}
else if (Greenfoot.mouseClicked(this)) // else if selecting
{
((OpenScrollWorld)getWorld()).scrollActor = this; // set selection
}
else // not selected
{
turn(1);
move(2);
}
}
}