Author Topic: 3D TOMB II : a DOOM-like in 4k of JavaScript  (Read 5541 times)

0 Members and 1 Guest are viewing this topic.

Offline p01

  • Atari ST
  • ***
  • Posts: 158
  • Karma: 51
    • View Profile
    • www.p01.org
The time has come to, finally, release 3D TOMB II, 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:

 


/!\ 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.

Offline Yaloopy

  • Death From Above
  • DBF Aficionado
  • ******
  • Posts: 2869
  • Karma: 35
    • View Profile
    • UltraPaste
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #1 on: July 02, 2007 »
That's pretty damn cool :) Shame about it not working in FF
Fuck L. Ron Hubbard and fuck all his clones.
Challenge Trophies Won:

Offline Rbz

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 2723
  • Karma: 485
    • View Profile
    • http://www.rbraz.com/
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #2 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...



Challenge Trophies Won:

Offline mike_g

  • Amiga 1200
  • ****
  • Posts: 435
  • Karma: 34
    • View Profile
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #3 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 :)

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #4 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
Challenge Trophies Won:

Offline benny!

  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4380
  • Karma: 228
  • in this place forever!
    • View Profile
    • bennyschuetz.com - mycroBlog
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #5 on: July 02, 2007 »
@p01:

Awesome, p01. Very well done !!!
[ mycroBLOG - POUET :: whatever keeps us longing - for another breath of air - is getting rare ]

Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1667
  • Karma: 133
    • View Profile
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #6 on: July 02, 2007 »
very cool :)
Challenge Trophies Won:

Offline Tetra

  • DBF Aficionado
  • ******
  • Posts: 2532
  • Karma: 83
  • Pirate Monkey!
    • View Profile
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #7 on: July 02, 2007 »
Very nice, and works pretty fast too :)
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17378
  • Karma: 497
  • evil/good
    • View Profile
    • My Homepage
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #8 on: July 02, 2007 »
Good work :) Heck of a programming exercise to get this game so tiny.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline p01

  • Atari ST
  • ***
  • Posts: 158
  • Karma: 51
    • View Profile
    • www.p01.org
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #9 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.
« Last Edit: July 02, 2007 by p01 »

Offline p01

  • Atari ST
  • ***
  • Posts: 158
  • Karma: 51
    • View Profile
    • www.p01.org
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #10 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.

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17378
  • Karma: 497
  • evil/good
    • View Profile
    • My Homepage
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #11 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.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #12 on: July 03, 2007 »
:P  Don't get me wrong, I thought it was great!

Jim
Challenge Trophies Won:

Offline p01

  • Atari ST
  • ***
  • Posts: 158
  • Karma: 51
    • View Profile
    • www.p01.org
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #13 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.

Offline DrewPee

  • I Toast Therefore I am
  • Pentium
  • *****
  • Posts: 563
  • Karma: 25
  • Eat Cheese - It's good for you!
    • View Profile
    • Retro Computer Museum
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #14 on: July 04, 2007 »
@p01 - played the game last nite - well done matey - that is some cool code you have there - karma+

Drew
DrewPee
aka Falcon of The Lost Boyz (Amiga)
Ex-Amiga Coder and Graphic Designer
Administrator of > www.retrocomputermuseum.co.uk

Offline Xone

  • C= 64
  • **
  • Posts: 79
  • Karma: 10
    • View Profile
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #15 on: March 20, 2008 »
karma applied, nice one  :)

Offline mazemaker

  • C= 64
  • **
  • Posts: 28
  • Karma: 11
    • View Profile
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #16 on: August 26, 2008 »
is there a non-obsfucated version of the source code?

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17378
  • Karma: 497
  • evil/good
    • View Profile
    • My Homepage
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #17 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..
Shockwave ^ Codigos
Challenge Trophies Won:

Offline p01

  • Atari ST
  • ***
  • Posts: 158
  • Karma: 51
    • View Profile
    • www.p01.org
Re: 3D TOMB II : a DOOM-like in 4k of JavaScript
« Reply #18 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.