Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Ich habe eine TransformGroup in der ein Model steckt. Nun würde ich gern, dass wenn ich einen Button drücken, dieses Model sich dreht. (obendrein noch um die z-Achse)
Dank einem einleuchtenden Tutorial hab ich ein klein wenig über RotationInterpolator in Erfahrung bringen können. Aber das reicht irgendwie nicht aus für das, was ich vorhabe.
Wie könnte ich einen RotationInterpolator auf Knopfdruck verwenden? (und wie geb ich ihm an WIE er zu rotieren hat? Im moment macht der das nur um die X-Achse ohne das ich ihm das gesagt hätte)
Mithilfe dieses Konstruktors kannst du die Achse angeben. Das Objekt dreht sich dann um die y-Achse des von "axisOfTransform" definierte Koordinatensystem.
Ich hab mir das wie bei so einer Google-Earth Karte vorgestellt.
Wenn ich auf den Button klicke, dreht er in einer sanften Animation die Darstellung um 90° nach links. Oder halt rechts, oder oben/unten... je nachdem was ich drücke.
So ungefähr zumindest.
Ich glaub ich muss mich erst mal genauer mit "Alpha" beshäftigen um davon einen Eindruck zu bekommen.
Hallo.
Schreibe dir doch eine eigene Animationsklasse. Und wie Marco schon erwähnt hat musst du doch einfach nur die Transform3D der TransformGroup neu setzen. Und um daraus eine Animation zu machen einfach eine Klasse die z.B von Thread erbt. Da kannst du dann wunderbar nach deinen Wünschen anpassen.
Sprich:
// x y z werden in einer Schleife erhöht oder anders rum
transform3D.setTranslation(new Vector3d(x, y, z));
transformGroup.setTransform(transform3D);
Ansonsten Java3D Api lesen was für Interpolatoren gibt.
ok ich habs jetzt einigermaßen hinbekommen.
Jetzt aber noch mal eine Frage in ähnlicher Richtung.
Ich hab den Button jetzt gedrückt, dann dreht sich das Ding hübsch um meine gestellten 90°.
ABER, wenn ich den Button jetzt noch mal drücke, rückt er den Stein erst in die alte Position und dreht dann seine 90°. Er macht also genau das gleiche.
Ich will aber das er von seiner jetzigen Position aus, weiter dreht. Wie kann ich das erreichen?
Ich dachte mir würde irgendwie diese LocalToVWorld weiterhelfen. Aber irgendwie versteh ich das nicht.
Ich versteh allgemein nicht was die ganzen void get-Methoden sollen die obendrein noch einen Parameter übergeben bekommen.
Alpha wäre auch nicht so falsch, aber so eine "einfache" Animation kann man auch per Hand machen (Alpha kann so hübsch schneller werden und am Ende abbremsen und so...). Poste am besten mal ein bißchen Code. Allgemein könntest du entweder den winkel irgendwo speichern und bei jedem Klick um 90° erhöhen, oder ... naja, getLocalToVWorld würde auch gehen, sollte man aber nicht brauchen.
Die getter mit Parameter schreiben im allgemeinen das Ergebnis in den Parameter, z.B.
getTransform(transform3D);
schreibt das Ergebnis (was man eigentlich als Rückgabe erwarten würde) in den Parameter. Wurde früher wohl in erster Linie gemacht, um Objekterzeugungen zu sparen.
private ActionListener aclRotNeg = new ActionListener() {
public void actionPerformed(ActionEvent e){
for (int i = 0; i <= 90; i++){
PiecesT3D.setRotation(new AxisAngle4f(0f,0f,1f, (float) Math.toRadians(90*index - i)));
try{
Thread.sleep(10);
} catch (InterruptedException exp){}
PiecesTG.setTransform(PiecesT3D);
}
if (index == 3) index = 0;
else index--;
}
};
Wie wir sehen ruf ich von einem Button diesen ActionListener auf. Dann wird das ganze Ding gedreht. Im Moment ist das also SEHR SEHR einfach gelöst.
Index ist dabei eine globale Variable um zu checken in welchem Quadranten ich bin. Sozusagen.
Als ich das mit Alpha probiert habe, hab ich das auch alles in den ActionListener gepackt. Das komische war, es ging nur einmal.
Aber so eine wahnsinnig tolle Animation brauch ich jetzt auch nicht.
Speicherst du denn irgendwo die aktuelle Position? sehe da nur index aber dieses erhöhst du nicht in deiner forschleife.
Als ich das mit Alpha probiert habe, hab ich das auch alles in den ActionListener gepackt. Das komische war, es ging nur einmal.
Aber so eine wahnsinnig tolle Animation brauch ich jetzt auch nicht.
Die Animation ging nur einmal oder wie meinst du das?
Wenn das der Fall ist schau dir mal die Konstruktoren von Alpha an, da kannst du wenn ich mich richtig erinner, angeben wie oft die Animation laufen soll.
Naja ein Kreis hat 360°. Also 4 mal 90°. In "index" wird also gespeichert, der wie vielte 90° Winkel erreicht wurde. 0,1,2 oder 3.
Mit "einmal" meinte ich nicht wie oft er gedreht hat.
Ich hab das "drehen" in ein ActionListener gepackt und den dann mit einem Button aufgerufen.
Wenn ich den Button gedrückt habe. Ist er fein rotiert. Hab ich den Button dann noch mal gedrückt, passierte nix... Aber das soll nich das Problem sein hier
Wie truesoul schon indirekt gezeigt hat sollte die Rotation auf jeden Fall von einem eigenen Thread gemacht werden (und nicht direkt mit einer for-Schleife in actionPerformed).
Abgesehen davon wäre eine von vielen möglichen Strukturen in Anlehnung an den ursprünglichen Code
Java:
class TheClass
{
private int currentAngleDeg = 0;
void somewhere()
{
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
doRotation(90);
}
});
}
private void doRotation(final int deltaDeg)
{
Thread t = new Thread(new Runnable()
{
public void run()
{
for (int i=0; i<deltaDeg; i++)
{
currentAngleDeg += 1;
setzeRotationSoWieVorher(currentAngleDeg);
}
}
});
t.start();
}
}
Von Feinheiten (wie z.B. dass der Button disabled sein sollte, während die Animation läuft) mal abgesehen...
Ich hab gelesen das ein Alpha Object quasi nachdem kompilieren startet.
Wie schreib ich mir jetzt also einen "Trigger" für Alpha der nicht von der Zeit abhängt, sondern von einer Aktion.
Zum Beispiel wird dank eines Observers immer eine update() Methode gestartet, wenn was passiert. Wie kann ich nun in dieser update() Methode das Alpha immer wieder neu triggern lassen?
Versteht ihr wo mein Problem liegt?
Ggf. kann man immer ein neues Alpha erstellen (mit passenden Zeiten), oder ganz auf das Alpha verzeichten, wenn es nur um einfache Animationen geht. Poste vielleicht mal mehr Code vom aktuellen Stand, idealerweise ein KSKB.
Also der ganze Code ist recht umfangreich und euch nur Ausschnitte zu zeigen würde wohl mehr Fragen aufwerfen als welche zu beantworten. Daher ist das recht schwer.
Also ich hab "damals" in ein ActionListener ein Alpha Objekt erstellt und halt ausgeführt. Was dazu führte, dass es einmal klappte. Bei abermaligen Klick auf den Button sprang das Alpha nicht mehr an, daher dacht ich würde es nicht klappen.
Ich schreib mal ein Stück Code und teste (mit Alpha), das kann ich euch dann schicken.
Bis später.
/**
* Update 3D-World.
* Create all pieces in universe and clip it to live group
*/
@Override
public void update(Observable observable, Object notification){
// enabled buttons
setEnabledComp(true);
PiecesTG = new TransformGroup( PiecesT3D );
// sets capabilities to transform and add transform group
PiecesTG.setCapability( TransformGroup.ALLOW_TRANSFORM_WRITE );
PiecesTG.setCapability( TransformGroup.ALLOW_TRANSFORM_READ );
PiecesTG.setCapability( TransformGroup.ALLOW_CHILDREN_EXTEND );
PiecesTG.setCapability( TransformGroup.ALLOW_CHILDREN_READ );
PiecesTG.setCapability( TransformGroup.ALLOW_CHILDREN_WRITE );
// clip all pieces to pieces transform group
createSceneGraph();
// sets transformation informations
PiecesTG.setTransform( PiecesT3D );
// remove pieces branch group
try{ RootBG.removeChild( piecesBG ); }
catch (Exception exp){}
if (notification instanceof IntroductionNotificationInterface)
{
int index = ((IntroductionNotificationInterface) notification).getPieceIndex();
Piece piece = board.getPiece(index);
PieceGraph3D pieceGraph = getGraph( piece );
PiecesTG.addChild( pieceGraph.introAnimation(5) );
}
// gimmick for action listeners
if (observable != null && notification != null){
// create new pieces branch group
piecesBG = new BranchGroup();
piecesBG.setCapability(BranchGroup.ALLOW_DETACH);
// clip pieces to branch group and compile
piecesBG.addChild( PiecesTG );
piecesBG.compile();
// clip pieces branch group to live group
RootBG.addChild( piecesBG );
// sets momently camera position
setViewingPosition(zoomSlider.getValue());
}
}//end update
/**
* Create all pieces and clip this pieces to pieces transform group.
*/
private void createSceneGraph(){
try{
// create list of 3D pieces
pieceGraphList = createPieces( board.getIntroducedPieces() );
// add all 3D pieces to group
for (int i = 0; i < pieceGraphList.size(); i++)
PiecesTG.addChild( pieceGraphList.get(i).transGroup );
} catch (NoSuchElementException exp){}
}
Mal abgesehen von meinem schlechten Englisch:
update: Diese Methode wird halt immer aufgerufen wenn was passiert.
Es gibt die Möglichkeit, dass ein Piece gelegt wird oder ein Piece bewegt wird. So viel zur Vorkenntnis.
CreateSceneGraph(): dient nun dazu, meine Objekte einer TransformGroup namens PiecesTG hinzuzufügen.
Wenn jetzt ein Piece gelegt wird, soll das von oben an seine Position fallen. Also such ich mir den Graphen zum Piece und rufe dazu die Methode introAnimation() auf. Die sieht wie folgt aus:
Hier erstelle ich nun ein Alpha-Object. (die 1s Wartezeit vor dem Start, rührt daher dass er noch mehr berechnet und man ansonsten die Animation gar nicht mitbekommen würde, weil sie längst vorbei wär bevor man überhaupt was sieht)
Dann ein Transform3D-Object von dem ich annahm, dass er die Art der Translation angibt.
Dann der PositionInterpolator mit den angegebenen Werten.
Dieser wird dann zurückgegeben.
Dann wird alles zu PiecesTG hinzugefügt, PiecesTG wiederum zu RootBG und RootBG dann zum Universum. Dann geht das alles.
Jetzt treten folgende Probleme auf.
1) Verständnisfrage... Wenn ich bei Alpha statt den beiden 1000, 1000 nur eines von beiden Wartezeiten auf 1000 setze, wartet Alpha überhaupt nicht, sondern legt sofort los. Warum denn das? oO
2) Die Translation findet überhaupt nicht entlang der Z-Achse statt wie ich wollte, sondern entlang der X-Achse (wieso auch immer, schließlich hab ich extra das Transform3D-Objekt erstellt)
3) Das Problem was ich letzte mal schon erwähnt habe. Sobald ich ein Piece "introduce" funktioniert erst mal alles "einwandfrei" (mal abgesehen von den beiden obigen Punkten) aber sobald ich das nächste Piece introduce, wird die Animation gar nicht gestartet, das Piece liegt zwar an richtiger Position, aber die Animation fehlt.
(das hab ich gemeint, als ich meinte, wenn ich den Button abermals drücke, funktioniert die Animation nicht mehr)
So... Ich hoffe ihr könnte helfen. Langsam wirds etwas eng mit der Zeit ~.~
Danke an alle die Helfen und drüber schauen
Ok. 2) konnte ich beheben. Ich hab gefunden dass man lieber einen PositionPathInterpolator verwenden soll, wenn es um die Z-Achse geht.
Das sieht bei mir jetzt so aus:
Warum ich bei Alpha immernoch beide "Warte-Werte" setzen muss, damit er auch wirklich wartet, versteh ich nicht.
Dafür geht "fällt" der Stein (das Piece) jetzt aber entlang der Z-Achse so wie er soll.
Das Problem, dass der nächste Stein der fallen soll, aber nicht fällt, bleibt weiterhin bestehen.
Warum reagiert die Animation nich, wenn er noch mal loslegen soll *grübel*
Also das einfügen mit den setStartTime()
Damit werden jetzt auch alle Pieces fein säuberlich einsortiert wie sie sollen. Sehr geil :applaus:
Was das KSKB angeht... ähh...
Das dürfte sich extrem schwierig gestalten. Ich hab bestimmt 50 Klassen.
Da lässt sich schwerlich was "kurz" angeben.
Wie wärs wenn ich dir das mal als zip. schicke. Da drin liegt die jar (die kannst einfach via doppelklick starten) und die benötigten bilder für das spiel...
Dann auf den Spatenklicken um ein "offlineSpiel" zu starten und dann bissl rumdrücken. Magst das haben? Dann schick ich dir das mal als PM