for(_='=0~16`g(b_50^),ZZ_YY-^X[b]WpW[VV2]U++)Q-1Y+^PRect(OclearNMath.LkWK+=J);Hk[b=(EG-1)/8,F;onkeyD|0)CC+^*(BBrA+1@||&&n[,`4*c.fillO`*",da.height+.5Interval(for(*e)Lrandom()-e/8E3<.0V1]V0]0,=[],function(b){=b.which]= (4,8,8)+.999;c.setTransform(1,1,u--K(vJlW,mW=_)ZC]GStyle="#;if(GAAAAAAC])klmnpE=5,r=3t=u=v~Ddown 1}Dup 0};b~;2E4>b;bQif(d=b%5e=b/^|e>3*Lsin(d/5)+32<.98K=32,lW=4,1K=p.push([d,e,0]))Z0==d49==d0==e399==e)K=1/0;g=d=mW;mW=1;dK(_@YPXY+^@XP-1X@))};g((EACHh=setc.NOa.width,)-`*-r+/2C;b in p)d=,e=,2<eJ(U%2*2FJ(2*(U>>1)Fk[(BC]U=4*|=d,=eZ>E>rE@>r@>alert("dead\\nscore: "+vZNh)Zf00-e-Hd~;^>d;dQe=r-24|0;e<r+24;eQ(b=d+^*e,mW)?K888,lWcc4+e+)):(000H00f";E*rH222";u=`];EJ((68]C-(65]C)/`(E@C-r+,u~ZE=E|0;tJ.0032*(.5>t)-(!t&87].15HrJt(0<t?83]:87])E+(r@C-Zr=r|t~>t?1E-9:00HText(v,220)},20)';g=/[^ -?EIMR-T[-\]a-}]/.exec(_);)with(_.split(g))_=join(shift());eval(_)
// used constants
var WIDTH = 50;
var HEIGHT = 400;
var SCALE = 16;
var MINETIME = 32;
var VIEW_HEIGHT = 24;
var SMALLER_THAN_1 = 0.999;
var MONSTER_SPEED = 1/8;
// used variables
var x, // two local variables
y,
i,
playerCollides, // the functions. declaring them here wil let closure rename them
view,
step,
world = [], // the playfield
worldValues = [], // the score for mining each block
worldVisible = [],
keys = [], // which keys are pressed
monsters = [], // an array of monsters.
// A monster is a length 3 array holding respectively the x position, y position and direction
player_x = 5, // the player position
player_y = 30,
player_dy = 0, // the vertical speed of the player
mining = 0, // whether the player is trying to mine a block
score = 0;
// make an array which stores whether a key is pressed or not
onkeydown = function(e){
keys[e.which] = 1;
};
onkeyup = function(e){
keys[e.which] = 0;
};
// test whether the player collides with any block
// if so, return index of collision location
// this function is not actually used anymore
// it would be nice if the closure compiler had an inline option..
playerCollides = function(i){
return (world[i=(player_x+0.5|0)+(player_y|0)*WIDTH]||
world[i=(player_x+0.5|0)+(player_y+SMALLER_THAN_1|0)*WIDTH]||
world[i=(player_x|0)+(player_y|0)*WIDTH]||
world[i=(player_x+SMALLER_THAN_1|0)+(player_y|0)*WIDTH]||
world[i=(player_x|0)+(player_y+SMALLER_THAN_1|0)*WIDTH]||
world[i=(player_x+SMALLER_THAN_1|0)+(player_y+SMALLER_THAN_1|0)*WIDTH])
&&i
};
// generate the map
(function(){
for (i=0; i<WIDTH*HEIGHT; i++){
x = i%WIDTH,
y = i/WIDTH|0;
// if the block is below a wave function, unless there is some random chance, fill it
if (y > 3*Math.sin(x/5)+32 && Math.random()>0.02){
// let the block take MINETIME steps to mine away
world[i] = MINETIME;
// set a 4% chance that there is gold at that location
worldValues[i] = (Math.random()-y/8000<0.04);
// a small chance of generating a monster, a larger chance when lower
if (Math.random()-y/8000<0.01){
world[i]=0;
monsters.push([x+0.5,y,0]);
}
}
// give the walls (the blocks at the edges of the map) infinite strength
if (x == 0 || x == WIDTH-1 || y == 0 || y == HEIGHT - 1){
world[i] = 1/0;
}
}
})();
// a recursive function that will make anything that is connected to the start index by air visible
// connections can be horizontal, vertical and diagonal
view = function(i){
x = worldVisible[i];
worldVisible[i] = 1;
if (!x && !world[i]){
view(i+1);
view(i-1);
view(i+WIDTH);
view(i-WIDTH);
view(i+ WIDTH+1);
view(i- WIDTH-1);
view(i+ WIDTH-1);
view(i- WIDTH+1);
}
}
// view everything from the player startpoint
view((player_x|0) + (player_y|0) * WIDTH);
// start the main loop
step = setInterval(function(i){
c.clearRect(0,0,a.width,a.height);
c.setTransform(1,0,0,1, -SCALE, -player_y*SCALE+a.height/2|0);
// update and draw the monsters under the fog and rocks
for (i in monsters){
// save the previous location
x = monsters[i][0];
y = monsters[i][1];
if (y>2){
// move in it's own direction
monsters[i][0] += ((monsters[i][2]%2)*2-1)*MONSTER_SPEED;
monsters[i][1] += ((monsters[i][2]>>1)*2-1)*MONSTER_SPEED;
// if a monster collides with a wall, go back to the previous location and choose a random direction
if (world[(monsters[i][0]|0) + (monsters[i][1]|0) * WIDTH]){
monsters[i][2] = Math.random()*4|0;
monsters[i][0] = x;
monsters[i][1] = y;
}
// if a monster collides with the player, the game is over
if (monsters[i][0]>player_x && monsters[i][1]>player_y && player_x + 1 > monsters[i][0] && player_y+1 > monsters[i][1]){
alert("dead\nscore: "+ score);
clearInterval(step);
}
// draw a red monster
c.fillStyle = "#f00";
c.fillRect(SCALE*x-SCALE*0.25, SCALE*y-SCALE*0.25, SCALE/2, SCALE/2);
}
}
// drawing is done first so later the drill can be drawn depending on whether a key is pressed or not
// draw the world
for (x=0; x<WIDTH; x++){
for (y=player_y-VIEW_HEIGHT|0; y<player_y+VIEW_HEIGHT; y++){
i = x +y*WIDTH;
// if there is a block here, draw a gray square
if(!worldVisible[i]){
c.fillStyle = "#000";
c.fillRect(SCALE*x, SCALE*y, SCALE, SCALE);
} else if (world[i]){
c.fillStyle = "#888";
c.fillRect(SCALE*x, SCALE*y, SCALE, SCALE);
// if there is gold here, draw a yellow square in the middle
// console.log(worldValues[i]);
if (worldValues[i]){
//c.fillStyle = (["#888","#aa6","#cc4","#ff2"])[worldValues[i]|0];
c.fillStyle = "#cc4";
c.fillRect(SCALE*x+SCALE*0.25, SCALE*y+SCALE*0.25, SCALE/2, SCALE/2);
}
}
// if this field is not visible, draw a black square over it
}
}
// set the color for drawing the drill
c.fillStyle = "#222";
// store whether the player wants to mine
// if the player does mine horizontally, this variable is set to 0 so the
// player won't mine both horizontally and vertically
mining = keys[16]
// update horizontal player location based on keypress of A and D
player_x += 1/16*((keys[68]|0)-(keys[65]|0));
// if the player collides with a block:
if (
world[i=(player_x+0.5|0)+(player_y|0)*WIDTH]||
world[i=(player_x+0.5|0)+(player_y+SMALLER_THAN_1|0)*WIDTH]||
world[i=(player_x|0)+(player_y|0)*WIDTH]||
world[i=(player_x+SMALLER_THAN_1|0)+(player_y|0)*WIDTH]||
world[i=(player_x|0)+(player_y+SMALLER_THAN_1|0)*WIDTH]||
world[i=(player_x+SMALLER_THAN_1|0)+(player_y+SMALLER_THAN_1|0)*WIDTH]){
// if shift is also pressed:
if (mining){
// lower block strength. if this is 0 the block is mined
if (!--world[i]){
score += worldValues[i];
// update visible blocks
worldVisible[i] = 0;
view(i);
}
// draw the drill
c.fillRect(SCALE*(player_x+1|0)-SCALE*0.25, SCALE*player_y+SCALE*0.25, SCALE*0.5, SCALE*0.5);
// set mining to 0 to avoid mining both horizontally and vertically
mining = 0;
}
// round the x position
player_x = player_x+0.5|0;
}
// update the y velocity: add gravity unless going to fast and jump if pressing W and on ground
player_dy += (player_dy<0.5)*0.0032 - (((!player_dy) & keys[87])&&0.15);
// instead of acutally testing whether the player is on the ground, this test wether y velocity is 0
// maybe the player can also jump again in the top of the jump
// remember to carefully manipulate the gravity and jump force so this isn't possible
// update vertical player location
player_y += player_dy;
// if the player collides with a block:
if (
world[i=(player_x+0.5|0)+(player_y|0)*WIDTH]||
world[i=(player_x+0.5|0)+(player_y+SMALLER_THAN_1|0)*WIDTH]||
world[i=(player_x|0)+(player_y|0)*WIDTH]||
world[i=(player_x+SMALLER_THAN_1|0)+(player_y|0)*WIDTH]||
world[i=(player_x|0)+(player_y+SMALLER_THAN_1|0)*WIDTH]||
world[i=(player_x+SMALLER_THAN_1|0)+(player_y+SMALLER_THAN_1|0)*WIDTH]){
// if shift and S or W are pressed:
if ((player_dy>0 ? keys[83] : keys[87]) && mining){
// lower block strenght. if this is 0 the block is mined
if (!--world[i]){
score += worldValues[i];
// update visible blocks
worldVisible[i] = 0;
view(i);
}
// draw the drill
c.fillRect(SCALE*player_x+SCALE*0.25, SCALE*(player_y+1|0)-SCALE*0.25, SCALE*0.5, SCALE*0.5);
}
// round the y position
player_y = player_y+0.5|0;
// set the y velocity to either 0 or a very small value once colliding
// this way, a y velocity of 0 indicates that the player is on the ground
player_dy = player_dy<0? 1e-9 : 0;
}
// draw the player
c.fillStyle = "#00f";
c.fillRect(SCALE*player_x, SCALE*player_y, SCALE, 1*SCALE);
// reset the transformation for drawing the score and clearing the screen
c.setTransform(1,0,0,1,0,0);
// draw the score, over everything else
c.fillText(score, 20 ,20);
}, 20);