Jeffkillian.com initially started as a Geocities website when I was in 6th grade. Over the years, it has slowly evolved into a place where I can practice and become familiar with web development as it progresses. I started out coding with Microsoft Frontpage, then moved to Dreamweaver. Initially, there was very little coding, and it was all WYSIWYG. However, as I learned more, I could make it more interactive.


I incorporate drawings and blog posts to keep those that are interested updated. Through the evolution of the website, I was forced to learn HTML, PHP, CSS, XML, jQuery, javascript, and the handling of MySQL Databases. I've put online some code samples.
Holy Stone HS177 Drone Review

These were the second drones I ever owned (I first bought the Holy Stone F181W), and thus I was pretty excited to see how a different, smaller drone behaved. I was expecting something pretty toyish, but found out these drones were more than just "battle toys". Ignoring the battle functionality completely, I would buy these individually just to fly around.

The set comes with two drones, as well as a removable cover so you can change one of the drones to have a different color top (blue, red, or green). While these drones are dueling drones, they very easily pass for a normal fly-as-a-hobby type drone, so I will be reviewing them accordingly.

Distance
Range never turned out to be an issue (not that you buy these for their range). With how small these drones are (about 7" x7"), you wouldn't want to fly it anywhere more than 30 meters. This is because, despite there being a bright light on the front to indicate which way is forward, it's hard to determine which way it's facing when it's far away due to it's size. Below you'll see two images comparing it to a GoPro, and comparing it to the larger Holy Stone F181W

Battery/Charging
Each drone takes one removable battery (included) that plugs into a standard usb charger (given). The batteries charge pretty quickly (30-40 minutes). When flying on beginner mode, the flight time was impressive (12-15 minutes). One plus that I noted: there was no cool down period needed for the drone between \flights (In other Holy Stone drones, you need to let the motors cool down between flights so that you don't burn out the motors) There is no mention of this in the manual, and I haven't found this to be the case. One flaw I found in their charging configuration was that it's not very easy to plug/unplug the battery into the drone. You wind up having to pull on the wires to get the charger out, which makes me feel like I'm going to crimp or break the wires on the battery. Additionally, when plugging the battery in, you have to use the wires to push the charger into the port. This becomes quite awkward as you have to line it up perfectly.

Speed Modes
The drone comes with three modes: beginner, intermediate, and advanced. A button on the remote controller allows you to quickly adjust which mode you are in mid-flight. Intermediate mode comes with significant speed, and advanced mode is truly an advanced mode, so there's a good range of skill required. This drone would be nice both for people who are just starting out, as well as those who are pretty familiar with flying.

Flight
The drones feel very responsive during flight. Because of the build in gyro, they remain mostly level during flight. On Expert mode, the drone is extremely sensitive, which allows you to make really sharp, banking turns. I'd consider myself somewhat of a beginner in terms of flying ability, and I feel most comfortable on the beginner setting. The drone is able to change horizontal direction quickly, though it's a little slow to descend at some times (but not enough to be annoying). I was surprised that, even flying this outside, the drone was incredibly stable, much more so than the larger F181W, especially when the wind picked up. Below you'll see a video I made demonstrating flight features.

Build Quality/Integrity
Because the drones are so light, it's more difficult to break them just from falling under their own weight. That being said, they are a bit fragile due to their size. While there are guards on the propellers to prevent you from breaking the propellers, the set does come with extra propellers in case you break some.

The plastic does feel a little cheap, specifically the removable colored cover. Durability was sacrificed a bit in favor of weight in this regard.

 

Extra Features

Pros

 

Cons

Overall, I would suggest these drones for anyone who is a beginner to intermediate, as they allow a lot of room for improvement, and come in at a low price

The simplest/most complete javascript box2d/liquidfun repository

I've spent way too much time looking into various ports of Box2d and liquidfun for javascript in order to find the most complete, simplest one. I wanted to create a game, but getting started with liquidfun in javascript seemed surprisingly difficult. I've created a few liquidfun games, but each time I'm never satisfied with the library that I'm using...until now.

Below is a list of notable forks that I've found.
TL;DR: Use liquidfun-pure-javascript. It's a barebones javascript fork that already has a working example so you can get right to coding/playing around.

Liquidfun

This is a great start. It incorporates everything box2d has, and adds in really fun particle physics. The major drawback for this is that it only comes with one minified js file. It's a conversion from C++ using emscripten, so it doesn't have all features properly ported over either.

Box2d.js

This is a great port that includes all *.js files. The main downside here is that it uses google's closure compiler, so you'll need to be familiar with that in order to use this box2d fork. One advantage of this over liquidfun is that it supports b2ParticleSystem.GetBodyContacts(). This is necessary if you want to detect collisions between particles and bodies. For some reason, the standard emscripten liquidfun port above does not include this.

liquidfun-pure-javascript

This things got everything:
  • No google closure compiler, or any compiler necessary
  • Uncompressed *.js files for debugging
  • Example index file to hit the ground running
  • Full liquidfun port that includes all functions (including b2ParticleSystem.GetBodyContacts())
Gifntext - Removing Hosting
This is going to make some people angry, so I want to clear up exactly what is happening with gifntext, and why we are making the decisions we are making.
 
Gifntext was always meant as a way to edit gifs, and that was it. It was not created initially with the idea that we would host the files, that was just something that happened to work out while the site was small. However, as the site grows, it becomes more and more tedious to host all of the files. On top of this, we can’t have ads (this has to do with users uploading pornographic images…I just don’t have the time to delete them all). 
 
I understand that ending the hosting of these gifs might upset some, as they might be hot linking directly to gifntext, which was previously acceptable. However, doing this allows a few things to happen:

  1. We continue to exist, and you continue to make gifs for free. If I kept hosting, I would eventually run out of money, as I’d need to pay for the bandwidth myself
  2. We can (potentially) break even on cost, as it might allow us to introduce a few non-intrusive ads to the site.
  3. We can focus more on new features
 
I wouldn’t be doing this if I didn’t feel like it was the right decision for the users. All along, we’ve constantly tried to put the users needs first. I know this is a disadvantage in the short run, but it’s the only option which allows the site to continue operating, providing new room for growth. 

 

Minor Change to Gifntext

The day has come where I’ve decided to put a few ads on the main page of Gifntext. I’d told myself I would only do this if it became necessary, and, to keep this website up, this seems necessary. I want to be completely transparent so here is why you’ll see a couple of ads on the home page of gifntext from now on.

I’m on an unlimited plan for web hosting. This means I don’t have a bandwidth limit. However, on the current plan I have, things like hot linking are not allowed. Users are doing this. One solution I have is to completely foil hot linking. While I am doing something to this effect, I can’t completely prevent it. Furthermore, I believe hot linking, although annoying to my hosting provider, can serve a purpose, as it can show a gif directly inline.

The other solution, and the one I am going to attempt, is to upgrade my plan. I believe it will cost around $30-$40 a month to do this. Therefore, I’m going to run a couple of non-intrusive ads on the main page in hopes that these will cover my monthly cost, and I can simply upgrade to the better account and keep things running smoothly.

TL;DR There will be a few ads on the gifntext.com homepage in order to cover a potential upgrade that I will be doing. I’m not sure how much I’ll generate from the ads, but over the next few days it will become pretty clear whether or not they will be able to keep this website afloat. If not, I'll keep you updated on any new changes I'll have to make in order to keep the website going.

Gifntext - Update 5

My main time outside of work/play has been working on the gif editor gifntext. There've been a bunch of updates since the last post, and I wanted to share them:

The main gifntext page in August, 2015
Gifntext - August 2015
The main gifntext page in January, 2016
Gifntext - January 2016

One reason I enjoy working on this is because I'm learning so much. Here are a few things I've learned in the ~6 months the website has been active:

Not only do I enjoy making the tool, but I get almost instant feedback, as I see people using it and making requests. To date, there have been 29,854 gifs created. Here's what the editor looks like now:

 

As the website has continued to grow, there have been some enhancement suggestions that I'm toying with implementing:

 

Another Gifntext Update
Following up on last post I thought I'd give another update on gifntext, as that's what I've been doing in my free time. There've been a bunch of updates in the last month:
The last one was the biggest one. It existed for a long time, and I couldn't figure out what was going on. You can see it in this soccer gif, right as the ball hits the post. Look for it glitching.

Background: The gifs that gifntext generates are very big files. In order to generate them, I take a frame, and do some magic on it to encode it so that it works in a gif. This encoding is process intensive. Because of this, I encode a gif frame by frame, rather than encoding the entire gif at once.

Once encoded, the frames are then saved to a file. I'd boiled down the issue to the fact that sometimes the frames saved out of order (for instance, it would save frame 5, then frame 7, then frame 6). However, the way that I was generating frames, this seemed impossible. This is because the next frame could only generate once the previous frame finished. On top of all of this, this bug never occurred when I was generating a gif. I could only see that on the "recently created" page, some gifs were skipping. This made it extremely difficult to debug. It also made debugging take a while, as I had to wait until I saw that a gif skipped before I could go examine the log to see what happened. I ended up creating a script that logged every single action that any user made in the order that they did it so that I could trace the code path that was taken. The log looked something like this:

        step: about to doStep while generating 10, Are we stepping?true
        Dostep: We are within doStep on frame 10(though it will change to 11) here
        DoStep: about to step frame 10
        DoStep: we just stepped to frame 11
        DoStep:  We are about to save frame 11
        SaveFrameToFile: about to save  frame  11 to file
        DoStep:  We just saved frame 11
        step: just did Step while generating 11 Are we stepping?true
        saveFrameToFile: Adding frame was a success - Previous: 10, Current: 11
        SaveFrameToFile: Now that we have succeeded in adding that frame, going to step
It allowed me to see which function I was in, and which frame was just added.

Using this log, I was able to find out that sometimes frame 1 ended it's process (without even saving the file) prior to frame 0 ending it's process. What this meant was that we actually had two concurrent processes trying to add the frames to the same file. I was able to add in a variable that allowed only one process of generation at a time, and the bug was fixed. This bug was the gifntext version of my water rendering problem from dangeraffe; both issues were challenging, but I logically went through the code and after much persistance, was able to solve the issue.

There are many new enhancements that I'm still hoping to implement, given that I have time:

Those are mostly just ideas that I've had for the website. Maybe I'll add a simple poll, so that people can fill in what they want to be on the site.

Gifntext - An Update
The majority of my time away from work has been working on gifntext, which is a website that allows you to add images or text over a gif. I was tired of seeing a bunch of cool gifs online without having any way to make them. Some of my favorite gifs (which I now know to be called animal text gifs, involve dubbing text over animals:
cat ballet gif

cat ballet gif

cat ballet gif

I had started to keep a perosnal repository of gifs that would be fun to dub over. However, I realized there was no easy way to add the captions to a gif. Because of my work with dangeraffe, I was pretty familiar with html canvases. Also, there was a point in dangeraffe where I had experimented with a recording feature so that you could record your craziest moments. Because of this, I had a solid base working with canvases. I decided I'd try to make an online gif editor, and see what would happen.

It started out with me just googling different gif libraries, trying to see what already existed. One requirement was that I wanted it (at least initally), to be all client side, so I wanted to try to do it with javascript whenever possible (this ended up happening, although some of the gif saving is saved to a file for memory purposes). I found a bunch of useful resources regarding how to turn gifs to a canvas. After a bunch of trial and error, I had a basic website set up where you could add text to a gif, and gifntext was born.

I posted about it on reddit, hoping to get some feedback, and got many positive responses, as well as ways that I could improve the website. I took all of the feedback, and developed the site for about three months. This was such a long process because I could only work on it in the off hours. On top of that I had to balance it with playing with my dog:
With the addition of the new requests, I realized the website was gaining popularity when I kept getting emails saying that generation of longer gifs wasn't working. I used excel and some javascript output to create the chart you see to the right. To understand this chart, you just need to know two things. First, gifs are just long strings of characters. Second for the gif generation, I go frame by frame, convert the image to the proper string of text, and then add that text to a long string, which we eventually spit back out as the gif file. What I found was that the later frames took much longer than the earlier frames. Because each frame is relatively the same size (width/height), it is not due to generlly having more data on these frames. Rather, it is because the string that represents the gif is being held in memory, and it is getting bigger and bigger. When I say big, I mean 7,000,000 characters big. When I initially developed it, I was only testing on smaller gifs, and just wanted a proof of concept. Once it was done, I figured I'd fine tune the performance aspects. The result of this is that, each time we added a new frame, we were going over every character in this long string. Because this is all happening client side, the client eventually runs out of memory. Once i realized this, I did some reorganization of code, and was able to completely eliminate the overhead of keeping that string in memory, as the frames are now saved off to a file on the server each time a frame is added.

This was the biggest problem that the website was facing. Once this was solved, most scalability concerns were handled, and I was able to sit back and see if the site was useful. From what I can tell, gifntext really is the easiest way to add text or images over a gif that I could find online. I'm now trying to learn more about search engine optimization, so that the website appears more frequently for appropriate searches. Using a simple SQL query, I grouped the number of uploads by day, and graphed that over time.

You can see that the number of uploads really started to take off around September 3rd. This is all with minimal advertisement. If I added a watermark to each gif, I could greatly increase the visibility of the site, as every gif would essentially be a link back to my site. However, I've chosen thus far to not implement a watermark, as I think it somewhat ruins the gifs to have dozens of watermarks all over from different websites. Hopefully the users are nice enough that they'll link back to the site, and word of mouth will be enough.
Sevi and Vinny

Here's a picture of my dog meeting our neighbors dog:

Gifntext.com

I've always been frustrated that there's no easy way to create gifs with text over them, so I've been working on a side project to do just that. It allows you to add text to a gif.

Simulating and rendering water from liquidfun.js, a box2d port
After some significant development in dangeraffe there was still one thing that really bugged me that I wasn't able to solve. Water just didn't feel right.

Rather than being a continuous liquid, it was just a series of differently sized balls. While the balls did have physics that mimicked liquid flow/properties, I couldn't stand how it looked. I had no idea even where to begin, but after a bit of googling, I was able to find a helpful page that explained the term I was looking for: Rendering.

In essence, I had the locations of all of the balls given to me by the liquidfun engine. What I wanted to do was find a way to render(display) those balls, without displaying the actual balls that were there. Instead I wanted to display something that moved and flowed like water, and looked like one coherent unit when all together.
I ended up on a blog post about Liquid Simulation in WebGL by Chris Wellons, which looked like it was right up my alley. However, it mentioned using something called WebGL, which I had never heard of at the time. From what I coudl tell, it was a way to take some stress off of the CPU when rendering, and instead use the GPU. Again, this was a foreign language to me, so I ignored it. Chris had made a bottle like simulation , and broadly detailed the steps needed to render water:
  1. Do a physics simulation of balls in a container
  2. Render the simulation onto a raster
  3. Blur the image
  4. Apply a threshold
Steps 3 and 4 were the crucial part. They were the actual solution to the question "how do you turn the balls in liquidfun/box2d into a liquid-like substance?"

While I won't get into too much detail about the actual mechanics behind rendering, (you can find more here), you must first blur the balls, and then you apply a threshold. Blurring the balls makes them appear more as one continous body. Applying the threshold allows a clear cut outline of any given water bodies. If the image is above the threshold, we paint it black (or in the case of water, blue). If it is not above the threshold, we paint it white.
While testing, you can alter the threshold to see what it would be best as. Too small, and nothign shows up because everythign is too blurred. Too big, and the threshold does not have any affect, and you get a blurred image.

Blurring and Thresholding
Now that I knew I had to use a blur and a threshold, (and because I had never worked with WebGL), my first thought was to look for a javascript library that would do this for me. My thought was, because my image is on a canvas, I can simulate all of the water balls on a seprate canvas, apply the blurring and thresholding, and then draw the image on that canvas. I looked at a bunch of different libraries, the most helpful were The problem with the libraries above is that they are all javascript based. glfx.js is actually a webgl framework, but I didn't even know enough to know that this is what I should be using, and that it was different. While I was able to get a tiny implementation running via stackblur, it required copying the red,green, and blue values for every pixel on the canvas. I had to do this every frame (the game runs at around 60 fps), and then redraw this on a new canvas. This was much too process intensive, and I was getting at maximum 5 or 6 frames per second. It was at this point that I decided to take a break, and admit defeat....or so I thought.

I developed some new features, but still couldn't get the water rendering out of my head. About three weeks later I decided to revisit the issue, and try from a fresh start. My new implementatation started as an actual copy of the bottle simulation mentioned before. I didn't know WebGL, and wasn't about to learn it. Water was important, but my time could better be used implementing other features. Therefore, I copied the entire bottle simulation repository, and pasted it into my directory. I then worked backwards, figuring out the coordinates relative to my coordinates, deleting the spikes on the sides, and so on. Eventually, I had a bottle simulation that was running over dangeraffe. The canvases were overlaid, with the bottle simulation being above dangeraffe.

I was able to transfer my points via an array to the bottle simulation, but the simulation kept crashing. This was a result of it having a memory leak from using an outdated version of box2d. I spent a while porting the included box2d into liquidfun.js (aka B.Vec2>b2Vec2, B.World>b2World...). I was relying on this fixing the memory leak, and it did.

The last step was to map the water points that I currently had in dangeraffe into points that were appropriate for the bottle simulation. This was the part that took the longest, as it turns out the y axes are inverted and the bottle simulation goes from -1 to 1 on both axes. Once I had a function that could map my points to the bottle canvas, it was just a matter of calling the render function from my source dangeraffe code, and we ended up with beautiful flowing water. It's not the prettiest implementation, but I'm not exactly going for coding points. Dangeraffe is for me, as much of a coding learning tool as it is a game, so the fact that the code is not pristine for the rendering is just fine by me :).
Want more? Check the blog archives
Untitled Document