Ich bin recht neu was Java angeht und hab jetzt versucht eine eigene Flappy Bird Version zu erstellen. Dabei habe ich folgende Probleme:
Moving Pipes:
Hier ist der Problem Code. Danke im Voraus für alle Hilfe:
Moving Pipes:
- Ich wollte ein Moving Pipes Feature einfügen, allerdings bewegt sich die Lücke zwischen Pipe oben und Pipe unten nicht.
- Die Moving Pipes sollten zufällig, aber selten (c.10%), die Grünen Pipes ersetzen, allerdings spawnen sie gar nicht
- Es soll ein Invincibility Item geben. Dieses soll man 3x einsameln, dann soll man für eine kurze Zeit unbesiegbar sein, die Röhren zum despawnen bringen, und nicht Game Over gehen. Dabei soll der Vogel blinken. Aktuell blinkt der Vogel dauerhaft.
- Wenn Items eingesamelt werden soll ein dunkelgelber Kreis in einer Ecke erscheinen, bis 3 voll sind. Diese sollen verschwinden sobald drei Items eingesammelt wurden und die Unsterblichkeit abgelaufen ist
- Items sollen aufhören zu spawnen wenn man Game Over geht
- Vogel soll sich nicht neigen wenn er auf dem Boden ist
Hier ist der Problem Code. Danke im Voraus für alle Hilfe:
Java:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class FlappyBird extends JFrame implements ActionListener, KeyListener {
private static final long serialVersionUID = 1L;
private Timer invincibilityTimer;
private final Timer timer;
private int birdY;
private boolean isGameOver;
private List<Rectangle> pipes;
private int ticks, yMotion;
private Random random;
private int score;
private int maxScore;
private int difficultyLevel;
private boolean invincible;
private Font difficultyFont;
private boolean spawningItem;
private int itemX, itemY;
private int itemWidth = 30;
private int itemHeight = 30;
private boolean spawningMovingPipe;
private int collectedItems;
private boolean displayInvincibility;
private int invincibilityCounter;
private boolean movingPipeVisible;
private int movingPipeY;
private int movingPipeSpeed;
public FlappyBird() {
setTitle("Flappy Bird");
setSize(800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
addKeyListener(this);
addMouseListener(new Click());
spawningMovingPipe = false;
birdY = 300;
isGameOver = false;
pipes = new ArrayList<>();
random = new Random();
score = 0;
maxScore = 0;
difficultyLevel = 1;
difficultyFont = new Font("Arial", Font.PLAIN, 20);
collectedItems = 0;
displayInvincibility = false;
invincibilityCounter = 0;
movingPipeVisible = false;
movingPipeSpeed = 5;
timer = new Timer(20, this);
timer.start();
addPipe(true);
addPipe(true);
addPipe(true);
addPipe(true);
}
private void moveMovingPipe() {
int minY = 100;
int maxY = 600 - 80;
if (movingPipeVisible) {
movingPipeY += movingPipeSpeed * (random.nextBoolean() ? 1 : -1);
movingPipeY = Math.max(minY, Math.min(maxY, movingPipeY));
} else {
if (spawningMovingPipe && ticks % 500 == 0 && random.nextDouble() < 0.05 && !spawningItem && !invincible) {
addPipe(false);
movingPipeVisible = true;
movingPipeY = random.nextInt(500) + 100;
}
}
}
public void addPipe(boolean start) {
int space = Math.max(100, 300 - Math.min(score / 5, 50) - (difficultyLevel * 10));
int width = 100;
int height = 50 + random.nextInt(300);
if (start) {
pipes.add(new Rectangle(800 + width + pipes.size() * 300, 600 - height - 80, width, height));
pipes.add(new Rectangle(800 + width + (pipes.size() - 1) * 300, 0, width, 600 - height - space));
} else {
pipes.add(new Rectangle(pipes.get(pipes.size() - 1).x + 600, 600 - height - 80, width, height));
pipes.add(new Rectangle(pipes.get(pipes.size() - 1).x, 0, width, 600 - height - space));
}
if (spawningMovingPipe && ticks % 500 == 0 && random.nextDouble() < 0.01 && !spawningItem && !invincible) {
addPipe(false);
movingPipeVisible = true;
movingPipeY = random.nextInt(500) + 100;
}
}
public void jump() {
if (isGameOver) {
birdY = 300;
isGameOver = false;
pipes.clear();
addPipe(true);
addPipe(true);
addPipe(true);
addPipe(true);
score = 0;
ticks = 0;
difficultyLevel = 1;
collectedItems = 0;
displayInvincibility = false;
}
if (yMotion > 0) {
yMotion = 0;
}
yMotion -= 10;
}
@Override
public void actionPerformed(ActionEvent e) {
ticks++;
pipes.removeIf(pipe -> pipe.width > 0 && pipe.x + pipe.width < 0);
moveMovingPipe();
if (birdY < 0) {
isGameOver = true;
}
if (ticks % 500 == 0) {
difficultyLevel++;
}
if (ticks % 500 == 0 && !invincible) {
invincible = true;
invincibilityTimer = new Timer(5000, event -> invincible = false);
invincibilityTimer.setRepeats(false);
invincibilityTimer.start();
}
if (invincible) {
invincibilityCounter++;
if (invincibilityCounter >= 3) {
invincible = false;
invincibilityCounter = 0;
collectedItems = 0;
displayInvincibility = false;
}
}
if (ticks % 400 == 0 && random.nextDouble() < 0.05 && !spawningItem && !invincible) {
addPipe(false);
movingPipeVisible = true;
movingPipeY = random.nextInt(500) + 100;
}
if (ticks % 50 == 0 && !invincible && !spawningItem) {
spawningItem = true;
itemX = 800;
itemY = 50 + random.nextInt(500);
while (isItemInPipes(itemX, itemY) || itemY > 600 - 80 - itemHeight) {
itemY = 50 + random.nextInt(500);
}
}
if (ticks % 50 == 0 && !invincible && !spawningItem && random.nextDouble() < 0.02) {
spawningItem = true;
itemX = 800;
itemY = 50 + random.nextInt(500);
}
if (spawningItem) {
itemX -= 5;
if (itemX < 0) {
spawningItem = false;
}
if (itemX < 0) {
spawningItem = false;
}
Rectangle birdRect = new Rectangle(50, birdY, 30, 30);
Rectangle itemRect = new Rectangle(itemX, itemY, itemWidth, itemHeight);
if (birdRect.intersects(itemRect)) {
collectedItems++;
if (collectedItems >= 3) {
displayInvincibility = true;
invincible = true;
if (invincibilityTimer != null && invincibilityTimer.isRunning()) {
invincibilityTimer.restart();
} else {
invincibilityTimer = new Timer(100, event -> {
invincible = false;
collectedItems = 0;
displayInvincibility = false;
});
invincibilityTimer.setRepeats(false);
invincibilityTimer.start();
}
}
spawningItem = false;
itemX = itemY = -1;
}
}
if (!isGameOver) {
for (int i = 0; i < pipes.size(); i++) {
Rectangle pipe = pipes.get(i);
pipe.x -= 10 + score / 5;
}
if (spawningMovingPipe && ticks % 500 == 0 && random.nextDouble() < 0.01) {
addPipe(false);
}
if (ticks % 2 == 0) {
int birdX = 50;
for (int i = 0; i < pipes.size(); i += 2) {
Rectangle lowerPipe = pipes.get(i);
Rectangle upperPipe = pipes.get(i + 1);
if (birdX + 30 > lowerPipe.x + lowerPipe.width && !isPipeCounted(lowerPipe)) {
score++;
score--;
if (score > maxScore) {
maxScore = score;
}
markPipeAsCounted(lowerPipe);
}
if (birdX + 30 > upperPipe.x + upperPipe.width && !isPipeCounted(upperPipe)) {
score++;
if (score > maxScore) {
maxScore = score;
}
markPipeAsCounted(upperPipe);
}
}
}
if (ticks % 2 == 0 && yMotion < 15) {
yMotion += 2;
}
birdY += yMotion;
for (int i = 0; i < pipes.size(); i++) {
Rectangle pipe = pipes.get(i);
if (pipe.intersects(new Rectangle(50, birdY, 30, 30)) && !invincible) {
isGameOver = true;
}
if (invincible && pipe.intersects(new Rectangle(50, birdY, 30, 30))) {
pipes.remove(pipe);
}
}
if (birdY + yMotion >= 600 - 80 - 30) {
birdY = 600 - 80 - 30;
}
for (int i = 0; i < pipes.size(); i += 2) {
Rectangle pipe = pipes.get(i);
if (pipe.x + pipe.width < 0) {
pipes.remove(pipe);
if (pipe.y == 0) {
addPipe(false);
}
}
}
}
repaint();
}
@Override
public void paint(Graphics g) {
g.setColor(Color.cyan);
g.fillRect(0, 0, 800, 600);
g.setColor(Color.orange.darker());
g.fillRect(0, 600 - 80, 800, 80);
g.setColor(Color.green);
g.fillRect(0, 600 - 80, 800, 20);
g.setColor(Color.red);
Graphics2D g2d = (Graphics2D) g;
if (birdY > 0) {
g2d.rotate(Math.toRadians(yMotion * 2), 50 + 15, birdY + 15);
g2d.fillRect(50, birdY, 30, 30);
g2d.rotate(-Math.toRadians(yMotion * 2), 50 + 15, birdY + 15);
} else {
g.fillRect(50, birdY, 30, 30);
}
for (Rectangle pipe : pipes) {
g.setColor(spawningMovingPipe ? Color.RED.darker() : Color.GREEN.darker());
g.fillRect(pipe.x, pipe.y, pipe.width, pipe.height);
}
if (spawningItem) {
if (ticks % 20 < 10) {
g.setColor(Color.YELLOW);
} else {
g.setColor(Color.WHITE);
}
g.fillOval(itemX, itemY, itemWidth, itemHeight);
}
if (spawningItem) {
if (itemX > 50 && itemX < 80) {
if (ticks % 20 < 10) {
g.setColor(Color.YELLOW);
} else {
g.setColor(Color.WHITE);
}
g.fillOval(itemX, itemY, itemWidth, itemHeight);
}
}
Rectangle birdRect = new Rectangle(50, birdY, 30, 30);
Rectangle itemRect = new Rectangle(itemX, itemY, itemWidth, itemHeight);
if (birdRect.intersects(itemRect)) {
collectedItems++;
if (collectedItems >= 3) {
invincible = true;
if (invincibilityTimer != null && invincibilityTimer.isRunning()) {
invincibilityTimer.restart();
} else {
invincibilityTimer = new Timer(100, event -> {
invincible = false;
collectedItems = 0;
displayInvincibility = false;
});
invincibilityTimer.setRepeats(false);
invincibilityTimer.start();
}
}
if (spawningItem) {
if (itemX > 50 && itemX < 80) {
if (ticks % 20 < 10) {
g.setColor(Color.YELLOW);
} else {
g.setColor(Color.WHITE);
}
g.fillOval(itemX, itemY, itemWidth, itemHeight);
}
}
spawningItem = false;
itemX = itemY = -1;
}
g.setColor(Color.white);
g.setFont(difficultyFont);
g.drawString("Difficulty: " + difficultyLevel, 650, 50);
g.setFont(new Font("Arial", Font.PLAIN, 30));
g.drawString("Score: " + score, 20, 50);
g.drawString("Max Score: " + maxScore, 20, 80);
if (isGameOver) {
g.drawString("Game Over! Your Score: " + score, 250, 300);
g.drawString("Max Score: " + maxScore, 250, 350);
}
if (invincible) {
if (ticks % 20 < 10) {
g.setColor(Color.YELLOW);
g.fillOval(50, birdY, 30, 30);
}
}
if (displayInvincibility) {
g.setColor(Color.YELLOW.darker());
for (int i = 0; i < collectedItems; i++) {
g.fillOval(700 + i * 40, 20, 30, 30);
}
}
if (movingPipeVisible) {
g.setColor(Color.ORANGE.darker());
g.fillRect(800, movingPipeY, 100, 50);
}
if(birdY>0)
{
g2d.rotate(Math.toRadians(yMotion * 2), 50 + 15, birdY + 15);
g2d.fillRect(50, birdY, 30, 30);
g2d.rotate(-Math.toRadians(yMotion * 2), 50 + 15, birdY + 15);
}else
{
g.fillRect(50, birdY, 30, 30);
}
Toolkit.getDefaultToolkit().sync();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
FlappyBird flappyBird = new FlappyBird();
flappyBird.setVisible(true);
});
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
jump();
}
}
@Override
public void keyReleased(KeyEvent e) {
}
private class Click extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
jump();
}
}
private boolean isPipeCounted(Rectangle pipe) {
return pipe.intersects(new Rectangle(50, birdY, 30, 30));
}
private void markPipeAsCounted(Rectangle pipe) {
pipe.width = 0;
}
private boolean isItemInPipes(int x, int y) {
for (Rectangle pipe : pipes) {
if (pipe.intersects(new Rectangle(x, y, itemWidth, itemHeight))) {
return true;
}
}
return false;
}
}