Dark Bit Factory & Gravity
ARCHIVE => Archive => Java,JS & Flash => Topic started 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.
-
That's pretty damn cool :) Shame about it not working in FF
-
Yeah, very nice work!
I just miss some sound effects, but I know that there's no free bytes for this...
-
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 :)
-
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
-
@p01:
Awesome, p01. Very well done !!!
-
very cool :)
-
Very nice, and works pretty fast too :)
-
Good work :) Heck of a programming exercise to get this game so tiny.
-
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.
-
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.
-
: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.
-
:P Don't get me wrong, I thought it was great!
Jim
-
I don't, don't worry. You're far from being the 1st one mentionning the idea of a bigger version.
-
@p01 - played the game last nite - well done matey - that is some cool code you have there - karma+
Drew
-
karma applied, nice one :)
-
is there a non-obsfucated version of the source code?
-
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: 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:// 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.