首先在这里发帖,请原谅我,如果这是绝对错误的事情,但我只是一点点腌菜。 - 我的计算机科学课让我们从零开始制作我们自己的游戏/程序,但是我们的老师特别忽略了挥杆的存在,并且说从我的读数开始教它是不可能的,似乎游戏几乎已经出局了问题,到目前为止我写的主要精灵和调试信息在关键输入上猛烈地闪烁。有没有解决的办法?
我知道JPanel / JFrame / Swing会解决这个问题,但是我们没有教过它,到目前为止我读到的所有内容都让我感到困惑,如果有人能够帮助我转换我的代码来使用它这将是惊人的,因为我从解剖它更容易学习..这可能看起来有点狡猾,但它确实是最容易学习的方法。到目前为止我的代码是;
public class GameThing extends Applet implements KeyListener {
Image rightsprite, picture;
Image leftsprite, picture2;
Image spritedead, picture3;
Image background, picture4;
boolean left;
boolean dead;
boolean wall;
boolean menu;
int widthX, heightY;
int bgx, bgy;
String sr = " ";
char ch = '*';
Graphics bufferGraphics;
Image offscreen;
Dimension dim;
@Override
public void init() {
rightsprite = getImage(getDocumentBase(), "SpriteRight.png");
leftsprite = getImage(getDocumentBase(), "SpriteLeft.png");
spritedead = getImage(getDocumentBase(), "Sprite.png");
background = getImage(getDocumentBase(), "Background.png");
requestFocus();
addKeyListener(this);
left = false;
menu = true;
setSize(600, 380);
dim = getSize();
offscreen = createImage(dim.width, dim.height);
bufferGraphics = offscreen.getGraphics();
bgx = 0;
bgy = 0;
}
public void pause(final int delay) { // PAUSE COMMAND LIFTED FROM RAY
// waits a while
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
return;
}
}
public GameThing() { // SPRITE INITIAL SPAWN LOCATION
widthX = 100;
heightY = 300;
}
@Override
public void paint(final Graphics g) { // DRAW MAIN CHARACTER SPRITE AND BACKGROUND
bufferGraphics.setColor(Color.black); // DRAW GROUND (REPLACE WITH BLOCKS SOON)
bufferGraphics.drawRect(0, 334, 500, 50);
bufferGraphics.setColor(Color.green);
bufferGraphics.fillRect(0, 335, 500, 50);
g.drawImage(offscreen, 0, 0, this);
if (menu == true) {
pause(500);
g.drawString("Side Scroller Test.", 180, 250);
pause(1500);
menu = false;
}
if (left == false) { // LEFT KEY MOVEMENT COMMANDS
g.drawImage(rightsprite, widthX, heightY, this);
g.drawString("Sprites Current X Location is: " + widthX, 20, 30);
g.drawString("Sprites Current Y Location is: " + heightY, 20, 50);
g.drawString("Background X location is: " + bgx, 20, 90);
g.drawString("Currently: " + sr, 20, 70);
}
if (left == true) { // RIGHT KEY MOVEMENT COMMANDS
g.drawImage(leftsprite, widthX, heightY, this);
g.drawString("Sprites Current X Location is: " + widthX, 20, 30);
g.drawString("Sprites Current Y Location is: " + heightY, 20, 50);
g.drawString("Background X location is: " + bgx, 20, 90);
g.drawString("Currently: " + sr, 20, 70);
}
if (dead == true) { // COMMANDS TO EXECUTE WHEN MAIN CHARACTER DIES
widthX = 506;
heightY = 314;
g.drawImage(spritedead, widthX, heightY, this);
pause(500);
g.setColor(Color.white);
g.drawRect(widthX, heightY, widthX, heightY);
g.fillRect(widthX, heightY, widthX, heightY);
pause(500);
widthX = 100;
heightY = 300;
bgx = 0;
left = true;
dead = false;
}
}
@Override
public void update(final Graphics g) { // KEEPS BACKGROUND STATIC
paint(g);
}
public void keyPressed(final KeyEvent e) {
sr = "blank!";
ch = '1';
if (e.getKeyCode() == 39) {
sr = "Moving Right!";
widthX = widthX + 7;
if (widthX <= 121) {
bgx = bgx;
} else {
bgx = bgx - 7;
}
left = false;
if ((widthX > 490) && (heightY > 300)) { // FALL DEATH
sr = "You Died!";
widthX = 900;
heightY = 900;
dead = true;
}
if (widthX == 499) {
heightY = heightY + 7;
}
}
if (widthX == 2) {
wall = true;
}
if (e.getKeyCode() == 37) {
if (wall == true) {
sr = "Wall!";
if (widthX > 2) {
wall = false;
}
}
if (wall == false) {
sr = "Moving Left!";
widthX = widthX - 7;
if (bgx >= 0) {
bgx = bgx;
} else {
bgx = bgx + 7;
}
left = true;
}
}
if (e.getKeyCode() == 38) {
sr = "Jumping!";
}
repaint();
}
public void keyTyped(final KeyEvent e) {
ch = e.getKeyChar();
repaint();
}
public void keyReleased(final KeyEvent e) {
} // key released
}
ps:使用向上键跳转也是一个问题,我不能简单地添加到Y变量然后减去,因为它变得如此之快,就好像它从未移动过一样。 sidecroller的基础知识比我预期的要多得多。
答案 0 :(得分:0)
我编辑了你的代码:
public class GameThing extends Applet {
// External resources
BufferedImage rightSprite, leftSprite, spriteDead, backgroundImg;
// Game data
int state = 1; //0 = left, 1 = right, 2 = dead
// Geometry
int locX = 100, locY = 300;
int bgX = 0, bgY = 0;
int groundX = 0, groundY = 334, groundW = 500, groundH = 50;
int appletW = 600, appletH = 480;
int wallW = 20, wallH = 40, wallX = 20, wallY = groundY - wallH;
final int STEP_SIZE = 7;
// Information
final String X_LOC_STR = "Sprites Current X Location is: ";
final String Y_LOC_STR = "Sprites Current Y Location is: ";
final String STATE_STR = "Currently: ";
final String X_BG_STR = "Background X location is: ";
String stateString = "";
// Double buffering
Image offscreen;
Graphics bufferGraphics;
Dimension dim;
// GUI components
Panel gamePanel;
Panel statusPanel = new Panel();
Label xLocLabel = new Label();
Label yLocLabel = new Label();
Label stateLabel = new Label();
Label xBGLocLabel = new Label();
@Override
public void init() {
// Load images
try {
rightSprite = ImageIO.read(new File(getClass().getResource("SpriteRIght.png").getPath()));
leftSprite = ImageIO.read(new File(getClass().getResource("SpriteLeft.png").getPath()));
spriteDead = ImageIO.read(new File(getClass().getResource("SpriteDead.png").getPath()));
backgroundImg = ImageIO.read(new File(getClass().getResource("Background.png").getPath()));
} catch (IOException e) {
e.printStackTrace();
}
// Set the panel that displays data
statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.Y_AXIS));
statusPanel.add(xLocLabel);
statusPanel.add(yLocLabel);
statusPanel.add(stateLabel);
statusPanel.add(xBGLocLabel);
// Create the panel that draws the game and specify its behavior
gamePanel = new Panel() {
// Reduces flickering
@Override
public void update(Graphics g) {
paint(g);
}
// DRAW MAIN CHARACTER SPRITE AND BACKGROUND
@Override
public void paint(Graphics g) {
bufferGraphics.clearRect(0, 0, dim.width, dim.width);
bufferGraphics.drawImage(backgroundImg, bgX, bgY, this);
bufferGraphics.setColor(Color.BLACK); // DRAW GROUND (REPLACE WITH BLOCKS SOON)
bufferGraphics.drawRect(groundX, groundY, groundW, groundH);
bufferGraphics.setColor(Color.GREEN);
bufferGraphics.fillRect(groundX, groundY + 1, groundW, groundH);
bufferGraphics.setColor(Color.RED);
bufferGraphics.fillRect(wallX, wallY, wallW, wallH);
switch (state) {
case 0: bufferGraphics.drawImage(leftSprite, locX, locY, this);
break;
case 1: bufferGraphics.drawImage(rightSprite, locX, locY, this);
break;
case 2: bufferGraphics.drawImage(spriteDead, locX, locY, this);
// After death wait a bit and reset the game
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
pause(2000);
reset();
}
});
break;
}
g.drawImage(offscreen, 0, 0, this);
}
};
// Set the applet window
setLayout(new BorderLayout());
add(statusPanel, BorderLayout.PAGE_START);
add(gamePanel);
// Set double buffering
setSize(appletW, appletH);
dim = getSize();
offscreen = createImage(dim.width, dim.height);
bufferGraphics = offscreen.getGraphics();
// Set the panel that draws the game
gamePanel.addKeyListener(new Controls());
gamePanel.requestFocusInWindow();
updateLabels();
}
// PAUSE COMMAND LIFTED FROM RAY (who is Ray?)
// waits a while
public void pause(int delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// Set to start parameters
public void reset() {
locX = 100; locY = 300;
bgX = 0;
state = 1;
gamePanel.repaint(); // These 2 lines automatically restart the game
updateLabels(); // Remove if you want to stay on the death screen until next press
}
public void updateLabels() {
xLocLabel.setText(X_LOC_STR + locX);
yLocLabel.setText(Y_LOC_STR + locY);
stateLabel.setText(STATE_STR + stateString);
xBGLocLabel.setText(X_BG_STR + bgX);
}
private class Controls extends KeyAdapter {
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_RIGHT:
stateString = "Moving Right!";
locX += STEP_SIZE;
state = 1;
if (locX > 121)
bgX -= STEP_SIZE;
// FALL DEATH
if ((locX > 490) && (locY > 300)) {
stateString = "You Died!";
state = 2;
}
// Start fall
if (locX == 499)
locY += STEP_SIZE;
// Check wall collision
if (locX >= wallX && locX <= wallX + wallW) {
locX -= STEP_SIZE;
stateString = "Wall!";
}
break;
case KeyEvent.VK_LEFT:
stateString = "Moving Left!";
locX -= STEP_SIZE;
state = 0;
if (bgX < 0)
bgX += STEP_SIZE;
// Check wall collision
if (locX >= wallX && locX <= wallX + wallW) {
locX += STEP_SIZE;
stateString = "Wall!";
}
break;
case KeyEvent.VK_UP:
// Implement jumping
stateString = "Jumping!";
break;
}
// Repaint the game panel and update the data panel
gamePanel.repaint();
updateLabels();
}
}
}
首先测试并了解更改:
if else
替换为switch
,VK_UP
而不是37等等。 final
。Color.RED
,而不是Color.red
)。@Override
,即使编译器理解它也是如此。sleep
或昂贵的计算阻止事件派发线程(EDT)。像paint
键事件这样的方法意味着快速执行。我使用invokeLater
仅在EDT处理完所有排队事件后暂停。 (据我所知,这个穿线主题来自一个无处不在的炸弹,只是忍受我)。期待代码的当前状态(无新功能):
state
应该是enum
或与其接近的内容而不是随机数。Shape
绘制对象,而不是在绘画期间指定其参数。双缓冲实施说明:
您可以创建一个离屏Image
对象offscreen
和一个Graphics
对象来绘制它 - bufferGraphics
。在paint
内,您只能使用 bufferGraphics
作为图纸。事实上,即使offscreen
属于paint
(或任何其他对象及其gamePanel
),您也会使用paint
,这有点令人困惑。当您在屏幕外完成所有内容绘制后,您可以使用g.drawImage(offscreen...)
使用gamePanel
的{{1}}对象Graphics
将其全部一次性放到屏幕上。
这个想法就像把所有东西都画在纸上,然后把它放在相机前,而不是一点一点地在相机上画画,或类似的......
目前,屏幕外图像是整个applet的大小,而不仅仅是游戏面板,但它没什么区别。
Swing 方法的相关差异:
g
替换为Label
,将JLabel
替换为Panel
等。JComponent
的JPanel
和setDoubleBuffered
)。删除所有屏幕外的恶作剧,并直接用isDoubleBuffered
绘制。无需覆盖Graphics g
。update
完成,而不在paintComponent
。答案 1 :(得分:0)
@ user1803551好的,所以它都会重新回到原来的状态。 - 滚动的背景在(只需要一些东西需要从你的帖子调整),我明白最后一行“gamePanel.repaint();是什么刷新屏幕上的一切,因为背景需要是更新了每个键输入,它不应该限于代码中的小方块,对吧?现在刷新整个屏幕,但我认为这不是想要的,因为它只会导致闪烁,缓冲图形但是底部的绿色矩形不会闪烁。所以我的假设是转换
g.drawImage(backgroundImg, bgx, bgy,this);
进入buffergraphics?
CNC中 将主Sprite移动到bufferGraphics以及背景图像。闪烁现在几乎消失了,但是在按住箭头键一点点后,屏幕会闪烁一会儿,然后恢复正常。
public class GameTest extends Applet {
/**
*
*/
private static final long serialVersionUID = -1533028791433336859L;
Image rightsprite, leftsprite, spritedead, backgroundImg, offscreen;
boolean left = false, dead = false, wall = false, menu = true;
int locX = 100, locY = 300, width, height, bgx = 0, bgy = 0;
final int STEP_SIZE = 7;
final String X_LOC_STR= "Sprites Current X Location is: ";
final String Y_LOC_STR= "Sprites Current Y Location is: ";
final String STATE_STR= "Currently: ";
final String X_BG_STR= "Background X location is: ";
String sr = " ";
Graphics bufferGraphics;
Dimension dim;
Panel gamePanel;
Panel statusPanel = new Panel();
Label xLoc = new Label(X_LOC_STR);
Label yLoc = new Label(Y_LOC_STR);
Label state = new Label(STATE_STR);
Label xBGLoc = new Label(X_BG_STR);
public void init() {
try {
rightsprite = ImageIO.read(new File(getClass().getResource("SpriteRight.png").getPath()));
leftsprite = ImageIO.read(new File(getClass().getResource("SpriteLeft.png").getPath()));
spritedead = ImageIO.read(new File(getClass().getResource("SpriteDead.png").getPath()));
backgroundImg = ImageIO.read(new File(getClass().getResource("Background.png").getPath()));
} catch (IOException e) {
e.printStackTrace();
}
height = rightsprite.getHeight(this);
width = rightsprite.getWidth(this);
statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.Y_AXIS));
statusPanel.add(xLoc);
statusPanel.add(yLoc);
statusPanel.add(state);
statusPanel.add(xBGLoc);
gamePanel = new Panel() {
/**
*
*/
private static final long serialVersionUID = 1L;
// DRAW MAIN CHARACTER SPRITE AND BACKGROUND
@Override
public void paint(Graphics g) {
bufferGraphics.drawImage(backgroundImg,bgx, bgy, this);
bufferGraphics.setColor(Color.black); // DRAW GROUND (REPLACE WITH BLOCKS SOON)
bufferGraphics.drawRect(0, 334, 500, 50);
bufferGraphics.setColor(Color.green);
bufferGraphics.fillRect(0, 335, 500, 50);
if (menu == true) {
pause(500);
g.drawString("Side Scroller Test.", 180, 250);
pause(1500);
menu = false;
}
// LEFT KEY MOVEMENT COMMANDS
if (left == false)
bufferGraphics.drawImage(rightsprite, locX, locY, this);
// RIGHT KEY MOVEMENT COMMANDS
else
bufferGraphics.drawImage(leftsprite, locX, locY, this);
// COMMANDS TO EXECUTE WHEN MAIN CHARACTER DIES
if (dead == true) {
locX = 506;
locY = 314;
bufferGraphics.drawImage(spritedead, locX, locY, this);
pause(500);
bufferGraphics.setColor(Color.white);
bufferGraphics.drawRect(locX, locY, width, height);
bufferGraphics.fillRect(locX, locY, width, height);
pause(500);
locX = 100;
locY = 300;
bgx = 0;
bgy = 0;
bufferGraphics.clearRect(locX, locY, width, height);
left = true;
dead = false;
}
g.drawImage(offscreen, 0, 0, this);
super.paint(g);
}
};
setLayout(new BorderLayout());
add(statusPanel, BorderLayout.PAGE_START);
add(gamePanel);
setSize(600, 480);
dim = getSize();
offscreen = createImage(dim.width, dim.height);
bufferGraphics = offscreen.getGraphics();
gamePanel.addKeyListener(new Controls());
gamePanel.requestFocusInWindow();
}
// waits a while
public void pause(int delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class Controls extends KeyAdapter {
public void keyPressed(KeyEvent e) {
sr = "blank!";
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
sr = "Moving Right!";
locX += STEP_SIZE;
if (locX > 121)
bgx = bgx - STEP_SIZE;
left = false;
// FALL DEATH
if ((locX > 490) && (locY > 300)) {
sr = "You Died!";
locX = 900;
locY = 900;
dead = true;
gamePanel.repaint();
}
if (locX == 499) {
locY += STEP_SIZE;
}
}
if (locX == 2) {
wall = true;
}
else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
if (wall == true) {
sr = "Wall!";
if (locX > 2) {
wall = false;
}
}
else {
sr = "Moving Left!";
locX -= STEP_SIZE;
if (bgx < 0)
bgx += STEP_SIZE;
left = true;
}
}
if (e.getKeyCode() == KeyEvent.VK_UP) {
sr = "Jumping!";
}
xLoc.setText(X_LOC_STR + locX);
yLoc.setText(Y_LOC_STR + locY);
state.setText(STATE_STR + sr);
xBGLoc.setText(X_BG_STR + bgx);
gamePanel.repaint();
}
}
}