Jump to content
  • Advertisement
Sign in to follow this  
  • entries
    68
  • comments
    177
  • views
    82391

About this blog

Save your forks, there's pie!

Entries in this blog

 

Icon pics

[disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed][disturbed]
[disturbed][disturbed][disturbed][disturbed]

capn_midnight

capn_midnight

 

3H-GDC base code

The issue of base-code in the 3H-GDC. Here's why I think it should stay:


cheaters cheat, and I don't know how to stop them. So, allowing the base code elliminates their advantage.
beginners don't know how to code basic graphics, but they can probably figure out the logic. Complete noobs (dare I say, "nooblets"), can't figure out either, so they won't finish anything at all. With base code, perhaps it will encourage beginners (distinctly different than noobs) to stretch out and participate
I want the contest to be more about design and concepts than to be about coding prowress. I want some coding to occur, but one needn't be the next topcoder grand champion in order to win.


thoughts?

capn_midnight

capn_midnight

 

is that better?

The Greatest Scientific Genius in the Universe Washu doesn't like it that I don't ever mention him in my journals. Well guess what, NOW I HAVE! Mr. Hyperbole! Now you can't say I *never* mention you!

capn_midnight

capn_midnight

 

I used to be a member here

This was me back then, in the year 2002:



And this is me now, 12 years later:





So what happened in between?

Well, after getting my degree in Computer Science, I ended up bouncing around between jobs. I've had--depending on how you count--6 to 8 jobs in the last twelve years. Most of them sucked. I got depressed from this, thinking it was my fault, that my work problems were because I didn't have the discipline to get out of bed in the morning. Turns out that there was a global conspiracy to give the middle class the shaft and I couldn't get out of bed in the morning because my bosses were universally assholes.

I flitted around the Mid-Atlantic region for a while. Living at home with my parents, renting a place with coworkers, living at home with my parents again, forcing myself out by moving to a completely different city, losing everything I owned in a flood, breaking up with almost all of my friends from childhood, getting fired for the first time from a job (for not looking like I was busy enough, despite the fact that my work provided most of the revenue to the company), living on friends couches and basements and spare rooms for a while, tusling with the decision of whether or not to become a fulltime alcaholic, experimenting with online dating--an experience that got too close to receiving violence on too many occasions for my liking--and just generally kissing the nose of complete destruction.

So I resolved I would always do things my own way and not have a boss ever again. I took about a 4 month sabbatical (and by that, I mean that is all the longer my unemployment benefits lasted, thus forcing me to find gainful employment) where I taught myself how to motivate myself for work. I sold t-shirts for a while. I made props for museums. I got some consulting gigs. I now have one major client who pays all my bills. I'm completely out of debt--no cars, no student loans, no credit cards.

And I got married to a woman who fills me with so much love and provides me with such an amazing base of rationality and sanity that it almost seems like the 10 years prior to her never even happened.

I now live with her just outside of our nation's capitol. I could be healthier, but overall, my life is really great now. I'm writing a lot lately, and I do a lot of photography and artwork when I'm not programming and actually finishing projects on a regular basis. I work from home, frequently not putting pants on all day. Most people in Northern Virginia either works for the government or works for a company that works for the government, people who I get to make extremely jealous with my beard, long hair, and carefree spirit. And that feels like winning.

So am I back? Sure, I guess you can call it something like that. Why am I here? I can't predict the future and know that I will post here regularly again. I only post this now because I see there are still some people here who would presumably remember my name and might have wondered what happened to me. I don't want to come in acting like "I'm an old, wisened master, bow before my wisening". I guess I'm here to learn again.

Here, this place, where I first learned.

capn_midnight

capn_midnight

 

Week of Awesome 2 - The Toys are Alive - #1

So Week of Awesome 2 starts on the day I have a half-day of job interviews and a demo of a product I'm working on. From 10:30am to about midnight tonight, I'm either driving somewhere or trying to present myself as awesome and totally not a slob at all. But tomorrow, I should be free for the rest of the week.

The theme is "The Toys are Alive". A title comes to mind, "Adult Toy Story". Nah, that's too obvious.

The key to a good game competition entry is to have a simple concept, executed well, completed early, to which "polish" is added with the remaining time. Yes, polish is a positive addition of things, like sprinkles on a cake. Also, to not neglect sound. Even the most basic sound instantly increases the quality of a submission 10-fold. One should stick to things one knows well. Venturing into new territory is a good way to get "stuck in the weeds" and fail to complete a submission.

With that in mind, I should probably be making a business intelligence suite, perhaps a series of reports demonstrating the effectiveness of a hospital full of toys. "Toy Hospital Administrator Simulator". I'm sure to win[1]!

Since I still don't have a real concept in mind after half an hour of typing, I'm going to continue to fill space with useless junk about strategy.

Ideas:
HTML5/JS game. I'm going to reuse my growing project template for doing HTML5 web apps. It's all just boilerplate stuff for loading bars, rounded corners on buttons, that sort of junk. Other people might use something like Angular or Bootstrap, but I am too old for that shit.
2D graphics. I'm still learning Three.js in my WebGL Virtual Reality[2] project, so I'm going to stick to what I know and do Canvas 2D instead of WebGL 3D.
3D audio. It's just so easy to do in modern browsers, why the hell not?
Mix of procedural and static content: Maybe a static level-select map and procedural levels.

Issues:
Figure out a proper concept to meet the theme
I don't currently have a good system for easily specifying and running keyframed 2D animations. Will have to figure something out here. Might be where I spend most of my time on this project.
I have simple boilerplate code for doing multiplayer stuff, but I feel like only a really good concept should have it. To add it as a gimmick would be detrimental.


Okay, that is all for now. I'll update this post here if I think of any concepts.



[1] Only if there is a "biggest Poindexter" award.

[2] Check it out. Star it. Follow it. Fork it and make contributions. Ask nicely and get direct commit access!

capn_midnight

capn_midnight

 

incompetence

At work, I'm tasked with fixing some bugs in a pre-existing application. We didn't write the app, but our client really likes us, so they gave us the work. Also, the company that originally did the work went bankrupt, so there is that issue. Somehow, they stay in contact with the lead developer, even though he's now on his second new job since the bankruptcy.

This web app is a simple ledger accounting thing for all of the various local groups in the state to use to track taxing for our client. It's basically an online version of quickbooks for these groups. They can enter in a few different types of data. All told, it's actually rather small, the database is only about 20MB total.

First, it's written in Java. This isn't horrible, Java on the server is nowhere near as bad as Java on the desktop (at least the toolchain is mature). Whoever originally wrote this application must have been tripping on LSD. It's a bunch of JSP files that all include each other in one way or another. It's a lot like some hackish PHP (is there any other kind?) that I've seen.

Second, it's written for Java 1.3. We run it succesfully on Java 1.4, but I first have to rewrite a sizable portion of the data access code.

So far, none of this is really that bad. Well, what I mean is, it seemed really bad when I first started on the project, but recent events really take the cake.

About four weeks ago, we got to a point where we had to move to the client site to continue working, so that we had access to their infrastructure and development databases. When we get there, the one machine they have for the three of us to work on (luckily we rotate days) is literally falling apart. I hit the power button and the face plate fell off. The red and blue phosphours in the monitor are starting to die, so everything has a greenish tint. Oh, there's also some banding on the display as well. The space bar on the keyboard only works half of the time. I just reallized today that there is not a padded cushion on the side of the mouse, that's a thick layer of grime.

It's running Windows 2000 that probably hasn't been reimaged in 6 years. Internet Explorer can't open new windows, meaning we can't use Exchange Webmail to access or work email. The Windows Find utility won't open, it just sits there looking at you like you're some kind of retard. The security policies won't let me open the run prompt, but I can navigate to CMD and run that. We can't get certain plugins to install for Eclipse, because for some unknown reason the installer thinks we're running an incompatible version of Eclipse (yes,I've verified we have the right version, as well as verified on another machine that the plugins install properly).

My first task is to get the app running on this workstation. Tomcat is already installed, my boss did that the day before. He spent a few hours n vain trying to get it to run, though. I get there and find out that he doesn't have the required environment variables set, but only after spending a few hours crawling over the configuration files that I don't rightly understand (we have other people in the company to handle deployment, I just write the damn code).

My second task is to get the application running off of the IBM DB2 development database. I contact the DBA and ask him for the connection details. He is a bit reluctant at first, "why do you need to know that info?" but I explain to him that I'm working on bug fixes for the application. Okay, so he relents and gives me the info. I spend the next hour crawling the internet trying to figure out how to properly create a JDBC connection to a DB2 database (we are primarly an Oracle house, we've never used DB2 for anything, and I've certainly never touched it before). I finally find a very, very good walk through and start fiddling around. First things first, I use the command line tools to connect to the DB and look at the data. Great, everything's good. I write up the JDBC connection string (I'm starting to get the hang of this), slap it into my code to replace the in-memory database I had been using as a fill in, and restart the application server. Every time the app tries to connect to the DB, the damn thing stalls.

Crawling google, crawling google. I start to think that maybe my connection string is wrong, so I fiddle around with it. Unfortunately, I determine that I had it *right*, because any time it was explicitly *wrong," the app would throw an Exception (as one would expect, actually). It's only when I have the correct connection details that the app hangs on me.

I went out on the web looking for bug info on the jdbc drivers. So, I start by looking up version numbers. Excellent, the database is running v8.2.2 and my workstation has the v7.2.3 client installed. Google revealse that the 7.2.3 *thin client* driver has a bug that causes the application to hang when one attempts to connect to a higher version database. The *thick client* driver does not have this bug. The thick client driver is not well suited to the task (the second user to visit the site will not be able to use it because the next application context will not be able to load the drivers, as the thick client locks them once they are loaded), but for development I can work with it until we upgrade the client on the workstation.

After a while of working in this way, suddenly it stops working, I'm getting Access Denied errors. I can't even use the command line tools anymore, either. It's getting pretty late though, so I went home.

The next day, I get an angry call from the DBA, chewing me out for using the production database for development. Apparently it through a security flag and locked itself down, which prompted a few hundred managers across the state to call this them and complain when they couldn't login to do their daily work. I appologize profusely, and ask for the connection details to the development database. He replies "I still have to set it up." The project manager behind me turns to me and says "that was supposed to have been done weeks ago" and I agree, it was one of the conditions that had to be met before we would come work on site. So, I call my boss (well, I try to, I never reached him, but that's a different story), and we stop work. For the next week. It took the DBA an entire week to get the development database up and running. Luckily it was the week I was on vacation, so I didn't miss much.

At this point, I need to back up and take you down another branch in the story. Before the database locked itself down, I was able to get a good amount of work done. I came to a defect in the list that I couldn't quite figure out how to reproduce. So, after half an hour of phone calls, I eventually located someone that knew how to reproduce the bug. He showed me on the live application. While he is doing this, I'm noticing certain things, like the lack of certain bugs that I had made mental notes to fix. It's a little confusing, but I chalk it up to the fact that we hadn't been running on the DB2 database yet, maybe that was the source of the bugs. If only it were that simple.

While on vacation, I get a call from my boss. He has noticed the same thing, did a little checking on some file dates here and there, and reallized that *we didn't get the latest cut of the code*. Another work stop while the lackeys hunt down the latest code. They have no source control, and the last work done on the app was almost 2 years ago. After another week, they locate a number of different folders labeled as "backups". My boss looked through them briefly (he was heading out for a business trip, another client in North Dakota), and figured that one particular one looked like it might be the full code.

I get there today and start looking at it. There are 5 folders, and not a single one of them have the entire application. The full app is there, spread out in bits and pieces, but not all together. Additionally, some of the backup folders have newer files than others, all the changes overlap between the 5 folders. There are so many badly named backup folders and renamed files (main.jsp, main0.jsp, main.jsp.old, copy of main.jsp, you get the idea) that some files have as many as 9 distinct versions running around. All of the files have at least 3 versions, judging from file size and time stamp. So, I start piecing together a full application from the files with the latest time stamps (shit, windows find utility won't open). I get them all together, setup the application, and then reallize that these various backup folders might represent numerous different "forks" of the app from the LAST time they lost the latest source code.

I'm now in the process of trying to figure out what is the "real code." I started by comparing file sizes in bytes and time stamps. If both values are equivalent, then it's a pretty good bet that they are two copies of the same file. I now have anywhere from 3 to 9 copies of each file. I'm going through and running a file comparison utility (actually, I didn't know CMD had one until now, called FC.EXE) on them to see if files with different time stamps aren't duplicates. 9 versions of one file needs at most 8+7+6+5+4+3+2+1 = 36 comparisons (#1 to #2, #1 to #3, #1 to #4, ..., #7 to #9, #8 to #9). Multiply out by a few hundred files. It took me 6 hours to get through half of them. I still have the other half to go. I need to do it tonight so that the code is ready for the one other developer that is going to work on Saturday to try to make up some lost time.

capn_midnight

capn_midnight

 

The Future of the 3H-GDC

Alright, so we just finished another wonderful contest, with the highest contestant participation yet. A total of 10 contestants and 8 submissions that came in on time. The submissions were actually all rather impressive for only 3 hours of work.

But where to take the 3H-GDC from here? It's starting to get really popular, and the prizes that were donated for this fourth one were really freaking expensive. I'm beginning to think it's time to get serious about the 3H-GDC.

How serious? Well, holding it regularly, having real corporate sponsors with really, really expensive prizes, having a real website with a real submission process. Basically, fixing everything that I do rather off the cuff right now.

Comments, suggestions? Please don't discuss the base-code issue here, I'm starting a new journal thread for it, as I do think it is a very important issue to get "right".

capn_midnight

capn_midnight

 

HTML5 audio for games made easy

Audio in the browser is deceptively tetchy. It's easy to get a basic sound to play with the tag.[code=html:1] If you can read this, your browser is not fully HTML5 compatible.
But there are several problems with this:
First of all, good luck navigating this compatibility chart. Until Mozilla finally caved and decided to support MP3, there was no single file format supporting Chrome, Firefox, Safari, and IE. Opera is still a painful holdout on file formats, and the situation on mobile is disgusting.
You can't programmatically trigger the audio playing on mobile devices without direct user action in your game loop. You basically have to put up a "start game" button that tricks the user into playing a silent audio file, then you have free reign to trigger that particular audio element.
You get almost no control over how the file plays. There is a volume setting, but it hasn't always been reliable on all platforms. There's no mixing. There are no effects.
It's super difficult to rewind and replay an audio file. Honestly, I still don't really know how to do it correctly, and I'm a goddamn salty pirate.

In short, the tag is for one thing and one thing only: for NPR to post their podcasts directly on their site.

Okay, let's get out of this malarky. What else do we have? Well, there's the Web Audio API:
Granted, formats still aren't great. Strangely, the compatibilities don't exactly match the tag. But MP3 is universally there, as is AAC. And technically, you could write a decoder if you wanted. I wouldn't suggest it, but it is possible.
You can play audio whenever you want, as many times as you want, on desktop and mobile, without buggering around with stupid hacks.
It's a fairly-well featured signal processing system. That's great if you know what you're doing, murder if you don't.

It's a little difficult to program. And the MDN tutorial gets far too into crazy effects for me to bother if all I want to do is make a few blips, bloops, and gunshot sounds.

That's why I wrote this: Audio3DOutput.js. Here's what you do:[code=js:1]// to start, create the audio contextvar audio = new Audio3DOutput();// then, check if your system supports itif(audio.isAvailable){ // if you want to play a specific sound file every time a user clicks a mouse button: audio.loadBuffer("click.mp3", null, function(buffer){ window.addEventListener("mousedown", function(evt){ audio.playBufferImmediate(buffer, 0.25); // 25% volume gain }); }); // if you want progress notifications while the audio is loading and processing: audio.loadFixedSound("song.mp3", /* looping */ true, function(op, file, numBytes){ console.log(op, file, numBytes); }, function(snd){ snd.source.start(); }); // if you want to position the sound in 3D space: var sourceX = 10, sourceY = -4, sourceZ = 3; audio.load3DSound("ambient-sound.mp3", true, sourceX, sourceY, sourceZ, null, function(snd){ snd.source.start(); setTimeout(moveListener, 5000); // 5 seconds }); function moveListener(){ audio.setPosition(x, y, z); audio.setVelocity(vx, vy, vz); audio.setOrientation( ox, oy, oz, upz, upy, upz); } // if you want to take the first file of a list that successfully loads: audio.loadFixedSoundCascadeSrcList(["song.aac", "song.ogg", "song.mp3"], null, function(snd){ snd.source.start(); }); // or if you want to synthesize the raw PCM data yourself: // in monaural var data = [], seconds = 0.25; for(var i = 0; i
There you go. If you find a need for more than these basic functions, please drop me a line and let's discuss adding it!

capn_midnight

capn_midnight

 

3H-GDC Prize organization

So far:
1 month GDNet+ from capn_midnight
3 months GDNet+ from Fruny
1 year GDNet+ or an Amazon item of equal or lesser value from Prozac
1 year GDNet+ or a programming-related book retailing less than $100 (wow) from kSquared

capn_midnight

capn_midnight

 

VR Lessons Learned So Far

[color=rgb(77,79,81)][font=Helvetica]
This is a loosely organized list of things I've noticed while using and developing virtual reality applications for the smartphone-in-headset form factor. It is specific to my experience and may not reflect anyone else's personal preference, such that VR is apparently quite dependent on preference. But I think that steadfast rules of design are necessary for the impending VR bubble, to convey an aesthetic and unified design such that users may expect certain, common idioms and adapt to VR software quickly. Thus, this is list a roadmap of my current aesthetic for VR. It is a living document, in the sense that future experiences may invalidate assumptions I have made and force me to recognize more universal truths. Proceed with caution.[/font][/color]
Presence is the ability to feel like you are in the scene, not just viewing a special screen. You'll hear a lot of people talk about it, and It is important, but ultimately I believe it to be a descriptor of an end result, a combination of elements done well. There is no one thing that makes "presence", just as there is no one thing that makes an application "intuitive", "user friendly", "elegant", or "beautiful". They either are or they are not, and it's up to the individual experiences of the users to determine it.
Presence is a double-edged sword. [font=inherit]I've found that, once I feel "present" in the application, I also feel alone, almost a "ghost town" feeling. Even if the app has a single-user purpose, it seems like it would be better in an "arcade" sort of setting. To be able to see other people may help with presence.[/font]
The hardware is not yet ready for the mass market. That's good, actually, because the software and design side of things are a lot worse off. Now is the time to get into VR development. I'll say nothing more about the hardware issues from a performance side. They are well known, and being worked on [font=inherit]fervently [/font]by people with far more resources than I.
Mixing 2D and 3D elements is a no-go. Others have talked about not placing fixed-screen-space 2D heads-up-display elements in the view for video game applications, but it extends much further than that. The problem is two-fold: we currently have to take off the display to do simple things involving any sort of user input, and there is no way to manage separate application windows. We're a long way off from getting this one right. For now, we'll have to settle for being consistent in a single app on its own. A good start would be to build a form API that uses three-space objects to represent its controls.
Give the user an avatar. This may be a personal preference, but when I look down, I want to see a body. It doesn't have to be my body, it just needs something there. Floating in the air gives me no sense of how tall I stand, which in turn gives me no sense of how far away everything is.
Match the avatar to the UI, and vice versa. If your application involves a character running around, then encourage the user to stand and design around gamepads. If you must have a user sit at a keyboard, then create a didactic explanation for the restriction of their movement: put them in a vehicle.
Gesture control may finally be useful. I'm still researching this issue, but the experiments I've done so far have indicated that the ability to move the view freely and see depth make gestures significantly easier to execute than they have been with 2D displays. I am anxious to finish soldering together a device for performing arm gestures and test this more thoroughly. This demo makes it clear that this is at least an extremely lucrative path of study.
Use all of the depth cues. Binocular vision is not the only one. Place familiar objects with well-known sizes in the scene. Use fog/haze and a hue shift towards blue at further distances. But most importantly, do not give the user long view distances. Restrict it with blind corners instead. Binocular vision is only good for a few feet before the other depth cues become more important, and we are not yet capable of making a convincing experience without the binocular cue.
Object believability has more to do with textures and shading than polygon count. Save on polygon count in favor of more detailed textures and smooth shading.
Frame rate is important. I remember being perfectly happy with 30FPS on games 10 years ago. That's not going to cut it anymore. You have to hit 60FPS, at least. Oculus Rift is targeting 75FPS. I'm sure that is a good goal. Make sure you're designing your content and algorithms to maintain this benchmark.
Use lots of non-repetitive textures. Flat colors give nothing for your eyes to "catch" on to make the stereo image. The design of these viewer devices is such that the eyes must actually fight their natural focus angle to see things in the display correctly. It will be easier for the user if you make it as hard as possible to not focus on object surfaces. Repetitive textures are only slightly better than flat colors, as they provide a chance to focus at the wrong angle, yet still achieve what is known as the "wallpaper effect". And do not place smaller objects in any sort of pattern with regular spacing.
Support as many different application interactions as possible. If the user has a keyboard hooked up, let them use the keyboard. If they have a gamepad, let them use the gamepad. If the user wants to use the app on their desktop with a regular 2D display, let them. Do not presume to know how the user will interact with the application. This early in development, not everyone will have all of the same hardware. Even into the future, it will be unlikely that an app will be successfully monetizable with a user base solely centered on those who have all of the requisite hardware to have a full VR experience. [font=inherit]Be maximally accessible.[/font]
[font=inherit] Make the application useful. This seems like it shouldn't be said, but ask yourself what would happen if you were to rip out the "VR" aspect of the application and have people use it with traditional IO elements. Treat the VR aspect of it as tertiary. Presence by its very definition means forgetting about the artifice of the experience. If the experience is defined by its VR nature, then it is actively destroying presence by reveling in artifice.[/font]
[font=inherit] Much research needs to be done on user input especially for large amounts of text. Typing on a keyboard is still the gold standard of text entry, but tying the user to the keyboard does not make for the best experience, and reaquiring a spatial reference to the keyboard after putting the headset on and moving away from the keyboard is nearly impossible. Too often, I find myself reaching completely behind in the wrong direction.[/font]
[font=inherit] 3D Audio is essential. We could mostly get away without audio in 2D application development, but in VR it is a significant component to sensing orientation and achieving presence. I believe it works by giving us a reference to fixed points in space that can always be sensed, even if they are not in view. Because you always hear the audio, you never lose the frame of reference.[/font]
[color=rgb(77,79,81)][font=Helvetica]
I may add to this later.[/font][/color]

capn_midnight

capn_midnight

 

Getting started with Node.JS part 1: Setup

I had been hearing about Node.JS for a while. "It's JavaScript on the server!" I mostly ignored it, as ASP.NET was forced on me at the time and I hadn't yet given employed life the finger and a flaming bag of poo on its doorstep[1]. What does "JavaScript on the server" even mean?

Well, it's a little more than just the bare meaning of a JS execution environment outside of a browser. Think of it like JS finally making something out of itself. All those years in college. Getting stuck in low paying design jobs. Now it commands respect! It can connect to databases!

Basically, start with V8--Google's JavaScript engine, not the salty-disgusting-juice that tricks you into eating vegetables when you were expecting a fruit smoothy instead. Just like the JavaScript that runs in their Chrome web browser. Then, throw away DOM--or rather--never add it because you didn't add WebKit into the sauce. Finally--and here comes the important part--throw on top a reliable package manager and a core set of libraries that make building a stand-alone Web server nothing more than a few lines of configuration code.

I should probably just shut up now and get to the point, because I'm the one late to the party and you, dear reader, probably know all this junk already.

What kept me away for so long was Django. And Ruby On Rails. And Leinenkugel, or Lemonysnickets, or whatever the hell those people in [s]ScalaClosure[/s]Clojure land are calling it. See, I have been trying for many years to get out of ASP.NET, and having heard the call of all of these programming-language-plus-web-environment-plus-package-manager combos[2], I had tried them out, to much dismay. These things were a pain in the ass! This was what everyone on HackerNews was raving about and telling me I was the idiot for sticking to ASP.NET? Half this junk wouldn't run on Windows without at least a day and a half of tracking down obscure patches and packages and talismans, of which you're on your own finding because the communities are hostile towards Windows users. Yes, I know, you don't like "Micro$oft". But not helping me and not spending the extra effort to make your software compatible with Windows, you're also not helping me get one step closer to using Linux full-time.

But Node.JS isn't like that.

First of all, you install one thing. You go to http://nodejs.org/download/ and you pick the version that is right for your system. Or, you open your terminal and type "apt-get install nodejs" or "emerge nodejs" or "yum install npm" or "brew install node" or whatever, you can probably figure it out, it's out there in your package manager of choice. And it's done. You have it. It's even installed on your PATH now.

Next, you don't "django-admin.py startproject mysite" or "rails new mysite" and then watch as it does a ton of stuff that nobody has explained yet and aren't anywhere close to explaining, because apparently you should be happy that it just dumped half a megabyte of text on your hard drive when all you want to do is give the thing a spin. If you want someone to make a project template for you later, you can do that, but up front, when you're just trying it out, there is no necessity.

And finally, when you install new libraries through the package manager, NPM, you also don't go hunting for obscure C libraries that maybe didn't get included in your particular Linux distro because the package maintainer is a masochist who compiled his own Gentoo from scratch and you're on a base config of Linux Mint, or because you're on Windows still and would really rather not have to install that bastard child Cygwin.

So let's try it out now. Open your command line. Type "node". Hit enter. I'll wait. If you installed it like I said, it should work. They realized people don't like to take more than one step to use new software, so they setup reasonable defaults for everything. You'll be presented with a REPL[3]. Then, just type sometimg. Sometimes I type "hello", a methaphorical call out into the dark, searching for a response. It comes in the form of evaluation.



Try a few more things, quit out of it by hitting CTRL+C twice[4].


If you've ever done anything with the HTML, this is probably no big surprise. And that's the brilliance of Node.JS! It's a programming language you already know.

Okay, one more example, to show off how easy it is to get a Web server going, because REPLs are great and all but they don't a project make. Particularly clever students with well refined bullshitting skills will find everything they need in the next screenshot to make a successful consultancy. If you've never done web development before, you have no clue how much I didn't have to do here. This is not a specially contrived example with 10MB of configuration files in a Turing-complete config format. I did this from a bare install as I described in the article and you see everything in this image necessary to replicate it.



That's it for now. Stay tuned for my next article, which will cover WebSockets with AJAX fall-back through Socket.IO. What does that even mean!? LOLGIBBERISH! It means lower overhead for requests back to the server, which means faster updates from the server, which means we can start writing networked games in JavaScript and deploy them through the browser in a way that Java never seemed to be able to pull off.

[1] for the record, I still haven't, but I have stopped returning its calls.
[2] the good, ol' PLPWEPPMC, as my pappy used to call it
[3] Read-Eval-Print-Loop, a new brand of cereal to compete with Fruit-Loops
[4] or CMD+C on OS X, but I suspect you probably know to make the mental translation on your own by now

capn_midnight

capn_midnight

 

Optical Illusions in Computer Graphics #3

I've moved hosting of my optical illusion project to here on GameDev. Link for great justice.

I planned the next entry to include my screenshots, so I will copy the screenshots page to here.


Die Schirmschusse fur alle
Demo 0
Basically just getting the isometric map rendering without any effects.


Demo 1
This is the isometric map of demo 0 with the primrose illusion rendered underneath, utilizing a different set of colors.


Demo 2
The illusion effect in demo 1 was not very strong, specifically because of the isometric projection. I attempted to return the pattern of the illusion itself to a normal orthographics projection, and then clip it down to fit the map, but the results were not impressive.




Demo 3
This is the demo that can be viewed in the isometric map demo under the demos page. Only a small portion of the illusion pattern is revealed at any one point in time, and that portion sweeps across the screen, giving the effect of a moving wave. This, however, is very subtle, leading me to rethink the perspective of the project.



Demo 4
This is the demo that can be viewed in the orthographic map demo under the demos page. It utilizes both the primrose field illusion for the water and the bulge illusion for the hills. This is the strongest demo so far. I will most likely make a game similar to Fire Emblem on the GameBoy Advance (yes, I will even develope it on the GBA).

capn_midnight

capn_midnight

 

Metal

So, I'm driving in my Fiji Blue 2008 Honda Civic Si to work at the Conservatory for Bad-Assery one morning along this really sick-ass section of road that runs along a cliff face plummeting down into this deep ravine full of rocks and trees and shit like out of a movie like Lord of the Rings or something, when this giant, fire-breathing dragon comes screaming in from deep, dark corner of the chasm, like it's some kind of chasm of despair, and starts hovering right in front of me on the road. I'm like, "ohshitohshitohfuckohshit" and really starting to freak out when I remember, "hey, I've got a fucking rocket launcher, I mean seriously, who doesn't amiright?" So, I hoist this rocket launcher up on my shoulder as I'm standing up out of my sunroof and blast a billboard on the side of the road, the billboard falls down, I punch the gas on my car and totally use the billboard to ramp up and over this gigantic dragon, like whoa, and the dragon is looking up at me as I'm flipping through the air and I can see the look in its eye, and the dragon is totally saying, "hoooolyyyyy shiiiiiit," and I'm all, "oooooh shiiiiit," and as I'm just over the dragon I say "yooooou shall not paaass" and I shoot my biggest heat seeking rocket right at the dragon's tonsils. The rocket flies right down his throat and EXPLODES in his stomache, raining down this mass of blood and guts and bubbles and jet fuel and shit everywhere.


It was fucking metal.

capn_midnight

capn_midnight

 

i herd yuo like mudkips?

Okay, my asteroidish game is coming along. I've got about half of the bugs ironed out of the physics system. It's still returning bad results, but they aren't quite as bad as they were before. Apparently I was using a quadratic formula of " (-b +- sqrt(4*a*c) ) / 2 * c ". Obviously, this is not the way to true enlightenment. Buddha would be pissed.

I added a simple sound system, using pure Java Sound API mixing. Eventually I'll have options for selecting the desired audio mixer for systems with multiple mixers. For now I'm just taking whatever is the first mixer, which is not guaranteed to work on anything other than my machine (it's not that bad, it should at least be able to load the default Java software mixer). The sound system still needs work, but it's not a critical feature right now, just having it is enough for now.

Increased max resolution to 1152x864. Got my unit testing on. Added a name label to the planet. Abstracted a little more physics out of the rendering code. blah blah blah. Now that I've introduced sound I need to reinvestigate how to load resources out of a jar file (I had an epic fail on that last night, totally set up my system the bomb). Still lots of work to do.

capn_midnight

capn_midnight

 

Grad School Applications, round 2

Well, it's been almost a year and a half since the last time I attempted to gain acceptance to a graduate school. So, here is a statement of academic objectives that I've been working on:



capn_midnight

capn_midnight

 

gdnet.lounge.con

You know what I'm talking about. That's right, a conference just for the GDNet Lounge.

I'm talking Booze, Bread, and BSD Unix for all (what, you'd think I'd kill such a great alliteration?).

New York City. New Years Eve. New YOU.

The conference will open in a grand ceremony and the cutting of the floor caek that is shaped like pi. We'll have workshops on quitting peeing in the shower. We'll have brainstorming events on Hockey MMORPGs. We might even have a live 3H-GDC (actually, that last one is serious).

DO IT!!

capn_midnight

capn_midnight

 

Optical Illusions in Computer Graphics #1

I'm working on a research project involving optical illusions in computer graphics. Many people here on Gamedev have already seen a lot of my screenshots. With this journal I will attempt to track my total research and development process.

I highly suggest that all computer science students complete a research project, either as a course or as an independent study credit. It will provide a good start for your portfolio and resume.

As an aside, I also suggest that CS students schedule as many Software Engineering courses as possible. Most everything else is pretty much stuff that you can learn on your own.

I have already put a lot of work into the project, but I will not present all of it right now.



The idea for the project began after viewing an odd illusion:


After viewing this illusion, and seeing the smoothly flowing ripples, I remarked to myself that the human brain was much better at manufacturing "special effects" than most computers.


capn_midnight

capn_midnight

 

Optical Illusions in Computer Graphics #10

This is the last update!

The paper is finished. All done. Waiting on a grade.

In summary, the hypothesis that optical illusions could be used in a utilitarian fashion was correct. Using optical illusions I was able to convey information that users were able to effectively use to complete a task. Read the paper for more.

I had a lot of fun working on the project. Going out to Philladelphia for the research symposium was great. I will be submitting my paper to a research conference in the next week or so, my professor thinks it has a good chance of being accepted, so that's cool.

The project has already impressed quite a few important people. I recently talked with the President of a local software development company, who saw my project poster, and he was very interested in some of the things that I proposed from it.

I want to thank the staff of Gamedev for stickifying my Survey Thread (Oluseyi is the one who did it, I believe). Because of that, I collected 550 data points, which really made my data look nice and complete.

Things I learned from the project:

stretching out into other fields of expertise is recommended
test driven development ALWAYS saves time. You may feel like you are writing twice the code, but the truth is that you are spending half the time (total) writing it. ALWAYS test, THEN code. NEVER code before you test. Even if you think it's small. Just don't do it.
regression testing is kind of dirty, but it can get the job done in a pinch. For 2D applications, it may not be necessary in most cases, you should try to find a way around it.
never write java applets. applications are okay (but only just so), applets are garbage. I wonder how good flash is for web apps?
pace yourself and work is a breeze! keeping this journal over the course of the project really made the poster and the final paper a simple task.

So, if anyone out there has a job for a graduating computer science student that involves 2D graphics and making people dizzy, send me an email!

capn_midnight

capn_midnight

 

so busy

well, I've been quite busy lately.

Two weeks ago, I started a new job working on a GIS web portal. Right now, I'm running through QA testing, oh joy, oh rapture, take me now. I HAVE NEVER BEEN SO FREAKING BORED IN MY LIFE!!!

On occasion, I get to write some code. It's funny, I was hired because I knew how to program C# using the features of .Net, and I had some experience with the eXtreme Programming methodology, which they are transitioning to (from what, I don't know, maybe CBTSOYP).

Transitioning to XP, my ass. They are flat out RESISTING it. Absolutely NO pair programming. Tasks are assigned, not volunteered. Strangely, we ARE doing the morning standup meetings. Almost no unit testing, and certainly no test driven development. I wrote a single class the other day and quadrupled the number of unit tests in the entire project, and it wasn't a large class (it handled adding and retrieving URLs from a DB). And yet, they find themselves with the problems that XP is meant to prevent (breaking large portions of functionallity when refactoring, ensuring that components integrate properly, etc), and wonder why.

(I need to cut this short, at work *right now*)

Some of you have probably already read "wasting time, but getting paid for it, so it's okay". So you'll know that little bit of code that I got to write is basically 50% wasted. I can reuse the DB code, since it's essentially the same data, I can reuse the data retrieval module (thankfully, that's the class that quadrupled the number of tests). But I have to completely rewrite the UI and the business logic, and add on top of that an RSS aggregator. Oh, did I mention that our "client" stipulates that we cannot use any OSS of any kind? (not that *I* mind, but I think the VP won't like the fact that I'm going to have to spend a few days reimplementing something that could be just dropped in).

I went to Miami, Florida to visit a friend and just generally party for 5 days. It was great, I took pictures.

I've gotten no work on projects done since starting this new job. It's about an hour drive to and from work, so by the time I get home I just want to eat, relax, and get to bed by 10pm so that I can get up at 5am and start over again. I hope it doesn't stay like this.

My flipping computer died. I think it's the hard drive. Luckily I keep all my docs on the secondary drive. And I don't have any money... I still need to buy a car and pay off my student loans. Someone kill me now.

capn_midnight

capn_midnight

 

AAGHH!

I am so pissed off right now, and this is why:



MOTHER OF PEARL! LINE THE HELL UP!!!

This is a mapping application that we are customizing for a client. They have a format of data called RPF that ESRI MapObjects is particularly bad at cacheing. However, we found an open source project called OpenMap that handles RPF data very well. So it should be a whiz-bang process to create a custom MobObjects layer (the MapObjects API supports this) that uses the OpenMap code to spit out images. Making a small application that did nothing but spit out images given a path to RPF data and the extents of the image was nothing, simple task. Writing custom MapObjects layers is also not a big deal, we do it all the time.l

EXCEPT OPENMAP DOESN'T DEFINE MAP EXTENTS IN ANY SANE MANNER!!!!

Typically, a map extent is defined as the min/max latitude and longitude. OpenMap on the other hand expects a center latitude and longitude, along with a map scale. Fine, whatever, except it completely ignores any concept of aspect ratio! But let's ignore that, let's just calculate the damn scale... wait, you CAN'T because a monitor's pixel-per-inch ratio is not fixed!

So, after much trial and error, I've come up with something that is a reasonable scale factor... I think. Panning the map left-right is good, panning it up-down is okay, but if you pan it diagonally you get this freaking fracturing of the image.

GHAKGHAKALHGAH!!!!!!!

capn_midnight

capn_midnight

 

Getting started with Node.JS part 2: Socket.IO

A few days ago, I talked about how easy it is to get Node.JS installed, regardless of your platform, and get code running that shows something in your browser. Whether you're on Windows or OS X or Linux, there is only one package to install that gives you access to an easy-to-configure web server running in a language you probably already know: JavaScript.

Today, we're going to jump feet first into Socket.IO: a library for Node.JS that supports WebSockets[1] between your server-side code and your client-side code, all the way back to IE5.5. Yeah[2].

To start, we'll need a basic web server that can load static files and send them to the user. I'm jumping ahead here and assuming that I'm going to eventually want to serve up some HTML, CSS, client-side JavaScript, PNG, and MP3 files, considering the goal is to make a game here. That's a lot of different types of content, so I'm going to cheat and take a library someone else wrote for handling it: Mime. This will also give me a chance to show you what happens when you install a dependency through NPM.

I'm going to make a new directory for a project, then install the Mime library through NPM. I'm making a new directory because NPM is going to download some files for me and I want it to stick them somewhere that won't junk up my harddrive. Installing the library is just simple "npm install mime" statement.


And there it goes. NPM knows where to download the code for Mime because someone registered Mime on the NPM website. The library gets copied to a directory called node_modules.

Now, let's throw down some code into a text file:


I hope this is pretty clear on what it does. There is not a lot to cover. Probably the most surprising part of it is the http.createServer call. It's registering a callback function that will be called whenever an HTTP request is made to the server. In general, Node.JS does a lot of stuff through callbacks, to make up for its lack of multi-threading primitives of any type. It's basic HTTP from there. I save this to a file called "server.js" and run it with a simple "node server" (Node adds the ".js" file extension for me), I open my browser and head over the http://localhost:81/ and this is what I get:File not found. / reason: {"errno":28,"code":"EISDIR"}
Aaaah, yes, I didn't actually tell it what file I want. That's pretty easy to fix though. Let's kill the server with CTRL+C (webServer.listen will keep Node running until we explicitly kill it) and make the code default to loading an "index.html" file if the URL specified indicates it was a directory name.


I've also created a file named "index.html" that just contains the text "Hello, world!". Now, when I restart the server and load the page, I see this:


"But capn_midnight", you say, "Why don't we just use Express and weeooeeooeeeoooooo". Because we're making a Single-Page Application (SPA) that will have mostly static files for making an extremely basic front end, with most of the logic residing on the server side. If we need more out of our static content delivery than this, then we can figure that out later. Also, this article series isn't really about Node.JS or Socket.IO or Express or any thing in particular, it's about getting to make a multiplayer game very quickly.

Alright, let's move on to the Socket.IO stuff. Do yourself an "npm install socket.io" in your project directory. You'll notice that there is a lot more spewed out than when we did it for Mime. This is because Socket.IO has its own dependencies and NPM went ahead and got them for us. If you've done any reading about NPM installs, you might ask if we would want to install Socket.IO with the -g switch, for "global". Typically, global installs are for installing Node software that we are going to use, not libraries that our project is going to use. If we wanted to use the TypeScript translator, that would be done with "npm install -g typescript" (and you would have to have admin rights, so you probably need to sudo that if you're on a Unix-like OS). Then, we would have the TypeScript compiler, tsc, installed into our PATH, and we could use it directly from the command line. But that's not necessary here.

For code, I'm going to first push most of the Web server stuff into it's own file, just to try to keep everything tidy. The only thing left in my original source file is the call to create the server and start listening. It's important at this point to point out a point of interest in Node's import system. When you call the require() function, the parameter to it is actually specifying a search string, not exactly a library. It iteratively searches from the current directory all the way up to the root directory of your system, looking for a "node_modules" folder that has a file that matches the name you're looking for. And if you didn't add a file extension to the file, require() automatically assumes ".js" for you.

But, if you don't want to put your files into a folder named "node_modules" (or pollute your NPM installation directory), then you need to tell require to look in a specific directory for the file. It's a lot simpler than it sounds, just use the "." single-dot name for the "current directory" and apply your filename to that.

So in this particular case, I've moved my code to a file named "httpRequestHandler.js". I've put it in the same directory as my "server.js" file. So to import it, I must "require('./httpRequestHandler.js')" or "require('./httpRequestHandler')" for a little-bit shorter version.

Anyway, now that we've had that little bit of a side-quest, back to the task at hand. I add code to my server.js file for creating a WebSockets listener. It's very simple. If you've done any sort of network programming before, I'm sure you'll be as flabbergasted as I was.


Look at that! It's all of four additional lines of code to listen, respond to new connections, and do some basic communication. In other words, it's one more freaking line of code than things we're freaking doing.

So what is going on here? Well, lines 5 and 6 get our web server going again, to be able to serve up the index.html file that will represent the client side of our client-server modeled program. And lines 8 through 14 setup the server side of our client-server modeled program.
Line 8: Socket.IO needs to know what socket it's going to listen on. You can give it a specific port number, or you can give it a reference to your webServer object and it will listen on the same port as the Web server is running on. That's pretty neat.
Line 9: Registers a callback function that will execute whenever a new connection is made. At this point, we're officially ready-and-waiting for connections. The callback receives a parameter that is the socket object with which we'll communicate with the connected client. No polling for new connections, no needing to worry that work done to accept a connection is blocking IO with all of the other clients. It's the very picture of "just works".
Line 10: To send data to the client, we use the emit() method on the socket object. It takes two parameters, an event name and a data package to include with the event. The names can be anything of your choosing. Any event issued with emit() can be consumed with on(). The data package can be anything as well. Typically, we'll send a plain Javascript object, but for now I'm just sending a string.
Line 11: To receive data from the client, we use the on() method on the socket object. It takes two parameters, an event name and a callback function to execute when the event occurs. The callback function receives a parameter of its own, which will be the data package that was emit()ed at the server from the client.
Line 12: And then, for this example, just to prove to the client that we heard it, we echo back a message.

Finally, we need a little bit of UI code to provide a user a physical interface with which to interact with server:


By now, there shouldn't be anything surprising here. We using an HTML SCRIPT tag to import the Socket.IO library for the client side[3]. It specifies an object called "io" that has a method connect(). Connect takes an address and does all the handshaking necessary to establish a connection[4]. From there, it's exactly the same as wiring up the events and handlers as we did on the server side. Exactly the same. Networking code really can't get any simpler than this.

Start it up, click the button a few times, and you should see this:


By this point, if you know HTML, CSS, and JavaScript already, you can be off to the races on making a multiplayer game with Node.JS and Socket.IO. But I'm not going to leave you out in the rain just yet. Next time[5], I'll show you a very simple chat program using what we've learned so far. And this very simple chat program will grow legs and eventually become a Multi-User Dungeon, or MUD for short.


[1] strictly speaking, it's only WebSockets if you're on a browser that supports WebSockets, but they smooth over the details for you with some fallback options. By default, you probably won't have to worry about it.
[2] I know. Sploosh. Okay, the IE5.5 support isn't that mind blowing considering that it's done through a Flash plugin. But it points to a larger issue of dedication to cross-platform compatability in the Socket.IO dev team. This works whether you're on a 3 year old iPhone or a 10 year old laptop. In other words, if your code has platform compatability issues, it's probably not Socket.IO.
[3] The location of which is a closely guarded secret. Actually, it's just coming out of your node_modules directory. But Socket.IO is hijacking the HTTP requests a little bit to look for requests to the client JS file. Anyway, this is mostly out of scope here.
[4] There is a seriously heavy amount of code in this connect() method. It has to figure out what the client browser is capable of doing, be it true WebSockets, AJAX long-polling, or eventually just giving up and using a Flash-based fallback. And then it has to make the connection to the server and communicate those details so that the server knows how to respond. Again, not really that important.
[5] Which unfortunately might be a couple of weeks. I'm going on a two-week-long trip to the Galapagos Islands with my wife, my camera, and distinctly not my computer.

capn_midnight

capn_midnight

 

How NOT to make games

that would be "As fast as possible, and in Java"
done as a dare, completed in 27 minutes

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferStrategy;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.Timer;

/*
* Created on Jul 13, 2005
*
*/

public class Pong extends JFrame implements MouseMotionListener, MouseListener, ActionListener
{
int p1x = 10, p1y = 0, p2x, p2y = 0, bx, by, bdx, bdy, s1 = 0, s2 = 0, state = DEAD, minspd = 2;
static int DEAD = 0, PLAY = 1;
Random r = new Random();
BufferStrategy bs;
Timer t;
Pong()
{
super("Pong in 27 minutes");
this.setBounds(0, 0, 800, 600);
this.addMouseMotionListener(this);
this.addMouseListener(this);
this.setVisible(true);
this.createBufferStrategy(2);
this.setBackground(Color.BLACK);
this.setForeground(Color.WHITE);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
bs = this.getBufferStrategy();
t = new Timer(1, this);
p2x = this.getWidth() - 10;
t.start();
}
/**
* @param args
*/
public static void main (String[] args)
{
new Pong();

}
public void mouseDragged (MouseEvent arg0)
{
// TODO Auto-generated method stub

}
public void mouseMoved (MouseEvent arg0)
{
p1y = arg0.getY();
}
public void actionPerformed (ActionEvent arg0)
{
update();
paint();

}
public void paint()
{
Graphics2D g = (Graphics2D) bs.getDrawGraphics();
g.clearRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.WHITE);
g.fillRect(bx-5, by-5, 10, 10);
g.fillRect(p1x-5, p1y-20, 10, 40);
g.fillRect(p2x-5, p2y-20, 10, 40);
g.setFont(new Font("fixedsys", 24, 24));
g.drawString(""+s1, this.getWidth()/3, 60);
g.drawString(""+s2, this.getWidth()*2/3, 60);
g.drawLine(this.getWidth()/2, 0, this.getWidth()/2, this.getHeight());
if(state == DEAD)
{
g.drawString("click a mouse button to start play", this.getWidth() - 500, this.getHeight()/2);
}
bs.show();

}
public void update()
{
if(state == PLAY)
{
bx += bdx;
by += bdy;
if(bx >= this.getWidth()){
s1++;
state = DEAD;
}
else if(bx0){
s2++;
state = DEAD;
}
if(40>= by || by>=this.getHeight())
{
bdy*=-1;
}
checkPaddles();
AIMove();
}

}
public void checkPaddles()
{
if(p1x - 5 5 >= bx && p1y - 20 20 >= by)
{
int dy = by - p1y;
bdx *= -1;
bdy += dy/10;

}
else if(p2x - 5 5 >= bx && p2y - 20 20 >= by)
{
int dy = by - p2y;
bdx *= -1;
bdy += dy/10;
}
}
public void AIMove()
{
if(by > p2y) p2y += 7+minspd/2;
if(by 7+minspd/2;
}
public void mouseClicked (MouseEvent arg0)
{
if(state == DEAD)
{
bx = this.getWidth()/2;
by = this.getHeight()/2;
bdx = r.nextInt(5)+minspd;
bdy = r.nextInt(5)+minspd;
minspd++;
state = PLAY;
}

}
public void mouseEntered (MouseEvent arg0)
{

}
public void mouseExited (MouseEvent arg0)
{
// TODO Auto-generated method stub

}
public void mousePressed (MouseEvent arg0)
{
// TODO Auto-generated method stub

}
public void mouseReleased (MouseEvent arg0)
{
// TODO Auto-generated method stub

}
}


capn_midnight

capn_midnight

Sign in to follow this  
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!