Hallo,
ich würde gerne mein Problem vorstellen und zwar handelt es sich um ein aus meiner Ansicht nach sehr "mysteriöses" Problem. (das aber natürlich trotzdem eine vollkommen rationale Erklärung haben muss, die mir nur nicht einleuchten will.)
Und zwar habe ich ein kleines Programm erstellt, bei dem ein kleiner Ball fällt durch eine Gravity-Klasse. Beim "Aufschlagen" (also die Geschwindigkeit des Balls beim Auftreffen auf den Boden muss eine Mindestgeschwindigkeit überschreiten, dass das Auftreffen als Aufschlagen gilt.) kommt eine Bounce-Klasse hinzu, die nun berechnet, wie sehr der Ball nach oben "dopst" je nach Aufschlaggeschwindigkeit.
Mein Problem ist, dass beim normalen Ablauf nie die Kondition ob der Ball aufgeschlagen ist in der Bounce-Klasse irgendwie abgefragt wird obwohl beide Threads (Gravity & Bounce) laufen.
Beim Debuggen mit einem Breakpoint auf der if-Abfrage funktioniert das Programm plötzlich. Zwar noch nicht perfekt, aber der Ball "dopst" jedenfalls überhaupt irgendwie sichtbar.
Hier sind die betroffenen Klassen:
Wäre wirklich toll, wenn mir jemand helfen könnte, denn ich finde das wirklich sehr komisch.
Danke.
ich würde gerne mein Problem vorstellen und zwar handelt es sich um ein aus meiner Ansicht nach sehr "mysteriöses" Problem. (das aber natürlich trotzdem eine vollkommen rationale Erklärung haben muss, die mir nur nicht einleuchten will.)
Und zwar habe ich ein kleines Programm erstellt, bei dem ein kleiner Ball fällt durch eine Gravity-Klasse. Beim "Aufschlagen" (also die Geschwindigkeit des Balls beim Auftreffen auf den Boden muss eine Mindestgeschwindigkeit überschreiten, dass das Auftreffen als Aufschlagen gilt.) kommt eine Bounce-Klasse hinzu, die nun berechnet, wie sehr der Ball nach oben "dopst" je nach Aufschlaggeschwindigkeit.
Mein Problem ist, dass beim normalen Ablauf nie die Kondition ob der Ball aufgeschlagen ist in der Bounce-Klasse irgendwie abgefragt wird obwohl beide Threads (Gravity & Bounce) laufen.
Beim Debuggen mit einem Breakpoint auf der if-Abfrage funktioniert das Programm plötzlich. Zwar noch nicht perfekt, aber der Ball "dopst" jedenfalls überhaupt irgendwie sichtbar.
Hier sind die betroffenen Klassen:
Java:
package gui;
import cstm.io.CustomIOHandler;
import cstm.geom.HitDetector;
import java.awt.*;
/**
*
* @author EKzyis
* @version 1.1
*/
public class Ball {
final static boolean d = true;
final double MASS = 10;
final int SIZE = 25;
final Color COLOR = Color.RED;
boolean ground = false;
boolean hit = false;
boolean dragged = false;
double v;
/**
* @param x X-Koordinate des Mittelpunkt des Kreises
* @param y Y-Koordinate des Mittelpunkt des Kreises.
*/
int x,y;
PE_Panel panel;
/**
* Einrichtung des Balls
* @param panel Zeichenfläche, auf der der Ball gezeichnet wird
*/
public Ball(PE_Panel panel) {
CustomIOHandler.setDebugMode(d,this);
x = panel.getPreferredSize().width/2;
y = panel.getPreferredSize().height/2;
this.panel = panel;
}
/**
* Legt fest, ob der Ball anvisiert wurde mit einer
* quadratischen Hitbox, dessen Kanten auf dem Kreis liegen.
* @param x1 X-Koordinate der Maus
* @param y1 Y-Koordinate der Maus
* @return getroffen oder nicht.
*/
public boolean quadrat_isHit(int x1,int y1) {
CustomIOHandler.println("x_ball: "+x+"-"+(x+SIZE)+" ; x_maus: " +x1 );
CustomIOHandler.println("y_ball: "+y+"-"+(y+SIZE)+" ; y_maus " + y1);
return HitDetector.recIsHit(x-SIZE/2,y-SIZE/2,SIZE,SIZE,x1,y1);
}
/**
* Legt fest, ob er Ball anvisiert wurde mit einer
* Hitbox, die den Kreis ideal wiedergibt.
* @param x1 X-Koordinate der Maus
* @param y1 Y-Koordinate der Maus
* @return getroffen oder nicht.
*/
public boolean circle_isHit(int x1, int y1) {
CustomIOHandler.println("x_ball: "+x+" mit Durchmesser von: "+SIZE+" ; x_maus: " +x1 );
CustomIOHandler.println("y_ball: "+y+" mit Durchmesser von: "+SIZE+" ; y_maus " + y1);
return HitDetector.circleIsHit(x, y, SIZE/2, x1, y1);
}
/**
*
* @return Farbe des Balls
*/
public Color getColor() {
return COLOR;
}
/**
*
* @return X-Koordinate des Balls.
*/
public int getX() {
return x;
}
/**
*
* @return Y-Koordinate des Balls
*/
public int getY() {
return y;
}
/**
* gibt Größe des Balls zurück
* @return Größe des Balls
*/
public int getSize() {
return SIZE;
}
/**
* setzt X fest
* @param x neue X-Koordinate des Balls.
*/
public void setX(int x) {
this.x = x;
}
/**
* setzt Y fest
* @param y neue Y-Koordinate des Balls.
*/
public void setY(int y) {
this.y = y;
if(y+SIZE/2>=panel.getPreferredSize().height){
CustomIOHandler.println("Ball is on the floor. -ball");
setIsOnTheGround(true);
this.y = panel.getPreferredSize().height-SIZE/2;
}
else {
setIsOnTheGround(false);
}
}
/**
* Setzt fest, ob der Ball auf dem Boden liegt und
* berechnet anhand einer Mindestgeschwindigkeit,
* ob der Ball aufgeschlagen ist oder nicht.
* (sonst bounct er ewig.)
* @param set auf dem Boden oder nicht
*/
public void setIsOnTheGround(boolean set) {
ground = set;
if(ground && getV()>1){
setHitTheGround(true);
}
else{
setHitTheGround(false);
}
}
/**
* Gibt zurück, ob der Ball den Boden berührt.
* @return auf dem Boden oder nicht
*/
public boolean isOnTheGround(){
return ground;
}
/**
* setzt fest, ob der Ball soeben auf den Boden aufgeschlagen ist.
* @param set hit oder nicht
*/
public void setHitTheGround(boolean set) {
hit = set;
if(hitTheGround()) {
CustomIOHandler.println("Ball hit the ground with v = " + getV() + " -ball ");
}
}
/**
* Ist der Ball soeben aufgeschlagen?
* @return hit oder nicht
*/
public boolean hitTheGround() {
return hit;
}
/**
* Wird der Ball gerade bewegt vom User?
* @return bewegt oder nicht
*/
public boolean isDragged(){
return dragged;
}
/**
* Setzt fest, ob der Ball bewegt wird.
* @param set wird bewegt oder nicht
*/
public void setDragging(boolean set){
dragged = set;
}
/**
* Lässt den Ball wissen, wie schnell er bewegt wird.
* Negative Geschwindigkeit bedeutet steigend,
* postive Geschwindigkeit bedeutet fallend.
* @param speed aktuelle Geschwindigkeit des Balls
*/
public void setV(double speed) {
this.v = speed;
}
/**
* Gibt aktuelle Geschwindigkeit des Balls zurück.
* Negative Geschwindigkeit bedeutet steigend,
* postive Geschwindigkeit bedeutet fallend.
* @return aktuelle Geschwindigkeit des Balls
*/
public double getV() {
return v;
}
/**
* Gibt Masse des Balls zurück (für bspw. Impulsberechnungen.)
* @return Masse des Balls
*/
public double getMass() {
return MASS;
}
}
Java:
package cmd;
import cstm.io.CustomIOHandler;
import cstm.io.Flag;
import gui.Ball;
import gui.PE_Panel;
/**
* Klasse, die für die Schwerkraft eines Balls zuständig ist.
* @author EKzyis
* @version 1.0
*/
public class Gravity extends Thread {
final static boolean d = true;
final static double ACCELERATION = 9.81;
Ball ball;
PE_Panel panel;
Flag flag;
double t,dT=0.1,v;
/**
* Einrichtung Gravity
* @param ball Ball-Instanz
* @param panel Zeichenfläche
*/
public Gravity(Ball ball, PE_Panel panel) {
flag = new Flag();
this.ball = ball;
this.panel = panel;
CustomIOHandler.setDebugMode(d,this);
CustomIOHandler.setBrandingMode(false);
}
@Override
public void run() {
while(true) {
/**
* Wenn Ball auf dem Boden ist, und noch kein "onthefloor"-Flag gesetzt wurde
* (verhindert mehreres Anzeigen von "Ball is on the floor."):
*/
if(ball.isOnTheGround() && !flag.contains("onthefloor")) {
flag.addFlag("onthefloor");
flag.removeFlag("falling");
}
/**
* Refresh-Intervall = 0,1s
*/
try {
sleep(100);
} catch (InterruptedException ex){
CustomIOHandler.println("***THREAD HAS BEEN INTERRUPTED***",true);
}
/**
* Solange Ball nicht auf dem Boden ist & Ball nicht vom User gezogen wird:
*/
while(!ball.isOnTheGround() && !ball.isDragged()) {
flag.addFlag("running");
/**
* Wenn noch kein "falling"-Flag gesetzt wurde (verhindert mehreres Anzeigen von "Ball is falling, watch out!")
* (Das bedeutet, dass Ball nun beginnt zu fallen, t=0):
*/
if(!flag.contains("falling")){
CustomIOHandler.println("Ball is falling, watch out! -gravity");
flag.addFlag("falling");
flag.removeFlag("onthefloor");
t=0;
}
/**
* Refresh-Intervall 10ms
*/
try {
sleep(10);
} catch (InterruptedException ex) {
CustomIOHandler.println("***THREAD HAS BEEN INTERRUPTED***",true);
}
v = ACCELERATION*t;
CustomIOHandler.println("v = "+v+ " -gravity");
ball.setV(ACCELERATION*t);
/**
* alle 0,1s wird Ball-Instanz neue Y-Koordinate zugewiesen nach der Formel s = 0.5*a*(t^2)
*/
ball.setY((int)(ball.getY()+(0.5*(ACCELERATION*t*t))));
panel.repaint();
t=t+dT;
}
t=0;
flag.removeFlag("running");
}
}
}
Java:
package cmd;
import cstm.io.CustomIOHandler;
import cstm.io.Flag;
import gui.Ball;
import gui.PE_Panel;
/**
* Klasse, die für das Dopsen eines Balls zuständig ist.
* @author EKzyis
* @version 1.0
*/
public class Bounce extends Thread {
final static boolean d = true;
Ball b;
PE_Panel panel;
double t;
double v0;
Flag flag;
public Bounce(Ball ball, PE_Panel panel){
this.b = ball;
this.panel = panel;
CustomIOHandler.setDebugMode(d,this);
CustomIOHandler.setBrandingMode(false);
flag = new Flag();
}
@Override
public void run() {
while(true) {
if(b.hitTheGround()) {
if(!flag.contains("bouncing")){
CustomIOHandler.println("Ball is bouncing. -bounce");
flag.addFlag("bouncing");
}
try {
sleep(10);
} catch (InterruptedException ex) {
CustomIOHandler.println("***THREAD HAS BEEN INTERRUPTED***",true);
}
t=0.1;
b.setV(b.getV()*-1);
v0 = b.getV();
while(b.getV()<0){
CustomIOHandler.println("v0 = "+v0 +" -bounce");
b.setY((int)(b.getY()+b.getV()*t));
b.setV(v0+Gravity.ACCELERATION*t);
panel.repaint();
try {
sleep(10);
} catch (InterruptedException ex) {
CustomIOHandler.println("***THREAD HAS BEEN INTERRUPTED***",true);
}
t=t+0.1;
}
b.setHitTheGround(false);
b.setIsOnTheGround(false);
flag.removeFlag("bouncing");
}
}
}
}
Java:
package gui;
import cstm.gui.CustomGraphicsHandler;
import cstm.io.CustomIOHandler;
import javax.swing.*;
import java.awt.*;
/**
* Zeichenklasse des Programms.
* @author EKzyis
*/
public class PE_Panel extends JPanel {
final static boolean d = true;
Ball b;
/**
* Einrichtung der Zeichenfläche
*/
public PE_Panel() {
this.setPreferredSize(new Dimension(500,1000));
CustomIOHandler.setDebugMode(d,this);
CustomIOHandler.setBrandingMode(false);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.WHITE);
g.setColor(b.getColor());
//g.drawOval(b.getX(),b.getY(),b.getSize(),b.getSize());
//Zeichnet einen Kreis und legt x und y als Mittelpunkt fest (nicht als oberen, linken Eckpunkt)
CustomGraphicsHandler.fillCircle(g, b.getX(), b.getY(), b.getSize());
g.setColor(Color.BLACK);
int x = b.getX();
int y = b.getY();
int size = b.getSize();
//g.drawRect(x-size/2,y-size/2,size,size);
}
public void addBall(Ball b) {
this.b = b;
}
}
Java:
package gui;
import cmd.Bounce;
import cmd.Gravity;
import cmd.PE_MouseAdapter;
import javax.swing.JFrame;
/**
* Hauptfenster des Programms.
* @author EKzyis
*/
public class PE_MFrame extends JFrame {
PE_Panel panel;
PE_MouseAdapter adapter;
Ball ball;
Gravity gravity;
public PE_MFrame(String title) {
super(title);
setLocation(5,5);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new PE_Panel();
ball = new Ball(panel);
adapter = new PE_MouseAdapter();
adapter.addPanel(panel);
adapter.addBall(ball);
gravity = new Gravity(ball,panel);
Bounce bounce = new Bounce(ball,panel);
panel.addMouseMotionListener(adapter);
panel.addMouseListener(adapter);
panel.addBall(ball);
getContentPane().add(panel);
pack();
gravity.start();
bounce.start();
}
}
Danke.
Zuletzt bearbeitet: