home *** CD-ROM | disk | FTP | other *** search
- /* GRDEMO.C - Demonstriert die Fähigkeiten der QuickC- Grafikbibliothek.
- * Dabei wird MENU zur Menüanzeige und TURTLE für Turtle-Grafik benutzt.
- *
- * Sofern GRAPHICS.LIB und PGCHART.LIB bei der Installation nicht in
- * die Laufzeit-Bibliothek eingefügt wurden, müssen die beiden
- * Bibliotheken in die Programmliste von GRDEMO.MAK aufgenommen
- * oder auf der Befehlszeile angegeben werden
- */
-
- #include <graph.h>
- #include <math.h>
- #include <malloc.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <conio.h>
- #include <time.h>
- #include "turtle.h"
- #include "menu.h"
-
- /* Funktionsprototypen */
- int main( void );
- void Kreise( void );
- void Kugel( void );
- int Polygone( void );
- int Spirale( int winkel, double inc );
- int UmSpirale( double seite, int winkel, int inc );
- void Wanze( void );
- void FensterRahmen( void );
- void Diamant (double xy);
-
- /* Ergibt eine Zufallszahl zwischen min und max, die im zulässigen Bereich
- * für Ganzzahlen liegen muß.
- */
- #define getrandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))
-
- /* Konstanten */
- #define PI 3.141593
- #define LASTATR 15
- #define NLASTATR 14
-
- /* Datenfeld und Aufzählungsliste für Hauptmenü */
- ITEM mnuMain[] =
- { /* Hell hervorgehobenes Zeichen - Position */
- 0, "Beenden", /* B 0 */
- 0, "Kreise", /* K 0 */
- 0, "Rotierende Kugel", /* R 0 */
- 0, "Tunnel", /* T 0 */
- 0, "Spirale", /* S 0 */
- 0, "Umgekehrte Spirale", /* U 0 */
- 0, "Wanze", /* W 0 */
- 0, "Fenster anpassen", /* F 0 */
- 0, "Modus ändern", /* M 0 */
- 0, ""
- };
-
- /* Konstanten für Menüauswahl definieren (0, 1, 2,...) */
- enum AUSWAHL
- {
- BEENDEN, KREISE, KUGEL, TUNNEL, SPIRALE, UMSPIRAL, WANZE, FENSTER, MODUS
- };
-
- /* Datenfelder aus Videomodus-Werte und entsprechende Modusnummern.
- * Jedes besitzt ein vorübergehendes Datenfeld mit allen Größen und eine
- * Zeigerversion die alle außer Olivetti mit einschließt.
- */
- ITEM mnuModesT[] =
- { /* Hell hervorgehobenes Zeichen - Position */
- 0, "ORESCOLOR ", /* O 0 */
- 4, "MRES4COLOR ", /* 4 4 */
- 4, "MRESNOCOLOR", /* N 4 */
- 4, "HRESBW", /* B 4 */
- 0, "MRES16COLOR", /* M 0 */
- 0, "HRES16COLOR", /* H 0 */
- 0, "ERESCOLOR", /* E 0 */
- 4, "VRES2COLOR", /* 2 4 */
- 0, "VRES16COLOR", /* V 0 */
- 1, "MRES256COLOR", /* R 4 */
- 0, ""
- };
- ITEM *mnuModes = &mnuModesT[1]; /* Vorgabe ist kein Olivetti-Modus */
-
- int aModesT[] =
- {
- _ORESCOLOR,
- _MRES4COLOR,
- _MRESNOCOLOR,
- _HRESBW,
- _MRES16COLOR,
- _HRES16COLOR,
- _ERESCOLOR,
- _VRES2COLOR,
- _VRES16COLOR,
- _MRES256COLOR,
- _TEXTMONO,
- _ERESNOCOLOR,
- _HERCMONO
- };
- int *aModes = &aModesT[1]; /* Vorgabe ist kein Olivetti-Modus */
-
- /* Globale Video-Konfiguration */
- struct videoconfig vc;
-
- int main()
- {
- int zeilMitte, spltMitte;
- int fFarbe, fAnfang = WAHR;
- int iMode, iMainGgw = 0, iModesGgw = 0;
-
- _displaycursor( _GCURSOROFF );
- _getvideoconfig( &vc );
- zeilMitte = vc.numtextrows / 2;
- spltMitte = vc.numtextcols / 2;
-
- /* Besten Grafikmodus wählen, Menüs anpassen, Farbkennungen einrichten.
- * Nicht vergessen, daß dafür sowohl der Adapter als auch die
- * Betriebsart geprüft werden müssen.
- */
- switch( vc.adapter )
- {
- case _OCGA:
- mnuModes = &mnuModesT[0]; /* Olivetti-Modus einschalten */
- aModes = &aModesT[0];
- case _CGA:
- mnuModesT[4].achItem[0] = '\0'; /* EGA-Modi ausschalten */
- iMode = _MRES4COLOR;
- break;
- case _HGC:
- mnuModesT[7].achItem[0] = '\0';
- iMode = _HERCMONO;
- break;
- case _OEGA:
- mnuModes = &mnuModesT[0]; /* Olivetti-Modus einschalten */
- aModes = &aModesT[0];
- case _EGA:
- mnuModesT[7].achItem[0] = '\0'; /* VGA-Modi ausschalten */
- if( vc.memory > 64 )
- iMode = _ERESCOLOR;
- else
- iMode = _HRES16COLOR;
- break;
- case _OVGA:
- mnuModes = &mnuModesT[0]; /* Olivetti-Modus einschalten */
- aModes = &aModesT[0];
- case _VGA:
- iMode = _VRES16COLOR;
- break;
- case _MCGA:
- iMode = _MRES256COLOR;
- break;
- case _MDPA:
- default:
- puts( "Kein Grafikmodus verfügbar.\n" );
- return WAHR;
- }
- switch( vc.mode )
- {
- case _TEXTBW80:
- case _TEXTBW40:
- fFarbe = FALSCH;
- break;
- case _TEXTMONO:
- case _ERESNOCOLOR:
- case _HERCMONO:
- fFarbe = FALSCH;
- if( iMode != _HERCMONO )
- iMode = _ERESNOCOLOR;
- mnuMain[8].achItem[0] = '\0'; /* Modus-Änderung ausschalten */
- break;
- default:
- fFarbe = WAHR;
- break;
- }
-
- /* Gegenwärtigen Modus in Modus-Datenfeld finden. */
- for( iModesGgw = 0; aModes[iModesGgw] != iMode; iModesGgw++ )
- ;
-
- /* Zufallsgenerator mit Uhrzeit als Anfangswert füttern. */
- srand( (unsigned)time( NULL ) );
-
- while( WAHR )
- {
- /* Auf Text-Modus schalten; wahlweise ganzen Bildschirm zu blau. */
- _setvideomode(_DEFAULTMODE );
- if( fFarbe )
- _setbkcolor( (long)_TBLUE );
- _clearscreen( _GCLEARSCREEN );
-
- /* Aus Menü wählen. */
- iMainGgw = Menue( zeilMitte, spltMitte, mnuMain, iMainGgw );
-
- /* Grafikmodus einrichten und Turtle-Grafik initialisieren. Fenster
- * mit Rand versehen.
- */
- if( iMainGgw != MODUS )
- {
- _setvideomode( iMode );
- _displaycursor( _GCURSOROFF );
- _getvideoconfig( &vc );
- InitTurtle( &vc );
- Rechteck( 2 * tc.xMax, 2 * tc.yMax );
- }
-
- /* Zu neuer Menüwahl verzweigen. */
- switch( iMainGgw )
- {
- case BEENDEN:
- _setvideomode( _DEFAULTMODE );
- return FALSCH;
- case KREISE:
- Kreise();
- break;
- case KUGEL:
- Kugel();
- break;
- case TUNNEL:
- StiftStatus( FALSCH );
- GeheZu( -tc.xMax * .2, tc.yMax * .15 );
- StiftStatus( WAHR );
- Polygone();
- while( !GetKey( NO_WAIT ) )
- FarbWertWeiter( VORGABE ); /* Rotate palette */
- break;
- case SPIRALE:
- if( Spirale( getrandom( 30, 80 ), (double)getrandom( 1, 5 ) ) )
- break;
- while( !GetKey( NO_WAIT ) )
- FarbWertWeiter( VORGABE );
- break;
- case UMSPIRAL:
- FarbIndexWeiter( 0 );
- if( UmSpirale( (double)getrandom( 8, 20 ),
- getrandom( 4, 22 ),
- getrandom( 3, 31 ) ) )
- break;
- while( !GetKey( NO_WAIT ) )
- FarbWertWeiter( VORGABE );
- break;
- case WANZE:
- Wanze();
- break;
- case FENSTER:
- FensterRahmen();
- continue;
- case MODUS:
- if( fFarbe )
- _setbkcolor( (long)_TBLUE );
- _clearscreen( _GCLEARSCREEN );
-
- iModesGgw = Menue( zeilMitte, spltMitte, mnuModes, iModesGgw );
- iMode = aModes[iModesGgw];
- if( vc.adapter == _MCGA )
- switch( iMode )
- {
- case _MRES16COLOR:
- case _HRES16COLOR:
- case _ERESCOLOR:
- case _VRES16COLOR:
- _settextposition( 1, 22 );
- _outtext( "Modus nicht verwendbar" );
- iMode = _MRES256COLOR;
- }
- break;
- }
- }
- }
-
- /* Kreise - In runder Anordnung Kreise unterschiedlicher Größe und Farbe
- * auf dem Bildschirm zeichnen.
- *
- * Parameter: Keine
- *
- * Ergebnis: Keines
- *
- * Benutzt: tc
- */
- void Kreise()
- {
- double x, y, xyRadius;
- int fFuell, fStiftStatus;
-
- /* Stifteinstellung und Füll-Kennungen initialisieren und speichern. */
- if( tc.afi <= 4 )
- fFuell = AusFuellung( FALSCH );
- else
- fFuell = AusFuellung( WAHR );
- fStiftStatus = StiftStatus( FALSCH );
-
- while( WAHR )
- {
- /* Kreise zeichnen. */
- for( xyRadius = 10.0; xyRadius <= 130.0; xyRadius++ )
- {
- x = (tc.xMax - 30) * atan( sin( xyRadius / PI ) );
- y = (tc.yMax - 30) * atan( cos( xyRadius / PI ) );
- GeheZu( x, y );
- StiftFarbe( FarbIndexWeiter( VORGABE ) );
- Kreis( xyRadius );
- if( GetKey( NO_WAIT ) )
- {
- StiftStatus( fStiftStatus );
- AusFuellung( fFuell );
- return;
- }
- }
-
- /* Für Palettenmodi (ausgen. 256-Farbig) neu anfangen. */
- if( tc.afw == 64 || tc.afw == 16 )
- {
- _clearscreen( _GCLEARSCREEN );
- AusFuellung( FALSCH );
- GeheZu( 0.0, 0.0 );
- StiftFarbe( WEISS );
- Rechteck( 2 * tc.xMax, 2 * tc.yMax );
- AusFuellung( fFuell );
- FarbWertWeiter( VORGABE );
- }
- }
- }
-
- /* Kugel - Scheiben einer Kugel zeichnen und füllen. Für EGA+ Modi mit mehr
- * als 4 Farbindizes die Farben weiterrotieren.
- *
- * Parameter: Keine
- *
- * Ergebnis: Keines
- *
- * Benutzt: tc
- */
- void Kugel()
- {
- double xGgw, xGroesse, yGroesse, xInc;
- short ciRand, fFuell;
- short cvi = 0, ci = 0, c = 0;
- extern long cvlColors[];
-
- yGroesse = xGroesse = tc.yMax * 0.9 * 2;
- fFuell = AusFuellung( FALSCH );
- FarbIndexWeiter( 0 );
- xInc = xGroesse / 14;
- ciRand = StiftFarbe( VORGABE );
- RandFarbe( ciRand );
-
- /* Scheiben zeichnen. */
- for( xGgw = xInc; xGgw <= xGroesse; xGgw += xInc * 2 )
- Ellipse( xGgw, yGroesse );
- AusFuellung( WAHR );
- StiftStatus( FALSCH );
- Schwenken( 90 );
- xGroesse /= 2;
- GeheZu( xGroesse - xInc, 0.0 );
-
- FarbWertWeiter( GRENZE );
-
- /* Scheiben füllen. */
- while( tc.xGgw >= (-xGroesse + xInc))
- {
- StiftFarbe( FarbIndexWeiter( VORGABE ) );
- Fuellen();
- Bewege( -xInc );
- }
-
- while( !GetKey( NO_WAIT ) )
- FarbWertWeiter( GRENZE );
-
- StiftStatus( WAHR );
- AusFuellung( fFuell );
- }
-
- /* Polygone - Zeichnet Polygone (Vielecke), vom Dreieck angefangen, wobei
- * deren Größe immer weiter wächst, indem die Anzahl der Seiten
- * inkrementiert wird, ohne die Seitelänge zu verringern. Natürlich muß der
- * Stift aktiv sein.
- *
- * Parameter: Keine
- *
- * Ergebnis: 1 bei Benutzer-Unterbrechung, 0 bei Bildschirmrand
- *
- * Benutzt: tc
- */
- int Polygone()
- {
- int cSeiten = 3, atrib = 1;
- double dxy = tc.yEinheit;
-
- while( WAHR )
- {
- StiftFarbe( FarbIndexWeiter( VORGABE ) );
- if( !Poly( cSeiten++, dxy += 1.5 ) )
- return FALSCH;
- if( GetKey( NO_WAIT ) )
- return WAHR;
- }
- }
-
- /* Spirale - Zeichnet eine Spirale durch laufendes Verlängern der Seiten
- * einer sich drehenden Figur.
- *
- * Parameter: wnkl - bestimmt Dichte
- * xyInc - bestimmt Größe der Seiten
- *
- * Ergebnis: 1 bei Benutzer-Unterbrechung, 0 bei Bildschirmrand
- *
- * Benutzt: tc
- */
- int Spirale( int wnkl, double xyInc )
- {
- double xy = tc.yEinheit;
-
- while( WAHR )
- {
- StiftFarbe( FarbIndexWeiter( VORGABE ) );
- if( !Bewege( xy += xyInc ) )
- return FALSCH;
- Schwenken( wnkl );
- if( GetKey( NO_WAIT ) )
- return WAHR;
- }
- }
-
- /* UmSpirale - Zeichnet eine umgekehrte Spirale durch laufendes Vergrößern
- * aller Winkel einer einer sich drehenden Figur, ohne die
- * Länge der Seiten zu ändern.
- *
- * Parameter: xy - bestimmt Größe
- * wnkl - bestimmt Dichte
- * xyInc - bestimmt Größe der Seiten
- *
- * Ergebnis: 1 bei Benutzer-Unterbrechung, 0 bei Bildschirmrand
- *
- */
- int UmSpirale( double xy, int wnkl, int wnklInc )
- {
- while( WAHR )
- {
- StiftFarbe( FarbIndexWeiter( VORGABE ) );
- if( !Bewege( xy ) )
- return FALSCH;
- Schwenken( wnkl += wnklInc );
- if( GetKey( NO_WAIT ))
- return WAHR;
- }
- }
-
- /* Wanze - Zeichnet einen geflügelten Käfer auf dem Bildschirm und bewegt
- * ihn dann willkürlich herum.
- *
- * Parameter: Keine
- *
- * Ergebnis: Keines
- *
- * Benutzt: tc
- */
- void Wanze()
- {
-
- static unsigned char uVordFlgel[] = { 0x81, 0x3c, 0xc3, 0x66,
- 0x66, 0x0f, 0xf0, 0x18 };
- static unsigned char uHintFlgel[] = { 0x66, 0x0f, 0xf0, 0x18,
- 0x81, 0x3c, 0xc3, 0x66 };
- char *buffer; /* Bild - Zwischenspeicher */
-
- /* Käfer zeichnen. */
- StiftStatus( FALSCH );
- AusFuellung( WAHR );
- Bewege( 40.0 ); /* Vordere Flügel zeichnen und ausfüllen */
- Schwenken( 90 );
- Bewege( 80.0 );
- StiftFarbe( 1 );
- _setfillmask( uVordFlgel );
- Ellipse( 172.0, 70.0 );
- Schwenken( 180 );
- Bewege( 160.0 );
- Ellipse( 172.0, 70.0 );
- Schwenken(-90 );
- GeheZu( 0.0, 0.0 );
- Bewege( 25.0 ); /* Hintere Flügel zeichnen und ausfüllen */
- Schwenken( 90 );
- Bewege( 70.0 );
- StiftFarbe( 2 );
- _setfillmask( uHintFlgel );
- Ellipse( 150.0, 70.0 );
- Schwenken( 180 );
- Bewege( 140.0 );
- Ellipse( 150.0, 70.0 );
- Schwenken(-90 );
- GeheZu( 0.0, 0.0 );
- _setfillmask( NULL ); /* Körper des Käfers zeichnen */
- StiftFarbe( 3 );
- RandFarbe( 3 );
- Ellipse( 52.0, 220.0 );
- StiftFarbe( 1 ); /* Nun die Augen */
- RandFarbe( 1 );
- AusFuellung( FALSCH );
- Bewege( 90.0 );
- Schwenken( 90 );
- Bewege( 22.0 );
- Kreis( 20.0 );
- StiftFarbe( 0 );
- Fuellen();
- StiftFarbe( 1 );
- Schwenken( 180 );
- Bewege( 44.0 );
- Kreis( 20.0 );
- StiftFarbe( 0 );
- Fuellen();
-
- /* Position einnehmen - rechts-oben des Bildes. */
- GeheZu( 0.0, 0.0 );
- Richtung( 0 );
- Bewege( 120.0 );
- Schwenken( -90 );
- Bewege( 175.0 );
- Schwenken( 90 );
-
- /* Bildgröße feststellen und Speicher dafür zuordnen. */
- buffer = (char *)malloc( (size_t)BildGroesse( 350.0, 240.0 ) );
- BildHolen( 350.0, 240.0, buffer );
-
- /* Nach Zufallswerten herumschwirren, an Bildschirmrändern anpassen. */
- while( !GetKey( NO_WAIT ) )
- {
- if( tc.xGgw <= (-tc.xMax + 15.0) )
- Richtung( 90 );
- else if( tc.yGgw <= (-tc.yMax + 15.0) )
- Richtung( 180 );
- else if( tc.xGgw >= (tc.xMax - 365.0) )
- Richtung( 270 );
- else if( tc.yGgw >= (tc.yMax - 255.0) )
- Richtung( 0 );
- else
- Schwenken( getrandom( -20, 20 ) );
- Bewege( 3.0 );
- BildPos( buffer, _GPSET );
- }
- free( (char *)buffer );
- }
-
- /* FensterRahmen - Damit kann man im Dialogbetrieb den Bildschirmausschnitt
- * einrichten. Richtungstasten allein zum Verändern der Fenstergröße;
- * Richtungstasten mit Umschalter bewegen das Fenster. Die Die Plus- bzw.
- * Minustaste auf dem Zahlentastenblock verändern das Seitenverhältnis, ohne
- * das Fenster selbst zu beeinflussen. Dabei erscheinen zur Orientierung ein
- * Fensterrahmen und ein Kreis.
- *
- * Parameter: Keine
- *
- * Ergebnis: Keines
- *
- * Benutzt: tc and vc
- */
- #define WININC 4
- void FensterRahmen()
- {
- short i, iSchreibModus;
- double xyRadius = 400.0, xEcke, yEcke;
- char achT[40];
-
- while( WAHR )
- {
- /* Anleitungen anzeigen. */
- _settextposition( 2, 2 );
- _outtext(" Seitenverhältnis graue PLUS- und MINUS-Taste\n" );
- _settextposition( 3, 2 );
- _outtext(" Fenstergröße mit Richtungstasten\n" );
- _settextposition( 4, 2 );
- _outtext(" Fenster verschieben UMSCH+Richtungstasten\n" );
- _settextposition( 5, 2 );
- _outtext(" Fertig EINGABETASTE\n\n" );
-
- /* Speichern des alten Schreibmodus und Setzen von XOR, damit Sie
- * Figuren durch erneutes Erstellen gelöscht werden. Dies möglicht das
- * Überschreiben von Text ohne ihn zu löschen.
- */
-
- iSchreibModus = _getwritemode();
- _setwritemode( _GXOR );
-
- while ( WAHR )
- {
- /* Daten ausgeben */
- _settextposition( 6,2 );
- sprintf( achT, "\n Seitenvh=%1.2f xMax=%.f yMax=%.f",
- tc.yxSeitenvh, tc.xMax, tc.yMax );
- _outtext( achT );
-
- /* Berechnen der aktuellen Boxenecken. */
- xEcke = 2 * tc.xMax;
- yEcke = 2 * tc.yMax;
-
- /* Zeichnen der Kanten des Rechtecks und des Diamanten
- * um das Verhältnis darzustellen.
- */
- Rechteck( xEcke, yEcke );
- Diamant( xyRadius);
-
- switch( GetKey( CLEAR_WAIT ) )
- {
- /* Seitenverhältnis anpassen. */
- case N_MINUS:
- if( tc.yxSeitenvh > 0.4)
- tc.yxSeitenvh = (tc.xMax - (WININC * tc.yEinheit)) / tc.yMax;
- break;
- case N_PLUS:
- if( tc.yxSeitenvh < 8.0)
- tc.yxSeitenvh = (tc.xMax + (WININC * tc.yEinheit)) / tc.yMax;
- break;
-
- /* Fenstergröße einrichten. */
- case U_RT:
- if( tc.xsLinks < (vc.numxpixels / 3) )
- tc.xsLinks += WININC;
- if( tc.xsRechts > (vc.numxpixels - (vc.numxpixels / 3)) )
- tc.xsRechts -= WININC;
- break;
- case U_LT:
- if( tc.xsLinks )
- tc.xsLinks -= WININC;
- if( tc.xsRechts < vc.numxpixels )
- tc.xsRechts += WININC;
- break;
- case U_DN:
- if( tc.ysOben < (vc.numypixels / 3) )
- tc.ysOben += WININC;
- if( tc.ysUnten > (vc.numypixels - (vc.numypixels / 3)) )
- tc.ysUnten -= WININC;
- break;
- case U_UP:
- if( tc.ysOben )
- tc.ysOben -= WININC;
- if( tc.ysUnten < vc.numypixels )
- tc.ysUnten += WININC;
- break;
-
- /* Fensterposition einrichten. */
- case S_LT:
- if( tc.xsLinks )
- {
- tc.xsLinks -= WININC;
- tc.xsRechts -= WININC;
- }
- break;
- case S_RT:
- if( tc.xsRechts < vc.numxpixels )
- {
- tc.xsLinks += WININC;
- tc.xsRechts += WININC;
- }
- break;
- case S_UP:
- if( tc.ysOben )
- {
- tc.ysOben -= WININC;
- tc.ysUnten -= WININC;
- }
- break;
- case S_DN:
- if( tc.ysUnten < vc.numypixels )
- {
- tc.ysOben += WININC;
- tc.ysUnten += WININC;
- }
- break;
-
- /* Ende. */
- case EINGABE:
- _setwritemode( iSchreibModus );
- return;
-
- /* Unbekannte Tasten ignorieren. */
- default:
- break;
- }
- /* Nach jeder Einstellung Bildschirm löschen, und auf Vorgaben rücksetzen. */
- Rechteck( xEcke, yEcke );
- Diamant ( xyRadius );
- Home();
- }
- }
- }
- /* Funktion wird von FensterRahmen zum Zeichnen des Diamanten benutzt. */
- void Diamant( double xy )
- {
- StiftStatus( FALSCH );
- GeheZu( 0.0, xy );
- StiftStatus( WAHR );
- GeheZu( xy, 0.0 );
- GeheZu( 0.0, -xy );
- GeheZu( -xy, 0.0 );
- GeheZu( 0.0, xy );
- StiftStatus( FALSCH );
- GeheZu( 0.0, 0.0 );
- StiftStatus( WAHR );
- }
-