Java-如何调整2D游戏的大小?
我正在开发一个2D游戏,但我在调整尺寸方面遇到了困难。正如您在下面的代码中所看到的,我将所有游戏内容绘制到一个BuffereImage中。之后,我从我的JPanel获取图形并在上面绘制图像 所以我的问题是我现在如何调整我的游戏?我认为有很多可能性:1是图像也可以用jpanel调整大小,另一种方法是,如果你有一个2d世界,你可以调整框架大小,游戏的大小仍然相同,但你现在可以看到更多的2d世界,就像你的观看距离增加了一样 有人知道我的代码的解决方案吗Java-如何调整2D游戏的大小?,java,resize,components,Java,Resize,Components,我正在开发一个2D游戏,但我在调整尺寸方面遇到了困难。正如您在下面的代码中所看到的,我将所有游戏内容绘制到一个BuffereImage中。之后,我从我的JPanel获取图形并在上面绘制图像 所以我的问题是我现在如何调整我的游戏?我认为有很多可能性:1是图像也可以用jpanel调整大小,另一种方法是,如果你有一个2d世界,你可以调整框架大小,游戏的大小仍然相同,但你现在可以看到更多的2d世界,就像你的观看距离增加了一样 有人知道我的代码的解决方案吗 package de.avarion.theen
package de.avarion.theenchanter;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game implements Runnable{
public static int WIDTH = 800;
public static int HEIGHT = 600;
public static int FPS = 30;
private JFrame frame;
private JPanel panel;
private BufferedImage image;
private Graphics2D g;
private Thread thread;
private boolean running
public Game() {
panel = new JPanel();
panel.setPreferredSize(new Dimension(WIDTH, HEIGHT));
panel.setFocusable(true);
panel.requestFocus();
frame = new JFrame("The Enchanter - pre Alpha");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setVisible(true);
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
running = true;
thread = new Thread(this);
thread.start();
}
@Override
public void run() { //game loop
while(running) {
update();
render();
try {
Thread.sleep(1000/FPS);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
private void update() {
if(frame.getWidth() != WIDTH || frame.getHeight() != HEIGHT) {
frame.pack();
}
}
private void render() {
g.setColor(Color.black);//drawing on my image
g.fillRect(0, 0, WIDTH, HEIGHT);
Graphics g2 = panel.getGraphics(); // get graphics from panel
g2.drawImage(image, 0, 0, null); //drawing on my panel
g2.dispose();
}
}
让我们从
Graphics g2=panel.getGraphics()开始代码>-这不是在Swing中绘制的方式。Swing使用被动渲染算法,这意味着绘制周期可能会在任何时间出于任何原因发生,其中许多都超出了您的控制或知识范围
使用当前的方法,最多只能冒引入闪烁的风险,因为渲染循环和Swing相互竞争,或者由于线程和EDT之间的线程竞争条件而进行部分更新
您也不应该处理非自己创建的图形
上下文,在某些系统上,这实际上可能会阻止绘制任何内容
请查看,并获取更多详细信息
一个简单的解决方案是覆盖Swing组件的paintComponent
方法,如JPanel
,并直接在其中执行自定义绘制。这不仅允许您确定组件的当前大小,而且在调整组件大小时将自动调用paintComponent
方法
Swing组件在默认情况下是双缓冲的,所以您可以免费自动获得它
您可以使用Swing计时器
作为“游戏循环”,更新游戏的当前状态,并使用重新绘制管理器
安排重新绘制请求,例如
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int xPos, yPos;
private int xDelta = 2;
public TestPane() {
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int x = (int) (getWidth() * 0.1);
int y = (int) (getHeight() * 0.1);
int width = getWidth() - (x * 2);
int height = getHeight()- (y * 2);
xPos += xDelta;
yPos = y + ((height - 5) / 2);
if (xPos + 10 > x + width) {
xPos = x + (width - 10);
xDelta *= -1;
} else if (xPos < x) {
xPos = x;
xDelta *= -1;
}
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (int) (getWidth() * 0.1);
int y = (int) (getHeight() * 0.1);
g2d.drawRect(x, y, getWidth() - (x * 2), getHeight() - (y * 2));
g2d.setColor(Color.RED);
g2d.drawOval(xPos, yPos, 10, 10);
g2d.dispose();
}
}
}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.Timer;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
公开课考试{
公共静态void main(字符串[]args){
新测试();
}
公开考试(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(newtestpane());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
});
}
公共类TestPane扩展了JPanel{
私人int XPO、YPO;
私有int xDelta=2;
公共测试窗格(){
计时器计时器=新计时器(40,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
intx=(int)(getWidth()*0.1);
int y=(int)(getHeight()*0.1);
int width=getWidth()-(x*2);
int height=getHeight()-(y*2);
xPos+=xDelta;
yPos=y+((高度-5)/2);
如果(xPos+10>x+宽度){
xPos=x+(宽度-10);
xDelta*=-1;
}否则如果(xPos
如果你想让你对渲染过程有更多的控制,那么你需要考虑使用像A这样的东西。这使您可以执行一个活动的绘制过程,在需要时绘制缓冲区,而不必担心其他线程也会绘制缓冲区
有关更多详细信息,请参见:panel.getGraphics();这不是秋千上绘画的方式。而是重写组件的paintComponent方法,当系统调用时,执行正在绘制的操作。Swing使用被动绘制过程,因此在没有直接交互或知识的情况下,您可以随时绘制组件。调用时,您希望更新组件的当前状态。感谢您的回复,我不是java专家,但我会努力保持覆盖jpanels绘制方法的方式编辑:哈哈,很好:D现在我使用JPanel中的paintComponent方法,调整大小可以很好地工作,无需编写任何其他代码!!:D