# Glücksrad



## Floesch84 (26. Jul 2005)

Hallo Leute.

Ich hoffe ihr könnt mir helfen. Ich bin gerade dabei ein Glücksrad-Spiel zu schreiben. Nur habe ich leider keinen blassen Schimmer, wie ich das Rad dazu bringen soll, dass es sich dreht. Hier ein Bild, wie das Rad bis jetzt aussieht (ist eher noch ein Platzhalter).







Hier ein kleiner Auszug aus meinem bisherigen Code (damit ihr wisst, wie ich bis jetzt vorgegangen bin):


```
private Ellipse2D oval;
private Area rhs;
private Area sector1; //und noch 15 weitere Sektoren, dieser dient als Beispiel

oval = new Ellipse2D.Double(30, 40, 290, 290);
rhs = new Area(oval);
sector1 = new Area(new Polygon(new int[]{175, 230, 230, 175}, new int[]{40, 40, 52, 185}, 4));

sector1.intersect(rhs); //damit nur der Teil des sector-Polygons dargestellt wird, der innerhalb des Kreises liegt


public void paint(Graphics g){ 
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
    g2.setPaint(Color.BLACK);
    g2.fill(sector1); //und das ganze noch 15 mal für die anderen Sektoren
}
    
/**
*Hier soll das Rad gedreht werden können
*
*/
public void spinWheel(){
}
```

Wie bekomme ich es also hin, dass sich das Rad drehen kann?

Und wie schaffe ich es, dass in den Sektoren Text angezeigt wird (z.B. der Geldbetrag, den man da bekommt oder das "Bankrott)

Ich bin dankbar für jede Anregung und jeden nütlichen Tipp!!

Floesch84


----------



## Sky (26. Jul 2005)

Vielleicht könntest Du ein Bild laden, welches Du rotieren läßt !?


----------



## m@nu (27. Jul 2005)

sorry, konnte mich nicht zurückhalten 
im code unten findest du eine JComponent, welche ein animiertes (primitives) glücksrad zeichnen und animieren kann.
sie enthält zum testen bereits eine main-methode... einfach mal laufen lassen 


```
/*
 * Created on 27.07.2005
 */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * @author Manuel Alabor
 * @version 1.0
 */
public class SpinningWheel extends JComponent {

    /* Eigenschaften: */
    private int sectorCount;
    private int startAngle = 0;
    private boolean runAnimation = false;
    
    // Konstruktoren -----------------------------------------------------------
    /**
     * @param sectorCount Anzahl "Teile" des Rades
     */
    public SpinningWheel(int sectorCount) {
        this.sectorCount = sectorCount;
    }
    
    /**
     * Konstruktor welcher automatisch 18 Rad-Teile erstellt.
     */
    public SpinningWheel() {
        this(18);
    }
    
    // Überschreibungen --------------------------------------------------------
    /**
     * Zeichnet das Rad.
     * 
     * @param g
     */
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        /* Vorbereiten: */
        // Variabeln:
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        int x = 15;                     // x-Position
        int y = 15;                     // y-Position
        int width = getWidth() - x*2;   // Breite
        int height = getHeight() - y*2; // Höhe
        int arc = 360 / sectorCount;    // Winkel eines Rad-Teiles
        
        // Immer ein "quadratisches" Rad zeichnen:
        if(width != height) {
            width = height;
        }
        
        /* Radteile zeichnen: */
        for(int i = 0; i < sectorCount; i++) {
            // Farbe abwechseln:
            if(i%2 == 0) {
                g2.setColor(Color.red);
            } else {
                g2.setColor(Color.yellow);
            }
            
            // Radteil zeichnen:
            // "startAngle" wird miteinbezogen, damit das ganze Rad animiert
            // werden kann.
            g2.fillArc(x,y,width,height, startAngle + i*arc, arc);
        }
        
        /* Rahmen zeichnen: */
        g2.setColor(Color.black);
        g2.drawOval(x,y, width,height);
    }
    
    // Animations-Steuerung ----------------------------------------------------
    /**
     * Lässt das Rad drehen.
     */
    public void startSpin() {
        if(!runAnimation) {
            /* Runnable erstellen: */
            // Solange runAnimation == true, wird startAngle um 1 erhöht.
            // Damit startAngle nicht irgendwann gröser als 360 wird, wird nach
            // "2*Radteil-Winkel" der startAngle wieder auf 0 gesetzt.
            Runnable animator = new Runnable() {
                public void run() {
                    while(runAnimation) {
                        // startAngle prüfen:
                        if(startAngle == (360 / sectorCount)*2) {
                            startAngle = 0;
                        }
                        
                        // startAngle erhöhen & Component neu zeichnen:
                        startAngle += 1;
                        repaint();
                        
                        // "Schlafen" bis zur nächsten Animationsphase:
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                };
            };
            
            /* Animation starten: */
            // runAnimation auf true setzen, sowie das erstellte Runnable in einem
            // neuen Thread starten.
            runAnimation = true;
            Thread animationThread = new Thread(animator);
            animationThread.start();
        }
    }
    
    /**
     * Stoppt die Animation.
     */
    public void stopSpin() {
        this.runAnimation = false;
    }
    
    // Getter-Methoden ---------------------------------------------------------
    public boolean isRunAnimation() {
        return runAnimation;
    }
    
    
    // Test-Programm -----------------------------------------------------------
    // diese main-Methode dient nur zu Testzwecken. Kann gelöscht werden.
    /**
     * Test-Programm um die SpinningWheel-Component zu testen.
     * 
     * @param args
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame("SpinningWheel");
        frame.setSize(250,250);
        frame.setLocation(200,200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        JComponent contentPane = (JPanel)frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        
        final SpinningWheel spwWheel = new SpinningWheel();
        JButton btnSpin = new JButton("Spin");
        btnSpin.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                if(!spwWheel.isRunAnimation()) {
                    spwWheel.startSpin();                    
                } else {
                    spwWheel.stopSpin();
                }                
            }
        });
        
        contentPane.add(spwWheel, BorderLayout.CENTER);
        contentPane.add(btnSpin, BorderLayout.SOUTH);
        
        frame.show();
    }
    
}
```

der code sollte ausreichend kommentiert sein... spiel einfach ein wenig mit den parametern herum... 
um die einzelnen rad-segmente zu zeichnen habe ich anstatt einzelner polygonen die drawArc-methode aus dem Graphics-api verwendet. dies erleichtert das zeichnen/animieren ungeimein, da du keine objekte mit den informationen zu den einzelnen rad-teilen erstellen musst.
mit etwas arbeit kannst du das glücksradtypische "verlangsamen" miteinbauen... textausgabe kannst du z.b. per drawString-methode bewerkstelligen.

folgend findest du den link zum Graphics2D-api von sun...
:arrow: Graphics2D Tutorial by Sun
dort findest du viele interessante dinge zur grafikprogrammierung

so far, greetz!
m@nu


----------



## Floesch84 (27. Jul 2005)

Cool, danke!

Werde mich so schnell wie möglich dran machen und das ganze mal testen. 
Danke auch für den Link.
Ich bin noch nicht so sehr bewandert, was Graphics bzw. Grphics2D angeht.

Hoffentlich komme ich heute noch dazu es zu testen, bin schon ganz wild drauf 

Danke nochmal,
 Floesch84


----------



## Sky (27. Jul 2005)

m@nu hat gesagt.:
			
		

> sorry, konnte mich nicht zurückhalten
> im code unten findest du eine JComponent, welche ein animiertes (primitives) glücksrad zeichnen und animieren kann.
> sie enthält zum testen bereits eine main-methode... einfach mal laufen lassen ...



Jetzt fehlt nur noch, dass das Rad in der Anlauf-Phase langsamer ist und mit der Zeit an Geschwindigkeit zulegt und analog dazu langsamer wird beim Abbremsen ;-)

Ansonsten: super!


----------



## m@nu (27. Jul 2005)

m@nu hat gesagt.:
			
		

> mit etwas arbeit kannst du das glücksradtypische "verlangsamen" miteinbauen... textausgabe kannst du z.b. per drawString-methode bewerkstelligen.



hehe, wollte ja nur einen anstoss geben ... okok, zugegeben, es ist ein ausführlicher anstoss 
hmm, du bringst mich da noch auf eine idee 8) man könnte das rad doch noch so gestalten, dass man es per drag'n'drop "laufen" lassen kann ... so mit schwung holen und allem :lol:


----------



## lin (27. Jul 2005)

wow, das hypnotisiert 
	

	
	
		
		

		
		
	


	


, toll! (aber die farbe? :bae


----------



## m@nu (27. Jul 2005)

hehe  dann änder den sleep auf 10, stell die farben auf schwarz/weiss und füg' den folgenden code vor dem "rahmen zeichnen" ein:


```
int x2 = x*4;
        int y2 = y*4;
        int width2 = (getWidth() - x2*2);
        int height2 = (getHeight() - x2*2);
        if(width2 != height2) {
            width2 = height2;
        }
        for(int i = 0; i < sectorCount; i++) {
            if(i%2 == 0) {
                g2.setColor(Color.white);
            } else {
                g2.setColor(Color.black);
            }
            
            g2.fillArc(x2,y2,width2,height2, -startAngle + i*arc, arc);
        }
```

dann fenster ganz gross machen und: "duuu wirst müüüüüüüde, ganz furchtbar müüüüüüüüdeee"


----------



## lin (27. Jul 2005)

Schnorch, razepfüüühhhh, schnorch, razepfüüüühüüüüü


----------



## Floesch84 (28. Jul 2005)

So, hab's jetzt mal eingebaut und es funktioniert auch schon ganz gut, aber 

1: Wenn man die Maus bewegt, während sich das Rad dreht, dreht es  sich schneller, als wenn man die Maus nicht bewegt. Liegt das daran, dass die Drehung in einem eigenen Thread realisiert wird?

2: Leider ist die variable "arc" nur als Integer realisiserbar, dafurch bleibt leider eine leere Fläche übrig, wenn man die Sektorenzahl ("sectorCount") so wählt, dass sich 360 nicht ohne Rest dadurch teilen lässt. Kann man das irgendwie umgehen?

Ansonsten abe noch mal Danke, du hast mir sehr weitergeholfen. mal sehen was ich damit noch so alles anstellen kann. Die Idee das Rad per Drag&Drop zu beschleunigen finde ich ziemlich klasse. Bin ich noch gar nicht drauf gekommen, wollte das "Ausholen" eigentlich anders umsetzen, aber jetzt.....


----------



## m@nu (28. Jul 2005)

zu 1: jop, dürfte ziemlich sicher daran liegen :-/ wüsste ich jetzt aber leider auch nicht, wie man das verbessern könnte... any ideas guys?

zu 2: das problem habe ich auch festgestellt. meiner meinung nach gibt es da aber kein workaround, da _fillArc_ als winkel nur int-werte entgegen nimmt :-/ ...

kein problem... bin auch froh, wenn mir wer weiterhilft wenn ich ne frage habe  ... darum: einfach wieder fragen wenn du irgendwo nicht weiterkommst


----------



## Floesch84 (28. Jul 2005)

m@nu hat gesagt.:
			
		

> zu 2: das problem habe ich auch festgestellt. meiner meinung nach gibt es da aber kein workaround, da _fillArc_ als winkel nur int-werte entgegen nimmt :-/ ...



Ja, das hab ich dann bei einem Blick in die Dokumentation auch gemerkt. Da kann man wohl wirklich nix dran machen. Egal, nehm ich halt 18 Sektoren. Habe ich mehr Felder um diverse "Bankrotts" und "Aussetzens" einzubauen. 



			
				m@nu hat gesagt.:
			
		

> kein problem... bin auch froh, wenn mir wer weiterhilft wenn ich ne frage habe  ... darum: einfach wieder fragen wenn du irgendwo nicht weiterkommst



Mach ich doch glatt. Also, erst mal ein Lob an euch. :toll: Bin ja noch neu hier, aber ich wurde doch bisher sehr freundlich aufgenommen. Ich glaub ich niste mich jetzt mal hier ein 

Hier ist auch schon meine nächste Frage. Die Sektoren werden ja durch _fillArc_ dargestellt. Diese sind aber doch keine Objekte, mit denen ich später noch was anfangen kann, oder? Mein Problem ist nämlich, dass ich jetzt nicht so genau weiß, wie ich feststellen soll, welcher Sektor gerade "aktiv" ist. Irgnedwie muss ich ja ein Ergebnis aus dem ganzen Gedrehe herausbekommen, z.B. ob der Spieler gerade ein "Bankrott" erdreht hat, oder 3ooo€. :?:


----------



## Sky (28. Jul 2005)

Floesch84 hat gesagt.:
			
		

> m@nu hat gesagt.:
> 
> 
> 
> ...



Das ist kein Problem von fillArc. Auf dem Monitor kann man halt nur ganze Pixel malen... ABER, trotzdem gibt es eine Lösung, die Nährungsweise an das "richtige" Ergebnis arbeitet:
Man muss einfach die Variable arc in der Schleife berechnen, in Abhängigkeit, wie viel schon gemalt wurde. Ein kleines Beispiel:

Sagen wird, wir haben 14 Sektoren.
arc ist beim 1. mal = 360 / 14 = 25(int).
arc ist beim 2. mal = 360-25 / 13=25(int)
arc ist beim 3. mal = 360-50 / 12=25(int)
arc ist beim 4. mal = 360-75 / 11=25(int)
arc ist beim 5. mal = 360-100 / 10=26(int)
arc ist beim 6. mal = 360-126 / 9=26(int)
arc ist beim 7. mal = 360-152 / 8=26(int)
arc ist beim 8. mal = 360-178 / 7=26(int)
arc ist beim 9. mal = 360-204 / 6=26(int)
arc ist beim 10. mal = 360-230 / 5=26(int)
arc ist beim 11. mal = 360-256 / 4=26(int)
arc ist beim 12. mal = 360-282 / 3=26(int)
arc ist beim 13. mal = 360-308 / 2=26(int)
arc ist beim 14. mal = 360-334 / 1=26(int)

Die Summe von allen 'arc' ist danach dann wieder 360!


----------



## m@nu (28. Jul 2005)

@Floesch84: das SpinningWheel mach das was du ihm sagst.
überleg dir jetzt mal folgendes: du berechnest im hintergrund das ergebnis z.b. per zufallsgenerator. danach willst du das ganze visualisieren und sagst deinem rad: "dreh bis zu sektor xy" ... machts klick? 

@sky80: hmm, ja ok, das wär eine möglichkeit... LOL, aber halbe pixel wären trotzdem geil :autsch: 8)


----------



## Floesch84 (29. Jul 2005)

m@nu hat gesagt.:
			
		

> überleg dir jetzt mal folgendes: du berechnest im hintergrund das ergebnis z.b. per zufallsgenerator. danach willst du das ganze visualisieren und sagst deinem rad: "dreh bis zu sektor xy" ... machts klick?



Ehrlich gesagt hat es nicht klick gemacht. 
Ist aber nicht weiter Schlimm.
Zunächst hab ich mir gedacht, könnte ich für den _Arc_ ja auch eine eigene Klasse schreiben. Aber dann habe ich bei einem Blick in die Dokumentation die tolle Klasse Arc2D bzw. Arc2D.Float entdeckt .
Daraufhin habe ich den Code daran angepasst und siehe da: Die Animation läuft wunderbar. Vorher war es ja so, dass wenn man die Maus bewegt hat, sich das Rad schneller gedreht hat. Das hab ich jetzt nicht mehr...jetzt läuft das Rad bei Mausbewegung etwas langsamer  :autsch: . Find ich jetzt zwar etwas seltsam, aber das ist erstmal egal. Hier mal kurz der geänderte Code:


```
//Ein Array von Arc2D
    private Arc2D.Float[] sectors = new Arc2D.Float[18];

   //Der Konstruktor, der automatisch ein Rad mit 18 Segmenten erstellt
    public SpinningWheel(){
        this.sectorCount = 18;
        
        for(int i = 0; i < sectors.length; i++){
            sectors[i] = new Arc2D.Float();
            sectors[i].setArc(30, 40, 290, 290, i * (360 / sectorCount), 360 / sectorCount, Arc2D.PIE);                    
        }
    }

   //die geänderte paintComponent()-Methode
 protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
        int arc = 360 / sectorCount;    
       
        for(int i = 0; i < sectorCount; i++) {
            if(i%2 == 0) {
                g2.setColor(Color.red);
            } else {
                g2.setColor(Color.yellow);
            }

            sectors[i].setArc(30, 40, 290, 290, startAngle + i * arc, arc, Arc2D.PIE);
            g2.fill(sectors[i]);
            g2.setColor(Color.BLACK);
            g2.drawString(values[i], i+20, i+20);
        }
    }

   //der Rest is unverändert
```


----------



## m@nu (29. Jul 2005)

du musst nicht denken: "dort wo das rad anhält, diesen wert will ich wissen", sondern "ich berechne das resultat im voraus und sage dem rad es soll dem user eine animation vorsetzen, damits so aussieht, als ob wirklich das rad das ergebnis ermittelt"

rein theoretisch ansatzweise MVC (model-viewer-controller) ... nicht die view (dein rad) sagt wie die daten entstehen, sondern der controller (z.b. ein zufallsgenerator) ... die view visualisiert das ganze nur
hm, weis nicht wie ich das sonst erklären könnte.... 


wieso hast du für die radstücke jeweils eine Arc2D-instanz erstellt?


----------



## Floesch84 (29. Jul 2005)

Naja, beim (echten) Glücksrad ist es ja so, dass das Ergebnis nicht im Vorraus ermittelt und dann das Rad gedreht wird, bis das Ergebnis da ist. Deswegen wollte ich das halt so umsetzen, dass das Ergebnis wirklich "zufällig" ist. 
Ich habe einzelne Arc2D-Instanzen erstellt, damit ich feststellen kann, welcher Sektor am Ende der Drehung beim Markierer (den ich noch einbauen muss) anliegt.
Sollte das ein schlechter Ansatz sein, verzeich mir bitte , aber ich bin halt doch noch Anfänger, besonders in Bezug auf so graphische Sachen.

Mal davon abgesehen, plane ich eigentlich noch, dass in den Sektoren noch Text angezeigt wird, z.B. "500 €", oder "Bankrott". Was halt so auf einem Glücksrad draufsteht. 
Nach meinem (Anfänger-)Verständnis, war daher der Anstatz die Sektoren einzeln zu kreieren der Richtige.

Wie gesagt, ich will ja, dass das Ergebnis "wirklich zufällig" ermittelt wird, beim Drehen und nicht, dass das Ergebnis vorher ermittelt wird. Weiß ja jetzt nicht ob das optimal ist. 

Naja, danke für deine Geduld mit mir .


----------



## lin (29. Jul 2005)

> Wie gesagt, ich will ja, dass das Ergebnis "wirklich zufällig" ermittelt wird, beim Drehen und nicht, dass das Ergebnis vorher ermittelt wird. Weiß ja jetzt nicht ob das optimal ist.



Das spielt doch für den user absolut keine Rolle...

Und wenn du willst das das Ergebnis wirklich zufällig ist, muss du einen wirklichen Zufallszahlengenerator nehmen (gibt glaub ne Möglichkeit mit der Soundkarte)... schau auch mal auf http://www.random.org/ 
Ansonsten sind die mir bekannten Generatoren Pseudozufallszahlengeneratoren.


----------



## Floesch84 (30. Jul 2005)

Okay, okay. Ich gebe mich gechlagen 



> Ansonsten sind die mir bekannten Generatoren Pseudozufallszahlengeneratoren.



Ja, das wusste ich ja durchaus auch. Mit "wirklich zufällig" meinte ich auch eher meinen Ansatz, das Ergebnis nicht vorher festzulegen und dann das Rad drehen zu lassen, bis das Ergebnis stimmt. 
Sorry, wenn ich mich da missverständlich ausgedrückt habe.


----------

