Graustufengrafiken mit TIGCC

In dieser Kategorie findet ihr verschiedene ASM/C-Tutorials, die euch beim Programmiereinstieg helfen sollen.

Graustufengrafiken mit TIGCC

Beitragvon saubue am 6. Juli 2008 01:14

Graustufengrafiken sind heute Teil jedes guten Spiels (zumindest auf den 68k-Rechnern), weshalb sie von guten Programmierern einfach beherrscht werden müssen. In diesem Tutorial werde ich versuchen, euch die Graustufenprogrammierung etwas näher zu bringen.

1. Funktionsweise von Graustufengrafiken

Wie sind Graustufen überhaupt möglich?

Nun, der Rechner kennt im Grunde keine Graustufen, sondern nur schwarz und weiss, also Pixel an und Pixel aus. Will man jedoch Graustufen anzeigen lassen, so muss man das menschliche Auge überlisten, indem man ständig zwischen zwei Bildern wechselt und das eine immer etwas länger anzeigt als das andere. Wird das schnell genug gemacht, sieht der User folgendes: Die Pixel, die nie angesteuert werden, erscheinen logischerweise weiß. Die Pixel, die nur von dem kürzer angezeigten Bild benutzt werden, erscheinen hellgrau. Die Pixel, die nur von dem länger angezeigten Bild benutzt werden, erscheinen hellgrau und die, die von beiden benutzt werden erscheinen schwarz. Somit hätten wir praktisch 4 Farben.
Damit wir nicht die ganze Arbeit dieses Wechselns übernehmen müssen, bietet uns TIGCC die in der Header-Datei gray.h definierten Graustufenfunktionen an. Dort wird zwischen zwei sog. Planes unterschieden: Dem LIGHT_PLANE, also dem kürzer gezeigten und dem DARK_PLANE, dem länger gezeigten. Sobald wir die Graustufen einschalten, werden also abwechselnd das LIGHT_PLANE und das DARK_PLANE gezeigt.

2. Ein kleines Beispiel

Nun gut, hierzu ein Beispiel mit einem 32*48-Sprite:

Code: Alles auswählen
// C Source File
// Created 03.06.2005; 19:41:24

#include <tigcclib.h>

#define HEIGHT 48

// Der anzuzeigende Sprite
unsigned long firehead[HEIGHT*2] = {
// DARK_PLANE
0x00010000,0x00030000,0x00060000,0x000F0000
,0x00190000,0x00320000,0x00320000,0x001E0000
,0x020B0000,0x06190000,0x04118000,0x04239000
,0x04239000,0x00679800,0x01671800,0x026E0C00
,0x05249C00,0x049DDC80,0x02B748C0,0x05A66DC0
,0x09624780,0x0B664A80,0x11E38CC0,0x11A39680
,0x33D194A0,0x63801160,0x651DDBE0,0x303FE980
,0x186FFC80,0x38FFFC40,0x6CDFFC40,0x69FFFE60
,0xC9FFFE60,0xC1FFFF60,0xC1FFFF60,0xE19FC6C0
,0xE19FC680,0x71850E00,0x11CD9F40,0x01FFFEC0
,0x18DFFCC0,0x18FFFB80,0x0E7BF600,0x073FE000
,0x008FC800,0x00DF1800,0x007DF000,0x0038E000
// LIGHT_PLANE
,0x00010000,0x00030000,0x00060000,0x00090000
,0x00131000,0x00264000,0x002E0000,0x00120000
,0x020D0000,0x04132000,0x06168000,0x002C9000
,0x002C8000,0x04488A00,0x00490800,0x02520400
,0x073C9400,0x07955480,0x03A2D8C0,0x04ABA540
,0x0F4DEA80,0x0959D380,0x1B9C5140,0x16DC4800
,0x24AE6320,0x5D7FEE20,0x5AFFE420,0x0FE3B600
,0x07DFD100,0x2783EA80,0x53EBFE00,0x47170520
,0x97BEFF00,0x9B0F0680,0xB0F67EA0,0x93147F40
,0x931FFF00,0x4BC7CF80,0x0B629E80,0x0FB8FD00
,0x17A98B00,0x17C7DC00,0x09EDF800,0x06F3FC00
,0x007FF000,0x0020E000,0x00000000,0x0038E000
};


// Haupt-Funktion
void _main(void)
{
   // Bildschirminhalt löschen
   ClrScr();
   
   // Graustufengrafik einschalten
   if (!GrayOn())
      return;
      
   // Den Sprite anzeigen
   Sprite32(50, 30, HEIGHT, &firehead[0], GrayGetPlane(DARK_PLANE), SPRT_XOR);   // Auf dem Dark Plane
   Sprite32(50, 30, HEIGHT, &firehead[HEIGHT], GrayGetPlane(LIGHT_PLANE), SPRT_XOR);   // Auf dem Light Plane
   
   // Auf Tastendruck warten
   ngetchx();
   
   // Graustufengrafik ausschalten
   GrayOff();
}


Also gut, wir sehen also einen brennenden Kopf. Dazu einige kleine Anmerkungen:

Code: Alles auswählen
   // Graustufengrafik einschalten
   if (!GrayOn())
      return;


Hier wird die Graustufengrafik aktiviert, d.h. ab hier wird permanent zwischen den Planes gewechselt. Dieses Einschalten kann auch schiefgehen. Ist das der Fall, wird FALSE als Wert zurückgegeben (und dann mit return das Programm verlassen).

Code: Alles auswählen
&firehead[0]


Was wird hier gemacht? & ist der Adressoperator. Wir übergeben der Funktion also die Adresse des ersten Elements unseres Sprite-Arrays. Die Funktion nimmt sich dann die nächsten HEIGHT Elemente ab dieser Adresse heraus. Genaus funktioniert das mit

Code: Alles auswählen
&firehead[HEIGHT]
.

Code: Alles auswählen
GrayGetPlane(LIGHT_PLANE)


Die Adresse eines Planes erhaltet ihr mittels der Funktion GrayGetPlane(plane), wobei das Argument das entsprechende Plane ist. Bei normaler monochromer Grafik ist dieses Argument meistens LCD_MEM, aber wenn die Graustufengrafik aktiviert ist, müsst ihr GrayGetPlane() verwenden.

So, ich hoffe Graustufen sind euch nun etwas weniger fremd als zuvor. Also dann:
Viel Spass beim Programmieren!

// Edit: Tastenwarte-funktion ist nun ngetchx()
"All animals are equal. But some animals are more equal than others." - George Orwell (Animal Farm)

boolsoft - software development for texas instruments 68k calculators
Benutzeravatar
saubue
Administrator
Administrator
 
Beiträge: 1434
Registriert: 11. März 2005 13:55
Wohnort: Freiburg im Breisgau

Re: Graustufengrafiken mit TIGCC

Beitragvon Crattely am 24. April 2012 20:37

Für was stehen denn die riesigen Zahlenkolonnen hinter Dark_Plane und Light_Plane ?
Crattely
Mobi Newbie
Mobi Newbie
 
Beiträge: 6
Registriert: 24. April 2012 17:40

Re: Graustufengrafiken mit TIGCC

Beitragvon Kevin Kofler am 29. April 2012 23:44

Für die Sprite-Daten, genauer, für die gesetzten und nicht gesetzten Pixel, hier der Kompaktheit in Hexadezimal kodiert.

Wenn du die Hex-Zahlen in Binär umrechnest:
0x0=0b0000
0x1=0b0001
0x2=0b0010
0x3=0b0011
0x4=0b0100
0x5=0b0101
0x6=0b0110
0x7=0b0111
0x8=0b1000
0x9=0b1001
0xA=0b1010
0xB=0b1011
0xC=0b1100
0xD=0b1101
0xE=0b1110
0xF=0b1111
und nach jeder Zeile des Sprites auch einen Zeilenumbruch setzt, dann kannst du das Sprite evtl. sogar erkennen (1 ist schwarz, 0 ist weiß).

In Graustufen gilt (da der dunkle Plane doppelt so lange angezeigt wird als der helle):
im dunklen und im hellen Plane 1 = schwarz (3/3 der Zeit schwarz)
im dunklen Plane 1, im hellen Plane 0 = dunkelgrau (2/3 der Zeit schwarz)
im dunklen Plane 0, im hellen Plane 1 = helllgrau (1/3 der Zeit schwarz)
im dunklen und im hellen Plane 0 = weiß (0/3 der Zeit schwarz)
Kevin Kofler, TIGCC Team
Benutzeravatar
Kevin Kofler
Moderator
Moderator
 
Beiträge: 1432
Registriert: 16. März 2007 23:54
Wohnort: Wien, Österreich


Zurück zu ASM/C Tutorials

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste

cron