The challenges of Creating a Civilization Web Game
code.google.com
code.google.com
While there were times when IE was a decent browser it is clearly standing in the way of innovation at the moment. It is very easy to download a modern alternate browser and a large number of websites using the canvas element would force Microsoft to build a fairly good implementation of it into IE 9 (as it was I believe hinted by the IE project team leader anyway).
So unless there's a burning desire to market this to IE users right this minute, save yourself the hassle and let IE catch up with standards while you work on a better javascript client with Canvas.
Pull the other one!
Some other suggestions:
* Investigate multipart XHR
This is "bleeding edge" and may not, in the end, work, but it'd be worth looking at the work Digg has done w/ multipart XmlHttpRequests (cramming multiple objects/files into a single XHR). The demo they've posted works pretty well in non-IE browsers and it looks like they've laid the foundations for supporting COMET-like delivery of objects over a single request, and have thought about how to address client side caching of objects.
* Business model? Is this just an OSS project or an attempt to build a business (or both)? I could imagine a small business that might generate enough $ to pay some coder/admins & some freelance graphic artists to work on the open source part of the code by providing easy-to-set-up on demand game servers for multi-player FreeCiv games, perhaps w/ a sister set of web apps for collecting game stats/organizing games/etc.
Good luck!
As it turns out, IE's rendering engine is actually faster than Firefox's. I know this from having written a pretty heavy Canvas-based web application recently, and from a dozen years of writing video games for browsers. If he were to ditch FF support, he'd actually have a better shot of getting this thing working.
But really, he doesn't have a chance, so the point is moot.
Building a Civ clone is not like building a Twitter clone. Especially with the terrible architecture decisions this guy has chosen. The project will most certainly fail, and he probably won't get far enough along to even learn anything.
I'd suggest he starts by building something small. Something that fits entirely in the browser, so that he can learn the basics of DHTML, Javascript and Canvas. Something small in scope so that he can learn the basics of video game programming. Something that doesn't overload his brain to the point where he's asking whether he should implement Comet to handle a turn-based game.
So no, I'm not saying he should quit programming, or even quit game development. I'm just saying he should abandon this particular project until he has at least some of the skills he'll need to pull it off.
Freeciv is a turn based strategy game, but it uses simultaneous movement; everyone moves their units at the same time. Therefore updating the mapview must occur in real-time.
Using Comet allows the web server to push data to a browser, without the browser explicitly requesting it. So when an event occurs on the server, it will immediately be trasmitted to the clients with Comet, rather than waiting for the polling interval of Ajax + the delay of a packet being transferred from the client to the server.
So in my mind, Comet could speed up the time it takes to transmit a packet from the server to the clients.
"Especially with the terrible architecture decisions this guy has chosen."
How would you do it better?
It was much appreciated, still have a couple of odd behaviours that I'd have to iron out before letting it out into the wild.
That should cut down on both latency and issues with IE only downloading one image at a time.
Civ also has some features which make it very easy to cheat creatively regarding logic for loading those things. You can guarantee, for example, that no Riflemen will show up anywhere on the map until someone has discovered Gunpowder. Thus, if someone discoverse Gunpowder, you send everyone an <img src=".../gunpowder_units.gif" style="display: hidden;" /> and you'll have the Riflemen sprite available instantly once someone actually constructs one. (Edit: There are, of course, security issues associated with that example.)
Internet Explorer has a limitation where only one image can be downloaded at a time
Really? Are they sure they don't mean "IE only downloads two resources in parallel from any particular domain, like suggested in the HTTP spec"? This has a fairly simple solution, familiar to anyone who has read the YSlow stuff: create a few subdomains to alias your HTTP server, load images from a few of them at a time. I do it for my website, works like a treat.
This also avoids some nasty binpacking problems around combining sprites of different sizes.
When the game starts up, you only need to preload the terrain, terrain decoration, and initial unit sprites - that's probably a couple dozen, no more than you'd need to draw the page as an image. Less, actually, since you can re-use your terrain sprites.
You should then be preloading the other sprites as the game goes on. If the user isn't doing anything, use that network connection to download the next spriteset the game will need.
It would also make it easier to move larger chunks of the FreeCiv client into the browser in a manner that would be easier to refactor and maintain than Javascript - and while being compiled to be as small as possible.
Java, for all its faults, is strong in refactorability, which would be essential for keeping the code in sync with a moving target like the current C implementation.
The way I'd do it is create a bunch of large tiles (like the size of Google Maps) and pre-draw all the sprites onto a single tile. Put those tiles into a single container div that is bigger than its container, positioned absolutely, and clipped with overflow:hidden. When the world scrolls, simply change the positioning of the container. If it scrolls far enough that you need to render another tile, drop the one off-screen and pre-render its replacement on the other side, so if the user scrolls even more, the images are waiting for them. Much like how G!Maps does it.
This offloads the graphics work onto the C++ rendering engine, which has been tuned for this sort of stuff. Doing it in JS is just asking for trouble.
The same goes for changes that occur to the map (at least changes within the current view). Map tile improvements would be a pain if you had to download a section of the map just to update a single tile. It would probably make sense to have the sprites on-hand to update the currently viewed map section, and have it automatically added to future pre-rendered tile updates. This way you wouldn't have to download the map you already have to see the improvement, but when you downloaded future sections (or even come back to the current section) it will be part of the pre-rendered section.
All of this is disregarding whether or not there is a mode to show the map without improvements on it (IIRC, there was an option like this in Civ2). Then you might have to change these design decisions to accommodate that unless you're ok with the user needed to re-download all map sections whenever that options is flipped on/off.
The reason for pre-rendering DHTML-based tiles is because a.) you have to worry about download times for the sprite images, though hopefully you can pay this once and have them cached forever and b.) it takes a fair bit of CPU to create lots of DOM elements and move them to the correct positions. Less than blitting an image to canvas, but more than just changing the top and left of a container div.
If AJAX is too slow, do not think Comet will solve your problems. It's very hard to get Comet to work reliably on all browsers across all types of firewalls and proxy servers.
I did a prototype of something using the library that powers GTalk, Google Docs, and now Wave. Even with the library all pre-built for me, it was pretty hard to keep it from occasionally dropping connections and associated messages, and once in a while it'd lock up my browser (much like GMail and Docs do, occasionally. ;-)). I also peeked under the covers, and there's a lot of subtlety in what's going on.
Comet is best for when you have stuff that really needs to be real-time. Things like stock quotes, or chat. IIRC, everything in Civilization is done in response to user input. AJAX is fine for that.
Please elaborate. (I have also been experimenting with Flex.)
When you do expect it, you have three options: 1) you always wait for a response before returning, making your function sychronous (thus maybe killing performance), 2) you pass the responsibility to handle this behaviour to the caller (thus creating an abstraction leak), 3) or you define a custom event that you trigger when the response occurs (best behaviour, but needs extra code).
Certainly not a huge issue once you get the hang of it, but something that can definitely trip you up when you're just learning it.
For instance to save the user you can't just call User.Save and then go about dependent routines, because there is a possibility that call fails or takes a long time and then the player is out of sync. This is especially important if you want to try to minimize cheating, as the longer the client goes without syncing, the higher the probability for tampering, replays, etc.
There are probably a few libraries around for this sort of thing, but the one I've had experience with is Raphael: http://raphaeljs.com/
It should mean less time redrawing the map because you can just reposition the elements on the screen dynamically.
Consider how 3D engines work, where they compute all the visible surfaces using vectors, and then transform and scale raster "textures" to apply on these surfaces.
The XML issue isn't actually relevant either because normally the SVG/VML DOM objects will be generated at runtime by JavaScript, rather than serialized in the page and served up statically.
http://www.mattryall.net/demo/civ-svg/
SVG is by no means a solid game development platform, but it is some interesting browser-based technology which might be useful for game developers to investigate.
This guy's whole project is going to revolve around DOM and Canvas stuff in Javascript. He needs complete control over that, so relying on somebody else's library for it will kill him.
If you're building a business app and need graphics for reporting, then sure, use a library. Use jQuery even. But if you're building a video game, you're going to need to do this stuff yourself.
If a library helps you deliver the software faster and better, use it. If it gets in your way, then consider using the layer underneath directly.
But, regardless, my main point was to consider browser-based _vector_ graphics, which are several orders of magnitude faster than canvas for activities like this.
But it's a commercial product and might be too expensive for the OpenCiv guys.
I haven't coded something like that myself, but I have been wondering if CSS layers would work nicely for isometric graphics.
I am surprised how many people suggest Flash. Flash needs to die, so it is a worthy goal to try to implement games in Javascript instead. Flash simply is not available anywhere and causes a lot of suffering.
I wonder how it would work as a java applet. Might require a jre download, but it should be many orders of magnitude faster then javascript.
But web games are better for a host of other reasons:
- compatibility between os-es
- compatibility between versions of the same OS (win 95 vs xp) - much greater lifetime
- no hassle with installs, play instantly and from anywhere
- easier to multiplay
- switch from "savegames" to a "profile".
Eh? How do you run a Java applet on a system without Java (Java Runtime Environment)?
1. Go with SVG and WebSockets.
or
2. Go with pure HTML,Javascript and CSS with transformations.
I am working right now on a game based on SVG and couldn't be happier. Works flawlessly on FX, WK & OP.
One last advice, drop support for IE and save headaches and wasted resources.