ATLAS: (BIJNA ALLE) INTERNE GEHEIMEN! Programmeren is terug van 'weg-geweest'. Wat lang het exclusieve domein was van professionals of freaks ligt sinds een paar jaar binnen het bereik van elke serieuze gebruiker en dat hoeft geen verslaafde te zijn. WERKING 1. Het programma detecteert de muis en de grafische schermdriver. Is er geen muisdriver geladen dan wordt op cursorbesturing overgeschakeld. De Cursorbesturing is overigens niet feilloos!! Er volgt een korte instructie. 2. Het scherm wordt opgebouwd en in het geheugen opgeslagen. Dat ge- beurt in 3 delen, want de variabele die de gegevens bevat mag niet groter zijn dan 64K. 3. De ko”rdinaten waar zich de muis (of de cursor) bevindt worden uitgele- zen en al naar gelang de uitkomst wordt er vanuit het hoofdmenu een ak- tie ondernomen. 4. Het menu OPTIES biedt twee speelmogelijkheden: aanwijzen of puzzelen. 5. Het menu INFO geeft informatie over de gekozen speelmogelijkheid. 6. Als wij de kaart van Nederland aanwijzen, dan wordt die snel getekend en er worden 25 records uit de file NEDERLND.GEO gelezen. Allemaal op het gekozen niveau of lager, maar verder in willekeurige volgorde. De 25 namen uit die records worden op het scherm in een kolom geplaatst. 7. Intern wordt de stopwatch gestart en steeds als er op de linkermuisknop is geklikt wordt de positie van de muis vergeleken met de ko”rdinaten uit het record dat aan de beurt is. Als alle opgegeven namen zijn aangewezen wordt de score berekend en de prestatie vergeleken met de prestaties die tot nu toe waren vastgelegd. Als er nog niet eerder met het programma was gewerkt, dan kunnen de eerste tien spelers hun naam invoeren. Als de elfde beter is dan een van de eerste tien, dan zal nummer tien afvallen: de gegevens (naam en puntental) verdwijnen. 8. Wordt er tijdens een spel of een menu op de rechtermuisknop (of op ESC bij cursorbesturing) gedrukt, dan keert het programma terug naar het hoofdmenu. TURBO-PASCAL De voorbeelden in dit artikel zijn in TURBO-PASCAL. Ervaren programmeurs in Basic of C kunnen zelf bedenken hoe de voorbeelden in hun taal zouden luiden. Kent u geen enkele programmeertaal, dan komt u met een paar Engelse woorden (repeat until, begin end, enz.) al een heel eind op weg. In de voorbeelden zit geen verdere hocus-pocus. ALLES INBOUWEN EN AUTOMATISCH DETECTEREN Het doel van de programmeur was ambitieus: hij wilde een educatief spel maken dat op alle MS-DOS computers zou kunnen werken: met of zonder muis, met of zonder kleurenscherm en automatisch omschakelend naar zoveel mogelijk verschil- lende schermen: CGA, HERCULES, EGA-VGA, ATT400 en PC3270. TURBO-PASCAL wordt geleverd met drivers voor deze schermen. In de handleiding is te vinden hoe je die drivers in het programma kunt inbouwen, zodat er geen externe files nodig zijn. Kort gezegd komt het hierop neer: Alle grafische drivers (*.BGI) worden met BINOBJ.EXE omgezet in *.OBJ files. Die *.OBJ files worden in het programma gelinkt en binnen het programma ge- registreerd v˘˘rdat INITGRAPH wordt aangeroepen. Dat werkt als volgt: procedure EgaVgaDriverProc; external; {$L EGAVGA.OBJ } procedure HercDriverProc; external; {$L HERC.OBJ } De stukjes tussen {} zijn geen commentaar, maar compilerinstructies. Nadat deze externe procedure is aangeroepen kan met RegisterBGIdriver(@EGAVGADriverProc); RegisterBGIdriver(@HercDriverProc); InitGraph(Gdriver,Gmode); de goede schermdriver worden ge‹nitialiseerd. Wie dit zelf eens wil proberen kan het door BORLAND met de compiler meegele- verde voorbeeld GRLINK.PAS bestuderen. Het programma wordt groter, maar overzichtelijker en de gebruiker komt niet voor verrassingen te staan als: 'Device driver file not found'. KAARTEN IN KLEUR Het meest opvallende detail aan het programma ATLAS zijn de acht kaartjes. Hoe komen die in het programma? Eerst is geprobeerd om de landkaarten met een scanner en met een digitaal fototoestel in het programma te krijgen. Dat mislukte, omdat een flink kaartje in kleur op de disk wel zo'n 100K neemt. Toen groeide het idee niet het hele kaartje op te slaan, maar slechts de handelingen die nodig zijn om het kaartje te tekenen. Het eenvoudigste tekenprogramma dat te bedenken was, voldeed voor dit doel. Het werkt zo: el- ke keer als er op de muisknop wordt gedrukt, worden de ko”rdinaten van de muis in een array geplaatst. program TEKENEN var Tekenarray : array[1..3500] of word; Stoppen, MuisKnopGedrukt : boolean; {er zijn uiteraard nog zo'n 30 andere minder belangrijke variabelen} begin SchermOpbouwen; {o.a. RegisterBGI en MouseInit} Stoppen := false; repeat {begin eerste lus} repeat {begin tweede lus} LeesMuis; {leest DOS-record REGISTERS BX, CX en DX uit} until MuisKnopGedrukt; {eind tweede lus} ZetKo”rdinaten_in_TekenArray; {subroutine die de getallen vastlegt} until stoppen {eind eerste lus} end. Vanzelfsprekend moesten de programmadelen LeesMuis en ZetKo”rdinaten_in_Te- kenarray ook gemaakt worden, maar de idee‰n daarvoor staan in de goede computer- boeken. AAN HET WERK: Het tekenen gaat zo: we starten het tekenprogramma en we plakken een trans- parant landkaartje (overheadsheet) op de beeldbuis van de monitor. In minder dan 20 minuten wordt dat kaartje met de muis 'overgetrokken'. Ama- teuristisch, die overheadsheets? Misschien, maar het resultaat mag er zijn. Op deze manier is het mogelijk acht gedetailleerde kaarten op te slaan in 28K! Dat is minder dan 4% van de omvang die voor acht complete pixel-geori‰n- teerde plaatjes (VGA) nodig zou zijn geweest! Iedere keer als tijdens het te- kenen op de muisknop wordt geklikt, zet de procedure ZetKo”rdinaten de X- en Y-waarde van de muis in de array. In de X- waarde wordt ook de aktie (lijn- type, kleur enz.) opgeslagen. Die TekenArray wordt later door de procedure PLOTKAART weer in een kaartje omgezet. procedure PLOTKAART; begin Teller := 1; repeat Ko”rdinaat_1 := TekenArray[teller]; {de X-Ko”rdinaat ophalen} Aktie := trunc(Ko”rdinaat_1/1000); {Aktie afleiden uit X-Ko”rdinaat} Ko”rdinaat_1 := TekenArray[teller]-Aktie*1000; {Nog een keer Ko”rdinaat_1 ophalen en Aktie daaruit 'lospellen'} Ko”rdinaat_2 := TekenArray[teller+1]; {de Y-Ko”rdinaat} inc(teller,2); {Teller ophogen met 2} Doe(Aktie,Ko”rdinaat_1,Ko”rdinaat_2); {Onderaannemer van PLOTKAART, zie beneden} until EindeArray; {EindArray is een boolean die true wordt als de TekenArray verder} {uit ongebruikte nullen bestaat} end; Dat 'lospellen' vraagt nog wat uitleg: komen er uit de TekenArray bijv. de ge- tallen 1600, 500 te voorschijn, dan worden die ontleed tot 1, 600, 500. Het eerste getal geeft de aktie aan. Die drie getallen worden dan aan de procedu- re Doe 'gevoerd'. Dat is in dit voorbeeld: vullen (in een bepaalde stijl) op ko”rdinaat 600, 500. Maar als mijn scherm nou geen ko”rdinaat 600,500 heeft? Geen nood, deze getallen zijn geen absolute waarden, maar relatieve. OMREKENEN Deze relatieve ko”rdinaten worden omgerekend naar absolute en dat verlost ons van de nachtmerrie die ontstaat door de lengte/breedte verhoudingen van de ver- schillende schermen. De eenvoudigste oplossing voor dit probleem bleek veruit de beste! Steeds als er X- en Y-waarden uit de array worden gehaald, worden ze door funktie X en funktie Y omgerekend voor het scherm dat op dit moment in gebruik is. IJkpunten zijn daarbij de funkties GetMaxX en GetMaxY. function X(BREEDTE : integer) : integer; begin X := round(BREEDTE/1000 * GetMaxX); end; function Y(HOOGTE : integer) :integer; begin Y := round(HOOGTE/1000 * GetMaxY); end; Een voorbeeld: X(500) op VGA: 500/1000 x 640 = 320 X(500) op HERC: 500/1000 x 720 = 360 In beide gevallen is dat precies het midden! Veel rekenwerk? Welnee, een computer is geen mens: luiheid kent hij niet. Tenslotte: hoe het in de procedure DOE kolkt en bruist; wat een oerkracht! procedure DOE(Aktie,Ko”rdinaat_1,Ko”rdinaat_2); begin case Aktie of 1..11 : begin SetFillStyle(Aktie,GetColor); FloodFill(X(Ko”rdinaat_1),Y(Ko”rdinaat_2),GetColor); end; 12 : LineTo(X(Ko”rdinaat_1),Y(Ko”rdinaat_2)); {enz. enz. verder nog zo'n 20 akties mogelijk} end; end; DE FILES MET OPDRACHTEN Het programma werkt met acht files met opdrachten. Deze files hebben de extensie *.geo. De files bestaan uit een keten van records die een plaats- naam en wat getallen bevatten. De type-definitie van dat record (32 bytes) ziet er zo uit: type PLEK = record NAAM : string[20]; PlekX,PlekY,TekstX,TekstY : word; {Ko”rdinaat v. plaats en naam} Symbool,Tolerantie,niveau : byte; end; Het niveau wordt ook in dit record vastgelegd. Afrika is niveau 1, Timboek- toe niveau 6. De tolerantie hangt af van de aard van het aan te wijzen object. Terschelling heeft een grote horizontale tolerantie en het Kanaal door Zuid Beveland een kleine! TOEKOMST Dit programma kan snel voor andere toepassingen worden aangepast. Als er in plaats van kaarten andere tekeningen worden opgenomen, dan is al snel een leesprogramma voor kinderen of een of ander presentatieprogramma te maken voor een museum of bedrijf. BRONCODE In dit artikel zijn de hoofdlijnen van ATLAS duidelijk gemaakt. Wie zelf aan het werk wil, kan de BRONCODE (van VERSIE 2.1 ong. 250Kb incl. kaarten) bestellen. Tjitte Dijkstra, Van Heemskercklaan 75 3843 XP Harderwijk