Surfaces voor beginners

Moeilijkheidsgraad: kennis van GML en draw-events
Geschikt voor: Elke versie van GM die surfaces ondersteunt (100% zeker van Game Maker7, 8 en 6 zal ook wel hebben maar niet zeker)



Wat zijn surfaces?
Surfaces kun je zien als een soort van sprite. Met uitzondering dat je op een surface dingen kunt tekenen in het spel zelf. Dit kan als voorbeeld hebben dat je in het begin de schaduwen berekend en deze in een surface zet en vervolgens draw je de surface gewoon zonder elk lang en ingewikkeld draw-event te herhalen (dat ook nog veel geheugen vreet).

Surfaces zijn een eenvoudige oplossing hiervoor maar ik kon geen tutorial over surfaces vinden dus maakte ik er zelf eentje.

Goede voorbeelden voor surfaces:

  • Mini-map
  • Schaduwen en licht (wordt uitgelegd in deze tutorial)
  • Fog of War (zodat je niet verder kunt zien dan je neus lang is bij RTS's :P)
  • Door de gebruiker getekende dingen (zoals characters)
  • Andere dingen die moeilijk zijn om te drawen en (die zouden kunnen) zorgen voor een vertraging (fps-drop)


De basis
Maak een nieuw project aan in Game Maker en maak hierin een object en een room (zet alvast dat ene object al in de room). Ga naar het create-event van het object en plaats onderstaande code...


surf = surface_create(room_width,room_height);
 
Deze code maakt een surface aan ten groote van de room (room_width is de breedte van de room en room_height de hoogte van de room) en slaagt zijn unieke id op in de variabele surf. Deze hebben we later nog nodig voor daadwerkelijk iets te tekenen.

We gaan een dradenspel met de muis maken en elke step voegen we een lijntje toe aan de surface... Zet verder nog in het create-event dit:


prevmousex = mouse_x;
prevmousey = mouse_y;
 


Ga vervolgens naar het step-event.


surface_set_target(surf); //We zetten het tekenen aan op de surface
draw_set_color(c_black); draw_set_alpha(0.5); //Even wat waardes aanduiden: de kleur en de alpha
draw_line(mouse_x,mouse_y,prevmousex,prevmousey); //We tekenen een lijntje van de huidige muiswaardes naar de vorige
draw_set_alpha(1); //Alpha terug naar 1 zetten
surface_reset_target(); //En we zorgen ervoor dat we terug normaal kunnen tekenen

//De waardes van de muis opslaan voor de volgende keer
prevmousex = mouse_x;
prevmousey = mouse_y;
 


Vergeet vervolgens niet om deze code aan het draw-event toe te voegen!

draw_surface(surf,0,0);


We tekenen met deze code de eerder gemaakte surface op de positie x en y. Aangezien we eerder al gezegd hebben dat de surface even groot is als de room kun je nu "tekenen" met lijntjes :)

Beknopt

Met surface_create(); maken we een surface aan.
Met surface_set_target(); zetten we de target op een surface
Met draw_...(); tekenen we iets op de huidige target
surface_reset_target(); zorgt ervoor dat je terug normaal kunt drawen
draw_surface(); tekent de surface.

Je kunt al deze actie's zetten waar je maar wilt behalve de laatste. Die moet in het draw-event (net zoals elke andere draw-actie).

Gebruiken om licht mee te berekenen

Als je realtime licht in je spel wilt is het gebruik van een surface een goed idee. Je hebt hiervoor slechts een enkele code voor nodig:


var surf, w, h;
w = 640
h = 480

//We maken een surface aan en we zetten deze direct als target
surf = surface_create(w,h);
surface_set_target(surf);

//We tekenen een grijs veld. Zodat we later de verlichte plaatsen kunnen verlichten
draw_set_color(c_gray);
draw_rectangle(0,0,w,h,0);
draw_set_color(c_white);

//We zetten de blend-mode op substract. [1]
draw_set_blend_mode(bm_subtract);

//We gaan rekening houden met de lampen :P
with (obj_lamp) {draw_circle_color(x,y,radius,kleur,c_black,0); }

//We neutraliseren de target
surface_reset_target();

//Teken de surface
draw_surface(surf,0,0);

//We zetten de blendmode op normaal
draw_set_blend_mode(bm_normal);

//We verwijderen de surface
surface_free(surf);
 


Je kunt ook dit alles in het step-event zetten (maar dan draw_surface() in het draw-event en surface_free() wegdoen. Maar dan is het niet realtime meer.
Net omdat we alles op een surface drawen worden bepaalde actie's niet met alle pixels gedaan maar enkel met de pixels die op de surface staan.

Probeer als oefening zelf een spel te maken dat geen real-time schaduwen heeft. Als je dit kunt begrijp je surfaces helemaal :)

Meer informatie

In de handleiding van Game Maker zit een Engelstalige uitleg over Surfaces. Er is ook een Nederlandse versie beschikbaar maar daar noemen ze het oppervlakten (het correcte Nederlandse woord eigenlijk). [link]

Wat als ik de surface niet meer nodig heb?
Als je surfaces niet meer nodig hebt is het het beste om ze uit het video-geheugen te plaatsen. Daarvoor is een simpele functie gemaakt:


surface_free(surf);
 


Waarbij surf staat voor de id die meegegeven is aan de surface.

Wat kan? Wat kan niet?

Vrij overgenomen van de eerder genoemde handleiding + verbeterd door MatreBatre
  • Je mag het "target" niet veranderen in de draw event. Hierdoor krijg je problemen met de projectie en views. Soms kan je dit tegengaan met de functie d3d_set_projection_ortho maar dat werkt niet in alle gevallen.
  • Je kan geen surfaces gebruiken in 3D. Bij het aanroepen van d3d_start of d3d_end worden alle surfaces verwijderd. Er bestaat wel een DLL genaamd "Surface Fix" waarmee het wel mogelijk is om surfaces te gebruiken in 3D, onder bepaalde voorwaarden.
  • Surfaces worden verwijderd wanneer sommige fullscreen-processen starten, bv wanneer de speler ctrl+alt+delete gebruikt of de screensaver verschijnt. Daarom kan je best in de step event controleren of een surface nog bestaat (met surface_exists) en hem opnieuw aanmaken als dat niet het geval is. Als je dat niet doet zal je errorberichten krijgen omdat je een surface probeert te gebruiken die niet bestaat.
  • Surfaces worden niet opgeslagen als een spel wordt opgeslagen.


[1]. Meer informatie over Blendmodus kun je hier vinden. [link]

Reactie's op Surfaces voor beginners

Nog geen reactie's op Surfaces voor beginners.

Geef een reactie op Surfaces voor beginners


Naam*
E-mail
Website:
Reactie*
Maximum 4000 tekens
Captcha*


* = verplicht