2017-07-19 37 views
1

第一篇文章,所以我会尽量保持清晰。 基本上,我想要做的是创建一个小游戏,你有一艘船,你可以从它射击子弹。船使用切线公式相应地旋转到玩家的DeltaX和DeltaY。我使用的是标准的游戏循环像这样的:一个对象中的图形正在影响另一个对象的图形 - JAVA

public void run() { 
    long lastTime = System.nanoTime(); 
    double amountOfTicks = 60.0; 
    double ns = 1000000000/amountOfTicks; 
    double delta = 0; 
    long timer = System.currentTimeMillis(); 
    @SuppressWarnings("unused") 
    int frames = 0; 
    while(running){ 
     long now = System.nanoTime(); 
     delta += (now - lastTime)/ns; 
     lastTime = now; 
     while(delta >=1){ 
       tick(); 
       delta--; 
      } 
     if(running) 
     repaint(); 
     frames++; 

     if(System.currentTimeMillis() - timer > 1000) 
     { 
      timer += 1000; 
      frames = 0; 
     } 
    } 
    stop(); 
} 

我的“游戏”运行在一个JPanel,一个名为董事会类的子类。在循环中,我调用更新信息的方法tick()和repaint(),该方法用作渲染方法。这是我的paintComponent(Graphics g)方法:

public void paintComponent(Graphics g) { 
    //This is for background 
    Graphics2D g2d = (Graphics2D) g; 
    g2d.setColor(Color.black); 
    g2d.fill(new Rectangle(0, 0, Constants.width, Constants.height)); 

    //This is where actual game rendering occurs 
    handler.render(g); 
    g.dispose(); 
} 

可以看出,我没有渲染我的Board类中的所有东西。我对我的处理程序这样做。这是我如何处理处理程序:

public void render(Graphics g) { 
    for (int i = 0; i < handlerList.size(); i++) { 
     //handlerList is a LinkedList 
     handlerList.get(i).render(g); 
    } 
} 

LinkedList handlerList包含实体。 实体是一个抽象类,它是玩家和子弹的父亲的生物的父亲。 这是一个播放器实例的渲染代码:其跟踪的对象条件

public void render(Graphics g) {   
    float centerX = x + (width/2); 
    float centerY = y + (height/2); 

    double theta = findAngle(deltaX, deltaY); 

    Graphics2D g2d = (Graphics2D) g; 
    if(!stopped) g2d.rotate(theta, centerX, centerY); 
    else g2d.rotate(stoppedTheta, centerX, centerY); 
    g2d.drawImage(shipImage, (int)x, (int)y, (int)width, (int)height, null); 
} 

有一个布尔“停止”。由于我希望能够旋转我的飞船,因此我使用Graphics2D而不是Graphics。

下面是子弹的渲染代码:

public void render(Graphics g) { 
    Graphics2D g2d = (Graphics2D) g; 

    g2d.setColor(Color.yellow); 
    g2d.fillOval((int)x, (int)y, (int)width, (int)height); 
} 

它看起来正确的,据我所知。每当我没有子弹,游戏运行良好,你可以看到在this GIF: 免责声明:抱歉低质量和水印,我刚格式化电脑,没有时间安装适当的东西。 ...

当我添加一颗子弹this发生:

x和子弹不会改变的y位置,但子弹与船舶旋转。我假设它与滥用“dispose()”方法有关,但我不确定可以采取什么措施来修复它。

预先感谢您。

+0

开始'的Graphics2D G2D =(Graphics2D的)克;''到的Graphics2D G2D =(Graphics2D的)g.create();' - 你不应该调用'在没有创建的上下文中处置 – MadProgrammer

+0

如果修改上下文的转换,则必须撤消该上下文,方法是创建上下文的快照并在完成上下文处理时进行处理,或手动对其进行处理并记住,转换正在复合 – MadProgrammer

+0

作为一般技巧,我会在它返回之前每次调用'render'方法和'g2d.dispose()'之前调用'Graphics2D g2d =(Graphics2D)g',因为我不相信其他的人们可能会这样做;) - 这意味着每个对象将获得它自己的'Graphics'上下文的快照 – MadProgrammer

回答

1
  1. 永远不要叫disposeGraphics环境下,你没有明确地创建(或快照与create),这可能进一步导致问题下来渲染管线。
  2. Graphics是一个共享的情境,因此你需要铭记的你做出的一些修改和撤消你做任何“显著”的转变,特别是转化

如果是我,我想创建一个每次调用render和它的后dispose以前Graphics上下文的快照,例如

public void render(Graphics g) { 
    for (int i = 0; i < handlerList.size(); i++) { 
     //handlerList is a LinkedList 
     Graphics2D g2d = (Graphics2D)g.create(); 
     handlerList.get(i).render(g2d); 
     g2d.dispose(); 
    } 
} 

这确保了什么都改变了render使得该Graphics上下文之前的下一个元素是被撤销呈现

如果更改复合,那么我会在循环开始之前创建快照,然后在它之后创建快照。

无论在哪种情况下,这意味着您可以控制所做的更改以及它们如何影响其他元素。

此外,请记住,转换是通过改变混合

相关问题