油漆在PaintComponent中途发生

时间:2014-07-17 04:38:00

标签: java synchronization paintcomponent

很抱歉,如果这太具体了。我有一个非常艰难的时间试图表达我的搜索,并在这一点上摸不着头脑。我决定足够了,发帖以防万一有人可以帮助我。

所以下面的第一张图片显示了我遇到的问题,第二张图片显示的是大部分时间的样子。我有时会在我的游戏的顶层和底层不同步的情况下绘画不正确。我迭代所有瓷砖两次的原因是因为我需要在不同的层上绘制不同的东西。在某种程度上注意:我想知道速度是否有任何改进,例如使用双缓冲。

badpaint goodpaint

我的paintComponent代码很长,因为有很多要绘制,但我不确定为什么它会尝试重绘中途(在调用DrawTopMap()之前)。除非我错过了我认为存在的其他问题。

时间的抽样:

time: 17
time: 17
time: 19
time: 17
time: 18
time: 18
time: 19
time: 18
time: 17
time: 18

大部分时间这是相当一致的,这很好。任何帮助将非常感激。非常感谢你的时间!!

//bits and pieces to keep this short
public void paintComponent(Graphics g) {
    long startTime = System.currentTimeMillis();
    logger.trace("begin: REPAINTNG...");
    super.paintComponent(g);
    g2 = (Graphics2D)g;
    final Composite freshComp = g2.getComposite();

    //map
    DrawMap();
    g2.drawImage(gamePanelImage, 0, 0, null);

    //enemy: players
    for (Map.Entry<String, String> entry : playersHashTable.entrySet()) {
    ...
    g2.drawImage(SpriteSheetCutter.makeColorTransparent((BufferedImage) SpriteStore.get().getSprite(GetSpriteString(tempRace, tempGender)).getImage()), ((((MyClient.xTiles-1)*32)/2) - ((MyClient.characterX - tempX)*32)), ((((MyClient.yTiles-1)*32)/2) - ((MyClient.characterY - tempY)*32)), null);
    ...
    }

    //mobs
    //npcs

    //player
    g2.drawImage(SpriteSheetCutter.makeColorTransparent((BufferedImage) SpriteStore.get().getSprite(GetSpriteString(MyClient.characterRace, MyClient.characterGender)).getImage()), ((MyClient.xTiles-1)*32)/2, ((MyClient.yTiles-1)*32)/2, null);

    //above tiles
    DrawTopMap();
    g2.drawImage(gameTopPanelImage, 0, 0, null);

    g2.dispose();

    long endTime = System.currentTimeMillis();
    System.out.println("time: " + (endTime - startTime));
}

private void DrawMap() {
    int count = (MyClient.characterX - (MyClient.xTiles/2)) + ((MyClient.characterY - (MyClient.yTiles/2)) * MyClient.mapWidth); //top left map tile
    for (int x = 0; x < MyClient.xTiles; x++){
        for (int y = 0; y < MyClient.yTiles; y++){
            if (count > -1){
                if (!MyClient.groundLayer[count].equals("0")){ //don't draw full transparent tiles
                    SpriteStore.get().getSprite("res/images/tiles/" + MyClient.groundLayer[count] + ".png").draw(gamePanelImage, x * 32, y * 32);
                }
                if (!MyClient.buildingLayer[count].equals("0")){ //don't draw full transparent tiles
                    SpriteStore.get().getSprite("res/images/tiles/" + MyClient.buildingLayer[count] + ".png").draw(gamePanelImage, x * 32, y * 32);
                }
                if (!MyClient.objectLayer[count].equals("0")){ //don't draw full transparent tiles
                    SpriteStore.get().getSprite("res/images/tiles/" + MyClient.objectLayer[count] + ".png").draw(gamePanelImage, x * 32, y * 32);
                }
            }
            count += MyClient.mapWidth;
        }
        count -= MyClient.yTiles * MyClient.mapWidth;
        count++;
    }
}

private void DrawTopMap() {
    gameTopPanelImage = new BufferedImage(32 * MyClient.xTiles, 32 * MyClient.yTiles, BufferedImage.TYPE_INT_ARGB); //to prevent streaks
    int count = (MyClient.characterX - (MyClient.xTiles/2)) + ((MyClient.characterY - (MyClient.yTiles/2)) * MyClient.mapWidth);
    for (int x = 0; x < MyClient.xTiles; x++){
        for (int y = 0; y < MyClient.yTiles; y++){
            if (count > -1){
                if (!MyClient.topLayer[count].equals("0")){ //don't draw full transparent tiles
                    SpriteStore.get().getSprite("res/images/tiles/" + MyClient.topLayer[count] + ".png").draw(gameTopPanelImage, x * 32, y * 32);
                }
            }
            count += MyClient.mapWidth;
        }
        count -= MyClient.yTiles * MyClient.mapWidth;
        count++;
    }
}

@MadProgrammer ...当我移动(或其他东西)时,我的服务器返回一条消息。然后,我的客户端更新所有这些哈希映射,然后调用重绘:

SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        MyClient.gamePanel.repaint();
    }
});

修改

我已经弄明白了我的问题,但我没有丝毫想法如何解决它。我的客户端有时会画画,当我的客户端线程监听服务器的消息时会更新播放器的位置。在日志中查看竞争条件(我认为它被称为)。

20203 [AWT-EventQueue-0] INFO com.jayavon.game.graphics.MapGamePanel  - begin: PAINT...
20203 [AWT-EventQueue-0] INFO com.jayavon.game.graphics.MapGamePanel  - begin: REPAINTNG...
20203 [AWT-EventQueue-0] INFO com.jayavon.game.graphics.MapGamePanel  - Map drawing started.
13,21 //sign
20207 [Timer-0] INFO com.jayavon.game.client.MyClient  - promage@walkNorthWest
20207 [commandReceiver-promage] INFO com.jayavon.game.client.MyCommandReceiver  - promage-walkNorthWest@true|62,44
20212 [AWT-EventQueue-0] INFO com.jayavon.game.graphics.MapGamePanel  - Map drawing done.
20217 [AWT-EventQueue-0] INFO com.jayavon.game.graphics.MapGamePanel  - Map top drawing started.
14,22 //sign overlay
20217 [AWT-EventQueue-0] INFO com.jayavon.game.graphics.MapGamePanel  - Map top drawing done.
20222 [AWT-EventQueue-0] INFO com.jayavon.game.graphics.MapGamePanel  - end: REPAINTNG...

正如你所看到它在地图上绘制了标志,然后服务器告诉玩家它的移动是有效的,然后它改变了玩家的坐标,然后它绘制了叠加层,并重新绘制完成。我需要同步吗?我从来没有擅长(显然),有人能给我一些提示吗?

0 个答案:

没有答案