<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bgie</title>
    <description>The latest articles on DEV Community by Bgie (@bgie).</description>
    <link>https://dev.to/bgie</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1060193%2F4f6889c5-425b-4b9b-90f3-a36ff8913852.png</url>
      <title>DEV Community: Bgie</title>
      <link>https://dev.to/bgie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bgie"/>
    <language>en</language>
    <item>
      <title>Een beat-em-up game maken met Godot - health</title>
      <dc:creator>Bgie</dc:creator>
      <pubDate>Fri, 16 Jun 2023 19:03:46 +0000</pubDate>
      <link>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-health-b8d</link>
      <guid>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-health-b8d</guid>
      <description>&lt;p&gt;Terug naar &lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-7-1h1l"&gt;deel 7&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Onze speler is nog onsterfelijk, maar dat willen we niet. We gaan hem een beperkt aantal levens geven. &lt;/p&gt;

&lt;p&gt;In het player.gd script voegen we helemaal vanboven (na de &lt;code&gt;extends CharacterBody2D&lt;/code&gt;) toe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;health_points&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wat wil dit zeggen? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;var&lt;/code&gt; hebben we al gebruikt en betekend: maak een variabele.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;health_points&lt;/code&gt; is de naam de we hebben gekozen voor de variabele.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;: int&lt;/code&gt; zegt dat onze variabele altijd een integer is (geheel getal zonder komma). Als we ons vergissen in de code, gaat Godot ons waarschuwen. Dit is een hulpmiddel.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;= 3&lt;/code&gt; is de start waarde, onze speler begint met 3 levens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We gaan deze variabele nu gebruiken in onze &lt;code&gt;take_damage()&lt;/code&gt; functie. Die zou er nog zo uit moeten zien:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HURT&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hurt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Die code zorgt enkel voor de juiste animatie als de speler geraakt wordt. We willen nu dat een aanval een leven kost.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;health_points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;health_points&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HURT&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hurt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De nieuwe code doet een eenvoudige berekening. De nieuwe &lt;code&gt;health_points&lt;/code&gt; (links) wordt gelijk aan de oude &lt;code&gt;health_points&lt;/code&gt; min 1. &lt;br&gt;
Dus iedere keer als we in &lt;code&gt;take_damage()&lt;/code&gt; komen gaat de speler 1 leven minder krijgen.&lt;/p&gt;

&lt;p&gt;We voegen nog een stukje voorlopige code toe, om nu snel te kunnen testen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;health_points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;health_points&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;health_points&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue_free&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HURT&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hurt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Als de &lt;code&gt;health_points&lt;/code&gt; zijn verminderd tot nul, laten we de speler verdwijnen met &lt;code&gt;self.queue_free()&lt;/code&gt;, zoals bij de vijand. We gaan dadelijk een beter einde maken, maar deze code kunnen we nu al testen.&lt;/p&gt;

&lt;p&gt;Het is vaak een goed idee je code in kleine stapjes aan te passen, en telkens te testen of het werkt. Schrijf je honderden regels ineens, zonder testen, dan kom je voor verrassingen te staan wanneer je het uiteindelijk wil testen. Dan is het moeilijker om de fout te vinden, tussen die honderden regels.&lt;/p&gt;

&lt;p&gt;Dit is ons resultaat:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sakTCh5i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9qzv6oyeay4pq0s12g93.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sakTCh5i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9qzv6oyeay4pq0s12g93.gif" alt="Player death gone animation" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wat we eigenlijk willen, is een death animation zoals bij de vijand. Daarvoor voegen we nog een state toe: &lt;code&gt;DYING&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ATTACK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HURT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DYING&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onze &lt;code&gt;take_damage()&lt;/code&gt; wordt ook uitgebreid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DYING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="n"&gt;health_points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;health_points&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;health_points&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DYING&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"die"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HURT&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hurt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wat veranderd er?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we starten met een &lt;code&gt;if&lt;/code&gt; en een &lt;code&gt;return&lt;/code&gt;, want als de speler al dood gaat, is een nieuwe &lt;code&gt;take_damage&lt;/code&gt; niet meer nodig. &lt;code&gt;return&lt;/code&gt; zorgt dat we onmiddellijk uit de functie gaan, de rest van de code wordt overgeslagen.&lt;/li&gt;
&lt;li&gt;de tijdelijke &lt;code&gt;self.queue_free()&lt;/code&gt; vervangen we. We zetten onze state op &lt;code&gt;DYING&lt;/code&gt; en starten de juiste animatie &lt;code&gt;"die"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;de laatste &lt;code&gt;if&lt;/code&gt; wordt een &lt;code&gt;elif&lt;/code&gt;. Enkel als de eerste &lt;code&gt;if&lt;/code&gt; niet waar is, gaan we deze tweede &lt;code&gt;elif&lt;/code&gt; doen. &lt;code&gt;DYING&lt;/code&gt; heeft voorrang op &lt;code&gt;HURT&lt;/code&gt; (staat eerst), en als de speler dood gaat doen we nooit een &lt;code&gt;HURT&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Er komt nog 1 regel bij in &lt;code&gt;_on_animated_sprite_2d_animation_finished&lt;/code&gt;. &lt;br&gt;
De huidige code dient om na een &lt;code&gt;ATTACK&lt;/code&gt; of een &lt;code&gt;HURT&lt;/code&gt; terug naar de gewone &lt;code&gt;READY&lt;/code&gt; te gaan, zodat we niet eeuwig blijven aanvallen of hurten.&lt;/p&gt;

&lt;p&gt;Maar dood gaan is wel redelijk definitief... De nieuwe code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_animated_sprite_2d_animation_finished&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DYING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enkel voor states verschillend van &lt;code&gt;DYING&lt;/code&gt; zetten we de state terug op &lt;code&gt;READY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Het resultaat:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RgQwksqf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j00wtotf6zvza0fyn75p.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RgQwksqf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j00wtotf6zvza0fyn75p.gif" alt="Player death animated" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;... en onze zeer enthousiaste vijand blijft lekker doormeppen!&lt;/p&gt;

&lt;p&gt;Wat er nu nog ontbreekt aan ons player health systeem, is een manier om te tonen hoeveel levens de speler nog heeft.&lt;/p&gt;

&lt;p&gt;Daarvoor maken we een HUD (heads-up-display). Dit is een vaste laag bovenop alle graphics van de game wereld, die nooit met de camera mee beweegt. We willen linksboven in het scherm met een reeks hartjes tonen hoeveel levens de speler nog heeft.&lt;/p&gt;

&lt;p&gt;We maken een nieuwe scene voor onze HUD. Klik met de rechtermuisknop op &lt;code&gt;res://&lt;/code&gt; in het &lt;code&gt;FileSystem&lt;/code&gt; paneel en kies &lt;code&gt;New&lt;/code&gt; en &lt;code&gt;Scene&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t_6s0AXU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bh8d3oij9o0s2pgmz1rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t_6s0AXU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bh8d3oij9o0s2pgmz1rg.png" alt="Add new scene" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vervolgens kiezen we als node type &lt;code&gt;CanvasLayer&lt;/code&gt; en we geven ook de naam 'HUD' aan onze scene.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s----mloN1---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ndf35uiqjcnvqydr5fln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s----mloN1---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ndf35uiqjcnvqydr5fln.png" alt="Create new CanvasLayer scene" width="520" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We krijgen nu een nieuwe scene, gelijkaardig aan onze andere scenes. Het verschil tussen een &lt;code&gt;CanvasLayer&lt;/code&gt; en onze andere scenes, is dat de &lt;code&gt;CanvasLayer&lt;/code&gt; NIET beïnvloed wordt door de camera. Dit is nu van geen belang, omdat we de camera (nog) niet verschuiven in onze game. Maar doen we dit later wel, dan willen we dat onze HUD op een vaste plaats in het scherm blijft staan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wlBke39g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/84jojb0865ro5pg4ovt5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wlBke39g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/84jojb0865ro5pg4ovt5.png" alt="Image description" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bij onze graphics zitten nog geen hartjes. Maar je kan gemakkelijk &lt;code&gt;png&lt;/code&gt; afbeeldingen van het web gebruiken in je game. &lt;/p&gt;

&lt;p&gt;Maak eerst een aparte map bij je assets. Je kan met rechtermuisknop klikken op de 'assets' map en via &lt;code&gt;New&lt;/code&gt; en &lt;code&gt;Folder&lt;/code&gt; een nieuwe map maken die we 'HUD' gaan noemen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AD5zkn2I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aeff6ma171jlu2ssie5n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AD5zkn2I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aeff6ma171jlu2ssie5n.png" alt="Add new folder to assets" width="605" height="745"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De nieuwe map komt onder je assets te staan:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qtSFqy6v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3b7ueodtc8xo72m0rzdy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qtSFqy6v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3b7ueodtc8xo72m0rzdy.png" alt="new hud folder" width="254" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dit is het hartje dat we gaan gebruiken:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BLTECSnO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fbqq67adzwivl897t6h3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BLTECSnO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fbqq67adzwivl897t6h3.png" alt="Heart" width="120" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Afhankelijk van je web browser is dit iets verschillend, maar meestal kan je rechts klikken en is er een &lt;code&gt;save image as&lt;/code&gt; optie. Verander de naam naar iets duidelijker zoals 'heart.png'. Je kan de naam ook veranderen vanuit Godot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vchCUdU3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gg9afx69xkoweisn6c68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vchCUdU3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gg9afx69xkoweisn6c68.png" alt="Heart.png asset" width="251" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nu gaan we de hartjes toevoegen aan onze scene.&lt;br&gt;
Zorg dat de 'HUD' &lt;code&gt;node&lt;/code&gt; is geselecteerd in je scene en klik de grote plus &lt;code&gt;+&lt;/code&gt; om een node toe te voegen. We kiezen voor een &lt;code&gt;TextureRect&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o9PcF86N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bxslrqq6wbcfa0pwlt72.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o9PcF86N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bxslrqq6wbcfa0pwlt72.png" alt="Add texture rect node" width="800" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We veranderen de naam van onze &lt;code&gt;TextureRect&lt;/code&gt; naar 'Hearts', en voegen een &lt;code&gt;Texture&lt;/code&gt; toe. We kiezen &lt;code&gt;load&lt;/code&gt; en zoeken onze 'hearts.png' in de 'assets/HUD' map.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vpObsx81--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u0uq6yzo0yylg236d0v3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vpObsx81--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u0uq6yzo0yylg236d0v3.png" alt="Rename texture rect etc" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dit levert ons 1 hartje op:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QS29Hfq1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xbqlem8zwzlms7ad09bc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QS29Hfq1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xbqlem8zwzlms7ad09bc.png" alt="Single heart" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Er zijn meerdere manieren om nu meerdere hartjes te krijgen. Het ligt voor de hand om simpelweg meerdere &lt;code&gt;TextureRect&lt;/code&gt; nodes te maken. Maar we gaan een truc gebruiken, waarbij we de grafische kaart al het werk laten doen. De grafische kaart kan zonder veel moeite een texture herhalen, dat is iets wat bijvoorbeeld in 3D games voortdurend gebruikt wordt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--msN2yBWK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uml319sjfroh90ji1qon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--msN2yBWK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uml319sjfroh90ji1qon.png" alt="Tile heart texture" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We veranderen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Expand Mode&lt;/code&gt; naar &lt;code&gt;Ignore Size&lt;/code&gt;. De grafische kaart negeert de vaste afmetingen van het hartje .&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Stretch Mode&lt;/code&gt; zetten we op &lt;code&gt;Tile&lt;/code&gt;. De grafische kaart gaat de afbeelding 'tegelen' (=herhalen).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Custom Minimum Size&lt;/code&gt; wordt &lt;code&gt;x=360&lt;/code&gt; en &lt;code&gt;y=90&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Het hartje zelf is 120x90 pixels groot. Omdat we tegelen  opzetten en vragen om een gebied van &lt;code&gt;360x90&lt;/code&gt; op te vullen, gaat de grafische kaart het hartje meermaals tekenen om het gevraagde gebied op te vullen. 360 is 3 x 120, we krijgen 3 hartjes.&lt;/p&gt;

&lt;p&gt;Wat we nu nog gaan doen, is de hartjes in de linkerbovenhoek plaatsen, met een kleine marge zodat ze niet helemaal tegen de rand van het scherm plakken.&lt;/p&gt;

&lt;p&gt;Verander de &lt;code&gt;Anchor Preset&lt;/code&gt; naar &lt;code&gt;Custom&lt;/code&gt;. Dan krijg je extra parameters, onder &lt;code&gt;Anchor Points&lt;/code&gt;, &lt;code&gt;Anchor Offsets&lt;/code&gt; en &lt;code&gt;Grow Direction&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_RAON99v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cgy7zmgdpmfurci6d29d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_RAON99v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cgy7zmgdpmfurci6d29d.png" alt="Anchor topleft with margins" width="545" height="965"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Het systeem van anchors (anker-punten) leggen we later beter uit. Zorg nu gewoon dat de &lt;code&gt;Anchor Offsets&lt;/code&gt; voor &lt;code&gt;Left&lt;/code&gt; en &lt;code&gt;Top&lt;/code&gt; op &lt;code&gt;25 px&lt;/code&gt; staan. Daarmee zorgen we voor een afstand van 25 pixels tussen de hartjes en de linker- en bovenrand van het scherm. Kijk even na of de andere waarden (aangeduid met groen) hetzelfde zijn.&lt;/p&gt;

&lt;p&gt;De hartjes gaan lichtjes verspringen wanneer je de offsets intypt, maar verder zien we niet veel. We moeten onze HUD nog toevoegen aan de game scene. &lt;/p&gt;

&lt;p&gt;Ga naar de 'game' scene en sleep 'HUD.tscn' beneden naar de root node 'Game'. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y-uOtWmX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owrmoy560zmgkl4ltj54.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y-uOtWmX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owrmoy560zmgkl4ltj54.png" alt="drag hud onto game scene root node" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Onze hartjes verschijnen, maar staan niet linksboven! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yqpBI9Ds--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jks2qd7xi63ka8zlizas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yqpBI9Ds--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jks2qd7xi63ka8zlizas.png" alt="Hearts on scene" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dit is verwarrend, maar toch komen de hartjes juist als we het spel starten.&lt;br&gt;
Het beeld in de editor toont niet wat de camera ziet, maar wat er op de scene staat. Starten we de game, dan kijken we &lt;em&gt;wel&lt;/em&gt; door de camera.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hCHxY2c8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35brjgj4wf9rb5i6antm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hCHxY2c8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35brjgj4wf9rb5i6antm.png" alt="Run game with HUD" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nu rest er enkel nog wat code, om ook werkelijk het aantal levens van de speler te tonen in de HUD.&lt;/p&gt;

&lt;p&gt;In de 'HUD' scene selecteren we de 'HUD' root node en voegen een nieuw script toe. Dit krijgt automatisch de naam 'HUD.gd', wat prima is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---xU9-w3W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/atcve3lo6tu1mozl0w4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---xU9-w3W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/atcve3lo6tu1mozl0w4f.png" alt="Create hud script" width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Het script ziet er zo uit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CanvasLayer&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;hearts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TextureRect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;Hearts&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;set_health&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;hearts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;custom_minimum_size&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wat doen we hier? De variabele 'hearts' verwijst naar de TextureRect die onze hartjes toont. De functie &lt;code&gt;set_health&lt;/code&gt; krijgt in de parameter 'health' mee hoeveel hartjes er getoond moeten worden. We weten dat een hartje 120 pixels breed is, en als we 120 maal 'health' doen, hebben we de breedte voor onze &lt;code&gt;TextureRect&lt;/code&gt; om het juiste aantal hartjes te tonen.&lt;/p&gt;

&lt;p&gt;Dit moeten we nog verbinden met de player. &lt;br&gt;
Omdat onze player en onze HUD twee aparte scenes zijn, die niets van mekaar afweten, gaan we de verbinding leggen in onze game scene.&lt;/p&gt;

&lt;p&gt;We voegen ook een script toe aan de root node 'Game' van onze game scene.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hJDlduXS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8gufry59wwwj8hvz7qss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hJDlduXS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8gufry59wwwj8hvz7qss.png" alt="Add script to game scene root node" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De eenvoudigste code is als volgt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;Arena&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;hud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CanvasLayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;HUD&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;hud&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_health&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;health_points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We maken de variabelen 'player' en 'hud' die de juiste node opzoeken en opslaan (via het $ symbool). De functie &lt;code&gt;_process(_delta)&lt;/code&gt; wordt bij elke frame opgeroepen. Hier vragen we &lt;code&gt;player.health_points&lt;/code&gt; op en geven dit door aan onze &lt;code&gt;set_health&lt;/code&gt; functie van de HUD.&lt;/p&gt;

&lt;p&gt;Dit kan efficiënter als we player een signaal laten uitsturen enkel wanneer health_points wijzigt, maar voorlopig is dit goed genoeg.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tx_eOE-S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xfflryvps0h1j8r6602m.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tx_eOE-S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xfflryvps0h1j8r6602m.gif" alt="Hud hearts animation" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Met onze HUD kunnen we nog meer doen. In het volgende deel maken we een "Game Over" scherm en de mogelijkheid om een nieuw spel te starten.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>gamedev</category>
      <category>godot</category>
    </item>
    <item>
      <title>Een beat-em-up game maken met Godot - hurtboxes en hitboxes</title>
      <dc:creator>Bgie</dc:creator>
      <pubDate>Fri, 02 Jun 2023 21:03:33 +0000</pubDate>
      <link>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-7-1h1l</link>
      <guid>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-7-1h1l</guid>
      <description>&lt;p&gt;Terug naar &lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-6-19ci"&gt;deel 6&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Het vecht-systeem is gebaseerd op 'hitboxes' en 'hurtboxes'. &lt;/p&gt;

&lt;p&gt;Het slachtoffer van een aanval heeft een hitbox. Het wapen van de aanvaller heeft een hurtbox. Als de hurtbox van de aanvaller de hitbox van het slachtoffer raakt, krijgt het slachtoffer 'damage'. &lt;/p&gt;

&lt;p&gt;Beiden gaan we maken met &lt;code&gt;CollisionShape2D&lt;/code&gt; objecten, waar we ook onze botsingen mee maakten.&lt;/p&gt;

&lt;p&gt;We hadden al een &lt;code&gt;CollisionShape2D&lt;/code&gt; op de voeten geplaatst van onze personages. Dit kunnen we ook gebruiken voor als hitbox. Om dit duidelijk te maken, veranderen we naam van deze nodes, zowel voor de 'Player' als voor de 'Minotaur':&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3Wdpl27Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/axtb7v1z8y12or924qju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3Wdpl27Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/axtb7v1z8y12or924qju.png" alt="Rename to hitbox" width="631" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vervolgens gaan we de hurtbox voor het wapen maken. Bij de speler voegen we 2 nodes toe, een &lt;code&gt;Area2D&lt;/code&gt; en daaronder een &lt;code&gt;CollisionShape2D&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5NYnHRdp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ac2hz33lsfvg1hm6k09x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5NYnHRdp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ac2hz33lsfvg1hm6k09x.png" alt="Add player area2d" width="316" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Om de hurtbox op de juiste plaats te kunnen zetten, gaan we tijdelijk onze &lt;code&gt;AnimatedSprite2D&lt;/code&gt; verzetten naar de juiste frame (5) voor de "attack" animatie. Zo zien we waar het wapen neerkomt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oF1-1xz2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y8oik9vja8chtlesxka7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oF1-1xz2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y8oik9vja8chtlesxka7.png" alt="Attack animation" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Zoals we al eerder deden, moeten we nu een &lt;code&gt;Shape&lt;/code&gt; toevoegen aan onze &lt;code&gt;CollisionShape2D&lt;/code&gt;. Hiervoor gebruiken we een &lt;code&gt;CapsuleShape2D&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ds9WKEbo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kc0gponn82zyvbarxn34.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ds9WKEbo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kc0gponn82zyvbarxn34.png" alt="Add shape to hurtbox" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We zetten enkele waardes van onze &lt;code&gt;CapsuleShape2D&lt;/code&gt; juist: de &lt;code&gt;Radius&lt;/code&gt; wordt &lt;code&gt;130 px&lt;/code&gt;, de &lt;code&gt;Height&lt;/code&gt; wordt &lt;code&gt;400 px&lt;/code&gt; en onze &lt;code&gt;Position&lt;/code&gt; krijgt een &lt;code&gt;x&lt;/code&gt; van &lt;code&gt;300&lt;/code&gt;. Het is ook mogelijk de kleur (&lt;code&gt;Debug Color&lt;/code&gt;) aan te passen, maar dit zie je niet in de game zelf, enkel in de editor tijdens het ontwerpen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tyV-XDf0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cwt09zcfxv2au1p9xgst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tyV-XDf0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cwt09zcfxv2au1p9xgst.png" alt="Set hurtbox properties" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Onze hurtbox noemt nog &lt;code&gt;Area2D&lt;/code&gt;, de standaard naam. Het is duidelijker als we deze van naam te veranderen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3C2bu7GM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1m8bongjy5so1adpjrk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3C2bu7GM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1m8bongjy5so1adpjrk.png" alt="Rename hurtbox" width="314" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Onze code hangen we aan het signaal &lt;code&gt;body_entered(body: Node2D)&lt;/code&gt; dat hoort bij onze hurtbox. (In de screenshot heet de hurtbox nog &lt;code&gt;Area2D&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tWCaOeyR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/92ts4zayat3l8n6xv5ig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tWCaOeyR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/92ts4zayat3l8n6xv5ig.png" alt="Connect body_entered" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De functie die we nu krijgen van Godot heeft een parameter &lt;code&gt;body&lt;/code&gt;. Dit is een variabele waarin het object zit waar we mee botsen. Allerlei objecten kunnen botsen, en niet elk object kunnen we aanvallen. &lt;/p&gt;

&lt;p&gt;Onze vijand, die kan aangevallen worden, gaan we dadelijk een "take_damage" functie geven. In onze &lt;code&gt;_on_hurt_box_body_entered&lt;/code&gt; van de speler kunnen we aan Godot vragen of de &lt;code&gt;body&lt;/code&gt; waar we mee botsen zo een functie "take_damage" heeft.&lt;br&gt;
Indien ja, dan roepen we die aan.&lt;/p&gt;

&lt;p&gt;We passen onze &lt;code&gt;_on_hurt_box_body_entered&lt;/code&gt; functie aan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_hurt_box_body_entered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"take_damage"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Het "take_damage" gedeelte komt in het script van de vijand. We voegen daar deze nieuwe functie toe. &lt;code&gt;self.queue_free()&lt;/code&gt; is de instructie om de vijand te laten verdwijnen. We zorgen straks voor een 'sterf' animatie.&lt;/p&gt;

&lt;p&gt;In het script van de vijand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue_free&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Als we dit testen, merken we dat er nog een probleem is. De vijand verdwijnt wel degelijk, maar onze speler moet niet eens aanvallen! Om dit correct te doen, moeten we de hurtbox enkel actief maken wanneer het wapen neerkomt.&lt;/p&gt;

&lt;p&gt;We zorgen dat onze hurtbox in het begin UIT staat, en geen botsingen gaat detecteren. We zetten &lt;code&gt;Monitoring&lt;/code&gt; en &lt;code&gt;Monitorable&lt;/code&gt; allebei uit. &lt;br&gt;
We zetten ook &lt;code&gt;Layer 1&lt;/code&gt; uit bij het collision gedeelte. Dit zorgt ervoor dat onze hurbox niet meetelt als 'hard' object voor botsingen. Andere objecten in laag 1 kunnen gewoon door onze hurtbox heen bewegen. Enkel &lt;code&gt;Mask&lt;/code&gt; staat op, wat wil zeggen dat onze hurbox wel gaat kijken naar andere objecten.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7y7SOK9d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gr5o6fz5xvpb2s62ccc8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7y7SOK9d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gr5o6fz5xvpb2s62ccc8.png" alt="Set hurtbox properties" width="388" height="738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nu willen we onze hurtbox AAN zetten wanneer het wapen neerkomt. Als we gaan kijken in onze &lt;code&gt;AnimatedSprite2D&lt;/code&gt; bij de "attack" animatie, zien we alle frames en hun nummers. In frame 4 tot 7 komt het wapen neer. We verbinden het signaal &lt;code&gt;frame_changed()&lt;/code&gt; aan ons script:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y2sYY_vA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g344ayc2g5t5g89cehi1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y2sYY_vA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g344ayc2g5t5g89cehi1.png" alt="Frames with attack" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vanboven in de code van de speler maken we een tweede &lt;code&gt;@onready&lt;/code&gt; variabele om aan onze hurtbox te kunnen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;
&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;hurtbox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Area2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;HurtBox&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De code voor onze &lt;code&gt;_on_animated_sprite_2d_frame_changed&lt;/code&gt; bestaat uit enkele eenvoudige &lt;code&gt;if&lt;/code&gt; instructies. Als de "attack" animatie aan frame 4 komt, zetten we &lt;code&gt;monitoring&lt;/code&gt; van de hurtbox aan. Bij frame 7 terug uit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_animated_sprite_2d_frame_changed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;animation&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"attack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;hurtbox&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;monitoring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;hurtbox&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;monitoring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De &lt;code&gt;frame_changed()&lt;/code&gt; functie wordt altijd opgeroepen, zelfs als de grafische kaart te traag is om het beeld feitelijk te tonen (lage FPS).&lt;/p&gt;

&lt;p&gt;We hebben nu dit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ykN-qqqY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8a87a79fmocil0jbdj4u.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ykN-qqqY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8a87a79fmocil0jbdj4u.gif" alt="Attack enemy gone" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De vijand verdwijnt gewoon, terwijl we een sterf animatie voor onze vijand hebben. Die willen we natuurlijk gebruiken!&lt;/p&gt;

&lt;p&gt;Het is eenvoudig om dit aan onze state machine toe te voegen. In het script van de vijand voegen we een extra state toe, &lt;code&gt;DYING&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ATTACK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DYING&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In de &lt;code&gt;take_damage()&lt;/code&gt; functie gaan we niet onmiddellijk de vijand laten verdwijnen, maar gaan we naar onze nieuwe &lt;code&gt;DYING&lt;/code&gt; state switchen en de juiste animatie starten.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DYING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"die"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DYING&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dit kan je testen, het werkt, maar na de dramatische val komt onze vijand gewoon terug recht. Dat komt door onze &lt;code&gt;animation_finished&lt;/code&gt; code, die we hebben geschreven voor het aanvallen.&lt;/p&gt;

&lt;p&gt;We passen de &lt;code&gt;_on_animated_sprite_2d_animation_finished&lt;/code&gt; functie dus ook aan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_animated_sprite_2d_animation_finished&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DYING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue_free&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nu verdwijnt onze vijand na het omvallen.&lt;/p&gt;

&lt;p&gt;Het is pas helemaal af met een fade-out animatie. Een manier om een eenvoudige animatie te starten vanuit code is met een &lt;code&gt;tween&lt;/code&gt;. We maken een &lt;code&gt;tween&lt;/code&gt;, en voegen een aantal animatie stappen toe, die de tween dan erna gaat uitvoeren. De animatie is als volgt: eerst 3 seconden wachten, dan de kleur van onze sprite geleidelijk over laten gaan naar transparant, gedurende 1 seconde. Dan pas volgt de &lt;code&gt;queue_free()&lt;/code&gt; waarmee onze vijand verdwijnt. De animatie wordt samengesteld in onze code, maar start pas nadat onze functie &lt;code&gt;_on_animated_sprite_2d_animation_finished&lt;/code&gt; afgelopen is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_animated_sprite_2d_animation_finished&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DYING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tween&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_tween&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;tween&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tween_interval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;tween&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tween_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"modulate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TRANSPARENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;tween&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tween_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue_free&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZngW9bb---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iv0hdiri5jdnziq1gtdj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZngW9bb---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iv0hdiri5jdnziq1gtdj.gif" alt="Attack with fade out" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Het is niet erg fair dat onze vijand zich niet kan verdedigen. We gaan dezelfde stappen herhalen voor de vijand, zodat de vijand onze speler ook pijn kan doen.&lt;/p&gt;

&lt;p&gt;In het &lt;code&gt;Scene&lt;/code&gt; paneel van de minotaurus voegen we ook een &lt;code&gt;Area2D&lt;/code&gt; toe met daaronder een &lt;code&gt;CollisionShape2D&lt;/code&gt;. De &lt;code&gt;Area2D&lt;/code&gt; geven we een ander naam: &lt;code&gt;HurtBox&lt;/code&gt;.&lt;br&gt;
De &lt;code&gt;CollisionShape2D&lt;/code&gt; krijgt een &lt;code&gt;CapsuleShape2D&lt;/code&gt; als vorm, met een &lt;code&gt;Radius&lt;/code&gt; van &lt;code&gt;150 px&lt;/code&gt;, een &lt;code&gt;Height&lt;/code&gt; van &lt;code&gt;500 px&lt;/code&gt; en een &lt;code&gt;Position&lt;/code&gt; met &lt;code&gt;x&lt;/code&gt; = &lt;code&gt;400 px&lt;/code&gt;. De &lt;code&gt;Debug Color&lt;/code&gt; kleur mag je ook aanpassen als je wil.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7oz7ql4l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1uceqpt1o55j3mq3qb3n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7oz7ql4l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1uceqpt1o55j3mq3qb3n.png" alt="Enemy hurtbox properties" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We verbinden ook het &lt;code&gt;body_entered(body: Node2D)&lt;/code&gt; signaal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Od-LhCt_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kj43waz40uebhydpjhsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Od-LhCt_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kj43waz40uebhydpjhsw.png" alt="Connect body entered" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We kunnen hier dezelfde code gebruiken als voor onze speler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_hurt_box_body_entered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"take_damage"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We moeten straks gewoon zorgen dat onze speler ook een "take_damage" functie heeft.&lt;/p&gt;

&lt;p&gt;Eerst gaan we zorgen dat de onze hurtbox enkel actief is wanneer de knuppel neerkomt.&lt;/p&gt;

&lt;p&gt;De hurtbox van onze minotaurus passen we aan: &lt;code&gt;Monitoring&lt;/code&gt; en &lt;code&gt;Monitorable&lt;/code&gt; moeten UIT, en &lt;code&gt;Layer 1&lt;/code&gt; moet ook UIT.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JuCAFZhe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d39e8e6ouax9sge76yc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JuCAFZhe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d39e8e6ouax9sge76yc6.png" alt="Disable enemy hurtbox monitoring" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dan verbinden we &lt;code&gt;frame_changed()&lt;/code&gt; van de &lt;code&gt;AnimatedSprite2D&lt;/code&gt; met ons script.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jVqNllAg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uwnarc4yewqlt2g8adwm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jVqNllAg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uwnarc4yewqlt2g8adwm.png" alt="Connect enemy frame_changed" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Net als bij de speler maken we een nieuwe &lt;code&gt;@onready&lt;/code&gt; variabele om aan de hurtbox te kunnen vanuit de Enemy.gd code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;hurtbox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Area2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;HurtBox&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De functie voor &lt;code&gt;frame_changed&lt;/code&gt; is identiek aan die van de speler, enkel de frame nummers zijn verschillend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_animated_sprite_2d_frame_changed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;animation&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"attack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;hurtbox&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;monitoring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;hurtbox&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;monitoring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Om dit stuk al te testen, maken we tijdelijk een "take_damage" functie in het Player.gd script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue_free&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Als we dit testen, dan lijkt het niet te werken. Er is een fout in de code geslopen, blijkbaar werkt de hurtbox alleen maar aan de rechterzijde van de vijand!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b-H4g9J3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kce4ats9jyqq94eowcm6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b-H4g9J3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kce4ats9jyqq94eowcm6.gif" alt="Hurtbox bug" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dit probleem had ik zelf niet voorzien, en ik wil de vorige screenshots niet opnieuw maken :(&lt;/p&gt;

&lt;p&gt;De oplossing is gelukkig niet moeilijk. Het probleem zit in het spiegelen van de personages als ze naar links lopen, met de code &lt;code&gt;sprite.scale.x = -1&lt;/code&gt;. Daar spiegelen we enkel de &lt;code&gt;AnimatedSprite2D&lt;/code&gt;. Maar de hurtbox blijft natuurlijk op dezelfde plaats staan, aan de rechterzijde van de sprite.&lt;/p&gt;

&lt;p&gt;We lossen dit op door de hurtbox van onze minotaurus te verslepen met de muis, en een kind te maken van de &lt;code&gt;AnimatedSprite2D&lt;/code&gt;. Als we dan spiegelen, worden de kind nodes ook mee gespiegeld. De hurtbox komt dan ook aan de linkerzijde te liggen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lY7ldird--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uy58c58mg0x4zb373hli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lY7ldird--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uy58c58mg0x4zb373hli.png" alt="Move hurtbox node" width="312" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Er is een kleine wijziging nodig in onze Enemy.gd code, omdat we de hurtbox gebruiken in onze code. De plaats waar de hurtbox staat is nu anders, hij is een kind geworden van de &lt;code&gt;AnimatedSprite2D&lt;/code&gt;. De regel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;hurtbox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Area2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;HurtBox&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... wordt nu ...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;hurtbox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Area2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;HurtBox&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De bug zit ook in onze player code. Ook daar moeten we de hurtbox node verslepen in de &lt;code&gt;Scene&lt;/code&gt; en de code aanpassen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ga0PaN09--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fj8rqz388bzpdipiv96r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ga0PaN09--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fj8rqz388bzpdipiv96r.gif" alt="Attack by enemy" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Er schuilt echter &lt;em&gt;nog&lt;/em&gt; een subtiele bug in ons spel. Slaat de speler naar links met zijn staf, dan verdwijnt hij zelf!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vu-BK5EX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jvlie71hjm62fe9i8pj4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vu-BK5EX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jvlie71hjm62fe9i8pj4.gif" alt="Attack with suicide" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dit is een goede gelegenheid om een debug optie van Godot te demonstreren. In het &lt;code&gt;debug&lt;/code&gt; menu kan je &lt;code&gt;Visible Collision Shapes&lt;/code&gt; opzetten. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gANhBa70--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4d373fo0ubuv6ctqkr4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gANhBa70--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4d373fo0ubuv6ctqkr4g.png" alt="Enable visible collision shapes" width="547" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dan krijg je de botsingen te zien &lt;em&gt;in&lt;/em&gt; de game, en dan zien we dit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZRh7sEZy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vps7fk08f7v4khb12ybw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZRh7sEZy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vps7fk08f7v4khb12ybw.png" alt="Hurtbox touching own hitbox" width="650" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Omdat de tekening van de engel niet helemaal in het midden staat, hebben we een probleem als we spiegelen. De hurtbox van de speler raakt zijn eigen hitbox!&lt;/p&gt;

&lt;p&gt;Er is een manier om dit op te lossen door verschillende lagen te gebruiken voor de botsingen, maar daar gaan we nu niet op ingaan.&lt;/p&gt;

&lt;p&gt;De eenvoudigste manier is, om in de &lt;code&gt;CollisionShape2D&lt;/code&gt; van de speler de &lt;code&gt;CapsuleShape2D&lt;/code&gt; wat smaller te maken. We veranderen  de &lt;code&gt;Radius&lt;/code&gt; naar &lt;code&gt;120 px&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dyDWTinJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ns5vulu33r23l4wwz3rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dyDWTinJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ns5vulu33r23l4wwz3rg.png" alt="Reduce capsule radius" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alles lijkt nu te werken!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cVMN2Enu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vm0i1uvfry8mlxx8lqem.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cVMN2Enu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vm0i1uvfry8mlxx8lqem.gif" alt="Attack with collision shapes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In de plaats van een instant-death voor onze speler, willen we misschien liever meerdere levens. Krijgt de speler een mep, dan spelen we de "hurt" animatie in plaats van te verdwijnen.&lt;/p&gt;

&lt;p&gt;We voegen een nieuwe state toe in Player.gd:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ATTACK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HURT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onze &lt;code&gt;take_damage&lt;/code&gt; maken we minder fataal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;take_damage&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HURT&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hurt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Een andere kleine wijziging is ook nodig: de vijand mept veel te snel, en de speler krijgt geen kans om te ontsnappen.&lt;/p&gt;

&lt;p&gt;Open de &lt;code&gt;2D&lt;/code&gt; view van de minotaurus, en open de &lt;code&gt;SpriteFrames&lt;/code&gt; van de &lt;code&gt;AnimatedSprite2D&lt;/code&gt;. In de "attack" animatie gaan we de laatste frame (11) langer laten duren. We zetten de &lt;code&gt;Frame Duration&lt;/code&gt; op &lt;code&gt;20&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9ITvy44F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/thk001vucdla0p1xeqwq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9ITvy44F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/thk001vucdla0p1xeqwq.png" alt="Add delay to minotaur attack" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hetzelfde kunnen we doen voor de speler, maar hier gebruiken we &lt;code&gt;10&lt;/code&gt; frames als vertraging. De staf van de speler is wat sneller dan de knuppel van de minotaurus.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y5P3PKd2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lqln4i02kd3xl3q8253v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y5P3PKd2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lqln4i02kd3xl3q8253v.png" alt="Add delay to player attack" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dankzij de vertraging kan de speler nog weglopen wanneer de minotaurus begint te meppen, maar hij krijgt toch een stevig pak rammel!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GiiXBfGd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5mrb5od5qwjyi03han1w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GiiXBfGd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5mrb5od5qwjyi03han1w.gif" alt="Taking a beating" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In de volgende delen gaan we nog toevoegen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nieuwe vijanden die spawnen&lt;/li&gt;
&lt;li&gt;een beperkt aantal levens voor de speler&lt;/li&gt;
&lt;li&gt;game over en een high-score systeem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In het &lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-health-b8d"&gt;volgende deel&lt;/a&gt; implementeren we een basis 'health' systeem voor onze player.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>gamedev</category>
      <category>godot</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Een beat-em-up game maken met Godot - meppen!</title>
      <dc:creator>Bgie</dc:creator>
      <pubDate>Sat, 06 May 2023 10:05:19 +0000</pubDate>
      <link>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-6-19ci</link>
      <guid>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-6-19ci</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-5-1n6k"&gt;Terug naar deel 5&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We hadden al een attack animatie gemaakt voor onze held, die gaan we nu gebruiken. Ons script voor de 'Player' gaan we uitbreiden.&lt;/p&gt;

&lt;p&gt;Om aanvallen mogelijk te maken, gaan we een concept gebruiken dat vaak terugkomt in games: een 'state machine'.&lt;/p&gt;

&lt;p&gt;Een 'state' is een toestand waarin ons personage zich bevindt. Er bestaan meerdere states, maar er is er maar eentje actief. Afhankelijk van de state die actief is, wordt er andere code uitgevoerd.&lt;/p&gt;

&lt;p&gt;Dit wordt duidelijker met een voorbeeld: we gaan een &lt;code&gt;ATTACK&lt;/code&gt; state toevoegen, en als de speler in de &lt;code&gt;ATTACK&lt;/code&gt; state zit, mag hij niet meer bewegen tot de aanval gedaan is. De gewone state noemen we &lt;code&gt;READY&lt;/code&gt;, dan mag de speler wel rondlopen. Later gaan we ook de state &lt;code&gt;DEAD&lt;/code&gt; gebruiken.&lt;/p&gt;

&lt;p&gt;In het eerste stuk van ons 'Player' script voegen we volgende regels toe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ATTACK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEAD&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De &lt;code&gt;enum&lt;/code&gt; is een opsomming (enumeratie) van states die we willen gebruiken. In de variabele &lt;code&gt;state&lt;/code&gt; slaan we de huidige state van onze speler op.&lt;/p&gt;

&lt;p&gt;Het gebruiken van states kan heel eenvoudig, met gewone &lt;code&gt;if&lt;/code&gt;s. Vaak wordt in tutorials complexe code met klassen en polymorfisme gebruikt, maar zo moeilijk moet het daarom niet zijn.&lt;/p&gt;

&lt;p&gt;Onze bestaande code om de speler te bewegen komt nu binnen een &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;elif&lt;/code&gt; blok te zitten:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ATTACK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ui_left"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ui_right"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
        &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ui_up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ui_down"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dit doet natuurlijk nog niets, want &lt;code&gt;state == State.READY&lt;/code&gt; gaat gewoon altijd waar zijn. We moeten nog code toevoegen om een overgang tussen states te maken.&lt;/p&gt;

&lt;p&gt;We doen dat via keyboard input, en zetten van onze &lt;code&gt;state&lt;/code&gt; variabele op een andere waarde.&lt;/p&gt;

&lt;p&gt;De uiteindelijke code in &lt;code&gt;_physics_process&lt;/code&gt; ziet er nu zo uit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ATTACK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_action_just_pressed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ui_accept"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ATTACK&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"attack"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ui_left"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ui_right"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ui_up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ui_down"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;move_and_slide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"walk"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De input "ui_accept" is standaard gekoppeld aan zowel de SPACE als de ENTER toets.&lt;br&gt;
Enkel als onze speler in de &lt;code&gt;READY&lt;/code&gt; state zit, gaan we kijken of er een aanval gestart moet worden. Daar zetten we de &lt;code&gt;state&lt;/code&gt; op &lt;code&gt;State.ATTACK&lt;/code&gt;. Alle volgende frames wanneer &lt;code&gt;_physics_process&lt;/code&gt; wordt opgeroepen, zal in de bovenste 'if' enkel het stukje code bij de &lt;code&gt;ATTACK&lt;/code&gt; state uitgevoerd worden. Alle code om rond te lopen wordt overgeslagen. De speler moet eerst zijn attack afwerken!&lt;/p&gt;

&lt;p&gt;Als we deze code uitvoeren merken we dat er nog iets ontbreekt: als je 1 maal een attack start, blijft de speler meppen. Er is ook nog code nodig om de aanval te stoppen.&lt;/p&gt;

&lt;p&gt;Daarvoor gebruiken we een signaal dat van de &lt;code&gt;AnimatedSprite2D&lt;/code&gt; komt: &lt;code&gt;animation_finished()&lt;/code&gt;. We gaan code hangen aan dit signaal. Open het &lt;code&gt;Node&lt;/code&gt; paneel en Klik rechts op &lt;code&gt;animation_finished()&lt;/code&gt;. Kies daar &lt;code&gt;Connect...&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Sr5WTgo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pi956iqptyqavalv63bs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Sr5WTgo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pi956iqptyqavalv63bs.png" alt="Select connect to animation_finished signal" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In de volgende dialoog zorg je dat we het &lt;code&gt;Player&lt;/code&gt; script gebruiken (dit is de standaard optie). De voorgestelde naam &lt;code&gt;on_animated_sprite_blabla&lt;/code&gt; voor de functie (&lt;code&gt;receiver method&lt;/code&gt;) is prima. Klik op &lt;code&gt;Connect&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bJFfUnxg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x820f380ws9gg9lmix0n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bJFfUnxg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x820f380ws9gg9lmix0n.png" alt="connect to animation_finished signal" width="530" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We krijgen een nieuwe functie met &lt;code&gt;pass&lt;/code&gt; (niks doen) als voorlopige inhoud.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_animated_sprite_2d_animation_finished&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt; &lt;span class="c1"&gt;# Replace with function body.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dit veranderen we naar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_animated_sprite_2d_animation_finished&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dit kunnen we in-game testen. Spatie-balk laat de speler 1 maal meppen. Blijven indrukken = blijven meppen. Dit kan later verbeterd worden met bijvoorbeeld een cooldown timer.&lt;/p&gt;

&lt;p&gt;Voor onze vijand doen we ongeveer hetzelfde. We maken ook een eenvoudige state machine met een &lt;code&gt;state&lt;/code&gt; variabele:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ATTACK&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De hele code in &lt;code&gt;_physics_process&lt;/code&gt; komt een niveau dieper te zitten in een &lt;code&gt;if/elif&lt;/code&gt; blok:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ATTACK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kt"&gt;null&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Vector2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MAX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;SPEED&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"walk"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;move_and_slide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ook hier moeten zorgen dat onze vijand effectief wisselt van state om een aanval te starten. Maar we hebben al een &lt;code&gt;if/else&lt;/code&gt; waar we dit kunnen inschuiven! Als de vijand net ver genoeg staat, dus tussen &lt;code&gt;ATTACK_DISTANCE_MAX&lt;/code&gt; en &lt;code&gt;ATTACK_DISTANCE_MIN&lt;/code&gt; staat, dan starten we een aanval.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MAX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;SPEED&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ATTACK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ook niet vergeten om onze animatie correct aan te passen. Waar we normaal enkel naar velocity kijken om te kiezen tussen "walk" of "idle", gaan we nu eerst kijken of we net naar de &lt;code&gt;ATTACK&lt;/code&gt; state zijn gegaan. In dat geval starten we de attack animatie. De regel &lt;code&gt;if velocity&lt;/code&gt; wordt nu een &lt;code&gt;elif velocity&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ATTACK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"attack"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"walk"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Net als bij de speler gaan we het &lt;code&gt;animation_finished()&lt;/code&gt; signaal gebruiken om de aanval af te sluiten. We verbinden het signaal zoals we eerder deden:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x3bOgZqX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0vgf50zdosvdvpmx9z84.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x3bOgZqX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0vgf50zdosvdvpmx9z84.png" alt="Connect minotaur animation finished" width="530" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Onze nieuwe functie die we kregen van Godot passen we aan, we veranderen de state terug naar &lt;code&gt;READY&lt;/code&gt; als de aanval klaar is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_on_animated_sprite_2d_animation_finished&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Het resultaat:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HzLoKu7m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t0znjxfoiu6rdwisrmd1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HzLoKu7m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t0znjxfoiu6rdwisrmd1.gif" alt="Meppen" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Onze personages zijn nog 'onsterfelijk'... in het &lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-7-1h1l"&gt;volgende deel&lt;/a&gt; zorgen we dat de speler en vijanden geraakt kunnen worden en sterven.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>gamedev</category>
      <category>godot</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Een beat-em-up game maken met Godot - bewegende vijand</title>
      <dc:creator>Bgie</dc:creator>
      <pubDate>Fri, 05 May 2023 17:43:41 +0000</pubDate>
      <link>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-5-1n6k</link>
      <guid>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-5-1n6k</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-4-25c7"&gt;Terug naar deel 4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wat hebben we nu al gemaakt? Een wereld met een speler die kan rondlopen, en een vijand, die gewoon wat staat te staan... nog niet bepaald een leuke game... &lt;/p&gt;

&lt;p&gt;Wat willen we: vijanden die net buiten beeld vertrekken en de speler komen aanvallen. We gaan ons werk in 3 delen splitsen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;vijanden moeten naar de speler toe lopen&lt;/li&gt;
&lt;li&gt;vijanden en de speler moeten kunnen vechten en doodgaan.&lt;/li&gt;
&lt;li&gt;net buiten beeld moeten telkens nieuwe vijanden 'spawnen'&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We starten met het lopen van de vijand. Plaats eerst de speler en de vijand op een goede startpositie in de wereld. De speler start links-midden, en de vijand uiterst rechts net buiten beeld:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ovYMO3Lx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ubke4h7jppqiyurseeck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ovYMO3Lx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ubke4h7jppqiyurseeck.png" alt="Starting positions" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nu gaan we code schrijven om onze vijand te laten bewegen. Open de minotaurus &lt;code&gt;scene&lt;/code&gt; en het script voor de vijand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zxYo47uP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l59pekokeds6r97d697j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zxYo47uP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l59pekokeds6r97d697j.png" alt="Open minotaur script" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Net als bij de speler gaan we een 'constante' maken voor de snelheid waarmee dit personage beweegt. We zetten hem op 250, langzamer dan de speler, zodat de speler nog kan weglopen. Deze regel komt in het bovenste deel van het script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;250.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De beweging van onze vijand hangt niet af van het toetsenbord, zoals bij onze speler, maar van de positie van die speler tegenover onze vijand. &lt;/p&gt;

&lt;p&gt;De code om te bewegen komt bij in onze bestaande &lt;code&gt;_physics_process&lt;/code&gt; functie die we al hadden.&lt;/p&gt;

&lt;p&gt;Eerste stap is het opzoeken van de node van onze player. Dit steken we in een nieuwe variabele 'target', het doelwit van onze minotaurus.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_parent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Player"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hoe werkt dit? We hebben in onze 'game' scene ervoor gezorgd dat zowel de 'Player' als de 'Minotaur' kinderen zijn van de 'Arena' node. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fRTUDbBZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5pbh3cxqy8hyf8146pe2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fRTUDbBZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5pbh3cxqy8hyf8146pe2.png" alt="Arena parent node" width="301" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In bovenstaande code starten we met &lt;code&gt;self&lt;/code&gt;, de Minotaurus node (waar het script aanhangt). &lt;code&gt;get_parent&lt;/code&gt; geeft dan de 'Arena' node erboven. Doen we dan &lt;code&gt;get_node("Player")&lt;/code&gt; om tussen de child nodes van 'Arena' te zoeken naar een node met de naam 'Player'. Dat is degene die we willen hebben, en die slaan we op in onze nieuwe variabele &lt;code&gt;var target&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Volgende stap is controleren of we wel een tegenstander hebben gevonden.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_parent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Player"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kt"&gt;null&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# movement code &lt;/span&gt;

    &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enkel als de node 'Player' gevonden is (misschien is de speler al dood?) dan gaan we onze minotaurus laten bewegen. &lt;code&gt;null&lt;/code&gt; is een speciale waarde die 'niets' betekend. Enkel als onze target NIET null is, gaan we verder.&lt;/p&gt;

&lt;p&gt;Nu volgt een stukje wiskunde, om de beweging van onze minotaurus te berekenen. &lt;/p&gt;

&lt;p&gt;Denk je ooit tijdens de les wiskunde: waarom moet ik dit allemaal kennen? Wel, computergames gebruiken een hoop wiskunde! En schrijf je uiteindelijk een succesvolle game? Dan heb je ook wiskunde nodig om je hopen geld te kunnen tellen.&lt;/p&gt;

&lt;p&gt;De code is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_parent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Player"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kt"&gt;null&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;

    &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Als je nog nooit van vectoren of coördinaten hebt gehoord, geen probleem, hier in het kort wat er gebeurt:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FlgBcJ5M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yruprswmrcmtx0umtj6s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FlgBcJ5M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yruprswmrcmtx0umtj6s.png" alt="Coordinates" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De posities van de 2 personages kan je in getallen uitdrukken.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;De horizontale as (links-rechts) noemen we &lt;code&gt;x&lt;/code&gt;. De speler staat op &lt;code&gt;x&lt;/code&gt;=4000. &lt;/li&gt;
&lt;li&gt;De verticale as (boven-onder) noemen we &lt;code&gt;y&lt;/code&gt;. De speler staat op &lt;code&gt;y&lt;/code&gt;=500.&lt;/li&gt;
&lt;li&gt;Samen noemen we dat de coördinaten van de speler (x,y). De speler staat op (4000, 500), de minotaurus staat op (5000, 1000).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We kunnen rekenen met coördinaten, zoals we met eenvoudige getallen doen. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Het verschil tussen de positie van de speler (&lt;code&gt;target&lt;/code&gt;) en de minotaurus (&lt;code&gt;self&lt;/code&gt;) geeft ons de blauwe pijl op de tekening. &lt;/li&gt;
&lt;li&gt;In code uitgedrukt: &lt;code&gt;target.position - self.position&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In ons voorbeeld is de uitkomst (4000,500) - (5000, 1000) = (-1000, -500).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We slaan dit op in variabele &lt;code&gt;delta&lt;/code&gt;. &lt;br&gt;
&lt;code&gt;Delta&lt;/code&gt; geeft ons de richting en afstand naar de target. &lt;/p&gt;

&lt;p&gt;We willen enkel de richting gebruiken, en dan met een vaste snelheid een stukje bewegen in die richting. Zonder te veel details te geven, maar &lt;code&gt;normalized&lt;/code&gt; doet net dat, en geeft als uitkomst de groene pijl. &lt;/p&gt;

&lt;p&gt;De groene pijl is een pijl met lengte 1 met dezelfde richting als de blauwe pijl. Dit slaan we op in &lt;code&gt;var direction&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;De laatste regel &lt;code&gt;velocity = direction * SPEED&lt;/code&gt; gebruikt de groene pijl (&lt;code&gt;direction&lt;/code&gt;) en onze constante snelheid (&lt;code&gt;SPEED&lt;/code&gt;) om de snelheid van bewegen voor onze minotaurus te bepalen. Dit steken we in &lt;code&gt;velocity&lt;/code&gt;, een bestaande variabele die bij onze &lt;code&gt;CharacterBody2D&lt;/code&gt; hoort.&lt;/p&gt;

&lt;p&gt;Nu volgt enkel nog het bewegen zelf, met de juiste animatie.&lt;/p&gt;

&lt;p&gt;Die code is gelijkaardig aan de code van de speler. Als onze minotaurus snelheid heeft (&lt;code&gt;velocity&lt;/code&gt; is niet nul) dan spelen we de 'walk' animatie. Anders spelen we 'idle'. De &lt;code&gt;move_and_slide()&lt;/code&gt; doet het feitelijke bewegen op basis van de &lt;code&gt;velocity&lt;/code&gt;, rekening houdend met botsingen.&lt;/p&gt;

&lt;p&gt;Alles te samen ziet onze code er nu zo uit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;250.0&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_parent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Player"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kt"&gt;null&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"walk"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;move_and_slide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dit kunnen we testen met &lt;code&gt;Run Project&lt;/code&gt; of &lt;code&gt;F5&lt;/code&gt;. Daar komt ie!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--259tUMsd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dxf6u34jjsff28tj91xu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--259tUMsd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dxf6u34jjsff28tj91xu.gif" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Merk op dat onze vijand nogal 'plakkerig' is... hij stopt nooit en loopt tot tegen de speler, en blijft maar lopen.&lt;/p&gt;

&lt;p&gt;Hij loopt ook achteruit, maar dat kennen we al en kunnen we oplossen zoals bij de speler. Er is een klein verschil, we hebben de &lt;code&gt;scale&lt;/code&gt; van onze minotaurus op 1.5 gezet omdat hij wat klein was.&lt;/p&gt;

&lt;p&gt;Als we dezelfde code gebruiken als bij de speler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... dan gaat onze &lt;code&gt;scale&lt;/code&gt; terug verspringen naar 1 of -1, en is onze minotaurus terug klein.&lt;/p&gt;

&lt;p&gt;Met de wiskundige functie &lt;code&gt;abs&lt;/code&gt; kunnen we dit oplossen. &lt;code&gt;abs&lt;/code&gt; geeft de absolute waarde van een getal, wat wil zeggen dat een min-teken wordt weggelaten als dit er is, elk getal wordt positief gemaakt.&lt;/p&gt;

&lt;p&gt;In de volgende code behouden we het getal dat in &lt;code&gt;sprite.scale.x&lt;/code&gt; zit, en veranderen we enkel het teken van plus naar min of omgekeerd, zodat de scale van de minotaurus van 1.5 behouden blijft.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Het andere probleem, dat onze minotaurus eeuwig blijft lopen, kunnen we oplossen met een paar extra &lt;code&gt;if&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Als de minotaurus ver weg is, willen we dat hij naar de speler toeloopt. Is hij te dichtbij, dan moet hij naar achteren. Zit hij op de ideale afstand, dan mag hij blijven staan, dan gaat hij aanvallen. De afstanden steken we in een paar constanten:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MAX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;520.0&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;480.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De logica zelf komt bij in onze &lt;code&gt;_physics_process&lt;/code&gt;. We berekenen de afstand tussen onze minotaurus en de speler uit de variabele delta die we al hadden. Met die afstand kunnen we &lt;code&gt;if&lt;/code&gt;s schrijven.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MAX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;SPEED&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Het uiteindelijke script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;250.0&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MAX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;520.0&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;480.0&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Node2D&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_ready&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_parent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Player"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kt"&gt;null&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Vector2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MAX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ATTACK_DISTANCE_MIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;SPEED&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;velocity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Vector2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"walk"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;move_and_slide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In het &lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-6-19ci"&gt;volgende deel&lt;/a&gt; starten we met het gevecht systeem. &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>godot</category>
      <category>gamedev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Een beat-em-up game maken met Godot - een vijand</title>
      <dc:creator>Bgie</dc:creator>
      <pubDate>Tue, 02 May 2023 16:45:08 +0000</pubDate>
      <link>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-4-25c7</link>
      <guid>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-4-25c7</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-3-329"&gt;Terug naar deel 3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We gaan een vijand toevoegen. De basis onderdelen zijn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;de animatie frames&lt;/li&gt;
&lt;li&gt;een collision shape&lt;/li&gt;
&lt;li&gt;en een enemy script&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hiervoor maken we eerst een nieuwe &lt;code&gt;scene&lt;/code&gt;. In het paneel linksonder, klik je met de rechtermuisknop op &lt;code&gt;res://&lt;/code&gt;. Vervolgens kies je &lt;code&gt;new&lt;/code&gt; en dan &lt;code&gt;scene&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9XCMtIIX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hod6fxp7s3jbg9r8hy3j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9XCMtIIX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hod6fxp7s3jbg9r8hy3j.png" alt="Add new scene" width="585" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In de &lt;code&gt;Create New Scene&lt;/code&gt; dialoog klikken we op de &lt;code&gt;Pick Root Node Type&lt;/code&gt; knop.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ebkiEC6j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1taos69hbhwiy9bnujfb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ebkiEC6j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1taos69hbhwiy9bnujfb.png" alt="Create new scene pick root node button" width="520" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dan kunnen we in de &lt;code&gt;Recent&lt;/code&gt; lijst opnieuw &lt;code&gt;CharacterBody2D&lt;/code&gt; kiezen. Deze gebruikten we eerder ook voor de speler. Bevestig met de &lt;code&gt;pick&lt;/code&gt; knop.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--97V1yJXI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9eeh1hxol7or8xyg0714.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--97V1yJXI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9eeh1hxol7or8xyg0714.png" alt="Pick CharacterBody2D" width="763" height="627"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terug in de eerste dialog, typen we nu een naam voor onze vijand: 'Minotaur'. We bevestigen met &lt;code&gt;ok&lt;/code&gt; en onze nieuwe scene wordt gemaakt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m8V5ydzg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e7db0n98oz664z4nb2fv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m8V5ydzg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e7db0n98oz664z4nb2fv.png" alt="Create minotaur scene" width="520" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Net zoals bij onze speler voegen we 2 child nodes toe aan onze minotaurus: &lt;code&gt;AnimatedSprite2D&lt;/code&gt; en &lt;code&gt;CollisionShape2D&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4WTMirgy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2biwyhrapxbjqcvjd3m4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4WTMirgy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2biwyhrapxbjqcvjd3m4.png" alt="Add minotaur child nodes" width="315" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Een shape instellen voor de collision shape is net hetzelfde als bij de speler. De vorm is ook een gedraaide &lt;code&gt;CapsuleShape 2D&lt;/code&gt; maar wat groter: &lt;code&gt;radius&lt;/code&gt; = 50, &lt;code&gt;height&lt;/code&gt; = 350 en &lt;code&gt;rotation&lt;/code&gt; = 90.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vFxS9NKE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g4qx3npwlkxqzh6b0soe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vFxS9NKE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g4qx3npwlkxqzh6b0soe.png" alt="Minotaur collision shape" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Onze &lt;code&gt;AnimatedSprite2D&lt;/code&gt; heeft &lt;code&gt;SpriteFrames&lt;/code&gt; nodig, die voegen we toe:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KKgsrs5s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ondf4gamqbidalbwf6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KKgsrs5s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ondf4gamqbidalbwf6c.png" alt="Create spriteframes" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Klikken we nu nogmaal op deze nieuwe &lt;code&gt;SpriteFrames&lt;/code&gt; dan opent het paneel waar we de animaties kunnen samenstellen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PqBDtq7h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4absu4il1bbca6t7vuj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PqBDtq7h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4absu4il1bbca6t7vuj.png" alt="SpriteFrames panel" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De minotaurus animaties zijn dezelfde als die van de speler: &lt;code&gt;attack&lt;/code&gt;, &lt;code&gt;die&lt;/code&gt;, &lt;code&gt;hurt&lt;/code&gt;, &lt;code&gt;idle&lt;/code&gt; en &lt;code&gt;walk&lt;/code&gt;. Deze voegen we toe met de &lt;code&gt;Add Animation&lt;/code&gt; knop, en we geven ze de juiste naam. De &lt;code&gt;default&lt;/code&gt; animatie mag weg.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q0A9Gm5k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwxu9sx1g6cf734tizva.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q0A9Gm5k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwxu9sx1g6cf734tizva.png" alt="Create animations" width="290" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voor elke animatie moeten we nu de juiste beelden toevoegen met de &lt;code&gt;Add frames from file&lt;/code&gt; knop. De afbeeldingen staan in submappen van de map 'minotaur' onder onze 'assets'.&lt;br&gt;
Alle animaties spelen aan &lt;code&gt;30 fps&lt;/code&gt;. Enkel de &lt;code&gt;idle&lt;/code&gt; en &lt;code&gt;walk&lt;/code&gt; animatie hebben &lt;code&gt;looping&lt;/code&gt; AAN staan, bij de rest staat dit UIT.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SDK5zjNc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qa12np4mv2fr2yeyidpb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SDK5zjNc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qa12np4mv2fr2yeyidpb.png" alt="Add frames to animations" width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Onze &lt;code&gt;AnimatedSprite2D&lt;/code&gt; staat nog te laag ten opzichte van onze &lt;code&gt;CollisionShape2D&lt;/code&gt;, de voeten van het monster moeten in de blauwe ovaal staan. We passen voor onze &lt;code&gt;AnimatedSprite2D&lt;/code&gt; de &lt;code&gt;position&lt;/code&gt; aan naar &lt;code&gt;y&lt;/code&gt; = -200.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YDCpgiUQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkqie27cp5ddsnq45rqt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YDCpgiUQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkqie27cp5ddsnq45rqt.png" alt="Set AnimatedSprite2D position" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Onze vijand tot leven brengen doen we met een script. Zorg dat de root node 'Minotaur' geselecteerd is en klik op de &lt;code&gt;Attach Script&lt;/code&gt; knop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0nifFjnC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hjnppa2pny3u4uf18khu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0nifFjnC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hjnppa2pny3u4uf18khu.png" alt="Attach script button" width="290" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In de volgende dialoog gaan we een andere naam kiezen voor ons script: we noemen het script 'res://Enemy.gd' omdat we hetzelfde script willen gebruiken voor meerdere soorten vijanden. Bevestig door op &lt;code&gt;Create&lt;/code&gt; te klikken.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9mk2SoFf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7xp7uc4swb9b3466suh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9mk2SoFf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7xp7uc4swb9b3466suh.png" alt="Attach enemy script dialog" width="594" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Het script voor de vijand gaan we geleidelijk opbouwen. We starten met het minimum: de vijand staat gewoon stil.&lt;br&gt;
Verwijder alle voorbeeldcode en gebruik dit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Om te kunnen testen gaan we onze vijand in de wereld plaatsen. Sla eerst de huidige scene op met &lt;code&gt;Ctrl+S&lt;/code&gt; of kies in het hoofdmenu linksboven &lt;code&gt;Scene&lt;/code&gt; - &lt;code&gt;Save&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dan keren we terug naar de &lt;code&gt;2D&lt;/code&gt; view en selecteren we onze 'game' scene. We slepen onze 'Minotaur.tscn' vanuit het &lt;code&gt;FileSystem&lt;/code&gt; naar de 'Arena' node in onze &lt;code&gt;scene&lt;/code&gt;. Daarna kan je de speler en de vijand verslepen in de wereld zelf, zodat ze niet vlak bij mekaar staan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tznzzbi9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/coyjc37kwgjgei21h59w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tznzzbi9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/coyjc37kwgjgei21h59w.png" alt="Add minotaur to game" width="800" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Het valt misschien dadelijk op dat ons monstertje niet heel indrukwekkend is... We gaan hem eerst wat groter maken!&lt;br&gt;
Dit is zo gebeurd: we openen terug de 'minotaur' scene, selecteren de &lt;code&gt;AnimatedSprite2D&lt;/code&gt; en zetten de &lt;code&gt;scale&lt;/code&gt; op 1.5&lt;br&gt;
Nu staan onze voeten niet meer op de juiste plaats, daarom passen we &lt;code&gt;position&lt;/code&gt; terug aan zodat &lt;code&gt;y&lt;/code&gt; = -300&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2b0EnuDu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ujmplzl1ohl3tb1i9imc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2b0EnuDu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ujmplzl1ohl3tb1i9imc.png" alt="Make monster larger" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nu dit gebeurd is, kunnen we testen! Start de game met de &lt;code&gt;Run Project&lt;/code&gt; knop of &lt;code&gt;F5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Als we naar onze vijand toelopen, merken we dat er nog een probleem is. Het overlappen van de graphics klopt nog niet, onze minotaurus staat altijd vanboven, ook al loopt de speler 'voor' hem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bdezpgr3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wza64b6hnczo67mwaepl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bdezpgr3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wza64b6hnczo67mwaepl.png" alt="Bad sorting" width="504" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Als game engine heeft Godot hier natuurlijk een oplossing voor. Onze 'Arena' node heeft bij zijn properties een optie &lt;code&gt;Y Sort Enabled&lt;/code&gt; die we eenvoudig aan kunnen zetten. &lt;br&gt;
Staat dit AAN, dan gaat Godot bij het tekenen van de child nodes van 'Arena' kijken naar de hoogte (y positie) en de nodes sorteren zodat de hoogste nodes 'vanonder' komen te liggen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1-gF5eL3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q94cuwsqfdcl1kbgyk43.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1-gF5eL3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q94cuwsqfdcl1kbgyk43.png" alt="Enable Y sort" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dit zit er al beter uit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6Lnm91j5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vvcu2hty3nt0scjejl9z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6Lnm91j5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vvcu2hty3nt0scjejl9z.gif" alt="Run circles clip" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In het volgende deel schrijven we een basis AI voor onze vijand: &lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-5-1n6k"&gt;deel 5&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>godot</category>
      <category>tutorial</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Een beat-em-up game maken met Godot - botsingen</title>
      <dc:creator>Bgie</dc:creator>
      <pubDate>Sun, 30 Apr 2023 11:09:56 +0000</pubDate>
      <link>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-3-329</link>
      <guid>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-3-329</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-2-4af9"&gt;Terug naar deel 2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In deel 3 van deze reeks zorgen we dat onze speler binnen onze wereld blijft, met het 'collision' systeem van Godot. Dit systeem is ook nodig voor bijvoorbeeld combat en interactie met objecten.&lt;/p&gt;

&lt;p&gt;Godot heeft zoals vele game engines een fysica systeem, waarmee we botsingen (collisions) van objecten kunnen simuleren. &lt;br&gt;
De afmetingen van een object staan los van de graphics (tekeningen) op het scherm. Objecten die kunnen botsen zijn meestal opgebouwd uit eenvoudige vormen, zoals rechthoeken, cirkels of lijnen.&lt;/p&gt;

&lt;p&gt;Willen we dat onze speler 'binnen' de wereld blijft, dan moeten we 2 zaken toevoegen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;de grenzen van de wereld, waar we ook collision objects voor gaan gebruiken,&lt;/li&gt;
&lt;li&gt;en een collision object voor de speler zelf.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We starten met onze speler. Zorg dat de &lt;code&gt;2D&lt;/code&gt; view open staat, en de 'player' scene actief is. Links moet de &lt;code&gt;node&lt;/code&gt; die 'CollisionShape2D' heet, geselecteerd zijn.&lt;br&gt;
Dan kiezen we rechts bij shape, een &lt;code&gt;CapsuleShape2D&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wNSEHGLT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zowy4mmi52oh4j38z29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wNSEHGLT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zowy4mmi52oh4j38z29.png" alt="Set player collision shape screenshot" width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De grootte en richting van de &lt;code&gt;CapsuleShape2D&lt;/code&gt; kan je met de muis aanpassen, via de kleine handvaten, maar in ons geval doen we het met het toetsenbord en typen we dadelijk de juiste waardes voor &lt;code&gt;radius&lt;/code&gt; = 50, &lt;code&gt;height&lt;/code&gt; = 300 en &lt;code&gt;rotation&lt;/code&gt; = 90:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6CBMALHz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/te7ao09tm9a47yha0yo2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6CBMALHz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/te7ao09tm9a47yha0yo2.png" alt="Set capsuleshape parameters" width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Om later geen problemen te hebben met sprites die niet op de juiste manier voor of achter mekaar liggen, zorgen we dat de &lt;code&gt;CapsuleShape2D&lt;/code&gt; op &lt;code&gt;position&lt;/code&gt; &lt;code&gt;x&lt;/code&gt; = 0 px en &lt;code&gt;y&lt;/code&gt; = 0 px blijft staan.&lt;/p&gt;

&lt;p&gt;We gaan de &lt;code&gt;AnimatedSprite2D&lt;/code&gt; verplaatsen, zodat de voeten van het personage in de &lt;code&gt;CapsuleShape2D&lt;/code&gt; staan. Selecteer de &lt;code&gt;AnimatedSprite2D&lt;/code&gt; en verander zijn positie naar &lt;code&gt;x&lt;/code&gt; = 10 px en &lt;code&gt;y&lt;/code&gt; = -300 px.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E4h_D0QP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j15tdl9wf40oet2rcxpe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E4h_D0QP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j15tdl9wf40oet2rcxpe.png" alt="Move animated sprite feet" width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Doordat we enkel de voeten gebruiken voor botsingen, kan ons personage voor en achter andere personages lopen. Dit ziet er beter uit. Als we het hele lichaam gebruiken voor botsingen, kan dit niet. De collision shapes kunnen niet overlappen, ze botsen. De sprites kunnen dat wel. Hier zie je het verschil:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Iv_lEfEb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/frmevzoemlod9mj2palc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Iv_lEfEb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/frmevzoemlod9mj2palc.png" alt="Large vs small collision shapes" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nu gaan we verder met de wereld. Zorg dat de &lt;code&gt;2D&lt;/code&gt; view open staat, en de 'game' scene actief is. Links moet je &lt;code&gt;node&lt;/code&gt; die we 'Arena' hebben genoemd, geselecteerd zijn. Deze node is een &lt;code&gt;StaticBody2D&lt;/code&gt;, wat wil zeggen dat het een object is dat meedoet aan botsingen, maar dat statisch blijft (niet beweegt). Klik op de &lt;code&gt;+&lt;/code&gt; (plus) knop om een child node toe te voegen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MItSpZda--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/priutwzj7p557diaeol8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MItSpZda--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/priutwzj7p557diaeol8.png" alt="Add child to arena node screenshot" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In de &lt;code&gt;Create New Node&lt;/code&gt; dialoog voegen we een &lt;code&gt;CollisionShape2D&lt;/code&gt; toe.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dDwaBbSu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/suq3qp5ddszie1ftb7w2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dDwaBbSu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/suq3qp5ddszie1ftb7w2.png" alt="Create CollisionShape2D screenshot" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voor de boven- en ondergrens van de wereld gebruiken we een simpele lijn. Alles aan 1 kant van de lijn telt als botsing, de andere kant is wandelbaar.&lt;/p&gt;

&lt;p&gt;Selecteer de nieuwe &lt;code&gt;CollisionShape2D&lt;/code&gt; en maak voor de &lt;code&gt;Shape&lt;/code&gt; een nieuwe &lt;code&gt;WorldBoundaryShape2D&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AilH0PJO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9bubo7aaqltmiaxn0f3v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AilH0PJO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9bubo7aaqltmiaxn0f3v.png" alt="New WorldBoundaryShape2D screenshot" width="800" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We stellen in welke kant van de lijn wandelbaar is door bij &lt;code&gt;Normal&lt;/code&gt; onze &lt;code&gt;y&lt;/code&gt; = 1 te maken. (Naar beneden). De lijn zelf zetten we vanboven aan de rand van de bomen door &lt;code&gt;position&lt;/code&gt; &lt;code&gt;y&lt;/code&gt; = -300 te maken:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xLGtMesF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/361u7af34hxp29e0e8qu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xLGtMesF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/361u7af34hxp29e0e8qu.png" alt="First world boundary screenshot" width="800" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dit kunnen we nu best eens testen. Start het project met de &lt;code&gt;Run Project&lt;/code&gt; knop of &lt;code&gt;F5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aDS0ig0a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tp4q3bd23xai2gt9vd8h.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aDS0ig0a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tp4q3bd23xai2gt9vd8h.gif" alt="Run up animation" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De ondergrens van de wereld maken we op dezelfde manier. Selecteer opnieuw de &lt;code&gt;Arena&lt;/code&gt; node en voeg een nieuwe &lt;code&gt;CollisionShape2D&lt;/code&gt; toe. Deze geven we ook een &lt;code&gt;WorldBoundaryShape2D&lt;/code&gt; als vorm.&lt;br&gt;
De &lt;code&gt;normal&lt;/code&gt; (richting) staat standaard op &lt;code&gt;x&lt;/code&gt; = 0 en &lt;code&gt;y&lt;/code&gt; = -1. Dit is goed, dit is naar boven. We veranderen wel de &lt;code&gt;position&lt;/code&gt; naar &lt;code&gt;y&lt;/code&gt; = 1080.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bR7hU1F4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9k4vqd4g7werb8g6kqm2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bR7hU1F4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9k4vqd4g7werb8g6kqm2.png" alt="World lower boundary" width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De linker- en rechtergrens zetten we iets buiten beeld. Dan kunnen straks de vijanden net buiten beeld spawnen.&lt;br&gt;
Maak nog twee maal onder de &lt;code&gt;Arena&lt;/code&gt; node een &lt;code&gt;CollisionShape2D&lt;/code&gt;, met telkens een &lt;code&gt;WorldBoundaryShape2D&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;De linkergrens heeft &lt;code&gt;normal&lt;/code&gt; &lt;code&gt;x&lt;/code&gt; = 1 en &lt;code&gt;y&lt;/code&gt; = 0. De &lt;code&gt;position&lt;/code&gt; &lt;code&gt;x&lt;/code&gt; = -2300 px.&lt;br&gt;
De rechtergrens heeft &lt;code&gt;normal&lt;/code&gt; &lt;code&gt;x&lt;/code&gt; = -1 en &lt;code&gt;y&lt;/code&gt; = 0. De &lt;code&gt;position&lt;/code&gt; &lt;code&gt;x&lt;/code&gt; = 2300 px.&lt;/p&gt;

&lt;p&gt;Als dit klaar is kan je opnieuw testen met &lt;code&gt;Run Project&lt;/code&gt; of &lt;code&gt;F5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xpcu7S1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tj8qu6onpa52b1zahcng.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xpcu7S1c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tj8qu6onpa52b1zahcng.gif" alt="Running around screenshot" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In het &lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-4-25c7"&gt;volgende deel (deel 4)&lt;/a&gt; gaan we een vijand toevoegen.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>godot</category>
      <category>tutorial</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Een beat-em-up game maken met Godot - de speler</title>
      <dc:creator>Bgie</dc:creator>
      <pubDate>Sat, 08 Apr 2023 08:55:13 +0000</pubDate>
      <link>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-2-4af9</link>
      <guid>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-2-4af9</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-1-42bi"&gt;Terug naar deel 1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In deel 2 van deze reeks voegen we onze speler toe.&lt;/p&gt;

&lt;p&gt;Maak een nieuwe scene.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOyiWowh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n4mkbcgqne6417f6h24y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOyiWowh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n4mkbcgqne6417f6h24y.png" alt="Create new scene menu screenshot" width="570" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De &lt;code&gt;node&lt;/code&gt; die we aanmaken moet van het type &lt;code&gt;CharacterBody2D&lt;/code&gt; zijn. Dit is een soort &lt;code&gt;node&lt;/code&gt; die wel meedoet met fysica simulatie (vallen en botsen) maar waar we volledige controle over hebben.&lt;br&gt;
Als naam van de &lt;code&gt;scene&lt;/code&gt; gebruiken we gewoon 'Player' (dit is vrij te kiezen).&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9JMxAJh---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ti3tmj954rawdfdfyp6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9JMxAJh---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ti3tmj954rawdfdfyp6.png" alt="Create Characterbody2d scene for player screenshot" width="520" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We krijgen nu een extra tabblad voor deze nieuwe 'Player' scene. Via de knoppen hieronder kan je wisselen tussen scenes die je open hebt.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BQplTasT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a1zvv7pl5iyop33o9p2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BQplTasT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a1zvv7pl5iyop33o9p2i.png" alt="Navigation buttons game scene - player scene screenshot" width="731" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We voegen 2 nodes toe aan onze player: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;een &lt;code&gt;AnimatedSprite2D&lt;/code&gt; voor de graphics,&lt;/li&gt;
&lt;li&gt;en een &lt;code&gt;CollisionShape2D&lt;/code&gt; om botsingen te kunnen detecteren.
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QT50y1at--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j3qmrzkwjh1kmzsjy96o.png" alt="Add nodes to player scene" width="314" height="280"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Om de graphics van de &lt;code&gt;AnimatedSprite2D&lt;/code&gt; te kiezen, moeten we eerst zorgen dat ie links geselecteerd is. Dan kunnen we rechts bij &lt;code&gt;Sprite Frames&lt;/code&gt; via het uitklap menu een nieuwe &lt;code&gt;SpriteFrames&lt;/code&gt; toevoegen.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZH1LaobK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4bd6cidu5uofn5m5k8ys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZH1LaobK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4bd6cidu5uofn5m5k8ys.png" alt="Add new spriteframes to player animatedsprite" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De nieuwe &lt;code&gt;SpriteFrames&lt;/code&gt; is nog leeg. Klik er op. Midden-beneden opent nu de editor voor de &lt;code&gt;SpriteFrames&lt;/code&gt; in een paneel.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pFIVt658--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2n0zwmessoipcqg9fo0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pFIVt658--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2n0zwmessoipcqg9fo0a.png" alt="Click on spriteframes to open editor" width="353" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De Godot ontwikkelomgeving zit vol met panelen en tabbladen... Hieronder zie je de knop die hoort bij het &lt;code&gt;SpriteFrames&lt;/code&gt; paneel, waaraan je ziet dat dit paneel open staat.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZRskEHny--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2cn95wqlyf4wotmcva7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZRskEHny--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2cn95wqlyf4wotmcva7.png" alt="Spriteframes editor with navigation button" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We gaan onze animaties toevoegen: in het &lt;code&gt;SpriteFrames&lt;/code&gt; paneel heb je onder 'Animations' wat knoppen en een lijstje met animaties die in de &lt;code&gt;SpriteFrames&lt;/code&gt; zitten.&lt;br&gt;
Met de &lt;code&gt;Add Animation&lt;/code&gt; knop voegen we de volgende animaties toe: &lt;code&gt;attack&lt;/code&gt;, &lt;code&gt;die&lt;/code&gt;, &lt;code&gt;hurt&lt;/code&gt;, &lt;code&gt;idle&lt;/code&gt; en &lt;code&gt;walk&lt;/code&gt; (&lt;code&gt;default&lt;/code&gt; mag weg).&lt;br&gt;
De naam veranderen van een animatie kan door 2 keer (langzaam) te klikken met de linkermuisknop.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NV--euk3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wwyrbyp10luwoa517pz3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NV--euk3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wwyrbyp10luwoa517pz3.png" alt="Add animations" width="285" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--owQ-0s-u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qnfs9mx9xfa89hzpdrrr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--owQ-0s-u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qnfs9mx9xfa89hzpdrrr.png" alt="Spriteframes editor buttons used" width="678" height="93"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De volgende knoppen gaan we gebruiken om alle animaties correct in te stellen. Van links naar rechts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;de &lt;code&gt;animation looping&lt;/code&gt; knop&lt;/li&gt;
&lt;li&gt;FPS = snelheid van de animatie (frames per seconde)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;play&lt;/code&gt; knop om een voorbeeld te zien&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add frame from file&lt;/code&gt; knop om losse afbeeldingen toe te voegen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Klik op de &lt;code&gt;add frame from file&lt;/code&gt;. In de dialoog die volgt, zoek de map met de juiste afbeeldingen en gebruik shift-muisklik om ze allemaal te selecteren.&lt;br&gt;
(Klik op de eerste afbeelding, houdt dan &lt;code&gt;SHIFT&lt;/code&gt; ingedrukt en klik op de laatste afbeelding)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lCvLf__F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lprnec8u1ubggwxdm8gr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lCvLf__F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lprnec8u1ubggwxdm8gr.png" alt="Add pngs as animation frames dialog" width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voeg de juiste beelden toe aan alle animaties, en stel de juiste opties in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;alle animaties spelen aan 30 FPS.&lt;/li&gt;
&lt;li&gt;'idle' en 'walk' hebben &lt;code&gt;animation looping&lt;/code&gt; AAN staan (knop icoon is blauw)&lt;/li&gt;
&lt;li&gt;'attack', 'hurt', 'die' hebben het UIT staan (knop icoon heeft zelfde kleur als andere knoppen). Deze animaties spelen maar 1 keer, tot we via code een nieuwe animatie starten.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nu gaan we voor de eerste keer code gebruiken, om onze 'Player' tot leven te brengen!&lt;br&gt;
In het linkerpaneel zorgen we dat de 'Player' geselecteerd is, en klikken we op de knop &lt;code&gt;Attach script&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9u8BsHX6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dpcwiwe2vjoda4me2k4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9u8BsHX6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dpcwiwe2vjoda4me2k4e.png" alt="Attach new script to player scene root node" width="313" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We krijgen een dialoog, waar we een template (voorbeeld) kunnen kiezen, en een naam voor het script. Omdat we onze node 'Player' hebben genoemd, krijgen we automatisch de naam 'Player.gd' als standaard, wat prima is. Klik &lt;code&gt;Create&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3f6zpIDD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/98y5uo6cv8qy53c32wft.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3f6zpIDD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/98y5uo6cv8qy53c32wft.png" alt="Create new script from template" width="594" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ry5eWwsJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8xa7htxf02x6hgoyy1zv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ry5eWwsJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8xa7htxf02x6hgoyy1zv.png" alt="Script editor example screen" width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Je krijgt van Godot nu wat voorbeeldcode voor een platformer, met springen. We hebben springen niet nodig. Je mag alle code wegdoen, behalve de eerste 2 regels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;300.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Omdat we dit script verbinden met onze player &lt;code&gt;node&lt;/code&gt;, en dat een &lt;code&gt;CharacterBody2D&lt;/code&gt; is, start het script met de regel &lt;code&gt;extends CharacterBody2D&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;De tweede regels is de definitie van een constante: we gaan het woord 'SPEED' later in ons script gebruiken, en daar wordt overal de waarde '300' ingevuld. Dit is de loop-snelheid van onze speler. We maken er '400' van.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;400.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We willen dat de speler onze 'held' kan laten bewegen. Hij moet kunnen links-rechts en boven-onder bewegen met de pijltoetsen. Deze logica gaan we in de &lt;code&gt;_physics_process&lt;/code&gt; functie steken: dit is een functie die de Godot engine oproept voor elke &lt;code&gt;game tick&lt;/code&gt;. Standaard is dit 60 maal per seconde. Deze snelheid is vast en hangt niet af van de kracht van je grafische kaart. We willen dat onze speler overal even snel loopt, of je nu een krachtige grafische kaart hebt of niet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ui_left"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ui_right"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
    &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ui_up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ui_down"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
    &lt;span class="n"&gt;move_and_slide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We kunnen dit al testen.&lt;br&gt;
Ga terug naar de game scene en sleep de &lt;code&gt;player.tscn&lt;/code&gt; naar de 'Arena' node, als kind van de node.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YucpzowF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jk0ipxf65bp08477v127.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YucpzowF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jk0ipxf65bp08477v127.png" alt="Drag player onto scene" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Klikken we nu op &lt;code&gt;Run Project&lt;/code&gt; rechtsboven, dan opent onze game en kunnen we met de pijltoetsen onze speler bewegen!&lt;/p&gt;

&lt;p&gt;Er zijn nog een paar basis zaken die ontbreken:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;het personage zelf beweegt niet&lt;/li&gt;
&lt;li&gt;het personage kijkt altijd naar dezelfde kant&lt;/li&gt;
&lt;li&gt;het personage kan 'buiten beeld' lopen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;De eerste 2 punten kunnen we snel oplossen met wat extra code.&lt;/p&gt;

&lt;p&gt;Ga terug naar het script via de &lt;code&gt;Script&lt;/code&gt; knop boven-midden.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2wyKzD3O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bdlwpb7jlsaqodbi9hcc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2wyKzD3O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bdlwpb7jlsaqodbi9hcc.png" alt="Script button screenshot" width="800" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We hebben daarstraks de animaties reeds gemaakt, nu moeten we enkel nog de juiste animatie starten vanuit onze code. Wanneer de speler loopt, spelen we de 'walk' animatie. Als hij stilstaat, spelen we 'idle'.&lt;/p&gt;

&lt;p&gt;De animaties worden getoond door de &lt;code&gt;AnimatedSprite2D&lt;/code&gt; die we aan onze player &lt;code&gt;scene&lt;/code&gt; hebben gehangen. In onze code gaan wie deze &lt;code&gt;node&lt;/code&gt; zoeken en opslaan in een variabele die we 'sprite' noemen. Dit stukje code komt vlak onder onze constante SPEED te staan, en wordt eenmaal uitgevoegd als het spel start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In onze &lt;code&gt;_physics_process&lt;/code&gt; functie kunnen we nu de variabele &lt;code&gt;sprite&lt;/code&gt; gebruiken om een animatie te starten. &lt;/p&gt;

&lt;p&gt;We vervangen het stukje &lt;code&gt;move_and_slide()&lt;/code&gt; door deze blok code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;move_and_slide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"walk"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onze code ziet er dan zo uit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;400.0&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ui_left"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ui_right"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
    &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ui_up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ui_down"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;move_and_slide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"walk"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test of het werkt via die &lt;code&gt;Run Project&lt;/code&gt; knop of de &lt;code&gt;F5&lt;/code&gt; toets.&lt;br&gt;
Het is vaak een goed idee je code te testen na elke kleine wijziging.&lt;/p&gt;

&lt;p&gt;De kijkrichting van de speler wijzigen doen we via een trukje. Je kan de schaal (grootte) van een afbeelding wijzigen, en zelfs de hoogte (y) en breedte (x) apart. Schaal 1 is de originele grootte. Schaal 2 is dan dubbel zo groot. Maar schaal -1 is originele grootte, maar gespiegeld. Als we de sprite schaal voor x veranderen van 1 naar -1 wordt de sprite gespiegeld in de breedte.&lt;/p&gt;

&lt;p&gt;Aan onze &lt;code&gt;_physics_process&lt;/code&gt; functie voegen we het volgende stukje code toe (onder de regels waar &lt;code&gt;velocity.x&lt;/code&gt; en &lt;code&gt;velocity.y&lt;/code&gt; worden ingesteld via &lt;code&gt;Input.get_axis&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De hele code ziet er nu zo uit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gdscript"&gt;&lt;code&gt;&lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;CharacterBody2D&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;400.0&lt;/span&gt;

&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="k"&gt;onready&lt;/span&gt; &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;AnimatedSprite2D&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;_physics_process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_delta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ui_left"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ui_right"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;
    &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ui_up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ui_down"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SPEED&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;move_and_slide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"walk"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Als je het project test, merk je dat het personage nu ook kijkt in de juiste richting als hij loopt.&lt;/p&gt;

&lt;p&gt;Er voor zorgen dat onze speler niet 'buiten beeld' kan lopen doen we in het volgende &lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-3-329"&gt;deel&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>godot</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Een beat-em-up game maken met Godot - de wereld</title>
      <dc:creator>Bgie</dc:creator>
      <pubDate>Fri, 07 Apr 2023 18:38:34 +0000</pubDate>
      <link>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-1-42bi</link>
      <guid>https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-1-42bi</guid>
      <description>&lt;p&gt;In deze tutorial maken we een eenvoudige beat-em-up game met Godot 4.&lt;/p&gt;

&lt;p&gt;NOTE: if anyone cares for an English version, msg me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2SzDBmDv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/27sasdt2grxd2pmiwog6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2SzDBmDv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/27sasdt2grxd2pmiwog6.gif" alt="Full game animation" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Downloads
&lt;/h2&gt;

&lt;p&gt;Zorg eerst dat je Godot geinstalleerd hebt: &lt;a href="https://godotengine.org/"&gt;https://godotengine.org/&lt;/a&gt;&lt;br&gt;
Deze tutorial is gemaakt met versie &lt;code&gt;4.0.1&lt;/code&gt;. Je hebt minstens Godot 4 nodig, een 3.x versie is te verschillend! &lt;br&gt;
Met een hogere versie moet het (normaal) wel lukken.&lt;/p&gt;

&lt;p&gt;Verder heb je de game assets nodig. Deze zijn gratis te downloaden via &lt;a href="https://craftpix.net/"&gt;craftpix&lt;/a&gt;. Volg je deze tutorial via CoderDojo, dan kan je een USB stick vragen aan de coach. &lt;/p&gt;

&lt;p&gt;Download de volgende assets (blauwe 'free download' knop), en pak de zipfiles uit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://craftpix.net/freebies/free-forest-battle-backgrounds/"&gt;de achtergrond&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://craftpix.net/freebies/free-minotaur-tiny-style-2d-sprites/"&gt;het monster (minotaurus)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://craftpix.net/freebies/free-fallen-angel-chibi-2d-game-sprites/"&gt;de 'held'&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;De game assets bevatten meerdere varianten voor de achtergrond of karakters, die kan je ook gebruiken voor deze tutorial, dan ziet jouw game er niet hetzelfde uit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nieuw project maken
&lt;/h2&gt;

&lt;p&gt;Als we Godot openen krijgen we eerst de &lt;code&gt;Project Manager&lt;/code&gt;.&lt;br&gt;
In deze tutorial staat de taal van Godot op Engels. Dat is makkelijker wanneer je hulp zoekt op het internet. Maar je kan de user interface in het Nederlands zetten. De programmeertaal blijft wel op Engels gebaseerd.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tdT_Tgnk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/axwa1r1q7je917haqosn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tdT_Tgnk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/axwa1r1q7je917haqosn.png" alt="Language setting screenshot" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We maken een nieuw project via de &lt;code&gt;New Project&lt;/code&gt; knop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--40ISxKKI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/egnyr0odqf024snpkm5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--40ISxKKI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/egnyr0odqf024snpkm5g.png" alt="New project button screenshot" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In de dialoog geven we ons project een naam bij &lt;code&gt;Project Name&lt;/code&gt; en klikken we op &lt;code&gt;Create Folder&lt;/code&gt; om de nieuwe map te maken voor ons project.&lt;br&gt;
(Indien nodig kan je eerst bij &lt;code&gt;Project Path&lt;/code&gt; kiezen waar je nieuwe map terecht komt.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---OQ1V8ke--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ceibj2b0onmi1jwu63zb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---OQ1V8ke--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ceibj2b0onmi1jwu63zb.png" alt="Create project dialog screenshot - create folder" width="798" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na het maken van de nieuwe map kiezen we &lt;code&gt;Create &amp;amp; Edit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zMYAUzHb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3k7wrp2gij1znr8snnb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zMYAUzHb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3k7wrp2gij1znr8snnb.png" alt="Create project dialog screenshot - create and edit" width="798" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Het hoofdvenster van Godot opent. De belangrijkste onderdelen op het scherm zijn:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QsyYG9ne--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/976x9y96cy98jtr55ic2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QsyYG9ne--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/976x9y96cy98jtr55ic2.png" alt="Godot main window screenshot - parts" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;De hoofdnavigatie: we gaan enkel 2D view en script gebruiken in deze tutorial.&lt;/li&gt;
&lt;li&gt;De &lt;code&gt;scene tree&lt;/code&gt;: een boom met alle onderdelen in de huidige scene. Dit wordt later duidelijk.&lt;/li&gt;
&lt;li&gt;Het &lt;code&gt;file system&lt;/code&gt;: waar alle bestanden te zien zijn die ook op je harde schrijf staan, zoals de afbeeldingen, scripts en scenes in je project.&lt;/li&gt;
&lt;li&gt;De &lt;code&gt;inspector&lt;/code&gt; waar je de &lt;code&gt;properties&lt;/code&gt; (eigenschappen) te zien krijgt van het geselecteerde object in je scene.&lt;/li&gt;
&lt;li&gt;De knoppen vanonder tonen verschillende extra panelen om allerlei editors te openen, afhankelijk welk object in de scene geselecteerd is.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Het middenstuk van het scherm toont de game scene zelf (als &lt;code&gt;2D&lt;/code&gt; gekozen is) of toont het script waar je aan werkt (als &lt;code&gt;Script&lt;/code&gt; gekozen is)&lt;/p&gt;

&lt;p&gt;Omdat we een leeg project hebben, is er niet veel te zien, maar wanneer als je een bestaande game open hebt, ziet dit scherm er zo uit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4l_yy-nT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qeyk2vbcrht7pqtms8r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4l_yy-nT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qeyk2vbcrht7pqtms8r.png" alt="Godot main window screenshot - finished game" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Game assets kopiëren
&lt;/h2&gt;

&lt;p&gt;We gaan eerst onze graphics kopiëren. &lt;br&gt;
Door rechts te klikken op &lt;code&gt;res://&lt;/code&gt; in het &lt;code&gt;FileSystem&lt;/code&gt; paneel openen we een menu. Daar kunnen we &lt;code&gt;Open in File Manager&lt;/code&gt; kiezen om een verkenner venster te krijgen. Dit hangt af van je besturingssysteem (Windows, Mac, Linux).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G69iZTiw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x828py4uzrsqjzuwyh8j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G69iZTiw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x828py4uzrsqjzuwyh8j.png" alt="Open in file manager context menu screenshot" width="413" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kopieer de juiste submappen vanuit je downloads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Downloads/craftpix-net-270096-free-forest-battle-backgrounds/PNG/game_background_1&lt;/li&gt;
&lt;li&gt;Downloads/craftpix-991117-free-fallen-angel-chibi-2d-game-sprites/Fallen_Angels_2/PNG/PNG Sequences&lt;/li&gt;
&lt;li&gt;Downloads/craftpix-net-484869-free-minotaur-tiny-style-2d-sprites/PNG/Minotaur_01/PNG Sequences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;... naar je Godot project map die we net openden. Ik heb zelf mapjes gemaakt met duidelijke namen om alles makkelijk terug te vinden.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q_DfUaRV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ktjwuzixaxo44g6gbuqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q_DfUaRV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ktjwuzixaxo44g6gbuqy.png" alt="Asset tree structure screenshot" width="183" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Een scene maken met nodes
&lt;/h2&gt;

&lt;p&gt;We starten met een eenvoudige achtergrond en een vaste camera, die niet beweegt.&lt;/p&gt;

&lt;p&gt;Onze &lt;code&gt;scene&lt;/code&gt; heeft een &lt;code&gt;root node&lt;/code&gt; nodig, het beginpunt van alles. Omdat onze game 2D is, kiezen we voor een &lt;code&gt;2D Scene&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gsfMANZk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fu7fd7sl28en7hh64k3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gsfMANZk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fu7fd7sl28en7hh64k3a.png" alt="Root node screenshot" width="237" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Met de &lt;code&gt;+&lt;/code&gt; (plus) knop kunnen we nodes toevoegen aan onze scene. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uLUiBeRE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j1qv4jg987rq0zl13b0s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uLUiBeRE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j1qv4jg987rq0zl13b0s.png" alt="Add node screenshot" width="246" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nu krijgen we de &lt;code&gt;Create New Node&lt;/code&gt; dialoog waar we moeten aangeven welke soort node we willen toevoegen. Via het zoekvak boven kiezen we voor een &lt;code&gt;Sprite2D&lt;/code&gt;, dit is de soort node voor een gewone, 2D tekening zonder animaties.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tupvrJEB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xpa96e5nnxlvj51fo3yn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tupvrJEB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xpa96e5nnxlvj51fo3yn.png" alt="Create New Node screenshot" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Onze nieuwe node komt bij in de &lt;code&gt;scene tree&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We maken nog een aantal nodes bij: een &lt;code&gt;StaticBody2D&lt;/code&gt;, nog een &lt;code&gt;Sprite2D&lt;/code&gt;, en een &lt;code&gt;Camera2D&lt;/code&gt;. &lt;br&gt;
Let erop dat alle nieuwe nodes op hetzelfde niveau zitten. Je kan een node 'onder' een andere node hangen. We willen al onze nodes onder de root node. De volgorde van de nodes is ook belangrijk.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jiqO9Qd_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vg9z0veansqxjpbujxst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jiqO9Qd_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vg9z0veansqxjpbujxst.png" alt="Scene tree with new nodes" width="278" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voor de duidelijkheid gaan we onze nodes een goede naam geven. Dit doe je door een node aan te klikken, even te wachten, en opnieuw te klikken. Je kan ook rechts klikken en &lt;code&gt;Rename&lt;/code&gt; kiezen of &lt;code&gt;F2&lt;/code&gt; gebruiken.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1Pm5FeOl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uryyabi3zf8l38diw1r3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1Pm5FeOl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uryyabi3zf8l38diw1r3.png" alt="Scene tree with renamed nodes" width="276" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;de root node wordt 'Game'&lt;/li&gt;
&lt;li&gt;de eerste sprite wordt 'Background'&lt;/li&gt;
&lt;li&gt;de static body wordt 'Arena'&lt;/li&gt;
&lt;li&gt;de tweede sprite wordt 'Foreground'&lt;/li&gt;
&lt;li&gt;de camera noemen we gewoon 'Camera'&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dit is een goed moment om op te slaan. Dit kan met &lt;code&gt;Ctrl+S&lt;/code&gt; of in de hoofdmenu &lt;code&gt;Scene&lt;/code&gt; - &lt;code&gt;Save Scene&lt;/code&gt;.&lt;br&gt;
Omdat dit de eerste keer is, krijgen we een dialoog. De naam 'Game' van onze root node is een goede naam voor de scene. Klik gewoon &lt;code&gt;Save&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oZ9fpbrX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbucgcipzev899xbb1tn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oZ9fpbrX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbucgcipzev899xbb1tn.png" alt="Save scene dialog screenshot" width="686" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Achtergrond en camera
&lt;/h2&gt;

&lt;p&gt;De achtergrond afbeelding instellen is nu makkelijk: klik links om de 'Background' node te selecteren, en klik dan in het &lt;code&gt;Inspector&lt;/code&gt; paneel op het kleine pijltje naar beneden bij &lt;code&gt;Texture: &amp;lt;empty&amp;gt;&lt;/code&gt;. In het menu kies je helemaal beneden voor &lt;code&gt;Load&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mE6tO81_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/irytqt0bqz0j6w7rh08s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mE6tO81_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/irytqt0bqz0j6w7rh08s.png" alt="Load sprite texture screenshot" width="372" height="828"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Je krijgt een dialoog waar we bladeren tot we &lt;code&gt;game_background_1.png&lt;/code&gt; hebben gevonden. Bij mij is het pad &lt;code&gt;res://assets/background/game_background_1.png&lt;/code&gt; omdat ik een submap &lt;code&gt;assets&lt;/code&gt; heb gemaakt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wSRRZ0jy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6490eepj2u6vhbqg8l1s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wSRRZ0jy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6490eepj2u6vhbqg8l1s.png" alt="Load background image dialog screenshot" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voor de 'Foreground' sprite doen we hetzelfde, maar we gebruiken een andere afbeelding: enkel de voorste laag van ons bos, waar er vanonder een strookje gras staat met een dikke steen: &lt;code&gt;res://assets/background/front_decor.png&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Door met 2 sprites te werken kunnen later onze karakters achter het voorste gras lopen, wat er realistischer uitziet.&lt;/p&gt;

&lt;p&gt;Je kan controleren of de twee sprites correct zijn door ze tijdelijk onzichtbaar te maken. Als de 'Background' sprite onzichtbaar is, moet je enkel de strook gras op de voorgrond zien.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sAXnFTWq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9g7ugey8vs9vpquxhtyj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sAXnFTWq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9g7ugey8vs9vpquxhtyj.png" alt="Background hidden screenshot" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Laatste stap in het instellen van de camera: voor dit eenvoudige spel staat de camera gewoon stil. Maar onze achtergrond afbeelding is erg groot, we gaan de camera wat uitzoomen.&lt;/p&gt;

&lt;p&gt;Selecteer de 'Camera' node en stel rechts de &lt;code&gt;Zoom&lt;/code&gt; in op &lt;code&gt;0.5&lt;/code&gt;. Beide waarden zijn verbonden, dus je moet dit maar 1 keer doen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vabnHCVH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grx0q6i6qigexzuir6pu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vabnHCVH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/grx0q6i6qigexzuir6pu.png" alt="Set Camera zoom screenshot" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We hebben nu het minimum gedaan om onze 'game' te kunnen testen. Klik op de &lt;code&gt;Run Project&lt;/code&gt; knop of druk &lt;code&gt;F5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kNZFLPdp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jphk9zqmwywof9n360nx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kNZFLPdp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jphk9zqmwywof9n360nx.png" alt="Run project button screenshot" width="428" height="95"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Omdat dit de eerste keer is dat we onze game uitvoeren, vraagt Godot welke scene de opstart-scene moet worden. We hebben maar 1 scene ('Game') en dat is de huidige. Dus kies gewoon &lt;code&gt;Select Current&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--81P3wynp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypagk5ah5dzlehrhgkiz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--81P3wynp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypagk5ah5dzlehrhgkiz.png" alt="First run select main scene dialog screenshot" width="645" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na een laad-scherm start onze game. Standaard is het venster 1152x648 pixels groot. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FzpRtaWX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/75qyh2s3c6mk1kkg7mr6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FzpRtaWX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/75qyh2s3c6mk1kkg7mr6.png" alt="First game run screenshot small window" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Je kan het venster maximaliseren, en dan zou je de hele afbeelding van het bos moeten zien, als je computermonitor op HD 1920x1080 staat.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cqAqMIhe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f4arlqsobmctvmnu9hz3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cqAqMIhe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f4arlqsobmctvmnu9hz3.png" alt="First game run screenshot maximized window" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tot zover deel 1. &lt;br&gt;
In &lt;a href="https://dev.to/bgie/een-beat-em-up-game-maken-met-godot-4-deel-2-4af9"&gt;deel 2&lt;/a&gt; gaan we onze speler toevoegen en tot leven brengen met code.&lt;/p&gt;

</description>
      <category>godot</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
