我正在制作Point课程,以便更轻松地制作积分。我希望它在我自己的坐标系统和屏幕的坐标系之间进行转换,但是当我调用方法getWidth时,它表示它为null并给出NullPointerException。这是我的Point类:
import java.awt.Graphics2D;
import java.awt.Image;
public class Point extends GameLoop{
public float X, Y;
private float scale;
public float getScale() {
return scale;
}
public void setScale(float scale) {
this.scale = scale;
}
public Point toScreenCoordinates(){
return new Point(((this.X + scale)/2 * screen.getWidth()), ((this.Y + scale)/2 * screen.getHeight()));
}
public void drawImageHere(Image i, Graphics2D g){
Point p = this.toScreenCoordinates();
g.drawImage(i, Math.round(p.X) - i.getWidth(null)/2, (Math.round(p.Y) - i.getHeight(null))/2, null);
}
public Point(float x, float y){
X = x;
Y = y;
scale = 1;
}
public void update(long timePassed) {
}
public void draw(Graphics2D g) {
}
}
这是我的GameLoop类,其中包含屏幕对象:
import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Window;
public abstract class GameLoop {
private static DisplayMode[] modes = {
new DisplayMode(800, 600, 32, 0),
new DisplayMode(800, 600, 24, 0),
new DisplayMode(800, 600, 16, 0),
new DisplayMode(640, 480, 32, 0),
new DisplayMode(640, 480, 24, 0),
new DisplayMode(640, 480, 16, 0)
};
private boolean running;
public Animation a;
public int fps;
public ScreenManager screen;
public void stopAll(){
running = false;
}
public void run(){
try{
init();
gameLoop();
}finally{
screen.restoreScreen();
}
}
public void gameLoop(){
long startTime = System.currentTimeMillis();
long cumTime = startTime;
while(running){
long timePassed = System.currentTimeMillis() - cumTime;
cumTime += timePassed;
update(timePassed);
Graphics2D g = screen.getGraphics();
draw(g);
g.dispose();
screen.update();
a.update(timePassed);
try{
Thread.sleep((1000 + (fps - (1000 % fps)))/fps);
}catch(Exception ex){}
}
}
public void init(){
fps = 60;
a = new Animation();
screen = new ScreenManager();
DisplayMode dm = screen.findFirstCompatibleMode(modes);
screen.setFullScreen(dm);
Window w = screen.getFullScreenWindow();
w.setFont(new Font("Times New Roman", Font.PLAIN, 30));
w.setBackground(Color.YELLOW);
w.setForeground(Color.BLACK);
running = true;
}
public abstract void update(long timePassed);
public abstract void draw(Graphics2D g);
}
这是我的ScreenManager类,它是我的屏幕变量是以下对象的类:
import java.awt.DisplayMode;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Window;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class ScreenManager {
private GraphicsDevice vc;
public ScreenManager(){
GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
vc = e.getDefaultScreenDevice();
}
public DisplayMode[] getCompatibleDisplayModes(){
return vc.getDisplayModes();
}
public DisplayMode findFirstCompatibleMode(DisplayMode[] modes){
DisplayMode goodModes[] = vc.getDisplayModes();
for(int x = 0;x<modes.length;x++){
for(int y = 0;y<goodModes.length;y++){
if(displayModesMatch(modes[x], goodModes[y])){
return modes[x];
}
}
}
return null;
}
public boolean displayModesMatch(DisplayMode m1, DisplayMode m2){
if(m1.getWidth() != m2.getWidth() || m1.getHeight() != m2.getHeight()){
return false;
}
if(m1.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m2.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI && m1.getBitDepth() != m2.getBitDepth()){
return false;
}
if(m1.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m2.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN && m1.getRefreshRate() != m2.getRefreshRate()){
return false;
}
return true;
}
public DisplayMode getCurrentDisplayMode(){
return vc.getDisplayMode();
}
public void setFullScreen(DisplayMode dm){
JFrame f = new JFrame();
f.setUndecorated(true);
f.setResizable(false);
f.setIgnoreRepaint(true);
vc.setFullScreenWindow(f);
if(dm != null && vc.isDisplayChangeSupported()){
try{
vc.setDisplayMode(dm);
}catch(Exception ex){}
}
f.createBufferStrategy(2);
}
public Graphics2D getGraphics(){
Window w = vc.getFullScreenWindow();
if(w != null){
BufferStrategy s = w.getBufferStrategy();
return (Graphics2D)s.getDrawGraphics();
}else{
return null;
}
}
public void update(){
Window w = vc.getFullScreenWindow();
if(w != null){
BufferStrategy s = w.getBufferStrategy();
if(!s.contentsLost()){
s.show();
}
}
}
public Window getFullScreenWindow(){
return vc.getFullScreenWindow();
}
public int getWidth(){
Window w = vc.getFullScreenWindow();
if(w != null){
return w.getWidth();
}else{
return 0;
}
}
public int getHeight(){
Window w = vc.getFullScreenWindow();
if(w != null){
return w.getHeight();
}else{
return 0;
}
}
public void restoreScreen(){
Window w = vc.getFullScreenWindow();
if(w != null){
w.dispose();
}
vc.setFullScreenWindow(null);
}
public BufferedImage createCompatibleImage(int w, int h, int t){
Window win = vc.getFullScreenWindow();
if(win != null){
GraphicsConfiguration gc = win.getGraphicsConfiguration();
return gc.createCompatibleImage(w, h, t);
}else{
return null;
}
}
}
答案 0 :(得分:0)
您只是在GameLoop的init方法中初始化屏幕字段,而且只能从run方法调用。
构建Point时,它会创建自己的屏幕字段,因为它是GameLoop的子类。所以它没有使用你可能拥有的GameLoop类的屏幕字段。
你实际上并不需要Point扩展GameLoop。但是如果你这样做,你必须在构造函数中初始化Point的本地版本的屏幕。