我正在尝试制作游戏。在这个游戏中,UI显示了多条路径(JPanel),其中障碍物(某种JComponent)沿着路径向下移动。用户(玩家)必须左右移动或切换路径以避开障碍物。这个游戏类似于谷歌小马快车。
https://www.google.com/doodles/155th-anniversary-of-the-pony-express
目前,由于我处于发展阶段,我只有一条路。 我有一个Player类,它扩展了JComponent并覆盖了绘制Component方法并绘制了一个蓝色方块。我有一个障碍组件类,它也扩展了JComponent并覆盖了paint组件方法并绘制了一个黑色圆圈。
在我的Board类中,我创建了一个名为theGame的JPanel,并在该路径中放置了一个路径,一个障碍组件和一个玩家。这个JPanel被放入JFrame。
玩家可以使用键监听器自由移动。我会将障碍组件放在一个地方,以便更容易进行调试。这不是主要问题。问题是我想在玩家与障碍物相交时结束游戏。我创建了类似于组件主体的骨架矩形。因此,例如,蓝色方块的矩形只是方形,而圆形是覆盖其内部大部分区域的矩形。所以我在两个矩形上调用intersects方法,如果是真的,我游戏结束。 但是,交叉方法不起作用。即使玩家和障碍物没有明显接触,intersects方法也会返回true。 (不,错误的刷新或类似的东西没有问题)。我如何与这两个对象相交? 如果回答者需要,将提供代码。
观察:我不确定,但我相信用于绘制玩家和障碍物的图形对象是不同的。为了验证这个假设,我在每个paintComponent方法中绘制了一个绿色方块,如下所示:
public void paintComponent(Graphics g)
{
//code to create the blue square
g2 = (Graphics2D) g;
rect = new Rectangle(x,y,w,h);
g2.setColor(Color.BLUE);
g2.fill(rect);
g2.draw(rect);
//code to see the green rectangle
Rectangle bill = new Rectangle(100,100,w,h);
g2.setColor(Color.GREEN);
g2.fill(bill);
g2.draw(bill);
}
原因在于,如果我使用播放器和障碍物的图形对象绘制一个看似相同坐标的绿色矩形,它们应该最终位于JPanel的相同位置。相反,绿色矩形对象出现在两个不同的位置。这让我相信图形对象使用不同的坐标系。如果是这样,如何为多个图形对象使用一个通用坐标系?
MCVE:我无法让这些类变小,因为如果我这样做,代码就不起作用了。 玩家等级:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import java.awt.event.*;
public class Player extends JComponent
{
private int x;
private int y;
private int h = 20;
private int w = 20;
private Rectangle rect;
private int dx=5;
private int dy=5;
private Graphics2D g2;
public Player(int x, int y)
{
this.x = x;
this.y = y;
rect= new Rectangle(x,y,w,h);
}
public void assignGraphics(Graphics g)
{
g2 = (Graphics2D)g;
}
public Player()
{
x=0;
y=0;
}
public void paintComponent(Graphics g)
{
g2 = (Graphics2D) g;
rect = new Rectangle(x,y,w,h);
g2.setColor(Color.BLUE);
g2.fill(rect);
g2.draw(rect);
Rectangle test = new Rectangle(100,100,w,h);
g2.setColor(Color.GREEN);
g2.fill(test);
g2.draw(test);
}
public Rectangle getRectComp()
{
return rect;
}
public void setMove(int a, int b)
{
x=x+a;
y=y+b;
repaint();
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
}
障碍组件:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import java.io.IOException;
public class ObstacleComponent extends JComponent
{
private int x;
private int y;
public Ellipse2D.Double elli;
private int dx=5;
private int dy=5;
private int h;
private int w;
private Graphics2D g2;
public ObstacleComponent(int x, int y, int h, int w)
{
this.x = x;
this.y = y;
this.h = h;
this.w = w;
}
public void assignGraphics(Graphics g)
{
g2 = (Graphics2D)g;
}
public ObstacleComponent()
{
x=0;
y=0;
}
public void paintComponent(Graphics g) // method declaration- a method which overrides the paintComponent method from the JComponent class.
// This method takes in an explicit parameter of a Graphics object
{
g2 = (Graphics2D) g;
elli = new Ellipse2D.Double(x,y,w,h);
g2.setColor(Color.BLACK);
g2.fill(elli);
g2.draw(elli);
Rectangle test= new Rectangle(0,0,w,h);
g2.setColor(Color.GREEN);
g2.fill(test);
g2.draw(test);
}
public void setMove(int a, int b)
{
x=x+a; // sets the dx variable to the value of parameter variable a
y=y+b;
repaint();
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public Rectangle getRectComp()
{
return new Rectangle(x,y,20,20);
}
}
路径:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.util.*;
import javax.swing.plaf.TableUI;
import javax.swing.table.TableColumn;
import java.awt.event.*;
import javax.swing.border.EtchedBorder;
public class Path extends JPanel implements ActionListener
{
public ArrayList <ObstacleComponent> badGuys;
private int interval;
private int xDimension = 1000;
private int yDimension = 600;
private Graphics2D pen;
public Path(int rate)
{
badGuys = new ArrayList<ObstacleComponent>();
setPreferredSize(new Dimension(xDimension, yDimension));
setBorder(new EtchedBorder());
setLayout(new GridLayout(1,1));
}
public Graphics2D getG()
{
return pen;
}
public void actionPerformed(ActionEvent av)
{
if(interval%10==0)
{
badGuys.add(new ObstacleComponent(200,10,20,20));
add(badGuys.get(badGuys.size()-1));
badGuys.get(badGuys.size()-1).assignGraphics(pen);
}
for(int b = 0;b<badGuys.size();b++)
{
badGuys.get(b).setMove(-5,0);
}
removeObstaclesOffTheScreen();
repaint();
interval++;
}
public void removeObstaclesOffTheScreen()
{
for(int b = 0;b<badGuys.size();b++)
{
if(badGuys.get(b).getX()<0)
{
remove(badGuys.remove(b));
}
}
}
}
板:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import java.util.*;
import javax.swing.plaf.TableUI;
import javax.swing.table.TableColumn;
import java.awt.event.*;
import javax.swing.border.EtchedBorder;
public class Board implements ActionListener {
// instance variables - replace the example below with your own
private ArrayList<Path> paths;
public JPanel theGame;
private int interval;
private int currentPlayerPath;
public Player player;
private int pathNumber = 1;//4;
private int levelTime;
private int levelRate;
private boolean notGameOver;
private int removeThisCounter=0;
private int timeToChangeRate;
private Random gen;
private int levelRange = 20;
public Board()
{
theGame = new JPanel();
setLayout(pathNumber);
player = new Player();
levelRate = 0;
paths = new ArrayList<Path>();
gen = new Random();
for(int a = 0;a<pathNumber;a++)
{
paths.add(new Path(getRandomRate()));
}
for(int a = 0;a<pathNumber;a++)
{
theGame.add(paths.get(a));
}
currentPlayerPath=0;
setCurrentPlayerPath();
}
public JPanel returnTheGamePanel()
{
return theGame;
}
public void setLayout(int paths)
{
theGame.setLayout(new GridLayout(pathNumber, paths));
}
public void setCurrentPlayerPath()
{
paths.get(currentPlayerPath).add(player);
player.assignGraphics(paths.get(currentPlayerPath).getG());
}
public boolean hit()
{
Path currentPath = paths.get(currentPlayerPath);
for(int a = 0;a<currentPath.badGuys.size();a++)
{
Object b = player.getRectComp();
Object c = currentPath.badGuys.get(a).getRectComp();
if (((Rectangle)b).intersects((Rectangle)c))
{
return true;
}
else
{
System.out.println("player: " + player.getX() + " " + player.getY());
System.out.println("badguy: " + currentPath.badGuys.get(a).getX() + " " + currentPath.badGuys.get(a).getY());
}
}
return false;
}
public void actionPerformed(ActionEvent av)
{
for(int a = 0;a<pathNumber;a++)
{
paths.get(a).actionPerformed(av);
}
player.repaint();
theGame.revalidate();
theGame.repaint();
}
public void gameOver()
{
notGameOver=!notGameOver;
}
public boolean isGameOver()
{
return notGameOver;
}
}
发动机:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.sound.sampled.*;
import java.io.*;
import java.awt.geom.*;
public class Engine {
public static void main (String[] args) {
JOptionPane.showMessageDialog(null, "Press arrow key to move.");
final JFrame display = new JFrame();
display.setSize(1000, 600);
display.setTitle("Code does not work");
display.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
final Board b = new Board();
class TimedAction implements ActionListener
{
private int removeThisCounter=0;
public void actionPerformed(ActionEvent av)
{
b.actionPerformed(av);
if(b.hit())
{
System.out.println("HIT!!"+removeThisCounter);
removeThisCounter++;
}
display.revalidate();
display.repaint();
}
}
class PlayerAction implements KeyListener
{
public void keyPressed (KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode==KeyEvent.VK_LEFT)
{
b.player.setMove(-7, 0);
}
if(keyCode==KeyEvent.VK_RIGHT)
{
b.player.setMove(7, 0);
}
if(keyCode==KeyEvent.VK_UP)
{
b.player.setMove(0,-7);
}
if(keyCode==KeyEvent.VK_DOWN)
{
b.player.setMove(0,7);
}
else
{
b.player.setMove(0,0);
}
}
public void keyReleased(KeyEvent e) {} //method delcaration for empty methods needed to override the abstract methods of the KeyListener interface
public void keyTyped(KeyEvent e) {}
}
Timer theTime = new Timer(1000, new TimedAction());
theTime.start();
JPanel masterPanel = new JPanel();
display.addKeyListener(new PlayerAction());
masterPanel.add(b.returnTheGamePanel());
display.add(masterPanel);
display.setVisible(true);
}
}