This week I worked on a lot of projects, some of which were even game development related (go figure!). Along the way I also got a little more conversant with my new editor of choice Sublime Text, worked a bit more with Wren and decided to leave it alone for now to mature a bit, and grappled with the HTML5 canvas and its handling of linear gradients.
All in all, an action packed week!
Lets hit those topics in order, shall we?
Firstly, the more I use Sublime Text (which is a lot; I’m using it for pretty much everything outside of a console currently, where vim still reigns supreme) the more I like it. It is fast, snappy and responsive. More importantly, if I notice something that it doesn’t do that I wish it did, it’s plugin API allows me to fix that shortcoming (if I have the wherewithal that is).
I’ve become somewhat active in the Sublime Text fourms, trying to field questions on the software where I can. At this stage this often involves me doing research to see if/what the actual answer is. So as a side effect of being helpful, I get to know more about Sublime itself. Or more likely, I get to know more about Sublime and help people as a side effect.
Here we transition into topic number 2; Wren. As a nice dovetail (hah, bird pun!) here, some of what I did involved making my own custom Sublime build system that matches how I usually set up my projects, with a Makefile per directory that builds from the current location down to the leaves of the tree. This is in contrast to the Sublime default, which assumes a single Makefile in the project root.
That done (including a special run target to make life easier) I wrenched a little more on my sample wren code. I hit another roadblock in the vm due to it’s (current) non-re-entrant behaviour, this time in regards to instance fields.
In Wren, instance variables are called into existence by just using them, the caveat being that you’re forced to prefix their names with an underscore. This is yet another thing about Wren that kinda rubs me the wrong way; making the grammar of the language smaller by forcing code style.
Any misgivings of that aside, I am unable to find any way to get at the values of instance variables from inside C code in a foreign method. As far as I can see, no API is currently defined to allow access to those kinds of slots in the class. Although Wren fully supports getter/setter methods (with a nice syntax) you can’t invoke them.
I’m left to assume that the solution to this problem is the same as the previous problem I had, which is that your foreign method needs to accept fields as a parameter and have a method defined in Wren code that acts as a proxy, passing your field in. This works, but makes changing the value of a field a problem since functions can only return a single value.
For the time being I’m going to leave Wren alone to let it mature a little bit more. I know that some of the stuff that I don’t like about it (that forced style) is not going to go away, but the API is only going to get more fleshed out as development continues, so the future is going to be bright, I think.
Stepping away from Wren, I got to work on exercise 8 of ts-breakout, which is to include a title screen. Here I’ve sort of branched away a little from the specifics of the exercise and am honouring it in spirit instead.
In particular, the exercise calls for the title screen showing you the score of the last game, but I am instead showing the high score. The idea in the exercise is that this lets the player see what their score was if they were not paying attention when the game ended.
In my case, I plan to have a game over screen (stub already in place) that leads back to the title screen, so this is not strictly needed as it can be displayed there, somewhat more naturally.
Currently the title screen is implemented and working; it will transition to the game, and the game will transition to the game over screen. There is still a bit more work to do, such as actually implementing the game over screen, but we’re mostly there!
Operations got somewhat stalled out when I decided to make the title of the game render with a gradient representing all of the brick colors. Here’s what the title screen currently looks like with that in place:
I envisioned the gradient itself doing a slow scroll, making the title text look animated. Unfortunately due to difficulties in how gradients actually work in HTML canvas applications, I have not gotten that far just yet.
A gradient (a linear one, in our case) is created by giving the coordinates of a line in canvas space. Any point that falls past the extents of the line that represents the gradient is rendered using the color of the gradient line at that point, with anything past the ends being an extension of the color at the appropriate end.
Once the gradient is created, you can add any number of color stops to it, giving a position (between 0.0 and 1.0) and the color at that point. Then it’s a simple matter of setting the gradient as the fill style when you render the text.
So for example, that might look something like:
let gradient = canvas.context.createLinearGradient (0, 0, textWidth, 0); gradient.addColorStop (0.0, 'red'); gradient.addColorStop (0.5, 'green'); gradient.addColorStop (1.0, 'blue');
This creates a gradient that blends from red to green to blue over a distance of textWidth (whatever that may be). Here’s the thing; the gradient size/position you specify is not affected at all by the transform, which can cause you troubles.
In my case, I am rendering the title text centered with something similar to:
canvas.context.translate (canvasWidth / 2, 25); canvas.context.textAlign = 'center'; canvas.context.textBaseline = 'middle';
Herein lies the problem: that translate operation makes the (0, 0) point of the canvas be 25 pixels from the top and right in the center of the canvas horizontally, and with the other parts, this renders the text centered. However, the location of the gradient does not take the translation into account (by design) and as such everything to the left of the center of the screen is flat shaded as red, and then the gradient runs from red->green->blue starting in the center of the text.
The solution to this problem is to create the initial gradient object to take this into account; everything to the left of the origin is a negative value, so the following is how you would create the initial gradient object:
let gradient = canvas.context.createLinearGradient (-(textWidth / 2), 0,textWidth / 2, 0);
With that change in place, everything works as expected. In fact even without this particular method of centering text, this would not have worked the way I wanted. The original gradient will only color items in the range of 0 to textWidth after all translations are applied. The lesson here is to always create the gradient knowing where the rendered item will finally be when it is actually rendered.
Unfortunately, it took me a little while to realize that’s what was happening, why it was happening, and how to work around it. I assume this is exactly how this should work as far as people in the know about computer graphics are concerned, but for my simple purposes here this seems entirely non-intuitive.
Like working with Sublime, it was a good excuse to learn something new though, so all’s well that ends well!