Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
spicyjack

Javascript Doom

Recommended Posts

Mods: please pigeonhole this post as appropriate

If you're not a regular reader of slashdot, this project got posted there today:

https://developer.mozilla.org/en-US/demos/detail/doom-on-the-web/

Doom on the Web

by azakai on May 29, 2011

The classic game Doom, playable on the web


Full source is available. I tried playing, but nothing happened. The site may be in the process of being slashdotted.

Share this post


Link to post

Sound effects are crap and it crashes Chrome. Wheee.

Very interesting nonetheless

Share this post


Link to post

In Firefox 4, the sprites aren't showing up when they should, and are showing up when they shouldn't. (Disappearing randomly and bleeding through doors)

Shouldn't this go in news?

Share this post


Link to post
spicyjack said:

I tried playing, but nothing happened.

Works for me, but sounds lags badly.

Share this post


Link to post

Not that my laptop is very powerful but it's not very old and I got a nice 1.2 - 2.0 FPS. What won't they port Doom too...

Share this post


Link to post

from Technical Details:
The Doom source code was compiled from C to JavaScript using Emscripten and Clang. Optimized using the Closure Compiler.


Hey, that's cheating! Lazy bums... ;-)

spicyjack said:

Full source is available.


Not quite. Yeah, there's a .js file but it's the result of the above process, and therefore humanly unreadable and unmaintainable. Reminds me of that old Internet C++ virtual machine, where the public "source code" was a single huge machine-generated C file.

Edit: ok, there's a link to a proper codebase which is...well...just the plain old linuxdoom + whatever is needed for Emscripten. If you expected a pure, readable Javascript port though, you'll be disappointed.

Share this post


Link to post

My main pet peeves towards such "quick and dirty" ports of Doom is that essentially they use none of the advantages of their target platform (essentially it's like running the original C program in a virtual machine) and they have a codebase that's no better than the original, quite literally.

E.g. if I had made Mochadoom by using a C to bytecode cross-compiler or somesuch, I would have none of the advantages of garbage collection, object-oriented architecture rewriting, type safety, source code readability, debugging ease etc. that go with a complete code rewrite in a language with a different philosophy. Of course, the two are completely different tasks in magnitude, and purpose.

Either way, I guess the important thing is that Doom gets richer anyway, no matter which approach is used.

Share this post


Link to post

You're right. This just shows off the tools involved and provides a very to see your old laptop is slower than it sometimes looks.

Share this post


Link to post

Yup. And just like e.g. Flash Doom this is most likely a one-off affair that won't be further developed in the direction of a full-fledged source port.

Share this post


Link to post

Dude, converting a code base like Doom from one language to another is badass, however you look at it. The fact that some people wrote a program (Emscripten) to do it programmatically is even more badass.

- Garbage collection

Check, JS is a garbage-collected language.

- Object-oriented architecture

OOP is lame anyway, boooo.

- Type safety

I see your type safety argument and raise you one NullPointerException. If you re-raise, I'll be forced to bet all my Exceptions (there are a lot, be wary).

- Source code readability

Just use the C version?

- Debugging ease

Just use the C version?

Also you've been working on Mocha Doom for the better part of a year. This guy probably spent a week on this tops.

Share this post


Link to post
Ladna said:

- Garbage collection

Check, JS is a garbage-collected language.


Only that it's used to emulate a staunchily non-garbage collected codebase. It's not very different than running an emulator or a virtual machine, so any "garbage collection" will only apply to the VM
itself, not the actual code being run. A static malloc will stay a static malloc inside the emulation, as will a dangling pointer or a memory leak.

Ladna said:

- Object-oriented architecture

OOP is lame anyway, boooo.


That's ironic to say, since Doom itself is actually VERY OO in some aspects. For the rest this is probably Holy War material, so I'll redirect you to the Elders for more insight :-p

Ladna said:

- Type safety

I see your type safety argument and raise you one NullPointerException. If you re-raise, I'll be forced to bet all my Exceptions (there are a lot, be wary).


Can't see the line between argumentation and trolling here, sorry, so I'll assume the latter. In any case, type safety/punning is starting to become an issue even for C-based ports (see the C99 debacle).

Ladna said:

- Source code readability

Just use the C version?

- Debugging ease

Just use the C version?


So "easy" that many asymptomatic bugs of the original codebase only showed up once a more bounds-checking environment was used (e.g. finetangent and solidsegs overflow).

Ladna said:

Also you've been working on Mocha Doom for the better part of a year. This guy probably spent a week on this tops.


As I said, different goals, and way different potential.

As for doing "code conversion programmatically", this is more properly a sort of cross-compilation, not a code conversion. For an example of actual "code converters" refer to that f2c utility of yore, or some older pascal-to-c converters which actually translated source code statements into other readable source code statements, not bytecode or some intermediate pseudo-assembly.

Share this post


Link to post

The main Mozdev page becomes unusable after clicking "Launch Demo" using Chrome and the button does nothing, I see nothing but a blank page.

Share this post


Link to post
Maes said:

Only that it's used to emulate a staunchily non-garbage collected codebase. It's not very different than running an emulator or a virtual machine, so any "garbage collection" will only apply to the VM
itself, not the actual code being run. A static malloc will stay a static malloc inside the emulation, as will a dangling pointer or a memory leak.

Doom has the ZONE allocator, so I don't know why you need garbage collection...? Emscripten uses a JS array for the heap, so ZONE should work just fine on it.

Maes said:

That's ironic to say, since Doom itself is actually VERY OO in some aspects. For the rest this is probably Holy War material, so I'll redirect you to the Elders for more insight :-p

Haha there is some stuff in Doom that mimics OOP paradigms... actually all I can think of is the thinker system, which is like the weakest dynamic dispatch and encapsulation system I can think of. I guess maybe you can go further and say all type-punning is "inheritance", but come on.

Maes said:

Can't see the line between argumentation and trolling here, sorry, so I'll assume the latter. In any case, type safety/punning is starting to become an issue even for C-based ports (see the C99 debacle).

I guess there are some awesome optimizations or safety checks that compilers can do if they don't have to worry about type punning? I don't know, I agree with Quasar that type punning is a pretty fundamental pattern in C; deprecating it seems insane to me. The most disappointing thing about the whole debacle is that the best way to deal with it (which is still laborious) is to define anything you might want to type-pun inside of a union... except that accessing the non-assigned value in the union is undefined! BOOOOO!

Maes said:

So "easy" that many asymptomatic bugs of the original codebase only showed up once a more bounds-checking environment was used (e.g. finetangent and solidsegs overflow).

What bounds checking environment was this? AFAIK these were bugs discovered by the community using the C ports, I'm pretty sure no one rewrote linuxdoom in Java just to find those bugs. Maybe modern compilers or tools like valgrind/memcheck helped, I doubt it though.

Bounds checking isn't difficult in C, it just involves overhead that most programmers aren't willing to spend (array indexing is supposed to be pretty fast, adding a big check at the beginning of it hurts). So while I don't disagree that IndexOutOfBoundsException would have found the invalid accesses (with proper testing), I think that the overhead of doing so in 1993 was insane. Most game developers still agree with this, choosing to write their games in C++ which also has no bounds checking.

Maes said:

As I said, different goals, and way different potential.

Yeah well you like Doom, and this guy likes JS (clearly you're way smarter than this guy haha). I agree there's no way the author makes this into a full-fledged source-port. It is neat that the source ports we have now might be able to run "natively" in the browser one day.

Maes said:

As for doing "code conversion programmatically", this is more properly a sort of cross-compilation, not a code conversion. For an example of actual "code converters" refer to that f2c utility of yore, or some older pascal-to-c converters which actually translated source code statements into other readable source code statements, not bytecode or some intermediate pseudo-assembly.

Well you're not supposed to read the JS output, just like almost no one reads the generated assembly or object code from a C/C++ compiler, or the bytecode output from the Python or Java compilers. So all this "readability" and "debugging" stuff is really just a red herring. These days nobody digs into what the compiler spits out. That said, it's not horribly unreadable; it's probably a good start for a conversion (you might want to go here for some info, the Technical Paper PDF is pretty simple and has some example output.

Share this post


Link to post
Ladna said:

What bounds checking environment was this?


Java. And at least Quasar had never heard of the finetangent overflow before (nor had I ever heard of a solidsegs overflow in the BSP tree trasversal, yet it happens e.g. in TNT MAP30). Especially finetangent overflows are practically asymptomatic and in theory, impossible to even break anything in the original source, at least the way they are used. But hey, maybe you are smarter than him and it doesn't come as a surprise to you, who knows ;-)

Ladna said:

Haha there is some stuff in Doom that mimics OOP paradigms... actually all I can think of is the thinker system


How about the status bar widgets? ;-)

Ladna said:

So all this "readability" and "debugging" stuff is really just a red herring.


I beg to differ. Stuff like the "javascript port" of the "flash port" of Doom are just cross-compilations of the original linuxdoom code. They add no novelty, maintainability or functionality to the code itself, and as you said, are typically implemented as one-time, one-off, proof-of-concept affairs for showing off the powers of cross compiling tools, not to generate something really innovative (even playability takes secondary priority, more often than not).

If the future of source ports lies in running stuff in virtual machines and browsers, then I'd rather see something based off a clean and readable codebase that can be developed and extended independently in the direction of modern source ports, not something piggybacking on the same old tired linuxdoom code (BTW, there's an MS-DOS emulator running Doom written in Java, which for me was the final drop that prompted me to start development). And AFAIK I'm the only one who took a step in a different direction and actually pulled it through (sadly, Stark and Doomcott both didn't take off for their own reasons).


Where all this may lead, I don't know, but I do hope that one day developing advanced Doom source ports will not require using C/C++ anymore, thus potentially bringing more developers and innovation to the Doom community.

Share this post


Link to post
Maes said:

I do hope that one day developing advanced Doom source ports will not require using C/C++ anymore

DelphiDoom :p

Share this post


Link to post
Gez said:


Die.

J/K, the only reason this one worked is because Delphi (and Pascal, in general) maps almost 1:1 to C, pointers included. This was true to the point that in the past there even were pascal-to-c and c-to-pascal source code converters. In any case, I have all of this covered here, so I won't repeat myself.

The metrics are interesting though: the author claims he did it in a month of intensive work, something like flash or "javascript" or Android Doom take about a week or so by using either external linking or cross-compilation, while a from-the-grounds-up approach like Mocha probably took something like 5-6 months of actual work (I had sizeable pauses in the mid). The major problem was not type safety or unsigned types, but coming up with a totally new way of organizing something that was a total free-for-all, code-wise. Simply translating functions was not enough, I had to come up with a new way of organizing stuff and deciding what should go together with what, what should be made into its own class, etc. Sure, there was a crude separation of concerns already but also a lot of cross-talking between modules.

Of course, you have different results in those three cases. Cross compilation gives you something that "just works" ASAP, but that's about it. The Delphi Doom stuff is...well...quite unappealing to work with, even compared to the C original. Something like Mocha is -I hope- actually friendlier to work with, easier to optimize at the source code level and easier to tinker with innovative stuff e.g. a parallelized renderer, which is, for now, an unique feature among Doom source ports.

And there has actually been a precedent which inspired Mocha Doom to a large degree: Jake 2.

Ironically, Jake 2 was later on converted into a "javascript" form by using GWT cross-compilation and yielding Quake II GWT Port :-p

The big difference is that now that the groundwork has been laid out by me, it's easier for someone else to do a port in e.g. C# or Python or even PHP.

That being said, I would love to have seen a Fortran port of Doom: the column-first arrangement of Fortran may have been an inherent advantage (plus some older versions had a library fixed precision type). That would be more oldschool than oldschool ;-)

Share this post


Link to post
Maes said:

That being said, I would love to have seen a Fortran port of Doom...


heh I would love to see a lolcode port of Doom :P

Share this post


Link to post

I'll be impressed when someone implements Doom entirely on an FPGA or several stitched together.

Share this post


Link to post
_bruce_ said:

Interesting, but I won't use it - same with the java port.


You mean this one, right?

Share this post


Link to post
Maes said:

Java. And at least Quasar had never heard of the finetangent overflow before (nor had I ever heard of a solidsegs overflow in the BSP tree trasversal, yet it happens e.g. in TNT MAP30). Especially finetangent overflows are practically asymptomatic and in theory, impossible to even break anything in the original source, at least the way they are used. But hey, maybe you are smarter than him and it doesn't come as a surprise to you, who knows ;-)

Ehhhhhhhhhhhhhh I don't know. I'd say bugs that went unnoticed for 15+ years aren't really worth inventing Java and reimplementing your program in it to discover. Bounds checking: not worth the hassle.

Honestly, I thought you meant infamous bugs like medusa or tutti-frutti, but looking them up on the Doom Wiki they aren't caused by invalid accesses. The only bug I could dig up that was is "Excessive scrolling texture overflow", which I guess is supposed to have a check but doesn't? Bleh whatever. Maybe ninja spawn also qualifies. Regardless, bounds checking: not worth the hassle.

Maes said:

How about the status bar widgets? ;-)

Nothing about those are object-oriented. We're talking about linuxdoom-1.10, st_* right? They don't even use function pointers...? There's no polymorphism, no inheritance, no dynamic dispatch.... I guess maybe if you mean "look at all those static variables... encapsulation!" or "objects are kind of like structs!", but then I don't see what your argument against C is, it has great support for OOP! (rofl)

Maes said:

I beg to differ. Stuff like the "javascript port" of the "flash port" of Doom are just cross-compilations of the original linuxdoom code. They add no novelty, maintainability or functionality to the code itself, and as you said, are typically implemented as one-time, one-off, proof-of-concept affairs for showing off the powers of cross compiling tools, not to generate something really innovative (even playability takes secondary priority, more often than not).

I mean, I understand your point. I don't think the author will be maintaining this to the degree it becomes a proper source port, and I think if that were the goal then he totally failed. Then again, I don't think that was the goal at all. This project demonstrates two things:

- JS's ability to function as the assembly language of the browser.
- Clang's (via Emscripten) ability to compile C/C++ programs that run NATIVELY in the browser.

I'm not the biggest JS fan on the planet, but I think you'd have to be a big sourpuss not to concede that both of those things are COOL AS SHIT. To say that this adds no novelty is pretty blind, this is an extremely novel thing. I can count the number of FPS games implemented in JS on my dick.

Maes said:

If the future of source ports lies in running stuff in virtual machines and browsers, then I'd rather see something based off a clean and readable codebase that can be developed and extended independently in the direction of modern source ports, not something piggybacking on the same old tired linuxdoom code

I thought Mocha Doom was based on linuxdoom, even though you're removing limits and adding some Boom stuff? Correct me if I'm wrong, I probably am!

Is this guy gonna implement DECORATE or portals? Shit no. Then again, all we have to do is run ZDoom or EE through his thingamajigger and *poof*. This is MUCH easier than re-implementing either of those ports in Java. It's also much easier than bringing Mocha Doom (while already an impressive achievement) up to feature parity with either of those ports.

And I don't really see what's so unreadable about C and C++. Sure there are endless examples of unreadable code in those languages, but the same goes for any popular language - Java included. If you're referring to the fact that the generated JS isn't something you'd ever want to work with, I'd say that:

- No one works with Java bytecode
- No one works with object code

Let's say we're running Odamex through this conversion. Odamex isn't magically any less readable or harder to debug. We just compiled it to JavaScript. Poof! (again)

Maes said:

Where all this may lead, I don't know, but I do hope that one day developing advanced Doom source ports will not require using C/C++ anymore, thus potentially bringing more developers and innovation to the Doom community.

I share this hope. I think a lot of would-be contributors are intimidated by C/C++ and a Java port can only help in that area. However, my opinion is that a C/C++ engine with powerful scripting is a better solution, and it seems that's ultimately where we differ. I guess we'll see what happens, but hopefully we get both! :p

Share this post


Link to post
Ladna said:

Nothing about those [status bar widgets] are object-oriented.


Weird, because they were practically structured in a struct status + functions working on particular instances combo. That, in my book, screams "ENCAPSULATE ME!!!" from 100 miles away. In fact, the STBAR widgets are a residue of an initial writing in Objective-C, I recall, before a change in direction was taken. Still, it shows very much, and were among the most natural things to transition to an OO form. Stuff like sectors, player object, mobjs also have functions designed to work on particular instances of them without requiring anything else. This may not have been deliberate, but sure it did map nicely. If you are still not convinced, take a look at ZDoom which actually is much more OO than Mocha Doom in some aspect.

Ladna said:

To say that this adds no novelty is pretty blind, this is an extremely novel thing.


Strange, I didn't see anyone calling this novel and "cool as shit". Maybe because it's not based on currently hip buzzwords?

Ladna said:

I can count the number of FPS games implemented in JS on my dick.


Then you must have no dick :-p (J/K, I'm sure there are a lot of Maze War like "FPS" written in pure Javascript + Canvas). Technically, this is not implemented in JS anymore than a GWT application is implemented in JS. The actual maintenance and development (and thus language semantics etc. take part in a whole other language's space and rules). I'd be more impressed with a hand-written port, personally, not with a dumb virtualization, which I consider abysmal in terms of performance and maintainability.

Ladna said:

I thought Mocha Doom was based on linuxdoom, even though you're removing limits and adding some Boom stuff? Correct me if I'm wrong, I probably am!


Yes, I started from the Linuxdoom codebase thinking that I should start from the ground up and that it would be better for learning the basics, but I now wonder if that was a wise decision and I should have started from Boom instead.

However what I meant by "not piggybacking" is that I'm not cross-compiling anything, and I actually had to re-map and study a lot of things in depth, as I can't rely on cross-compilation masking those issues for me. I could just have compiled linuxdoom into an external DLL, link to it via JNI and claim that I finally brought "Doom to Java", but really, that's just hiding a language with another.

And yeah, I'm adding more and more Boom stuff, sometimes copying them/adapting them directly, and sometimes using my own original approach to solving a problem or adding a new functionality.

Ladna said:

Is this guy gonna implement DECORATE or portals? Shit no. Then again, all we have to do is run ZDoom or EE through his thingamajigger and *poof*. This is MUCH easier than re-implementing either of those ports in Java. It's also much easier than bringing Mocha Doom (while already an impressive achievement) up to feature parity with either of those ports.


Why so negative? If enough contributors join in (just see what _D_ did with Mocha in just a few months, and I've still to merge all changes) Mocha Doom will eventually reach Boom level in features or even depart in a wholly different direction. It doesn't have to be clone-lackey of anything. The only bad thing is that a lot of time was lost and none undertook such a project seriously. TBQH, I realized that this would've been much harder and/or impossible with Java as it was e.g. 10 years ago, which might explain why earlier projects like Start or Doomcott were eventually abandoned. Surely I wouldn't want to tackle this without Java 5's programming conveniences.

Its main advantage vs something cross-compiled to Javascript is performance. Even if one day we'll have enough computrons to run e.g. a cross-compiled ZDoom in a browser at 200 fps, something based off Mocha will easily do 20000 instead (actually, in timedemos it currently achieves 60-70% of the performance of prboom+ at resolution parity and -nosound). The overhead of mimicking C's runtime environment just kills off any performance, compared to something hand-optimized for a particular platform.

Yeah, OK, it's not as buzzword-compliant as in "Whooo! It runs in a browser with Javascript *cums*", but programming-wise it's light-years ahead. Well...until someone runs Mocha through GWT and ruins everything, that is ;-)

Share this post


Link to post

* runs javascript Doom in ancient Internet Exploder *

* types IDDQD *

Hah, now those evil hax0rz can't pwn my box anymore! :P

Share this post


Link to post

The point of JavaScript Doom is not Doom, it's emscripten. Doom has been for a long while the benchmark by which every platform was judged, sorting the wheat ("it runs Doom!") from the chaff ("it doesn't"). Probably because Doom was open-source, famous, popular, and reasonably complex while still quite small. So, porting Doom is both not so trivial that people won't care; and not so tedious that people won't bother finishing. It's a perfect program for proofs of concept; which is what this thing is.

Mocha Doom and Delphi Doom, on the other hand, were intended to be true source ports rather than proofs of concept.

Share this post


Link to post

- Status bar widgets

Functions that take structs as arguments, or even struct members as arguments (like doors, platforms, etc.) is not OOP in any way. Seriously. If you think it is, I don't understand why you say you "got object-oriented programming" out of converting Doom from C to Java, because 90% of stuff in Doom is functions operating on structs (like 99% of C programs). Just because something's easy to translate into an OOP paradigm doesn't mean it was already object-oriented, it required translation.

Newer ports are more object oriented. They're also written in C++....

- "Strange, I didn't see anyone calling this novel and "cool as shit". Maybe because it's not based on currently hip buzzwords?"

If someone tried to argue that that x86 emulator in Java "add(s) no novelty" then I would say "to say that this adds no novelty is pretty blind, this is an extremely novel thing. I can count the number of x86 emulators implemented in Java on my dick." But I'm pretty sure we're not talking about whether Java or Java x86 emulators are cool or not, we're arguing about whether or not JavaScript Doom is cool, and I think it is... and you think it isn't...?

- I have no dick!

Haha :p Actually I looked around real quick for some JS FPS games, and you're right there are some maze war ones and the GWT port of Jake2. At first I thought I might have to grow a second dick due to that GWT port, but I don't really consider a serverside Java app that generates JS on the fly an "FPS implemented in JS". It is certainly "novel" and "cool as shit" though. Anyway, AFAIK this Doom port is the only FPS in JS.

- Why so negative?

I don't really mean to be negative. Don't we all agree that getting Doom to run in the browser probably took about a week? Don't we all agree that this is less than the 24-52 weeks it took to get Mocha Doom running in the browser, and it requires no (gigantic, insecure) Java plugin?

I'm not saying I'm gonna run ZDoom through Emscripten and put up my own demo this week. I'm saying that even if it takes me a month of solid work to do it, there is NO WAY Mocha Doom can reach feature parity in the same amount of time. It's IMPOSSIBLE. I will seriously eat my 1 remaining dick if Mocha Doom becomes Mocha ZDoom by the 4th of July.

- Performance sucks

Yeah, then again JS and browsers suck. It's still cool as shit though.

EDIT:

I tried it on my Windows XP Core2Duo (1.86GHz, 1GB RAM) machine using Firefox 4, and I get ~35 FPS during the intro, ~30 FPS running around, and ~20 FPS whenever anything is happening like monsters or doors moving. All in all it's almost there. I don't really understand the need for "20000 FPS" or even "200 FPS" (and FWIW Carmack thinks 60 FPS is all you need ever) but to each his own I suppose.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×