Java 我与JPanel、getWidth和getHeight斗争
所以我昨天开始了这个“项目”,我想尝试一个立方体与windows边框碰撞的程序。看起来很简单 然而,我与边界作斗争。我似乎无法在窗户的右侧和底部找到“完美”的collison。立方体总是比预期的要远一点 我认为问题与我设置窗口大小的方式有关?我不确定,但我尝试了一些改变,但没有成功 代码如下:Java 我与JPanel、getWidth和getHeight斗争,java,swing,jpanel,Java,Swing,Jpanel,所以我昨天开始了这个“项目”,我想尝试一个立方体与windows边框碰撞的程序。看起来很简单 然而,我与边界作斗争。我似乎无法在窗户的右侧和底部找到“完美”的collison。立方体总是比预期的要远一点 我认为问题与我设置窗口大小的方式有关?我不确定,但我尝试了一些改变,但没有成功 代码如下: package spritesInJava; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; im
package spritesInJava;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.ImageObserver;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Game {
public static JFrame myGame;
public static Timer timer;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createGame();
timer.start();
}
});
}
public static void createGame() {
myGame = new JFrame("Felicia");
myGame.add(new MyPanel());
myGame.pack();
myGame.setSize(new Dimension(1000,1000));
myGame.setPreferredSize(new Dimension(1000,1000));
myGame.setVisible(true);
myGame.setDefaultCloseOperation(1);
MyPanel.loadImage();
}
}
class MyPanel extends JPanel implements ActionListener {
private static Image image; //Sprite
private static final long serialVersionUID = 1251340649341903871L;
private static ImageObserver observer;
private int x = 50;
private int y = 50;
private int width = 200;
private int height = 100;
private int speedx = 2;
private int speedy = 2;
MyPanel() {
Game.timer = new Timer(10,this);
}
@Override
public void actionPerformed(ActionEvent e) {
int screenWidth = Game.myGame.getWidth();
int screenHeight = Game.myGame.getHeight();
x+=speedx;
y+=speedy;
if(x >= screenWidth - width) {
speedx = -speedx;
}
else if(x < 0 ) {
speedx = -speedx;
}
if(y >= screenHeight- height ) {
speedy = -speedy;
}
else if(y < 0 ) {
speedy = -speedy;
}
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
//g.drawImage(image, x, y,width,height,observer); //Uses the image that was loaded below and draws it.
g.fillRect(x, y, width, height);
}
public static void loadImage() { //Load the image
ImageIcon icon = new ImageIcon("photos/Felicia.png");
image = icon.getImage(); //Set the "temp" ImageIcon icon to the public ImageIcon
}
}
package spritesInJava;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Image;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.image.ImageObserver;
导入javax.swing.ImageIcon;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.SwingUtilities;
导入javax.swing.Timer;
公开课游戏{
公共静态jframemygame;
公共静态定时器;
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createGame();
timer.start();
}
});
}
公共静态void createGame(){
myGame=新JFrame(“Felicia”);
添加(新的MyPanel());
myGame.pack();
myGame.setSize(新维度(10001000));
myGame.setPreferredSize(新维度(10001000));
myGame.setVisible(true);
myGame.setDefaultCloseOperation(1);
MyPanel.loadImage();
}
}
类MyPanel扩展JPanel实现ActionListener{
私有静态映像;//Sprite
私有静态最终长serialVersionUID=1251340649341903871L;
专用静态图像观测器;
私人整数x=50;
私人int y=50;
私有整数宽度=200;
私人内部高度=100;
私人整数速度x=2;
私有int=2;
我的小组(){
Game.timer=新计时器(10,此);
}
@凌驾
已执行的公共无效操作(操作事件e){
int screenWidth=Game.myGame.getWidth();
int screenHeight=Game.myGame.getHeight();
x+=速度x;
y+=快速;
如果(x>=屏幕宽度-宽度){
speedx=-speedx;
}
else如果(x<0){
speedx=-speedx;
}
如果(y>=屏幕高度-高度){
迅捷=-迅捷;
}
else if(y<0){
迅捷=-迅捷;
}
重新油漆();
}
公共组件(图形g){
超级组件(g);
//g、 drawImage(图像,x,y,宽度,高度,观察者);//使用下面加载的图像并绘制它。
g、 fillRect(x,y,宽度,高度);
}
public static void loadImage(){//加载映像
ImageIcon=新的ImageIcon(“photos/Felicia.png”);
image=icon.getImage();//将“temp”ImageIcon图标设置为public ImageIcon
}
}
立方体应该撞击4个边界中的一个,然后变为“-速度”,因此如果速度为5,则速度应完全相反(负),并转向另一个方向。这是可行的,但有点太晚了。我做的碰撞系统似乎不起作用
很抱歉将所有代码放在一个类中
提前谢谢 所以,这似乎马上就错了
myGame.add(new MyPanel());
myGame.pack();
myGame.setSize(new Dimension(1000, 1000));
myGame.setPreferredSize(new Dimension(1000, 1000));
myGame.setVisible(true);
在设置/确定首选大小之前,您将pack
窗口,这意味着窗口将希望采用尽可能最小的大小(因为内容的preferredSize
默认为0x0
)
一般来说,您应该避免调用setPreferredSize
,但我尤其要避免在JFrame
上使用它
为什么??由于JFrame
具有嵌入窗口的装饰(窗口标题和边框),因此可查看的大小实际上是frameSize-decorationSets
,这将成为以后问题的核心
因此,我将在MyPanel
中覆盖getPreferredSize
,并指定组件的“可视”范围
class MyPanel extends JPanel implements ActionListener {
//...
@Override
public Dimension getPreferredSize() {
return new Dimension(1000, 1000);
}
然后在你的主课上你可以做
myGame = new JFrame("Felicia");
myGame.add(new MyPanel());
myGame.pack();
myGame.setVisible(true);
API将为您解决这个问题
好的,下一个问题
public void actionPerformed(ActionEvent e) {
int screenWidth = Game.myGame.getWidth();
int screenHeight = Game.myGame.getHeight();
Game.myGame
是一个JFrame
,您要求的是窗口大小,但正如我前面所说,框架带有装饰,这些装饰嵌入到框架中,减少了组件可用的可视区域。相反,您应该使用组件本身的大小
public void actionPerformed(ActionEvent e) {
int screenWidth = getWidth();
int screenHeight = getHeight();
一些建议。。。
我认为需要这些
public static JFrame myGame;
public static Timer timer;
但是我在使用static
;)时遇到了一个问题。使myGame
static
可以“轻松”地从代码中没有任何责任的位置访问其功能
在这种情况下,Timer
是有争议的,但我可能会尝试使用一个“更新引擎”来封装它和过度更新的工作流,但这就是我;)
我认为这不是必需的(必须是静态的
)
功能应该在组件创建时由组件本身创建(或通过其他“设置”阶段)。我还鼓励使用ImageIO.read
,因为当出现问题时,它会生成IOException
,而不像ImageIcon
那样会无声失败
作为一个附带的好处(使用ImageIO.read
),您还可以知道图像何时完成加载,因为该方法在加载之前不会返回,这意味着您不必冒一些空帧的风险
你不需要
private static ImageObserver observer;
它也不需要是静态的(就像是私有的),但是,
JPanel实际上是一个ImageObserver
,所以你可以把这个传递给drawImage,所以,很快,这似乎是错误的
myGame.add(new MyPanel());
myGame.pack();
myGame.setSize(new Dimension(1000, 1000));
myGame.setPreferredSize(new Dimension(1000, 1000));
myGame.setVisible(true);
在设置/确定首选大小之前,您将pack
窗口,这意味着窗口将希望采用尽可能最小的大小(因为内容的preferredSize
是