游戏的无限背景

我正在研究一个Java项目来模拟直升机在一个框架中的飞行。 直升机使用箭头键在屏幕上移动。 我希望直升机能够无限移动,也就是说,当直升机到达框架的边缘时,背景应朝相反的方向移动,以产生无尽的地形效果。

这是我到目前为止的代码:

import java.awt.Graphics; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.net.URL; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.*; public class MainFrame extends JFrame { private static int FRAME_WIDTH = 800; private static int FRAME_HEIGHT = 500; public MainFrame() { add(new AnotherBackground(FRAME_WIDTH, FRAME_HEIGHT)); setTitle("Helicopter Background Test"); setSize(FRAME_WIDTH,FRAME_HEIGHT); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } public static void main(String[] args) { new MainFrame(); } } class AnotherBackground extends JPanel { private BufferedImage heliImage = null; private BufferedImage backImage = null; private int heliX = 0; private int heliY = 0; private int backX = 0; private int backY = 0; private int frameWidth = 0; private int frameHeight = 0; private int backWidth = 0; private int backHeight = 0; public AnotherBackground(int fWidth, int fHeight) { frameWidth = fWidth; frameHeight = fHeight; this.setFocusable(true); this.addKeyListener(new HeliListener()); try { heliImage = ImageIO.read(new URL("http://sofzh.miximages.com/java/helicopter2f.png")); // 2.7 Meg Crap that is a humungous image! Substitute dummy. backImage = new BufferedImage(1918,1200,BufferedImage.TYPE_INT_RGB); } catch(IOException ex) { System.out.println("Problem durinng loading heli image"); } backWidth = backImage.getWidth(); backHeight = backImage.getHeight(); HeliPainter l = new HeliPainter(); new Thread(l).start(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(backImage, backX, backY, null); g.drawImage(heliImage, heliX, heliY, null); } class HeliListener extends KeyAdapter { @Override public void keyPressed(KeyEvent e) { System.out.println(heliX + " " + heliY + " " + backX + " " + backY); if (e.getKeyCode() == KeyEvent.VK_LEFT) { if(heliX > 0) { heliX -= 5; } else { backX += 5; } } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { if(heliX  0) { heliY -= 5; } else { backY += 5; } } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { if(heliY < frameHeight) { heliY += 5; } else { backY -= 5; } } } } class HeliPainter implements Runnable { @Override public void run() { try { while(true) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { repaint(); } }); Thread.sleep(1); } } catch(InterruptedException ex) { System.out.println("Problem putting thread to sleep"); } } } } 

现在代码中有两个图像。 一个是小型直升机,另一个是大型(2.7兆)背景。 他们在这里:

  • 背景
  • 直升机http://imageshack.us/a/img7/2133/helicopter2f.png

如何连续显示BG?

看看这个源以更可预测的方式运行,并且还包括对斩波器图像( 动画 )的一个很好的调整 。 ;)

用BG滚动车辆

 import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.awt.image.BufferedImage; import java.net.URL; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.*; public class MainFrame { public MainFrame() { JFrame f = new JFrame("Helicopter Background Test"); f.add(new AnotherBackground()); //setTitle("Helicopter Background Test"); Redundant.. // Set a preferred size for the content area and pack() the frame instead! // setSize(FRAME_WIDTH,FRAME_HEIGHT); // setLocationRelativeTo(null); Better to.. f.setLocationByPlatform(true); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.pack(); // Size the GUI - VERY MPORTANT! f.setVisible(true); } public static void main(String[] args) { new MainFrame(); } } class AnotherBackground extends JPanel { private static int PREFERRED_WIDTH = 400; private static int PREFERRED_HEIGHT = 200; private BufferedImage heliImage = null; private BufferedImage heliLeftImage = null; private BufferedImage heliRightImage = null; private BufferedImage backImage = null; //getFlippedImage( private int heliX = 0; private int heliY = 0; private int backX = 0; private int backY = 0; private int frameWidth = 0; private int frameHeight = 0; private int backWidth = 0; private int backHeight = 0; public AnotherBackground() { frameWidth = PREFERRED_WIDTH; frameHeight = PREFERRED_HEIGHT; this.setFocusable(true); this.addKeyListener(new HeliListener()); try { heliLeftImage = ImageIO.read( new URL("http://imageshack.us/a/img7/2133/helicopter2f.png")); heliRightImage = getFlippedImage(heliLeftImage); heliImage = heliLeftImage; // 2.7 Meg Crap that is an humungous image! Substitute dummy. backImage = getTileImage(250); //ImageIO.read( // new URL("http://i.stack.imgur.com/T5uTa.png")); backWidth = backImage.getWidth(); backHeight = backImage.getHeight(); //HeliPainter l = new HeliPainter(); // see mention of repaint() //new Thread(l).start(); } catch(IOException ex) { // THERE IS NO POINT CONTINUING AFTER THIS POINT! // unless it is to pop an option pane error message.. System.out.println("Problem durinng loading heli image"); } } @Override public Dimension getPreferredSize() { return new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); int normalizeX = (heliRealX-heliX)%backImage.getWidth(); int normalizeY = (heliRealY-heliY)%backImage.getHeight(); int timesRepeatX = (getWidth()/backImage.getWidth())+2; int timesRepeatY = (getHeight()/backImage.getHeight())+2; for (int xx=-1; xx 0) { heliX -= 5; } else { backX += 5; } heliRealX-=5; heliImage = heliLeftImage; } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { // correct for image size + padding if(heliX+heliImage.getWidth()+pad < getWidth()) { heliX += 5; } else { backX -= 5; } heliRealX+=5; heliImage = heliRightImage; } else if (e.getKeyCode() == KeyEvent.VK_UP) { if(heliY > 0) { heliY -= 5; } else { backY += 5; } heliRealY-=5; } else if (e.getKeyCode() == KeyEvent.VK_DOWN) { // correct for image size + padding if(heliY+heliImage.getHeight()+pad < getHeight()) { heliY += 5; } else { backY -= 5; } heliRealY+=5; } repaint(); // Replaces need for threads for this simple demo! } } public BufferedImage getFlippedImage(BufferedImage original) { BufferedImage bi = new BufferedImage( original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D g = bi.createGraphics(); AffineTransform at = AffineTransform.getTranslateInstance(bi.getWidth(),1d); at.concatenate(AffineTransform.getScaleInstance(-1d,1d)); g.setTransform(at); g.drawImage(original,0,0,this); g.dispose(); return bi; } public BufferedImage getTileImage(int s) { BufferedImage bi = new BufferedImage(s,s,BufferedImage.TYPE_INT_ARGB); Graphics2D g = bi.createGraphics(); GradientPaint gp1 = new GradientPaint( (float)0,(float)s/4, Color.YELLOW, (float)s/4,0f, Color.GREEN, true); g.setPaint(gp1); g.fillRect(0,0,s,s); int trans = 165; GradientPaint gp2 = new GradientPaint( (float)s/2,(float)s/2, new Color(255,0,0,trans), 0f,(float)s/2, new Color(255,255,255,trans), true); g.setPaint(gp2); g.fillRect(0,0,s,s); g.dispose(); return bi; } } 

这是一个非常简单的例子(你只能向一个方向移动)。 基本思想是有一个prepareView方法,负责根据可用的可视区域生成世界视图。 如果视图正在尝试查看地图外的区域,则会标注地图以弥补它。

在此处输入图像描述

 import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class InfiniteBackground { public static void main(String[] args) { new InfiniteBackground(); } public InfiniteBackground() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public static class TestPane extends JPanel { protected static final int DELTA = 5; private BufferedImage terrian; private BufferedImage heli; private Point pov; private Point heliPoint; private BufferedImage view; public TestPane() { pov = new Point(); heliPoint = new Point(); try { terrian = ImageIO.read(getClass().getResource("/terrain_map.jpg")); heli = ImageIO.read(getClass().getResource("/helicopter2f.png")); pov.x = terrian.getWidth() - getPreferredSize().width; pov.y = ((terrian.getHeight() - getPreferredSize().height) / 2); heliPoint.x = getPreferredSize().width / 2; heliPoint.y = getPreferredSize().height / 2; prepareView(); InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); ActionMap am = getActionMap(); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "goLeft"); am.put("goLeft", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { heliPoint.x -= DELTA; if (heliPoint.x - (heli.getWidth() / 2) < 0) { heliPoint.x = (heli.getWidth() / 2); prepareView(); pov.x -= DELTA; } repaint(); } }); } catch (IOException ex) { ex.printStackTrace(); } } @Override public Dimension getPreferredSize() { return new Dimension(400, 200); } protected void prepareView() { if (getWidth() > 0 && getHeight() > 0) { view = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB); Graphics2D g2d = view.createGraphics(); if (pov.x < 0) { pov.x = terrian.getWidth(); } g2d.drawImage(terrian, -pov.x, -pov.y, this); if (pov.x + getWidth() > terrian.getWidth()) { g2d.drawImage(terrian, -pov.x + terrian.getWidth(), -pov.y, this); } g2d.dispose(); } } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (terrian != null) { Graphics2D g2d = (Graphics2D) g.create(); if (view == null) { prepareView(); } g2d.drawImage(view, 0, 0, this); g2d.drawImage(heli, heliPoint.x - (heli.getWidth() / 2), heliPoint.y - (heli.getHeight() / 2), this); g2d.dispose(); } } } }