Pac-Man: The Untold Story of How We Really Played the Game - intriguing description of how generations of right-hand Pac-Man players clutching the left side for leverage leaves its mark on the old upright cabinets.
Interesting how Pac-Man, which like Q*bert was button free, was ambidextrous. Nintendo famously put the crosspad under the left thumb, which may have heralded a switch in games away from being focused on rough movement and towards precision timing. (Continued with the WASD/mouselook arrangement favored by PC gamers- something I've never quite gotten into my skin.)
Thursday, February 28, 2019
videogames and the modern ul techstack
On my "regular" (now almost two-decades-old) blog - Just Cause 3 as Psychological Self-Care. Interesting to think about how games' "you can do this and persistence is always repaid" might help counteract the frustration with UI tech stacks that don't do a great job scaling down into quick "throw these on your personal webserver" projects...
Monday, February 18, 2019
is dotAll you got? (frustrations with firefox multiline string matching)
There's growing discontent among developers with Chrome as a browser (and the risk of it becoming a kind of monoculture in the way IE was, albeit not quite as crappily and a bit more standards-compliant) and many are making the leap to Firefox. And recently I was delighted to see that the developer tools were pretty much at parity with Chrome's, and used many of the same UI patterns as well.
But I found Firefox was choking on some regular expressions I put into the backend tooling for my website.
So to quote T.J. Crowser in StackOverflow:
I wish I knew more about the history here - feels like Firefox was sticking to the spec more righteously than Chrome, which I guess is fair enough, but why was such a critical piece missing from JS/ECMAScript in the first place? It smells a little bit like some religious war fallout, some coders didn't like multiline conceptually, or something...
But I found Firefox was choking on some regular expressions I put into the backend tooling for my website.
SyntaxError: invalid regular expression flag sThat s flag, letting an expression like /(.*)/s match multiple lines (because it says to treat linebreaks as normal whitespace-ish stuff) was a critical tool going back to my Perl days...
So to quote T.J. Crowser in StackOverflow:
You are looking for theHis examples then show `[\s\S]` replacing good old `.`. I'm happy to have the workaround, but man is that an ugly one!/.../s
modifier, also known as the dotall modifier. It forces the dot.
to also match newlines, which it does not do by default.
The bad news is that itdoes not exist in JavaScript(it does as of ES2018, see below). The good news is that you can work around it by using a character class (e.g.\s
) and its negation (\S
) together, like this:
[\s\S]
I wish I knew more about the history here - feels like Firefox was sticking to the spec more righteously than Chrome, which I guess is fair enough, but why was such a critical piece missing from JS/ECMAScript in the first place? It smells a little bit like some religious war fallout, some coders didn't like multiline conceptually, or something...
p5 and figure-ground reversal fun
I have a notebook from when I was 18, the summer before college.
I had designed T-shirts for my high school's jazz band the years previous, and I guess the band was still the focus of tooling around with some design stuff, and so I made this:
I've always enjoyed handcrafting blockletters, and I believe I made these by drawing the 3D extrusion behind the letters and then just filling in the extruded bits on the page in front.
Anyway, I realized I can now have the mojo to get a computer to do most of the work for me, and so I made fgrtext: figure-ground reversal (the fancy word I saw for it on wikipedia's entry for negative space.) It's a little virtual toy to mess around with the words, colors and other factors.
I made it so you can bookmark creations - here are some designs I made for 222 Street Jazz:
BABAM!
and JP Honk:
You can view source on the page to see everything in one file. The core idea is pretty simple - keep drawing the letters repeatedly in the "foreground" color on a diagonal slant, and then switch to the background color and keep drawing the letters a few more times. There were some challenges in the P5 code for it - they have a library for DOM elements and oddly (to me anyway) you set their .parent() after creation of them, otherwise they just end up attached directly to the body of the DOM, which is kind of weird. (Also since they didn't seem to support textareas, it was pretty easy to manually set up the HTML for that and use vanilla JS onkeyup events to call my functions directly, a bit of mix and match.) One drawback to the sliders was I had to only pay attention to mouse moves withing the boundaries of the main canvas - slider adjustments were showing up as background/foreground movements.
Also I made creations in this system bookmarkable by putting all the parameters in a state object and then encoding the JSON stringified version of that as the hash at every draw(), and then reading the hash at start.
Another courtesy I do is using noLoop() to only draw when the state has changed - p5 is great for many things but processor efficiency isn't one of them.
I had designed T-shirts for my high school's jazz band the years previous, and I guess the band was still the focus of tooling around with some design stuff, and so I made this:
I've always enjoyed handcrafting blockletters, and I believe I made these by drawing the 3D extrusion behind the letters and then just filling in the extruded bits on the page in front.
Anyway, I realized I can now have the mojo to get a computer to do most of the work for me, and so I made fgrtext: figure-ground reversal (the fancy word I saw for it on wikipedia's entry for negative space.) It's a little virtual toy to mess around with the words, colors and other factors.
I made it so you can bookmark creations - here are some designs I made for 222 Street Jazz:
BABAM!
and JP Honk:
You can view source on the page to see everything in one file. The core idea is pretty simple - keep drawing the letters repeatedly in the "foreground" color on a diagonal slant, and then switch to the background color and keep drawing the letters a few more times. There were some challenges in the P5 code for it - they have a library for DOM elements and oddly (to me anyway) you set their .parent() after creation of them, otherwise they just end up attached directly to the body of the DOM, which is kind of weird. (Also since they didn't seem to support textareas, it was pretty easy to manually set up the HTML for that and use vanilla JS onkeyup events to call my functions directly, a bit of mix and match.) One drawback to the sliders was I had to only pay attention to mouse moves withing the boundaries of the main canvas - slider adjustments were showing up as background/foreground movements.
Also I made creations in this system bookmarkable by putting all the parameters in a state object and then encoding the JSON stringified version of that as the hash at every draw(), and then reading the hash at start.
Another courtesy I do is using noLoop() to only draw when the state has changed - p5 is great for many things but processor efficiency isn't one of them.
Saturday, February 16, 2019
ripping music the old-fashioned way
In the beginning (well, my beginning anyway) there were LPs and my parents old 33s. Then cameth cassette tapes and behold the radiant wonder of the CD. Upon this time was a golden age of mixtapes, whereupon one might assemble a cherrypicked selection of tunes (and come on - some may disagree but wouldn't you say most albums are a few good songs and a bunch of filler?) for thine only pleasure or to pitcheth a bit of woo... (gettest thou to the High Fidelity if you are ill-informed of this most wond'rous art.)
There was a brief interval when "mix-CDs" were also kind of a thing - an impressive feat to make one in the mid-90s, when blank CDs were like $25 a pop and a "buffer underrun error" would leave your CD as nothing more than a pretty coaster or frisbee...
But then things went digital even before portable MP3 players (most famously the iPod) really took off. And when laptops were still price luxuries... not sure how we listened to our music, maybe with computer desktop speakers? Anyway, "Napster" was the darling of the turn of millennium - a co-operative venture that would let you nab pretty much any song you could think of. That was amazing! But, it failed to produce a good method of getting money back to artists...and so Napster was crushed, and for a while there was nothing that replaced it - if you read about a tune and wanted to hear a sample of it, you were probably out of luck.
Eventually, things got better. Online music stores emerged (and Apple dropped its DRM), Youtube coverage of esoteric tracks got about as complete as Napster was, and then came the rise of streaming - a trend I still don't really get. (I sort of see the appeal of customized robo-DJs, but man, I just don't want to encounter that much new so-so music all the time. I prefer buying MP3s, listening to my "recently added" playlist to get acclimated to songs, and keeping all my music even if I stop using a service.)
ANYWAY. There are still some songs or amateur-musicaly-things that aren't available for purchase or other legit download. For a a long while Convert2MP3 did a good job of ripping tracks, but with the rise of Youtube's own attempts at subscription music services, this no longer works for most music tracks (I think it still is an option for some other things that Youtube doesn't categorize as music.)
I figure that with my multiple laptops and tablets I would be able to do rips manually - that a stereo wire with a plug on both ends would let one device playback and the other to record. Turns out it wasn't quite that easy? There are some rumors that Macs' lone audio port used to be able to be used as an input device, but maybe later versions of the OS stopped supporting that. An old Windows 8 laptop didn't seem much better about it.
So not wanting to resort to "be in a really quiet room and use the built-in mic for recording", I bought a USB mic and speaker dongle for like $7, and was then able to use Audacity. I have one wire from the headphone jack on an iPad and it goes right into the microphone dongle, so there's no room noise. I wasn't quite sure how to set the levels, but fiddling with the iPad volume while recording some throwaway tracks 'til the visualization showed consistent filling of most but not all off the space seemed to work ok.
I do worry over time this path will be shut down somehow - already it was awkward. I would have needed a dongle to do it from my iPhone, of course, and if my main Macbook was newer I wouldn't have needed a USB-C dongle for that as well ... and that's beyond obscure technologies that will strive to prevent this kind of shenanigans (like if you try to record video from a secure playback source, or for that matter how photocopiers will recognize currency and decline to duplicate it...)
There was a brief interval when "mix-CDs" were also kind of a thing - an impressive feat to make one in the mid-90s, when blank CDs were like $25 a pop and a "buffer underrun error" would leave your CD as nothing more than a pretty coaster or frisbee...
But then things went digital even before portable MP3 players (most famously the iPod) really took off. And when laptops were still price luxuries... not sure how we listened to our music, maybe with computer desktop speakers? Anyway, "Napster" was the darling of the turn of millennium - a co-operative venture that would let you nab pretty much any song you could think of. That was amazing! But, it failed to produce a good method of getting money back to artists...and so Napster was crushed, and for a while there was nothing that replaced it - if you read about a tune and wanted to hear a sample of it, you were probably out of luck.
Eventually, things got better. Online music stores emerged (and Apple dropped its DRM), Youtube coverage of esoteric tracks got about as complete as Napster was, and then came the rise of streaming - a trend I still don't really get. (I sort of see the appeal of customized robo-DJs, but man, I just don't want to encounter that much new so-so music all the time. I prefer buying MP3s, listening to my "recently added" playlist to get acclimated to songs, and keeping all my music even if I stop using a service.)
ANYWAY. There are still some songs or amateur-musicaly-things that aren't available for purchase or other legit download. For a a long while Convert2MP3 did a good job of ripping tracks, but with the rise of Youtube's own attempts at subscription music services, this no longer works for most music tracks (I think it still is an option for some other things that Youtube doesn't categorize as music.)
I figure that with my multiple laptops and tablets I would be able to do rips manually - that a stereo wire with a plug on both ends would let one device playback and the other to record. Turns out it wasn't quite that easy? There are some rumors that Macs' lone audio port used to be able to be used as an input device, but maybe later versions of the OS stopped supporting that. An old Windows 8 laptop didn't seem much better about it.
So not wanting to resort to "be in a really quiet room and use the built-in mic for recording", I bought a USB mic and speaker dongle for like $7, and was then able to use Audacity. I have one wire from the headphone jack on an iPad and it goes right into the microphone dongle, so there's no room noise. I wasn't quite sure how to set the levels, but fiddling with the iPad volume while recording some throwaway tracks 'til the visualization showed consistent filling of most but not all off the space seemed to work ok.
I do worry over time this path will be shut down somehow - already it was awkward. I would have needed a dongle to do it from my iPhone, of course, and if my main Macbook was newer I wouldn't have needed a USB-C dongle for that as well ... and that's beyond obscure technologies that will strive to prevent this kind of shenanigans (like if you try to record video from a secure playback source, or for that matter how photocopiers will recognize currency and decline to duplicate it...)
Thursday, February 14, 2019
drawing x1,y1,x2,y2 lines (any angle) with divs
When I was playing with different technologies for my timelines project Timelines project one advantage P5 had over straight DOM-stuff was being able to draw arbitrary lines (I was already using a lot of X/Y coordinate absolute positioning, rather than letting things flow)
Not surprisingly it's pretty easy to do similar in DOM and CSS, using transform rotations and just a bit of geometry.
The core CSS could be
.line {
height:1px;
background-color: #000;
position: absolute;
transform-origin: top left;
}
(the container div should be be styled position:relative or similar)
and then the JS something like
function addLine(id,x1,y1,x2,y2) {
const canvas = document.getElementById(id);
const newLine = document.createElement("div");
newLine.classList.add("line");
const length = Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
const ang = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
newLine.style.top = `${x1}px`;
newLine.style.left = `${y1}px`;
newLine.style.width = `${length}px`;
newLine.style.transform = `rotate(${ang}deg)`;
canvas.appendChild(newLine);
}
I created a codepen proof of concept but didn't make it do anything interesting.
Of course, this doesn't hold a candle to stuff like Diana Adrianne's pure-CSS oilpaintings but it's a start :-D (For that matter, arguably I'm just reinventing svg, badly...)
Not surprisingly it's pretty easy to do similar in DOM and CSS, using transform rotations and just a bit of geometry.
The core CSS could be
.line {
height:1px;
background-color: #000;
position: absolute;
transform-origin: top left;
}
(the container div should be be styled position:relative or similar)
and then the JS something like
function addLine(id,x1,y1,x2,y2) {
const canvas = document.getElementById(id);
const newLine = document.createElement("div");
newLine.classList.add("line");
const length = Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
const ang = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
newLine.style.top = `${x1}px`;
newLine.style.left = `${y1}px`;
newLine.style.width = `${length}px`;
newLine.style.transform = `rotate(${ang}deg)`;
canvas.appendChild(newLine);
}
I created a codepen proof of concept but didn't make it do anything interesting.
Of course, this doesn't hold a candle to stuff like Diana Adrianne's pure-CSS oilpaintings but it's a start :-D (For that matter, arguably I'm just reinventing svg, badly...)
Tuesday, February 12, 2019
design failure - when numbers confuse
I am one of the organizers for BABAM, a Boston-based alliance of activist musicians. We had some internal debate about whether it was appropriate for us as an activist group to get involved in electoral politics - for example, some of our partner bands are 501(c)(3) organizations who would be prohibited from that kind of activity. Or, there might be some members who might object to implicit endorsement for a particular politician.
I created an online survey, and then decided to have some design fun posting the results. I came up with the following, where the size of each of the 28 votes was a dot, with the size of the dot reflecting how often the person said they attended events. A comment at the top explained that the numbers were references to numbered comments below the main display...
But I was surprised when the first response back from the mailing list was
My fix was to replace the numbers with letters, and then visually repeat the circle motif at the start of the comment itself:
Ah well. Maybe the thing was trying to be too clever. I may have been too anxious to cross reference what a person voted from how often they showed up (originally I was going to do a 2 axis graph of "frequency person attends" to "enthusiasm for allowing campaign activity)
I created an online survey, and then decided to have some design fun posting the results. I came up with the following, where the size of each of the 28 votes was a dot, with the size of the dot reflecting how often the person said they attended events. A comment at the top explained that the numbers were references to numbered comments below the main display...
But I was surprised when the first response back from the mailing list was
I may be reading these results wrong, but it looks like :Aargh! I'm not quite sure how they were working the math, but clearly the digits were throwing things off.
6 fully
22 quietly
1 indirectly
17 none
1 dunno
My fix was to replace the numbers with letters, and then visually repeat the circle motif at the start of the comment itself:
Ah well. Maybe the thing was trying to be too clever. I may have been too anxious to cross reference what a person voted from how often they showed up (originally I was going to do a 2 axis graph of "frequency person attends" to "enthusiasm for allowing campaign activity)
Sunday, February 10, 2019
RIP WAP (or don't, we don't care)
Doing some cleanup of my blog, I ran into suck.com's rant about WAP - now available only on the Internet Wayback Machine. At the time I linked to the article I wrote
Around that time I was working on a project making a WAP gateway to your ATM account balance information (which is why I was intimately familiar with the 1492 character limit) -- late stage dot com boom was a weird time
WAP is the underlying protocol that you use when you use "wireless internet" on your cellphone. Although the protocol itself isn't too too bad (except for an odd 1492 character limit in how much a server can send in one gulp), it's associated with WML, a terrible HTML-like language, and also having to use the cellphone keypad to laboriously tap in letters.I'm impressed at the combination of technical depth and strong feeling of that article. WAP was horrible. And like the article mentions but my summary leaves out, the nickel-and-diming of the usage fees kept people away in droves. While some other phones were creating more-or-less-ok web experiences on phones (I will always love this horribly NSFW rant extolling the Nokia E70 over the iPhone) I am convinced that one absolutely critical factor in the success of the first iPhone was getting Cingular/AT&T to offer it only with "all you can eat" data, so people could just use the thing without hearing the tick tick tick of an invisible meter run.
Around that time I was working on a project making a WAP gateway to your ATM account balance information (which is why I was intimately familiar with the 1492 character limit) -- late stage dot com boom was a weird time
Thursday, February 7, 2019
VS Code jump back to last edit spot
One feature I'd gotten used to in IntelliJ is a "back" button that would take you back to the last place you were editing, even across files. According to stackoverflow on a mac the combo I want is ctrl-minus (or ctrl-shift-minus to go the other way.)
One feature of VS Code I didn't really grok til I did a big React/Redux fix is the "list of currently open files" on the sidebar. At first this seems a little redundant - isn't that what tabs are for? But there's a bit more room there to show the relevant path bits. Depending on your project structure, it can be very useful to be able to see path info (like "containers/" or "components/" or "reducers/" or what not) to more quickly get back to the file you're thinking of.
One feature of VS Code I didn't really grok til I did a big React/Redux fix is the "list of currently open files" on the sidebar. At first this seems a little redundant - isn't that what tabs are for? But there's a bit more room there to show the relevant path bits. Depending on your project structure, it can be very useful to be able to see path info (like "containers/" or "components/" or "reducers/" or what not) to more quickly get back to the file you're thinking of.
Wednesday, February 6, 2019
visual studio code's logo is a disaster
Trying to be one of the hip kids at work, I'm migrating to Visual Studio Code.
I've complained about editor icons before but VS Code's is horrible:
This page talks about its origins - it claims
B. with current coloring it looks more like "XJ" then "Infinity Corner"... or like it's a sideways "ribbon for cancer awareness" (Esophagal Cancer according to this page )
For people who tend to think phonetically, it's a disaster, and I don't see many othe redeeming factors in terms of meaning.
I've complained about editor icons before but VS Code's is horrible:
This page talks about its origins - it claims
We iterated on the infinity logo for some time [...] Until we landed on the current "fish", which tested well with admittedly, a small number of developers.A. That's... not the infinity logo, chief.
B. with current coloring it looks more like "XJ" then "Infinity Corner"... or like it's a sideways "ribbon for cancer awareness" (Esophagal Cancer according to this page )
For people who tend to think phonetically, it's a disaster, and I don't see many othe redeeming factors in terms of meaning.
immutability
Just note to future self:
Work buddy Noah used this immutable.js codepen to help me come up with "how can I modify values in particular Map which is the member of a Set":
const set = Immutable.Set([Immutable.Map({a:'1',b:'foo'}), Immutable.Map({a:'2',b:'bar'}), Immutable.Map({a:'3',b:'baz'})]);
const newSet = set.map(value =>
value.get('a') === '1' ? value.set('b', 'hello').set('c','woot') : value
)
console.log(JSON.stringify(newSet));
Work buddy Noah used this immutable.js codepen to help me come up with "how can I modify values in particular Map which is the member of a Set":
const set = Immutable.Set([Immutable.Map({a:'1',b:'foo'}), Immutable.Map({a:'2',b:'bar'}), Immutable.Map({a:'3',b:'baz'})]);
const newSet = set.map(value =>
value.get('a') === '1' ? value.set('b', 'hello').set('c','woot') : value
)
console.log(JSON.stringify(newSet));
confirming argument order with es6 property shorthand
A coworker was helping me with some Immutable.js (blarg) and wasn't sure of the exact order of arguments his callback would be receiving so he did this:
const funk = (foo,bar,baz) => console.log({foo,bar,baz});
and then
funk(1,2,3);
const funk = (foo,bar,baz) => console.log({foo,bar,baz});
and then
funk(1,2,3);
would put
{foo: 1, bar: 2, baz: 3}
in the console, and he could make sure foo and bar and baz were in the right places in the argument list.
Thought that was pretty clever, an easy cut and paste way of adding human readable labels from "mere" variable names via the es6 sweetening.
Subscribe to:
Posts (Atom)