Een paar algemene vuistregels:
De inhoud van een if-statement moet tussen {accolades}. Bij maar één statement mag je die weglaten. Ik adviseer dat niet te doen. Zo zie je sneller wat bij elkaar hoort, en hoef je er niet aan te denken als je een tweede statement bijvoegt.
Om aan te geven wat onderdeel is van wat, laten we code inspringen. Regels tussen een “ {” en een “ ” begint een kolom verder naar rechts.
Zo zie je snel welke haakjes bij elkaar horen.
1 2 3 4 5 6 7 8 9 10 11 12 13 | if instance_exists(enemy) { with enemy { if y > 400 { if gravity > 0 { vspeed = 0; } else { vspeed += 0.01; } } hspeed += 0.1; } } |
In dit voorbeeld horen regels 2 en 12 bij elkaar. Dat kun je snel zien, want ze beginnen op dezelfde kolom.
Gebruik vorm om de inhoud te structureren, zoals in een gedicht. Als je dat niet doet ...
1 2 3 4 5 6 7 | b=0; for (i=1;i<=15;i+=1){ if real(argument[i])=0{break;}else{b+=1;}} a=ceil(random(argument0-b)); for (i=1;i<=b;i+=1){ if a>=argument[i]{a+=1}} return a; |
... ontstaat een brij van tekens zonder structuur. Neem dus de tijd om het te ordenen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | b = 0; for (i = 1; i <= 15; i += 1) { if real(argument[i]) = 0 { break; } else { b += 1; } } a = ceil(random(argument0 - b)); for (i = 1; i <= b; i += 1) { if a >= argument[i] { a += 1; } } return a; |
Zo zie je de structuur en de afzonderlijke onderdelen beter.
Alle ingebouwde woorden zijn al in het Engels. Als je alles in het Engels doet lijkt het het meest op mensentaal. Bovendien kunnen dan buitenlandse programmeurs het ook lezen, mocht dat ooit nodig blijken.
Zorg dat alles een naam heeft die beschrijft wat het is. Dus niet zo:
1 2 3 4 5 6 | if a > 0 { with en01 { compute(xd, yd); } a = 0; } |
maar zo:
1 2 3 4 5 6 | if enemies_killed_count > 0 { with flyingenemyobject { enemy_compute_shortest_path(xgoal, ygoal); } enemies_killed_count = 0; } |
Zo beschrijft de code zichzelf.
Gebruik een standaard-naamgevingsschema met voorvoegsels en achtervoegsels om om dingen te groeperen en dubbele namen te voorkomen.
Verder gebruik ik voor objecten nog deze regel:
Dus het object menu omdat er maar één menu is, en het object menubuttonobject omdat er meerdere menubuttons zijn. De naam menubutton blijft dan beschikbaar als variabelenaam, bijvoorbeeld var menubutton = instance_nearest(mouse_x, mouse_y, menubuttonobject);.
Als een variabele alleen aan of uit kan zijn, gebruik dan true en false in plaats van 0 en 1, zodat je kan zien dat het geen andere waarden kan hebben.
Als een variabele een instantie-id bevat, gebruik dan noone voor géén instantie. Dan kun je meteen aflezen dat deze variabele instantie-id’s bevat.
Voor strings, gebruik "" als standaardwaarde.
Bedenk een passende standaardwaarde voor variabelen, die past bij het waardenbereik.
Als een variabele een string is, zorg dat die altijd een string is. Op die manier is het type steeds duidelijk. Uitzondering is de speciale waarde undefined die je mooi kunt inzetten als standaardwaarde voor allerlei dingen en de functie is_undefined kan gebruiken.
Constanten als fa_centeren c_red bevatten getallen, maar met deze woorden wordt je code beter leesbaar. Gebruik dit idee ook voor je eigen getallen. Heb je drie wapens, maak dan drie constanten aan, en gebruik die overal. De getalswaarde is dan helemaal niet belangrijk.
1 2 3 4 5 | switch current_weapontype { case weapontype_shotgun: /*do something*/; break case weapontype_minigun: /*do something*/; break case weapontype_flamethrower: /*do something*/; break } |
Het is ook handig om een weapontype_none te maken voor “geen wapen”.
Als je je wapentypevariabele weapontype noemt, is het handig om alles dat te maken heeft met wapentypes, weapontype te noemen en niet later ineens wp of weapon.
1 2 3 4 5 | switch current_weapontype { case weapontype_shotgun: /*do something*/; break case weapontype_minigun: /*do something*/; break case weapontype_flamethrower: /*do something*/; break } |
De volgende twee doen hetzelfde als foo een boolean variabele is:
De volgende twee zijn ook inwisselbaar:
Computertalen hebben de neiging steeds beter op normaal Engels te lijken. Het ligt dus voor de hand om voor de logische operatoren de Engelse varianten te gebruiken:
Voor de bitsgewijze operatoren |, & en ^ zijn dergelijke alternatieven er niet.
Voeg comments toe waar nodig, maar niet meer dan dat. Te veel comments is ook niet handig. Handige comments zijn:
1 2 | //point_line_distance(x, y, p, q, s, t) //returns the distance from (x, y) to line (p, q)-(s, t). |
Voeg geen commentaren toe die alleen de code vertalen.
1 | instance_create(320, 240, enemyobject); //create the enemy |
Het commentaar zegt niets dat niet al in de code staat, maar voegt wel meer tekst toe. Hou deze vuistregel aan: de code vertelt hoe, het commentaar vertelt waarom.
Begin elk event met ///Omschrijving hier op de eerste regel. Je omschrijving verschijnt dan in de actielijst.
Als je code aanpast, en er staat commentaar bij, verander dat commentaar dan ook. Anders klopt het misschien niet, en verkeerd commentaar is nog erger dan géén commentaar.
Zorg dat je alleen de verticale scrollbalk nodig hebt.
Als regels te lang worden, dan raad ik aan om ze op logische plaatsen af te breken. Bij lange functieaanroepen kun je elk argument op een aparte regel zetten, bijvoorbeeld zo:
1 2 3 4 5 6 | var dist = point_distance( controllerobject.node_x[controllerobject.edge_b[e]], controllerobject.node_y[controllerobject.edge_b[e]], controllerobject.node_x[controllerobject.edge_e[e]], controllerobject.node_y[controllerobject.edge_e[e]] ); |
Op deze manier gebruik je de haakjes net zoals je accolades gebruikt.
Maak scripts waar het kan. Dan kun je het een (beschrijvende) naam geven en dat maakt het overzicht groter. Het advies is om al een script te maken zodra je een berekening twee keer of vaker nodig hebt.
De variabelenamen argument0 etc. zijn weinig beschrijvend. Als je argument een instantie is, begin dan met var inst = argument0; zodat je de beschrijvende naam inst kunt gebruiken.
1 2 3 4 5 6 7 8 | var ind = argument0; var dist = point_distance( x1[ind, count[ind]], y1[ind, count[ind]], x2[ind, count[ind]], y2[ind, count[ind]] ) + margin[n]; var box_xdiff = abs(box_x2[ind] - box_x1[ind]) / dist; var box_ydiff = abs(box_y2[ind] - box_y1[ind]) / dist; |
Zet niet te veel code in één actie, maar deel die op in logische stukken en geef elk stuk een duidelijke omschrijving. Dan krijg je overzicht over wat er gebeurt in een event, en kun je makkelijker stukken verwisselen.
Pas in de Preferences de syntaxismarkering aan naar je voorkeuren, zodat je dingen snel kan terugvinden.