The Legend of Zelda: A Link to Your Page Add an interactive game character to your HTML

Sometimes I think we haven't played around enough with the easy stuff that the web can do.

We've gone from the age of the personal website where everybody from all backgrounds and skill levels made what they liked, to an age of letting either Facebook or premade templates do everything. It's an increasingly sophisticated and monotonous age, as sterile as an Apple products lineup, where professional designers and developers try to make sure they're doing the same thing as everybody else (IIRC something about job security in an industry where experience makes you obsolete). It's an age where Content Is King but he's living in someone else's castle.

For those of you wannabe programers who are tired of seeing the same thing over and over, or who remember those days when you you were fascinated by what HTML and Javascript could do and made those cursor trailers and tiled animated gif backgrounds, here's something to help you rekindle that thrill (building off the example from my Shop page).

All you need is a simple text editor like Notepad++. Some of you may even have an old copy of Dreamweaver still laying around. Break it open and let's make a simple HTML file.

We want to be bare-bones simple - no libraries, no industrial-strength Node or React, no HTML5 canvas, no optimizing, just doing the thing we want to do. Let's start by making something you can move with the traditional WASD keys. Here's a chunk of code you can copy and paste into your HTML file that'll do just that.

Here we're using a game loop to check for certain things on every frame of animation. We detect whenever you hit a key, and then 1) we dig out the key's name and add it as a data attribute to Link's div for the CSS to make him face the right direction, and then 2) we add it to an array so that the game loop has a way to detect it and move him in the right direction.

This little chunk of code is all you need for a fully interactive element on your page, but the problem is he keeps moving even when he goes off the screen. We need to add a way to tell him when to stop.

Collision

Let's add a "Block" div and use the game loop to check, on each frame of animation, if we're crashing into it. Actually, wait, that's not good enough. If we're crashing, we also want to know which side we're hitting, so that we can stop moving in that one direction.

How do we do that? Let's think like our code for a bit: Javascript is blind. It can't know whether or not Link's colliding with anything until it's scanned everything. So once it scans Link and the block, can it tell where they both are? Do a little research and you find yes, by using getBoundingClientRect to read their screen coordinates. How convenient. So the way we'll know if we're colliding is if the X & Y coordinates of any of Link's 4 corners are within the X & Y coordinates of the block's 4 corners.

For example if the top of Link's 50px x 50px div is 100px down from the top of the page and the top of the block's 50px x 50px div is 90px down, is Link crashing into it? So far, he might be because vertically he's 10px in the block. But what if he's way off to the right side? It isn't until we know the left side of Link is 220px away from the left side of the page and the left side of the block is 200px away that there's definitely a collision.

Let that last paragraph soak in. It's the part I spent the most time thinking about. I had a rough time with math as a kid because guess what? Back then I couldn't think of anything fun to use it with.

How do we translate that into javascript? You could write out every condition (if block.top < link.bottom < block.bottom AND block.left < link.left < block.right OR block.left < link.right < block.right ...and that's just checking the top), but you'll find that's a ton of checks. Another quick search of StackOverflow shows that instead of checking for conditions that should be met, it'd be easier to check for the conditions that should not be met. Then once we detect there's a collision, we can tell which direction to stop moving by doing a little calculation to find which side Link's block is closest to.

There are different ways to be clever in programing. One way is to use sophisticated tricks to write out an idea with fewer characters. That's the bad kind of clever that costs other people time who might want to pick up your work *cough arrowfunctions cough*. Then there's being clever with your logic and solving problems with simpler ideas, like this collision check. That's the good kind of clever, which makes people like you more and want to pay you more money. Try to be that kind of clever.

Important note: if you don't already know about and use your browser's 'Inspect Element' feature (right-click in the page, choose Inspect Element), you've got to start. Try that feature out on a few websites and you'll be addicted to web design in no time. Check YouTube for all the stuff it lets you do. You can use it here to check or modify Link's top pixel position and such. It'll even let you run javascript in its Console, which is a fantastic way to learn coding.

Okay so we have collision working on this one block, but that naturally leads to the next question/problem: what if we want more than one boundary on our page? Like, a lot more than one? Thank goodness for loops:

At this point we could stop and finish up with some CSS graphics and you'd have everything needed for a stylish diversion on your page. But there's one more feature I want to add before I call this a completely satisfying project: enemy blocks that you can kill. (Feel free to skip to the CSS part now if you want to start simple, of course.)

Enemies

Let's add two features: a block with a class of 'enemy', and a way to attack it.

It turns out the enemy is just a block with an additional class name which adds behavior that makes it disappear if you hit it with the sword.

For the sword, we're adding a div inside of Link's div so that it moves with him and makes the CSS positioning easier. When you hit the Delete key, the 'attack' state changes to true, which the game loop then notices and 1) changes Link's class (which could've easily been a data attribute instead) to make the CSS move the sword into place, then 2) checks if the sword is colliding with an enemy and if so, 3) changes the enemy's CSS to the killed state. We're also adding in some checks to record which way Link should be facing when either walking or idle so that the sword strikes in the right direction in every case.

With those feature done, now at last I can be satisfied the important pieces are there. Now at last I'll start filling in the graphics with CSS

CSS Graphics

Let's use CSS animation to handle Link's walk cycle. Step animation in CSS can be a little goofy so it helps to use the Inspect Element tools to get the right settings. You'll want a sprite sheet with each sprite evenly spaced apart. Link's divs will use that as a background image and the animation will change its background position.

I've doubled the size of the sprites - 200% Nearest Neighbor - to be readable on modern hi-def monitors. That makes the standard tiles 32x32, and standard tile sizes make CSS calculations simple. It's pretty cool how the restrictions the developers had to work within during NES days fit together so well with web design 30+ years later.

You may have noticed there's been no links to .gif or .png files in the code this whole time. I'm using inline data-URIs to keep everything you need in one HTML file. Although that means some really long strings of characters, the tradeoff is all you have to do is copy this one batch of code and paste it into a blank html file and you've got the whole example and it'll run anywhere.

Let's add the background images:

By now this may be looking like a lot to sort through so I'll stop things here. But keep this in mind: I spent a bunch of time thinking about little parts and then adding them in to my main formula. Like writing a term paper, it doesn't all just come together. It came as bits and pieces to me and it should for you, so that you get a chance to slowly build a train of thought, get the dopamine hits from seeing each new part of your logic work correctly on the screen, and form an addiction to your project by adding "ooh, just one more thing.." (which you can see I did quite a bit of with this page) and going back to switch out old ideas with better ones as inspiration strikes.

This was all very flow-of-thought code, but hopefully that helps make it easy for the most possible people to follow. For those of you inspired by the possibilities, rip apart this page's final code and start adjusting things. Switch the graphics, see what changing this does, see what deleting that does, and go build something new with it. I'll leave you with some ideas of where you can take things:

  • Accumulated damage - on this page one hit kills you or an enemy. But you can add something like data-life=3 to an enemy and reduce it by 1 every time they're hit. You can even add a fixed-position div at the top of the page that shows Link's heart icons, and match them to his data-life number. If the player dies, they have to reload the page (and thus your ads, if you have any)
  • With a few more additions to the sprite sheet, you can have an end boss with a huge data-life and give him a repeating attack pattern.
  • Projectiles. Beware, having too many projectiles running at a time can clog up a browser fast. Be sure to stop them from running and remove them once they leave the screen or go too far.
  • You have no idea how hard it's been on me to follow internet courtesy and not play a repeating midi of the level music or attach sound effects to the attack key. It would be so easy.
  • Isometric RPGs. If you're *really* into it, you can go all Final Fantasy and give a player stats and levels in their cookies or local storage, which can be saved for their next visit to your website. Loyal visitors get more points or unique stuff when they come for your next article.
  • Hidden warp doors to pages with hidden content.
    Man what on earth would that look like?
  • And of course nothing says you can't switch out the graphics to other overhead games.

Designers, developers: Don't make yourselves replaceable by following trends. Try new pet projects and break as many conventions as you can. Use fixed-width pages. Use absolute positioning. Heck, use the marquee tag. You know, the tag was made obsolete by CSS animations which can do the exact same thing, just with more lines of complex code (check out my home page on mobile if you think marquees have no ideal use cases anymore).

Try working inside the more liberating confines of "is it good enough" instead of "is it perfect". Learn The Pareto principle that everyone in software seems to be forgetting about.

Above all, be nuts. Do new things. Play around with the easy stuff. Make something you like and bring back that pioneering age of the personal web pages.