【发布时间】:2014-06-18 12:38:36
【问题描述】:
我正在创建一个自上而下的射击游戏,让僵尸跟随你并旋转以直接瞄准你。如果有多达 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 类...
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();
}
}
}
"zombie" 是 Zombie 类的数组列表。 “Pistol”等也是用于子弹等的数组列表。被调用的循环方法用于移动所有图像,添加图像并检查碰撞。为代码的混乱程度道歉。 (我很快就会把它放在不同的方法里整理一下)
【问题讨论】:
-
你应该查找双缓冲。
-
如果这是你的意思,我已经在 JPanel 中完成了这个? setDoubleBuffered(true);
-
JPanel默认情况下是双缓冲的。实际的runnable example that demonstrates your problem 将涉及更少的猜测工作和更好的响应。 -
调用
setDoubleBuffered(true)应该没有必要。 Swing 默认情况下是双缓冲的。这里更有趣的是关于你如何和在哪里画这个的问题。应该从JPanel的paintComponent方法调用drawZombie方法。如有疑问,请发布您正在绘制此面板的代码(格式正确,如果可能...) -
“在我看来,随着更多僵尸的加入,它会导致游戏运行速度变慢” 我可以向您展示一个屏幕上有超过 4500 个动画对象的示例立即运行“合理”良好,当然没有闪烁。我认为还有其他事情发生 - 恕我直言