我正在尝试通过在Jpanel上添加Jpanel来制作2D赛车游戏。这是通过使用我在下面发布的2个类来完成的。
问题是汽车永远不会出现在赛道上......我真的不确定我错过了什么......任何帮助都非常受欢迎!
提前谢谢!
public class Car extends JPanel implements Runnable
{
private static final long serialVersionUID = 007;
private BufferedImage car = null;
private float x = 100F, y = 100F;
private Thread driveThread = new Thread(this);
private double currentAngle = 0; // angel of the car
private static int[] key = new int[256]; // keyboard input
private float MAX_SPEED = 7F;
private float speed = 0F; // speed of our racing car
private float acceleration = 0.15F;
private int player;
private boolean playable = true;
public Car(int player)
{
this.player = player;
this.setSize(super.getHeight(), super.getWidth());
this.setFocusable(true); // enables keyboard
try
{
if (player == 1)
{
//red car
car = ImageIO.read(this.getClass().getResource(
"/imagesCar/first-0.png"));
System.out.println(car.getColorModel());
} else if(player == 2)
{
//blue car
car = ImageIO.read(this.getClass().getResource(
"/imagesCar/second-0.png"));
x = x +30;
}
} catch (IOException e) {
System.out.println("dupi");
}
// starts the drive thread
startGame();
}
private void startGame() {
driveThread.start();
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setOpaque(false);
// rotation
Graphics2D g2d = (Graphics2D) g;
AffineTransform rot = g2d.getTransform();
// Rotation at the center of the car
float xRot = x + 12.5F;
float yRot = y + 20F;
rot.rotate(Math.toRadians(currentAngle), xRot, yRot);
g2d.setTransform(rot);
//Draws the cars new position and angle
g2d.drawImage(car, (int) x, (int) y, 50, 50, this);
}
protected void calculateCarPosition() {
//calculates the new X and Y - coordinates
x += Math.sin(currentAngle * Math.PI / 180) * speed * 0.5;
y += Math.cos(currentAngle * Math.PI / 180) * -speed * 0.5;
}
protected void carMovement() {
// Player One Key's
if (player == 1) {
if (key[KeyEvent.VK_LEFT] != 0) {
currentAngle-=2;
} else if (key[KeyEvent.VK_RIGHT] != 0) {
currentAngle+=2;
}
if (key[KeyEvent.VK_UP] != 0) {
if (speed < MAX_SPEED) {
speed += acceleration;
}
} else if (key[KeyEvent.VK_DOWN] != 0 && speed > -1) {
speed = speed - 0.1F;
}
speed = speed * 0.99F;
} else {
//Player Two Key's
if (key[KeyEvent.VK_A] != 0) {
currentAngle -= 2;
} else if (key[KeyEvent.VK_D] != 0) {
currentAngle += 2;
}
if (key[KeyEvent.VK_W] != 0) {
if (speed < MAX_SPEED) {
speed += acceleration;
}
} else if (key[KeyEvent.VK_S] != 0 && speed > -1) {
speed = speed - 0.1F;
}
//reduce speed when no key is pressed
speed = speed * 0.99F;
}
}
public void getUnderground() {
}
// get key events!
final protected void processKeyEvent(KeyEvent e) {
key[e.getKeyCode()] = e.getID() & 1;
}
@Override
public void run() {
while (true) {
repaint();
carMovement();
calculateCarPosition();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class RaceTrack extends JPanel
{
@Override
public void paintComponent(Graphics g)
{
Color c1 = Color.green;
g.setColor(c1);
g.fillRect(150, 200, 550, 300);
Color c2 = Color.black;
g.setColor(c2);
g.drawRect(50, 100, 750, 500); // outer edge
g.drawRect(150, 200, 550, 300); // inner edge
Color c3 = Color.yellow;
g.setColor(c3);
g.drawRect(100, 150, 650, 400); // mid-lane marker
Color c4 = Color.white;
g.setColor(c4);
g.drawLine(425, 500, 425, 600); // start line
}
}
public static void main(String[] args) {
JFrame mainFrame = new JFrame();
mainFrame.setSize(850,650);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content = mainFrame.getContentPane();
RaceTrack track = new RaceTrack();
Car carP1 = new Car(1);
track.add(carP1);
content.add(track);
mainFrame.setVisible(true);
}
答案 0 :(得分:1)
0x0
Car
添加到使用RaceTrack
的{{1}}会将FlowLayout
布局为Car
的首选大小不确定这是否是解决此问题的正确方法
不要为此目的使用组件,这个问题只是尖叫自定义绘画。
有很多关于基本游戏开发的博客和教程,所以我不想花很多时间浏览相同的材料。
基本上,你想要的是为你想要在游戏中使用的对象定义一系列“属性”(AKA“实体”)。并非所有实体都需要具有可绘制性,有些实体可能触发其他操作,或者只是充当其他实体使用的“标记”。
在这个例子中,我定义了两个基本实体,“可移动”和“可绘制”。 “可绘制的”实体可以是静态的(即轨道)或“可移动的”(即汽车)
目的是提供一个孤立的功能概念,可以很容易地应用于真实对象,以“描述”他们在游戏中的功能和目的。
例如......
0x0
因此,在您的情况下,public interface MovableEntity extends Entity {
public void update(Rectangle bounds);
}
public interface PaintableEntity extends Entity {
public void paint(Graphics2D g2d, ImageObserver imageObserver, Rectangle bounds);
}
同时为Car
和Paintable
。
然后,您的“引擎”将维护这些“实体”的一个或多个列表并相应地处理它们。
这个例子只是使用Swing Movable
作为“主循环”
Timer
这提供了一定程度的线程安全性,因为mainLoop = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight());
// Lots of collision detection and other awesome stuff
for (MovableEntity entity : movableEntitys) {
entity.update(bounds);
}
repaint();
}
});
mainLoop.start();
是在事件调度线程的上下文中触发的,这意味着当我们更新实体时,它们不能被绘制。
然后我们只是使用Timer
的{{1}}方法充当渲染过程......
JPanel
这是一个非常广泛的例子,它基于以简单的方式展示基本概念。有更复杂的可能解决方案遵循相同的基本原则。
就个人而言,我会定义某种“路径”作为轨道,然后汽车会根据不同因素计算出位置,但这是一个更复杂的解决方案,现在需要。但如果你真的感兴趣,它可能看起来像like this
paintComponent