service/games/13/3dfps.js
soafen e364b9143f wiinet is ready™️
hopefully, after over a year of development, it will have been worth the wait
2022-09-09 23:24:33 +02:00

192 lines
No EOL
7.7 KiB
JavaScript

//////////////////////////////////////////////////////////////////////////////
// //
// 3DS Browser SDK - Raycasting Class v1.8.11 2011-07-20 //
// (c) 2007-2011 Daniel Gump. All Rights Reserved. //
// http://3dspaint.com //
// hullbreach@hullbreachonline.com //
// //
// Nintendo 3DS is a trademark of Nintendo Co., Ltd. This software //
// package is not associated with Nintendo but was created to support //
// their products //
// //
// Redistribution and use in source and binary forms, with or without //
// modification, are permitted provided that the following conditions //
// are met: //
// * Redistributions of source code must retain the above copyright //
// notice, this list of conditions and the following disclaimer. //
// * Redistributions in binary form must reproduce the above copyright //
// notice, this list of conditions and the following disclaimer in //
// the documentation and/or other materials provided with the //
// distribution. //
// * Neither this software nor the names of contributors may be used to //
// endorse or promote products derived from this software without //
// specific prior written permission. //
// * If the explicit purpose of the software is not to support the //
// Nintendo 3DS Internet browser, then the names of such must //
// not be used in any derived product. The name shall be the //
// HULLBREACH LITE SDK with a reference link to //
// http://hullbreachonline. //
// //
// THIS SOFTWARE IS PROVIDED BY Daniel Gump ''AS IS'' AND ANY EXPRESS OR //
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED //
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE //
// DISCLAIMED. IN NO EVENT SHALL Daniel Gump BE LIABLE FOR ANY DIRECT, //
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR //
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) //
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, //
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING //
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //
// POSSIBILITY OF SUCH DAMAGE. //
//////////////////////////////////////////////////////////////////////////////
function RayCast(){
//Canvas size
WIDTH=312; HEIGHT=205;
//Player's coordinates
X=1.5; Y=1.5;
U=0; V=1;
PLANEU=1; PLANEV=0;
ANGLE=0;
ROTATESPEED=.2; MOVESPEED=.2;
WALLSCENE=[]; TEXTURES=[]; TELEPORTS=[];
CANVAS=null;
SKYFILL='rgb(0,0,0)'; GROUNDFILL='rgb(0,0,0)';
SKYIMAGE = 0;
COLLISION=0;
}
RayCast.prototype.generateScene = function(){
CANVAS.fillStyle=SKYFILL;
CANVAS.fillRect(0,0, WIDTH,HEIGHT>>1);
CANVAS.fillStyle=GROUNDFILL;
CANVAS.fillRect(0,HEIGHT>>1, WIDTH,HEIGHT);
if(SKYIMAGE){
CANVAS.drawImage(TEXTURES[SKYIMAGE], -ANGLE*WIDTH/(2*Math.PI),-20);
CANVAS.drawImage(TEXTURES[SKYIMAGE], (2*Math.PI-ANGLE)*WIDTH/(2*Math.PI),-20);
}
//Player location
var rayX=X, rayY=Y;
//Ray length data
var sideDistX, sideDistY;
//Stepping data
var stepX, stepY;
var side, hit;
for(var column=WIDTH, camerastep = 2/WIDTH; column>=0; column-=6){
//Ray length
var deltaDistX = Math.sqrt(1+((rayV=V+PLANEV*(cameraX = column*camerastep-1))*rayV)/((rayU=U+PLANEU*cameraX)*rayU));
var deltaDistY = Math.sqrt(1+(rayU*rayU)/(rayV*rayV));
//Find initial side dist
stepX = stepY = -1;
sideDistX = rayX-(mapX=X|0);
sideDistY = rayY-(mapY=Y|0);
if(rayU>=0){
stepX = 1;
sideDistX = 1-sideDistX;
}
if(rayV>=0){
stepY = 1;
sideDistY = 1-sideDistY;
}
sideDistX*=deltaDistX;
sideDistY*=deltaDistY;
//Step DDA
do{
if(sideDistX<sideDistY){
sideDistX+=deltaDistX;
mapX+=stepX;
side=0;
}else{
sideDistY+=deltaDistY;
mapY+=stepY;
side=1;
}
}while(!(hit=WALLSCENE[mapX][mapY]));
var drawStart = ((HEIGHT-(lineHeight=HEIGHT/((perpWallDist=(!side)?(mapX-rayX+(1-stepX)*.5)/rayU:(mapY-rayY+(1-stepY)*.5)/rayV)>>31?-perpWallDist:perpWallDist)))>>1)+(walkBounce=HEIGHT/(10*perpWallDist));
var drawEnd = ((lineHeight+HEIGHT)>>1)-drawStart;
var wallX = side?rayX+perpWallDist*rayU:rayY+perpWallDist*rayV;
var texX = ((wallX-(wallX|0))*(texture=TEXTURES[WALLSCENE[mapX][mapY]]).width)|0;
if((!side && rayU>0) || (side && rayV<0)) texX = texture.width-texX-1;
CANVAS.drawImage(texture, texX,0, 1,texture.height, column,drawStart, 6,drawEnd);
}
}
RayCast.prototype.loadScene = function(array){
if(WALLSCENE = array.split(';')) for (i=WALLSCENE.length;--i>=0;) WALLSCENE[i] = WALLSCENE[i].split(',');
}
RayCast.prototype.moveForward = function(){
COLLISION=1;
if(!WALLSCENE[(X+U*MOVESPEED)|0][Y|0]){
X+=U*MOVESPEED;
COLLISION=0;
}
if(!WALLSCENE[X|0][(Y+V*MOVESPEED)|0]){
Y+=V*MOVESPEED;
COLLISION=0;
}
}
RayCast.prototype.moveBackward = function(){
COLLISION=1;
if(!WALLSCENE[(X-U*MOVESPEED)|0][Y|0]){
X-=U*MOVESPEED;
COLLISION=0;
}
if(!WALLSCENE[X|0][(Y-V*MOVESPEED)|0]){
Y-=V*MOVESPEED;
COLLISION=0;
}
}
RayCast.prototype.moveLeft = function(){
COLLISION=1;
if(!WALLSCENE[(X-V*MOVESPEED)|0][Y|0]){
X-=V*MOVESPEED;
COLLISION=0;
}
if(!WALLSCENE[X|0][(Y+U*MOVESPEED)|0]){
Y+=U*MOVESPEED;
COLLISION=0;
}
}
RayCast.prototype.moveRight = function(){
COLLISION=1;
if(!WALLSCENE[(X+V*MOVESPEED)|0][Y|0]){
X+=V*MOVESPEED;
COLLISION=0;
}
if(!WALLSCENE[X|0][(Y-U*MOVESPEED)|0]){
Y-=U*MOVESPEED;
COLLISION=0;
}
}
RayCast.prototype.checkTeleports = function(){
for(tele=TELEPORTS.length;--tele>=0;){
if(TELEPORTS[tele][0]==.5+(Y|0) && TELEPORTS[tele][1]==.5+(X|0)){
if(TELEPORTS[tele][4]) document.location.href = TELEPORTS[tele][4];
Y = TELEPORTS[tele][2];
X = TELEPORTS[tele][3];
}
}
}
RayCast.prototype.isCollided = function(){ return COLLISION; }
RayCast.prototype.setAltitude = function(alt){ ALTITUDE=alt>=-5*HEIGHT?(alt<=5*HEIGHT?alt:5*HEIGHT):-5*HEIGHT; }
RayCast.prototype.setDirection = function(angle){
U = Math.sin(ANGLE=angle*0.0174533);
V = Math.cos(ANGLE);
PLANEU = Math.sin(ANGLE+1.5707963);
PLANEV = Math.cos(ANGLE+1.5707963);
}
RayCast.prototype.setGroundColor = function(r,g,b){ GROUNDFILL="rgb("+(r<0?0:(r>255?255:r|0))+","+(g<0?0:(g>255?255:g|0))+","+(b<0?0:(b>255?255:b|0))+")"; }
RayCast.prototype.setLocation = function(x,y){ X=y; Y=x; }
RayCast.prototype.setSize = function(w,h){ WIDTH=w; HEIGHT=h; }
RayCast.prototype.setSkyColor = function(r,g,b){ SKYFILL="rgb("+(r<0?0:(r>255?255:r|0))+","+(g<0?0:(g>255?255:g|0))+","+(b<0?0:(b>255?255:b|0))+")"; }
RayCast.prototype.setTeleports = function(teleports){ TELEPORTS=teleports; }
RayCast.prototype.setTextures = function(textures){ TEXTURES=textures; }
RayCast.prototype.setWalls = function(Walls){ WALLSCENE = Walls; }
RayCast.prototype.initialize = function(canvas){ CANVAS = canvas.getContext("2d"); }
RayCast.prototype.setSkyImage = function(img){ SKYIMAGE=img; }
RayCaster = new RayCast();