ikbensiep / lofigame

A 2D game without canvas, only html vibes. SVG is used not only for artwork but to annotate as much world/level data as possible, simply by drawing shapes accoring to a few rules. Exploring wether it's worthwile to make it into an open source 2d world game engine.
https://ikbensiep.github.io/lofigame/
GNU General Public License v3.0
1 stars 0 forks source link

iscarontrack: implements dirt attrition when the car is outside of the racetrack #23

Closed ikbensiep closed 9 months ago

ikbensiep commented 9 months ago

This PR implements dirt attrition when the car is outside of the racetrack (ie, slowing down), closing #8.

It uses the <g id="track"> layer loaded into the visually hidden iframe, to test the players x/y coordinates against <path id="racetrack">, using the svg method isPointinStroke().

This also meant a bit of a redo of track files (which were due for an overhaul anyway) to make sure a track complies with a few rules. Most notably, the track itself now must be the stroke on a vector path. In a previous version of the game we could get by with any vector shape as long as the track had a certain color. Read more below on the why and the how:

With trying this approach I can circumvent having to do a whole bunch of Pythagorean math to determine the on/off track status. The initial idea was to measure how far off the player is from an imagined straight line between the next and previous waypoints (by measuring the distance of a normal line square off of this line): image

Using the svg method(s) instead came at a price though. Chrome and Firefox are a bit fuzze on the documentation wether one should use new DOMPoint() or svg.createSVGPoint(). To top it off not all track files worked in the exact identical way, so when I was getting a lot off false responses to my checks it didn't occur to me that the path(s) I was doing checks on were not being rendered to screen and thus the function would always return false.

Because of some confusing results and me thinking the Stroke was too thin, I tried turning all stokes into svg shapes to test against that. Now I was getting some more confusing results, thinking that this method would test against an outer path (note how the path on the right has basically two outlines and a black will, because it is a shape with a hole punched into it, whereas the image on the left is just one stroked path without a fill color):

image

It took me way too long to realize that this method, along with its counterpart, isPointInFill(), require the svg to actually be drawn to the screen somewhere. This may sound logical, but I assumed that, since we can .querySelect() for paths on a visually hidden svg and read their xml properties -and the paths are really only a bit of math- these methods should always return correct information.

The iframe's job is to load in the entire svg, so that the entire svg file will have already been loaded when rendering out the separate layers of the svg in an img tag. Therefore, I put it in a hidden element along with some other items I want to preload. Turns out, I needed to not hide the iframe (well, not hide it entirely: of course I might still obscure it). But we still need it to be there!

Eddy's note: I'm writing this the day after and can't be bothered to find the SO link I found explaining an error I got saying stuff about a non-rendering element leading me to this insight

SVG track file rule changes

Once this confusion was cleared up, I was getting reliable results and that's where I made the decision to only stick with #racetrack's stroke outline.

This means we can definitively do away with the separate #path layer that used to house all the differently colored surface layers which would determine max speed / driveability, since we can check the actual #racetrack path that also gets rendered to screen. Less magic is good. image Old track file with a dedicated #path layer, containing separate colored shapes to give meaning to the surfaces.

So, with this change we'll now always be testing against the #racetrack outline/stroke. I'm actually in favor of this rule, and have been, because it makes laying out the track easier and consistent; in some cases i'd cheated and turned the racetrack into a filled shape, for example so that I could give it a little white outline to mark the track edge. Doing a track outline like that now means that you have to duplicate the #racetrack path, put this new copy below the racetrack and then increase the stoke width by a few pixels and make it light colored to make it outline the .. other outline :P image Example. Note how the racetrack outline is the exact same path, just a bit wider so that its color peeks out from underneath the racetrack surface.