Training and Consulting | ||
| Home |
| Previous Page - The revenge of the Monsters | Current Page - 25 - A Scrolling playfield | Next Page - Monster respawning |
| Return to the index of free Java tutorials |
A Scrolling playfieldMany shooters achieve a very nice effect by adding a scrolling background. This effect is very easy to achieve simply by erasing the screen with a texture instead of a solid black color. The scrolling effect is achieved by changing the coordinates of the anchor rectangle. To understand this, imagine that we have the following image, which we'll use as a texture:
If we fill the screen with it using an anchor rectangle of (0,0,256,256), we get the following effect:
Now if we use an anchor rectangle of (0,20,256,256), that is, if we increase the y coord of the upper left corner of the rectangle, we get the following :
The effect is as if the whole background had moved 20 points downwards. Precisely this is what we'll be using to achieve a scrolling background. Of course, there are quicker ways to achieve the same effect, but we'll use this as a starting point. We also want a smoother movement, so we will be increasing the position of the anchor rectangle one pixel per turn. And of course we will use an image better suited for a background, like the following one, called "oceano.gif":
The only class that is changed in this step is the Invaders class, and it becomes the following:
1 package version25; 2 /** 3 * Curso B?sico de desarrollo de Juegos en Java - Invaders 4 * 5 * (c) 2004 Planetalia S.L. - Todos los derechos reservados. Prohibida su reproducci?n 6 * 7 * http://www.planetalia.com 8 * 9 */ 10 11 12 import java.awt.Canvas; 13 import java.awt.Color; 14 import java.awt.Dimension; 15 import java.awt.Font; 16 import java.awt.Graphics2D; 17 import java.awt.Rectangle; 18 import java.awt.TexturePaint; 19 import java.awt.event.KeyEvent; 20 import java.awt.event.KeyListener; 21 import java.awt.event.WindowAdapter; 22 import java.awt.event.WindowEvent; 23 import java.awt.image.BufferStrategy; 24 import java.awt.image.BufferedImage; 25 import java.util.ArrayList; 26 27 import javax.swing.JFrame; 28 import javax.swing.JPanel; 29 30 public class Invaders extends Canvas implements Stage, KeyListener { 31 32 private BufferStrategy strategy; 33 private long usedTime; 34 35 private SpriteCache spriteCache; 36 private ArrayList actors; 37 private Player player; 40 41 private boolean gameEnded=false; 42 43 public Invaders() { 44 spriteCache = new SpriteCache(); 45 46 47 JFrame ventana = new JFrame("Invaders"); 48 JPanel panel = (JPanel)ventana.getContentPane(); 49 setBounds(0,0,Stage.WIDTH,Stage.HEIGHT); 50 panel.setPreferredSize(new Dimension(Stage.WIDTH,Stage.HEIGHT)); 51 panel.setLayout(null); 52 panel.add(this); 53 ventana.setBounds(0,0,Stage.WIDTH,Stage.HEIGHT); 54 ventana.setVisible(true); 55 ventana.addWindowListener( new WindowAdapter() { 56 public void windowClosing(WindowEvent e) { 57 System.exit(0); 58 } 59 }); 60 ventana.setResizable(false); 61 createBufferStrategy(2); 62 strategy = getBufferStrategy(); 63 requestFocus(); 64 addKeyListener(this); 65 } 66 67 public void gameOver() { 68 gameEnded = true; 69 } 70 71 public void initWorld() { 72 actors = new ArrayList(); 73 for (int i = 0; i < 10; i++){ 74 Monster m = new Monster(this); 75 m.setX( (int)(Math.random()*Stage.WIDTH) ); 76 m.setY( i*20 ); 77 m.setVx( (int)(Math.random()*20-10) ); 78 79 actors.add(m); 80 } 81 82 player = new Player(this); 83 player.setX(Stage.WIDTH/2); 84 player.setY(Stage.PLAY_HEIGHT - 2*player.getHeight()); 85 } 86 87 public void addActor(Actor a) { 88 actors.add(a); 89 } 90 91 public Player getPlayer() { 92 return player; 93 } 94 95 public void updateWorld() { 96 int i = 0; 97 while (i < actors.size()) { 98 Actor m = (Actor)actors.get(i); 99 if (m.isMarkedForRemoval()) { 100 actors.remove(i); 101 } else { 102 m.act(); 103 i++; 104 } 105 } 106 player.act(); 107 } 108 109 public void checkCollisions() { 110 Rectangle playerBounds = player.getBounds(); 111 for (int i = 0; i < actors.size(); i++) { 112 Actor a1 = (Actor)actors.get(i); 113 Rectangle r1 = a1.getBounds(); 114 if (r1.intersects(playerBounds)) { 115 player.collision(a1); 116 a1.collision(player); 117 } 118 for (int j = i+1; j < actors.size(); j++) { 119 Actor a2 = (Actor)actors.get(j); 120 Rectangle r2 = a2.getBounds(); 121 if (r1.intersects(r2)) { 122 a1.collision(a2); 123 a2.collision(a1); 124 } 125 } 126 } 127 } 128 129 public void paintShields(Graphics2D g) { 130 g.setPaint(Color.red); 131 g.fillRect(280,Stage.PLAY_HEIGHT,Player.MAX_SHIELDS,30); 132 g.setPaint(Color.blue); 133 g.fillRect(280+Player.MAX_SHIELDS-player.getShields(),Stage.PLAY_HEIGHT,player.getShields(),30); 134 g.setFont(new Font("Arial",Font.BOLD,20)); 135 g.setPaint(Color.green); 136 g.drawString("Shields",170,Stage.PLAY_HEIGHT+20); 137 138 } 139 140 public void paintScore(Graphics2D g) { 141 g.setFont(new Font("Arial",Font.BOLD,20)); 142 g.setPaint(Color.green); 143 g.drawString("Score:",20,Stage.PLAY_HEIGHT + 20); 144 g.setPaint(Color.red); 145 g.drawString(player.getScore()+"",100,Stage.PLAY_HEIGHT + 20); 146 } 147 148 public void paintAmmo(Graphics2D g) { 149 int xBase = 280+Player.MAX_SHIELDS+10; 150 for (int i = 0; i < player.getClusterBombs();i++) { 151 BufferedImage bomb = spriteCache.getSprite("bombUL.gif"); 152 g.drawImage( bomb ,xBase+i*bomb.getWidth(),Stage.PLAY_HEIGHT,this); 153 } 154 } 155 156 public void paintfps(Graphics2D g) { 157 g.setFont( new Font("Arial",Font.BOLD,12)); 158 g.setColor(Color.white); 159 if (usedTime > 0) 160 g.drawString(String.valueOf(1000/usedTime)+" fps",Stage.WIDTH-50,Stage.PLAY_HEIGHT); 161 else 162 g.drawString("--- fps",Stage.WIDTH-50,Stage.PLAY_HEIGHT); 163 } 164 165 166 public void paintStatus(Graphics2D g) { 167 paintScore(g); 168 paintShields(g); 169 paintAmmo(g); 170 paintfps(g); 171 } 172 173 public void paintWorld() { 174 Graphics2D g = (Graphics2D)strategy.getDrawGraphics(); The effect we get is the following:
and our game has now a nice looking scrolling background |
||||||||
Do you want to be notified when new tutorials or lessons are published? Press here
| Actor.java | Bomb.java | Bullet.java | Invaders.java |
| Laser.java | Monster.java | Player.java | SpriteCache.java |
| Stage.java |
| Previous Page - The revenge of the Monsters | Current Page - 25 - A Scrolling playfield | Next Page - Monster respawning |
| Return to the index of free Java tutorials |
(c) 2004 Planetalia S.L. All rights reserved. Unauthorized reproduction and/or mirroring is not permitted