Download presentation
Presentation is loading. Please wait.
Published byErnest Stokes Modified over 8 years ago
1
Chapter 11: Scrolling with Greenfooot
2
What Is Scrolling? Scrolling is an important and often necessary concept in games. It can be used to: a)Convey a sense of movement to the player. b)Implement a world that extends beyond the immediate borders of the visible screen.
3
What Is Scrolling? Generally speaking, we cannot see what is not on the screen until we scroll in the direction of what is off-screen. To emphasize the scrolling movement, it is necessary to have a background that changes as we scroll. This gives the player visual cues, telling them that they are moving to a new position in the world.
4
What Is Scrolling? For example, lets assume the following is the entire world of a game: However, at any one time you can only see half of this world (due to screen restrictions):
5
What Is Scrolling? When we scroll to the right, a different portion of the world comes into view:
6
Using Scrolling Whenever we want to have a level that exceeds or appears to exceed a single “frame”, we have to use scrolling. The scrolling can either be automatic, or depend on the movement of a player- controller actor. If the player moves to the right, we want to scroll our level accordingly, etc.
7
How To Implement Scrolling We can manage the scrolling of the World’s background by creating a method that shifts the background-image itself. The game might require movement in more then 1 dimension, so a general scrolling method should be able to handle both an x and y offset. For simplicities sake, we will start with scrolling in only dimension.
8
How To Implement Scrolling It is certainly possible to implement scrolling using fixed and complex images (as shown in earlier slides with out “panorama”). However, it is usually preferable to scroll a pattern created by repeating simple cells.
9
Pattern Scrolling A pattern that is scrolled as a background image should be a pattern that repeats seamlessly. This means that if we put the image side by side next to itself, there would be no visible breaks or gaps:
10
Pattern Scrolling When we use a repeatable pattern (of size less than our World) as our World-image, the pattern will be automatically tiled. This means it is placed end to end until it fills up the whole screen. Due to tiling, we can scroll the screen by continually shifting where the drawing of the pattern starts. To do this, we will be using the drawImage() method of the GreenfootImage class.
11
Pattern Scrolling An example: If we want to scroll 10 pixels to the left, we will do so by starting the drawing-process 10 pixels to the right. However, this leaves empty space at the left.
12
Pattern Scrolling We can fill this empty space by going one screen width to the left from our initial position, and drawing an entire screen length of background starting from there:
13
Pattern Scrolling Only the part within the Greenfoot window is actually seen by the user, so it appears that the background has scrolled by whatever amount we shifted it:
14
Pattern Scrolling Note that this process can be applied to scrolling both left and right. When scrolling to the right, we will simply shift our image to the left. The resulting empty space can be filled in by going one screen length to the right and drawing another full screen.
15
Pattern Scrolling Thus, to implement a scroll-effect we will draw our background-image at least twice: once offset to the left (i.e. by a negative value) once offset to the right (i.e. by a positive value) Scrolling left and scrolling right differ only in how far we offset left/right and how they are perceived by the user. The process itself stays the same.
16
Pattern Scrolling This means that we can implement a normalized shifting process by always shifting in one direction first. For example: if dx is the shift amount and WIDTH is the screen width, then the following code ensures that the shift always starts from the left: dx = dx % WIDTH; // keep shift amount within one width if (dx > 0) dx = dx - WIDTH; // always draw the left-offset image first
17
The World act() method So far, we have only used Actor based act() methods. However, it is also possible to create World-based act() methods. Generally speaking, an act() method of a World object functions just like the act() method of an Actor object: It gets called continuously and can be used to implement tasks that require constant repetition (such as scrolling).
18
Pattern Scrolling Below is code that implements a continual shift for a generic World of size 400*300: private static final int WIDTH = 400; private static final int HEIGHT = 300; private GreenfootImage bgImage; private int scrollSpeed = 2; private int scrollPosition = 0; public ScrollWorld() { super(WIDTH, HEIGHT, 1); bgImage = new GreenfootImage(getBackground()); } public void act() { scrollBackground(-scrollSpeed); }
19
Pattern Scrolling private void scrollBackground(int dx) { dx = dx % WIDTH; if (dx > 0) dx = dx - WIDTH; scrollPosition = (scrollPosition + dx) % WIDTH; GreenfootImage bg = getBackground(); bg.drawImage(bgImage,scrollPosition,0); bg.drawImage(bgImage,scrollPosition + WIDTH, 0); } Because of the act() method in this World class, this code immediately starts shifting the background left. A positive dx value would shift it to the right.
20
Using Pattern Scrolling The horizontalScrolling scenario is a modification of our Asteroids scenario. It uses the exact code we just discussed and random enemy spawning to create the impression of our rocket actually moving through space.
21
Pattern Scrolling Scrolling in the vertical direction is very similar to scrolling in the horizontal direction. We substitute the WIDTH constant with HEIGHT throughout our code, and use the y-coordinate argument for the drawImage commands: bg.drawImage(bgImage,scrollPosition,0); bg.drawImage(bgImage,scrollPosition + WIDTH, 0); bg.drawImage(bgImage, 0, scrollPosition); bg.drawImage(bgImage, 0, scrollPosition + HEIGHT);
22
Pattern Scrolling Scrolling both horizontally and vertically functions very similar to just scrolling horizontally. However, it requires some additional code, as we need to take 2 dimensions into account: private static final int WIDTH = 600; private static final int HEIGHT = 600; private GreenfootImage bgImage; private int scrollSpeed = 2; private int scrollHPosition = 0; private int scrollVPosition = 0; public ScrollWorld() { super(WIDTH, HEIGHT, 1); bgImage = new GreenfootImage(getBackground()); }
23
Pattern Scrolling public void act() { scrollBackground(-scrollSpeed, scrollSpeed); } private void scrollBackground(int dx, int dy) { dx = dx % WIDTH; if (dx > 0) dx = dx - WIDTH; scrollHPosition = (scrollHPosition + dx) % WIDTH; dy = dy % HEIGHT; if (dy > 0) dy = dy - HEIGHT; scrollVPosition = (scrollVPosition + dy) % HEIGHT; GreenfootImage bg = getBackground();
24
Pattern Scrolling bg.drawImage(bgImage,scrollHPosition, scrollVPosition); bg.drawImage(bgImage,scrollHPosition + WIDTH, scrollVPosition); bg.drawImage(bgImage,scrollHPosition, scrollVPosition + HEIGHT); bg.drawImage(bgImage,scrollHPosition + WIDTH, scrollVPosition + HEIGHT); } Because of the act() method, this code will immediately start shifting the background down and to the left.
25
Using Pattern Scrolling The horizontalandVerticalScrolling scenario is a modification of our Asteroids scenario. In this scenario, the Rocket seems to move diagonally. It is also unable to fire Bullets and thus has to dodge incoming Asteroids.
26
Input-based Scrolling So far, we have only implemented automatic scrolling. While this works well for some types of game, it is not always a sufficient solution. On the following slides, we will discuss how to implement Input and Actor based scrolling.
27
Connecting Input and Scrolling Luckily, we can use the same tools to implement manual scrolling as we have used previously to implement manual movement: public void act() { if (Greenfoot.isKeyDown("left")) scrollBackground(-scrollSpeed,0); if (Greenfoot.isKeyDown("right")) scrollBackground(scrollSpeed,0); if (Greenfoot.isKeyDown("up")) scrollBackground(0,-scrollSpeed); if (Greenfoot.isKeyDown("down")) scrollBackground(0,scrollSpeed); }
28
Bounded and Unbounded Worlds In Greenfoot, a World can be bounded or unbounded. We cannot place an object in a coordinate that is off of the World when a world is bounded. The object will simply be placed on the nearest edge, and no farther. When a world is unbounded, we can place objects at coordinates outside of the world. In combination with scrolling, this will allow us to build Worlds that expand beyond a single screen.
29
Bounded and Unbounded Worlds Imagine a 400x300 world with a wombat in it, and you try to move the wombat to position (500,150). The following would be the result: In the bounded case it gets stuck on the nearest edge (400, 150). In the unbounded case it goes off the screen and we can no longer see it. However, the wombat still exists in our game.
30
Bounded and Unbounded Worlds By default, Worlds in Greenfoot are bounded. If we want an unbounded world, we must pass the value of false as the fourth value to the super() call in the constructor of the world: super(400,300,1,false); // 400x300 unbounded world
31
Scrolling Actors While we are able to scroll manually, this is a purely aesthetic effect so far: only the background moves. If we want to get to our lost wombat back, we have to move our Actor objects, too. We will use a new method for this: public void scrollActors(int dx, int dy)
32
Scrolling Actors Conceptually, the scrollActors method functions similar to the scrollBackground method. We supply two parameters and the method shifts the objects in that direction. However, we apply the changes not to our background, but to specific Actor objects. public void scrollActors(int dx, int dy) { List actors = getObjects(Wombat.class); for(Actor a : actors) { a.setLocation(a.getX()+dx, a.getY()+dy);} }
33
Using Input-based Scrolling The scrollingPengu scenario implements user-controlled scrolling and Actor scrolling. Specifically, the background and the Ground objects scroll left/right, depending on what key is being pressed. The only part of the scenario that is NOT moving is the Pengu object, as the Pengu class it is not included in the scrollActors method.
34
Picture Image Scrolling Instead of scrolling patterns, we can also use fixed images as scrollable backgrounds. However, we have to take care that the image connects to itself more or less seamlessly in the direction we want to scroll:
35
Picture Image Scrolling A Panorama Image:
36
Picture Image Scrolling Note: Complex images rarely connect seamlessly to themselves in both dimensions.
37
Picture Image Scrolling While panorama images look nice, they are usually only repeatable horizontally. This means they cannot be properly vertically tiled by Greenfoot. There are two ways to handle this issue: 1)Scale (stretch or shrink) the image to exactly fit the window size horizontally and vertically 2)Scale (stretch or shrink) the image to make the height match the window height and let the image exceed the window horizontally
38
Scaling to Exactly fit the Window When you scale to exactly fit the window, your image may be contorted, and that may or may not present a problem: The above example shows how when then whole image is scaled to fit the screen the mountains look thinner. This change in the look and feel may or may not be a problem.
39
Picture Image Scrolling w/ Contortion If the contortion is not a problem, then we can use the following code to scroll the background. In this case, the image is named "landscape.jpg": private static final int WIDTH = 400; private static final int HEIGHT = 300; private GreenfootImage bgImage; private int scrollSpeed = 2; private int scrollPosition = 0; public ScrollWorld() { super(WIDTH, HEIGHT, 1); bgImage = new GreenfootImage("landscape.jpg"); bgImage.scale(WIDTH,HEIGHT) ; getBackground().drawImage(bgImage,0,0); }
40
Picture Image Scrolling w/ Contortion public void act() { scrollBackground(-scrollSpeed); } private void scrollBackground(int dx) { dx = dx % WIDTH; if (dx > 0) dx = dx- WIDTH; scrollPosition = (scrollPosition + dx) % WIDTH; GreenfootImage bg = getBackground(); bg.drawImage(bgImage,scrollPosition,0); bg.drawImage(bgImage,scrollPosition + WIDTH, 0); } Once again, because of the act() method in this World class, this code immediately starts shifting the background left. A positive dx value would shift it to the right.
41
Picture Image Scrolling w/o Contortion If the contortion is a problem, then we need to use a different approach. We will set the height of the image to be the same as the height of the screen. However, we will re-calculate the width of the image to keep the original aspect ratio: WIDTH2 = ( bgImage.getWidth() / bgImage.getHeight() ) * HEIGHT
42
Picture Image Scrolling w/o Contortion private static final int WIDTH = 400; private static final int HEIGHT = 300; private final int pictureWidth; private GreenfootImage bgImage; private int scrollSpeed = 2; private int scrollPosition = 0; public ScrollWorld() { super(WIDTH, HEIGHT, 1); bgImage = new GreenfootImage("landscape.jpg"); pictureWidth = (int) ((double) bgImage.getWidth() / bgImage.getHeight() * HEIGHT); bgImage.scale(pictureWidth,HEIGHT) ; getBackground().drawImage(bgImage,0,0); }
43
Picture Image Scrolling w/o Contortion public void act() { scrollBackground(-scrollSpeed); } private void scrollBackground(int dx) { dx = dx %pictureWidth; if (dx > 0) dx = dx - pictureWidth; scrollPosition = (scrollPosition + dx) % pictureWidth; GreenfootImage bg = getBackground(); bg.drawImage(bgImage,scrollPosition,0); bg.drawImage(bgImage,scrollPosition + pictureWidth, 0); }
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.