|
|
|
Breakout will nicht so wie wir !
|
Guten Morgen,
wir arbeiten im Moment an einem Projekt in Java für die Schule. Wir durften uns ein Spiel aussuchen und haben uns gleich das "schwerste" ausgesucht
Es nennt sich Breakout, jeder kennt es ... man hat einen Schläger, einen Ball und ein paar Spielblöcke die man mit Hilfe des Balls und des Schlägers abschießen muss.
Problem im Moment, unser Schläger bewegt sich nicht und die Kollision funktioniert beim Schläger, als auch bei den Steinen nicht. Außerdem wissen wir nicht, wie die Steine vereinfachen können, so dass wir nicht soviel Code haben.
Wir sind alle drei nicht gerade die Java-Köpfchen und müssen dazu noch eine Ausarbeitung machen
Hier alle Klassen, bitte helft uns, es geht um Leben und Note ;D
Main:
|
Code: |
package outbreak;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
public class Main extends JFrame {
private JPanel jContentPane = null;
private JMenuBar mnuBar = null;
private JMenu mnDatei = null;
private JMenu mnSpiel = null;
private JMenu mnOption = null;
private JMenu mnHelp = null;
public JMenuItem itemBeenden = null;
private JMenuItem itemHighscore = null;
public JMenuItem itemNeuesSpiel = null;
private JMenuItem itemStop = null;
private JMenuItem itemSchwierigkeitsgrad = null;
private JMenuItem itemInfo = null;
private JMenuItem itemHilfe = null;
GamePanel pnlGame;
JButton btnStart;
JButton btnStopp;
Schlaeger schlaeger;
Baustein baustein;
public Main() {
initialize();
}
private void initialize() {
this.setSize(640, 480);
this.setJMenuBar(getMnuBar());
this.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setTitle("Outbreak v2937");
this.setVisible(true);
this.setLocationRelativeTo(null);
pnlGame = new GamePanel(this);
schlaeger = new Schlaeger(pnlGame);
this.getContentPane().add(pnlGame, BorderLayout.CENTER);
pnlGame.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
schlaeger.move();
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
schlaeger.move();
}
}
});
}
public static void main(String[] args) {
Main mainFrame = new Main();
mainFrame.setVisible(true);
}
private JMenuBar getMnuBar() {
if (mnuBar == null) {
mnuBar = new JMenuBar();
mnuBar.add(getMnDatei());
mnuBar.add(getMnSpiel());
mnuBar.add(getMnOption());
mnuBar.add(getMnHelp());
}
return mnuBar;
}
/**
* This method initializes mnDatei
*
* @return javax.swing.JMenu
*/
private JMenu getMnDatei() {
if (mnDatei == null) {
mnDatei = new JMenu();
mnDatei.setText("Datei");
mnDatei.add(getItemHighscore());
mnDatei.add(getItemBeenden());
}
return mnDatei;
}
/**
* This method initializes mnSpiel
*
* @return javax.swing.JMenu
*/
private JMenu getMnSpiel() {
if (mnSpiel == null) {
mnSpiel = new JMenu();
mnSpiel.setText("Spiel");
mnSpiel.add(getItemNeuesSpiel());
mnSpiel.add(getItemStop());
}
return mnSpiel;
}
/**
* This method initializes mnOption
*
* @return javax.swing.JMenu
*/
private JMenu getMnOption() {
if (mnOption == null) {
mnOption = new JMenu();
mnOption.setText("Optionen");
mnOption.add(getItemSchwierigkeitsgrad());
}
return mnOption;
}
/**
* This method initializes mnHelp
*
* @return javax.swing.JMenu
*/
private JMenu getMnHelp() {
if (mnHelp == null) {
mnHelp = new JMenu();
mnHelp.setText("Hilfe");
mnHelp.add(getItemInfo());
mnHelp.add(getItemHilfe());
}
return mnHelp;
}
/**
* This method initializes itemBeenden
*
* @return javax.swing.JMenuItem
*/
private JMenuItem getItemBeenden() {
if (itemBeenden == null) {
itemBeenden = new JMenuItem();
itemBeenden.setText("Beenden");
}
return itemBeenden;
}
/**
* This method initializes itemHighscore
*
* @return javax.swing.JMenuItem
*/
private JMenuItem getItemHighscore() {
if (itemHighscore == null) {
itemHighscore = new JMenuItem();
itemHighscore.setText("Highscore");
}
return itemHighscore;
}
/**
* This method initializes itemNeuesSpiel
*
* @return javax.swing.JMenuItem
*/
private JMenuItem getItemNeuesSpiel() {
if (itemNeuesSpiel == null) {
itemNeuesSpiel = new JMenuItem();
itemNeuesSpiel.setText("Neues Spiel");
itemNeuesSpiel.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
java.awt.event.KeyEvent.VK_N, 0, false));
itemNeuesSpiel
.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
pnlGame.startGame();
}
});
}
return itemNeuesSpiel;
}
private JMenuItem getItemStop() {
if (itemStop == null) {
itemStop = new JMenuItem();
itemStop.setText("Pause");
itemStop.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
pnlGame.stoppGame();
}
});
}
return itemStop;
}
private JMenuItem getItemSchwierigkeitsgrad() {
if (itemSchwierigkeitsgrad == null) {
itemSchwierigkeitsgrad = new JMenuItem();
itemSchwierigkeitsgrad.setText("Schwierigkeitsgrad");
}
return itemSchwierigkeitsgrad;
}
/**
* This method initializes itemInfo
*
* @return javax.swing.JMenuItem
*/
private JMenuItem getItemInfo() {
if (itemInfo == null) {
itemInfo = new JMenuItem();
itemInfo.setText("Information");
}
return itemInfo;
}
/**
* This method initializes itemHilfe
*
* @return javax.swing.JMenuItem
*/
private JMenuItem getItemHilfe() {
if (itemHilfe == null) {
itemHilfe = new JMenuItem();
itemHilfe.setText("Hilfe");
}
return itemHilfe;
}
}
|
|
GamePanel:
|
Code: |
package outbreak;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Observer;
import java.util.Random;
public class GamePanel extends JPanel implements Runnable {
private static final int NO_DELAYS_PER_YIELD = 16;
/* Number of frames with a delay of 0 ms before the animation thread yields
to other running threads. */
private static int MAX_FRAME_SKIPS = 5;
// no. of frames that can be skipped in any one animation loop
// i.e the games state is updated but not rendered
// used for gathering statistics
private long gameStartTime;
private Thread animator; // the thread that performs the animation
private boolean running = false; // used to stop the animation thread
private boolean isPaused = false;
private boolean gameOver = false;
private long period; // period between drawing in _nanosecs_
private Graphics dbg;
private Image dbImage = null;
private int fps; // Frames per second
private Main mainFrame;
private Ball ball;
private int pnlHeight;
private int pnlWidth;
private ArrayList<Baustein> bausteine = new ArrayList<Baustein>();
private int anzahlSteine = 18;
private Schlaeger schlaeger;
public GamePanel(Main owner) {
mainFrame = owner;
setBackground(Color.WHITE);
setFpsAndPeriod(50);
setFocusable(true);
setVisible(true);
initialize();
Cursor c = getToolkit().createCustomCursor(
new ImageIcon("/outbreak/balls/icons/Schlaeger_invis.PNG/").getImage(),
new Point (0,0), "Cursor");
setCursor(c);
}
private void initialize() {
}
public void setFpsAndPeriod(int fps) {
this.fps = fps;
this.period = 1000000000L / fps;
}
public void startGame() {
ball = new Ball(this);
for (int i = 0; i < anzahlSteine; i++){
Baustein einBaustein = new Baustein(this,i);
bausteine.add(einBaustein);
}
schlaeger = new Schlaeger(this);
this.requestFocus();
if (animator == null || !running) {
animator = new Thread(this);
animator.start();
}
}
public void stoppGame() {
running = false;
}
// ----------------------------------------------
public void run() {
long beforeTime;
long afterTime;
long timeDiff;
long sleepTime;
long overSleepTime = 0L;
int noDelays = 0;
long excess = 0L;
pnlHeight = this.getHeight();
pnlWidth = this.getWidth();
gameStartTime = System.nanoTime();
beforeTime = gameStartTime;
running = true;
while (running) {
gameUpdate();
gameRender();
paintScreen();
afterTime = System.nanoTime();
timeDiff = afterTime - beforeTime;
sleepTime = (period - timeDiff) - overSleepTime;
if (sleepTime > 0) {
// some time left in this cycle
try {
Thread.sleep(sleepTime / 1000000L); // nano -> ms
} catch (InterruptedException ex) {
}
overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
} else {
// sleepTime <= 0; the frame took longer than the period
excess -= sleepTime; // store excess time value
overSleepTime = 0L;
if (++noDelays >= NO_DELAYS_PER_YIELD) {
Thread.yield(); // give another thread a chance to run
noDelays = 0;
}
}
beforeTime = System.nanoTime();
/* If frame animation is taking too long, update the game state
without rendering it, to get the updates/sec nearer to
the required FPS. */
int skips = 0;
while ((excess > period) && (skips < MAX_FRAME_SKIPS)) {
excess -= period;
gameUpdate(); // update state but don't render
skips++;
}
}
}
private void gameUpdate() {
if (!isPaused && !gameOver) {
ball.move();
}
}
private void gameRender() {
if (dbImage == null) {
dbImage = createImage(pnlWidth, pnlHeight);
if (dbImage == null) {
System.out.println("dbImage is null");
return;
} else {
dbg = dbImage.getGraphics();
}
}
// clear the background
dbg.setColor(Color.WHITE);
dbg.fillRect(0, 0, pnlWidth, pnlHeight);
ball.draw(dbg);
schlaeger.draw(dbg);
for (int i = 0; i < bausteine.size(); i++){
bausteine.get(i).draw(dbg);
}
}
private void paintScreen() {
Graphics g;
try {
g = this.getGraphics();
if ((g != null) && (dbImage != null)) {
g.drawImage(dbImage, 0, 0, null);
}
g.dispose();
} catch (Exception e) {
System.out.println("Graphics context error: " + e);
}
}
} |
|
Schlaeger:
|
Code: |
/*
* Ball.java
*
* Created on 18.10.2007, 10:30:02
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package outbreak;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import java.awt.geom.Rectangle2D;
public class Schlaeger {
private final int SCHLAEGERSIZE = 10; // Druchmesser des Balls in Pixel
private int ppWidth;// Breite des Spielfelds
private int ppHeight; // Höhe des Spielfelds
private Point position;
private int dx = 7;
private int dy = 7;
private int x;
private int y;
private int h;
private int height;
private BufferedImage sprite;
private GamePanel gp;
private final String[] SCHLAEGER = { "/outbreak/balls/icons/Schlaeger2.PNG" };
public Schlaeger(GamePanel gp) {
this.gp = gp;
this.ppWidth = gp.getWidth();
this.ppHeight = gp.getHeight();
// do {
// dx = 5 - (int) (Math.random()*6);
// } while (dx == 0);
// do {
// dy = 4 - (int) (Math.random()*6);
// } while (dy == 0);
position = new Point(0, 410);
setSprite(0);
}
public void draw(Graphics g) {
// zeichnet den Ball
Graphics2D g2D = (Graphics2D) g;
g2D.drawImage(sprite, position.x, position.y, null);
}
// public void moveLeft(){
// position.setLocation(position.getX() + dy, position.getY() + dx);
// }
//
// public void moveRight(){
// position.setLocation(position.getX() - dy, position.getY() + dx);
// }
public void move() {
// bewegt den Ball an die neue Position
position.setLocation(position.getX() + dx, position.getY());
//
// Kollisionen mit dem Rand der Zeichenfläche abfangen
//
// Kollision mit oberem Rand
// if (position.getY() < SCHLAEGERSIZE / 2) {
// position.y = SCHLAEGERSIZE / 2;
// dy = -dy;
// }
//
// // Kollision mit unterem Rand
// if (position.getY() > ppHeight - SCHLAEGERSIZE / 2) {
// position.y = ppHeight - SCHLAEGERSIZE / 2;
// dy = -dy;
if (x <= SCHLAEGERSIZE) {
x = SCHLAEGERSIZE;
}
// Kollision mit unterem Rand
if (x + height >= h - SCHLAEGERSIZE) {
x = h - height - SCHLAEGERSIZE;
}
}
public int getSCHLAEGERSIZE() {
return SCHLAEGERSIZE;
}
public Point getPosition() {
return position;
}
public int getPpHeight() {
return ppHeight;
}
public int getPpWidth() {
return ppWidth;
}
private void setSprite(int index) {
try {
sprite = ImageIO.read(getClass().getResource(SCHLAEGER[index]));
} catch (IOException ex) {
Logger.getLogger(Schlaeger.class.getName()).log(Level.SEVERE, null,
ex);
}
}
} |
|
Baustein:
|
Code: |
/*
* Ball.java
*
* Created on 18.10.2007, 10:30:02
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package outbreak;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
public class Baustein {
private final int BAUSTEINSIZE = 25; // Druchmesser des Balls in Pixel
private int ppWidth = 630;// Breite des Spielfelds
private int ppHeight = 470; // Höhe des Spielfelds
private Point position;
private Point position2;
private Point position3;
private Point position4;
private Point position5;
private Point position6;
private Point position7;
private int dx = 25;
private int dy = 13;
private int y;
private int height;
private int h;
private BufferedImage sprite;
private GamePanel gp;
private String[] STEINE = { "/outbreak/balls/bausteine/1.png",
"/outbreak/balls/bausteine/2.png",
"/outbreak/balls/bausteine/3.png",
"/outbreak/balls/bausteine/4.png" };
public Baustein(GamePanel gp, int nummer) {
this.gp = gp;
this.ppWidth = gp.getWidth();
this.ppHeight = gp.getHeight();
position = new Point(30*nummer+45, 40);
position2 = new Point(30*nummer+45, 60);
position3 = new Point(30*nummer+45, 80);
position4 = new Point(30*nummer+45, 100);
position5 = new Point(30*nummer+45, 120);
position6 = new Point(30*nummer+45, 140);
position7 = new Point(30*nummer+45, 160);
setSprite(0);
}
public void draw(Graphics g) {
// zeichnet den Ball
Graphics2D g2D = (Graphics2D) g;
g2D.drawImage(sprite, position.x, position.y, null);
g2D.drawImage(sprite, position2.x, position2.y, null);
g2D.drawImage(sprite, position3.x, position3.y, null);
g2D.drawImage(sprite, position4.x, position4.y, null);
g2D.drawImage(sprite, position5.x, position5.y, null);
g2D.drawImage(sprite, position6.x, position6.y, null);
g2D.drawImage(sprite, position7.x, position7.y, null);
}
public void kollision(){
if (y <= BAUSTEINSIZE) {
y = BAUSTEINSIZE;
}
// Kollision mit unterem Rand
if (y + height >= h - BAUSTEINSIZE) {
y = h - height - BAUSTEINSIZE;
}
}
// public void kollision(){
// // Kollision mit linkem Rand
// if (position.getX() < BAUSTEINSIZE) {
// position.x = BAUSTEINSIZE / 2;
// dx = -dx;
// }
// // Kollision mit rechtem Rand
// if (position.getX() + BAUSTEINSIZE>= ppWidth) {
// position.x = ppWidth - BAUSTEINSIZE;
// dx = -dx;
// }
// // Kollision mit oberem Rand
// if (position.getY() < BAUSTEINSIZE) {
// position.y = BAUSTEINSIZE;
// dy = -dy;
// }
//
// // Kollision mit unterem Rand
// if (position.getY() > ppHeight - BAUSTEINSIZE) {
// position.y = ppHeight - BAUSTEINSIZE;
// dy = -dy;
// }
// }
public int getBAUSTEINSIZE() {
return BAUSTEINSIZE;
}
public int getDx() {
return dx;
}
public int getDy() {
return dy;
}
public Point getPosition() {
return position;
}
public int getPpHeight() {
return ppHeight;
}
public int getPpWidth() {
return ppWidth;
}
private void setSprite(int index) {
try {
sprite = ImageIO.read(getClass().getResource(STEINE[index]));
} catch (IOException ex) {
Logger.getLogger(Baustein.class.getName()).log(Level.SEVERE, null,
ex);
}
}
} |
|
Ball:
|
Code: |
/*
* Ball.java
*
* Created on 18.10.2007, 10:30:02
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package outbreak;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
public class Ball {
private final int BALLSIZE = 32; // Druchmesser des Balls in Pixel
private int ppWidth;// Breite des Spielfelds
private int ppHeight; // Höhe des Spielfelds
private Point position; // Mittelpunkt des Balls
private int dx;
private int dy;
private BufferedImage sprite;
private GamePanel gp;
public Ball(GamePanel gp) {
this.gp = gp;
this.ppWidth = gp.getWidth();
this.ppHeight = gp.getHeight();
do {
dx = 5 - (int) (Math.random()*6);
} while (dx == 0);
do {
dy = 4 - (int) (Math.random()*6);
} while (dy == 0);
setRandomStartPosition();
setSprite(0);
}
public void draw(Graphics g) {
// zeichnet den Ball
Graphics2D g2D = (Graphics2D) g;
g2D.drawImage(sprite, position.x - BALLSIZE / 2, position.y - BALLSIZE / 2, null);
}
public void move() {
// bewegt den Ball an die neue Position
position.setLocation(position.getX() + dx, position.getY() + dy);
//
// Kollisionen mit dem Rand der Zeichenfläche abfangen
//
// Kollision mit linkem Rand
if (position.getX() <= BALLSIZE / 2) {
position.x = BALLSIZE / 2;
dx = -dx;
}
// Kollision mit rechtem Rand
if (position.getX() >= ppWidth) {
position.x = ppWidth - BALLSIZE / 2;
dx = -dx;
}
// Kollision mit oberem Rand
if (position.getY() < BALLSIZE / 2) {
position.y = BALLSIZE / 2;
dy = -dy;
}
// // Kollision mit unterem Rand
// if (position.getY() > ppHeight - BALLSIZE / 2) {
// position.y = ppHeight - BALLSIZE / 2;
// dy = -dy;
// }
}
private void setRandomStartPosition() {
position = new Point((int) (Math.random()*ppWidth), (int) (Math.random()*ppHeight / 2));
}
private void setSprite(int index) {
try {
sprite = ImageIO.read(getClass().getResource("/outbreak/balls/icons/ballSprite.png"));
} catch (IOException ex) {
Logger.getLogger(Ball.class.getName()).log(Level.SEVERE, null, ex);
}
}
} |
|
HALP!
|
|
|
|
|
|
|
Haben es gelöst, nur nach 4 Stunden.
Hatten den Keylistener bzw Adapter falsch gesetzt bzw den Schläger falsch deklariert ...
|
|
|
|
|
|
|
Kleiner Tipp. Wir sind faul. Besonders lesefaul.
Dir wird bei solchen Problemen eher geholfen, wenn du das Problem vorher evtl. lokalisierst und nur entsprechende Codeschnipsel postest.
|
|
|
|
|
|
|
noch ein kleiner tipp. alle informatiker sind faul. insbesondere denkfaul.
erstmal konzept und euern gedanken dahinter aufschreiben, dann liest sich sowas deutlich einfacher.
|
|
|
|
|
|
|
Also ich hab mal den Code so überflogen.
Finde das Grundsätzlich gut gemacht, für welche Schule ist das bzw. Klasse?
|
|
|
|
|
|
|
| Zitat von TriggerTG
Kleiner Tipp. Wir sind faul. Besonders lesefaul.
Dir wird bei solchen Problemen eher geholfen, wenn du das Problem vorher evtl. lokalisierst und nur entsprechende Codeschnipsel postest.
| |
Schlägst du mich, wenn ich dir nun sage, dass wir gestern überhaupt nicht wussten, wo wir suchen sollten
Achja, ham nun das Problem gelöst. Nun hängen wir an der Kollision des Schlägers.
Hier der Schnipsel aus der Ball Klasse:
|
Code: |
// Kollision mit unterem Rand
if (schlaeger.getPosition().getY() > position.getY() - BALLSIZE / 2) {
schlaeger.getPosition().y = (int) (position.getY() - BALLSIZE / 2);
dy = -dy; |
|
|
|
|
|
|
|
|
was genau ist grad das problem? tut sich nix oder tut sich was falsches? einfach den bewegungsvektor spiegeln ist korrekt und mehr sagt das snippet nicht.
|
|
|
|
|
|
|
Und wenn du schon viel Code postet benutz nopaste, dann hat man auch Syntaxhighlighting und kann den Code viel besser lesen.
Bei 3 zeilen natürlich nicht!
|
|
|
|
|
|
|
Neues Problem. Wir versuchen gerade die Kollision mit dem Schläger hinzubekommen.
Dazu haben wir in der Methode move() eine If Verzweigung angelegt.
Dennoch bringt es nicht viel, er dotzt zwar unten am Rand ab, aber nicht an unseren Schläger
Hier der Codeschnipsel, unser Lehrer meint, es sei einfache Mathematik dieses Problem zu lösen :<
|
Code: |
if (schlaeger.getPosition().getY() < position.getY() + BALLSIZE / 2) {
position.y = (int)(schlaeger.getPosition().getY() + BALLSIZE / 2);
dy = -dy;
} |
|
|
|
|
|
|
|
|
Morgen,
Du könntest mal eine .zip erstellen mit deinen Klassen, dann könnte ich dir bei mir ins Eclipse packen und schöner danach schauen !
Denn mit den kleinen CodeSchnipseln ist das echt schwer..
¤: hehe, ja grundlegend reichen ja auch kliene Schnipsel, wenn sich das problem auch nur auf den Schnipsel bezieht.. aber bei dir sind das eben Dinge die muss man mal im Ganzen sehen oder du beschreibst was die Funktion da genau macht..
Zudem gehöre ich hier gar nicht rein bin nur zufällig auf den Thread gestoßen .
|
[Dieser Beitrag wurde 2 mal editiert; zum letzten Mal von JJDTE am 22.11.2007 10:16]
|
|
|
|
|
|
| Zitat von JJDTE
Morgen,
Du könntest mal eine .zip erstellen mit deinen Klassen, dann könnte ich dir bei mir ins Eclipse packen und schöner danach schauen !
Denn mit den kleinen CodeSchnipseln ist das echt schwer..
| |
Ihr wisst auch nicht was ihr wollt
Ich exportiere es, und versuchs hier ma zu zippen... .
|
|
|
|
|
|
|
Ein bisschen JavaDoc dürfte auch nicht schaden. Außer euer VET hat das ja niemand gemacht.
|
|
|
|
|
|
|
Unser Lehrer hat uns nun folgendes aufgeschrieben:
|
Code: |
Kollision von oben:
p1.y + r = p2.y
p2.x <= p1.x <= p2.x + b
Kollision von unten:
p1.y - r = p2.y + h
p2.x <= p1.x <= p2.x +b
Kollision von links:
p1.x + r = p2.x
p2 <= p1.y <= p2.y + h
Kollision von rechts:
p1.x - r = p2.x + b
p2 <= p1.y <= p2.y + h
p1 = Anfangsposition des Balls
p2 = Anfangsposition des Bausteins
b = Breite
h = Höhe
r = Radius vom Ball
|
|
Für die Kollision des Balls mit dem Baustein.
Umgesetzt haben wir es so:
|
Code: |
public void kollision(){
// Kollision von oben
if (steinchen.getPosition().getX() <= position.getX() <= steinchen.getPosition().getX() + steinchen.getSW()) {
position = steinchen.getPosition().getY() && position.y + BALLSIZE ;
}
// Kollision von unten
if (steinchen.getPosition().getX() <= position.getX() <= steinchen.getPosition().getX() + steinchen.getSW()){
position.x = steinchen.getPosition().getY() + steinchen.getSH() && position.y() - BALLSIZE ;
}
// Kollision von links
if (steinchen.getPosition().getY() <= position.y <= steinchen.getPosition().getY() + steinchen.getSH()) {
position.y = steinchen.getPosition().getX() = position.x + BALLSIZE ;
}
// Kollision von rechts
if (steinchen.getPosition().getY() <= position.y <= steinchen.getPosition().getY() + steinchen.getSH()){
position.y = steinchen.getPosition().getX() + steinchen.getSW() && position.x - BALLSIZE ;
}
|
|
Das es falsch ist, wissen wir, aber wie macht man es richtig ? =D
|
[Dieser Beitrag wurde 1 mal editiert; zum letzten Mal von leslie am 29.11.2007 10:21]
|
|
|
|
|
|
wie ausführlich und gut soll denn deine "physik-engine" sein? für pong könnte man das wohl problemlos so lösen.
das problem gliedert sich ja in mehrere fragen:
a) liegt ein kollisionsfall vor?
b) wenn ja: wo kam es zur kollision?
c) wie ändert sich die bewegung des balles?
antworten:
a) die vier fälle hast du aufgeschrieben. prüf nochmal h und b, die hast du (glaub ich) vertauscht. also zum beispiel linksseitige prüfung: p1+r>=p2; rechtseitig: p1-r<=p2+b; rest analog.
b) es liegt also eine kollision vor.
wenn an es an einer der seiten war: guck dir den bewegungsvektor an. dann reicht es die jeweilige ortskomponente zu spiegeln.
beispiel, wenn der ball von links kam:
neu_p1.x=p2.x-(bewegung.x-(p2.x-(alt_p1.x+r)))-r (ich hoffe, ich hab mich nicht verguckt.)
versuch das nachzuvollziehen! man nimmt den bewegungsvektor und bricht den am kollisionspunkt ab. das restliche stück wird dann spiegelverkeht wieder angesetzt. zu beachten ist der radius des balls, der nicht unter den tisch fallen darf. das ist natürlich sehr simpel (schönschreibübung...), funktioniert aber auch nur eingeschränkt.
wenn er auf eine ecke getroffen ist, dann kannst du dich entweder für eine der beiden seiten entscheiden, oder eine echt komplizierte bewegungsanalyse vornehmen. mein vorschlag: nimm die einfach variante und tu so, als sei er kurz neben der ecke aufgeschlagen.
c) bewegung.x=-bewegung.x (für den obigen fall.)
das sollte trivial zu verstehen sein.
konklusion: (mann, das klingt aber gestochen :=D)
zerleg es in kleine probleme. sieh zu, dass du code wiederverwenden kannst, ansonsten artet das in echt üble schreibarbeit aus. und denk daran, dass du ja pro zug mehrere pixel überspringst, deswegen eine kollision NIE mit = prüfen, sondern immer mit >= !
ich hoffe, ich hab mich grad nicht total verrant.
|
|
|
|
|
|
|
Deja vu! Wir haben damals sogar unseren Vektor auch (dx/dy) genannt. Wenn auch in Delphi.
| Zitat von rABBI
und denk daran, dass du ja pro zug mehrere pixel überspringst, deswegen eine kollision NIE mit = prüfen, sondern immer mit >= !
ich hoffe, ich hab mich grad nicht total verrant.
| |
Und pass auf, dass wenn die Kollision innerhalb des Schlägers (der Wand, whatever) und nicht an der Außenwand passiert ist, du dafür sorgst, dass das Objekt wieder rauskommt bevor die nächste Kollisionsprüfung kommt. Sonst "zittert" der nämlich in dem Objekt durch die Gegend.
|
[Dieser Beitrag wurde 1 mal editiert; zum letzten Mal von [Dicope] am 29.11.2007 15:32]
|
|
|
|
|
|
oh ja, passiert gerne, wenn man den bewegungsvektor nicht nur spiegelt, sondern auch bei jeder kollision schwächt. ist mir mehr als einmal passiert.
wegen delphi: wir haben das in der schule in zig sprachen implementiert (meistens ein springender punkt oder einfaches pong) und jedes mal den gleichen stil und die gleichen benamungen und so weiter genutzt. hat mit letztendlich nix gebracht, außer vieles lesen zu können. alternative sprachkonzepte sollte man jedenfalls nicht so zu lernen versuchen.
|
|
|
|
|
|
|
Also die Kollision zwischen Schläger und Ball haben wir schon fertig, aber wie gesagt, wir hängen an den Bausteinen grml.
Danke schonmal, ich versuchs morgen in der Schule mal, falls nicht, werd ich mir hier wieder melden
|
|
|
|
|
|
|
Wir = zu doof
|
|
|
|
|
|
|
was ist denn das problem? die logik? die umsetzung? mit "zu doof" kann man wenig anfangen und die glaskugel ist grad in der werkstatt.
|
|
|
|
|
|
|
rABBI need your Help.
Wir haben nun fast alles, bis auf den Highscore/Scoreanzeige und die richtige Kollision.
Er löscht nun die einzelnen Steine, wenn sie getroffen werden, jedoch löscht er die ganze Reihe, wenn der Ball über die Höhe der Steinreihe kommt.
Wir finden den Fehler einfach nicht. Hilfe!
|
Code: |
public void kollision() {
for (int i = baustein.size()-1; i >= 0; i--) {
// Kollision von oben
if ( baustein.get(i).getPosition().getY() >= position.y
+ BALLSIZE / 2 && baustein.get(i).getPosition().getX() <= position.x
&& position.x <= baustein.get(i).getPosition().getX()
+ baustein.get(i).getSW()) {
kollidiert = true;
dy = -dy;
}
// Kollision von unten
else if (baustein.get(i).getPosition().getY() + baustein.get(i).getSH() >= position.y
- BALLSIZE / 2
&& baustein.get(i).getPosition().getX() <= position.x
&& position.x <= baustein.get(i).getPosition().getX()
+ baustein.get(i).getSW()) {
kollidiert = true;
dy = -dy;
}
// Kollision von links
else if (baustein.get(i).getPosition().getX() < position.x
+ BALLSIZE / 2 && baustein.get(i).getPosition().getY() <= position.y
&& position.y <= baustein.get(i).getPosition().getY()
+ baustein.get(i).getSH()) {
kollidiert = true;
dx = -dx;
}
// Kollision von rechts
else if (baustein.get(i).getPosition().getX()
+ baustein.get(i).getSW() > position.x
- BALLSIZE / 2 && baustein.get(i).getPosition().getY() <= position.y
&& position.y <= baustein.get(i).getPosition().getY()
+ baustein.get(i).getSH()) {
kollidiert = true;
dx = -dx;
}
if(kollidiert == true){
baustein.remove(i);
int punkte = 100;
int punktestand = gp.getScore() + punkte;
gp.setScore(punktestand);
Console.println("Score: "+ punktestand);
kollidiert = false;
}
}
} |
|
Wir glauben, dass die Kollision für Unten kaputt ist :[
|
|
|
|
|
|
|
|
Code: |
public void kollision() {
for (int i = baustein.size()-1; i >= 0; i--) {
// Kollision von oben
if ( (baustein.get(i).getPosition().getY() - (BALLSIZE/2) <= position.y)
&& (baustein.get(i).getPosition().getY() >= position.y)
&& (baustein.get(i).getPosition().getX() - (BALLSIZE/2) <= position.x)
&& (baustein.get(i).getPosition().getX() + baustein.get(i).getSW() + (BALLSIZE/2) >= position.x)
) {
kollidiert = true;
dy = -dy;
}
// Kollision von unten
else if ( (baustein.get(i).getPosition().getY() + baustein.get(i).getSH() <= position.y)
&& (baustein.get(i).getPosition().getY() + baustein.get(i).getSH() + (BALLSIZE/2) >= position.y)
&& (baustein.get(i).getPosition().getX() - (BALLSIZE/2) <= position.x)
&& (baustein.get(i).getPosition().getX() + baustein.get(i).getSW() + (BALLSIZE/2) >= position.x)
) {
kollidiert = true;
dy = -dy;
}
// Kollision von links
else if ( (baustein.get(i).getPosition().getY() - (BALLSIZE/2) <= position.y)
&& (baustein.get(i).getPosition().getY() + baustein.get(i).getSH() + (BALLSIZE/2) >= position.y)
&& (baustein.get(i).getPosition().getX() - (BALLSIZE/2) <= position.x)
&& (baustein.get(i).getPosition().getX() >= position.x)
) {
kollidiert = true;
dx = -dx;
}
// Kollision von rechts
else if ( (baustein.get(i).getPosition().getY() - (BALLSIZE/2) <= position.y)
&& (baustein.get(i).getPosition().getY() + baustein.get(i).getSH() + (BALLSIZE/2) >= position.y)
&& (baustein.get(i).getPosition().getX() + baustein.get(i).getSW() <= position.x)
&& (baustein.get(i).getPosition().getX() + baustein.get(i).getSW() + (BALLSIZE/2) >= position.x)
) {
kollidiert = true;
dx = -dx;
}
if(kollidiert == true){
baustein.remove(i);
int punkte = 100;
int punktestand = gp.getScore() + punkte;
gp.setScore(punktestand);
Console.println("Score: "+ punktestand);
kollidiert = false;
}
}
} |
|
versuch mal den. ich hab das kollisionsmodell mal so abgeändert, dass er die randbereiche, die um die steine liegen (durch den ballradius aufgespannt), absucht nach bällen und daran die kollision festmacht. hat natürlich auch einen nachteil: wenn der ball pro zug mehr als ballsize/2 pixel fliegt, dann gibts fehler, weil er plötzlich in der mitte des steins ist und keine kollision erkannt wird.
|
|
|
|
|
|
|
so. das weiße innen ist der stein. das "schraffierte" drumrum ist der bereich, in dem sicht der mittelpunkt des balls befinden muss, damit der rand kollidiert.
die möglichkeiten des mittelpunkts:
grün: keine kollision.
blau: kollision oben. dy umkehren.
rot: kollision innen. der ball hat den randbereich einfach übersprungen (zu schnell) und hängt jetzt in der mitte fest. im idealfall: sonderfall für die kollisionsprüfung einrichten und den bewegungsvektor angucken, woher der ball kam.
|
[Dieser Beitrag wurde 1 mal editiert; zum letzten Mal von rABBI am 13.12.2007 20:56]
|
|
|
|
|
Thema: [Java/Coding] Spieleproblem ( Breakout will nicht so wie wir ! ) |
|