Dark Bit Factory & Gravity

ARCHIVE => Archive => Java,JS & Flash => Topic started by: p01 on July 01, 2007

Title: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: p01 on July 01, 2007
The time has come to, finally, release 3D TOMB II (http://www.3dtomb2.com/), the DOOM-like in 4k of JavaScript I initially made for the5k 2004.


The whole game now weighs 4003 bytes, all files included. The controls are X,C to strafe, SPACE to fire, the arrows to move around. And here is a downsized screenshot:

 (http://poi.ribbon.free.fr/3DT2_img/screenshot.gif)


/!\ Due to a bug in Safari and Gecko's handling of the zIndex, the game doesn't work as expected in Safari, FireFox and co. But it works like a charm, on a semi-recent computer, in IE and Opera.


Hope you'll enjoy it.
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: Yaloopy on July 02, 2007
That's pretty damn cool :) Shame about it not working in FF
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: Rbz on July 02, 2007
Yeah, very nice work! 

I just miss some sound effects, but I know that there's no free bytes for this...



Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: mike_g on July 02, 2007
Nice game. I played it in Opera and it ran a quite slow, but then I have got quite an old PC and doing stuff like this in Javascript is quite demanding. Considering theres the graphics in there thats quite clever getting all that done in around 4K. I got reasonably simple functions that are bigger than that. Good stuff :)
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: Jim on July 02, 2007
That's neat!  The 4k is a real achievement.  Why not make a full version with sounds and higher res graphics to really show it off?

Jim
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: benny! on July 02, 2007
@p01:

Awesome, p01. Very well done !!!
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: ninogenio on July 02, 2007
very cool :)
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: Tetra on July 02, 2007
Very nice, and works pretty fast too :)
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: Shockwave on July 02, 2007
Good work :) Heck of a programming exercise to get this game so tiny.
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: p01 on July 02, 2007
Thank you very much for the good words and the karma++  :cow:

3D TOMB II works best in IE. Sorry, Opera does well, but Firefox doesn't seem too happy about handling a page with 2650+ DIVs.

As for making a bigger version with improved graphics and what not ... well, that crossed my mind but honestly I should rather spend that energy on a new JavaScript demo. I've already worked on 3D TOMB II way too long : every now and then since 2002, plus some more intense periods ( a month ago, the game was ~4.6K and didn't work in Opera. It was fun, and tiresome, squeezing almost 700b. )

That doesn't mean I won't do another crazy game in JavaScript.
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: p01 on July 03, 2007
Ahoy! rejoice people for now 3D TOMB II works in IE (quickly), Opera (ok), Firefox (slowly) and Safari 3 beta (almost nicely).

Beside, I really like that cow -> :cow:
She looks really cool.
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: Shockwave on July 03, 2007
:cow:

Works here in FF, IE is the way to play this though.
For what it's worth I think you are right about wanting to move on to another project, the whole point of this was to get a fps in 4kb and you did a great job of it.
Time to make something else, people who want to play a complete version of Doom with sound effects etc should perhaps get dosbox out.
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: Jim on July 03, 2007
:P  Don't get me wrong, I thought it was great!

Jim
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: p01 on July 03, 2007
I don't, don't worry. You're far from being the 1st one mentionning the idea of a bigger version.
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: DrewPee on July 04, 2007
@p01 - played the game last nite - well done matey - that is some cool code you have there - karma+

Drew
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: Xone on March 20, 2008
karma applied, nice one  :)
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: mazemaker on August 26, 2008
is there a non-obsfucated version of the source code?
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: Shockwave on August 26, 2008
Quote
As for making a bigger version with improved graphics and what not ... well, that crossed my mind but honestly I should rather spend that energy on a new JavaScript demo. I've already worked on 3D TOMB II way too long : every now and then since 2002, plus some more intense periods ( a month ago, the game was ~4.6K and didn't work in Opera. It was fun, and tiresome, squeezing almost 700b. )

I guess not..
Title: Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
Post by: p01 on August 26, 2008
Shockwave: correct :p

However I just ran the code through a de-obfuscater and it's "ok", and not so long that it should remain manageable if you are a bit curious. I also added a couple of comments:
Code: [Select]
// main
function N()
{
    t++;
    C = '#000';
    //    if player still alive, move it if need be
    if (h = p.h)
    {
        p.A += (K[39] - K[37]) * P / 96 + P * 2;
        while (p.A > P)
        {
            p.A -= P * 2;
        }
        p.U(K[38] - K[40], K[67] - K[88])
    }
    p.t += I =- 1;
    U[32] &= m * p.t * p.h < 0;
    z = p.h ? P / 3 : P / (3 + Math.cos(t / 5) / 3);
    A = p.A - z / 2;
    n = p.x - p.c * 64;
    o = p.y - p.s * 64;
    a = 4 * 64 * 64 * Math.tan(z / 2);
    //    do the floor casting
    for (Z = x = 0; x < 50; x++)
    {
        r = a / Math.cos(A - p.A);
        u = Math.cos(A) * r;
        s = Math.sin(A) * r;
        A += z / 50;
        i = 130;
        d = (c = x * 52) + 52;
        do
        {
            d--;
            v = n + u / i;
            w = o + s / i;
            k = q[(w >> 3 & 56) + (v >> 6)];
            if (k >> 8 || (v | w) &- 512)
            {
                break;
            }
            if (H[d].style.backgroundColor != Q[b = T[k + (v & 56) + (w >> 3 & 7)]])
            {
                H[d].style.backgroundColor = Q[b], H[c].style.backgroundColor = Q[b + 1];
            }
            c++
        }
        while (i -= 5);
        with (W[x].style)
        {
            left =- ((v^w) & 56) - (v & w & 64);
            top = W[x].t = 130 - i;
            W[x].parentNode.style.zIndex = height = i * 2
        }
        if (x == 25)
        {
            Z = i;
        }
    }
    //    process the entities
    for (j = 0; j < 6 + L / 2; j++)
    {
        X = E[j].x - n;
        Y = E[j].y - o;
        A = Math.atan2(Y, X) - p.A + P * 2;
        while (A > P)
        {
            A -= P * 2;
        }
        i = Math.round(Math.sqrt(a / Math.cos(A) * a / Math.cos(A) / (E[j].d = d = X * X + Y * Y)));
        i *= i < 130;
        A *= 400 / z;
        //    close to the player then point towards it
        if (d < 16 * 64 * 64 && p.h)
        {
            E[j].A = p.A;
        }
        E[j].A += (((Math.random() * 3) & 3) - 1) * P / 8;
        with (W[j + 51].parentNode.style)
        {
            left = 200 + A - i;
            top = 130 - i;
            width = zIndex = height = i * 2
        }
        //    living entity ->
        if (E[j].h)
        {
            x = Math.round(25 + A / 8);
            if (--E[j].t < L * 2 && W[x] && 130 - i < W[x].t)
            {
                E[j].t = 48, C = '#600', p.h -= p.h > 0;
            }
            W[j + 51].style.left =- (E[j].k + ((j * 4 + E[j].t) & 4 ? 1 : 0)) + '00%';
            E[j].U(-2, 0);
            if (U[32] && (Math.abs(A) | Z) < i && (I < 0 || E[I].d > d))
            {
                I = j;
            }
        }
        //    pick up entity if it's close
        else if (d < 64 * 64)
        {
            $ += (E[j].k - 1 ? 1 : 10), E[j].k ? m += 5 : p.h += 2, E[j].x =- d;
        }
    }
    //    firing
    if (I + 1 && !--E[I].h)
    {
        W[I + 51].style.left = '-200%', $ += E[I].k - 3 ? 10 : 5;
    }
    //    hud
    W[50].style.left = p.h ?- 112 * U[32] :- 224;
    m -= U[32];
    p.t += U[32] * 8;
    U[32] = 0;
    B.style.backgroundColor = C;
    S.innerHTML = p.h + '<br>' + m + '<br>' + L + '<br>' + $;
    //    oh noes! you just died
    if (!p.h & h)
    {
        M.src = $ + '<br>' + (prompt('your name ?', ''));
    }
    //    bottom right of the map -> next level
    if (p.x > 464 && p.y > 384)
    {
        l();
    }
}
//    Entity class
function O(v, w, h)
{
    i = q[(v >> 6) + (w >> 3 & 56)] >> 8;
    W[j + 51].style.left =- h + '00%';
    this.x = v;
    this.y = w;
    this.A = 0;
    this.k = h;
    this.t = this.h = h > 1 ? h : 0;
    //    move() method
    this.U = function (X, Y)
    {
        this.c = v = Math.cos(this.A);
        this.s = w = Math.sin(this.A);
        e = (v * X - w * Y) * this.k / 3;
        u = (w * X + v * Y) * this.k / 3;
        v = this.x + e;
        w = this.y;
        if (q[(w >> 3 & 56) + (v >> 6)] >> 8)
        {
            v -= e;
        }
        w += u;
        if (q[(w >> 3 & 56) + (v >> 6)] >> 8)
        {
            w -= u;
        }
        this.x = v;
        this.y = w;
    }
}
//    initLevel()
function l()
{
    Q = '#10,#21,#32,#43,#54,#b9,#ca,#db'.split(',');
    for (i = 0; i < 3 * 64; U[i] = K[i++] = 0)
    {
        Q[i] += (i + L % 3) >> 1;
        T[i] =+ '000000000000000000000000000000000000000000000000000000000000000000000000001111000122221001222210012222100122221000111100000000000000000000000000005555000005500000000000055555500055550000055000'.charAt(i) + eval('(i' + '^+|-*&%/'.charAt(L & 7) + '(i>>3))/4&1');
        q[i] = ((b = '5555555520000005500000055000000550000005500000055000000255555555'.charAt(i)) > 1 ? b : Math.random() * 9 > 5 ? Math.random() * 9 > 5 : 9) * 64
    }
    i = 54;
    while (i > 1)
    {
        q[i] = (n = Math.random() * 9 > 5) * 64, i -= (i & 7) - 1 ? (i >> 3) - 1 ? 1 + 7 * n : 1 : 8;
    }
    m = 50;
    L++;
    for (j = 0; j < 6 + L / 2; j += i < 1)
    {
        p = new O(32, 96, 10), E[j] = new O(Math.random() * 512, Math.random() * 512, j < 2 + L  / 6 ? (j < L  / 9 - .5 ? 1 : 0) : (j < 1 + L  / 2 ? 5 : 3));
    }
    p.k = 3;
    N();
    alert('START LEVEL ' + L)
}
// global stuff
H = [];
W = [];
K = [];
U = [];
q = [];
E = [];
T = [];
P = Math.PI;
//    create the markup for the rendering area, the entities & player
for (t = $ = i = j = L = p = m = Q = x = 0; x < 50; x++)
{
    with ((d = document.createElement('div')).style)
    {
        width = 8;
        height = 260;
        left = x * 8
    }
    y = 0;
    while (y < 260)
    {
        with ((H[i] = document.createElement('div')).style)
        {
            width = 8;
            height = 5;
            top = y
        }
        d.appendChild(H[i++]);
        y += 5
    }
    (W[j] = document.createElement('img')).src = 1;
    with (W[j].style)
    {
        width = 128
    }
    d.appendChild(W[j]);
    R.appendChild(d);
    j += 50;
    with ((d = document.createElement('div')).style)
    {
        width = 112;
        height = 143;
        top = 117;
        zIndex = 512;
        left = 143 + x * 512
    }
    (W[j] = document.createElement('img')).src = x ? 0 : 2;
    with (W[j].style)
    {
        width = (x ? 7 : 3) + '00%';
        height = '100%'
    }
    d.appendChild(W[j]);
    R.appendChild(d);
    j -= 49
}
//    init the first level
l();
//    let the be light
setInterval(N, 9)
Have fun.