ubuntuusers.de

Suche Algorithmus zum ändern der Basisfarben eines Balls in Bewegung

Status: Ungelöst | Ubuntu-Version: Xubuntu 12.04 (Precise Pangolin)
Antworten |

Phil_Latio

Avatar von Phil_Latio

Anmeldungsdatum:
21. August 2011

Beiträge: 292

Hallo zusammen,

ich suche einen Algorithmus für folgende Situation in einem Programm für C++ und Qt Bibliotheken (geschrieben wird das ganze im QtCreator)

Ein Ball ist in Bewegung. Dabei durchläuft er eine Farbveränderung, wobei jeder Bewegung um ein Pixel eine Farbveränderung um "eins" entspricht. Dabei geht der Farbverlauf von RGB {0, 0, 0} zunächst zu {255, 0, 0} danach zu {255, 255, 0} danach: { 255, 255, 255 }, {0, 255, 255}, { 0, 0, 255}, { 0, 0, 0 } wonach er sich wiederholt.

Der Ball wird folgendermaßen befüllt:

1
painter.setBrush(QBrush(QColor(colorX, colorY, colorZ), Qt::SolidPattern));

Nun ist dies mein Lösungsansatz:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
if (increment) // increment = 1 also ist der Ball in Bewegung

        switch (color) {

        case 0:
            if (colorX <= 255 && colorY == 0 && colorZ == 0) {
                colorX++;
            }
                else color = 1;

                //break;

        case 1:
            if (colorX >= 255 && colorY <= 255 && colorZ == 0) {
                colorX = 255;
                colorY++;

            }
                else color = 2;
                //break;

        case 2:
            if (colorX >= 255 && colorY >= 255 && colorZ <= 255) {
                colorX = 255;
                colorY = 255;
                colorZ++;
            }
                else color = 3;
                //break;

        case 3:
            if (colorX >= 255 && colorY >= 255 && colorZ >= 255) {
                colorX--;
                colorY = 255;
                colorZ = 255;
            }
                else color = 4;
                //break;

        case 4:
            if (colorX <= 0 && colorY >= 255 && colorZ >= 255){
                colorX = 0;
                colorY--;
                colorZ = 255;
            }
                else color = 5;
                //break;

        case 5:
            if (colorX <= 0 && colorY <= 0 && colorZ >= 255){
                colorX = 0;
                colorY = 0;
                colorZ--;
            }
                else color = 6;
                //break;

        case 6:
            if (colorX <= 0 && colorY <= 0 && colorZ <= 0){
                colorX = 0;
                colorY = 0;
                colorZ = 0;
            }
                color = 0;
                //break;


        }

Der Ball durchläuft ein paar Farben und bleibt dann weiß. Wo ist hier der Fehler? Hat jemand hier eine elegantere Variante?

Danke und grüße eurer Phil

Dominik_Schuster

Anmeldungsdatum:
19. September 2013

Beiträge: 122

Hi,

es könnte daran liegen:

1
2
3
4
5
6
7
8
        case 3:
            if (colorX '''>=''' 255 && colorY '''>=''' 255 && colorZ '''>=''' 255) {
                colorX--;
                colorY = 255;
                colorZ = 255;
            }
                else color = 4;
                //break;

">=" heißt ja größer als und über 256 ist weiß weil es eigentlich nicht höher als 255 geht. Ich hoffe ich konnt dir helfen.

Mfg,

Dominik

Phil_Latio

(Themenstarter)
Avatar von Phil_Latio

Anmeldungsdatum:
21. August 2011

Beiträge: 292

Das habe ich verhindern können, indem ich nach dem Hochzählen der Werte die Werte explizit nochmal setze auf 255 oder 0. Der Compiler gibt auch ne Meldung aus, falls der RGB Farbenbereich überschritten wird ("RGB Colour out of range" o.ä."). Da dies nicht eintritt, bin ich mir ziemlich sicher diese Range nicht zu überschreiten.

Der Fehler muss sich irgendwo in case 3 befinden, da die Kugel ja weiß wird und sich dann nicht mehr verändert. Bei 255, 255, 255 müsste ja der Wert weiß erreicht sein.

Phil_Latio

(Themenstarter)
Avatar von Phil_Latio

Anmeldungsdatum:
21. August 2011

Beiträge: 292

">=" heißt ja größer als und über 256....

Das heißt doch, dass der Wert größer oder gleich ist oder???

Dominik_Schuster

Anmeldungsdatum:
19. September 2013

Beiträge: 122

">=" heißt ja größer als und über 256....

Das heißt doch, dass der Wert größer oder gleich ist oder???

Ja sry. Aber

1
2
3
4
5
6
7
8
        case 3:          |Hier ist er aber noch 255
            if (colorX >= 255 && colorY >= 255 && colorZ >= 255) {
                colorX--; <-- Hier änderts du den Wert auf null
                colorY = 255;
                colorZ = 255;
            }
                else color = 4;
                //break;

bei deinen vorigen cases hast du den wert oben gleich mit geändert nicht erst ein case weiter.

Mfg,

Dominik

Ps: Wenns fertig ist lass mal was sehen 😀

Phil_Latio

(Themenstarter)
Avatar von Phil_Latio

Anmeldungsdatum:
21. August 2011

Beiträge: 292

Ich glaube ich kann dir nicht ganz folgen. Im case 3 sind alle Werte auf 255. Und genau in diesem Fall soll der x Wert ja wieder weniger werden. Ich hoffe wir reden nicht aneinander vorbei...

Madda

Anmeldungsdatum:
23. Januar 2013

Beiträge: 42

Die if Abfrage in case 3 wird genau einmal ausgeführt. Wenn du den Wert dekrementierst ist die erste Bedingung nicht mehr erfüllt. Ich denke das sollte so heissen:

1
2
3
if (colorX > 0 && colorY >= 255 && colorZ >= 255) {
...
}

EDIT: bei case 4 und 5 musst du dann äquivalent die Bedingungen für colorY und colorZ anpassen

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17606

Wohnort: Berlin

Du wählst, wenn der Wert (255,255,255) ist aus, dass colorX decrementiert wird, also auf 254. Danach ist colorX aber nicht mehr >= 255 und so wird case3 nur einmal erfüllt.

Case 4 prüft dann:

1
2
3
4
5
6
        case 4:
            if (colorX <= 0 && colorY >= 255 && colorZ >= 255){
                colorX = 0;
                colorY--;
                colorZ = 255;
            }

colorX ist aber 254 und nicht ⇐ 0.

Auf >= 255 zu prüfen, wenn es nur maximal 255 werden soll, ist einerseits falsches, defensives Programmieren. Ein Wert > 255 würde stillschweigend korrigiert ohne dass man merkt, dass irgendwo was falsch läuft. Auch müsstest Du nicht ständig 2 Werte mehr setzen, als zu setzen sind.

Ich würde einen Counter hochzählen und modulo 6*255 nehmen, das durch 255 teilen und es gibt Dir den case, der anzuspringen ist. Dort ist dann (x,y,z) (+/- 1) zu setzen.

P.S.: Wieso sind die breaks auskommentiert?

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17606

Wohnort: Berlin

Hier ein Demo in Java, was syntaktisch ja sehr ähnlich ist:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Colorswitch
{
	public Colorswitch ()
	{
		int colorX = 0; 
		int colorY = 0; 
		int colorZ = 0; 
		int cnt = 0; 
		
		while (6*256 > cnt++) 
		{
			System.out.println (colorX + "\t" + colorY  + "\t" + colorZ);
			switch ((cnt%(6*256)-1)/255) {
				case 0: colorX++; break;
				case 1: colorY++; break;
				case 2: colorZ++; break;
				case 3: colorX--; break;
				case 4: colorY--; break;
				case 5: colorZ--; break;
			}
		}
	}

	public static void main (String args[])
	{
		new Colorswitch ();		
	}
}

Phil_Latio

(Themenstarter)
Avatar von Phil_Latio

Anmeldungsdatum:
21. August 2011

Beiträge: 292

Ja genau das war der Fehler. Vielen Dank schonmal für Euren freundlichen Rat.

Nun habe ich dazu noch eine weitere Frage. Der Ball bewegt sich über die x Koordinate hin und her und zwar so:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
      switch(phase) {

           case 0:
                   if (moveX<300)
                       moveX++;
                   else phase=1;
                   break;
           case 1:
                   if (moveX>100)
                       moveX--;
                   else phase=0;
                   break;
        }

Nun möchte ich es auch realisieren, dass die farbliche Veränderung auch tatsächlich von der Bewegung von moveX ausgelöst wird. Im Moment sind die beiden switch case Abfragen ja nur von der increment Variable abhängig. Daher meine Frage: Ist das überhaupt notwendig? Die color Variablen ändern sich ja, sobald der Ball in Bewegung kommt. Bin mir nicht ganz sicher, ob ich das evtl. falsch verstehe.

Phil_Latio

(Themenstarter)
Avatar von Phil_Latio

Anmeldungsdatum:
21. August 2011

Beiträge: 292

P.S.: Wieso sind die breaks auskommentiert?

Wenn die breaks nicht auskommentiert sind, geht der Farbbereich out of range:

1
QColor::setRgb: RGB parameters out of range

Die Lösung über den modulo Operator ist weitaus eleganter. Ich werde dies mal umsetzen. Danke für den Java Code.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17606

Wohnort: Berlin

Bei Werten > 6*255 läuft es nicht wie gewünscht weiter. Ein Workaround wäre leicht, aber die Ursache zu finden sicher wieder eleganter.

Antworten |