旋转多个图像导致闪烁。 Java Graphics2D

时间:2014-05-01 22:32:38

标签: java graphics

我正在创造一个自上而下的射击游戏,让僵尸跟着你并旋转直接瞄准你。如果最多有5个僵尸,则没有闪烁。如果有超过5个僵尸,则在屏幕上绘制的所有其他图像上都会闪烁。在我看来,随着越来越多的僵尸被添加,它导致游戏运行速度变慢,并且它不时地将其他图像略微抽出。 我正在使用Graphics2D并旋转图像。然后将绘制后的图像旋转回原始位置,这样就不会影响其后绘制的其他图像。 如何以像素为单位停止闪烁和轻微移动?

提前致谢!

以下是僵尸的代码......

 package com.game.stayalive;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;

public class Zombie extends Sprite {

Zombie() {
    x = -50;
    width = Display.spriteWidth;
    height = Display.spriteHeight;
    DELAY = rand.nextInt(8)+8;
    life = 5;
}

long lastUpdate;
boolean barrierDestroyed = false;
public void drawZombie(Graphics g,int playerX, int playerY) {

    if (!visible) {
        return;
    }
    Graphics2D g2d = (Graphics2D) g;

    direction = Math.atan2(y - playerY, x - playerX);

    g2d.rotate(direction - Math.PI / 2.0, x + width / 2, y + height / 2);
    if(DELAY > 10){
    g2d.setColor(Color.green.darker());
    }else{
        g2d.setColor(Color.red.darker());
    }
    // Main body rectangle
    g2d.drawRect(x, y, width, height);
    // Left arm
    g2d.drawRect(x - width / 2, y, width / 2, height);
    g2d.fillRect(x - width / 2, y, width / 2, height);
    // Right arm
    g2d.drawRect(x + width, y, width / 2, height);
    g2d.fillRect(x + width, y, width / 2, height);
    // Main body filled
    if(DELAY > 10){
    g2d.setColor(Color.green);
}else{
        g2d.setColor(Color.red);
    }
    g2d.fillRect(x, y, width, height);
    g2d.rotate(-(direction - Math.PI / 2.0), x + width / 2, y + height / 2);

}




long waited = System.currentTimeMillis();
long waitTime;
public void setWaitTime(long waitTime){
    this.waitTime = waitTime;
    if (System.currentTimeMillis() - waited < waitTime) {
        return;

    }
}
int moveSpeed = 10;

public void collisionDetection(Zombie zombie1, Zombie zombie2) {
    xAcc += gradientX;
    yAcc += gradientY;
    x = (int) xAcc;
    y = (int) yAcc;
    if (zombie1.getRect().intersects(zombie2.getRect()) && zombie1.visible &&  zombie1.life > 0) {
        xAcc -= gradientX;
        yAcc -= gradientY;
        xAcc += (gradientX/10)+rand.nextDouble()-0.5;
        yAcc += (gradientY/10) + rand.nextDouble()-0.5;
        x = (int) xAcc;
        y = (int) yAcc;
}
    xAcc -= gradientX;
    yAcc -= gradientY;
    x = (int) xAcc;
    y = (int) yAcc;
}

Random rand = new Random();
long spawnRate = 10000, lastZombieAdded;

public void addZombie() {
    if (System.currentTimeMillis() - lastZombieAdded > spawnRate) {
        Display.zombie.add(new Zombie());
        Display.zombie.get(Display.zombie.size()-1).visible = true;
        Display.zombie.get(Display.zombie.size()-1).setWaitTime(500);
        Display.zombie.get(Display.zombie.size()-1).xAcc = rand.nextInt(950);
        Display.zombie.get(Display.zombie.size()-1).yAcc = rand.nextInt(600);
        lastZombieAdded = System.currentTimeMillis();
    }
}
public void removeZombie(){
    for (int i = 0; i < Display.zombie.size(); i++) {
        if(!Display.zombie.get(i).visible ){
        Display.zombie.remove(i);
        }
    }
}

double gradientX, gradientY;

public void move() {
    setWaitTime(waitTime);
    if (life <= 0) {
        visible = false;
    }
    if (System.currentTimeMillis() - lastUpdate > DELAY) {
        xAcc += gradientX;
        yAcc += gradientY;
        x = (int) xAcc;
        y = (int) yAcc;
        lastUpdate = System.currentTimeMillis();
    }gradientX = -Math.cos(direction);
    gradientY = -Math.sin(direction);
    }

}

JPanel Class ......

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
            RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    player.drawPlayer(g2d);

    for (int i = 0; i < zombie.size(); i++) {
        if (zombie.get(i).visible) {
            zombie.get(i).drawZombie(g2d,playerX,playerY);
        }
    }
    for (int i = 0; i < pistol.size(); i++) {
        if (pistol.get(i).visible) {
            pistol.get(i).drawPistol(g2d);
        }
    }
    for (int i = 0; i < machineGun.size(); i++) {
        if (machineGun.get(i).visible) {
            machineGun.get(i).drawMachineGun(g2d);
        }
    }
    for (int i = 0; i < flamethrower.size(); i++) {
        if (flamethrower.get(i).visible) {
            flamethrower.get(i).draw(g2d);
        }
    }
    reloadBar.drawReloadBar(g2d);
    selector.drawSelector(g2d);
    money.draw(g2d);
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}
@Override
public void run() {
    long beforeTime, timeDiff, sleep;
    beforeTime = System.currentTimeMillis();
    while (true) {
        cycle();
        repaint();
        timeDiff = System.currentTimeMillis() - beforeTime;
        sleep = DELAY - timeDiff;
        if (sleep < 0) {
            sleep = 2;
        }
        try {
            Thread.sleep(sleep);
        } catch (InterruptedException e) {
            System.out.println("interrupted");
        }
        beforeTime = System.currentTimeMillis();
    }
}

}

&#34;僵尸&#34;是Zombie类的数组列表。 &#34;手枪&#34;其他也是用于子弹等的数组列表。被调用的循环方法用于移动所有图像,添加图像和检查冲突。对于代码无组织的道歉。 (我很快就会用不同的方法把它搞砸了)

1 个答案:

答案 0 :(得分:1)

这是我放在一起的一个非常简单的例子......

它基本上有一个具有随机运动和旋转的精灵。该程序能够渲染1到10,000个僵尸......认真......

我已经使用了你&#34;主循环&#34;同样,只是为了确定......

Zombies

没有真正的优化,如果我真的这样做,我会在某个地方设置一个可以拉出并放置的僵尸池,以减少创建它们所需的时间......

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class ZombieLand {

    protected static final Random RND = new Random();

    private static BufferedImage zombie;

    public static void main(String[] args) {
        new ZombieLand();
    }

    public ZombieLand() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                try {
                    zombie = ImageIO.read(getClass().getResource("/Zombie.png"));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }

                final ZombiePane zombiePane = new ZombiePane();

                final JSlider slider = new JSlider(1, 10000);
                slider.setMajorTickSpacing(1000);
                slider.setMinorTickSpacing(100);
                slider.setPaintTicks(true);
                slider.addChangeListener(new ChangeListener() {
                    @Override
                    public void stateChanged(ChangeEvent e) {
                        JSlider slider = (JSlider) e.getSource();
                        zombiePane.setZombies(slider.getValue());
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(zombiePane);
                frame.add(slider, BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        slider.setValue(10000);
                    }
                });
            }
        });
    }

    public static class ZombiePane extends JPanel {

        private List<ZombieSprite> sprites;
        protected static final Object SPRITE_LOCK = new Object();

        private int desiredCount = 1;

        public ZombiePane() {
            sprites = new ArrayList<>(25);
            sprites.add(new ZombieSprite());
            Thread t = new Thread(new MainLoop());
            t.setDaemon(false);
            t.start();
            Font font = getFont();
            setFont(font.deriveFont(Font.BOLD, 48f));
        }

        public void setZombies(int count) {
            desiredCount = count;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            synchronized (SPRITE_LOCK) {
                for (ZombieSprite sprite : sprites) {
                    sprite.paint(g2d);
                }
            }
            String text = Integer.toString(sprites.size());
            FontMetrics fm = g2d.getFontMetrics();
            g2d.drawString(text, getWidth() - fm.stringWidth(text), getHeight() - fm.getHeight() + fm.getAscent());
            g2d.dispose();
        }

        protected void cycle() {
            synchronized (SPRITE_LOCK) {
                if (desiredCount != sprites.size()) {
                    int count = 0;
                    int fill = 100;
                    while (sprites.size() > desiredCount && count < fill) {
                        sprites.remove(0);
                        count++;
                    }
                    count = 0;
                    while (sprites.size() < desiredCount && count < fill) {
                        sprites.add(new ZombieSprite());
                        count++;
                    }
                }

                for (ZombieSprite sprite : sprites) {
                    sprite.update(getWidth(), getHeight());
                }
            }
        }

        public class MainLoop implements Runnable {

            private int DELAY = 40;

            public void run() {
                long beforeTime, timeDiff, sleep;
                beforeTime = System.currentTimeMillis();
                while (true) {
                    cycle();
                    repaint();
                    timeDiff = System.currentTimeMillis() - beforeTime;
                    sleep = DELAY - timeDiff;
                    if (sleep < 0) {
                        sleep = 2;
                    }
                    try {
                        Thread.sleep(sleep);
                    } catch (InterruptedException e) {
                        System.out.println("interrupted");
                    }
                    beforeTime = System.currentTimeMillis();
                }
            }
        }
    }

    public static class ZombieSprite {

//        private BufferedImage zombie;
        private Point motionDelta;
        private double rotationDelta;

        private Point location;
        private double angle;

        public ZombieSprite() {
            motionDelta = new Point();
            motionDelta.x = (int) ((Math.random() * 3) + 1);
            motionDelta.y = (int) ((Math.random() * 3) + 1);
            if (Math.random() > 0.5) {
                motionDelta.x *= -1;
            }
            if (Math.random() > 0.5) {
                motionDelta.y *= -1;
            }
            rotationDelta = (int) ((Math.random() * 9) + 1);
            if (Math.random() > 0.5) {
                rotationDelta *= -1;
            }
        }

        public void paint(Graphics2D g2d) {
            if (location != null) {
                Graphics2D g = (Graphics2D) g2d.create();
                AffineTransform at = new AffineTransform();
                at.translate(location.x, location.y);
                at.rotate(Math.toRadians(angle), zombie.getWidth() / 2, zombie.getHeight() / 2);
                g.setTransform(at);
                g.drawImage(zombie, 0, 0, null);
                g.dispose();
            }
        }

        public void update(int width, int height) {
            if (location == null) {
                angle = (Math.random() * 360d);
                location = new Point();
                location.x = (int) (Math.random() * (width - zombie.getWidth()));
                location.y = (int) (Math.random() * (height - zombie.getHeight()));
            } else {
                angle += rotationDelta;
                location.x += motionDelta.x;
                location.y += motionDelta.y;

                if (location.x < 0) {
                    location.x = 0;
                    motionDelta.x *= -1;
                } else if (location.x + zombie.getWidth() > width) {
                    location.x = width - zombie.getWidth();
                    motionDelta.x *= -1;
                }
                if (location.y < 0) {
                    location.y = 0;
                    motionDelta.y *= -1;
                } else if (location.y + zombie.getHeight() > height) {
                    location.y = height - zombie.getHeight();
                    motionDelta.y *= -1;
                }
            }
        }

    }

}