# PingPong 3D



## Tessarozza (3. Mrz 2009)

Hallo Forengemeinde,

ich habe leider ein mittelschweres Problem. Ich habe einen Pongspiel geschrieben, dass auf Java3D basiert, es ist grafisch soweit fertig, nur es hat noch keinerlei Funktionalität.  
Ich habe Schwierigkeiten dabei Funktionen für die Balken und den Ball zu implementieren, ich hoffe einer von euch kann mir helfen, dass Spiel zum laufen zu bringen! Vielen Dank schonmal im Vorraus! 

Den Quellcode findet ihr hier:

[HIGHLIGHT="Java"]  
import java.awt.Button;
import java.awt.Panel;
import java.awt.event.*;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.swing.JFrame;
import javax.swing.Timer;


public class PingPong3D extends JFrame{

		public Canvas3D Spiel3D; 
		BoundingSphere bounds = new BoundingSphere(new   Point3d(0.0,0.0,0.0),Double.MAX_VALUE);
		//Variabeln die für die Positionsinterpolation benötigt werden!
		private final float maxLeftRight = 0.95f;
		private final long todotime = 4000;
		private int startingTime = 3000;
		private Button start = new Button("Start");




		public PingPong3D(){
		//Mechanismus zum Schliessen des Fensters und beenden des Programms
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Spiel3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
		SimpleUniverse simpleUniverse = new SimpleUniverse(Spiel3D);
		simpleUniverse.getViewingPlatform().setNominalViewingTransform();

		//Die Szene wird in dieser Methode erzeugt
		createSceneGraph(simpleUniverse);

		Panel panel = new Panel();
		panel.add(start);
		add("North", panel);
		//Hinzufügen von Licht
		addLight(simpleUniverse);
		setTitle("PingPong3D");
		setSize(800, 300);
		getContentPane().add("Center", Spiel3D);
		setVisible(true);

	  }


	  public void createSceneGraph(SimpleUniverse simpleUniverse){


		//Erzeugen eines weissen Hintergrundes
		  Background bg = new Background(new Color3f(1.0f,1.0f,1.0f));
		  BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),1000.0);
		  bg.setApplicationBounds(bounds);

		  //Zusammenstellung der Szene aus (Hintergrundfarbe, Ball, Balken1, Balken2, Musik)
		  BranchGroup theScene = new BranchGroup();
		  theScene.addChild(this.initBall());
		  theScene.addChild(this.initBalken1());
		  theScene.addChild(this.initBalken2());
		  theScene.addChild(bg);
		  theScene.compile();
		  simpleUniverse.addBranchGraph(theScene); 

	  }

	  public void addLight(SimpleUniverse simpleUniverse){

		  //Einfügen von zwei Lichtquellen
		  BranchGroup bgLight = new BranchGroup();
		  BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
		  Color3f lightColour1 = new Color3f(1.0f,1.0f,1.0f);
		  Vector3f lightDir1  = new Vector3f(-1.0f,0.0f,-0.5f);
		  DirectionalLight light1 = new DirectionalLight(lightColour1, lightDir1);
		  light1.setInfluencingBounds(bounds);
		  bgLight.addChild(light1);
		  Vector3f lightDir2  = new Vector3f(1.0f,0.0f,0.5f);
		  DirectionalLight light2 = new DirectionalLight(lightColour1, lightDir2);
		  light2.setInfluencingBounds(bounds);
		  bgLight.addChild(light2);
		  /*//Einfügen von Umgebungslicht
		  Color3f lightColour = new Color3f(0.2f, 2.5f, 4.0f);
		  AmbientLight ambLight = new AmbientLight(lightColour);
		  ambLight.setInfluencingBounds(bounds);
		  bgLight.addChild(ambLight);*/

		  simpleUniverse.addBranchGraph(bgLight);
	  }

	  public TransformGroup initBalken1(){

			//Ein rechter Balken, der in der Szene erscheinen soll inklusive Transformationsgruppe

			 //Die Farben fuer die Appearance
			 Color3f ambientColourFBalken1 = new Color3f(0.2f,0.2f,0.2f);
			 Color3f emissiveColourFBalken1 = new Color3f(0.0f,0.0f,0.0f);
			 Color3f diffuseColourFBalken1 = new Color3f(0.6f,0.6f,0.6f);
		     Color3f specularColourFBalken1 = new Color3f(0.5f,0.5f,0.5f);
		     float shininessFBalken1 = 128.0f;


			 //Die Appearance fuer den Balken1
		     Appearance balken1App = new Appearance();
		     balken1App.setMaterial(new Material(ambientColourFBalken1,emissiveColourFBalken1,
				                          diffuseColourFBalken1,specularColourFBalken1,shininessFBalken1));

		     //Der Balken1 mit Größenangaben und balken1App = Aussehen
			 Box balken1 = new Box(0.006f,0.06f,0.006f,balken1App);

			 //Die Transformationsgruppe des Wuerfels mit Math.PI/x ist es möglich
			 //Balken zu drehen und zu wenden!
		     Transform3D tfFBalken1 = new Transform3D();
		     tfFBalken1.rotY(Math.PI/1);
			 Transform3D rotationX = new Transform3D();
		     rotationX.rotX(Math.PI/1);
			 tfFBalken1.mul(rotationX);
			 TransformGroup tgFBalken1 = new TransformGroup(tfFBalken1);
			 tgFBalken1.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			 Transform3D seatAxis = new Transform3D();
			 seatAxis.rotX(Math.PI/2);
			 Alpha seatAlpha = new Alpha(1,//unendliche male
					 Alpha.INCREASING_ENABLE, 0, startingTime,
			         todotime,//time for rotation
			         0,0,0,0,0);//der rest
			 PositionInterpolator movSeat = new PositionInterpolator(
			      seatAlpha, tgFBalken1, seatAxis, 0.0f, maxLeftRight);
			    movSeat.setSchedulingBounds(bounds);




			tgFBalken1.addChild(movSeat);
			tgFBalken1.addChild(balken1);
			return tgFBalken1;

		  }

	  public TransformGroup initBalken2(){

			//Ein linker Balken, der in der Szene erscheinen soll inklusive Transformationsgruppe

			 //Die Farben fuer die Appearance
			 Color3f ambientColourFBalken2 = new Color3f(0.2f,0.2f,0.2f);
			 Color3f emissiveColourFBalken2 = new Color3f(0.0f,0.0f,0.0f);
			 Color3f diffuseColourFBalken2 = new Color3f(0.6f,0.6f,0.6f);
		     Color3f specularColourFBalken2 = new Color3f(0.5f,0.5f,0.5f);
		     float shininessFBalken2 = 128.0f;


			 //Die Appearance fuer den Balken1
		     Appearance balken2App = new Appearance();
		     balken2App.setMaterial(new Material(ambientColourFBalken2,emissiveColourFBalken2,
				                          diffuseColourFBalken2,specularColourFBalken2,shininessFBalken2));

		     //Der Wuerfel
			 Box balken2 = new Box(0.006f,0.06f,0.006f,balken2App);

			 //Die Transformationsgruppe des Wuerfels mit Math.PI/x ist es möglich
			 //Balken zu drehen und zu wenden!

		     Transform3D tfFBalken2 = new Transform3D();
		     tfFBalken2.rotY(Math.PI/1);
			 Transform3D rotationX = new Transform3D();
		     rotationX.rotX(Math.PI/1);
			 tfFBalken2.mul(rotationX);
			 TransformGroup tgFBalken2 = new TransformGroup(tfFBalken2);

			 tgFBalken2.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			 Transform3D seatAxis = new Transform3D();
			 seatAxis.rotY(2*Math.PI/2);
			 Alpha seatAlpha = new Alpha(1,//unendliche male
					 Alpha.INCREASING_ENABLE, 0, startingTime,
			         todotime,//time for rotation
			         0,0,0,0,0);//der rest
			 PositionInterpolator movSeat = new PositionInterpolator(
			      seatAlpha, tgFBalken2, seatAxis, 0.0f, maxLeftRight);
			    movSeat.setSchedulingBounds(bounds);


			 tgFBalken2.addChild(movSeat);
			 tgFBalken2.addChild(balken2);
		     return tgFBalken2;

		  }
	  public TransformGroup initBall(){

		  //Unser Ball, der in der Szene erscheinen soll inklusive  Transformationsgruppe
		  //und Rotation.

		  Color3f ambientColourBSphere = new Color3f(0.2f,0.2f,0.2f);
		  Color3f emissiveColourBSphere = new Color3f(0.0f,0.0f,0.0f);
		  Color3f diffuseColourBSphere = new Color3f(0.6f,0.6f,0.6f);
		  Color3f specularColourBSphere = new Color3f(0.5f,0.5f,0.5f);
		  float shininessBSphere = 128.0f;

	    //Die Appearance fuer die Kugel
		  Appearance bSphereApp = new Appearance();
		  bSphereApp.setMaterial(new Material(ambientColourBSphere,emissiveColourBSphere,
	                          diffuseColourBSphere,specularColourBSphere,shininessBSphere));

		//Der Ball ohne Tesselierung
		  //Sphere bSphere = new Sphere(0.1f,bSphereApp);

		// Ball mit Tesselierung
		  PolygonAttributes polygBall = new PolygonAttributes();
		  polygBall.setPolygonMode(PolygonAttributes.POLYGON_LINE);
		  bSphereApp.setPolygonAttributes(polygBall);
		  Sphere bSphere = new Sphere(0.015f, Sphere.GENERATE_NORMALS, 500, bSphereApp);

	    //Die Transformationsgruppe des Balls

		  Transform3D tfBSphere = new Transform3D();
		  tfBSphere.setTranslation(new Vector3f(1.0f,1.0f,-1.0f));
		  TransformGroup tgBSphere = new TransformGroup();
		  tgBSphere.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

	    //Ball rotieren lassen

		  Alpha rotationAlpha = new Alpha(-1, 15000);
		  RotationInterpolator rotator = 
			  new RotationInterpolator(rotationAlpha, tgBSphere);
		  rotator.setSchedulingBounds(bounds);
		  tgBSphere.addChild(rotator);
		  tgBSphere.addChild(bSphere);

		  return tgBSphere;

	  }



	  public static void main(String[] args)  {

		  new PingPong3D();

	  }

}
[/HIGHLIGHT]


----------



## Marco13 (3. Mrz 2009)

Und die Frage ist............ ?


----------



## Tessarozza (3. Mrz 2009)

Ja, ich schaffe es nicht Funktionen zu schreiben.... z.B Balken bewegen mit Tastatur... oder dass der Ball sich im Raum bewegt.... damit habe ich probleme .... ich schaue mir ständig irgendwelche Pong2D-Codes an und werde daraus nicht schlau.... und das ist mein Problem und auch meine Frage...

Wie binde ich eine Funktion in meinen Code Funktionen ein, dass sich 

1) der Ball im Raum bewegt

2) sich die Balken bewegen

????


----------



## Developer_X (3. Mrz 2009)

erstmal, mach deine klasse extends Keylistener
dann füge die voids:

```
public class PingPong3D extends Keylistener
{
....
public void keypressed(arg0){}
public void keyreleased(arg0){}
public void keytyped(arg0){}
.....
}
```
Ich hoffe doch sehr, du bist vertraut mit dem verwenden von Keylistenern,
wenn nicht, ich machs dir kein problem, musst es nur sagen.


----------



## Ebenius (3. Mrz 2009)

Developer_X, da ich das in letzter Zeit schon öfter lesen musste: Bitte feile mal an Deiner Wortwahl; zumindest was die Fachbegriffe angeht! Was Du schreibst ergibt in sich Sinn (habe den Thread nicht verfolgt), die richtige Formulierung wäre doch aber viel weniger falsch: _Lass Deine Klasse das KeyListener-Interface *implementieren* und füge diese *Methoden* hinzu!_​"Void" heißt nichts anderes als "ungültig", "Lücke" oder "Leerstelle" und hat mit dem Wort "Methode" eben nichts zu tun.

Danke, Ebenius


----------



## Illuvatar (3. Mrz 2009)

Außerdem schreibt man die Methoden von KeyListener anders. keyPressed, keyReleased, keyTyped.

Aber das ist egal, weil man sowas *nicht mit KeyListenern* macht. Schreib stattdessen einen *Behavior* und verwende ein WakeupOnAWTEvent.

Das wollte ich erstmal loswerden, ein kurzer Beispielcode folgt gleich noch


----------



## Developer_X (3. Mrz 2009)

is ja ma gut ok


----------



## Illuvatar (3. Mrz 2009)

So, ein bisschen Code. Der Code hat noch ein Problem, mehr dazu unten.

[HIGHLIGHT="Java"]import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;

public class KeyMovement extends JFrame
{
  public KeyMovement()
  {
    super ("Beispiel");
    Canvas3D canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
    SimpleUniverse universe = new SimpleUniverse(canvas);

    BranchGroup scene = new BranchGroup();
    TransformGroup movingGroup = new TransformGroup();
    movingGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
    movingGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    movingGroup.addChild(new com.sun.j3d.utils.geometry.ColorCube(0.5f));
    scene.addChild(movingGroup);
    CubeMover behavior = new CubeMover(movingGroup);
    behavior.setSchedulingBounds(new BoundingSphere());
    behavior.setEnable(true);
    scene.addChild(behavior);
    scene.compile();

    universe.addBranchGraph(scene);
    universe.getViewingPlatform().setNominalViewingTransform();

    add(canvas);
    setSize(800, 600);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
  }

  public static void main(String[] args) {
    new KeyMovement().setVisible(true);
  }
}

class CubeMover extends Behavior
{
  private TransformGroup affectedTransform;
  private WakeupOnAWTEvent condition;
  public CubeMover(TransformGroup affectedTransform)
  {
    this.affectedTransform = affectedTransform;
    this.condition = new WakeupOnAWTEvent(AWTEvent.KEY_EVENT_MASK);
  }

  @Override
  public void initialize()
  {
    wakeupOn(condition);
  }

  @Override
  public void processStimulus(Enumeration criteria)
  {
    KeyEvent event = (KeyEvent)condition.getAWTEvent()[0];

    Transform3D transform = new Transform3D();
    affectedTransform.getTransform(transform);
    Vector3f translation = new Vector3f();
    transform.get(translation);

    if (event.getKeyCode() == KeyEvent.VK_LEFT) {
      translation.add(new Vector3f(-0.1f, 0, 0));
      transform.set(translation);
    } else if (event.getKeyCode() == KeyEvent.VK_RIGHT) {
      translation.add(new Vector3f(0.1f, 0, 0));
      transform.set(translation);
    } else if (event.getKeyCode() == KeyEvent.VK_UP) {
      translation.add(new Vector3f(0, 0, -0.1f));
      transform.set(translation);
    } else if (event.getKeyCode() == KeyEvent.VK_DOWN) {
      translation.add(new Vector3f(0, 0, 0.1f));
      transform.set(translation);
    }
    affectedTransform.setTransform(transform);

    wakeupOn(condition);
  }
}[/HIGHLIGHT]

Das Problem: Der Behavior wacht noch bei jedem beliebigen KeyEvent auf, d.h. bei pressed, typed und released. Das ganze funktioniert nur, weil solange eine Taste gedrückt ist, ständig keyPressed-Events gesendet werden - allerdings in unregelmäßigen Abständen.
Richtig wäre: 2 Behaviors. Der erste registriert nur keyPressed und keyReleased-Events - und aktiviert/deaktiviert den anderen Behavior dann entsprechend. Der andere Behavior wird dann einfach alle 50 oder so Millisekunden ausgeführt (siehe hier) und ändert die Position.
Das mit 2 Behaviors ist noch bisschen unschön - man könnte es auch in einen schreiben. Dafür bräuchte man ein WakeupOr und muss die "Enumeration criteria" auswerten.


----------



## Tessarozza (3. Mrz 2009)

Ja, ich habe jetzt 

[HIGHLIGHT="Java"]public class PingPong3D extends JFrame implements Keylistener
{
....
public void keypressed(arg0){}
public void keyreleased(arg0){}
public void keytyped(arg0){}
.....
}[/HIGHLIGHT]

implementiert....

aber wie binde ich jetzt meine Spielbalken ein????


----------



## Tessarozza (3. Mrz 2009)

Ok, gut.... die Idee gefällt mir... Illuvatar!!!!


----------



## Illuvatar (3. Mrz 2009)

Developer_X hat gesagt.:


> is ja ma gut ok



Sorry, kam vielleicht etwas zu hart rüber. Der KeyListener ist ja grundsätzlich schonmal ne gute Idee und wird vielleicht auch funktionieren - allerdings kann es (und das ist mir auch schon passiert deswegen hacke ich da immer drauf rum ) wenn man den J3D-Thread so umgeht, zu schwer behebbaren Bugs führen.


----------



## Tessarozza (3. Mrz 2009)

Hallo Leute, ich habe den Code von Illuvatar implementiert und angepasst an meinen Code aber es läuft leider immer noch nicht, die Spielbalken lassen sich immer noch nicht bewegen!!! :-(

Hier mein Code: (Wo ist mein Fehler???):

[HIGHLIGHT="Java"]import java.awt.AWTEvent;
import java.awt.Button;
import java.awt.Panel;
import java.awt.event.*;
import java.util.Enumeration;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.swing.JFrame;
import javax.swing.Timer;


public class PingPong3D extends JFrame{

		public Canvas3D Spiel3D; 
		BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE);
		//Variabeln die für die Positionsinterpolation benötigt werden!
		private final float maxLeftRight = 0.95f;
		private final long todotime = 4000;
		private int startingTime = 3000;
		private Button start = new Button("Spiel starten");


		public PingPong3D(){
		//Mechanismus zum Schliessen des Fensters und beenden des Programms
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Spiel3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
		SimpleUniverse simpleUniverse = new SimpleUniverse(Spiel3D);
		simpleUniverse.getViewingPlatform().setNominalViewingTransform();

		//Die Szene wird in dieser Methode erzeugt
		createSceneGraph(simpleUniverse);

		Panel panel = new Panel();
		panel.add(start);
		add("North", panel);
		//Hinzufügen von Licht
		addLight(simpleUniverse);
		setTitle("PingPong3D");
		setSize(800, 300);
		getContentPane().add("Center", Spiel3D);
		//setVisible(true);

	  }


	  public void createSceneGraph(SimpleUniverse simpleUniverse){


		//Erzeugen eines weissen Hintergrundes
		  Background bg = new Background(new Color3f(1.0f,1.0f,1.0f));
		  BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),1000.0);
		  bg.setApplicationBounds(bounds);

		  //Zusammenstellung der Szene aus (Hintergrundfarbe, Ball, Balken1, Balken2, Musik)
		  BranchGroup theScene = new BranchGroup();
		  theScene.addChild(this.initBall());
		  theScene.addChild(this.initBalken1());
		  theScene.addChild(this.initBalken2());
		  theScene.addChild(bg);
		  theScene.compile();
		  simpleUniverse.addBranchGraph(theScene); 

	  }

	  public void addLight(SimpleUniverse simpleUniverse){

		  //Einfügen von zwei Lichtquellen
		  BranchGroup bgLight = new BranchGroup();
		  BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
		  Color3f lightColour1 = new Color3f(1.0f,1.0f,1.0f);
		  Vector3f lightDir1  = new Vector3f(-1.0f,0.0f,-0.5f);
		  DirectionalLight light1 = new DirectionalLight(lightColour1, lightDir1);
		  light1.setInfluencingBounds(bounds);
		  bgLight.addChild(light1);
		  Vector3f lightDir2  = new Vector3f(1.0f,0.0f,0.5f);
		  DirectionalLight light2 = new DirectionalLight(lightColour1, lightDir2);
		  light2.setInfluencingBounds(bounds);
		  bgLight.addChild(light2);
		  /*//Einfügen von Umgebungslicht
		  Color3f lightColour = new Color3f(0.2f, 2.5f, 4.0f);
		  AmbientLight ambLight = new AmbientLight(lightColour);
		  ambLight.setInfluencingBounds(bounds);
		  bgLight.addChild(ambLight);*/

		  simpleUniverse.addBranchGraph(bgLight);
	  }

	  public TransformGroup initBalken1(){

			//Ein rechter Balken, der in der Szene erscheinen soll inklusive Transformationsgruppe

			 //Die Farben fuer die Appearance
			 Color3f ambientColourFBalken1 = new Color3f(0.2f,0.2f,0.2f);
			 Color3f emissiveColourFBalken1 = new Color3f(0.0f,0.0f,0.0f);
			 Color3f diffuseColourFBalken1 = new Color3f(0.6f,0.6f,0.6f);
		     Color3f specularColourFBalken1 = new Color3f(0.5f,0.5f,0.5f);
		     float shininessFBalken1 = 128.0f;


			 //Die Appearance fuer den Balken1
		     Appearance balken1App = new Appearance();
		     balken1App.setMaterial(new Material(ambientColourFBalken1,emissiveColourFBalken1,
				                          diffuseColourFBalken1,specularColourFBalken1,shininessFBalken1));

		     //Der Balken1 mit Größenangaben und balken1App = Aussehen
			 Box balken1 = new Box(0.006f,0.06f,0.006f,balken1App);

			 //Die Transformationsgruppe des Wuerfels mit Math.PI/x ist es möglich
			 //Balken zu drehen und zu wenden!
		     Transform3D tfFBalken1 = new Transform3D();
		     tfFBalken1.rotY(Math.PI/1);
			 Transform3D rotationX = new Transform3D();
		     rotationX.rotX(Math.PI/1);
			 tfFBalken1.mul(rotationX);
			 TransformGroup tgFBalken1 = new TransformGroup(tfFBalken1);
			 tgFBalken1.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
			 tgFBalken1.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			 BalkenMover1 behavior1 = new BalkenMover1(tgFBalken1);
			 Transform3D seatAxis = new Transform3D();
			 seatAxis.rotX(Math.PI/2);
			 Alpha seatAlpha = new Alpha(1,//unendliche male
					 Alpha.INCREASING_ENABLE, 0, startingTime,
			         todotime,//time for rotation
			         0,0,0,0,0);//der rest
			 PositionInterpolator movSeat = new PositionInterpolator(
			      seatAlpha, tgFBalken1, seatAxis, 0.0f, maxLeftRight);
			    movSeat.setSchedulingBounds(bounds);



			tgFBalken1.addChild(behavior1);
			tgFBalken1.addChild(movSeat);
			tgFBalken1.addChild(balken1);
			return tgFBalken1;

		  }

	  public TransformGroup initBalken2(){

			//Ein linker Balken, der in der Szene erscheinen soll inklusive Transformationsgruppe

			 //Die Farben fuer die Appearance
			 Color3f ambientColourFBalken2 = new Color3f(0.2f,0.2f,0.2f);
			 Color3f emissiveColourFBalken2 = new Color3f(0.0f,0.0f,0.0f);
			 Color3f diffuseColourFBalken2 = new Color3f(0.6f,0.6f,0.6f);
		     Color3f specularColourFBalken2 = new Color3f(0.5f,0.5f,0.5f);
		     float shininessFBalken2 = 128.0f;


			 //Die Appearance fuer den Balken1
		     Appearance balken2App = new Appearance();
		     balken2App.setMaterial(new Material(ambientColourFBalken2,emissiveColourFBalken2,
				                          diffuseColourFBalken2,specularColourFBalken2,shininessFBalken2));

		     //Der Wuerfel
			 Box balken2 = new Box(0.006f,0.06f,0.006f,balken2App);

			 //Die Transformationsgruppe des Wuerfels mit Math.PI/x ist es möglich
			 //Balken zu drehen und zu wenden!

		     Transform3D tfFBalken2 = new Transform3D();
		     tfFBalken2.rotY(Math.PI/1);
			 Transform3D rotationX = new Transform3D();
		     rotationX.rotX(Math.PI/1);
			 tfFBalken2.mul(rotationX);
			 TransformGroup tgFBalken2 = new TransformGroup(tfFBalken2);
			 tgFBalken2.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
			 tgFBalken2.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			 // Behavior für Balken 2
			 BalkenMover2 behavior2 = new BalkenMover2(tgFBalken2);
			 behavior2.setSchedulingBounds(new BoundingSphere());
			 behavior2.setEnable(true);

			 Transform3D seatAxis = new Transform3D();
			 seatAxis.rotY(2*Math.PI/2);
			 Alpha seatAlpha = new Alpha(1,//unendliche male
					 Alpha.INCREASING_ENABLE, 0, startingTime,
			         todotime,//time for rotation
			         0,0,0,0,0);//der rest
			 PositionInterpolator movSeat = new PositionInterpolator(
			      seatAlpha, tgFBalken2, seatAxis, 0.0f, maxLeftRight);
			    movSeat.setSchedulingBounds(bounds);

			 tgFBalken2.addChild(behavior2);
			 tgFBalken2.addChild(movSeat);
			 tgFBalken2.addChild(balken2);
		     return tgFBalken2;

		  }
	  public TransformGroup initBall(){

		  //Unser Ball, der in der Szene erscheinen soll inklusive Transformationsgruppe
		  //und Rotation.

		  Color3f ambientColourBSphere = new Color3f(0.2f,0.2f,0.2f);
		  Color3f emissiveColourBSphere = new Color3f(0.0f,0.0f,0.0f);
		  Color3f diffuseColourBSphere = new Color3f(0.6f,0.6f,0.6f);
		  Color3f specularColourBSphere = new Color3f(0.5f,0.5f,0.5f);
		  float shininessBSphere = 128.0f;

	    //Die Appearance fuer die Kugel
		  Appearance bSphereApp = new Appearance();
		  bSphereApp.setMaterial(new Material(ambientColourBSphere,emissiveColourBSphere,
	                          diffuseColourBSphere,specularColourBSphere,shininessBSphere));

		//Der Ball ohne Tesselierung
		  //Sphere bSphere = new Sphere(0.1f,bSphereApp);

		// Ball mit Tesselierung
		  PolygonAttributes polygBall = new PolygonAttributes();
		  polygBall.setPolygonMode(PolygonAttributes.POLYGON_LINE);
		  bSphereApp.setPolygonAttributes(polygBall);
		  Sphere bSphere = new Sphere(0.015f, Sphere.GENERATE_NORMALS, 500, bSphereApp);

	    //Die Transformationsgruppe des Balls

		  Transform3D tfBSphere = new Transform3D();
		  tfBSphere.setTranslation(new Vector3f(1.0f,1.0f,-1.0f));
		  TransformGroup tgBSphere = new TransformGroup();
		  tgBSphere.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

	    //Ball rotieren lassen

		  Alpha rotationAlpha = new Alpha(-1, 15000);
		  RotationInterpolator rotator = 
			  new RotationInterpolator(rotationAlpha, tgBSphere);
		  rotator.setSchedulingBounds(bounds);
		  tgBSphere.addChild(rotator);
		  tgBSphere.addChild(bSphere);

		  return tgBSphere;

	  }

	  public class BalkenMover1 extends Behavior{

		  private TransformGroup affectedTransform;
		  private WakeupOnAWTEvent condition;
		  public BalkenMover1(TransformGroup affectedTransform){
			  this.affectedTransform = affectedTransform;
			  this.condition = new WakeupOnAWTEvent(AWTEvent.KEY_EVENT_MASK);
		  }

		  //Überschreiben
		  public void initialize()
	      {
	          wakeupOn(condition);
	      }

		  //Überschreiben
		  public void processStimulus(Enumeration criteria)
		  {
			  KeyEvent event = (KeyEvent)condition.getAWTEvent()[0];
			  Transform3D transform = new Transform3D();
	          affectedTransform.getTransform(transform);
	          Vector3f translation = new Vector3f();
	          transform.get(translation);

	          if (event.getKeyCode() == KeyEvent.VK_UP)
	          {
	            translation.add(new Vector3f(0, 0.1f, 0));
	            transform.set(translation);
	          } 
	          else if (event.getKeyCode() == KeyEvent.VK_DOWN) 
	          {
	            translation.add(new Vector3f(0, -0.1f, 0));
	            transform.set(translation);
	          }

	          affectedTransform.setTransform(transform);
	          wakeupOn(condition);

	        }
	  }

	  public class BalkenMover2 extends Behavior{
		  private TransformGroup affectedTransform;
		  private WakeupOnAWTEvent condition;
		  public BalkenMover2(TransformGroup affectedTransform){
			  this.affectedTransform = affectedTransform;
			  this.condition = new WakeupOnAWTEvent(AWTEvent.KEY_EVENT_MASK);
		  }

		  //Überschreiben
		  public void initialize()
	      {
	          wakeupOn(condition);
	      }

		  //Überschreiben
		  public void processStimulus(Enumeration criteria)
		  {
			  KeyEvent event = (KeyEvent)condition.getAWTEvent()[0];
			  Transform3D transform = new Transform3D();
	          affectedTransform.getTransform(transform);
	          Vector3f translation = new Vector3f();
	          transform.get(translation);

	          if (event.getKeyCode() == 'w')
	          {
	            translation.add(new Vector3f(0, 0.1f, 0));
	            transform.set(translation);
	          } 
	          else if (event.getKeyCode() == 's') 
	          {
	            translation.add(new Vector3f(0, -0.1f, 0));
	            transform.set(translation);
	          }

	          affectedTransform.setTransform(transform);
	          wakeupOn(condition);

	        }
	  }

	  public static void main(String[] args)  {

		  new PingPong3D().setVisible(true);

	  }

}[/HIGHLIGHT]



Vielen Dank an alle die mich unterstützen!!! tessa


----------



## Developer_X (4. Mrz 2009)

also hör mal zu ich würde sagen, du 
hast ja dieses keylistener jetzt,
so du machst jetzt drei private floats x,y,z.
so, dann machst du folgendes:

```
public class PingPong3D extends JFrame  implements Keylistener
{
//... Ich poste nur das wichtige
//...Bitte vergiss nicht die balken so zu translatieren, dass der vector3f x,y,z enthält ok?
private float x = 0;
private float y = 0;
private float z = 0;
public void keyPressed(KeyEvent arg0)
{
if(arg0.getKeyCode()==KeyEvent.VK_UP) 
{x = x +0.1f;}
}
public void keyReleased(KeyEvent arg0){}
public void keyTyped(KeyEvent arg0){}
}
```


----------



## Illuvatar (4. Mrz 2009)

Tessarozza hat gesagt.:


> Wo ist mein Fehler???



Bei dem ersten Behavior hast du die schedulingBounds vergessen.
Bei dem zweiten Behavior solltest du die keyCodes nicht mit 'w' und 's' sondern mit KeyEvent.VK_W und KeyEvent.VK_S vergleichen. Die int-Konstante in VK_W ist nicht die gleiche wie der Integer-Wert des chars 'w'.


----------



## Tessarozza (4. Mrz 2009)

Ja, ok! Beides führte aber leider immer noch nicht zum Erfolg!!!
 jetzt bin ich ratlos

kann es sein, dass an der PositonInterpolation liegt, die ich für den Effekt der dynamischen Balkenpositionierung benutzte????


----------



## Tessarozza (4. Mrz 2009)

Neuer Code: 


```
import java.awt.AWTEvent;
import java.awt.Button;
import java.awt.Panel;
import java.awt.event.*;
import java.util.Enumeration;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.swing.JFrame;
import javax.swing.Timer;


public class PingPong3D extends JFrame{
	
		public Canvas3D Spiel3D; 
		BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE);
		//Variabeln die für die Positionsinterpolation benötigt werden!
		private final float maxLeftRight = 0.95f;
		private final long todotime = 4000;
		private int startingTime = 3000;
		private Button start = new Button("Spiel starten");

		//Variablen für den KeyListener 
		private float x = 0;
		private float y = 0;
		private float z = 0;
		
		public PingPong3D(){
		//Mechanismus zum Schliessen des Fensters und beenden des Programms
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Spiel3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
		SimpleUniverse simpleUniverse = new SimpleUniverse(Spiel3D);
		simpleUniverse.getViewingPlatform().setNominalViewingTransform();
		
		//Die Szene wird in dieser Methode erzeugt
		createSceneGraph(simpleUniverse);
		
		Panel panel = new Panel();
		panel.add(start);
		add("North", panel);
		//Hinzufügen von Licht
		addLight(simpleUniverse);
		setTitle("PingPong3D");
		setSize(800, 300);
		getContentPane().add("Center", Spiel3D);
		setVisible(true);
		
	  }
	  
        
	  public void createSceneGraph(SimpleUniverse simpleUniverse){
	    
		
		//Erzeugen eines weissen Hintergrundes
		  Background bg = new Background(new Color3f(1.0f,1.0f,1.0f));
		  BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),1000.0);
		  bg.setApplicationBounds(bounds);

		  //Zusammenstellung der Szene aus (Hintergrundfarbe, Ball, Balken1, Balken2, Musik)
		  BranchGroup theScene = new BranchGroup();
		  theScene.addChild(this.initBall());
		  theScene.addChild(this.initBalken1());
		  theScene.addChild(this.initBalken2());
		  theScene.addChild(bg);
		  theScene.compile();
		  simpleUniverse.addBranchGraph(theScene); 
	  
	  }
	 
	  public void addLight(SimpleUniverse simpleUniverse){
		  
		  //Einfügen von zwei Lichtquellen
		  BranchGroup bgLight = new BranchGroup();
		  BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
		  Color3f lightColour1 = new Color3f(1.0f,1.0f,1.0f);
		  Vector3f lightDir1  = new Vector3f(-1.0f,0.0f,-0.5f);
		  DirectionalLight light1 = new DirectionalLight(lightColour1, lightDir1);
		  light1.setInfluencingBounds(bounds);
		  bgLight.addChild(light1);
		  Vector3f lightDir2  = new Vector3f(1.0f,0.0f,0.5f);
		  DirectionalLight light2 = new DirectionalLight(lightColour1, lightDir2);
		  light2.setInfluencingBounds(bounds);
		  bgLight.addChild(light2);
		  /*//Einfügen von Umgebungslicht
		  Color3f lightColour = new Color3f(0.2f, 2.5f, 4.0f);
		  AmbientLight ambLight = new AmbientLight(lightColour);
		  ambLight.setInfluencingBounds(bounds);
		  bgLight.addChild(ambLight);*/
		  
		  simpleUniverse.addBranchGraph(bgLight);
	  }
	  
	  public TransformGroup initBalken1(){
		  
			//Ein rechter Balken, der in der Szene erscheinen soll inklusive Transformationsgruppe

			 //Die Farben fuer die Appearance
			 Color3f ambientColourFBalken1 = new Color3f(0.2f,0.2f,0.2f);
			 Color3f emissiveColourFBalken1 = new Color3f(0.0f,0.0f,0.0f);
			 Color3f diffuseColourFBalken1 = new Color3f(0.6f,0.6f,0.6f);
		     Color3f specularColourFBalken1 = new Color3f(0.5f,0.5f,0.5f);
		     float shininessFBalken1 = 128.0f;


			 //Die Appearance fuer den Balken1
		     Appearance balken1App = new Appearance();
		     balken1App.setMaterial(new Material(ambientColourFBalken1,emissiveColourFBalken1,
				                          diffuseColourFBalken1,specularColourFBalken1,shininessFBalken1));

		     //Der Balken1 mit Größenangaben und balken1App = Aussehen
			 Box balken1 = new Box(0.006f,0.06f,0.006f,balken1App);

			 //Die Transformationsgruppe des Wuerfels mit Math.PI/x ist es möglich
			 //Balken zu drehen und zu wenden!
		     Transform3D tfFBalken1 = new Transform3D();
		     tfFBalken1.setTranslation(new Vector3f(x, y, z));
		     tfFBalken1.rotY(Math.PI/1);
		     Transform3D rotationX = new Transform3D();
		     rotationX.rotX(Math.PI/1);
			 tfFBalken1.mul(rotationX);
			 TransformGroup tgFBalken1 = new TransformGroup(tfFBalken1);
			 /*Transform3D tfBSphere = new Transform3D();
			 tfBSphere.setTranslation(new Vector3f(1.0f,1.0f,-1.0f));
			 TransformGroup tgBSphere = new TransformGroup();*/
			 tgFBalken1.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
			 tgFBalken1.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			 BalkenMover1 behavior1 = new BalkenMover1(tgFBalken1);
			 behavior1.setSchedulingBounds(new BoundingSphere());
			 behavior1.setEnable(true);
			 Transform3D seatAxis = new Transform3D();
			 seatAxis.rotX(Math.PI/2);
			 Alpha seatAlpha = new Alpha(1,//unendliche male
					 Alpha.INCREASING_ENABLE, 0, startingTime,
			         todotime,//time for rotation
			         0,0,0,0,0);//der rest
			 PositionInterpolator movSeat = new PositionInterpolator(
			      seatAlpha, tgFBalken1, seatAxis, 0.0f, maxLeftRight);
			    movSeat.setSchedulingBounds(bounds);
			 
			    
		
			tgFBalken1.addChild(behavior1);
			tgFBalken1.addChild(movSeat);
			tgFBalken1.addChild(balken1);
			return tgFBalken1;
			 
		  }
	  
	  public TransformGroup initBalken2(){
		  
			//Ein linker Balken, der in der Szene erscheinen soll inklusive Transformationsgruppe

			 //Die Farben fuer die Appearance
			 Color3f ambientColourFBalken2 = new Color3f(0.2f,0.2f,0.2f);
			 Color3f emissiveColourFBalken2 = new Color3f(0.0f,0.0f,0.0f);
			 Color3f diffuseColourFBalken2 = new Color3f(0.6f,0.6f,0.6f);
		     Color3f specularColourFBalken2 = new Color3f(0.5f,0.5f,0.5f);
		     float shininessFBalken2 = 128.0f;


			 //Die Appearance fuer den Balken1
		     Appearance balken2App = new Appearance();
		     balken2App.setMaterial(new Material(ambientColourFBalken2,emissiveColourFBalken2,
				                          diffuseColourFBalken2,specularColourFBalken2,shininessFBalken2));

		     //Der Wuerfel
			 Box balken2 = new Box(0.006f,0.06f,0.006f,balken2App);

			 //Die Transformationsgruppe des Wuerfels mit Math.PI/x ist es möglich
			 //Balken zu drehen und zu wenden!
			 
		     Transform3D tfFBalken2 = new Transform3D();
		     tfFBalken2.setTranslation(new Vector3f(x, y, z));
		     tfFBalken2.rotY(Math.PI/1);
			 Transform3D rotationX = new Transform3D();
		     rotationX.rotX(Math.PI/1);
			 tfFBalken2.mul(rotationX);
			 TransformGroup tgFBalken2 = new TransformGroup(tfFBalken2);
			 /*Transform3D tfBSphere = new Transform3D();
			 tfBSphere.setTranslation(new Vector3f(1.0f,1.0f,-1.0f));
			 TransformGroup tgBSphere = new TransformGroup();*/
			 tgFBalken2.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
			 tgFBalken2.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			 // Behavior für Balken 2
			 BalkenMover2 behavior2 = new BalkenMover2(tgFBalken2);
			 behavior2.setSchedulingBounds(new BoundingSphere());
			 behavior2.setEnable(true);
			 
			 Transform3D seatAxis = new Transform3D();
			 seatAxis.rotY(2*Math.PI/2);
			 Alpha seatAlpha = new Alpha(1,//unendliche male
					 Alpha.INCREASING_ENABLE, 0, startingTime,
			         todotime,//time for rotation
			         0,0,0,0,0);//der rest
			 PositionInterpolator movSeat = new PositionInterpolator(
			      seatAlpha, tgFBalken2, seatAxis, 0.0f, maxLeftRight);
			    movSeat.setSchedulingBounds(bounds);

			 tgFBalken2.addChild(behavior2);
			 tgFBalken2.addChild(movSeat);
			 tgFBalken2.addChild(balken2);
		     return tgFBalken2;
		     
		  }
	  public TransformGroup initBall(){
		  
		  //Unser Ball, der in der Szene erscheinen soll inklusive Transformationsgruppe
		  //und Rotation.
		  
		  Color3f ambientColourBSphere = new Color3f(0.2f,0.2f,0.2f);
		  Color3f emissiveColourBSphere = new Color3f(0.0f,0.0f,0.0f);
		  Color3f diffuseColourBSphere = new Color3f(0.6f,0.6f,0.6f);
		  Color3f specularColourBSphere = new Color3f(0.5f,0.5f,0.5f);
		  float shininessBSphere = 128.0f;

	    //Die Appearance fuer die Kugel
		  Appearance bSphereApp = new Appearance();
		  bSphereApp.setMaterial(new Material(ambientColourBSphere,emissiveColourBSphere,
	                          diffuseColourBSphere,specularColourBSphere,shininessBSphere));
		
		//Der Ball ohne Tesselierung
		  //Sphere bSphere = new Sphere(0.1f,bSphereApp);
	    
		// Ball mit Tesselierung
		  PolygonAttributes polygBall = new PolygonAttributes();
		  polygBall.setPolygonMode(PolygonAttributes.POLYGON_LINE);
		  bSphereApp.setPolygonAttributes(polygBall);
		  Sphere bSphere = new Sphere(0.015f, Sphere.GENERATE_NORMALS, 500, bSphereApp);
		  
	    //Die Transformationsgruppe des Balls
	    
		  Transform3D tfBSphere = new Transform3D();
		  tfBSphere.setTranslation(new Vector3f(1.0f,1.0f,-1.0f));
		  TransformGroup tgBSphere = new TransformGroup();
		  tgBSphere.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
	    
	    //Ball rotieren lassen
		  
		  Alpha rotationAlpha = new Alpha(-1, 15000);
		  RotationInterpolator rotator = 
			  new RotationInterpolator(rotationAlpha, tgBSphere);
		  rotator.setSchedulingBounds(bounds);
		  tgBSphere.addChild(rotator);
		  tgBSphere.addChild(bSphere);
		
		  return tgBSphere;
		  
	  }
	  
	  public class BalkenMover1 extends Behavior{
		  
		  private TransformGroup affectedTransform;
		  private WakeupOnAWTEvent condition;
		  public BalkenMover1(TransformGroup affectedTransform){
			  this.affectedTransform = affectedTransform;
			  this.condition = new WakeupOnAWTEvent(AWTEvent.KEY_EVENT_MASK);
		  }
		  
		  //Überschreiben
		  public void initialize()
	      {
	          wakeupOn(condition);
	      }
	  
		  //Überschreiben
		  public void processStimulus(Enumeration criteria)
		  {
			  KeyEvent event = (KeyEvent)condition.getAWTEvent()[0];
			  Transform3D transform = new Transform3D();
	          affectedTransform.getTransform(transform);
	          Vector3f translation = new Vector3f(x, y, z);
	          transform.get(translation);
	  
	          /*
	           * if(arg0.getKeyCode()==KeyEvent.VK_UP) 
				{x = x +0.1f;}

	           */
	          if (event.getKeyCode() == KeyEvent.VK_UP)
	          {
	            translation.add(new Vector3f(0, 0.1f, 0));
	            transform.set(translation);
	          } 
	          else if (event.getKeyCode() == KeyEvent.VK_DOWN) 
	          {
	            translation.add(new Vector3f(0, -0.1f, 0));
	            transform.set(translation);
	          }
	  
	          affectedTransform.setTransform(transform);
	          wakeupOn(condition);
	  
	        }
	  }

	  public class BalkenMover2 extends Behavior{
		  private TransformGroup affectedTransform;
		  private WakeupOnAWTEvent condition;
		  public BalkenMover2(TransformGroup affectedTransform){
			  this.affectedTransform = affectedTransform;
			  this.condition = new WakeupOnAWTEvent(AWTEvent.KEY_EVENT_MASK);
		  }
		  
		  //Überschreiben
		  public void initialize()
	      {
	          wakeupOn(condition);
	      }
	  
		  //Überschreiben
		  public void processStimulus(Enumeration criteria)
		  {
			  KeyEvent event = (KeyEvent)condition.getAWTEvent()[0];
			  Transform3D transform = new Transform3D();
	          affectedTransform.getTransform(transform);
	          Vector3f translation = new Vector3f(x, y, z);
	          transform.get(translation);
	  
	          if (event.getKeyCode() == KeyEvent.VK_W)
	          {
	            translation.add(new Vector3f(0, 0.1f, 0));
	            transform.set(translation);
	          } 
	          else if (event.getKeyCode() == KeyEvent.VK_S) 
	          {
	            translation.add(new Vector3f(0, -0.1f, 0));
	            transform.set(translation);
	          }
	  
	          affectedTransform.setTransform(transform);
	          wakeupOn(condition);
	  
	        }
	  }
	  
	  public static void main(String[] args)  {
	    
		  new PingPong3D();
	  
	  }
	  
}
```

So sieht es momentan aus??!!??


----------



## Illuvatar (4. Mrz 2009)

Der Code funktioniert bei mir (bis auf das was ich hier unten geschrieben habe).

Man muss allerdings erstmal einmal das Canvas3D anklicken, damit es den Fokus hat und die Eingaben mitkriegt.


----------



## Tessarozza (4. Mrz 2009)

Stimmt, cool sehr schön.... jetzt komm ich der Sache langsam näher!!! 

tessa


----------



## Tessarozza (4. Mrz 2009)

So ich hab mal ein paar Fragen:

1) Wie kann ich den Raum des PingPong-Spiels  im Canvas3D begrenzen, so, das meine Balken eine bestimmte Grenze nicht überschreiten?

2) Wie und was für möglichkeiten gibt es, eine Funktion an meinen Button anzubinden, so dass der Ball startet und wenn er von einem Balken getroffen wird zurück in den Raum fliegt?

tessa


----------



## 0x7F800000 (4. Mrz 2009)

Tessarozza hat gesagt.:


> 1) Wie kann ich den Raum des PingPong-Spiels  im Canvas3D begrenzen, so, das meine Balken eine bestimmte Grenze nicht überschreiten?
> 
> 2) Wie und was für möglichkeiten gibt es, eine Funktion an meinen Button anzubinden, so dass der Ball startet und wenn er von einem Balken getroffen wird zurück in den Raum fliegt?


Wenn ich mir das so durchlese, dann entsteht bei mir der eindruck, als ob du alles in einen topf schmeißen würdest... Grenzen und Kollisionserkennung sollten imho weder mit dem Canvas noch mit 3D noch mit Canvas3D irgendwas zu tun haben, das gehört doch alles zum Model...


----------



## Tessarozza (4. Mrz 2009)

Und wie könnte man das realisieren???


----------



## 0x7F800000 (4. Mrz 2009)

Naja... ich würd' mal vorschlagen, du fängst ganz einfach an, erstellst dir eine ganz neue Klasse für das Pong spiel, überlegst dir, was für eigenschften das spiel hat, etwa:

-breite
-länge
-ballgeschwindigkeit
-schlägergeschwindigkeit

was für zustände du abspeichern musst:

-positionen der beweglichen objekte
-punktezahl
-queue mit benutzerbefehlen, die du nacheinander abarbeitest 

dann sorgst du dafür, dass sich was bewegt, normalerweise bastelt man sich sowas wie eine "gameloop":

-move(long vergangeneMillis)
in dieser methode: 
        --verschiebst du alle objekte
        --arbeitest benutzereingaben ab
        --erkennst kollisionen, veränderst entsprechend die bewegungsrichtung
        --...

Dann kann man eigentlich noch nebenbei einen Thread laufen lassen, der die Anzeige aktualisiert, und einfach nur so oft es geht den spielzustand abfragt und alles neuzeichnet.

Dann sind die einzelnen dinger schön getrennt, die Ausgabe kann dann allgemein auf jede beliebige art und weise realisiert werden:
-auf einem oszilloskop
-mit pseudografik und ein paar rumspringenden buchstaben und strichen
-mit öden awt routinen
-etwas hübscher mit Graphics2D
-mit Java3D oder Jogl oder was auch immer, wenn man es ganz fett haben will.
Das ist aber grafischer schnickschnack, hat mit dem "Kern" des Spiels erstmal nichts zu tun, den grafischen kram kann man auch später draufkleben und beliebig ausschmücken, wenn alles an sich läuft. Wenn du deine Klasse für die Darstellung schon fertig hast: umso besser, bleibt dir eben nach der implementierung des kerns die nervige vorfreude auf das endergebnis erspart^^


----------



## Marco13 (4. Mrz 2009)

Als man noch keine ausgefeilten elektronischen Kameras und Computerunterstützung hatte, hat man in der Astronomie einen Trick verwendet, um neue, bewegte Himmelskörper, wie etwa Kometen, aufzuspüren: Man hat mit kurzem zeitlichen Abstand zwei Fotoaufnahmen von der selben Region des Himmels gemacht. Diese beiden Fotos hat man dann in ein Gerät gesteckt, in das man durch ein "Guckloch" reinsehen konnte, und bei dem man mit einem Hebel schnell zwischen den beiden Fotos hin- und herschalten konnte. Wenn einer der Himmelskörper sich bewegte, hat man diese Bewegung beim schnellen hin- und herschalten der Fotos als eine Art "Blinken" wahrgenommen. (Und es gibt nur wenige optische Reize, auf die Mensch so stark und mit so großer Aufmerksamkeit reagiert, wie auf Blinken, wie du ja selbst gemerkt hast  ).

Worauf ich eigentlich raus will: Ich habe auch bei deinem Code eine Technik angewendet, die daran erinnert, und die ich bedauerlicherweise in der letzten Zeit (beim Durchwühlen eines riesigen Berges schrecklichen, schrecklichen fremd-C++-Codes) häufig angewendet habe. Ich habe die Methoden "initBalken1" und "initBalken2" in jeweils eine Datei kopiert, und dann schnell zwischen den Ansichten auf beide Dateien hin- und hergeschaltet. Abgesehen von einem kleinen Unterschied bei der Rotation ist der einzige unterschied zwischen beiden Methoden: Der Name! (und die Namen der darin verwendeten Variablen). Es gibt beim Programmieren 3 wichtige Regeln: 1. Don't repeat yourself, 2. Don't repeat yourself, und 2. Don't repeat yourself. Das könnte man hübscher machen.


----------



## 0x7F800000 (4. Mrz 2009)

Marco13 hat gesagt.:


> Ich habe auch bei deinem Code eine Technik angewendet


Marco13, sorry, könntest du bitte kurz erläutern wie das einzuordnen ist, ich konnte in dem Thread nicht mal innerhalb von 0.89 Sekunden irgendwelchen code entdecken den du geschrieben hast, was meinst du?


----------



## Marco13 (4. Mrz 2009)

Ich hatte die Methoden "initBalken1" und "initBalken2" aus Tessarozza' post http://www.java-forum.org/grafik-und-spieleprogrammierung/79906-pingpong-3d.html#post493333 mal so verglichen. Und sie sind praktisch gleich. Ich wollte nur auch mal was potentiell http://www.java-forum.org/plauderecke/79834-wissenswertes.html posten


----------



## 0x7F800000 (4. Mrz 2009)

Aaaah! Sorry, habe deinen tollen Beitrag beim ersten durchlesen absolut nicht verstanden  Ich wäre auch nie auf die Idee gekommen, so etwas rein mechanisches mit Quellcode anzustellen^^ Diesen "Wissenswertes"-Thread finde ich irgendwie unheimlich  Verstehe nicht, wieso so ein "Erfahrener Benutzer" plötzlich hunderte seiner Beiträge löscht, und dann noch drei tage lang irgendwelchen kram in die plauderecke postet, ohne auf verwirrte Reaktionen zu reagieren


----------



## Tessarozza (4. Mrz 2009)

Danke für die Tips!!! very nice!!! ich werde es schlanker scheiben, wenn es funkioniert und komplett geht....
bin erstmal sehr dankbar für euer Know-How.... ich versuch mir java und java3D selber beizubringen .... semesterferien ...-> langeweile....

Hier mein aktueller Code: (Wer Ideen hat wie man es umschreiben kann???) 
Ich bin dabei....   Damit habe ich immer die meisten schwierigkeiten 


```
import java.awt.AWTEvent;
import java.awt.Button;
import java.awt.Panel;
import java.awt.event.*;
import java.util.Enumeration;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.swing.JFrame;

import java.awt.*;
//import javax.swing.*;

public class PingPong3D extends JFrame{
	
		public Canvas3D Spiel3D; 
		BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE);
		//Variabeln die für die Positionsinterpolation benötigt werden!
		private final float maxLeftRight = 0.95f;
		private final long todotime = 4000;
		private int startingTime = 3000;
		private Button start = new Button("Spiel starten");

		//Variablen für den KeyListener 
		private float x = 0;
		private float y = 0;
		private float z = 0;
		
		//Bewegungsvariablen
		int dx = 2; //Bewegungsänderung in x
		int dy = 2; //Bewegungsänderung in y
		
		public PingPong3D(){
		//Mechanismus zum Schliessen des Fensters und beenden des Programms
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Spiel3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
		SimpleUniverse simpleUniverse = new SimpleUniverse(Spiel3D);
		simpleUniverse.getViewingPlatform().setNominalViewingTransform();
		
		//Die Szene wird in dieser Methode erzeugt
		createSceneGraph(simpleUniverse);
		
		Panel panel = new Panel();
		panel.add(start);
		add("North", panel);
		//Hinzufügen von Licht
		addLight(simpleUniverse);
		setTitle("PingPong3D");
		setSize(800, 300);
		getContentPane().add("Center", Spiel3D);
		setVisible(true);
		
		//Thread t = new Thread(); //GameLoop in eingenem Thread
		//t.run();
	  }
		
	/*public class run{  
		
		public void run() {
			
			while(Spiel3D.isVisible()){  //???Thread so lange ausführen, wie Fenster sichtbar ist.
				
				moveBall();       //Ball bewegen
				checkCollision(); //Schläger-Ball-Kollision
				
				try {
					Thread.sleep(20);  //Päuschen
				} catch (InterruptedException e) {}
				
				repaint();  //Repaint
			}
			
		}
		
		private void checkCollision(){
			
			if(initBalken1().intersects(ball)){  //Standard-Methode von Rectangle intersetcts(Rectangle r)
				dx *= -1;                //dx negieren, damit Ball wegfliegt
				ball.x += dx;            //einmal bewegen, damit Kollisionsabfrage nicht nochmal greift
			}
			
		}
		
		private void moveBall(){
			
			//wenn linke Seite des Balls nicht mehr sichtbar. X-Bewegung ändern
			if(ball.x<0){
				dx = 2;
			}
			
			//das selbe in Grün für die rechte Seite
			if(ball.x+ball.width >getWidth()){
				dx = -2;
			}
			
			//Beide Bedingung für analog für Y
			if(ball.y<0){
				dy = 2;
			}
			
			if(ball.y+ball.height>getHeight()){
				dy = -2;
			}

			//simple Ballbewegung - unabhängig vom GameLoop
			ball.x += dx;
			ball.y += dy;

		}
	}*/
	  public void createSceneGraph(SimpleUniverse simpleUniverse){
	    
		
		//Erzeugen eines weissen Hintergrundes
		  Background bg = new Background(new Color3f(1.0f,1.0f,1.0f));
		  BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),1000.0);
		  bg.setApplicationBounds(bounds);

		  //Zusammenstellung der Szene aus (Hintergrundfarbe, Ball, Balken1, Balken2, Musik)
		  BranchGroup theScene = new BranchGroup();
		  theScene.addChild(this.ball());
		  theScene.addChild(this.balken1());
		  theScene.addChild(this.balken2());
		  theScene.addChild(bg);
		  theScene.compile();
		  simpleUniverse.addBranchGraph(theScene); 
	  
	  }
	 
	  public void addLight(SimpleUniverse simpleUniverse){
		  
		  //Einfügen von zwei Lichtquellen
		  BranchGroup bgLight = new BranchGroup();
		  BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
		  Color3f lightColour1 = new Color3f(1.0f,1.0f,1.0f);
		  Vector3f lightDir1  = new Vector3f(-1.0f,0.0f,-0.5f);
		  DirectionalLight light1 = new DirectionalLight(lightColour1, lightDir1);
		  light1.setInfluencingBounds(bounds);
		  bgLight.addChild(light1);
		  Vector3f lightDir2  = new Vector3f(1.0f,0.0f,0.5f);
		  DirectionalLight light2 = new DirectionalLight(lightColour1, lightDir2);
		  light2.setInfluencingBounds(bounds);
		  bgLight.addChild(light2);
		  /*//Einfügen von Umgebungslicht
		  Color3f lightColour = new Color3f(0.2f, 2.5f, 4.0f);
		  AmbientLight ambLight = new AmbientLight(lightColour);
		  ambLight.setInfluencingBounds(bounds);
		  bgLight.addChild(ambLight);*/
		  
		  simpleUniverse.addBranchGraph(bgLight);
	  }
	  public TransformGroup balken1(){
		  
		//Ein rechter Balken, der in der Szene erscheinen soll inklusive Transformationsgruppe

			 //Die Farben fuer die Appearance
			 Color3f ambientColourFBalken1 = new Color3f(0.2f,0.2f,0.2f);
			 Color3f emissiveColourFBalken1 = new Color3f(0.0f,0.0f,0.0f);
			 Color3f diffuseColourFBalken1 = new Color3f(0.6f,0.6f,0.6f);
		     Color3f specularColourFBalken1 = new Color3f(0.5f,0.5f,0.5f);
		     float shininessFBalken1 = 128.0f;


			 //Die Appearance fuer den Balken1
		     Appearance balkenApp = new Appearance();
		     
		     balkenApp.setMaterial(new Material(ambientColourFBalken1,emissiveColourFBalken1,
				                          diffuseColourFBalken1,specularColourFBalken1,shininessFBalken1));
		     
		  
		   //Der Balken1 mit Größenangaben und balken1App = Aussehen
			 Box balken1 = new Box(0.006f,0.06f,0.006f,balkenApp);
			 		  
		   //Die Transformationsgruppe des Wuerfels mit Math.PI/x ist es möglich
		   //Balken zu drehen und zu wenden!
			 Transform3D tfFBalken = new Transform3D();
			 tfFBalken.setTranslation(new Vector3f(x, y, z));
			 tfFBalken.rotY(Math.PI/1);
			 Transform3D rotationX = new Transform3D();
			 rotationX.rotX(Math.PI/1);
			 tfFBalken.mul(rotationX);
			 TransformGroup tgFBalken = new TransformGroup(tfFBalken);
			 tgFBalken.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
			 tgFBalken.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			 Move1 behavior1 = new Move1(tgFBalken);
			 behavior1.setSchedulingBounds(new BoundingSphere());
			 behavior1.setEnable(true);
			 
			 Transform3D seatAxis = new Transform3D();
			 seatAxis.rotX(Math.PI/2);
			 Alpha seatAlpha = new Alpha(1,//unendliche male
				 Alpha.INCREASING_ENABLE, 0, startingTime,
		         todotime,//time for rotation
		         0,0,0,0,0);//der rest
			 PositionInterpolator movSeat = new PositionInterpolator(
		      seatAlpha, tgFBalken, seatAxis, 0.0f, maxLeftRight);
			 movSeat.setSchedulingBounds(bounds);
			 
			 
			       
			 tgFBalken.addChild(behavior1);   
			 tgFBalken.addChild(movSeat);  
			 tgFBalken.addChild(balken1);
			 
			 return tgFBalken;
			 
	  }
	  public TransformGroup balken2(){
		  
			//Ein rechter Balken, der in der Szene erscheinen soll inklusive Transformationsgruppe

				 //Die Farben fuer die Appearance
				 Color3f ambientColourFBalken1 = new Color3f(0.2f,0.2f,0.2f);
				 Color3f emissiveColourFBalken1 = new Color3f(0.0f,0.0f,0.0f);
				 Color3f diffuseColourFBalken1 = new Color3f(0.6f,0.6f,0.6f);
			     Color3f specularColourFBalken1 = new Color3f(0.5f,0.5f,0.5f);
			     float shininessFBalken1 = 128.0f;


				 //Die Appearance fuer den Balken1
			     Appearance balkenApp = new Appearance();
			     
			     balkenApp.setMaterial(new Material(ambientColourFBalken1,emissiveColourFBalken1,
					                          diffuseColourFBalken1,specularColourFBalken1,shininessFBalken1));
			     
			  
			   //Balken2 mit Größenangaben und balkenApp = Aussehen
				 Box balken2 = new Box(0.006f, 0.06f, 0.006f, balkenApp);
			  
			   //Die Transformationsgruppe des Wuerfels mit Math.PI/x ist es möglich
			   //Balken zu drehen und zu wenden!
				 Transform3D tfFBalken = new Transform3D();
				 tfFBalken.setTranslation(new Vector3f(x, y, z));
				 tfFBalken.rotY(Math.PI/1);
				 Transform3D rotationX = new Transform3D();
				 rotationX.rotX(Math.PI/1);
				 tfFBalken.mul(rotationX);
				 TransformGroup tgFBalken = new TransformGroup(tfFBalken);
				 tgFBalken.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
				 tgFBalken.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
				 Move1 behavior1 = new Move1(tgFBalken);
				 behavior1.setSchedulingBounds(new BoundingSphere());
				 behavior1.setEnable(true);
				 Move2 behavior2 = new Move2(tgFBalken);
				 behavior2.setSchedulingBounds(new BoundingSphere());
				 behavior2.setEnable(true);
				 
				 Transform3D seatAxis = new Transform3D();
				 seatAxis.rotY(2*Math.PI/2);
				 Alpha seatAlpha = new Alpha(1,//unendliche male
						 Alpha.INCREASING_ENABLE, 0, startingTime,
				         todotime,//time for rotation
				         0,0,0,0,0);//der rest
				 PositionInterpolator movSeat = new PositionInterpolator(
				      seatAlpha, tgFBalken, seatAxis, 0.0f, maxLeftRight);
				    movSeat.setSchedulingBounds(bounds);
				 
				       
				    
				 tgFBalken.addChild(behavior2);
				 tgFBalken.addChild(movSeat);  
				 tgFBalken.addChild(balken2);
				 
				 return tgFBalken;
				 
		  }
		  
	 
	  public TransformGroup ball(){
		  
		  //Unser Ball, der in der Szene erscheinen soll inklusive Transformationsgruppe
		  //und Rotation.
		  
		  Color3f ambientColourBSphere = new Color3f(0.2f,0.2f,0.2f);
		  Color3f emissiveColourBSphere = new Color3f(0.0f,0.0f,0.0f);
		  Color3f diffuseColourBSphere = new Color3f(0.6f,0.6f,0.6f);
		  Color3f specularColourBSphere = new Color3f(0.5f,0.5f,0.5f);
		  float shininessBSphere = 128.0f;

	    //Die Appearance fuer die Kugel
		  Appearance bSphereApp = new Appearance();
		  bSphereApp.setMaterial(new Material(ambientColourBSphere,emissiveColourBSphere,
	                          diffuseColourBSphere,specularColourBSphere,shininessBSphere));
		
		//Der Ball ohne Tesselierung
		  //Sphere bSphere = new Sphere(0.1f,bSphereApp);
	    
		// Ball mit Tesselierung
		  PolygonAttributes polygBall = new PolygonAttributes();
		  polygBall.setPolygonMode(PolygonAttributes.POLYGON_LINE);
		  bSphereApp.setPolygonAttributes(polygBall);
		  Sphere bSphere = new Sphere(0.015f, Sphere.GENERATE_NORMALS, 500, bSphereApp);
		  
	    //Die Transformationsgruppe des Balls
	    
		  Transform3D tfBSphere = new Transform3D();
		  //tfBSphere.setTranslation(new Vector3f(1.0f,1.0f,-1.0f));
		  tfBSphere.setTranslation(new Vector3f(x , y, z));
		  TransformGroup tgBSphere = new TransformGroup();
		  tgBSphere.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
		  tgBSphere.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		// Bewegung des Balls im Raum
			/* run mover = new run(tgBSphere);
			 mover.setSchedulingBounds(new BoundingSphere());
			 mover.setEnable(true);*/
	    //Ball rotieren lassen
		  Alpha rotationAlpha = new Alpha(-1, 15000);
		  RotationInterpolator rotator = 
			  new RotationInterpolator(rotationAlpha, tgBSphere);
		  rotator.setSchedulingBounds(bounds);
		  
		  
		  tgBSphere.addChild(rotator);
		  tgBSphere.addChild(bSphere);
		
		  return tgBSphere;
		  
	  }
	  
	  public class Move1 extends Behavior{
		  
		  private TransformGroup affectedTransform;
		  private WakeupOnAWTEvent condition;
		  public Move1(TransformGroup affectedTransform){
			  this.affectedTransform = affectedTransform;
			  this.condition = new WakeupOnAWTEvent(AWTEvent.KEY_EVENT_MASK);
		  }
		  
		  //Überschreiben
		  public void initialize()
	      {
	          wakeupOn(condition);
	      }
	  
		  //Überschreiben
		  public void processStimulus(Enumeration criteria)
		  {
			  KeyEvent event = (KeyEvent)condition.getAWTEvent()[0];
			  Transform3D transform = new Transform3D();
	          affectedTransform.getTransform(transform);
	          Vector3f translation = new Vector3f(x, y, z);
	          transform.get(translation);
	
	          if (event.getKeyCode() == KeyEvent.VK_UP)
	          {
	            translation.add(new Vector3f(0, 0.03f, 0));
	            transform.set(translation);
	          } 
	          else if (event.getKeyCode() == KeyEvent.VK_DOWN) 
	          {
	            translation.add(new Vector3f(0, -0.03f, 0));
	            transform.set(translation);
	          }
	  
	          affectedTransform.setTransform(transform);
	          wakeupOn(condition);
	  
	        }
	  }

	  public class Move2 extends Behavior{
		  private TransformGroup affectedTransform;
		  private WakeupOnAWTEvent condition;
		  public Move2(TransformGroup affectedTransform){
			  this.affectedTransform = affectedTransform;
			  this.condition = new WakeupOnAWTEvent(AWTEvent.KEY_EVENT_MASK);
		  }
		  
		  //Überschreiben
		  public void initialize()
	      {
	          wakeupOn(condition);
	      }
	  
		  //Überschreiben
		  public void processStimulus(Enumeration criteria)
		  {
			  KeyEvent event = (KeyEvent)condition.getAWTEvent()[0];
			  Transform3D transform = new Transform3D();
	          affectedTransform.getTransform(transform);
	          Vector3f translation = new Vector3f(x, y, z);
	          transform.get(translation);
	  
	          if (event.getKeyCode() == KeyEvent.VK_W)
	          {
	            translation.add(new Vector3f(0, 0.03f, 0));
	            transform.set(translation);
	          } 
	          else if (event.getKeyCode() == KeyEvent.VK_S) 
	          {
	            translation.add(new Vector3f(0, -0.03f, 0));
	            transform.set(translation);
	          }
	  
	          affectedTransform.setTransform(transform);
	          wakeupOn(condition);
	  
	        }
	  }
	  
	
	  
	  public static void main(String[] args)  {
	    
		  new PingPong3D();
	  
	  }
	  
}
```

Ich versuche mich gerade mit der Funktionalität des Balls!!!


----------



## 0x7F800000 (5. Mrz 2009)

Also, wie gesagt, sowas wie "initBalken1" ist schon gruselig genug, aber indizierte Klassenbezeichner wie "BalkenMover2" ist echt extrem übertrieben...


----------



## Tessarozza (5. Mrz 2009)

Neuer Code neues Glück.... habs versucht schlanker zu schreiben und nicht so dicht aufzutragen mit den bezeichnungen!!!

Funktionen zu implementieren bleibt mir immer noch ein grauß!


----------



## 0x7F800000 (5. Mrz 2009)

Der neue eek!-smiley ist toll, nich?  voll 3D^^


----------



## Tessarozza (5. Mrz 2009)

Andrey... kannst du dir bitte mal meinen Code anschauen und mir ein wenig unter die arme greifen.... ich kann mich in den Spielcode so schlecht hineinversetzen!!??!!

tessa


----------



## 0x7F800000 (5. Mrz 2009)

Ich kann mich da nochmal wesentlich schlechter hineinversetzten, denn
1) ich hab den nicht geschrieben
2) ich hab hier kein java3D, und sehe auch keinen allzu tollen Grund es runterzuladen

Funktioniert denn daran irgendwas konkret nicht?
Wenn du es nur schöner schreiben willst, dann würde ich wirklich empfehlen, einfach einen leeren Zettel zu nehmen, die einzelnen Sachen wie Model/Visualisierung/Sonstige gui's sinnvoll zu unterteilen, damit sowas:

```
private Button start = new Button("Spiel starten");

		//Variablen für den KeyListener 
		private float x = 0;
		private float y = 0;
		private float z = 0;
		
		//Bewegungsvariablen
		int dx = 2; //Bewegungsänderung in x
		int dy = 2; //Bewegungsänderung in y
```
in der nächsten version nicht vorkommt, das ist einfach der totale Salat... Geschwindigkeit und Button in einen Topf zu schmeißen ist einfach pfui, egal was man damit macht.

Und wenn du die Erfahrungen aus der Ersten version benutzt hast, um die Anforderungen an das Programm genauer zu stellen, und alles nochmal überdacht hast, dann legst du das erste Programm zur Seite, und schreibst es einfach komplett neu. Nächstes mal aber sinnvoll aufgeteilt und in kleinen Häppchen, und vor allem DRY.

Sowas ist doch toll, nennt sich "Prototyping"...


----------

