Freiwillige vortreten?
schnelles farbiges Apfelmännchen
-
ivettaB -
27. März 2025 um 16:19 -
Erledigt
Es gibt 46 Antworten in diesem Thema, welches 2.412 mal aufgerufen wurde. Der letzte Beitrag (
-
-
Dein C code

Du bist da sicher versierter als wir andere ?Ich hänge noch im Floodfill von vorhin geistig fest.
Während mein anderer Rechner die Hintergrundgrafik hackt vom SWIV.
Code ist nicht optimal. aber soweit schonmal...
Mein Code verfolgt dein Video frame by frame und rechnet die Sprites weg indem er mehrere Frames durchrechnet danach wartet bis neuer Bildinhalt (alle 3 Sek) geliefert werden - dann den CUT Punkt sucht und die Bilder aneinander klebt.
Code 115 Zeilen Python bis jetzt.
Fazit: Kompliziert im Detail
-
Warum nur? Am Ende wirst Du die Grafik ja doch nicht auf den c64 übernehmen können, weil der c64 die Anzahl der Bitplanes gar nicht kann
-
mc hires. Bitplanes egal. Stream vom Laufwerk oder aus EPROM CRT
wäre ein Test wert. -
Fürs Floodfill gibt es sicherlich wieder verschiedene Ansätze, so wie es ja auch viele verschiedene Floodfill-Algorithmen für Malprogramme gibt. Es soll schnell sein, aber es darf auch nichts von dem bunten Bereich übersehen werden. So was mache ich gern in BASIC, und erst, wenn ich den Algorithmus nicht mehr schneller machen kann, setze ich das in Asm um.
-
Ich hab zu PC (-AT) Zeiten mal ein Apfelmännchen geschrieben, in das ich etwas Arbeit investiert hab, um es schneller zu bekommen. Das hat dann z.B. Linien gezeichnet. Aber das gcc Apfelmännchen war ja eher als Compilertest gedacht und weniger zum schnellen Apfelmännchen malen.
Aber diese Sources hab ich evtl. nur noch auf alten Disketten, für die ich gerade kein Laufwerk eingebaut hab.
-
Na aber absolut. Das ist wie gemacht für den C64. Wurde bisher wohl nicht gemacht, weil sich wohl niemand so richtig vorstellen konnte, dass das Ergebnis gut aussieht.
Doch, Amica Paint kann das. Bitte melde dich an, um diesen Link zu sehen. zur Funktionsweise.
Arndt -
Fürs Floodfill gibt es sicherlich wieder verschiedene Ansätze, so wie es ja auch viele verschiedene Floodfill-Algorithmen für Malprogramme gibt. Es soll schnell sein, aber es darf auch nichts von dem bunten Bereich übersehen werden. So was mache ich gern in BASIC, und erst, wenn ich den Algorithmus nicht mehr schneller machen kann, setze ich das in Asm um.
hast du was in Basic ?
ich habe nur einen Dreieckfüller für mein 3d System gemacht und der war schon hart.
-
C
Alles anzeigenso ? #include "graphics.h" #include <stdio.h> #include <limits.h> #include <stdlib.h> #include <string.h> #define WIDTH (getMaxX()+1) #define HEIGHT (getMaxY()+1) const float xCentre = -0.75; const float yCentre = +0.0; const float dxy = 0.005; // Buffer to store iteration count per pixel unsigned char iterations[200][160]; // Enough for 160x200 mode unsigned char visited[200][160]; // Floodfill marker // Simple queue structure for floodfill #define QUEUE_SIZE (WIDTH * HEIGHT) typedef struct { int x, y; } Point; Point queue[QUEUE_SIZE]; int qhead = 0, qtail = 0; void enqueue(int x, int y) { if (qtail < QUEUE_SIZE) { queue[qtail].x = x; queue[qtail].y = y; qtail++; } } Point dequeue() { return queue[qhead++]; } int queue_not_empty() { return qhead < qtail; } int in_bounds(int x, int y) { return x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT; } void floodfill_from_edges() { // Initialize queue with all edge pixels where iterations[y][x] == 255 for (int x = 0; x < WIDTH; x++) { if (iterations[0][x] == 255) enqueue(x, 0); if (iterations[HEIGHT-1][x] == 255) enqueue(x, HEIGHT-1); } for (int y = 0; y < HEIGHT; y++) { if (iterations[y][0] == 255) enqueue(0, y); if (iterations[y][WIDTH-1] == 255) enqueue(WIDTH-1, y); } // Floodfill while (queue_not_empty()) { Point p = dequeue(); int x = p.x; int y = p.y; if (!in_bounds(x, y)) continue; if (visited[y][x]) continue; if (iterations[y][x] != 255) continue; visited[y][x] = 1; enqueue(x+1, y); enqueue(x-1, y); enqueue(x, y+1); enqueue(x, y-1); } } int main() { float cx, cy; float zx, zy, new_zx; unsigned char n; grafmode(GRAFMODE_160_200_4); // Step 1: Berechne Iterationen pro Pixel for (int j = 0; j < HEIGHT; ++j) { cy = yCentre + (j - HEIGHT/2)*dxy; for (int i = 0; i < WIDTH; ++i) { cx = xCentre + (i - WIDTH/2)*dxy*2; zx = 0.0; zy = 0.0; n = 0; while ((zx*zx + zy*zy < 4.0) && (n != 255)) { new_zx = zx*zx - zy*zy + cx; zy = 2.0*zx*zy + cy; zx = new_zx; n++; } iterations[j][i] = n; } } // Step 2: Floodfill von Rand aus floodfill_from_edges(); // Step 3: Ausgabe for (int j = 0; j < HEIGHT; ++j) { for (int i = 0; i < WIDTH; ++i) { if (visited[j][i]) { // Außengebiet (kein Mandelbrot): zeichne mit n plot(i, j, iterations[j][i] & getMaxColor()); } else { // Inneres der Mandelbrot-Menge: direkt schwarz plot(i, j, 0); } } } textmode(); return 0; }mal sehen ob cc65 das frisst - ansonsten ist es shitty den gcc will ich nicht auch noch am laptop haben....
oh shit ... ich bin raus:D:\c64\cc65\samples\ColorMandel>..\..\bin\cl65 mandel2.c -o mandel2.prg
mandel2.c:10: Fatal: Floating point type is currently unsupported
-
hast du was in Basic ?
bin zwar nicht atomcode, aber ja, hier: Bitte melde dich an, um diesen Link zu sehen.
So ein Floodfill arbeitet übrigens grundsätzlich anders als etwa ein Dreieck-Füll-Algorithmus. Letzteres geht rein von den Geometrie-Informationen aus, berechnet in dem umfassenden Rechteck auf dem Bildschirm für jede Zeile die äußersten Koordinaten links und rechts und zieht dann entsprechend die Linien.
Ein Floodfill hat diese Geometrie-Informationen nicht, nur die Bitmap. Als zusammenhörend gilt (im Regelfall) was von jedem leeren Pixel in der Fläche aus gesehen, waagerecht oder senkrecht verbunden ist und auch leer ist. Versucht man auf diese Weise ein Dreieck zu füllen, indem man zuerst mit einer Linienziehroutine die Umrisse zeichnet und dann einen Floodfill darauf losläßt, kann es gerade bei spitzwinkligen Dreiecken passieren, daß der Floodfill nicht in die Ecken "reinkommt".
-
zu deinem Beitrag Bitte melde dich an, um diesen Link zu sehen.: eine Queue herzunehmen ist schon mal ganz prima; die naive Methode, alle 4 Nachbarpixel zu speichern ist allerdings speichertechnisch relativ ineffizient. Die Füllregion läuft in Form eines Diamants vom Ausgangspunkt weg, und es wird jeder Punkt am Rand im Regelfall 2x auf die Queue geworfen.
Mein in Bitte melde dich an, um diesen Link zu sehen. gegebenes Verfahren arbeitet mit horizontalen Spännen und braucht erheblich weniger Speicher für die Queue. Mit etwa so vielen Einträgen wie der Bildschirm horizontale Pixel hat kommt man in 99,999%+ aller Fälle aus. Das BASIC Programm nimmt dazu einfach zwei Zeichenketten her, eine für x, eine für y. Mit + wird hinten angehängt, mit MID$(...,2) vorne abgeschnitten.

-
- Offizieller Beitrag
mc hires
Das widerspricht sich – entweder Multicolor ODER Hires. Ich nehme an, du meinst MC Bitmap.
MC vs. Hires, Bitmap vs. Charset.
-
hast du was in Basic ?
Ich leider nicht. Das "so was" war mehr allgemein gemeint, also dass ich Algorithmen immer erst in BASIC konzipiere. Hab mich zwar schon oft durch Pixelwüsten gehangelt, aber Füllen von völlig unregelmäßigen Flächen habe ich noch nicht gemacht. Hätte ich durchaus Lust zu, aber ich habe noch genug andere Baustellen.

-
hast du was in Basic ?
Ich leider nicht. Das "so was" war mehr allgemein gemeint, also dass ich Algorithmen immer erst in BASIC konzipiere. Hab mich zwar schon oft durch Pixelwüsten gehangelt, aber Füllen von völlig unregelmäßigen Flächen habe ich noch nicht gemacht. Hätte ich durchaus Lust zu, aber ich habe noch genug andere Baustellen.

das ist gar nicht easy das füllzeug.
Habe mir extra den cc65 installiert weil ich am assembler gescheitert bin.... ich habe jetzt einen Triangle fillercode welcher immer funktioniert egal wie das dreieck steht solange es 3 ecken hat.
Code
Alles anzeigenin python war es einfach: def fill_triangle(vertices, color): vertices.sort(key=lambda v: v[1]) # Sort vertices by y-coordinate v1, v2, v3 = vertices def interpolate(y1, y2, x1, x2, y): if y2 == y1: # Prevent division by zero return x1 return int(x1 + (x2 - x1) * (y - y1) / (y2 - y1)) # Fill upper part for y in range(v1[1], v2[1] + 1): x_start = interpolate(v1[1], v2[1], v1[0], v2[0], y) x_end = interpolate(v1[1], v3[1], v1[0], v3[0], y) pygame.draw.line(screen, color, (x_start, y), (x_end, y)) #pygame.time.wait(1) pygame.display.flip() # Fill lower part for y in range(v2[1], v3[1] + 1): x_start = interpolate(v2[1], v3[1], v2[0], v3[0], y) x_end = interpolate(v1[1], v3[1], v1[0], v3[0], y) pygame.draw.line(screen, color, (x_start, y), (x_end, y)) #pygame.time.wait(1) pygame.display.flip()in c wo ich mich nicht gut auskenne:
Code
Alles anzeigenvoid fill_triangle(FixedPoint v[3], unsigned char color) { int i; FixedPoint tmp; FixedPoint v1, v2, v3; int y, x; int x1, x2; // Sort vertices by Y for (i = 0; i < 2; ++i) { if (v[i].y > v[i + 1].y) { tmp = v[i]; v[i] = v[i + 1]; v[i + 1] = tmp; i = -1; } } v1 = v[0]; v2 = v[1]; v3 = v[2]; tgi_setcolor(color); for (y = v1.y; y <= v2.y; ++y) { if (v2.y != v1.y && y >= 0 && y < SCREEN_Y) { x1 = v1.x + ((v2.x - v1.x) * (y - v1.y)) / (v2.y - v1.y); x2 = v1.x + ((v3.x - v1.x) * (y - v1.y)) / (v3.y - v1.y); if (x1 > x2) { int t = x1; x1 = x2; x2 = t; } if (x1 < 0) x1 = 0; if (x2 >= SCREEN_X) x2 = SCREEN_X - 1; for (x = x1; x <= x2; ++x) tgi_setpixel(x, y); } } for (y = v2.y; y <= v3.y; ++y) { if (v3.y != v2.y && y >= 0 && y < SCREEN_Y) { x1 = v2.x + ((v3.x - v2.x) * (y - v2.y)) / (v3.y - v2.y); x2 = v1.x + ((v3.x - v1.x) * (y - v1.y)) / (v3.y - v1.y); if (x1 > x2) { int t = x1; x1 = x2; x2 = t; } if (x1 < 0) x1 = 0; if (x2 >= SCREEN_X) x2 = SCREEN_X - 1; for (x = x1; x <= x2; ++x) tgi_setpixel(x, y); } } }im meinem 3d Thread am c64 habe ich ja irgendwo ein rotierendes Dreieck das weiss gefüllt wird. Das ist der Source. Das muss ich jetzt mit assembler verkleben denn ich habe schnellere Routine in Assembler (bruteforce Speedcode) aber ich habe hier probleme den übergang vom C code in den Assemblerteil...
-
C
Alles anzeigenso ? #include "graphics.h" #include <stdio.h> #include <limits.h> #include <stdlib.h> #include <string.h> #define WIDTH (getMaxX()+1) #define HEIGHT (getMaxY()+1) const float xCentre = -0.75; const float yCentre = +0.0; const float dxy = 0.005; // Buffer to store iteration count per pixel unsigned char iterations[200][160]; // Enough for 160x200 mode unsigned char visited[200][160]; // Floodfill marker // Simple queue structure for floodfill #define QUEUE_SIZE (WIDTH * HEIGHT) typedef struct { int x, y; } Point; Point queue[QUEUE_SIZE]; int qhead = 0, qtail = 0; void enqueue(int x, int y) { if (qtail < QUEUE_SIZE) { queue[qtail].x = x; queue[qtail].y = y; qtail++; } } Point dequeue() { return queue[qhead++]; } int queue_not_empty() { return qhead < qtail; } int in_bounds(int x, int y) { return x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT; } void floodfill_from_edges() { // Initialize queue with all edge pixels where iterations[y][x] == 255 for (int x = 0; x < WIDTH; x++) { if (iterations[0][x] == 255) enqueue(x, 0); if (iterations[HEIGHT-1][x] == 255) enqueue(x, HEIGHT-1); } for (int y = 0; y < HEIGHT; y++) { if (iterations[y][0] == 255) enqueue(0, y); if (iterations[y][WIDTH-1] == 255) enqueue(WIDTH-1, y); } // Floodfill while (queue_not_empty()) { Point p = dequeue(); int x = p.x; int y = p.y; if (!in_bounds(x, y)) continue; if (visited[y][x]) continue; if (iterations[y][x] != 255) continue; visited[y][x] = 1; enqueue(x+1, y); enqueue(x-1, y); enqueue(x, y+1); enqueue(x, y-1); } } int main() { float cx, cy; float zx, zy, new_zx; unsigned char n; grafmode(GRAFMODE_160_200_4); // Step 1: Berechne Iterationen pro Pixel for (int j = 0; j < HEIGHT; ++j) { cy = yCentre + (j - HEIGHT/2)*dxy; for (int i = 0; i < WIDTH; ++i) { cx = xCentre + (i - WIDTH/2)*dxy*2; zx = 0.0; zy = 0.0; n = 0; while ((zx*zx + zy*zy < 4.0) && (n != 255)) { new_zx = zx*zx - zy*zy + cx; zy = 2.0*zx*zy + cy; zx = new_zx; n++; } iterations[j][i] = n; } } // Step 2: Floodfill von Rand aus floodfill_from_edges(); // Step 3: Ausgabe for (int j = 0; j < HEIGHT; ++j) { for (int i = 0; i < WIDTH; ++i) { if (visited[j][i]) { // Außengebiet (kein Mandelbrot): zeichne mit n plot(i, j, iterations[j][i] & getMaxColor()); } else { // Inneres der Mandelbrot-Menge: direkt schwarz plot(i, j, 0); } } } textmode(); return 0; }mal sehen ob cc65 das frisst - ansonsten ist es shitty den gcc will ich nicht auch noch am laptop haben....
oh shit ... ich bin raus:D:\c64\cc65\samples\ColorMandel>..\..\bin\cl65 mandel2.c -o mandel2.prg
mandel2.c:10: Fatal: Floating point type is currently unsupported
Das ist ja eben der Hauptvorteil des gcc6502. Ich hab aber irgendwo auch einen Code hier geposted, wo ich Floats mit dem cc65 gemacht hab. Ich glaub, das basierte auf ner Idee von Sauhund, wenn ich mich recht entsinne.
Bitte melde dich an, um diesen Link zu sehen.
-
ok habe anderen PC mit Win7 64bit
Was brauche ich alles damit der gcc rennt ?
-
Na aber absolut. Das ist wie gemacht für den C64. Wurde bisher wohl nicht gemacht, weil sich wohl niemand so richtig vorstellen konnte, dass das Ergebnis gut aussieht.
Doch, Amica Paint kann das. Bitte melde dich an, um diesen Link zu sehen. zur Funktionsweise.
ArndtIch check nicht worauf du hinaus willst ? FLI ?
-
mc hires
Das widerspricht sich – entweder Multicolor ODER Hires. Ich nehme an, du meinst MC Bitmap.
MC vs. Hires, Bitmap vs. Charset.
stimmt - ich kanns mir nicht merken ... DANKE
-
ok habe anderen PC mit Win7 64bit
Was brauche ich alles damit der gcc rennt ?
Ich hab den ganzen Kram in einer VirtualBox mit Linux laufen. Mit Windows möcht ich mir lieber nix anfangen?
-
verstehe
-