I understand from reading the wikipedia page on the different methods of implementing it that you create an error variable and loop through every value between the two points X components, then you add the slope of the line to the error until it reaches over 0.5 and then you increase the Y component and subtract 1 from the error.

That's the simple implementation which has different cases to handle shallow lines (iterate over x conditionally changing y) and steep lines (iterate over y conditionally changing x). This code is considerably cleverer: it combines the cases into a single loop using multiple tests.

I also understand that this is more or less what's happening above using integer arithmetic rather than floating point arithmetic although I'm not entirely sure why error needs to be multiplied by 2

You mentioned that in the simple implementation you need to compare the error to 0.5. To do that in integers you compare twice the error to 1.

or what the significance of this being over -dy or under dx is.

That's where it gets really clever.

To analyse a loop you want to ask three main questions: does the loop always do something? What are its invariants? Does it stop?

In this case, since

`dx` and

`dy` are both non-negative by design, the only way to fail both tests

`e2 > -dy` and

`e2 < dx` if is

`e2 == -dy == dx == 0`, in which case we will certainly hit the break before getting to either of the tests. Since

`dx` and

`dy` don't change, we conclude that the loop always does something.

For the invariants, look at the changes.

`err -= dy; xx0 += stepx;` induces the invariant

`err * stepx + xx0 * dy = constant`.

`err += dx; yy0 += stepy;` induces the invariant

`err * stepy - yy0 * dx = constant`. You can look at the values before entering the loop to find out what the constants are.

I hope that gets you on the right track.