Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Jan 23, 2012

Dynamic Pictures

At CUSEC 2012 a programmer/designer by the name of Bret Victor gave one of the most interesting presentations at the conference (he received a standing ovation for it) on the importance of having visual connections between the code you write and what that code does.

Among other things, he showed a very interesting prototype where when you modify some Javascript code it will execute the code in real-time and show you exactly what will happen when you make those changes. On top of that, it provides a number of tools for "tweaking" constants: click on an integer and a slider will pop up above it that will modify that integer. As you move the slider the number will change, updating the visual display at the same time. Press the '.' after an object and it will give you an autocomplete list, but unlike every other autocomplete system it will actually show you what will happen if you call this method. Select drawRect and you will see a little black rectangle appear. Select arc and a little black circle will appear.

The demo worked amazingly well, however he admitted afterwards that they weren't based on a program that works but just some proof-of-concept demos that don't actually work outside of his presentation. That inspired me to actually attempt building some of this stuff to make it easier for people to build "dynamic pictures" - that is, pictures that change over time and respond to what the user might want to do. This is a non-trivial task because it not only involves processing the Javascript code live, but also determining what might be "good" values in each case. For example if you were to be adjusting numbers in context.lineTo() you might want to go between 0 and the width/height of the canvas, but if you were in context.arc() you would want to be adjusting angles. It would involve some kind of annotations to functions to determine what the valid ranges of values are for that argument.

You can check out the basic prototype here (warning: it is very basic at the moment) and see the code on Github here. When you enter code in the right-hand panel it will execute the code and any canvas drawing done will appear in the left-hand side.

Oct 1, 2011

Events in Javascript

One of the features of C# that I really enjoy is events. For the many folks out there who have never used C#, an event is an implementation of the observer pattern that allows objects to watch for certain notifications within other objects. For example in the Windows.Forms library the Button object has a Click event that you can bind an action to:

var button = new Button();
button.Click += (sender, ev) => {
MessageBox.Show("Hello, world!");
};

You can define events within your own classes and fire them easily:

public delegate void MyEventHandler();
public event MyEventHandler MyEvent;

// ... lots of code ...

// ... in some method that triggers the event:
if (MyEvent != null){
MyEvent();
}

Turns out this is fairly easily implemented in Javascript. This code here should do the trick:

function createEvent(eventName, obj){
var event = function() {
var ob;
for (var i = 0; i < obj[eventName].observers.length; i++){
ob = obj[eventName].observers[i];
ob.apply(ob, arguments);
}
};

event.observers = [];

event.add = function(observer) {
event.observers.push(observer);
};

event.remove = function(observer) {
var i = event.observers.indexOf(observer);
if (i >= 0){
event.observers.splice(i, 1);
}
};

obj[eventName] = event;
}

Now you can go like this:

var obj = {};

createEvent("test", obj);

obj.test.add(function(){
alert("Hello, world!");
});

obj.test();


You can try it by clicking here.

Sep 26, 2011

Crafty: Gaming Engine for Javascript

I started fiddling with this Javascript gaming library called Crafty, which allows you to build simple video games using DOM or canvas elements. Up front I like it better than gameQuery since it allows you to use canvas, but also because it seems to be much more of a framework rather than just a collection of jQuery extensions for gaming.

The most interesting thing about the library though is the use of components, which are essentially an implementation of Ruby's mixins in Javascript. A large number of built-in components support fancy things sprites, physics and input-related components that make an entity (such as a player) automatically respond to the arrow keys on the keyboard.

You can even define your own components. For example, you could define a component called FollowsMouse which means the sprite will follow the mouse cursor.

The main issue so far is that the documentation is sparse and the examples are not at all up-to-date. When you create an entity, you do it like this:

obj = Crafty.e("list", "of", "included", "components");

However it turns out that the capitalization style of components has changed:

// examples say to do this:
obj = Crafty.e("2D", "canvas");
// when in fact you do this:
obj = Crafty.e("2D", "Canvas");

These types of problems are very difficult to track down, since there is no failure notice when a required component doesn't exist. Instead, the system just ignores it and your entities don't render. I typically follow the adage, "the bug is not in the library, despite how much it seems like it" and yet, sometimes the bug is actually in the library (or in this case, the documentation).

There is probably a few other hiccups, maybe I'll make a few tweaks to the library and send it over in hopes they'll merge a patch in.

Jun 12, 2010

Colonial

A while back I announced that I was building up a new game using Javascript and gameQuery. My inspiration for this was not actually Farmville, but a board game called Agricola which I played with the Concordia Games Club. Unfortunately I ran in to a few problems:
  • I don't actually like farm video games. Farmville looked boring (and supposedly is). The board game was fun but that's more because you're playing it with real people. This one you just sit around and watch plants grow.
  • gameQuery is based on just straight up jQuery and divs, which ends up getting very slow very quickly. I decided it might be not worth it to keep working on the project.
So I started up another project, I have called it Colonial. This game is based off of the Caesar/Pharoah series of games, which I actually really liked playing. I figure now I'll try to make my own variant so that I can fix some of the little annoying things about those other games.

Also this project uses the HTML5 canvas, which ends up being quite interesting. It is much more performant than gameQuery, and a fair bit more flexible since it is literally a canvas where you just draw things. No need to have all the extra bloat of divs and what-not.

Anyway check it out if you like, all you can do right now is build little houses and give them water, but I'm working on it on a semi-regular basis (I have a job now so I don't work on it as much as I used to) so you'll see updates and bug fixes. At least I say that now ;) as I'm sure you might be aware, I tend to start projects and not finish them fairly often.

May 8, 2010

Testing Javascript Apps with Chrome

While testing a Javascript app under Chrome today, I learned something interesting. If the HTML/JS file you're viewing in Chrome is located on the local drive (ie. you're accessing it via file:///...) then you're not normally able to use AJAX to request other files on the local hard drive. I tried doing the following in jQuery:
$.getJSON("local/file/on/hard-drive", function (response){
  // blah blah blah
});
Every single time, the response variable would come out as null. I wasn't sure what happened, but after a quick Google search I learned that in order to make Chrome play nice with local files, you need to disable web security:
google-chrome filename.html --disable-web-security
After this it seems to work just fine! Now to fix the other bugs...

May 6, 2010

Faster Background Rendering in HTML5 Canvas

One thing that is common in video games and other graphical applications is generating some sort of background image. Generating this may not be a very fast task, so rendering it every frame in this case is not a feasible option.

A common technique to use instead is to render to an off-screen surface that works as a kind of cache. If you're programming using Javascript and the HTML5 canvas element, an off-screen surface is just another canvas that is not being displayed.

To render to an off-screen canvas:
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;

var context = canvas.getContext("2d");

// rendering code
How do you go about getting this onto your main canvas? It's really simple. As it turns out, the drawImage() function of the canvas context object can take not only image objects, but other canvas objects. So you would just go:
var context = mainCanvas.getContext("2d");

context.drawImage(offscreenSurface, ...);
You can get more details on the different ways the surface can be rendered by looking at the specs for the canvas. A great thing about some of the options are that you can have the background of the entire world (if the world is not gigantic) rendered to an off-screen surface, and only render a certain portion of it to your main canvas. This makes it nice and easy for you to implement some kind of scrolling mechanism.

This is very applicable for games, since many 2D games use some kind of tiled background, and need to render it 30+ times per second. Unfortunately if you have say 400 or so tiles visible at a time, using a basic drawImage() for each tile is too slow. You'd need to use some sort of off-screen surface to do this.

May 1, 2010

AJAX in 5 minutes using jQuery

One thing that really amazes me is how people can write an entire book on AJAX. It's a truly simple thing. It shouldn't even be a topic on its own, it should maybe be a subchapter in a book on Javascript or something. Anyway I'll show you how to use AJAX in 5 minutes using jQuery. You should usually use a library like jQuery (or others like Prototype or Mootools, use whichever you like the most) since using AJAX with regular old Javascript is a more tedious process with lots of repetition.

As a prerequisite to actually using AJAX in practice, you should know how to do some server-side programming using something like PHP, Ruby on Rails, etc. You should also be a bit familiar with Javascript.

All AJAX does is make a little request to the server without reloading the page. Here's some code:
$.get("profile.php", { username: "rob" },
function(response){
// put the HTML content of profile.php into a div with id = "profile_page"
$("#profile_page").html(response);
}
);
This simple example makes a request to profile.php with the parameters username = "rob", and drops the text into a div on the current page. This is effectively the same as accessing profile.php?username=rob directly, except without refreshing the page.

You can also do POST requests for mutable actions:
$.post("login.php",
{ username: "rob", password: "secret" },
function(response){
if (response == "good"){
alert("You have logged in successfully.");
}else{
alert("Invalid username/password");
}
}
);
The login action here would just output "good" if the login worked, or "bad" if the login didn't work.

There, you're now an AJAX master! Of course it would be better to learn by trying it out for yourself, but that's the basics of it all.

Mar 2, 2010

Javascript Profiling With Firebug

I realized something today when trying to figure out how to profile my Javascript game jarm. If you go into Firebug and go to the Console tab, there is a button there that says "Profile". For some reason I've never actually noticed it was there! It works just like a regular profiler, click "Profile" and let it do its thing. When you're done click "Profile" again to stop and it will give you a report.

Feb 14, 2010

Jarm

Well, it's time to announce yet another pet project of mine. This time it is a little Javascript game using gameQuery where you wander around planting stuff. I guess it's kinda like that Farmville game that is making its way around Facebook (I personally have no clue what that game is about, I avoid Facebook applications like the plague), however I got the idea more from a board game called Agricola, although this game and my game are not all that similar.

It's still far from finished, all you do right now is go around finding seeds, plant them, watch them grow, and then pick them. I'm hoping to add some sort of money system so that you can buy stuff to advance your garden-growing skills, and also some random events that could happen that will hinder your garden's growth. Hopefully someday I'll get some sort of points system so that maybe after X amount of time the game will end and your points are tallied up, and you have to somehow beat your old high score.

You can check out the source at GitHub if you're interested in playing it. It runs just fine in Firefox 3+ and Chrome (both tested on Linux only, not sure about anything else).

Feb 11, 2010

gameQuery

I've been working recently with a jQuery plugin called gameQuery, which is a basic 2D game development library for Javascript. It is designed to help you make simple browser games without the use of Flash or Java - which is nice, since Flash development doesn't work so well in Ubuntu (Adobe does provide an ActionScript compiler for Linux, but it doesn't really have any tools with it) and Javascript is a lot easier to program in than Java.

Right now it is still very basic, however it handles certain primitives for you quite well. Animations are implemented for you using tiled images (this is where you put all your frames into a row/column in a single image) which is very handy and much better than using animated .gifs. It will also do the preloading for those animations so that they don't need to be done during the gameplay. There are also mechanisms for grouping different animations into layers so that you can have different background/foreground groups, sprite groups, etc.
There's also some nice little addons for the game loop and input handling.

Other than that, there isn't really much to it. It has sound, although it is experimental and is not guaranteed to work (I haven't tested that part out yet). Supposedly it has collision detection, but it doesn't seem to work for me. Maybe I'll fix it and submit a patch.

I've been expanding on it a lot, I've made up two view classes that handle a scrolling background. You can either just straight up scroll by calling scroll(dx, dy), or you can have a "locked view" where it follows a particular sprite (it nicely handles the edge of the screen!).
I've also built-in a more efficient object management system using quad-trees, which are a space-partitioning data structure. It means that when you do location-dependent things like collision-detection you don't need to query every single object in the game, you just need to update the visible ones. This might also be good for animation rendering since you wouldn't need to update animations that are not visible.

Anyway give it a shot if you like, but remember that it is still pretty alpha! And don't bother with IE since it is really too slow for something like games.

Nov 8, 2009

flot

Recently I've been working with a Javascript library called flot, which does graphs purely in Javascript. It's a pretty handy tool for plotting graphs without resorting to Flash or Java - it's pure Javascript. Not only that, but it is really snappy and looks good! There's a cool example here that shows both the graphing capabilities and interactivity.

It's not as powerful as Flex by any stretch, but unless you need fancy morphing of graphs or things like that flot is just fine for you. And you have the benefit of not having to use Flex/Flash to do it!

Nov 2, 2009

Stats App Revisited

A while back I mentioned that I was working on an addon for OpenOffice called ooregress, which adds some more advanced statistics functionality to OpenOffice Calc.

Unfortunately when I wrote it, it was for OpenOffice 2.4. I think they changed the API for OpenOffice 3.0, so my code no longer works.

Rather than try to repair my code, I decided to port the thing to Javascript so that I could release it as an easily accessible website. The issue with the original version was that it was written in JRuby so you would need JRuby actually installed to run it, and it needed the development files for OpenOffice installed on the machine (not to mention OpenOffice).

This one is in a website, so all you need installed is a supported web browser. Since this is a personal project, IE is not a supported web browser :P I am currently supporting Firefox, Chrome and Safari - I can probably support Opera too, I'd just have to install it.

A temporary link is here, although I won't guarantee that this will always be active. I've got it hosted on my SheevaPlug, which I turn off sometimes. UPDATE: The site is now statsan.com, and I've called it StatSan for STATiStical ANalysis.

I'm planning on putting all the code as open source (GPL) so that anybody can host their own version of it should you want to, I'll put up the link once I get something set up - I've got a local git repo of it, it's just a matter of creating something on GitHub and pushing everything over.

Anyway, why am I writing this? Well, a few reasons. First, my stats classes at school have required various stats software, including Excel, EViews and Stata. I've also tried R. For the most part, these programs fall into one or more of the following categories: tedious, hard to use, expensive, not cross-platform. I want to make something that is more streamlined, easy to use, free, accessible and portable. You don't get much more accessible and portable than JavaScript, since the vast majority of people have something installed that supports it to some degree or another (however I guess this isn't 100% portable since I'm not supporting IE).
There is one downside: JavaScript is slow. I'm sure if you were running a regression on 20 variables with hundreds of thousands of observations, it would make your computer cry. This is an issue that I've been thinking about a bit and will hopefully come up with some solution for (if that native code plugin that Google is talking about ever comes out, that would be awesome!).

So if you have to do stats calculations, feel free to check out this app and let me know what you think. If you find any bugs or come up with any features you'd like, feel free to let me know.

Oct 31, 2009

Javascript Dataset Speedup

I've been working on a little project and I noticed it was loading very very slowly when working with large datasets (large being ~6000 numbers, so it is "large"). After doing some digging, I realized that it was because I was rendering my objects as Javascript objects:
<%= @workspace.as_js %>
Since the objects had some very large arrays in them, it took quite some time for the browser to parse that Javascript and load it in.

However, the weird part was then when I'd use Javascript code to process these arrays once they were loaded, it was nice and speedy.

The solution was simple: don't put the objects as Javascript. Parsing it is slow.
Initially I decided I would put the data in some raw form inside a <div> and then process the innerHTML. However that also turned out to affect the rendering time of the page (surprise surprise).

My final solution was to load the data from an AJAX action. This way the rendering time of the page is snappy, and there is not a lot of Javascript to parse.

The raw format is pretty simple. It is a set of name-value pairs separated by pipes (|), and each element is separated by colons - as I write this it might make more sense to use a URL formatting with & and =. The datasets themselves are arrays, so the name is preceded by a @ and is stored in the vars subfield of the object that I'm loading in. Here's the code:
<script type = "text/javascript">
var workspace = {vars: {}};
$(function(){
$.get('data_set_url', {},
function(response){
$.each(response.split("|"), function(i, obj){
if (obj.substring(0, 1) == "@"){
// dataset
obj = obj.substring(1).split(":");

workspace.vars[obj[0]] = $.map(obj[1].split(","), function(obj2, i2){
return parseFloat(obj2);
});
}else{
obj = obj.split(":");
workspace[obj[0]] = obj[1];
}
});
}
);
});
</script>
Even with the AJAX, this turns out to be much faster than putting the data as Javascript (or JSON), or putting the raw data in the HTML.

Jun 8, 2009

Blocking Reddit from Blogger

Over the year and a half or so that I've been writing this blog, a number of my posts have been put onto reddit by their search bot, gst - at least I think it is a search bot, I don't think anybody could have posted as many articles as they have unless they are sitting there reading blogs 24/7 - or maybe it is actually multiple people, who knows. Anyway, some posts were well liked, some were not, but in the end it doesn't really matter to me.

There is a good and a bad side to reddit. The people who like my stuff either just leave (possibly putting a vote up on reddit) or they subscribe and continue reading and occasionally share an intelligent comment. This is welcome. What does bug me is the people who just come in, leave a nasty comment or two like "yer gay" or something and fuck off. These people contribute absolutely nothing and when I'm having a bad day it is not the kind of email I want to come home to.

So anyway, I wrote up a little script to block out reddit traffic. To install this on your Blogger blog, just click the "Layout" tab, go to "Edit HTML" and drop this somewhere outside of a CSS tag:
<script>
if (document.referrer.match(/reddit\./)){
window.location = document.referrer;
}
</script>
This basically just boots them back to reddit. It won't affect them if they copy+paste the URL into their browser, but I figure if they're willing to go through that much effort to read your stuff they actually want to read your stuff and probably aren't going to troll.

Nov 12, 2008

Montreal on Rails

I'm doing a presentation at the upcoming Montreal on Rails gathering, on Nov. 18. My presentation is a simple introduction to jQuery and jRails, and why you might want to use them instead of Prototype and Scriptaculous. I haven't thought of a cool name for it yet, stay tuned for that.

If you're in the Montreal area and like/use/are-interested-in-using Rails, you should come check this out as there are plenty of interesting talks and cool people to meet.

Oct 14, 2008

Taconite

I'm working with a jQuery plugin called Taconite (not sure how to pronounce it, is it a soft C or hard C, long A or short A?) that is very handy for doing a whole bunch of jQuery commands with an AJAX request. Basically what you have to do is use XML, and the XML tags are the commands that you want to be executed.

There are a few things that I really like about it. First off, it makes it easy to have multiple updated divs. See with a regular updater object (like in Prototype) you can specify a URL and an HTML element ID, and it will dump the result of an AJAX request into that HTML element. Fairly handy. Taconite takes it two levels higher in that you can dump parts of the result in say three HTML elements, or seven thousand. You do this by passing a jQuery selector as a target, so if you go ".pickles", it replaces all HTML elements that have a class "pickles". Nice.

There's more than just replacing that you can do. Suppose you want to hide an element:
<hide select = "#thingy-id" />
All sorts of other commands can be used. Makes it nice and easy to do fancy stuff. You can also use <eval> tags to execute random Javascript.

The icing on the cake is that it is all automatic. You just have to include the Taconite js file, and all your AJAX requests will be Taconite-enabled. However, this doesn't mean every one will be processed by Taconite, only if it is XML-valid (perfect enforcer of standard XHTML) and it contains the <taconite> tag. Other than that, nothing happens - which is slightly annoying at times if you haven't managed to get your XHTML right, but that's what a validator is for.

So using this led me to some issues with Rails. How do we serve up XML? It's fairly easy, you just have to specify it. Go like this:
respond_to |wants|
wants.xml
end
And Rails will look for action.xml.erb. Easy enough. The next problem is a little trickier, although the solution is fairly simple and intuitive. Since some of the "XML" that is put into this file is actually XHTML (it better be XHTML, or you're gonna be having headaches - remember to put the / in <img />) you're going to have to be coding part of your view in the Taconite XML file. It works just fine with the eRuby stuff, just code like you always have. The problem will come once you start trying to render partials in your XML file. Suppose you go
render :partial => "mypartial"
Since you're currently rendering XML, Rails will look for _mypartial.xml.erb, which may or may not exist. For me, the partials that I wanted to render in the XML were also being rendered in HTML files elsewhere in the app. Now the first option is to just copy the file from _mypartial.html.erb, but then we have code duplication which is so not cool dude. Maybe we could use a symlink, but that seems rather hackish and won't work if someone on your team is using Windows - speaking of which, I should write another article on Linux at work, seeing as how I haven't used Windows for work in over two months. The solution is very easy. Instead of the regular render statement, you go like this:
render :partial => "_mypartial.html.erb"
And it will work. Now you can have your cake and eat it too.

I just realized something, I haven't posted an article about how jQuery is so much more awesome than the other Javascript libraries I've used (Prototype/Scriptaculous or Mootools). More on this another day.