Skip to content

Latest commit

 

History

History
97 lines (45 loc) · 5.64 KB

enemies.adoc

File metadata and controls

97 lines (45 loc) · 5.64 KB

Enemies

In the original game the shape of the "enemies" is defined in a large class and they are created in waves. For this tutorial we keep it simpler. We have some predefined enemy arrangements that repeat themselves.

Let’s first introduce a new type Enemy:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="26:30", language="elm" %}{% endcodesnippet %}

  • radius: the distance of the enemies to the center

  • parts: a list of true/false that indicate where the enemy has a "hole"

We add a list of enemies to the game state as well as enemySpeed which will increase over time.

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="31:45", language="elm" %}{% endcodesnippet %}

We also need to add new initial states for our game:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="352:371", language="elm" %}{% endcodesnippet %}

We further define the constant values enemyThickness, enemyDistance, enemyInitialSpeed and enemyAcceleration:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="67:70", language="elm" %}{% endcodesnippet %}

Our enemies are made out of trapezoids, so that they occupy 1-5 sectors of the hexagon. We configure one enemy with an array of booleans, where True indicates an occupied sector and False a hole. We define a fixed set of enemies:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="72:82", language="elm" %}{% endcodesnippet %}

You can chose whatever configuration you like, just make sure that you keep one side open ;-)

As you may have noticed, we have only defined the parts property of the Enemy type so far. The radius will represent the distance to the center (and therefore to the player) and we will calculate it in the update-function.

Updating radius

Let’s introduce two new functions in the onFrame function that will update enemies and enemySpeed on the game state:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="192:213", language="elm" %}{% endcodesnippet %}

updateEnemySpeed will slowly increase enemySpeed over time starting with an initial value:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="160:163", language="elm" %}{% endcodesnippet %}

updateEnemies is a little bit tricky. Let’s first take a look at the whole function:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="140:158", language="elm" %}{% endcodesnippet %}

The enemies will approach the player over time. We represent this as the enemyProgress:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="143:143", language="elm" %}{% endcodesnippet %}

As we have only a fixed set of enemies, we need them to repeat after all have passed the player. We do this by defining a maxDistance that is the total radius of all enemies.

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="144:145", language="elm" %}{% endcodesnippet %}

The enemies should repeat whenever enemyProgress exceeds this maxDistance. You see this in radiusFor where we calculate the radius for every enemy modulo maxDistance:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="150:152", language="elm" %}{% endcodesnippet %}

offsetForEnemy represents the distance for a single enemy.

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="147:148", language="elm" %}{% endcodesnippet %}

We subtract the enemyProgress, so that value will be negative (for most enemies). But because we take the modulo maxDistance of it, it will always be between 0 and maxDistance and will decrease for every enemy over time.

Display enemies

First we need a function to create a trapezoid:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="240:248" %}{% endcodesnippet %}

We will now use this function to create a trapezoid for every occupied part of any enemy:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="250:262" %}{% endcodesnippet %}

This function returns a Form that contains a group of these trapezoids. Notice how we filter out parts by creating a tuple of (index:Int, part:Bool), removing parts where part is False and sending the index to makeEnemyPart. Pure functional magic:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="261:262", language="elm" %}{% endcodesnippet %}

The following function makeEnemies will create a List(Form) for every enemy:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="264:266", language="elm" %}{% endcodesnippet %}

Finally we add this function to our view function:

{% codesnippet "https://raw.githubusercontent.com/macrozone/elm-hexagon-tutorial/chapter/enemies/src/Hexagon.elm", lines="320:338", language="elm" %}{% endcodesnippet %}