Friday, January 29, 2016

A Slider Control for the Web

Today's comic has a slider control embedded in the third frame, allowing you to adjust the brightness of the sun and extend daylight. It's suppose to look a bit like the brightness slider control on your phone. I got the idea from my daughter who keeps her brightness on the lowest setting in order to extend the battery life. She also panics when it gets down to 70%, as if a dead phone battery will somehow mean her own death as well. Teenagers...

You might assume that a big fan of HTML5 such as myself would use the range input field to implement the slider. You would be wrong. Unfortunately, I do try to keep the comic mostly compatible with IE9 (that might change be the end of the year) and it does not support the range type of input. Also, the default styling of the range slider looks pretty terrible. It would have taken me a while to get something that looked the way I wanted.

A standard HTML5 slider control. Input type "range" does this.

Well, how about the jQuery Mobile slider? It looks nice, and I already use jQuery. But, alas, its mobile styling really messed up the default styling of all kinds of things on my pages. It would have taken me quite some time to straighten it all out.

The jQuery Mobile Slider control. Looks nice, destroys Amphibian.com.

So twice I was thwarted by wanting a slider that looked nice and didn't cause me to do a lot of extra work. Before I gave up on this idea, I found the Slider for Bootstrap by Kyle J. Kemp. It came with CSS that didn't interfere with the rest of my CSS, and was easy to use.

Start by including the bootstrap-slider.js (or bootstrap-slider.min.js) file on your page. Also include the bootstrap-slider.css (or bootstrap-slider.min.css). Then write some HTML like this:

<input id="brightnessSlider" type="text"
       data-slider-tooltip="hide"
       data-slider-id="bSlider"
       data-slider-min="0"
       data-slider-max="19"
       data-slider-step="1"
       data-slider-value="19"/>

Note that the type of the input is "text" and not "range." Don't worry about that for now, look at the data-slider- attributes. These are used to pass configuration settings to the control. In my case, I wanted to hide the tooltip, set the minimum value to 0, the maximum value to 19 (for 20 total values), the stepping to 1, and start with a value of 19 (the max). The data-slider-id attribute is of interest, though. What it means is that when the JavaScript turns this input into a bunch of other elements that look like a slider, the parent div for all those will be named "bSlider". Once that's created, this text input will be hidden from view. But when the user interacts with the slider, the value will be written back to the text input's value - making it easy to figure out what to use when the form is submitted.

Take a look at the JavaScript now.

var bChange = function() {

    var n = Number($('#brightnessSlider').val());
    console.log("current value is " + n);

};
    
var bslide = $('#brightnessSlider').slider()
                    .on('change', bChange);

In this example, the bChange function doesn't really do much, but it shows how you can get the current value of the slider. The bChange function is passed in as the event handler for the change even when the slider is created.

If you want to change the width of the slider, the only way I found was to alter the CSS width attribute of the control's created div. I did this programmatically when the comic is displayed in one of the small-screen formats. Remember, the control's div will have the id matching the data-slider-id attribute in the input tag.

$("#bSlider").css("width", "150px");

The default width seemed to be 210px, but I reduced that to 150px for the phone screen sizes.

The styled slider in the comic.

After that, I added a few CSS rules to change the colors of parts of the slider, and I ended up with pretty much exactly what I envisioned it should look like. For now, this is the slider control that gets my recommendation - as long as you also use jQuery and Bootstrap. But who doesn't these days?

See the slider in action in today's comic!

Amphibian.com comic for 29 January 2016

Wednesday, January 27, 2016

Less Snow, More Snow Days?

The schools here were closed today. A snow day? No, it didn't snow. This has become normal it seems. The schools here in Pennsylvania close for bad weather much more than they ever did when I was in school.

Today the reason was a forecast of freezing rain. I'm not sure if there was any freezing rain. But they also sometimes close in advance due to a forecast of snow. The next day when the snowfall is much less than predicted (or doesn't materialize at all) it seems ridiculous that the kids had to miss school. Do they call and un-do the closure? No, the kids just stay home.

They also close school when it just gets too cold. I'm fairly certain that I had to stand outside waiting for the school bus in temperatures in the single digits - when measured in kelvin. I have to wonder if they give days off school when it gets too sunny in places like Florida.

The other thing that is missing from schools today is the 1-hour delay. When I was a kid, we had 1-hour delays, 2-hour delays, and complete cancellations. I can remember only a few early dismissals. I don't think 1-hour delay is an option anymore. There's never been one since my kids have been in school. What happened to them? Did snow plows get slower? Is it not possible to clear the roads in an hour anymore?

I don't know how these rampant closures prepare the children for adulthood. I don't get the day off when it snows. They get to stay home, but I have to drive my car in those terribly unsafe conditions to get to my job.

Why don't we just get school buses like this one?



I probably sound old now. When I was a kid we had to walk to school in the snow uphill both ways while being chased by bears! Well that's enough of my ranting about school closures, time to read today's comic. It never snows in the comic. Maybe it should. I don't know what the frogs would do in the snow.

Amphibian.com comic for 27 January 2016

Monday, January 25, 2016

Run Your Own Comic

Mechanical frogs, for repeatable
 installations of Amphibian.com
As you may have heard, the East Coast got hit by a major snow storm this weekend. It started snowing Friday night and snowed most of the day Saturday. Since I couldn't go anywhere I was able to get a lot done - making some new comics and enhancing the platformer game that I've been working on.

But before I did any of that, I finished checking in files and instructions for repeatable installations of the Amphibian.com webcomic application. I started doing this over a year ago, but never finished it. The goal was to have all of the files and complete keystroke-level instructions necessary to set up Amphibian.com on a new Ubuntu instance.

Why do I want this? Currently, the comic is running on an Ubuntu virtual machine hosted by Digital Ocean. Digital Ocean is great and I hope they're around for a long time, but what if they aren't? Or what if another service comes along for a better price? Or what if I just want to set up another instance somewhere for test purposes?

The complete installation includes:


I sat down in the morning with VirtualBox, the Ubuntu 14.04.3 server ISO image, and got to work. I created a fresh virtual machine with a clean install of Ubuntu and documented all the steps I had to perform to get the comic running. When I thought I had all the commands documented, I started from scratch with a new virtual machine and did it all again by just copying and pasting commands. Of course, I missed a few. I updated my document and tried again with a third virtual machine. That time, everything went well and I had Amphibian.com running in under 10 minutes.

The things that I was really missing were database setup scripts (to make the database, user, and tables), the site configuration files for Nginx, and a script to start and stop the application. I added those to the repository along with my complete setup instructions and now I feel a lot better. Not only does it allow me to have the confidence that I can recreate my application if I ever need to, but it allows other people to easily set up and run my application as well. Maybe you'd like to try it, and make your own comic?

Here is the link directly to the INSTALL.txt file in the repo on GitHub, so you can check it out.

What's next? Maybe complete automation of the setup using something like Puppet. That way I could take advantage of an auto-scaling service like AWS offers, so when my comic gets insanely popular I won't have to worry about long response times. It could happen.





As a side note, I found out while I was doing this that a new major version of PhantomJS was recently released. This 2.0.0 has some major differences and actually fixes some bugs that I've encountered while using it to generate the static images of my comics. Unfortunately, there is no binary distribution available for Linux yet - so my installation instructions for Amphibian.com actually include building PhantomJS 2.0.0 from source. That takes a long time, so I'm keeping my binary around in case I need it again before the official ones are available. If you would like it (built for Ubuntu 14.04.3 64-bit) just let me know and I'll give you a link.



If you're done setting up your own copy of Amphibian.com now, click the picture below and view my Amphibian.com comic for today!

Amphibian.com comic for 25 January 2016

Friday, January 22, 2016

Training Days

I've only had one day of "real" work in the last two weeks. I have been attending lots of trainings. Last week it was DoDAF and Cyber security architecture. This week it's Amazon Web Services. Next week it will be more Amazon Web Services. I haven't sat in class this much since college.

Now, I'm not complaining. It's great that my company is investing so much in me and is helping me to become a better software architect. It's just that I have a hard time with formal classroom-type training and so much of it at once is wearing me out.

I'm self-taught in most areas of software. Sure, I have a Bachelor's degree in Computer Science...but that was a formality. I had already learned (the hard way) just about every concept I was taught in my major courses. I suppose I learned something in my general education classes, probably. I'm not entirely sure that I would have been ready for a job as a professional software engineer had I not been writing and selling commercial software before going to college and working on cutting edge stuff on the side while in college. But that's just me.

I guess I have a Master's degree in software engineering as well. But I got that after already working as a software engineer for 12 years. I'm sure I learned something in the course of getting that degree, but it's all mixed up in my mind with things I learned on the job.

I really like to learn by selecting a technology of which I know very little and then building something with it. Academic exercises don't do it for me. I need to make something. I need to make something real and practical. That's how I learn.

It's been a struggle, but I'll survive. Hey, why don't you click on the picture below and look at the comic I made for today? You won't learn anything from it, I promise.

Amphibian.com comic for 22 January 2016

Wednesday, January 20, 2016

A Match-3 Tile Game in Phaser

It's finally here! The day I release the comic containing my match-3 game! I've been working on this thing for way too long. When I had the idea to put one of those classic tile-matching games in a comic (you know, like Bejeweled) I had thought that it would be easy to put together. I used Phaser, course, but I was unprepared for just how much goes in to one of these things.

Getting this one simple game embedded in the 3rd frame of the comic came in at a couple hundred lines of code. Like everything else in my comic, you can see the complete source code on GitHub (this link goes directly to the game's .js file) so I won't bother to post the whole thing here. But one concept came up more than once during the development which I'd like to talk about.

Tile Matching game with Amphbian.com's frogs

The issue was that I needed to do Phaser Tween animations on possibly over 20 sprites at once, and then take some other action when they had all finished. Making a single Tween call a function when complete is rather straightforward, but what is the proper mechanism for firing off an event when a bunch of other asynchronous events have completed?

Here's an example of a Tween that calls a function when complete:

var tween = game.add.tween(sprite.scale);
tween.onComplete.add(someFunction);
tween.to( { x: 1, y: 1 }, 500,
    Phaser.Easing.Linear.None, true, 0, 0, false);

The above code creates a Tween that will change the x and y fields on sprite.scale both to 1 in 500 milliseconds. When complete, the function someFunction will be called.

Now what if I had 5 Tweens that all take different lengths of time to finish, and I don't want to execute a function until they are all done? Sure, I could just call the function when the longest one is complete, but what if they don't even all start at the same time? It could get messy. The solution is to make a little closure function that counts completions and then executes a callback function when the counter reaches a set level. Here is what I mean...

var num = 5;

var counter = function(total, callback) {
    var t = total;
    var c = 0;
    return {
        inc: function() {
            c++;
            if (c === t) {
                callback();
            }
        }
    };
}(num, someFunction);

var tween = game.add.tween(sprite.scale);
tween.onComplete.add(counter.inc);
tween.to( { x: 1, y: 1 }, 500,
    Phaser.Easing.Linear.None, true, 0, 0, false);

// now make 4 more Tweens here, with different lengths


Assuming I know how many Tweens I'm going to make, which is 5 in my example above, I can declare an anonymous function and then immediately call it passing in that number along with the function I want to use as the callback. That anonymous function creates a closure and returns an object (assigned to the variable counter) with a function inc. Every time counter.inc is called, it increments the internal counter and checks to see if it is equal to the expected total. If so, callback is executed - and here callback is someFunction. The onComplete event on the Tweens just has to call counter.inc and everything goes off like expected. Once all five are done, no matter how long it takes, someFunction will be called.

I ended up using this pattern in two different places in my match-3 game. My game certainly isn't the best example of a classic match-3 tile game but it's also meant to be a joke in a comic. If you're interested in how it works anyway, be sure to check out the source code. At the very least, look at the comic and match up some frogs!

Amphibian.com comic for 20 January 2016

Monday, January 18, 2016

A Phaser Game With Mouse/Touch Input

I'm back from Texas and have mostly recovered from the events of last week. I still have a bit of a cold, but I'm not letting it stop me from getting a simple game ready for inclusion in a comic this week. This game will use mouse/touch input instead of the keyboard like my last one did, so I had to figure out how to use sprite dragging in Phaser.


Like most things have been with Phaser so far, it took a few tries to get it all correct but in the end it all seems really simple. It revolves around enabling input on individual Sprites, enabling drag, and then optionally listening for drag-related events.

Here is the complete source code for a Sprite-dragging demo:

var init = function() {

    var game = new Phaser.Game(width, height, Phaser.CANVAS, "gameArea", {
        preload : preload,
        create : create
    });

    function selectFrog(sprite, pointer) {
        console.log("selected");
        sprite.frame = 1; // frog in the air
    }

    function releaseFrog(sprite, pointer) {
        console.log("released");
        sprite.frame = 0; // frog sitting
    }

    function preload() {
        this.load.spritesheet('frog', 'assets/sprites/frog.png', 79, 60);
    }

    function create() {

        this.stage.backgroundColor = "#999999";

        var frog = this.add.sprite(50, 50, "frog", 0);
        frog.inputEnabled = true;
        frog.input.enableDrag(true);
        frog.events.onDragStart.add(selectFrog, this);
        frog.events.onDragStop.add(releaseFrog, this);

    }

};

window.onload = function() {
    init();
};

The selectFrog and releaseFrog functions are the event handlers for the drag start and drag stop events. In this example, all they do is log something to the console and change the frame of the sprite. In my upcoming game, I do more in here such as tween animations and game logic.

When I make the frog sprite in the create function of my example, setting inputEnabled to true is the first step. Without this, you can't do anything with input to the individual sprite. Once that is done, you can set the specific input behaviors. The very next line, frog.input.enableDrag(true), turns on drag-ability. The single parameter passed to the function sets whether or not the Sprite should re-center itself to the cursor upon being drug. I passed true, which will cause the center of the sprite to jump to the position of the cursor when the drag starts. If this isn't what you want, you can also say false and drag from any part of the sprite - not just center.

When dragging is enabled, the sprite will fire off events for drags starting and stopping. I added the selectFrog and releaseFrog functions as event handlers using the onDragStart and onDragStop fields of the sprite's events field. Note the parameters that get passed to these event handlers when they fire. The first is the sprite object that was the subject of the drag and the second is the Pointer object. There's lots of information on the Pointer object about the state of the pointer if you want any of that to matter in your game.

If you've tried the code above and are using a mouse, you might be disappointed that the cursor changes to that text-select I-beam cursor thing while you drag the frog. If you'd like it to stay as the default cursor while you drag, no problem! You can simply override the cursor style in the create function. Just add this line:

this.game.canvas.style.cursor = "default";

Now the cursor will always be the default pointer regardless of what you are clicking or dragging in the game. If you'd like the cursor to turn into the click-here hand whenever it's over the frog (dragging or not), there's also the useHandCursor field on the input object. If you add this line to the create function instead...

frog.input.useHandCursor = true;

...it will turn the cursor into the hand when you mouse-over the frog. I didn't care for that personally, but it might be useful in certain situations.

Now that you've read all this, you probably want to see this sprite-dragging in action. Sorry, but the game I was making is not actually in today's comic. You have to wait until later in the week. Click the image or link below for today's comic.

Amphibian.com comic for 18 January 2016

Friday, January 15, 2016

Least Productive Day Ever

This hasn't happened in a very long time, but I have absolutely nothing of interest to share today. I've been in training all day, ate some dinner, and then couldn't get anything to work with the comic game for next week. I think I'm too tired. I have one more day here in Dallas, so I found a nearby movie theater and went to see Star Wars again. I took the stuffed frog with me.


Hopefully I'll have something better next week, including better comics. For now, you get this one.

Amphibian.com comic for 15 January 2016

Wednesday, January 13, 2016

A Stuffed Frog Returns to Texas

Again I have returned to the Dallas area for a week of work that is slightly different from my usual work. Since living out of a hotel is not extremely conducive to either my game development or comic writing hobbies, I present you instead with more pictures of my daughter's stuffed frog doing things with me on my trip.


At our airport, there's a phone on the wall after you go through the security line. It links to the other side of these big glass windows so you can talk to people after going through security. It's been there for a long time, since before people could do that with cell phones I guess. But anyway, here is Froggy talking to my youngest daughter using that phone. My wife is helping her.


When I do these types of posts, you'll notice that Froggy is eating in many of the pictures. Since I have to work most of the day, dinner time is when Froggy and I get to spend the most time together. I always try to feed him well. Here he is eating some macaroni-and-cheese with bacon and mushrooms in our hotel room. It was from the Potbelly Sandwich Shop. I ate the sandwich (not pictured).


What does Froggy do all day while I'm working? Mostly he just sleeps in my backpack, as seen here.


We don't always eat in the hotel. Above is a picture of Froggy eating at the Texas Land & Cattle Steakhouse. He doesn't eat much but is always stuffed.

Now please enjoy today's Amphibian.com comic where the frogs are no more real but no less entertaining.

Amphibian.com comic for 13 January 2016

Monday, January 11, 2016

Tweens in Phaser

I was playing around with another simple game-in-a-comic idea today and I started using Phaser's Tweens. No, Phaser doesn't actually have children between the ages of 10 and 12. Phaser's Tweens are a convenient way of updating one or more object properties over a specified time range.

I'd never used a Tween before, but after playing around with them for a little while I decided that I could use them to replace an effect I had been doing "the hard way" in my platformer. Recall that when the frog gets hurt, I temporarily set his alpha value to 0.5 and then start a timer to set it back. Along with the alpha value, I also set/unset an immune flag on the frog. I can do this same thing better using a Tween.

I've replaced my frog-hurting-alpha-adjusting code with the following...

var t = game.add.tween(frog);
t.onComplete.add(function() {
    frog.immune = false;
});
t.to( { alpha: 0.5 }, 50, Phaser.Easing.Linear.None, true, 0, 2, true);

On line 1, I create the Tween object using the familiar GameObjectFactory (game.add). When creating a Tween, you pass in the object on which it will work. In my case, that's the frog sprite.

Before starting any tweening, I add a listener for the onComplete event. I do this because I want to turn off the frog's immunity when the alpha animation is over.

The final step is to create and start the tween. The last line above calls the to function, creating a tween that moves the specified properties of the object TO the given values. The properties and the target values are given by the object that is the first argument to the function. In my example above, that's { alpha: 0.5 }, which means I want to move the frog.alpha property from whatever it is currently to 0.5. The second argument is 50, which means I want the transition to the new alpha value to take 50 milliseconds. The third argument specifies the easing function to use in the transition. The fourth argument specifies auto-start. I want this tween to start immediately upon creation, so I specified true. The 5th argument is start delay, which is none because I used 0. The 6th argument, which I have set to 2, is the number of times to repeat. The final argument, which I set to true, is the yoyo parameter. Turning on yoyo means that the tween with play backwards automatically at the end. This means that after reaching the alpha value 0.5, it will start transitioning back to the original alpha value. For me, this created a nice flashing effect.

So how long does the whole thing take? I specified 50 milliseconds, but that's just for the one-way transition from 1 to 0.5. Since I turned on yoyo, it doubles to 100 milliseconds. And I also set it for 2 repeats, so the whole flashing alpha thing should complete around 300 milliseconds after it starts. Just remember to do all that math if the length of time is important to you.

The frog's alpha flashes after being hit - thanks to Tweens!
Tweens give me the ability to do some nice things with animating Sprite properties which would be very difficult to do in other ways. I'm glad I discovered them. You can discover the complete source code for the game on GitHub. Just click on this link!

And speaking of discovering things, have you discovered how much you like reading my Amphibian.com comics yet? Look at today's, and maybe look at some other ones while you're there.

Amphibian.com comic for 11 January 2016

Friday, January 8, 2016

You Can't Play Forever

With my one hour of game development time this evening, I decided to finally add "lives" to my Phaser platformer. While I don't want to actually kill Science Frog, the concept of getting more than one life (or attempt) in a game is a fairly standard concept. So far, my game was once-and-done.

The glasses represent the number
of tries (or lives) you get in the game.
Keeping track of how many lives you currently have in the game was simple. I added a lives field to my gameState object. That's the one that I am using to keep track of aspects in the game that need to be shared between the two main game states - the picking a stage and the playing.

var gameState = {
    levels: [],
    currentLevel: "sb",
    lives: 3
};

Now to use that... First, to display the number to the player I added an image of the frog's glasses next to some text beside it. I decided that the glasses would be a good representation of Science Frog. Maybe when he gets beat up too much his glasses will break and that's why he has to restart. That way, I don't have to say he gets killed. Anyway, those steps are simple.

var g = game.add.image(40, 15, "glasses", 0, meters);
g.fixedToCamera = true;

var livesText = game.add.text(78, 5, "x " + gameState.lives, {
    fontSize: 20,
    fill: "#FFFFFF",
    stroke: "#000000",
    strokeThickness: 3
}, meters);
livesText.fixedToCamera = true;

First, I add an Image to the game at position (40, 15). The key for the image is "glasses" which is what I assigned to this image in the asset pack. The 4th parameter, 0, is unused here because as an Image (as opposed to a Sprite) there is only one frame. The last parameter is the group to which this image is added. I am putting it in my meters group, the same one that contains the health bar. After creating it, I set it to be fixed to the camera. This way it doesn't scroll with the rest of the world.

Adding the text for the lives is also simple. Calling game.add.text is all it takes! The first two arguments are the X and Y coordinates. The third is the text itself. The fourth argument is the style object. Its fields define the style of the text. I set the size, fill, stroke, and stroke thickness. Since the background can be very light, putting a black border around the text makes it more readable. The fifth argument is once again the group to which this text should be added - again I use my meters group. Finally, this also gets fixed to the camera.

I've had an onKilled listener on my frog object for some time now, but it didn't do a whole lot. I expanded on that today to take advantage of the lives counter.

frog.events.onKilled.add(function() {
    dieSound.play();
    gameState.lives--;
    bgmusic.stop();
    if (gameState.lives === 0) {
        console.log("game over!");
        game.state.start("stageSelect");
    } else {
        console.log("try again!");
        game.state.restart();
    }
}, this);

The player's frog is killed by Phaser when its health reaches 0 (from colliding with enemies) or when it falls off the bottom of the map. This onKilled event listener is called when that happens. It plays the death sound, decrements the number of lives, and stops the music. If the player has no more lives, the game is returned to the stage select screen, but otherwise the current level just gets reset and the frog starts over back at the beginning.

I suppose this means I need to add in extra-life power-ups somewhere...

You can access the complete source code for this game on GitHub, and you can access the complete Amphibian.com comic on Amphibian.com! Or click on the picture below.

Amphibian.com comic for 8 January 2015

Wednesday, January 6, 2016

Back to Work

I might not get anything done for the rest of the week. Yes, after an extended end-of-year vacation, I've had to return to my real job. My next holiday is in five months. I'm getting extremely limited exposure to sunlight. This is my least favorite time of year.

It's also 8 degrees outside right now. That's Fahrenheit. For you non-Americans, it's -13.

The good news is that I already took down the Christmas decorations. Last year, it was so cold outside for so long, I left them up until March.

But I feel like I have to share something valuable on my blog today...so here is a link to a great frog wallpaper for your computer. I'm using it right now. The site has more.


I feel better now. Maybe today's comic is too depressing. I don't know, read it and tell me what you think.

Amphibian.com comic for 6 January 2016

Monday, January 4, 2016

Falling Down - Disable Some Phaser World Bounds Checks

Since adding the ability to have more than one level in the platformer I'm building with Phaser, I actually created a second level. Like many platformers, it has...ummm...platforms. What I mean is that unlike my first test level that just had the ground and some boxes to jump on, this second level has no ground and is just a bunch floating clouds on which to jump. If you miss your platform and fall to the bottom of the world, you die.

Hey, you! Get off of my cloud!

Well, not really. The way the game worked was that the player just landed on the bottom of the world bounds and stood there. When I create the player's frog Sprite, I turn on collision with the world bounds. What are the world bounds? Basically that's the defined map. The world bounds collision check prevents the player from walking off the world on the far left and right, but it also prevents the player from falling through the bottom or jumping off the top.

var frog = group.create(50, 50, 'frog');
game.physics.enable(frog, Phaser.Physics.ARCADE);

// stay inside the world boundaries
frog.body.collideWorldBounds = true;

I had a hard time finding an example of what I wanted to do. I performed a great number of fruitless searches, which is fine because I wasn't really looking for fruit. I just wanted to find the easiest way to keep the left/right/top world collisions but turn off the bottom. I read some rather complex solutions that actually replaced the bounds check function on the Sprite, but the simplest solution turns out to be really...simple.

First, the player's frog object needs some minor settings adjusted.

frog.checkWorldBounds = true;
frog.outOfBoundsKill = true;

I already had collideWorldBounds set to true on the physics body, but I also need to set the checkWorldBounds property directly on the Sprite to true. By itself, this has no effect, but it is necessary if I also want to set the outOfBoundsKill property to true. Independent of the physics collisions, these two settings tell Phaser to check on each frame to see if the sprite in question is inside the bounds of the world, and if not, to kill it.

With just this change made to the frog, nothing seems any different. The player can't actually fall or walk off the world because collideWorldBounds is also set to true. It takes just one more line of code to turn off the bottom-of-the-world bounds check and allow the frog to fall to his death. Here it is, on line 6 below:

function create() {

    game.physics.startSystem(Phaser.Physics.ARCADE);

    // turn off the collision with the bottom of the world
    game.physics.arcade.checkCollision.down = false;

    // ... other stuff ...

}

As you can see, I make this adjustment immediately after starting the physics system. I only turn off the down collision checks, but you could just as easily turn off up, left, or right depending on your game's needs.

Now the frog can't walk off the left or right of the map but can fall in a hole or off a platform. If you want to see the complete source code for the game, it is freely available on GitHub. If you want to see today's Amphibian.com comic, it is also freely available. Just click on the image of the first frame below...

Amphibian.com comic for 4 January 2016

Friday, January 1, 2016

Particle Emitters in Phaser

Happy New Year!

I had a list of things I wanted to get done with the platformer I'm building with Phaser before 2016. One of them was to add bosses to the levels. Not like manager bosses. Bosses like the big enemy at the end of the stage.

The basics of adding a boss were the same as adding another type of "regular" enemy. I placed the enemy in the level editor, took note of the gid assigned to it by Tiled, and added a setup function to add specialized behavior. I wrote about this process in more detail previously (read those posts here and here).

The big addition here is that I want the boss to throw something at the frog. To accomplish this, I decided to use a Phaser Particle Emitter.

Phaser's Particle system is very nice. Using an Emitter, you can generate bursts of Sprites easily and with randomized attributes. In my game, I made a level boss dinosaur that throws plates off his tail. Those plates are the particles.

First, I had to define the image for the plate and put it in my asset pack. I did this and gave it a key of "dino-plate." After that, making an Emitter that throws the plates is simple. Look at this sample code from my game (you can see the complete source code of the game on GitHub):

var e = game.add.emitter(0, 0, 5);
e.makeParticles('dino-plate', 0, 5, true);
e.gravity = 30;
e.maxParticleSpeed.x = -700;
e.minParticleSpeed.x = -400;
e.maxParticleSpeed.y = -500;
e.minParticleSpeed.y = -300;

The first line creates the Emitter. The first two arguments to the function are the X and Y coordinates of the emitter. I don't have to worry about the real position right now because I'll move it every time I use it to be in the same position as the dinosaur. The third argument is the maximum number of particles this emitter will contain.

The second line calls the makeParticles function to actually create the particles that will be emitted. The first argument is the key for the image or spritesheet to use for the particle. The second argument is the frame of the sprite, but I'm using a single image so I just use 0. The third argument is again the number of particles to create. The fourth argument is set to true to enable physics bodies on the particles. I need this set to true because I want the particles to be able to collide with the frog.

The rest of the lines control the properties of the particles tossed out of this emitter. For this boss, I want the things thrown to have less gravity than the rest of the game. This makes them fall slower purely for dramatic effect, and is completely optional. The max and min speed settings define the bounds for the speed of the particles. Phaser will assign a random speed to each particle within these bounds.

When the time comes for the boss to attack, it's simple to start the emitter.

e.x = boss.position.x + 100;
e.y = boss.position.y;
e.start(true, 2000, null, 5);

Like I said above, I re-position the emitter before I start it each time to make it appear as though the particles are actually coming from the dinosaur's position. After that, calling start causes the Emitter to burst out the particles. The first argument to start is true because I want it to emit the maximum number of particles (in this case, 5) all at once. The second argument is the life of the particles in milliseconds. I want them to exist for 2 seconds. The third argument, which I set to null, is the frequency of the emissions. It's not used when the first argument is set to true, so I use null. The last argument is the quantity to emit. I use 5 so all the particles are thrown out.

The effect is very nice when you see it in action. The randomization of the various attributes makes the burst look natural and realistic. I captured an animation of it...



I like it. I hope you like the comic today, and the rest of the comics that will be coming this year.

Amphibian.com comic for 1 January 2016