Wednesday, August 15, 2018

Search for Comics

Another new feature I've just added to the comic is the ability to search the archive for comics containing a certain word or phrase. I've wanted this feature since 2014! I always had to bring up a terminal and perform SQL queries manually to find the comic I was looking for.

Since the titles often don't give any real hints as to the content, I often had trouble finding one.

If you want to give it a try, go to the Archive page. You'll see the search box near the top.

The new Search feature!

Just type in a word or two and give it a try. If your search comes up empty, you'll get a confused-looking Business Frog to share in your puzzlement.

You won't have to search for today's comic though. The link to it is right here:

Amphibian.com comic for 15 August 2018


Wednesday, August 8, 2018

Minor Comic Style Improvements

I've made a few minor adjustments to the comic's style coinciding with the restart. You might not notice unless you have a keen eye for detail.

Font Upgrades


First, I've set a specific font for the free-text in comic frames. The speech bubbles have always used Sniglet, but any text that just floated there was actually set to Verdana with a fallback to sans serif. Sure, it looked fine for Windows users and didn't look too bad when I viewed them on Linux, but sometimes I'd be on a weird browser and get a weird font that looked...weird. I don't know why I never fixed this in the first three years of the comic, but when I set my mind on it I had a lot of trouble picking a free font that I liked. I ended up going with Ubuntu. Now the text should look consistent for all browsers on all operating systems.

Here's a sample of a comic in the original font:

And here's that same comic using the new font:

The difference is subtle, but I think it's important. I'm much happier with the new font.

In addition that font fix, I've added another font option for comics. Anything that's supposed to look hand-written will now use the Architect's Daughter font. It's clean and easy to read but also warm.

Here's an old comic with writing on the whiteboard:

And here's that same comic, updated for the new font:

Mobile Theme Color


Mobile users may also notice another minor change that I've made. I set a "theme color" so the address bar will be green. Oddly enough, this is done via meta tags instead of CSS like I'd expected.

<meta name="theme-color" content="#006600">

Here's what it looks like for me, in Chrome for Android:



More to Come

That's all for now, but there are more updates coming along with the new comics. Here's this week's:

Amphibian.com comic for 8 August 2018





Wednesday, August 1, 2018

Where Have I Been?

It's been a while. I wrote my last blog post over a year ago, and the comics stopped shorty after the blogs. Some people emailed me to make sure I was okay, since there was no notice or anything. Stuff just stopped. So what happened?

Lots of stuff. Life is complicated. My life is extra complicated.

My wife and I are foster parents. We have three of our own children and at any time we could have any number of additional children. In March of 2017, while I was out of town for business, we were given a 3-month-old foster baby. We already had a toddler only 21 months old. It was just too much. I didn't have time to make comics anymore. I didn't have time to sleep anymore. I burned through my buffer of comics. I found some time to finish a bunch of drafts that I'd started, but I was unable to start anything new and in August of 2017 they just ran out.

I didn't make an announcement or anything because I didn't know what to say. Was it only temporary? Was it the end? I didn't know.

And then things continued to get harder. In October, was got an additional foster child - the baby's 10-year-old sister. I was pretty sure I'd never write another comic again.

Until the spring of 2018. It turns out that babies grow into toddlers. They start sleeping through the night. I guess I should have remembered this fact about babies, but I was really really tired. I'm not saying that anything around here is easy, but I am somehow able to write comics again.

A few of them anyway.

I'm going to start slow. There's only going to be one new comic per week, on Wednesdays. And I don't know if I'll embed any games or anything in them for a while yet. But hey, I've got something. We'll see how it goes.

Here it is, the link to the comic you've all been waiting for!

Amphibian.com comic for 1 August 2018


Sunday, April 30, 2017

New Webcomic Ad

It's been a long time, but I've started advertising Amphibian.com on another webcomic list site. Actually, The Webcomic List site. After successfully getting my comic to show up as updating properly on that site after all these years, I decided to try their sponsorship deal where you can get your comic's little square icon in the banner for a month. I'd been seeing pretty good traffic from that list already just from fixing the update status, so we'll see how this goes.

Monday, May 16, 2016

CSS3 Smoke Animation Effect

The comic today uses quite a bit of CSS3 animation. This is a rather new thing for me - I've been using mostly JavaScript-powered animations on Amphibian.com since it started. But after I did the rain animation using CSS back in March (see the comic here), I've been warming up to the idea of more CSS and less JavaScript to move things around.

For this task, I wanted to make some animated smoke come out of the frogs' rocket ship before the launch. My style is mostly just simple geometric shapes arranged to look like things, so using circular DIV elements to look like puffs of smoke was fine with me. I found a great starting point by Andrea Verlicchi on CodePen, and then modified it for my comic.

Here's the basic idea - puffs of smoke emanate from a given source element. They move downward and off to the side while fading away.

The puffs of smoke will be represented by rounded SPAN elements, with this CSS applied to them:

span.smokepuff {
    display: block;
    position: absolute;
    bottom: -35px;
    left: 50%;
    margin-left: -20px;
    height: 0px;
    width: 0px;
    border: 35px solid #4b4b4b;
    border-radius: 35px;
    left: -14px;
    opacity: 0;
    transform: scale(0.2);
}

The above styling just makes them round, grey, and positioned absolutely in their container. I also have two animation keyframes defined, one for the down-and-left movement and one for the down-and-right movement:

@keyframes smokeL {
    0% {
        transform: scale(0.2) translate(0, 0);
    }
    10% {
        opacity: 1;
        transform: scale(0.2) translate(0, 5px);
    }
    100% {
        opacity: 0;
        transform: scale(1) translate(-50px, 80px);
    }
}

@keyframes smokeR {
    0% {
        transform: scale(0.2) translate(0, 0);
    }
    10% {
        opacity: 1;
        transform: scale(0.2) translate(0, 5px);
    }
    100% {
        opacity: 0;
        transform: scale(1) translate(50px, 80px);
    }
}

The above keyframe definitions define an animation that will move the smoke puffs lower by 80 pixels and 50 pixels to either side while at the same time scaling them up and fading them out. It defines 3 steps: 0% (the start), 10% (moved a little down), and 100% (moved completely down and over). There's one for the left, smokeL, and one for the right, smokeR.

Note: if you care about being compatible with slightly older browsers, you would want copies of these with @-moz-keyframes and @-webkit-keyframes as the names as well as adding -moz-transform and -webkit-transform to them all! I left that out here to keep the example simpler!

I said this was pure CSS3 animation, but there's still a little JavaScript involved. It doesn't really do the animating, but I use some code to generate the puffs in the first place. Something like this:

function createSmoke(time, num) {

    var timeGap = (time / num); 

    for( var i = 0; i < num; i++) {

        var delay = (timeGap * i) + 's';

        var aniName = "smokeL";
        if (((i+1) % 2) == 0) {
            aniName = "smokeR";
        }

        var aniStyle = "animation: " + aniName + " " + duration + " " + delay + " infinite";
        $('#smoker').append('<span class="smokepuff" style="' + aniStyle + '"></span>');

    }

}

When this function is called, you give it the length of the animation and the number of puffs of smoke you want. It figures out how much of a delay there should be between each puff's animation starting based on those two values. For example, if you want the animation to run 5 seconds and have 10 puffs of smoke, the first puff would have no delay, the second would have a delay of ( 5 / 10 ) * 1, the third a delay of (5 / 10 ) * 2, and so on. In this example, that just means add a half-second delay for each puff you generate. Also, each time through the loop, it alternates between the smokeL and smokeR animations so that every other puff moves in the opposite direction. One final piece of the total animation style is to set the repeat-count to infinite, so the puffs keep on coming! The function generates new SPAN tags with these animation styles applied and appends them to the parent element, which here is named smoker. It's just a DIV somewhere on the page - all the puffs of smoke will appear to come out of it.

The finished animation. Don't miss it!

I think the effect turned out great. Even though I used a little JavaScript to create the elements, doing all the animation with JavaScript would have been much, much more complicated. I may consider replacing all the old JavaScript-powered animation on Amphibian.com with CSS animation, and fix up my animation editor to go with it!

Now don't miss the smoke effect in today's comic! If you're reading this on the publication day (16 May 2016) the countdown to launch will be live! That means the last frame of the comic will change and do different things right up to the launch time! Keep watching it!

Amphibian.com comic for 16 May 2016

Monday, May 9, 2016

Add Gamepad Support to a Phaser Game

It seems like I haven't written a blog post in forever! It's actually been less than 2 weeks. Right before I took a break, I wrote a little about my new NES-style Bluetooth gamepad. I've been trying off-and-on ever since then to get my 8-bit style platformer to work with it, and today I finally had some success!

First of all, it needs to be said that support for gamepads in the browser is very inconsistent. The W3C's Gamepad API document is still a working draft after all these years (I first read about it and tried it out in 2013). It seems as though Mozilla and Google have some different opinions on how it should work, because the way you interact with the devices varies significantly between Firefox and Chrome. Phaser provides gamepad support through the Gamepad object, but the documentation carries a warning about the volatility of the specification.

Here's what I learned when I tried to use it...

I started with some of the examples on Phaser's site. They worked, most of the time. Let me explain. In theory, working with a gamepad in Phaser is simple. You get a gamepad object, setup a callback to handle the detection of a gamepad device, and bind to buttons in that callback. Then you start the gamepad polling.

function create() {

    // ... setup stuff ...

    var jumpButton = null;

    controller = game.input.gamepad.pad1;

    controller.addCallbacks(this, {
        onConnect: function() {
            // you could use a different button here if you want...
            jumpButton = controller.getButton(Phaser.Gamepad.BUTTON_1);
        }
    });

    game.input.gamepad.start();

    // ... other stuff ...

}

function update() {

    // ... other stuff ...

    if (jumpButton.isDown) {
        // jump code goes here!
    }

    // ... other stuff ...

}

Much like you do for keyboard input, you can set up the buttons you want to listen for in create and then perform actions based on their state in update. And this works pretty well - in Firefox. Chrome, on the other hand, has some issues. Phaser's example code, much like my example above, works most of the time in Chrome when the code gets executed very quickly after the page loads. But if you put enough setup code in front of your gamepad initialization you'll be wondering, like I was, why your gamepad never connects.

I had to dig into the Phaser code in order to figure this out. It works consistently in Firefox because Firefox waits until the first time a button is pressed on a gamepad before it emits a gamepadconnected event from the window object. Phaser catches that and sets everything up, calling the onConnect function when complete. In Chrome, however, gamepads just show up magically at some point after the page is loaded, in an array-like object accessed by calling navigator.getGamepads(). Phaser checks this list constantly, and when things appear for the first time, it makes all the internal setup calls. And right there's the problem! If the gamepads appear BEFORE my onConnect callback function is set up, I missed the boat. A default, no-op callback got executed instead and my gamepad buttons never get set up!

There was no work-around for this that I felt was acceptable, so I actually forked Phaser and fixed the problem in the Gamepad object's code. It was a fairly simple fix - I just don't start polling for those gamepad objects until after the call has been made to game.input.gamepad.start().

I forked off of version 2.4.7 and submitted a pull request, so hopefully my fix makes it in to the next Phaser release and the rest of you won't have to deal with this problem like I had to! If you can't wait, try using my fork and gamepad branch.
UPDATE: My pull request was merged, but not in time for 2.4.8. Look for this fix in the 2.4.9 release!
If you're just interesting in playing the game I've been working on, you can do that here: http://amphibian.com/eight-bit. The full source code is available on GitHub. If you're just interested in viewing today's comic, you can do that here:

Amphibian.com comic for 9 May 2016

Wednesday, April 27, 2016

The Most Awesome Thing on the Internet

Here it is, people. The most awesome thing on the Internet (besides my frog comics) - a
Mariachi Cover of the Dark World theme from The Legend of Zelda: A Link to the Past.




You can thank me later (by viewing and sharing today's comic!). Oh look, here it is...

Amphibian.com comic for 27 April 2016

Monday, April 25, 2016

Review of Xgaming's NES-style Wireless Gamepad

Late last week I received my new Bluetooth wireless gamepad from Xgaming. I was really excited about this new product. I've had one of their arcade joysticks for years and found it to be an excellent piece of hardware that fully lives up to the high expectations set for it on their web site. I was certain that this new wireless gamepad, a bit of a departure from their existing product line, would not disappoint me.


So, what do I think now that I've had a few days to play with it?

Let's start with my initial impressions. It was a little smaller than I had expected it to be. It doesn't really give dimensions anywhere on Xgaming's site (as far as I could tell) but the unit is only 5.125 inches wide and 2.5 inches tall. It's slightly over half an inch thick (not counting the sticks and buttons). For me, the small size makes hitting both sets of top trigger buttons awkward but maybe I just need to get used to it. Most games I play only need one set of top triggers anyway. Besides that, the position of all the buttons and sticks is excellent. It weighs only 3 ounces, but feels very solid. The buttons and D-pad are very firm and have a wonderful feel to them.

Technically, it has been functioning very well. I had no problems pairing it to my Windows 10 PC as a Bluetooth game controller, but it did seem to lose its pairing once (there are colored LED lights on the bottom which indicate things like that - flashing blue means ready to pair). I'm not sure if it was the device's fault or mine - I may have been holding down one of the settings buttons inadvertently while powering it on. I'll withhold judgement on that issue until I see if it repeats. There were no issues setting up button mappings in my emulator software either. It all worked very well.

Playing games with it has been very enjoyable so far. The button response is much better than my old SNES-style USB game controller. I honestly haven't liked a PC game controller this much since my Gavis PC GamePad.

The device is currently selling for about $45. If you love playing emulated NES and SNES games as much as I do, I believe you'll find it to be well-worth the money.

The only question left might be, does it work in web-based HTML5 games such as the 8-bit style platformer I've been working on? The answer is...maybe. Web browser gamepad support is still weird. Phaser has an API for it, but so far I've found it difficult to work with. I'll keep trying and maybe have something to report next week.

Until then, I've got more comics for you to enjoy!

Amphibian.com comic for 25 April 2015

Friday, April 22, 2016

Answering Questions

Tonight I'm working on answering interview questions. Yes, I'm being interviewed by Best WebComics, a site that promotes the discovery of new webcomics. Their questions are rather unique so the finished interview should be a good read. I also get Amphibian.com promoted on their site for a week next month.

I've been working on the comics for over 2 years now. The first comic was published in August of 2014 but I actually started working on it in January of that year. It took almost 8 months to get things ready. I had to develop the web page stuff, the back-end application that runs everything, make the editor for the comics, and write a bunch of comics. Looking back on some of my early work, I think I've gotten a lot better.

So when you view today's comic, why don't you click the link to go back to the first comic too? Even if you've been reading them from the beginning, you've probably forgotten the early ones.

Amphibian.com comic for 22 April 2016

Wednesday, April 20, 2016

Read Another Blog Today

As I said last week, I'm not spending as much time writing this blog as I normally have been. I need a few weeks off from it due to the demands of the real world. But that doesn't mean that you, the reader, have to suffer. Please take the time you would have normally spent reading my inane ramblings to read someone else's.

Here are some excellent options:

Smoke in the Cinderhaze
I'm not exactly sure what a "Cinderhaze" is, but I suspect that it's a word used to describe Cinderella's mental state before she has her first cup of coffee in the morning. Either that or some kind of sailor thing. This tech blog is written by my friend Daryl Wiest, and he doesn't update it often enough. Go leave him some comments about that.
David Walsh Blog
An excellent tech blog that covers a variety of topics, but often covers JavaScript and front-end stuff. Also some excellent career advice sometimes. This David Walsh guy is fairly famous so you might have heard of him already. If not, you should.

While you wander off to read those, don't forget to read today's comic! It's #314, which is a lower number than Monday's comic (#315). That kind of thing hasn't happened in a while. I move the publish dates around from time to time after I make them. I hope it doesn't bother anyone.

Amphibian.com comic for 20 April 2016

Monday, April 18, 2016

Better Static Images for Amphibian.com

The new, improved version of the image for a recent comic.
As I mentioned last week, I have been working to close Issue #7 on my webcomic. Basically, Amphibian.com is not a normal webcomic. It's not an image, which is great until someone wants to share a link to a comic on social media. I auto-generate static images of the comic just for sharing. But the comics which contain embedded games and stuff haven't looked right in the static captures. I wanted to at least put a warning in the image that explains why they often look weird, but as an added bonus I actually made them look better (most of the time).

As you can see in the picture on the right, I was able to add some warning text to the top of dynamic comics. I generally share this version on TopWebcomics.com but you may see it other places as well. When people see comics like this in the future, they'll know that they should view it on Amphibian.com to get the full effect.

Also, when this comic was originally published, the third frame was black. The game was not captured as part of the image. This was due to two things - the URL of the page used for the image capture was such that the game's image assets could not be loaded, and the fact that the capture was taken before the game initialized asynchronously. I fixed the URL issue by changing the static image comic path from /basic/[comic-number] to /[comic-number]&b=1. There wasn't really a generic way to ensure the comic will be rendered before the capture in all cases, but I added a 500 millisecond delay which should be good enough the majority of the time.

Finally, I also locked-down the ability to see the basic versions of the comic. It was the case that you could view a future comic if you asked for the basic rendering. I changed the rules so that only authenticated users or requests coming from the server itself can see them. I use PhantomJS to perform the image capture and it runs on the server, so that was a simpler fix than I initially thought that it would be.

It always feels good to resolve an issue. It also feels good to read one of my comics. Here's the link so you can feel good too.

Amphibian.com comic for 18 April 2016

Friday, April 15, 2016

Basic Images are Complicated

I sat down tonight thinking that I would quickly resolve Comic Issue #7, which has to do with the static images generated for sharing on social media platforms. Here it is almost midnight and I am not finished.

It's been bothering me that many of the dynamic comics (the ones that use JavaScript for a game or something) are not rendering correctly at all as static images. See this post on how I generate the static images. I finally figured out that it is because I take pictures of "basic" versions of the comics (no header, footer, etc.) and I generated the "basic" versions of the comics at a slightly different URL. When the page rendered there, sometimes file paths used in embedded JavaScript would be wrong and lead to missing resources which in turn leads to a bad picture.

Another problem with this method was that I render the images before the comic's official release date and so I had to leave the basic URL open - that is, no authentication was required to see future comics if you requested them in basic form. I doubt that many people took advantage of this flaw, but still...

Of course I wanted to fix all these problems in addition to just marking dynamic comics as dynamic in the basic view. So I'm not finished with any of it. I'm like, 85% finished. But tomorrow is another day. A day in which I might write another post about what I actually did to fix the problems! Until then, entertain yourself with today's comic. It's funny, and that's no accident.

Amphibian.com comic for 15 April 2016

Wednesday, April 13, 2016

Use Tiled's Map Background Color in Phaser

I actually did some work on my Phaser platformer this week! Yeah! I resolved an issue that was submitted on GitHub concerning the water physics in Level 7, and I started thinking some more about another thing which had been bothering me.

Even though I can set a map's background color in the Tiled map editor, Phaser doesn't parse that property when it builds a Tilemap object. I had been keeping track of the background colors for each level separately, but that violates one of my principles - the map editor should be the one and only source of data about each level map.

The Background Color map property in Tiled

I was able to make a few minor changes to work around this limitation. In the stage's create function, I first pull the tilemap data manually for the map's key. This is the same data that is used behind-the-scenes when you call game.add.tilemap(key).

function create() {

    // get the asset key for this level
    mapKey = "key-for-this-level";

    // pull the tilemap data from the asset cache
    var tilemapData = game.cache.getTilemapData(mapKey);

    // all the data from Tiled is in the data field
    var mapData = tilemapData.data;

    // set the stage's background color from the map's background color.
    // note that Tiled didn't capitalize the "c"...
    game.stage.backgroundColor = mapData.backgroundcolor;

    // go about making the make the normal way
    var map = game.add.tilemap(mapKey);
    map.addTilesetImage("ground", "tiles");

    // ... the rest of the stuff ...

}

The tilemap data object returned from the asset cache has itself a data field, which is essentially the Tiled JSON map object. The backgroundcolor property is there can can be used to set the backgroundColor property for the stage. Remember, you can view the full source code to this game in its public repo on GitHub!

It really was that simple. In only a few minutes, I feel like I accomplished something on this game for the first time in a month! It doesn't take much to make me feel good about my achievements. Now, go read today's comic and feel good about that achievement!

Amphibian.com comic for 13 April 2016

Monday, April 11, 2016

A Little Break

Over the last month, regular readers here might notice that the stresses of travel and a new job have greatly limited my ability to do interesting things and blog about them. It's just been too hard to keep up both the writing of the blog and the writing of the comic. I've decided that the comic is more important and must continue on its regular publication schedule, while blog posts might get a little more irregular.

I haven't forgotten about my 8-bit-style Phaser platformer, and I will be finishing it up over the next few weeks - I just might have one blog post per week instead of three.

I will try very hard to get back on my old schedule as soon as possible. And speaking of things being back on schedule, look what's on Cartoon Network's schedule: a reboot of the Powerpuff Girls! Along with Dexter's Laboratory, the Powerpuffs were one of my favorite shows back when I was in college. My wife, who was known to watch them with me back in those days, even has the Heroes and Villians Powerpuff Girls soundtrack CD somewhere in this house. We added it to our iTunes library years ago but no longer have any iDevices so I haven't heard it in a while...

Anyway, to promote the new series Cartoon Network put together this Powerpuff Yourself thing and I used it to make this Powerpuff version of my wife:

Powerpuff Rebecca, with her super-powered latte.

It looks just like her, trust me.

And you might say that the art style of the Powerpuff Girls influenced my own work. You might be right. I loved the art in the original series. The new one is very similar, but it's not quite the same. Or maybe it is and I've just gotten older.

Amphibian.com comic for 11 April 2016

Friday, April 8, 2016

New Things to Learn

I'm back home in Pennsylvania after spending 4 days in Virginia learning about my new job. I'll be working with some technologies that I haven't really used much before, so maybe I'll have some new stuff to share here soon. Angular is currently at the top of my list of things to learn better.

So here's another super-short blog post followed by a link to another super-entertaining comic. Well, at least mildly-entertaining.

Amphibian.com comic for 8 April 2015

Wednesday, April 6, 2016

I'm Tired of Hotels

So here I am in another hotel. In the past 5 weeks, I've been to Texas, Florida, and Virginia. I don't mind a business trip every now and then, but this has been difficult. This week I'm in Virginia because I'm starting a new job and need to learn some things before I go back home to Pennsylvania. So far I've learned that I am really tired of hotels.

They've all been nice hotels. There's nothing really wrong with them. There's just something wrong with me. A lot of people travel much more than I do, and I am starting to think those people are crazy. Back six months ago, I was able to do some work on my comic and some games while in a hotel room. Now I can't even get Eclipse to start. I once wrote 2 blog posts per night in my hotel. Now I forget that I even have a blog until the last minute. I may have to take a hiatus from the blog writing for a while so that I don't get behind on the comic too. I haven't decided yet.

My friend Daryl tries to help keep me working on things by writing issues on GitHub for my unfinished games. Maybe if more people did that I would be forced to work on them more. Why don't you go read my comics and play some of my games right now and write an issue for a bug fix or improvement on one of them? That would really help me out. It would help more if you did the fix yourself and just sent the fix...

Amphibian.com comic for 6 April 2016

Monday, April 4, 2016

New Job Today

The main reason that I've been under too much stress to work on anything lately is because I'm starting a new job today. Yes, after nearly 15 years at the same one, I recently resigned. I've worked for the same company since I graduated from college, so this is a very new experience for me. Lots of stuff is changing. And I hate change.

So once again, I have nothing to share in this blog. I'm sorry. Hopefully in no more than a few weeks I'll be settled in to a routine and can go back to gleefully making frog games in my spare time. But for today, all I have is today's comic. It's the first of a short series.

Amphibian.com comic for 4 April 2016

Friday, April 1, 2016

April Fools!

Things are still out of control here. I've had no more time to work on that Science Frog game this week, and April Fools Day caught me off-guard. Making a comic for today proved more time-consuming that it should have been, and in the middle of it all I got sucked into a Google code challenge thing that ended up not even working! Google's fault, not mine (pretty sure).

What? Yeah, so it turns out that Google does some recruiting by looking at the kind of things for which you search. I don't claim to know their algorithm for identifying potential candidates, but if you are searching for computer science terms you might get an invitation to play a game in your search results. It happened to me Tuesday night, and despite the obvious parallels to War Games and the fact that I was really tired when it happened, I agreed to play the game.

I was given a programming challenge and a Unix-like terminal-in-a-web-page in which to write some code and test it before submission. I wrote up a solution within a few minutes, but got a very unhelpful error message when I attempted to verify it against the test cases. I was so certain that my solution was correct, but I was too tired to look at it any more. I left the window up and came back to it the next day after work.

When I sat down, the first thing I did was just try to verify again. This time, even though I hadn't changed anything, I got a valid response. I was surprised so I verified again. This time I got an error response: 400 bad request. I tried again. That time it worked. Obviously, something was going wrong intermittently on the Google side of the test. Knowing that my solution was most likely correct, I perhaps foolishly submitted it. Did the submit work? No, 400, bad request. I hit submit again. Same thing. I tried verify again. No. And again. No. It never worked again after that. Oh well, it might have been fun to continue with it...but I had to eventually close the window.

I'm not even kidding. This is no April Fool's joke. It really happened.

Know what else happened? I wrote this comic. No picture link today. It just wasn't working. Just like last year's April Fools comic, these "special" ones break my automated image capture.




Wednesday, March 30, 2016

Dependency Cost

Over the weekend I was alerted to a bug in the Amphibian.com web application by a reader. For him, the "previous" and "next" navigation links would not work. Clicking on them put the page into endless "Grabbing Frogs" mode and never displayed another comic.

Fortunately, the issue was not difficult to correct. Since Amphibian.com is (almost) a single-page-application, each time a new comic replaces the currently visible one I have to generate a new Pinterest button for the correct comic. Yeah, you're probably wondering, "why a Pinterest button?" I don't know. It seemed like a good idea at the time...

I'm generating the new button by calling a slightly undocumented function in the Pinterest code. I don't think they intended for it to be used on pages quite like mine. The problem arises when the function is unavailable. Maybe Pinterest is blocked. Maybe Pinterest is down. Maybe certain browsers actually download an older version of the code where that function doesn't exist. Doesn't matter why - the end result is the same. Without that function, an error occurs in my JavaScript and the new comic is never displayed. I fixed this issue and then immediately found another similar issue with my call to Emoji One's JavaScript. Fixed that too.

This got me thinking about what I'll call Dependency Cost. I didn't really think about the cost of my code being dependent on Pinterest and Emoji One behaving in a certain way. I don't control either of them, and they could change or vanish at any time - resulting in my comic readers getting shut out of my site. When you think about it, this is really an unacceptable situation. But how many situations like this are you in right now with your code? I think we're all in too many. Take the setup Amphibian.com for example - it's built on Node using Express and over a dozen other modules all downloaded from npm at first install. What if I had to recreate the site and npm was down. Do I think npm will be around forever? Nothing lasts forever.

Just something to think about when you're building your next application. Or you can think about today's comic. That's much more fun.

Amphibian.com comic for 30 March 2016

Monday, March 28, 2016

Know Your vi

I through in a little jab at vi in the third frame of today's comic. The truth is, I actually use vi almost every day at work. Remote displays are such a hassle. It got me thinking about this nice vi cheat sheet I was given on my first day of work (almost 15 years ago).

It hung on the wall of my cubicle all these years. I found a copy of it on the Internet and wanted to share it with you!

There are a couple of cleaned-up versions of this same style sheet floating around. I like it because it spells out "vi" with the commands. Just in case you forget what the commands are for. Mine is a copy of a copy of a copy and has some hand-written notes on it too, just like the one I found above. Gives it character.

Right after you read today's comic, go log on to a Linux terminal and edit something with vi!

Amphibian.com comic for 28 March 2016