Glücksrad

Status
Nicht offen für weitere Antworten.

Floesch84

Mitglied
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).

wheel6ou.jpg


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

Code:
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
 

m@nu

Bekanntes Mitglied
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 :)

Code:
/*
 * 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

Mitglied
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

Top Contributor
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

Bekanntes Mitglied
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:
 

m@nu

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

Code:
        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" ;)
 

Floesch84

Mitglied
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

Bekanntes Mitglied
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

Mitglied
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

Top Contributor
Floesch84 hat gesagt.:
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. :)

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

Bekanntes Mitglied
@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

Mitglied
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 :D.
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:

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

Bekanntes Mitglied
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

Mitglied
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

Top Contributor
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

Mitglied
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.
 
Status
Nicht offen für weitere Antworten.

Oben