gpt4 book ai didi

java - 将图像移动到新位置后删除图像

转载 作者:行者123 更新时间:2023-12-02 06:28:33 25 4
gpt4 key购买 nike

我正在制作小行星游戏。一切功能都正常工作,但最初我将背景颜色设置为黑色,并用在 Canvas 上移动的形状表示对象。此后,我将背景更改为Image,并正在努力更改由图像表示的对象。

但是,无论背景如何,我都无法在新位置重新绘制图像。您可以看到每个对象移动到每个新位置后的路径。我主要关注的是射击,我注意到如果我在屏幕周围射击,背景就会刷新,但它看起来几乎是完全随机的。如果有人可以帮助引导我朝正确的方向前进,那就太好了!我阅读了一些文档、教科书,并观看了一些视频来试图理解。

package comets;


import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;
import javax.sound.sampled.*;
import javax.swing.*;

import java.util.*;
import java.io.*;
import java.net.URL;

// This class is primarily responsible for organizing the game of Comets
public class CometsMain extends JPanel implements KeyListener
{



// GUI Data
private JFrame frame; // The window itself
private JPanel playArea; // The area where the game takes place



private final int playWidth = 500; // The width of the play area (in pixels)
private final int playHeight = 500; // The height of the play area (in pixels)

// Game Data
private SpaceObject spaceObject;
private Ship ship; // The ship in play
private Shot s = new Shot(0, 0, 0, 0);
private LargeComet large = new LargeComet(0, 0, 0, 0);
private MediumComet medium = new MediumComet(0, 0, 0, 0);
private SmallComet small = new SmallComet(0, 0, 0, 0);
private Vector<Shot> shots; // The shots fired by the player
private Vector<Comet> comets; // The comets floating around

private boolean shipDead; // Whether or not the ship has been blown up
private long shipTimeOfDeath; // The time at which the ship blew up

// Keyboard data
// Indicates whether the player is currently holding the accelerate, turn
// left, or turn right buttons, respectively
private boolean accelerateHeld = false;
private boolean turnLeftHeld = false;
private boolean turnRightHeld = false;
private boolean slowDownHeld = false;

// Indicates whether the player struck the fire key
private boolean firing = false;


// Create Images
private Image background; // background image
private BufferedImage spaceShip = null;
private BufferedImage largeComet = null;
private BufferedImage mediumComet = null;
private BufferedImage smallComet = null;
private BufferedImage bullet = null;
private int type = AlphaComposite.SRC_OVER;
private float alpha = 0;










// Set up the game and play!
public CometsMain()
{





// Get everything set up
configureGUI();
configureGameData();



// Display the window so play can begin
frame.setVisible(true);

//Use double buffering
frame.createBufferStrategy(2);

//play music
playMusic();

// Start the gameplay
playGame();






}

private void playMusic(){

try {

URL url = this.getClass().getClassLoader().getResource("BackgroundMusic.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);

Clip clip = AudioSystem.getClip();

clip.open(audioIn);

clip.start();
clip.loop(5);

} catch (Exception e) {
e.printStackTrace();
}
}

// Set up the initial positions of all space objects
private void configureGameData()
{
// Configure the play area size
SpaceObject.playfieldWidth = playWidth;
SpaceObject.playfieldHeight = playHeight;

// Create the ship
ship = new Ship(playWidth/2, playHeight/2, 0, 0);

// Create the shot vector (initially, there shouldn't be any shots on the screen)
shots = new Vector<Shot>();

// Read the comets from comets.cfg
comets = new Vector<Comet>();

try
{
Scanner fin = new Scanner(new File("comets.cfg"));

// Loop through each line of the file to read a comet
while(fin.hasNext())
{
String cometType = fin.next();
double xpos = fin.nextDouble();
double ypos = fin.nextDouble();
double xvel = fin.nextDouble();
double yvel = fin.nextDouble();

if(cometType.equals("Large"))
comets.add(new LargeComet(xpos, ypos, xvel, yvel));
else if(cometType.equals("Medium")){
comets.add(new MediumComet(xpos, ypos, xvel, yvel));
}
else
comets.add(new SmallComet(xpos, ypos, xvel, yvel));
}
}
// If the file could not be read correctly for whatever reason, abort
// the program
catch(FileNotFoundException e)
{
System.err.println("Unable to locate comets.cfg");
System.exit(0);
}
catch(Exception e)
{
System.err.println("comets.cfg is not in a proper format");
System.exit(0);
}
}

// Set up the game window
private void configureGUI()
{
// Load Images & Icons
// Background Image
try {
background = ImageIO.read(this.getClass().getClassLoader().getResource("galaxy.jpg"));
} catch (IOException e) {
}

// Space Ship Image
try {
spaceShip = ImageIO.read(this.getClass().getClassLoader().getResource("ship.png"));
} catch (IOException e) {
}

// Large Comet Image
try {
largeComet = ImageIO.read(this.getClass().getClassLoader().getResource("largecomet.png"));
} catch (IOException e) {
}

// Medium Comet Image
try {
mediumComet = ImageIO.read(this.getClass().getClassLoader().getResource("mediumcomet.png"));
} catch (IOException e) {
}

// Medium Comet Image
try {
smallComet = ImageIO.read(this.getClass().getClassLoader().getResource("smallcomet.png"));
} catch (IOException e) {
}

// bullet Image
try {
bullet = ImageIO.read(this.getClass().getClassLoader().getResource("bullet.png"));
} catch (IOException e) {
}





// Create the window object
frame = new JFrame("Comets");
frame.setSize(playWidth+20, playHeight+35);
frame.setResizable(false);


// The program should end when the window is closed
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);



frame.setSize(playWidth, playHeight);
// Set the window's layout manager
frame.setLayout(new FlowLayout());



// Create background
JLabel bgLabel = new JLabel( new ImageIcon(background.getScaledInstance(playWidth, playHeight, 0) ) );
bgLabel.setSize(playWidth, playHeight);
frame.setContentPane(bgLabel);
frame.pack();



// Create the play area
playArea = new JPanel();
playArea.setSize(playWidth, playHeight);
playArea.setFocusable(false);
playArea.setOpaque(false);
frame.add(playArea);






// Make the frame listen to keystrokes
frame.addKeyListener(this);


}


// The main game loop. This method coordinates everything that happens in
// the game
private void playGame()
{


while(true)
{
// Measure the current time in an effort to keep up a consistent
// frame rate
long time = System.currentTimeMillis();

// If the ship has been dead for more than 3 seconds, revive it
if(shipDead && shipTimeOfDeath + 3000 < time)
{
shipDead = false;
ship = new Ship(playWidth/2, playHeight/2, 0, 0);
}

// Process game events, move all the objects floating around,
// and update the display
if(!shipDead)
handleKeyEntries();
handleCollisions();
moveSpaceObjects();

// Sleep until it's time to draw the next frame
// (i.e. 32 ms after this frame started processing)
try
{
long delay = Math.max(0, 32-(System.currentTimeMillis()-time));

Thread.sleep(delay);
}
catch(InterruptedException e)
{
}

}
}

// Deal with objects hitting each other
private void handleCollisions()
{
// Anything that is destroyed should be erased, so get ready
// to erase stuff
Graphics g = playArea.getGraphics();
Graphics2D g2d = (Graphics2D) g;
g2d.setComposite(AlphaComposite.getInstance(type, alpha));

// Deal with shots blowing up comets
for(int i = 0; i < shots.size(); i++)
{
Shot s = shots.elementAt(i);
for(int j = 0; j < comets.size(); j++)
{
Comet c = comets.elementAt(j);

// If a shot has hit a comet, destroy both the shot and comet
if(s.overlapping(c))
{

// Erase the bullet
shots.remove(i);
i--;
repaint((int)shots.elementAt(i).getXPosition(), (int)shots.elementAt(i).getYPosition(), (int)(2*shots.elementAt(i).getRadius()), (int)(2*shots.elementAt(i).getRadius()));

// If the comet was actually destroyed, replace the comet
// with the new comets it spawned (if any)
Vector<Comet> newComets = c.explode();

if(newComets != null)
{

paintComponent(g);
comets.remove(j);
j--;
comets.addAll(newComets);
}
break;
}
}
}

// Deal with comets blowing up the ship
if(!shipDead)
{
for(Comet c : comets)
{
// If the ship hit a comet, kill the ship and mark down the time
if(c.overlapping(ship))
{
shipTimeOfDeath = System.currentTimeMillis();
shipDead = true;
spaceObject=ship;
paintComponent(g);
}
}
}
}

// Check which keys have been pressed and respond accordingly
private void handleKeyEntries()
{
// Ship movement keys
if(accelerateHeld)
ship.accelerate();

if(slowDownHeld)
ship.slowDown();

// Shooting the cannon
if(firing)
{
firing = false;
shots.add(ship.fire());
}


}

// Deal with moving all the objects that are floating around
private void moveSpaceObjects()
{
Graphics g = playArea.getGraphics();


// Handle the movements of all objects in the field
if(!shipDead)
updateShip(g);
updateShots(g);
updateComets(g);
}

// Move all comets and draw them to the screen
private void updateComets(Graphics g)
{


for(Comet c : comets)
{
spaceObject=c;
paintComponent(g);

// Move the comet to its new position
c.move();


paintComponent(g);

}
}


// Move all shots and draw them to the screen
private void updateShots(Graphics g)
{

for(int i = 0; i < shots.size(); i++)
{
Shot s = shots.elementAt(i);

// Erase the shot at its old position
paintComponent(g);


// Move the shot to its new position
s.move();

// Remove the shot if it's too old
if(s.getAge() > 180)
{
shots.remove(i);
i--;
}
// Otherwise, draw it at its new position
else
{
moveImage(g, s, (int)s.getXPosition(), (int)s.getYPosition());
paintComponent(g);
}
}
}


// Moves the ship and draws it at its new position
private void updateShip(Graphics g)
{
// Erase the ship at its old position
paintComponent(g);

// Ship rotation must be handled between erasing the ship at its old position
// and drawing it at its new position so that artifacts aren't left on the screen
if(turnLeftHeld)
ship.rotateLeft();
if(turnRightHeld)
ship.rotateRight();
ship.move();

// Draw the ship at its new position
moveImage(g, ship, (int)ship.getXPosition(), (int)ship.getYPosition());
paintComponent(g);
}

// Draws this ship s to the specified graphics context
private void drawShip(Graphics g, Ship s)
{




Graphics2D ship = (Graphics2D) spaceShip.getGraphics();

double x = Math.sin(s.getAngle());
double y = Math.cos(s.getAngle());


AffineTransform transformsave = AffineTransform.getRotateInstance(x, y, spaceShip.getWidth()/2, spaceShip.getHeight()/2);
AffineTransformOp transform = new AffineTransformOp( transformsave, AffineTransformOp.TYPE_BILINEAR );


// Figure out where the ship should be drawn
int xCenter = (int)s.getXPosition();
int yCenter = (int)s.getYPosition();



// Draw the ship body
g.drawImage(transform.filter(spaceShip, null), xCenter-10, yCenter-20, null);
ship.setTransform(transformsave);


}

public void setSpaceObject(SpaceObject s){
spaceObject=s;
}

public SpaceObject getSpaceObject(){
return spaceObject;
}

@Override
protected void paintComponent( Graphics g ){
super.paintComponent(g);

spaceObject=getSpaceObject();
int radius = (int)s.getRadius();
int xCenter = (int)s.getXPosition();
int yCenter = (int)s.getYPosition();

// Draw the object
if(spaceObject==s)
g.drawImage( bullet, xCenter-radius, yCenter-radius, this );
else if(spaceObject==large)
g.drawImage( largeComet, xCenter-radius, yCenter-radius, this );
else if(spaceObject==medium)
g.drawImage( mediumComet, xCenter-radius, yCenter-radius, this );
else if(spaceObject==small)
g.drawImage( smallComet, xCenter-radius, yCenter-radius, this );
else if(spaceObject==ship)
drawShip(g, ship);



}

public void moveImage(Graphics g, SpaceObject s, int x, int y){
int radius = (int)s.getRadius();
int xCenter=0, yCenter=0;



if(xCenter!=x || yCenter!=y){

xCenter= (int)s.getXPosition();
yCenter = (int)s.getYPosition();
repaint(xCenter, yCenter, radius*2, radius*2);
}


}



// Deals with keyboard keys being pressed
public void keyPressed(KeyEvent key)
{
// Mark down which important keys have been pressed
if(key.getKeyCode() == KeyEvent.VK_UP)
this.accelerateHeld = true;
if(key.getKeyCode() == KeyEvent.VK_LEFT)
this.turnLeftHeld = true;
if(key.getKeyCode() == KeyEvent.VK_RIGHT)
this.turnRightHeld = true;
if(key.getKeyCode() == KeyEvent.VK_SPACE)
this.firing = true;
//ADD DOWN TO SLOW DOWN SHIP!!!
if(key.getKeyCode() == KeyEvent.VK_DOWN)
this.slowDownHeld = true;
}

// Deals with keyboard keys being released
public void keyReleased(KeyEvent key)
{
// Mark down which important keys are no longer being pressed
if(key.getKeyCode() == KeyEvent.VK_UP)
this.accelerateHeld = false;
if(key.getKeyCode() == KeyEvent.VK_LEFT)
this.turnLeftHeld = false;
if(key.getKeyCode() == KeyEvent.VK_RIGHT)
this.turnRightHeld = false;
//ADD DOWN TO SLOW DOWN SHIP!!!
if(key.getKeyCode() == KeyEvent.VK_DOWN)
this.slowDownHeld = false;
}

// This method is not actually used, but is required by the KeyListener interface
public void keyTyped(KeyEvent arg0)
{
}





public static void main(String[] args)
{



// A GUI program begins by creating an instance of the GUI
// object. The program is event driven from that point on.
new CometsMain();



}

}

最佳答案

不要使用getGraphics 。问题是,这只是最后绘制的快照。

这就像拿一张纸并在上面反复绘画,很快就会变得一团糟。

getGraphics还可以返回null .

在 Swing 中绘画是由 RepaintManager 控制的它决定应该绘制什么以及何时绘制事物。

您应该尝试遵循的基本概念是...

  • 更新游戏模型的状态
  • 更新游戏模型的 View
  • 将 View 渲染到屏幕

这可以通过几种不同的方式来实现,但首先,如果您想更新 UI,您应该覆盖 paintComponent从类似 JComponent 扩展的组件的方法.

接到电话时,请调用 super.paintComponent这将自动准备 Graphics绘画的背景。

更新 View ...

你可以...

  • 在后台线程中,更新游戏模型并请求重新绘制 View
  • 在 View 中 paintComponent方法,重新绘制模型

这是一种相对简单的方法,但如果控制不好,可能会导致 View 和模型不同步。您还需要确保更新 View 时模型不会更改...

或者,你可以...

  • 创建两个(或更多)BufferedImages
  • 在后台线程中更新游戏模型
  • 在后台线程中,更新“离屏”缓冲区以表示当前游戏模型状态
  • 切换缓冲图像(将“离屏”缓冲区移至“Activity 屏幕”,将“Activity 屏幕”移至“离屏”)
  • 请求更新 View
  • 在 View 中 paintComponent方法,只需绘制“Activity 屏幕”

这是一个更复杂的过程,需要您确保缓冲区的大小与 View 相同,但这意味着模型可以独立于 View 重绘进行更新。仍然存在这样的危险:在绘制 View 时您可能会更改“关闭”和“Activity ”屏幕缓冲区。

您可以通过使用某种队列来稍微提升此过程,在其中放置 BufferedImage可用于渲染(通过将它们从队列中弹出)并让“ View ”在渲染后再次将它们推回...

或者这些的某种组合,您可以锁定“Activity ”和“关闭”屏幕缓冲区的切换,以确保“Activity ”缓冲区不会被绘制。

看看Performing Custom PaintingPainting in AWT and Swing了解更多详情

例如...

关于java - 将图像移动到新位置后删除图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20292891/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com