Merge pull request #5 from riperiperi/gh-pages
Particle Effects, Loop/Sticky collision types
This commit is contained in:
19 files changed
+6575
-3152
No files matched your search
@@ -42,7 +42,14 @@ window.cameraIngame = function(kart) {
|
||||
camNormal[2] += (kart.kartNormal[2]-camNormal[2])*0.075;
|
||||
vec3.normalize(camNormal, camNormal);
|
||||
|
||||
camAngle += dirDiff(kart.physicalDir+kart.driftOff/2, camAngle)*0.075;
|
||||
if (kart.physBasis != null) {
|
||||
var kartA = kart.physicalDir+kart.driftOff/2;
|
||||
var forward = [Math.sin(kartA), 0, -Math.cos(kartA)];
|
||||
vec3.transformMat4(forward, forward, kart.physBasis.mat);
|
||||
camAngle += dirDiff(Math.atan2(forward[0], -forward[2]), camAngle)*0.075;
|
||||
} else {
|
||||
camAngle += dirDiff(kart.physicalDir+kart.driftOff/2, camAngle)*0.075;
|
||||
}
|
||||
camAngle = fixDir(camAngle);
|
||||
|
||||
boostOff += (((kart.boostNorm+kart.boostMT > 0)?5:0) - boostOff)*0.075
|
||||
@@ -52,14 +59,23 @@ window.cameraIngame = function(kart) {
|
||||
var dist = 192;
|
||||
this.targetShadowPos = vec3.add([], kart.pos, [Math.sin(kart.angle)*dist, 0, -Math.cos(kart.angle)*dist])
|
||||
|
||||
thisObj.view = {p:p, mv:mat};
|
||||
thisObj.view = {p:p, mv:mat, pos: vec3.scale([], vec3.transformMat4([], [0,0,0], mat4.invert([], mat)), 1024)};
|
||||
|
||||
return thisObj.view;
|
||||
}
|
||||
|
||||
function buildBasis() {
|
||||
//order y, x, z
|
||||
var basis = gramShmidt(camNormal, [Math.cos(camAngle), 0, Math.sin(camAngle)], [Math.sin(camAngle), 0, -Math.cos(camAngle)]);
|
||||
var kart = thisObj.kart;
|
||||
var forward = [Math.sin(camAngle), 0, -Math.cos(camAngle)];
|
||||
var side = [Math.cos(camAngle), 0, Math.sin(camAngle)];
|
||||
/*
|
||||
if (kart.physBasis != null) {
|
||||
vec3.transformMat4(forward, forward, kart.physBasis.mat);
|
||||
vec3.transformMat4(side, side, kart.physBasis.mat);
|
||||
}
|
||||
*/
|
||||
var basis = gramShmidt(camNormal, side, forward);
|
||||
var temp = basis[0];
|
||||
basis[0] = basis[1];
|
||||
basis[1] = temp; //todo: cleanup
|
||||
|
||||
@@ -102,7 +102,7 @@ window.cameraIntro = function() {
|
||||
|
||||
thisObj.targetShadowPos = lookAtPos;
|
||||
|
||||
return {p:p, mv:mat}
|
||||
return {p:p, mv:mat, pos: vec3.scale([], vec3.transformMat4([], [0,0,0], mat4.invert([], mat)), 1024)}
|
||||
}
|
||||
|
||||
var initCam = function(scene, came) {
|
||||
|
||||
@@ -55,6 +55,7 @@ window.cameraSpectator = function(kart) {
|
||||
if (zoomLevel > curCam.zoomEnd) zoomLevel = curCam.zoomEnd;
|
||||
|
||||
thisObj.view = camFunc[curCam.camType](scene, curCam);
|
||||
thisObj.view.pos = vec3.scale([], vec3.transformMat4([], [0,0,0], mat4.invert([], thisObj.view.mv)), 1024)
|
||||
return thisObj.view;
|
||||
}
|
||||
|
||||
|
||||
@@ -141,8 +141,10 @@ window.MKDS_COLTYPE = new (function(){
|
||||
this.PHYS_MAP[this.LOOP] = 11;
|
||||
|
||||
//collision sound handlers
|
||||
//26 is blue water, 30 is white
|
||||
//28 and 15 might be sand/dirt
|
||||
|
||||
var waterRoad = {drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATER, drive: MKDS_COLSOUNDS.DRIVE_WATER};
|
||||
var waterRoad = {drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATER, drive: MKDS_COLSOUNDS.DRIVE_WATER, particle: 30};
|
||||
|
||||
this.SOUNDMAP = {
|
||||
0x00: //road
|
||||
@@ -164,7 +166,7 @@ window.MKDS_COLTYPE = new (function(){
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATERDEEP, drive: MKDS_COLSOUNDS.DRIVE_WATER},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_WATER, brake: MKDS_COLSOUNDS.BRAKE_WATER, land: MKDS_COLSOUNDS.LAND_WATERDEEP, drive: MKDS_COLSOUNDS.DRIVE_WATER, particle: 30},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_ASPHALT},
|
||||
{},
|
||||
{},
|
||||
@@ -187,27 +189,27 @@ window.MKDS_COLTYPE = new (function(){
|
||||
|
||||
0x03: //road 4
|
||||
[
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT, particle: 15},
|
||||
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS, particle: 32},
|
||||
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_SNOW}, //snow
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_SNOW, particle:112}, //snow
|
||||
{},
|
||||
{}
|
||||
],
|
||||
|
||||
0x05: //road 5
|
||||
[
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND , land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_DIRT, brake: MKDS_COLSOUNDS.BRAKE_DIRT, land: MKDS_COLSOUNDS.LAND_DIRT, drive: MKDS_COLSOUNDS.DRIVE_DIRT, particle: 15},
|
||||
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS, particle: 32},
|
||||
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_SAND, brake: MKDS_COLSOUNDS.BRAKE_SAND, land: MKDS_COLSOUNDS.LAND_SAND, drive: MKDS_COLSOUNDS.DRIVE_SAND, particle: 28},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ASPHALT, brake: MKDS_COLSOUNDS.BRAKE, land: MKDS_COLSOUNDS.LAND_GRASS, drive: MKDS_COLSOUNDS.DRIVE_GRASS, particle: 32},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
@@ -216,7 +218,7 @@ window.MKDS_COLTYPE = new (function(){
|
||||
0x06: //slippery
|
||||
[
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_ICE, brake: MKDS_COLSOUNDS.BRAKE_ICE, land:MKDS_COLSOUNDS.LAND_ICE},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_MARSH, brake: MKDS_COLSOUNDS.BRAKE_MARSH, land:MKDS_COLSOUNDS.LAND_MARSH, drive: MKDS_COLSOUNDS.DRIVE_MARSH},
|
||||
{drift: MKDS_COLSOUNDS.DRIFT_MARSH, brake: MKDS_COLSOUNDS.BRAKE_MARSH, land:MKDS_COLSOUNDS.LAND_MARSH, drive: MKDS_COLSOUNDS.DRIVE_MARSH, particle: 24},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -19,6 +19,7 @@ window.controlRaceCPU = function(nkm) {
|
||||
}
|
||||
|
||||
this.fetchInput = fetchInput;
|
||||
this.setRouteID = setRouteID;
|
||||
|
||||
var battleMode = (nkm.sections["EPAT"] == null);
|
||||
|
||||
@@ -53,11 +54,30 @@ window.controlRaceCPU = function(nkm) {
|
||||
|
||||
var dist = vec3.dot(destNorm, kart.pos) + destConst;
|
||||
if (dist < ePoi.pointSize) advancePoint();
|
||||
if (ePath.loop) debugger;
|
||||
|
||||
destPoint = vec3.add([], ePoi.pos, vec3.scale([], vec3.lerp([], posOffset, destOff, offTrans), ePoi.pointSize));
|
||||
var dirToPt = Math.atan2(destPoint[0]-kart.pos[0], kart.pos[2]-destPoint[2]);
|
||||
|
||||
var diff = dirDiff(dirToPt, kart.physicalDir);
|
||||
var physDir = kart.physicalDir;
|
||||
if (kart.physBasis) {
|
||||
if (kart.physBasis.loop) {
|
||||
return {
|
||||
accel: true, //x
|
||||
decel: false, //z
|
||||
drift: false, //s
|
||||
item: false, //a
|
||||
|
||||
//-1 to 1, intensity.
|
||||
turn: 0,
|
||||
airTurn: 0 //air excitebike turn, doesn't really have much function
|
||||
};
|
||||
}
|
||||
var forward = [Math.sin(physDir), 0, -Math.cos(physDir)];
|
||||
vec3.transformMat4(forward, forward, kart.physBasis.mat);
|
||||
var physDir = Math.atan2(forward[0], -forward[2]);
|
||||
}
|
||||
var diff = dirDiff(dirToPt, physDir);
|
||||
var turn = Math.min(Math.max(-1, (diff*3)), 1);
|
||||
|
||||
offTrans += 1/240;
|
||||
@@ -94,6 +114,11 @@ window.controlRaceCPU = function(nkm) {
|
||||
|
||||
}
|
||||
|
||||
function setRouteID(routeID) {
|
||||
ePoiInd = routeID-1
|
||||
advancePoint();
|
||||
}
|
||||
|
||||
function advancePoint() {
|
||||
if (++ePoiInd < ePath.startInd+ePath.pathLen) {
|
||||
//next within this path
|
||||
@@ -102,10 +127,14 @@ window.controlRaceCPU = function(nkm) {
|
||||
//advance to one of next possible paths
|
||||
|
||||
if (battleMode) {
|
||||
var pathInd = ((Math.random()>0.5 && ePath.source.length>0)?ePath.source:ePath.dest)[Math.floor(Math.random()*ePath.dest.length)];
|
||||
var loc = (Math.random()>0.5 && ePath.source.length>0)?ePath.source:ePath.dest;
|
||||
var pathInd = loc[Math.floor(Math.random()*loc.length)];
|
||||
ePoiInd = pathInd;
|
||||
ePoi = points[ePoiInd];
|
||||
recomputePath();
|
||||
var pt = points[ePoiInd];
|
||||
if (pt != null) {
|
||||
ePoi = pt;
|
||||
recomputePath();
|
||||
}
|
||||
} else {
|
||||
var pathInd = ePath.dest[Math.floor(Math.random()*ePath.dest.length)];
|
||||
ePath = paths[pathInd];
|
||||
|
||||
@@ -18,6 +18,7 @@ window.IngameRes = function(rom) {
|
||||
|
||||
this.Race = new narc(lz77.decompress(rom.getFile("/data/Scene/Race.carc"))); //contains lakitu, count, various graphics
|
||||
this.RaceLoc = new narc(lz77.decompress(rom.getFile("/data/Scene/Race_us.carc"))); //contains lakitu lap signs, START, YOU WIN etc. some of these will be replaced by hi res graphics by default.
|
||||
this.RaceEffect = new spa(r.MainEffect.getFile("RaceEffect.spa"));
|
||||
|
||||
this.MainFont = new nftr(r.Main2D.getFile("marioFont.NFTR"));
|
||||
//debugger;
|
||||
@@ -30,20 +31,25 @@ window.IngameRes = function(rom) {
|
||||
"koura_w" /*blue shell item rep*/, "f_box", "killer" /*bullet bill*/
|
||||
]
|
||||
|
||||
//order
|
||||
//donkey, toad, bowser?, luigi, mario, peach, wario, yoshi, daisy, waluigi, dry bones (karon), robo, heyho
|
||||
var toSoundOff = [
|
||||
4, 0, 1, 2, 5, 6, 7, 3, 10, 8, 9, 11, 12
|
||||
];
|
||||
|
||||
var charNames = [
|
||||
"mario", "donkey", "kinopio", "koopa", "peach", "wario", "yoshi", "luigi", "karon", "daisy", "waluigi", "robo", "heyho"
|
||||
]
|
||||
];
|
||||
|
||||
var charAbbrv = [
|
||||
"MR", "DK", "KO", "KP", "PC", "WR", "YS", "LG", "KA", "DS", "WL", "RB", "HH"
|
||||
]
|
||||
];
|
||||
|
||||
var tireName = ["kart_tire_L", "kart_tire_M", "kart_tire_S"];
|
||||
|
||||
var characters = [];
|
||||
var karts = [];
|
||||
|
||||
var test = new spa(r.MainEffect.getFile("RaceEffect.spa"));
|
||||
loadItems();
|
||||
loadTires();
|
||||
|
||||
@@ -75,6 +81,7 @@ window.IngameRes = function(rom) {
|
||||
loseA: new nsbca(r.KartModelSub.getFile(base+"_lose.nsbca")),
|
||||
spinA: new nsbca(r.KartModelSub.getFile(base+"_spin.nsbca")),
|
||||
winA: new nsbca(r.KartModelSub.getFile(base+"_win.nsbca")),
|
||||
sndOff: toSoundOff[ind]*14,
|
||||
}
|
||||
characters[ind] = obj;
|
||||
return characters[ind];
|
||||
|
||||
@@ -165,6 +165,11 @@ window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes)
|
||||
vec3.scale(targ, targ, 1/1024);
|
||||
mat4.mul(scn.shadMat, mat4.ortho(mat4.create(), targ[0]-shadres, targ[0]+shadres, targ[1]-shadres, targ[1]+shadres, -targ[2]-2.5, -targ[2]+2.5), scn.lightMat);
|
||||
|
||||
var places = [];
|
||||
for (var i=0; i<scn.karts.length; i++) { places.push(scn.karts[i]); }
|
||||
places.sort(function(a, b) {return b.getPosition() - a.getPosition()});
|
||||
for (var i=0; i<places.length; i++) { places[i].placement = i+1; };
|
||||
|
||||
for (var i=0; i<scn.karts.length; i++) {
|
||||
var ent = scn.karts[i];
|
||||
if (ent.active) ent.update(scn);
|
||||
@@ -291,9 +296,9 @@ window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes)
|
||||
// the thresholds for different win sounds and music
|
||||
// thresh, goalsound, goalmusic, goalpostmusic
|
||||
var finishPercents = [
|
||||
[0, 66, 46, 58],
|
||||
[0.5, 66, 47, 56],
|
||||
[1.1, 67, 48, 57]
|
||||
[0, 66, 46, 58, 9],
|
||||
[0.5, 66, 47, 56, 10],
|
||||
[1.1, 67, 48, 57, 11]
|
||||
]
|
||||
|
||||
function lapAdvance(kart) {
|
||||
@@ -309,20 +314,21 @@ window.courseScene = function(mainNarc, texNarc, music, chars, options, gameRes)
|
||||
else if (kart.lapNumber == 4) {
|
||||
var finishTuple = [];
|
||||
for (var i=0; i<finishPercents.length; i++) {
|
||||
if (finishPercents[i][0] > winPercent) continue;
|
||||
finishTuple = finishPercents[i];
|
||||
if (finishPercents[i][0] >= winPercent) break;
|
||||
}
|
||||
|
||||
kart.controller = new controlRaceCPU(scn.nkm, {});
|
||||
kart.controller.setKart(kart);
|
||||
|
||||
kart.anim.setAnim(winPercent>0.5?kart.charRes.LoseA:kart.charRes.winA);
|
||||
kart.anim.setAnim(winPercent>0.5?kart.charRes.loseA:kart.charRes.winA);
|
||||
kart.animMode = "raceEnd";
|
||||
|
||||
scn.camera = (new cameraSpectator(kart, scn));
|
||||
nitroAudio.playSound(finishTuple[1], {volume:2}, 0);
|
||||
nitroAudio.playSound(finishTuple[2], {volume:2}, null);
|
||||
nitroAudio.instaKill(scn.musicPlayer);
|
||||
kart.playCharacterSound(finishTuple[4], 2);
|
||||
musicRestartTimer = 0;
|
||||
musicRestart = 7.5*60;
|
||||
musicRestartType = 1;
|
||||
|
||||
@@ -179,7 +179,7 @@ window.ObjDecor = function(obji, scene) {
|
||||
forceBill = false;
|
||||
return {mdl:[{nsbmd:"choropu.nsbmd"}], other:[null, null, "choropu.nsbtp"]}; //has nsbtp
|
||||
case 0x019B: //cheep cheep (bouncing)
|
||||
return {mdl:[{nsbmd:"pukupuku.nsbmd"}], other:[null, null, "pukupuku.nsbtp"]}; //has nsbtp
|
||||
return {mdl:[{nsbmd:"pukupuku.nsbmd"}]}; //has nsbtp //, other:[null, null, "pukupuku.nsbtp"]
|
||||
case 0x019D: //snowman
|
||||
return {mdl:[{nsbmd:"sman_top.nsbmd"}, {nsbmd:"sman_bottom.nsbmd"}]};
|
||||
case 0x019E: //trunk with bats
|
||||
|
||||
@@ -45,6 +45,7 @@ window.ItemBox = function(obji, scene) {
|
||||
for (var j=0; j<10; j++) {
|
||||
scene.particles.push(new ItemShard(scene, ok, res.mdl[2]));
|
||||
}
|
||||
scene.particles.push(new NitroEmitter(scene, ok, 47));
|
||||
t.mode = 1;
|
||||
t.time = 0;
|
||||
break;
|
||||
|
||||
+266
-31
@@ -21,6 +21,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
|
||||
var params = scene.gameRes.kartPhys.karts[kartN];
|
||||
var offsets = scene.gameRes.kartOff.karts[kartN];
|
||||
this.wheelClass = (offsets.name[10] == "L")?2:((offsets.name[10] == "M")?1:0);
|
||||
|
||||
this.local = controller.local;
|
||||
this.active = true;
|
||||
@@ -66,12 +67,20 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
this.drawWheels = drawWheels;
|
||||
this.drawChar = drawChar;
|
||||
|
||||
this.getPosition = getPosition;
|
||||
this.playCharacterSound = playCharacterSound;
|
||||
|
||||
this.trackAttach = null; //a normal for the kart to attach to (loop)
|
||||
this.boostMT = 0;
|
||||
this.boostNorm = 0;
|
||||
|
||||
this.kartColVel = vec3.create();
|
||||
this.kartColTimer = 0;
|
||||
this.kartWallTimer = 0;
|
||||
this.charSoundTimer = 0;
|
||||
|
||||
this.placement = 0;
|
||||
this.lastPlacement = 0;
|
||||
|
||||
var charRes = scene.gameRes.getChar(charN);
|
||||
var kartRes = scene.gameRes.getKart(kartN);
|
||||
@@ -95,14 +104,24 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
this.lastInput = null;
|
||||
|
||||
//race statistics
|
||||
this.lapNumber = 0;
|
||||
this.lapNumber = 1;
|
||||
this.passedKTP2 = false;
|
||||
this.checkPointNumber = 0;
|
||||
this.OOB = 0;
|
||||
|
||||
this.wheelParticles = [
|
||||
new NitroEmitter(scene, k, -1, [1, 1.5, -1]),
|
||||
new NitroEmitter(scene, k, -1, [-1, 1.5, -1])
|
||||
];
|
||||
|
||||
scene.particles.push(this.wheelParticles[0]);
|
||||
scene.particles.push(this.wheelParticles[1]);
|
||||
|
||||
var nkm = scene.nkm;
|
||||
var startLine = nkm.sections["KTPS"].entries[0];
|
||||
var passLine = nkm.sections["KTP2"].entries[0];
|
||||
var checkpoints = nkm.sections["CPOI"].entries;
|
||||
var respawns = nkm.sections["CPOI"].entries;
|
||||
var respawns = nkm.sections["KTPJ"].entries;
|
||||
var futureChecks = [1];
|
||||
|
||||
var hitGroundAnim = [ //length 13, on y axis
|
||||
@@ -193,6 +212,10 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
mat4.scale(wmat, wmat, [scale, scale, scale]);
|
||||
if (i<2) mat4.rotateY(wmat, wmat, ((k.driveAnimF-14)/14)*Math.PI/6);
|
||||
mat4.rotateX(wmat, wmat, wheelTurn);
|
||||
|
||||
if (i>1) {
|
||||
k.wheelParticles[i-2].offset = vec3.scale(k.wheelParticles[i-2].offset, vec3.add(k.wheelParticles[i-2].offset, offsets.wheels[i], [k.wheelClass*(i-2.5)*-2, (-params.colRadius)-k.wheelClass*2, 0]), 1/16);
|
||||
}
|
||||
}
|
||||
|
||||
var scale = 16;
|
||||
@@ -262,7 +285,20 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
drawChar(view, pMatrix);
|
||||
}
|
||||
|
||||
|
||||
k.lWheelParticle = null;
|
||||
|
||||
function update(scene) {
|
||||
if (k.placement != k.lastPlacement) {
|
||||
if (k.placement < k.lastPlacement) {
|
||||
if (k.charSoundTimer == 0) {
|
||||
playCharacterSound(5);
|
||||
k.charSoundTimer = 60;
|
||||
}
|
||||
}
|
||||
k.lastPlacement = k.placement;
|
||||
}
|
||||
|
||||
var lastPos = vec3.clone(k.pos);
|
||||
updateMat = true;
|
||||
|
||||
@@ -314,7 +350,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
sounds.boost = null;
|
||||
}
|
||||
|
||||
if (onGround && k.speed > 0.5) {
|
||||
var isMoving = onGround && k.speed > 0.5;
|
||||
if (isMoving) {
|
||||
if (lastCollided != sounds.lastTerrain || lastBE != sounds.lastBE || sounds.drive == null) {
|
||||
if (sounds.drive != null) nitroAudio.kill(sounds.drive);
|
||||
if (lastColSounds.drive != null) {
|
||||
@@ -337,7 +374,10 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
} else {
|
||||
if (sounds.drift != null) { nitroAudio.kill(sounds.drift); sounds.drift = null; }
|
||||
if (sounds.drive != null) { nitroAudio.kill(sounds.drive); sounds.drive = null; }
|
||||
|
||||
}
|
||||
k.wheelParticles[0].pause = !isMoving;
|
||||
k.wheelParticles[1].pause = !isMoving;
|
||||
|
||||
//end sound update
|
||||
|
||||
@@ -346,25 +386,55 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
} else if (k.cannon != null) { //when cannon is active, we fly forward at max move speed until we get to the cannon point.
|
||||
var c = scene.nkm.sections["KTPC"].entries[k.cannon];
|
||||
|
||||
var mat = mat4.create();
|
||||
mat4.rotateY(mat, mat, c.angle[1]*(Math.PI/180));
|
||||
mat4.rotateX(mat, mat, c.angle[0]*(-Math.PI/180));
|
||||
if (c.id2 != 0) {
|
||||
var c2 = scene.nkm.sections["KTPC"].entries[c.id2];
|
||||
c = c2;
|
||||
|
||||
var forward = [0, 0, 1];
|
||||
var up = [0, 1, 0];
|
||||
var mat = mat4.create();
|
||||
mat4.rotateY(mat, mat, c.angle[1]*(Math.PI/180));
|
||||
mat4.rotateX(mat, mat, c.angle[0]*(-Math.PI/180));
|
||||
|
||||
k.vel = vec3.scale([], vec3.transformMat4(forward, forward, mat), MAXSPEED);
|
||||
k.speed = MAXSPEED;
|
||||
vec3.add(k.pos, k.pos, k.vel);
|
||||
k.physicalDir = (180-c.angle[1])*(Math.PI/180);
|
||||
k.angle = k.physicalDir;
|
||||
k.kartTargetNormal = vec3.transformMat4(up, up, mat);
|
||||
k.pos = vec3.clone(c2.pos);
|
||||
vec3.add(k.pos, k.pos, vec3.transformMat4([], [0,16,16], mat));
|
||||
|
||||
var planeConst = -vec3.dot(c.pos, forward);
|
||||
var cannonDist = vec3.dot(k.pos, forward) + planeConst;
|
||||
if (cannonDist > 0) k.cannon = null;
|
||||
k.physicalDir = (180-c2.angle[1])*(Math.PI/180);
|
||||
k.angle = k.physicalDir;
|
||||
k.cannon = null;
|
||||
} else {
|
||||
|
||||
var mat = mat4.create();
|
||||
mat4.rotateY(mat, mat, c.angle[1]*(Math.PI/180));
|
||||
mat4.rotateX(mat, mat, c.angle[0]*(-Math.PI/180));
|
||||
|
||||
var forward = [0, 0, 1];
|
||||
var up = [0, 1, 0];
|
||||
|
||||
k.vel = vec3.scale([], vec3.transformMat4(forward, forward, mat), MAXSPEED);
|
||||
k.speed = Math.min(k.speed+1, MAXSPEED);
|
||||
vec3.add(k.pos, k.pos, k.vel);
|
||||
k.physicalDir = (180-c.angle[1])*(Math.PI/180);
|
||||
k.angle = k.physicalDir;
|
||||
k.kartTargetNormal = vec3.transformMat4(up, up, mat);
|
||||
|
||||
var planeConst = -vec3.dot(c.pos, forward);
|
||||
var cannonDist = vec3.dot(k.pos, forward) + planeConst;
|
||||
if (cannonDist > 0) k.cannon = null;
|
||||
}
|
||||
} else { //default kart mode
|
||||
|
||||
if (k.OOB > 0) {
|
||||
playCharacterSound(0);
|
||||
var current = checkpoints[k.checkPointNumber];
|
||||
var respawn = respawns[current.respawn];
|
||||
k.physicalDir = (180-respawn.angle[1])*(Math.PI/180);
|
||||
k.angle = k.physicalDir;
|
||||
k.speed = 0;
|
||||
k.vel = vec3.create();
|
||||
k.pos = vec3.clone(respawn.pos);
|
||||
vec3.add(k.pos, k.pos, [0,16,0]);
|
||||
if (k.controller.setRouteID != null) k.controller.setRouteID(respawn.id1);
|
||||
k.OOB = 0;
|
||||
}
|
||||
var groundEffect = 0;
|
||||
if (lastCollided != -1) {
|
||||
groundEffect = MKDS_COLTYPE.PHYS_MAP[lastCollided];
|
||||
@@ -402,6 +472,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
if ((onGround) && !(input.accel && input.drift && (k.speed > 2 || !k.driftLanded))) {
|
||||
//end drift, execute miniturbo
|
||||
k.drifting = false;
|
||||
clearWheelParticles();
|
||||
if (sounds.powerslide != null) {
|
||||
nitroAudio.instaKill(sounds.powerslide);
|
||||
sounds.powerslide = null;
|
||||
@@ -434,11 +505,15 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
|
||||
if (onGround) {
|
||||
if (!k.driftLanded) {
|
||||
if (k.driftMode == 0) k.drifting = false;
|
||||
if (k.driftMode == 0) {
|
||||
k.drifting = false;
|
||||
clearWheelParticles();
|
||||
}
|
||||
else {
|
||||
k.driftPSMode = 0;
|
||||
k.driftPSTick = 0;
|
||||
k.driftLanded = true;
|
||||
if (k.drifting) setWheelParticles(20, 1); //20 = smoke, 1 = drift priority
|
||||
}
|
||||
}
|
||||
if (k.drifting) {
|
||||
@@ -467,7 +542,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
k.driftPSMode++;
|
||||
k.driftPSTick = 1;
|
||||
|
||||
//play blue spark sound
|
||||
//play blue spark sound, flare
|
||||
setWheelParticles(126, 2); //126 = blue flare, 2 = flare priority
|
||||
var blue = nitroAudio.playSound(210, {}, 0, k);
|
||||
blue.gainN.gain.value = 2;
|
||||
|
||||
@@ -487,6 +563,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
k.driftPSMode++;
|
||||
k.driftPSTick = 1;
|
||||
//play red sparks sound, full MT!
|
||||
setWheelParticles(22, 2); //22 = red flare, 2 = flare priority
|
||||
setWheelParticles(17, 1); //17 = red mt, 1 = drift priority
|
||||
sounds.powerslide = nitroAudio.playSound(209, {}, 0, k);
|
||||
sounds.powerslide.gainN.gain.value = 2;
|
||||
} else k.driftPSTick = 0;
|
||||
@@ -562,6 +640,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
|
||||
if (!onGround) {
|
||||
this.kartTargetNormal = [0, 1, 0];
|
||||
if (k.physBasis != null) vec3.transformMat4(this.kartTargetNormal,this.kartTargetNormal,k.physBasis.mat);
|
||||
vec3.add(k.vel, k.vel, k.gravity)
|
||||
if (k.ylock >= 0) {
|
||||
ylvel += k.gravity[1];
|
||||
@@ -584,6 +663,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
}
|
||||
|
||||
if (k.kartColTimer > 0) k.kartColTimer--;
|
||||
if (k.kartWallTimer > 0) k.kartWallTimer--;
|
||||
if (k.charSoundTimer > 0) k.charSoundTimer--;
|
||||
|
||||
wheelTurn += k.speed/16;
|
||||
wheelTurn = fixDir(wheelTurn);
|
||||
@@ -602,7 +683,15 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
|
||||
var steps = 0;
|
||||
var remainingT = 1;
|
||||
var velSeg = vec3.clone(k.vel);
|
||||
var baseVel = k.vel;
|
||||
if (k.physBasis != null) {
|
||||
if (k.physBasis.time-- < 0) exitBasis();
|
||||
else {
|
||||
baseVel = vec3.transformMat4([], baseVel, k.physBasis.mat);
|
||||
k.vel[1] = -1;
|
||||
}
|
||||
}
|
||||
var velSeg = vec3.clone(baseVel);
|
||||
var posSeg = vec3.clone(k.pos);
|
||||
var ignoreList = [];
|
||||
while (steps++ < 10 && remainingT > 0.01) {
|
||||
@@ -611,7 +700,10 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
colResponse(posSeg, velSeg, result, ignoreList)
|
||||
remainingT -= result.t;
|
||||
if (remainingT > 0.01) {
|
||||
velSeg = vec3.scale(vec3.create(), k.vel, remainingT);
|
||||
if (k.physBasis != null) {
|
||||
baseVel = vec3.transformMat4([], k.vel, k.physBasis.mat);
|
||||
}
|
||||
velSeg = vec3.scale(vec3.create(), baseVel, remainingT);
|
||||
}
|
||||
} else {
|
||||
vec3.add(posSeg, posSeg, velSeg);
|
||||
@@ -642,6 +734,43 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
positionChanged(lastPos, k.pos);
|
||||
}
|
||||
|
||||
function playCharacterSound(sound, volume) {
|
||||
//0 - hit
|
||||
//1 - hit spin
|
||||
//2 - hit ?? hit grnd
|
||||
//3 - hit banana? race start?
|
||||
//4 - hit spin?
|
||||
//5 - good pass?
|
||||
//6 - good OK!
|
||||
//7 - use item
|
||||
//8 - hit someone?
|
||||
//9 = win
|
||||
//10 = alright
|
||||
//11 = bad
|
||||
//12 = good record
|
||||
//13 = bad record
|
||||
if (volume == null) volume = 1;
|
||||
nitroAudio.playSound(sound + charRes.sndOff, {volume: 2*volume}, 2, k);
|
||||
}
|
||||
|
||||
function clearWheelParticles(prio) {
|
||||
for (var i=0; i<2; i++) {
|
||||
if (prio == null) {
|
||||
//clear all specials
|
||||
k.wheelParticles[i].clearEmitter(1); //drift mode
|
||||
//k.wheelParticles[i].clearEmitter(2); //drift flare (blue mt, red big flash)
|
||||
} else {
|
||||
k.wheelParticles[i].clearEmitter(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setWheelParticles(id, prio) {
|
||||
for (var i=0; i<2; i++) {
|
||||
k.wheelParticles[i].setEmitter(id, prio);
|
||||
}
|
||||
}
|
||||
|
||||
function genFutureChecks() {
|
||||
//all future points that
|
||||
var chosen = {}
|
||||
@@ -661,6 +790,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
|
||||
function positionChanged(oldPos, pos) {
|
||||
//crossed into new checkpoint?
|
||||
if (checkpoints.length == 0) return;
|
||||
for (var i=0; i<futureChecks.length; i++) {
|
||||
var check = checkpoints[futureChecks[i]];
|
||||
var distOld = vec2.sub([], [check.x1, check.z1], [oldPos[0], oldPos[2]]);
|
||||
@@ -685,11 +815,21 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
k.lapNumber++;
|
||||
k.checkPointNumber = 0;
|
||||
k.passedKTP2 = 0;
|
||||
futureChecks = [1];
|
||||
scene.lapAdvance(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getPosition() {
|
||||
if (futureChecks.length == 0) return 0;
|
||||
var check = checkpoints[futureChecks[0]];
|
||||
var dist = vec2.sub([], [check.x1, check.z1], [k.pos[0], k.pos[2]]);
|
||||
var dot = vec2.dot(dist, [check.sinus, check.cosinus]);
|
||||
|
||||
return k.checkPointNumber + (1-(Math.abs(dot)/(0xFFFF))) + k.lapNumber*checkpoints.length;
|
||||
}
|
||||
|
||||
function forwardCrossedKTP(ktp, oldPos, pos) {
|
||||
var distOld = vec2.sub([], [ktp.pos[0], ktp.pos[2]], [oldPos[0], oldPos[2]]);
|
||||
var dist = vec2.sub([], [ktp.pos[0], ktp.pos[2]], [pos[0], pos[2]]);
|
||||
@@ -768,7 +908,13 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
function buildBasis() {
|
||||
//order y, x, z
|
||||
var dir = k.physicalDir+k.driftOff+(Math.sin((COLBOUNCE_TIME-k.kartColTimer)/3)*(Math.PI/6)*(k.kartColTimer/COLBOUNCE_TIME));
|
||||
var basis = gramShmidt(k.kartNormal, [Math.cos(dir), 0, Math.sin(dir)], [Math.sin(dir), 0, -Math.cos(dir)]);
|
||||
var forward = [Math.sin(dir), 0, -Math.cos(dir)];
|
||||
var side = [Math.cos(dir), 0, Math.sin(dir)];
|
||||
if (k.physBasis != null) {
|
||||
vec3.transformMat4(forward, forward, k.physBasis.mat);
|
||||
vec3.transformMat4(side, side, k.physBasis.mat);
|
||||
}
|
||||
var basis = gramShmidt(k.kartNormal, side, forward);
|
||||
var temp = basis[0];
|
||||
basis[0] = basis[1];
|
||||
basis[1] = temp; //todo: cleanup
|
||||
@@ -781,6 +927,56 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
|
||||
}
|
||||
|
||||
function enterBasis(normal) {
|
||||
//establish a new basis for the kart velocity based on this normal.
|
||||
//used by looping and sticky track surface types.
|
||||
|
||||
//first let's get the forward direction in our current basis
|
||||
|
||||
var dir = k.angle;
|
||||
var forward, side;
|
||||
if (k.physBasis != null) {
|
||||
forward = vec3.transformMat4([], [- Math.sin(dir), 0, Math.cos(dir)], k.physBasis.mat);
|
||||
side = vec3.transformMat4([], [Math.cos(dir), 0, Math.sin(dir)], k.physBasis.mat);
|
||||
} else {
|
||||
forward = [-Math.sin(dir), 0, Math.cos(dir)];
|
||||
side = [Math.cos(dir), 0, Math.sin(dir)];
|
||||
}
|
||||
|
||||
var basis = gramShmidt(normal, side, forward);
|
||||
var temp = basis[0];
|
||||
basis[0] = basis[1];
|
||||
basis[1] = temp; //todo: cleanup
|
||||
var m4 = [
|
||||
basis[0][0], basis[0][1], basis[0][2], 0,
|
||||
basis[1][0], basis[1][1], basis[1][2], 0,
|
||||
basis[2][0], basis[2][1], basis[2][2], 0,
|
||||
0, 0, 0, 1
|
||||
];
|
||||
|
||||
k.physicalDir = dirDiff(k.physicalDir, k.angle);
|
||||
k.angle = 0; //our front direction is now aligned with z.
|
||||
k.vel = [Math.sin(k.angle)*k.speed, k.vel[1], -Math.cos(k.angle)*k.speed];
|
||||
|
||||
k.physBasis = {
|
||||
mat: m4,
|
||||
inv: mat4.invert([], m4),
|
||||
time: 15,
|
||||
loop: false
|
||||
};
|
||||
}
|
||||
|
||||
function exitBasis() {
|
||||
//return to a normal y up, z forward basis.
|
||||
|
||||
var v = vec3.transformMat4([], k.vel, k.physBasis.mat);
|
||||
k.physicalDir = dirDiff(k.physicalDir, k.angle);
|
||||
k.angle = Math.atan2(v[0], -v[2]);
|
||||
k.physicalDir += k.angle;
|
||||
k.vel = v;
|
||||
k.physBasis = null;
|
||||
}
|
||||
|
||||
function sndUpdate(view) {
|
||||
k.soundProps.pos = vec3.transformMat4([], k.pos, view);
|
||||
if (k.soundProps.lastPos != null) k.soundProps.vel = vec3.sub([], k.soundProps.pos, k.soundProps.lastPos);
|
||||
@@ -805,6 +1001,11 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
return MKDS_COLTYPE.SOUNDMAP[collision][effect] || {};
|
||||
}
|
||||
|
||||
function colParticle(collision, effect) {
|
||||
if (MKDS_COLTYPE.SOUNDMAP[collision] == null) return null
|
||||
return MKDS_COLTYPE.SOUNDMAP[collision][effect].particle || null;
|
||||
}
|
||||
|
||||
function project(u, v) {
|
||||
return vec3.scale([], u, (vec3.dot(u, v)/vec3.dot(u, u)))
|
||||
}
|
||||
@@ -815,25 +1016,41 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
var colType = (plane.CollisionType>>8)&31;
|
||||
var colBE = (plane.CollisionType>>5)&7;
|
||||
|
||||
var change = (colType != lastCollided);
|
||||
lastCollided = colType;
|
||||
lastBE = colBE;
|
||||
lastColSounds = colSound(lastCollided, colBE);
|
||||
|
||||
var n = vec3.normalize([], dat.normal);
|
||||
var an = n;
|
||||
if (k.physBasis != null) {
|
||||
an = vec3.transformMat4([], n, k.physBasis.inv);
|
||||
}
|
||||
var gravS = Math.sqrt(vec3.dot(k.gravity, k.gravity));
|
||||
var angle = Math.acos(vec3.dot(vec3.scale(vec3.create(), k.gravity, -1/gravS), n));
|
||||
var adjustPos = true;
|
||||
|
||||
if (colType == MKDS_COLTYPE.OOB || colType == MKDS_COLTYPE.FALL) {
|
||||
k.OOB = 1;
|
||||
}
|
||||
|
||||
if (MKDS_COLTYPE.GROUP_WALL.indexOf(colType) != -1) { //wall
|
||||
//sliding plane, except normal is transformed to be entirely on the xz plane (cannot ride on top of wall, treated as vertical)
|
||||
var xz = Math.sqrt(n[0]*n[0]+n[2]*n[2])
|
||||
var adjN = [n[0]/xz, 0, n[2]/xz]
|
||||
var xz = Math.sqrt(an[0]*an[0]+an[2]*an[2])
|
||||
var adjN = [an[0]/xz, 0, an[2]/xz]
|
||||
var proj = vec3.dot(k.vel, adjN);
|
||||
|
||||
if (proj < -1) {
|
||||
if (lastColSounds.hit != null) nitroAudio.playSound(lastColSounds.hit, {volume:1}, 0, k)
|
||||
if (k.kartWallTimer == 0) {
|
||||
if (lastColSounds.hit != null) nitroAudio.playSound(lastColSounds.hit, {volume:1}, 0, k)
|
||||
var colObj = {pos:pos, vel:[0,0,0], mat: mat4.fromTranslation([], pos)};
|
||||
scene.particles.push(new NitroEmitter(scene, colObj, 13));
|
||||
scene.particles.push(new NitroEmitter(scene, colObj, 14));
|
||||
}
|
||||
k.kartWallTimer = 15;
|
||||
}
|
||||
vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), adjN, proj));
|
||||
vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), adjN, proj));
|
||||
|
||||
|
||||
//convert back to angle + speed to keep change to kart vel
|
||||
|
||||
@@ -846,13 +1063,31 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
k.boostNorm = BOOSTTIME;
|
||||
}
|
||||
|
||||
var stick = (colType == MKDS_COLTYPE.STICKY || colType == MKDS_COLTYPE.LOOP);
|
||||
|
||||
if (k.vel[1] > 0) k.vel[1] = 0;
|
||||
var proj = vec3.dot(k.vel, n);
|
||||
if (proj < -4 && k.vel[1] < -2) { proj -= 1.5; }
|
||||
vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), n, proj));
|
||||
var proj = vec3.dot(k.vel, an);
|
||||
if (!stick && proj < -4 && k.vel[1] < -2) { proj -= 1.5; }
|
||||
vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), an, proj));
|
||||
|
||||
if (stick) {
|
||||
enterBasis(dat.pNormal);
|
||||
k.physBasis.loop = colType == MKDS_COLTYPE.LOOP;
|
||||
} else {
|
||||
if (k.physBasis != null)
|
||||
exitBasis();
|
||||
}
|
||||
|
||||
k.kartTargetNormal = dat.pNormal;
|
||||
if (!onGround) {
|
||||
console.log("ground: "+colType+", "+colBE);
|
||||
|
||||
if (change) {
|
||||
var particle = colParticle(lastCollided, colBE);
|
||||
if (particle == null)
|
||||
clearWheelParticles(0);
|
||||
else
|
||||
setWheelParticles(particle, 0);
|
||||
}
|
||||
if (!onGround && !stick) {
|
||||
groundAnim = 0;
|
||||
if (lastColSounds.land != null) nitroAudio.playSound(lastColSounds.land, {volume:1}, 0, k)
|
||||
}
|
||||
|
||||
+98
-29
@@ -9,6 +9,7 @@
|
||||
window.spa = function(input) {
|
||||
var t = this;
|
||||
this.load = load;
|
||||
this.getTexture = getTexture;
|
||||
|
||||
var colourBuffer;
|
||||
|
||||
@@ -36,42 +37,108 @@ window.spa = function(input) {
|
||||
|
||||
offset += 24;
|
||||
if (version == "12_1") {
|
||||
this.particles = [];
|
||||
for (let i=0; i<particleCount; i++) {
|
||||
this.particles[i] = readParticle(view, offset);
|
||||
offset = this.particles[i].nextOff;
|
||||
t.particles = [];
|
||||
for (var i=0; i<particleCount; i++) {
|
||||
t.particles[i] = readParticle(view, offset);
|
||||
t.particles[i].parent = t;
|
||||
offset = t.particles[i].nextOff;
|
||||
}
|
||||
}
|
||||
|
||||
offset = firstTexOffset;
|
||||
this.particleTextures = [];
|
||||
for (let i=0; i<particleTexCount; i++) {
|
||||
this.particleTextures[i] = readParticleTexture(view, offset);
|
||||
offset = this.particleTextures[i].nextOff;
|
||||
t.particleTextures = [];
|
||||
for (var i=0; i<particleTexCount; i++) {
|
||||
t.particleTextures[i] = readParticleTexture(view, offset);
|
||||
offset = t.particleTextures[i].nextOff;
|
||||
}
|
||||
|
||||
//window.debugParticle = true;
|
||||
if (window.debugParticle) {
|
||||
for (let i=0; i<particleCount; i++) {
|
||||
for (var i=0; i<particleCount; i++) {
|
||||
var text = document.createElement("textarea");
|
||||
var p = this.particles[i];
|
||||
var p = t.particles[i];
|
||||
p.parent = null;
|
||||
text.value = JSON.stringify(p, true, 4);
|
||||
p.parent = t;
|
||||
text.style.width = 500;
|
||||
text.style.height = 200;
|
||||
|
||||
|
||||
var obj = this.particleTextures[p.textureId];
|
||||
if (p.texAnim) obj = this.particleTextures[p.texAnim.textures[0]];
|
||||
var obj = t.particleTextures[p.textureId];
|
||||
if (p.texAnim) obj = t.particleTextures[p.texAnim.textures[0]];
|
||||
if (obj == null) {
|
||||
continue;
|
||||
}
|
||||
var test = readTexWithPal(obj.info, obj);
|
||||
document.body.appendChild(document.createElement("br"));
|
||||
document.body.appendChild(document.createTextNode(i+":"));
|
||||
document.body.appendChild(test);
|
||||
document.body.appendChild(text);
|
||||
document.body.appendChild(document.createElement("br"));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getTexture(id, gl) {
|
||||
var t = this;
|
||||
var obj = t.particleTextures[id];
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
if (obj.glTex == null) {
|
||||
var canvas = readTexWithPal(obj.info, obj);
|
||||
var m = obj.info;
|
||||
if (m.flipX || m.flipY) {
|
||||
var fC = document.createElement("canvas");
|
||||
var ctx = fC.getContext("2d");
|
||||
fC.width = (m.flipX)?canvas.width*2:canvas.width;
|
||||
fC.height = (m.flipY)?canvas.height*2:canvas.height;
|
||||
ctx.drawImage(canvas, 0, 0);
|
||||
ctx.save();
|
||||
if (m.flipX) {
|
||||
ctx.translate(2*canvas.width, 0);
|
||||
ctx.scale(-1, 1);
|
||||
ctx.drawImage(canvas, 0, 0);
|
||||
ctx.restore();
|
||||
ctx.save();
|
||||
}
|
||||
if (m.flipY) {
|
||||
ctx.translate(0, 2*canvas.height);
|
||||
ctx.scale(1, -1);
|
||||
ctx.drawImage(fC, 0, 0);
|
||||
ctx.restore();
|
||||
}
|
||||
var t = loadTex(fC, gl, !m.repeatX, !m.repeatY);
|
||||
t.realWidth = canvas.width;
|
||||
t.realHeight = canvas.height;
|
||||
obj.glTex = t;
|
||||
} else {
|
||||
var t = loadTex(canvas, gl, !m.repeatX, !m.repeatY);
|
||||
t.realWidth = canvas.width;
|
||||
t.realHeight = canvas.height;
|
||||
obj.glTex = t;
|
||||
}
|
||||
}
|
||||
return obj.glTex;
|
||||
}
|
||||
|
||||
function loadTex(img, gl, clampx, clampy) { //general purpose function for loading an image into a texture.
|
||||
var texture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
|
||||
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
if (clampx) gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
if (clampy) gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
|
||||
texture.width = img.width;
|
||||
texture.height = img.height;
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
return texture;
|
||||
}
|
||||
|
||||
function readParticle(view, off) {
|
||||
var obj = {};
|
||||
var ParticleFlags =
|
||||
@@ -106,6 +173,7 @@ window.spa = function(input) {
|
||||
Bit29: 0x20000000
|
||||
}
|
||||
|
||||
obj.ParticleFlags = ParticleFlags;
|
||||
obj.flag = view.getUint32(off, true);
|
||||
obj.position = [view.getInt32(off+0x4, true)/4096, view.getInt32(off+0x8, true)/4096, view.getInt32(off+0xC, true)/4096];
|
||||
//this is just hilarious at this point
|
||||
@@ -118,8 +186,8 @@ window.spa = function(input) {
|
||||
//not sure what this vector is for. grass it's (0, 1, 0), smoke it's (-0.706787109375, 0, -0.707275390625) billboard alignment vector? (it's a bit crazy for powerslide)
|
||||
obj.vector = [view.getInt16(off+0x1C, true)/4096, view.getInt16(off+0x1E, true)/4096, view.getInt16(off+0x20, true)/4096];
|
||||
obj.color = view.getUint16(off+0x22, true); //15 bit, usually 32767 for white.
|
||||
obj.randomxz = view.getUint32(off+0x24, true); //random xz velocity intensity
|
||||
obj.velocity = view.getUint32(off+0x28, true); //initial velocity related
|
||||
obj.randomxz = view.getUint32(off+0x24, true)/4096; //random xz velocity intensity
|
||||
obj.velocity = view.getUint32(off+0x28, true)/4096; //initial velocity related (along predefined vector)
|
||||
obj.size = view.getUint32(off+0x2C, true)/4096; //size
|
||||
obj.aspect = view.getUint16(off+0x30, true) / 4096; //aspect
|
||||
|
||||
@@ -130,8 +198,8 @@ window.spa = function(input) {
|
||||
obj.rotVelFrom = view.getInt16(off+0x34, true);
|
||||
obj.rotVelTo = view.getInt16(off+0x36, true);
|
||||
|
||||
obj.unknown13 = view.getUint16(off+0x38, true); //??? (0)
|
||||
obj.unknown14 = view.getUint16(off+0x3A, true); //??? (4B)
|
||||
obj.scX = view.getInt16(off+0x38, true)/0x8000; //??? (0) //scale center offset?
|
||||
obj.scY = view.getInt16(off+0x3A, true)/0x8000; //??? (4B) //scale center offset?
|
||||
obj.emitterLifetime = view.getUint16(off+0x3C, true); //stop emitting particles after this many frames
|
||||
obj.duration = view.getUint16(off+0x3E, true);
|
||||
|
||||
@@ -146,8 +214,8 @@ window.spa = function(input) {
|
||||
obj.textureId = view.getUint8(off+0x47, true);
|
||||
obj.unknown21 = view.getUint32(off+0x48, true); //negative number makes grass disappear (1 for grass, smoke)
|
||||
obj.unknown22 = view.getUint32(off+0x4C, true); //some numbers make grass disappear (0x458d00 for grass, 0x74725f60 for smoke)
|
||||
obj.xScaleDelta = view.getUint16(off+0x50, true); //x scale delta for some reason. usually 0
|
||||
obj.yScaleDelta = view.getUint16(off+0x52, true); //y scale delta for some reason. usually 0
|
||||
obj.xScaleDelta = view.getInt16(off+0x50, true)/4096; //x scale delta for some reason. usually 0
|
||||
obj.yScaleDelta = view.getInt16(off+0x52, true)/4096; //y scale delta for some reason. usually 0
|
||||
obj.unknown25 = view.getUint32(off+0x54, true); //FFFFFFFF makes run at half framerate. idk? usually 0
|
||||
off += 0x58;
|
||||
|
||||
@@ -165,7 +233,8 @@ window.spa = function(input) {
|
||||
unkBase: view.getUint16(off, true)/4096,
|
||||
scaleFrom: view.getUint16(off+2, true)/4096,
|
||||
scaleTo: view.getUint16(off+4, true)/4096,
|
||||
param: view.getUint16(off+6, true),
|
||||
fromZeroTime: view.getUint8(off+6, true)/0xFF, //time to dedicate to an animation from zero size
|
||||
holdTime: view.getUint8(off+7, true)/0xFF, //time to dedicate to holding state at the end.
|
||||
flagParam: view.getUint16(off+8, true),
|
||||
unk4b: view.getUint16(off+10, true),
|
||||
};
|
||||
@@ -173,7 +242,7 @@ window.spa = function(input) {
|
||||
}
|
||||
if ((obj.flag & ParticleFlags.ColorAnimation) != 0)
|
||||
{
|
||||
obj.ColorAnimation = {
|
||||
obj.colorAnim = {
|
||||
colorFrom: view.getUint16(off, true), //color from
|
||||
colorTo: view.getUint16(off+2, true), //color to (seems to be same as base color)
|
||||
framePct: view.getUint16(off+4, true), //frame pct to become color to (FFFF means always from, 8000 is about the middle)
|
||||
@@ -203,7 +272,7 @@ window.spa = function(input) {
|
||||
if ((obj.flag & ParticleFlags.TextureAnimation) != 0)
|
||||
{
|
||||
var textures = [];
|
||||
for (let i=0; i<8; i++) textures[i] = view.getUint8(off+i);
|
||||
for (var i=0; i<8; i++) textures[i] = view.getUint8(off+i);
|
||||
obj.texAnim = {
|
||||
textures: textures,
|
||||
frames: view.getUint8(off+8),
|
||||
@@ -215,7 +284,7 @@ window.spa = function(input) {
|
||||
if ((obj.flag & ParticleFlags.Bit16) != 0)
|
||||
{
|
||||
obj.Bit16 = [];
|
||||
for (let i=0; i<20; i++) obj.Bit16[i] = view.getUint8(off+i);
|
||||
for (var i=0; i<20; i++) obj.Bit16[i] = view.getUint8(off+i);
|
||||
off += 20;
|
||||
}
|
||||
if ((obj.flag & ParticleFlags.Gravity) != 0)
|
||||
@@ -239,31 +308,31 @@ window.spa = function(input) {
|
||||
{
|
||||
//seems to be 4 int 16s typically in some kind of pattern.
|
||||
obj.Bit25 = [];
|
||||
for (let i=0; i<8; i++) obj.Bit25[i] = view.getUint8(off+i);
|
||||
for (var i=0; i<8; i++) obj.Bit25[i] = view.getUint8(off+i);
|
||||
off += 8;
|
||||
}
|
||||
if ((obj.flag & ParticleFlags.Bit26) != 0)
|
||||
{
|
||||
obj.Bit26 = [];
|
||||
for (let i=0; i<16; i++) obj.Bit26[i] = view.getUint8(off+i);
|
||||
for (var i=0; i<16; i++) obj.Bit26[i] = view.getUint8(off+i);
|
||||
off += 16;
|
||||
}
|
||||
if ((obj.flag & ParticleFlags.Bit27) != 0)
|
||||
{
|
||||
obj.Bit27 = [];
|
||||
for (let i=0; i<4; i++) obj.Bit27[i] = view.getUint8(off+i);
|
||||
for (var i=0; i<4; i++) obj.Bit27[i] = view.getUint8(off+i);
|
||||
off += 4;
|
||||
}
|
||||
if ((obj.flag & ParticleFlags.Bit28) != 0)
|
||||
{
|
||||
obj.Bit28 = [];
|
||||
for (let i=0; i<8; i++) obj.Bit28[i] = view.getUint8(off+i);
|
||||
for (var i=0; i<8; i++) obj.Bit28[i] = view.getUint8(off+i);
|
||||
off += 8;
|
||||
}
|
||||
if ((obj.flag & ParticleFlags.Bit29) != 0)
|
||||
{
|
||||
obj.Bit29 = [];
|
||||
for (let i=0; i<16; i++) obj.Bit29[i] = view.getUint8(off+i);
|
||||
for (var i=0; i<16; i++) obj.Bit29[i] = view.getUint8(off+i);
|
||||
off += 16;
|
||||
}
|
||||
|
||||
@@ -278,7 +347,7 @@ window.spa = function(input) {
|
||||
|
||||
var flags = view.getUint16(off+4, true);
|
||||
obj.info = {
|
||||
pal0trans: (flags>>3)&1, //weirdly different format
|
||||
pal0trans: true,//z(flags>>3)&1, //weirdly different format
|
||||
format: ((flags)&7),
|
||||
height: 8 << ((flags>>8)&0xF),
|
||||
width: 8 << ((flags>>4)&0xF),
|
||||
|
||||
Vendored
+20
-20
@@ -2,27 +2,27 @@
|
||||
* @fileoverview gl-matrix - High performance matrix and vector operations
|
||||
* @author Brandon Jones
|
||||
* @author Colin MacKenzie IV
|
||||
* @version 2.2.1
|
||||
* @version 2.4.0
|
||||
*/
|
||||
/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
|
||||
|
||||
* 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.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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(e){"use strict";var t={};typeof exports=="undefined"?typeof define=="function"&&typeof define.amd=="object"&&define.amd?(t.exports={},define(function(){return t.exports})):t.exports=typeof window!="undefined"?window:e:t.exports=exports,function(e){if(!t)var t=1e-6;if(!n)var n=typeof Float32Array!="undefined"?Float32Array:Array;if(!r)var r=Math.random;var i={};i.setMatrixArrayType=function(e){n=e},typeof e!="undefined"&&(e.glMatrix=i);var s=Math.PI/180;i.toRadian=function(e){return e*s};var o={};o.create=function(){var e=new n(2);return e[0]=0,e[1]=0,e},o.clone=function(e){var t=new n(2);return t[0]=e[0],t[1]=e[1],t},o.fromValues=function(e,t){var r=new n(2);return r[0]=e,r[1]=t,r},o.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e},o.set=function(e,t,n){return e[0]=t,e[1]=n,e},o.add=function(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e},o.subtract=function(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e},o.sub=o.subtract,o.multiply=function(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e},o.mul=o.multiply,o.divide=function(e,t,n){return e[0]=t[0]/n[0],e[1]=t[1]/n[1],e},o.div=o.divide,o.min=function(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e},o.max=function(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e},o.scale=function(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e},o.scaleAndAdd=function(e,t,n,r){return e[0]=t[0]+n[0]*r,e[1]=t[1]+n[1]*r,e},o.distance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return Math.sqrt(n*n+r*r)},o.dist=o.distance,o.squaredDistance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return n*n+r*r},o.sqrDist=o.squaredDistance,o.length=function(e){var t=e[0],n=e[1];return Math.sqrt(t*t+n*n)},o.len=o.length,o.squaredLength=function(e){var t=e[0],n=e[1];return t*t+n*n},o.sqrLen=o.squaredLength,o.negate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e},o.normalize=function(e,t){var n=t[0],r=t[1],i=n*n+r*r;return i>0&&(i=1/Math.sqrt(i),e[0]=t[0]*i,e[1]=t[1]*i),e},o.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]},o.cross=function(e,t,n){var r=t[0]*n[1]-t[1]*n[0];return e[0]=e[1]=0,e[2]=r,e},o.lerp=function(e,t,n,r){var i=t[0],s=t[1];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e},o.random=function(e,t){t=t||1;var n=r()*2*Math.PI;return e[0]=Math.cos(n)*t,e[1]=Math.sin(n)*t,e},o.transformMat2=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i,e[1]=n[1]*r+n[3]*i,e},o.transformMat2d=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i+n[4],e[1]=n[1]*r+n[3]*i+n[5],e},o.transformMat3=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[3]*i+n[6],e[1]=n[1]*r+n[4]*i+n[7],e},o.transformMat4=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[4]*i+n[12],e[1]=n[1]*r+n[5]*i+n[13],e},o.forEach=function(){var e=o.create();return function(t,n,r,i,s,o){var u,a;n||(n=2),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u<a;u+=n)e[0]=t[u],e[1]=t[u+1],s(e,e,o),t[u]=e[0],t[u+1]=e[1];return t}}(),o.str=function(e){return"vec2("+e[0]+", "+e[1]+")"},typeof e!="undefined"&&(e.vec2=o);var u={};u.create=function(){var e=new n(3);return e[0]=0,e[1]=0,e[2]=0,e},u.clone=function(e){var t=new n(3);return t[0]=e[0],t[1]=e[1],t[2]=e[2],t},u.fromValues=function(e,t,r){var i=new n(3);return i[0]=e,i[1]=t,i[2]=r,i},u.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e[2]=t[2],e},u.set=function(e,t,n,r){return e[0]=t,e[1]=n,e[2]=r,e},u.add=function(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e[2]=t[2]+n[2],e},u.subtract=function(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e[2]=t[2]-n[2],e},u.sub=u.subtract,u.multiply=function(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e[2]=t[2]*n[2],e},u.mul=u.multiply,u.divide=function(e,t,n){return e[0]=t[0]/n[0],e[1]=t[1]/n[1],e[2]=t[2]/n[2],e},u.div=u.divide,u.min=function(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e[2]=Math.min(t[2],n[2]),e},u.max=function(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e[2]=Math.max(t[2],n[2]),e},u.scale=function(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e[2]=t[2]*n,e},u.scaleAndAdd=function(e,t,n,r){return e[0]=t[0]+n[0]*r,e[1]=t[1]+n[1]*r,e[2]=t[2]+n[2]*r,e},u.distance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1],i=t[2]-e[2];return Math.sqrt(n*n+r*r+i*i)},u.dist=u.distance,u.squaredDistance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1],i=t[2]-e[2];return n*n+r*r+i*i},u.sqrDist=u.squaredDistance,u.length=function(e){var t=e[0],n=e[1],r=e[2];return Math.sqrt(t*t+n*n+r*r)},u.len=u.length,u.squaredLength=function(e){var t=e[0],n=e[1],r=e[2];return t*t+n*n+r*r},u.sqrLen=u.squaredLength,u.negate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e[2]=-t[2],e},u.normalize=function(e,t){var n=t[0],r=t[1],i=t[2],s=n*n+r*r+i*i;return s>0&&(s=1/Math.sqrt(s),e[0]=t[0]*s,e[1]=t[1]*s,e[2]=t[2]*s),e},u.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]},u.cross=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2];return e[0]=i*a-s*u,e[1]=s*o-r*a,e[2]=r*u-i*o,e},u.lerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e[2]=o+r*(n[2]-o),e},u.random=funLine truncated
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE. */
|
||||
|
||||
!function(t,n){if("object"==typeof exports&&"object"==typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define([],n);else{var r=n();for(var a in r)("object"==typeof exports?exports:t)[a]=r[a]}}(this,function(){return function(t){function n(a){if(r[a])return r[a].exports;var e=r[a]={i:a,l:!1,exports:{}};return t[a].call(e.exports,e,e.exports,n),e.l=!0,e.exports}var r={};return n.m=t,n.c=r,n.d=function(t,r,a){n.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:a})},n.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(r,"a",r),r},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="",n(n.s=4)}([function(t,n,r){"use strict";function a(t){n.ARRAY_TYPE=i=t}function e(t){return t*s}function u(t,n){return Math.abs(t-n)<=o*Math.max(1,Math.abs(t),Math.abs(n))}Object.defineProperty(n,"__esModule",{value:!0}),n.setMatrixArrayType=a,n.toRadian=e,n.equals=u;var o=n.EPSILON=1e-6,i=n.ARRAY_TYPE="undefined"!=typeof Float32Array?Float32Array:Array,s=(n.RANDOM=Math.random,Math.PI/180)},function(t,n,r){"use strict";function a(){var t=new g.ARRAY_TYPE(9);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function e(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[4],t[4]=n[5],t[5]=n[6],t[6]=n[8],t[7]=n[9],t[8]=n[10],t}function u(t){var n=new g.ARRAY_TYPE(9);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n}function o(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t}function i(t,n,r,a,e,u,o,i,s){var c=new g.ARRAY_TYPE(9);return c[0]=t,c[1]=n,c[2]=r,c[3]=a,c[4]=e,c[5]=u,c[6]=o,c[7]=i,c[8]=s,c}function s(t,n,r,a,e,u,o,i,s,c){return t[0]=n,t[1]=r,t[2]=a,t[3]=e,t[4]=u,t[5]=o,t[6]=i,t[7]=s,t[8]=c,t}function c(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function f(t,n){if(t===n){var r=n[1],a=n[2],e=n[5];t[1]=n[3],t[2]=n[6],t[3]=r,t[5]=n[7],t[6]=a,t[7]=e}else t[0]=n[0],t[1]=n[3],t[2]=n[6],t[3]=n[1],t[4]=n[4],t[5]=n[7],t[6]=n[2],t[7]=n[5],t[8]=n[8];return t}function M(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8],M=f*o-i*c,h=-f*u+i*s,l=c*u-o*s,v=r*M+a*h+e*l;return v?(v=1/v,t[0]=M*v,t[1]=(-f*a+e*c)*v,t[2]=(i*a-e*o)*v,t[3]=h*v,t[4]=(f*r-e*s)*v,t[5]=(-i*r+e*u)*v,t[6]=l*v,t[7]=(-c*r+a*s)*v,t[8]=(o*r-a*u)*v,t):null}function h(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8];return t[0]=o*f-i*c,t[1]=e*c-a*f,t[2]=a*i-e*o,t[3]=i*s-u*f,t[4]=r*f-e*s,t[5]=e*u-r*i,t[6]=u*c-o*s,t[7]=a*s-r*c,t[8]=r*o-a*u,t}function l(t){var n=t[0],r=t[1],a=t[2],e=t[3],u=t[4],o=t[5],i=t[6],s=t[7],c=t[8];return n*(c*u-o*s)+r*(-c*e+o*i)+a*(s*e-u*i)}function v(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=r[0],l=r[1],v=r[2],d=r[3],b=r[4],m=r[5],p=r[6],P=r[7],E=r[8];return t[0]=h*a+l*o+v*c,t[1]=h*e+l*i+v*f,t[2]=h*u+l*s+v*M,t[3]=d*a+b*o+m*c,t[4]=d*e+b*i+m*f,t[5]=d*u+b*s+m*M,t[6]=p*a+P*o+E*c,t[7]=p*e+P*i+E*f,t[8]=p*u+P*s+E*M,t}function d(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=r[0],l=r[1];return t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=i,t[5]=s,t[6]=h*a+l*o+c,t[7]=h*e+l*i+f,t[8]=h*u+l*s+M,t}function b(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],s=n[5],c=n[6],f=n[7],M=n[8],h=Math.sin(r),l=Math.cos(r);return t[0]=l*a+h*o,t[1]=l*e+h*i,t[2]=l*u+h*s,t[3]=l*o-h*a,t[4]=l*i-h*e,t[5]=l*s-h*u,t[6]=c,t[7]=f,t[8]=M,t}function m(t,n,r){var a=r[0],e=r[1];return t[0]=a*n[0],t[1]=a*n[1],t[2]=a*n[2],t[3]=e*n[3],t[4]=e*n[4],t[5]=e*n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t}function p(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=n[0],t[7]=n[1],t[8]=1,t}function P(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=0,t[3]=-r,t[4]=a,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function E(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=n[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function O(t,n){return t[0]=n[0],t[1]=n[1],t[2]=0,t[3]=n[2],t[4]=n[3],t[5]=0,t[6]=n[4],t[7]=n[5],t[8]=1,t}function x(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r+r,i=a+a,s=e+e,c=r*o,f=a*o,M=a*i,h=e*o,l=e*i,v=e*s,d=u*o,b=u*i,m=u*s;return t[0]=1-M-v,t[3]=f-m,t[6]=h+b,t[1]=f+m,t[4]=1-c-v,t[7]=l-d,t[2]=h-b,t[5]=l+d,t[8]=1-c-M,t}function A(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],s=n[6],c=n[7],f=n[8],M=n[9],h=n[10],l=n[11],v=n[12],d=n[13],b=n[14],m=n[15],p=r*i-a*o,P=r*s-e*o,E=r*c-u*o,O=a*s-e*i,x=a*c-u*i,A=e*c-u*s,q=f*d-M*v,y=f*b-h*v,w=f*m-l*v,R=M*b-h*d,L=M*m-l*d,S=h*m-l*b,_=p*S-P*L+E*R+O*w-x*y+A*q;return _?(_=1/_,t[0]=(i*S-s*L+c*R)*_,t[1]=(s*w-o*S-c*y)*_,t[2]=(o*L-i*w+c*q)*_,t[3]=(e*L-a*S-u*R)*_,t[4]=(r*S-e*w+u*y)*_,t[5]=(a*w-r*L-u*q)*_,t[6]=(d*A-b*x+m*O)*_,t[7]=(b*E-v*A-m*P)*_,t[8]=(v*x-d*E+m*p)*_,t):null}function q(t,n,r){return t[0]=2/n,t[1]=0,t[2]=0,t[3]=0,t[4]=-2/r,t[5]=0,t[6]=-1,t[7]=1,t[8]=1,t}function y(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"}function w(t){return Math.sqrt(Math.pLine truncated
|
||||
+5594
-2998
File diff suppressed because it is too large.
Load diff
@@ -5,35 +5,35 @@
|
||||
//
|
||||
|
||||
window.ItemShard = function(scene, targ, model) {
|
||||
var t = this;
|
||||
t.update = update;
|
||||
t.draw = draw;
|
||||
var t = this;
|
||||
t.update = update;
|
||||
t.draw = draw;
|
||||
|
||||
t.time = 0;
|
||||
t.pos = vec3.clone(targ.pos);
|
||||
t.vel = vec3.add([], targ.vel, [(Math.random()-0.5)*5, Math.random()*7, (Math.random()-0.5)*5]);
|
||||
t.dirVel = [(Math.random()-0.5), (Math.random()-0.5), (Math.random()-0.5)];
|
||||
t.dir = [Math.random()*2*Math.PI, Math.random()*2*Math.PI, Math.random()*2*Math.PI];
|
||||
t.scale = Math.random()+0.5;
|
||||
t.scale = [t.scale, t.scale, t.scale];
|
||||
t.time = 0;
|
||||
t.pos = vec3.clone(targ.pos);
|
||||
t.vel = vec3.add([], targ.vel, [(Math.random()-0.5)*5, Math.random()*7, (Math.random()-0.5)*5]);
|
||||
t.dirVel = [(Math.random()-0.5), (Math.random()-0.5), (Math.random()-0.5)];
|
||||
t.dir = [Math.random()*2*Math.PI, Math.random()*2*Math.PI, Math.random()*2*Math.PI];
|
||||
t.scale = Math.random()+0.5;
|
||||
t.scale = [t.scale, t.scale, t.scale];
|
||||
|
||||
function update(scene) {
|
||||
vec3.add(t.pos, t.pos, t.vel);
|
||||
vec3.add(t.vel, t.vel, [0, -0.17, 0]);
|
||||
vec3.add(t.dir, t.dir, t.dirVel);
|
||||
function update(scene) {
|
||||
vec3.add(t.pos, t.pos, t.vel);
|
||||
vec3.add(t.vel, t.vel, [0, -0.17, 0]);
|
||||
vec3.add(t.dir, t.dir, t.dirVel);
|
||||
|
||||
if (t.time++ > 30) scene.removeParticle(t);
|
||||
}
|
||||
if (t.time++ > 30) scene.removeParticle(t);
|
||||
}
|
||||
|
||||
function draw(view, pMatrix, gl) {
|
||||
var mat = mat4.translate(mat4.create(), view, t.pos);
|
||||
|
||||
mat4.rotateZ(mat, mat, t.dir[2]);
|
||||
mat4.rotateY(mat, mat, t.dir[1]);
|
||||
mat4.rotateX(mat, mat, t.dir[0]);
|
||||
function draw(view, pMatrix, gl) {
|
||||
var mat = mat4.translate(mat4.create(), view, t.pos);
|
||||
|
||||
mat4.rotateZ(mat, mat, t.dir[2]);
|
||||
mat4.rotateY(mat, mat, t.dir[1]);
|
||||
mat4.rotateX(mat, mat, t.dir[0]);
|
||||
|
||||
mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
|
||||
model.draw(mat, pMatrix);
|
||||
}
|
||||
mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
|
||||
model.draw(mat, pMatrix);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
//
|
||||
// nitroEmitter.js
|
||||
//--------------------
|
||||
// Implemtents the generic nitro particle emitter.
|
||||
// by riperiperi
|
||||
//
|
||||
|
||||
window.NitroEmitter = function(scene, targ, emitterID, vector, offset) {
|
||||
var t = this;
|
||||
t.update = update;
|
||||
t.draw = draw;
|
||||
|
||||
var pRes = scene.gameRes.RaceEffect;
|
||||
var emitter = (emitterID == -1)?null:pRes.particles[emitterID];
|
||||
t.attached = targ; //an entity with pos and vel.
|
||||
|
||||
if (vector == null) vector = [0, 1, 0];
|
||||
if (offset == null) offset = [0,0,0];
|
||||
t.offset = offset;
|
||||
t.vector = vector;
|
||||
t.pctParticle = 0;
|
||||
t.time = 0;
|
||||
t.dead = false;
|
||||
t.curPrio = 0;
|
||||
t.doNotDelete = (emitter == null);
|
||||
t.pause = false;
|
||||
|
||||
t.setEmitter = setEmitter;
|
||||
t.clearEmitter = clearEmitter;
|
||||
|
||||
var particleList = [emitterID, -1, -1, -1];
|
||||
|
||||
function setEmitter(emitterID, prio) {
|
||||
particleList[prio] = emitterID;
|
||||
if (t.curPrio <= prio) {
|
||||
//activate this emitter immediately.
|
||||
t.curPrio = prio;
|
||||
t.dead = false;
|
||||
emitter = pRes.particles[emitterID];
|
||||
t.time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function clearEmitter(prio) {
|
||||
//if (t.curPrio > prio) return; //this emitter cannot be unset
|
||||
if (prio == t.curPrio) {
|
||||
findNextEmitter();
|
||||
} else {
|
||||
particleList[prio] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
function findNextEmitter() {
|
||||
particleList[t.curPrio] = -1;
|
||||
var em = t.curPrio-1;
|
||||
while (em >= 0) {
|
||||
if (particleList[em] != -1) {
|
||||
t.dead = false;
|
||||
emitter = pRes.particles[particleList[em]];
|
||||
t.time = 0;
|
||||
t.curPrio = em;
|
||||
return;
|
||||
}
|
||||
em--;
|
||||
}
|
||||
if (em == -1) {
|
||||
t.curPrio = 0;
|
||||
emitter = null;
|
||||
dead = true;
|
||||
}
|
||||
t.curPrio = em;
|
||||
}
|
||||
|
||||
function update(scene) {
|
||||
if (emitter == null || t.dead || t.pause) return;
|
||||
if ((t.time % (emitter.frequency)) == 0 && t.time >= emitter.delay) {
|
||||
//should we create new particles? fractional logic for doing this
|
||||
t.pctParticle += emitter.particleChance;
|
||||
while (t.pctParticle >= 1) {
|
||||
|
||||
var attach = (emitter.flag & 0x8000) > 0;
|
||||
|
||||
t.pctParticle -= 1;
|
||||
//create a new particle
|
||||
//TODO: make these transform with the target's world matrix
|
||||
var pos = vec3.create();
|
||||
//add offset
|
||||
vec3.add(pos, pos, t.offset);
|
||||
//add emitter properties
|
||||
vec3.add(pos, pos, emitter.position);
|
||||
var spread = [Math.random()*2-1, Math.random()*2-1, Math.random()*2-1];
|
||||
var spreadMode = (emitter.flag & 0xF);
|
||||
if (spreadMode == 2) {
|
||||
spread[1] = 0; //spread is only in xz direction
|
||||
}
|
||||
vec3.normalize(spread, spread);
|
||||
if (spreadMode == 0) {
|
||||
spread = [0,0,0];
|
||||
}
|
||||
vec3.scale(spread, spread, Math.random()*emitter.areaSpread*2);
|
||||
vec3.add(pos, pos, spread);
|
||||
|
||||
vec3.scale(pos, pos, 16);
|
||||
if (!attach) {
|
||||
if (targ.mat != null) {
|
||||
vec3.transformMat4(pos, pos, targ.mat);
|
||||
} else {
|
||||
vec3.add(pos, pos, targ.pos);
|
||||
}
|
||||
}
|
||||
|
||||
//inherit velocity
|
||||
var vel = (attach)?vec3.create():vec3.clone(targ.vel);
|
||||
vec3.scale(vel, vel, 1/32);
|
||||
|
||||
var vector = vec3.clone(t.vector);
|
||||
if (!attach) {
|
||||
if (targ.mat != null) {
|
||||
//tranform our vector by the target matrix
|
||||
var mat = targ.mat;
|
||||
var org = [];
|
||||
mat4.getTranslation(org, mat);
|
||||
mat[12] = 0;
|
||||
mat[13] = 0;
|
||||
mat[14] = 0;
|
||||
|
||||
vec3.transformMat4(vector, vector, mat);
|
||||
|
||||
mat[12] = org[0];
|
||||
mat[13] = org[1];
|
||||
mat[14] = org[2];
|
||||
}
|
||||
}
|
||||
vec3.normalize(vector, vector);
|
||||
vec3.add(vel, vel, vec3.scale([], vector, emitter.velocity));
|
||||
|
||||
var xz = [Math.random()*2-1, 0, Math.random()*2-1];
|
||||
vec3.normalize(xz, xz);
|
||||
vec3.scale(xz, xz, Math.random()*emitter.randomxz);
|
||||
vec3.add(vel, vel, xz);
|
||||
|
||||
var rotVel = ((emitter.rotVelFrom + ((Math.random()*emitter.rotVelTo-emitter.rotVelFrom) | 0))/65535) * Math.PI*2;
|
||||
var dir = ((emitter.flag & 0x2000) > 0)?(Math.random()*Math.PI*2):0;
|
||||
var duration = emitter.duration + emitter.duration * emitter.varDuration/0xFF * (Math.random() * 2 - 1);
|
||||
var scaleMod = (emitter.varScale/0xFF * (Math.random() * 2 - 1)) + 1;
|
||||
|
||||
var scale = [scaleMod * emitter.size, scaleMod * emitter.size * emitter.aspect];
|
||||
|
||||
var particle = new NitroParticle(scene, emitter, pos, vel, dir, rotVel, duration, scale, (attach?t.attached:null));
|
||||
particle.ovel = (attach)?vec3.create():vec3.scale([], targ.vel, 1/32);
|
||||
|
||||
scene.particles.push(particle);
|
||||
}
|
||||
|
||||
|
||||
var pos = vec3.clone(targ.pos);
|
||||
|
||||
}
|
||||
t.time++;
|
||||
|
||||
if (t.time == emitter.emitterLifetime) {
|
||||
t.dead = true;
|
||||
if (!t.doNotDelete) scene.removeParticle(t);
|
||||
else {
|
||||
findNextEmitter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function draw(view, pMatrix, gl) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
//
|
||||
// nitroParticle.js
|
||||
//--------------------
|
||||
// Implements a generic nitro particle. Currently positioned and updated in software for debug
|
||||
// simplicity - but should be moved to vertex shader in future.
|
||||
// by riperiperi
|
||||
//
|
||||
|
||||
window.NitroParticle = function(scene, emitter, pos, vel, dir, dirVel, duration, scale, attached) {
|
||||
var t = this;
|
||||
t.update = update;
|
||||
t.draw = draw;
|
||||
|
||||
t.time = 0;
|
||||
t.duration = duration | 0;
|
||||
t.pos = vec3.add(pos, pos, [0, 0, 0]);
|
||||
t.vel = vel;
|
||||
t.dirVel = dirVel; //float
|
||||
t.dir = dir; //float
|
||||
t.attached = attached;
|
||||
t.scale = scale; //vec2
|
||||
t.emitter = emitter;
|
||||
|
||||
t.aScale = 1;
|
||||
//decode 16 bit color into float
|
||||
t.baseColor = convertCol(emitter.color);
|
||||
t.baseColor[3] = emitter.opacity / 0x1F;
|
||||
t.aColor = vec4.clone(t.baseColor);
|
||||
|
||||
t.frame = emitter.textureId;
|
||||
if (t.emitter.texAnim)
|
||||
t.frame = t.emitter.texAnim.textures[0];
|
||||
|
||||
function convertCol(col) {
|
||||
return [
|
||||
((col&31)/31),
|
||||
(((col>>5)&31)/31),
|
||||
(((col>>10)&31)/31),
|
||||
1 //Math.round((col>>15)*255);
|
||||
];
|
||||
}
|
||||
|
||||
function update(scene) {
|
||||
var particlePct = t.time / t.duration;
|
||||
|
||||
t.pos[0] += t.vel[0] * 16;
|
||||
t.pos[1] += t.vel[1] * (t.emitter.yOffIntensity/128) * 16;
|
||||
t.pos[2] += t.vel[2] * 16;
|
||||
if (t.emitter.gravity) {
|
||||
vec3.add(t.vel, t.vel, t.emitter.gravity);
|
||||
}
|
||||
if (t.emitter.colorAnim) {
|
||||
var ca = t.emitter.colorAnim;
|
||||
var from = convertCol(ca.colorFrom);
|
||||
var to = convertCol(ca.colorTo);
|
||||
var pctFloat = (ca.framePct/0xFFFF);
|
||||
vec4.lerp(t.aColor, from, to, Math.max(0, (particlePct - pctFloat)/(1 - pctFloat)));
|
||||
t.aColor[3] = t.emitter.opacity/0x1F;
|
||||
} else {
|
||||
t.aColor = vec4.clone(t.baseColor);
|
||||
}
|
||||
if (t.emitter.opacityAnim) {
|
||||
var oa = t.emitter.opacityAnim;
|
||||
var pctFade = oa.startFade / 0xFFFF;
|
||||
var opaMul = 1-Math.max(0, (particlePct - pctFade)/(1 - pctFade));
|
||||
t.aColor[3] = opaMul;// * oa.intensity/0x0FFF;
|
||||
//vec4.scale(t.aColor, t.aColor, opaMul);
|
||||
}
|
||||
if (t.emitter.texAnim) {
|
||||
var ta = t.emitter.texAnim;
|
||||
var frame = 0;
|
||||
if ((ta.unknown1 & 128) > 0) {
|
||||
//select frame based on particle duration
|
||||
var frame = ta.textures[Math.min((particlePct * ta.frames) | 0, ta.frames-1)];
|
||||
} else {
|
||||
//repeating anim with framerate
|
||||
//not sure what framerate is, but its likely in the unknowns.
|
||||
var frame = ta.textures[(t.time % ta.frames)];
|
||||
}
|
||||
t.frame = frame;
|
||||
}
|
||||
|
||||
t.dir += t.dirVel;
|
||||
|
||||
if (t.time++ >= t.duration) scene.removeParticle(t);
|
||||
}
|
||||
|
||||
function draw(view, pMatrix, gl) {
|
||||
var particlePct = t.time / t.duration;
|
||||
|
||||
var pos = t.pos;
|
||||
var vel = t.vel;
|
||||
|
||||
if (t.attached != null) {
|
||||
pos = vec3.transformMat4([], pos, t.attached.mat);
|
||||
|
||||
|
||||
//tranform our vector by the target matrix
|
||||
var mat = t.attached.mat;
|
||||
var org = [];
|
||||
|
||||
mat4.getTranslation(org, mat);
|
||||
mat[12] = 0;
|
||||
mat[13] = 0;
|
||||
mat[14] = 0;
|
||||
|
||||
vel = vec3.transformMat4([], vel, mat);
|
||||
|
||||
mat[12] = org[0];
|
||||
mat[13] = org[1];
|
||||
mat[14] = org[2];
|
||||
|
||||
}
|
||||
|
||||
var mat = mat4.translate(mat4.create(), view, pos);
|
||||
|
||||
var bbMode = t.emitter.flag & 0xF0;
|
||||
|
||||
if (bbMode == 0x10) { //spark, billboards towards camera
|
||||
var camPos = scene.camera.view.pos;
|
||||
|
||||
camPos = vec3.sub([], camPos, pos);
|
||||
vec3.normalize(camPos, camPos);
|
||||
|
||||
var n = vec3.sub([], vel, t.ovel);
|
||||
vec3.normalize(n,n);
|
||||
mat4.multiply(mat, mat, mat4.invert([], mat4.lookAt([], [0,0,0], camPos, n)));
|
||||
|
||||
} else if (bbMode == 0x20) { //no billboard
|
||||
mat4.rotateY(mat, mat, t.dir);
|
||||
} else if (bbMode == 0x30) { //spark, no billboard
|
||||
var camPos = scene.camera.view.pos;
|
||||
|
||||
camPos = vec3.sub([], camPos, pos);
|
||||
vec3.normalize(camPos, camPos);
|
||||
|
||||
var n = vec3.sub([], vel, t.ovel);
|
||||
vec3.normalize(n,n);
|
||||
mat4.multiply(mat, mat, mat4.invert([], mat4.lookAt([], [0,0,0], camPos, n)));
|
||||
mat4.rotateY(mat, mat, t.dir);
|
||||
} else { //billboard
|
||||
mat4.multiply(mat, mat, nitroRender.billboardMat);
|
||||
mat4.rotateZ(mat, mat, t.dir);
|
||||
}
|
||||
var finalScale = 1;
|
||||
if (t.emitter.scaleAnim) {
|
||||
var sa = t.emitter.scaleAnim;
|
||||
if (particlePct < sa.fromZeroTime) {
|
||||
var fzPct = particlePct / sa.fromZeroTime;
|
||||
finalScale = sa.scaleFrom * fzPct;
|
||||
} else {
|
||||
var rescaledPct = Math.min(1, (particlePct - sa.fromZeroTime) / (1-(sa.fromZeroTime + sa.holdTime*(1-sa.fromZeroTime))));
|
||||
finalScale = sa.scaleFrom * (1-rescaledPct) + sa.scaleTo * rescaledPct;
|
||||
}
|
||||
}
|
||||
mat4.scale(mat, mat, vec3.scale([], [t.scale[0], t.scale[1], 1], 12*finalScale));
|
||||
mat4.translate(mat, mat, [t.emitter.xScaleDelta, t.emitter.yScaleDelta, 0]);
|
||||
|
||||
drawGeneric(mat, pMatrix, gl);
|
||||
}
|
||||
|
||||
var MAT3I = mat3.create();
|
||||
var MAT4I = mat4.create();
|
||||
function drawGeneric(mv, project, gl) {
|
||||
var shader = nitroRender.nitroShader;
|
||||
if (!nitroRender.flagShadow) {
|
||||
gl.uniform1f(shader.shadOffUniform, 0.001);
|
||||
gl.uniform1f(shader.lightIntensityUniform, 0);
|
||||
}
|
||||
if (window.VTX_PARTICLE == null) genGlobalVtx(gl);
|
||||
var obj = window.VTX_PARTICLE;
|
||||
|
||||
nitroRender.setColMult(t.aColor);
|
||||
|
||||
gl.uniformMatrix4fv(shader.mvMatrixUniform, false, mv);
|
||||
gl.uniformMatrix4fv(shader.pMatrixUniform, false, project);
|
||||
//matrix stack unused, just put an identity in slot 0
|
||||
gl.uniformMatrix4fv(shader.matStackUniform, false, MAT4I);
|
||||
|
||||
var frame = t.emitter.parent.getTexture(t.frame, gl);
|
||||
gl.bindTexture(gl.TEXTURE_2D, frame);
|
||||
//texture matrix not used
|
||||
gl.uniformMatrix3fv(shader.texMatrixUniform, false, MAT3I);
|
||||
if (obj != nitroRender.last.obj) {
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vPos);
|
||||
gl.vertexAttribPointer(shader.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vTx);
|
||||
gl.vertexAttribPointer(shader.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vCol);
|
||||
gl.vertexAttribPointer(shader.colorAttribute, 4, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vMat);
|
||||
gl.vertexAttribPointer(shader.matAttribute, 1, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, obj.vNorm);
|
||||
gl.vertexAttribPointer(shader.normAttribute, 3, gl.FLOAT, false, 0, 0);
|
||||
nitroRender.last.obj = obj;
|
||||
}
|
||||
|
||||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
nitroRender.setColMult([1, 1, 1, 1]);
|
||||
if (!nitroRender.flagShadow) {
|
||||
nitroRender.resetShadOff();
|
||||
gl.uniform1f(shader.lightIntensityUniform, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
function genGlobalVtx(gl) {
|
||||
var vecPos = [-1,-1,0, 1,-1,0, -1,1,0, 1,1,0];
|
||||
var vecTx = [1,1, 0,1, 1,0, 0,0];
|
||||
var vecCol = [1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1];
|
||||
var vecMat = [0,0,0,0];
|
||||
var vecNorm = [0,1,0, 0,1,0, 0,1,0, 0,1,0];
|
||||
|
||||
var pos = gl.createBuffer();
|
||||
var col = gl.createBuffer();
|
||||
var tx = gl.createBuffer();
|
||||
var mat = gl.createBuffer();
|
||||
var norm = gl.createBuffer();
|
||||
|
||||
var posArray = new Float32Array(vecPos);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, pos);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, posArray, gl.STATIC_DRAW);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, tx);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecTx), gl.STATIC_DRAW);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, col);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecCol), gl.STATIC_DRAW);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, mat);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecMat), gl.STATIC_DRAW);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, norm);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vecNorm), gl.STATIC_DRAW);
|
||||
|
||||
window.VTX_PARTICLE = {
|
||||
posArray: posArray,
|
||||
vPos: pos,
|
||||
vTx: tx,
|
||||
vCol: col,
|
||||
vMat: mat,
|
||||
vNorm: norm,
|
||||
verts: vecPos.length/3,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -246,10 +246,9 @@ window.nitroRender = new function() {
|
||||
|
||||
gl.uniformMatrix4fv(shader.shadowMatUniform, false, sMat);
|
||||
gl.uniformMatrix4fv(shader.farShadowMatUniform, false, fsMat);
|
||||
gl.uniform1f(shader.lightIntensityUniform, 0.3);
|
||||
|
||||
gl.uniform1f(shader.shadOffUniform, 0.00005+((mobile)?0.0005:0));
|
||||
gl.uniform1f(shader.farShadOffUniform, 0.0005);
|
||||
|
||||
this.resetShadOff();
|
||||
gl.activeTexture(gl.TEXTURE1);
|
||||
gl.bindTexture(gl.TEXTURE_2D, sTex);
|
||||
gl.uniform1i(shader.lightSamplerUniform, 1);
|
||||
@@ -262,6 +261,12 @@ window.nitroRender = new function() {
|
||||
this.prepareShader();
|
||||
}
|
||||
|
||||
this.resetShadOff = function() {
|
||||
var shader = shaders[1];
|
||||
gl.uniform1f(shader.shadOffUniform, 0.00005+((mobile)?0.0005:0));
|
||||
gl.uniform1f(shader.farShadOffUniform, 0.0005);
|
||||
}
|
||||
|
||||
this.unsetShadowMode = function() {
|
||||
this.nitroShader = shaders[0];
|
||||
gl.useProgram(this.nitroShader);
|
||||
@@ -384,7 +389,7 @@ function nitroModel(bmd, btx, remap) {
|
||||
}
|
||||
|
||||
if (remap != null) {
|
||||
setTextureRemap(remap)
|
||||
setTextureRemap(remap);
|
||||
}
|
||||
|
||||
if (btx != null) {
|
||||
|
||||
+45
-13
@@ -16,9 +16,39 @@ window.nitroShaders = new (function() {
|
||||
\n\
|
||||
uniform sampler2D uSampler;\n\
|
||||
\n\
|
||||
float indexValue() {\n\
|
||||
int x = int(mod(gl_FragCoord.x, 4.0));\n\
|
||||
int y = int(mod(gl_FragCoord.y, 4.0));\n\
|
||||
int i = (x + y * 4);\n\
|
||||
if (i == 0) return 0.0;\n\
|
||||
else if (i == 1) return 8.0;\n\
|
||||
else if (i == 2) return 2.0;\n\
|
||||
else if (i == 3) return 10.0;\n\
|
||||
else if (i == 4) return 12.0;\n\
|
||||
else if (i == 5) return 4.0;\n\
|
||||
else if (i == 6) return 14.0;\n\
|
||||
else if (i == 7) return 6.0;\n\
|
||||
else if (i == 8) return 3.0;\n\
|
||||
else if (i == 9) return 11.0;\n\
|
||||
else if (i == 10) return 1.0;\n\
|
||||
else if (i == 11) return 9.0;\n\
|
||||
else if (i == 12) return 15.0;\n\
|
||||
else if (i == 13) return 7.0;\n\
|
||||
else if (i == 14) return 13.0;\n\
|
||||
else if (i == 15) return 5.0;\n\
|
||||
}\n\
|
||||
\n\
|
||||
float dither(float color) {\n\
|
||||
float closestColor = (color < 0.5) ? 0.0 : 1.0;\n\
|
||||
float secondClosestColor = 1.0 - closestColor;\n\
|
||||
float d = indexValue();\n\
|
||||
float distance = abs(closestColor - color);\n\
|
||||
return (distance < d) ? closestColor : secondClosestColor;\n\
|
||||
}\n\
|
||||
\n\
|
||||
void main(void) {\n\
|
||||
gl_FragColor = texture2D(uSampler, vTextureCoord)*color;\n\
|
||||
if (gl_FragColor.a == 0.0) discard;\n\
|
||||
if (gl_FragColor.a < 1.0 && (gl_FragColor.a == 0.0 || dither(gl_FragColor.a) == 0.0)) discard;\n\
|
||||
}"
|
||||
|
||||
this.defaultVert = "attribute vec3 aVertexPosition;\n\
|
||||
@@ -62,20 +92,20 @@ window.nitroShaders = new (function() {
|
||||
\n\
|
||||
uniform sampler2D uSampler;\n\
|
||||
\n\
|
||||
float shadowCompare(sampler2D map, vec2 pos, float compare) {\n\
|
||||
float shadowCompare(sampler2D map, vec2 pos, float compare, float so) {\n\
|
||||
float depth = texture2D(map, pos).r;\n\
|
||||
return step(compare, depth);\n\
|
||||
return smoothstep(compare-so, compare, depth);\n\
|
||||
}\n\
|
||||
\n\
|
||||
float shadowLerp(sampler2D depths, vec2 size, vec2 uv, float compare){\n\
|
||||
float shadowLerp(sampler2D depths, vec2 size, vec2 uv, float compare, float so){\n\
|
||||
vec2 texelSize = vec2(1.0)/size;\n\
|
||||
vec2 f = fract(uv*size+0.5);\n\
|
||||
vec2 centroidUV = floor(uv*size+0.5)/size;\n\
|
||||
\n\
|
||||
float lb = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 0.0), compare);\n\
|
||||
float lt = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 1.0), compare);\n\
|
||||
float rb = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 0.0), compare);\n\
|
||||
float rt = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 1.0), compare);\n\
|
||||
float lb = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 0.0), compare, so);\n\
|
||||
float lt = shadowCompare(depths, centroidUV+texelSize*vec2(0.0, 1.0), compare, so);\n\
|
||||
float rb = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 0.0), compare, so);\n\
|
||||
float rt = shadowCompare(depths, centroidUV+texelSize*vec2(1.0, 1.0), compare, so);\n\
|
||||
float a = mix(lb, lt, f.y);\n\
|
||||
float b = mix(rb, rt, f.y);\n\
|
||||
float c = mix(a, b, f.x);\n\
|
||||
@@ -89,14 +119,14 @@ window.nitroShaders = new (function() {
|
||||
float dist = max(ldNorm.x, ldNorm.y);\n\
|
||||
\n\
|
||||
if (dist > 0.5) {\n\
|
||||
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff));\n\
|
||||
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff, farShadOff*2.0));\n\
|
||||
} else if (dist > 0.4) {\n\
|
||||
float lerp1 = shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff);\n\
|
||||
float lerp2 = shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff);\n\
|
||||
float lerp1 = shadowLerp(farLightDSampler, vec2(4096.0, 4096.0), fLightDist.xy, fLightDist.z-farShadOff, farShadOff*2.0);\n\
|
||||
float lerp2 = shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff, shadOff*4.0);\n\
|
||||
\n\
|
||||
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), mix(lerp2, lerp1, (dist-0.4)*10.0));\n\
|
||||
} else {\n\
|
||||
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff));\n\
|
||||
gl_FragColor = col*mix(vec4(0.5, 0.5, 0.7, 1.0), vec4(1.0, 1.0, 1.0, 1.0), shadowLerp(lightDSampler, vec2(2048.0, 2048.0), lightDist.xy, lightDist.z-shadOff, shadOff*4.0));\n\
|
||||
}\n\
|
||||
\n\
|
||||
if (gl_FragColor.a == 0.0) discard;\n\
|
||||
@@ -118,6 +148,7 @@ window.nitroShaders = new (function() {
|
||||
\n\
|
||||
uniform mat4 shadowMat;\n\
|
||||
uniform mat4 farShadowMat;\n\
|
||||
uniform float lightIntensity; \n\
|
||||
\n\
|
||||
varying vec2 vTextureCoord;\n\
|
||||
varying vec4 color;\n\
|
||||
@@ -133,7 +164,7 @@ window.nitroShaders = new (function() {
|
||||
lightDist = (shadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
|
||||
fLightDist = (farShadowMat*pos + vec4(1, 1, 1, 0)) / 2.0;\n\
|
||||
vec3 adjNorm = normalize(vec3(uMVMatrix * matStack[int(matrixID)] * vec4(aNormal, 0.0)));\n\
|
||||
float diffuse = 0.7-dot(adjNorm, vec3(0.0, -1.0, 0.0))*0.3;\n\
|
||||
float diffuse = (1.0-lightIntensity)-dot(adjNorm, vec3(0.0, -1.0, 0.0))*lightIntensity;\n\
|
||||
\n\
|
||||
color = aColor*colMult;\n\
|
||||
color = vec4(color.x*diffuse, color.y*diffuse, color.z*diffuse, color.w);\n\
|
||||
@@ -270,6 +301,7 @@ window.nitroShaders = new (function() {
|
||||
var shadUnif = [
|
||||
["shadowMatUniform", "shadowMat"],
|
||||
["farShadowMatUniform", "farShadowMat"],
|
||||
["lightIntensityUniform", "lightIntensity"],
|
||||
|
||||
["shadOffUniform", "shadOff"],
|
||||
["farShadOffUniform", "farShadOff"],
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
<head>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="mkjs">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, user-scalable=no">
<!-- Client Code Includes -->
<script src="code/engine/largeSphereCollider.js"></script>
<script src="code/engine/collisionTypes.js"></script>
<script src="code/engine/mkdsConst.js"></script>
<script src="code/engine/ingameRes.js"></script>
<script src="code/engine/itemController.js"></script>
<script src="code/IndexedDBShim.min.js"></script>
<script src="code/engine/storage/fileStore.js"></script>
<script src="code/engine/controls/controlDefault.js"></script>
<script src="code/engine/controls/controlRaceCPU.js"></script>
<script src="code/engine/controls/controlNetwork.js"></script>
<script src="code/engine/cameras/cameraIngame.js"></script>
<script src="code/engine/cameras/cameraSpectator.js"></script>
<script src="code/engine/cameras/cameraIntro.js"></script>
<script src="code/engine/scenes/sceneDrawer.js"></script>
<script src="code/engine/scenes/courseScene.js"></script>
<script src="code/engine/scenes/clientScene.js"></script>
<script src="code/engine/scenes/singleScene.js"></script>
<script src="code/ui/race3DUI.js"></script>
<script src="code/formats/net/netKart.js"></script>
<script src="code/entities/objDatabase.js"></script>
<script src="code/entities/trafficCar.js"></script>
<script src="code/entities/water.js"></script>
<script src="code/entities/itembox.js"></script>
<script src="code/entities/decorations.js"></script>
<script src="code/entities/rotatingGear.js"></script>
<script src="code/entities/bowserPlatforms.js"></script>
<script src="code/entities/soundMaker.js"></script>
<script src="code/particles/itemboxShard.js"></script>
<script src="code/entities/shell.js"></script>
<script src="code/entities/kart.js"></script>
<script src="code/formats/kcl.js"></script>
<script src="code/formats/ndsFS.js"></script>
<script src="code/formats/nitro.js"></script>
<script src="code/formats/nsbtx.js"></script>
<script src="code/formats/nsbmd.js"></script>
<script src="code/formats/nsbta.js"></script>
<script src="code/formats/nsbca.js"></script>
<script src="code/formats/nsbtp.js"></script>
<script src="code/formats/nftr.js"></script>
<script src="code/formats/narc.js"></script>
<script src="code/formats/lz77.js"></script>
<script src="code/formats/spa.js"></script>
<script src="code/formats/nkm.js"></script>
<script src="code/formats/kartphysicalparam.js"></script>
<script src="code/formats/kartoffsetdata.js"></script>
<script src="code/render/nitroRender.js"></script>
<script src="code/render/nitroShaders.js"></script>
<script src="code/render/shadowRender.js"></script>
<script src="code/render/nitroAnimator.js"></script>
<script src="code/glmatrix/gl-matrix.js"></script>
<script src="code/formats/sdat.js"></script>
<script src="code/formats/swav.js"></script>
<script src="code/formats/swar.js"></script>
<script src="code/formats/sbnk.js"></script>
<script src="code/formats/sseq.js"></script>
<script src="code/formats/ssar.js"></script>
<script src="code/audio/sseqPlayer.js"></script>
<script src="code/audio/nitroAudio.js"></script>
<!-- Inline code (because that's always a good idea) -->
<script>
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
var files = {};
var fileQuota;
var filesLoaded = 0;
var mobile = (function(a,b){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mLine truncated
|
||||
<head>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="mkjs">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, user-scalable=no">
<!-- Client Code Includes -->
<script src="code/engine/largeSphereCollider.js"></script>
<script src="code/engine/collisionTypes.js"></script>
<script src="code/engine/mkdsConst.js"></script>
<script src="code/engine/ingameRes.js"></script>
<script src="code/engine/itemController.js"></script>
<script src="code/IndexedDBShim.min.js"></script>
<script src="code/engine/storage/fileStore.js"></script>
<script src="code/engine/controls/controlDefault.js"></script>
<script src="code/engine/controls/controlRaceCPU.js"></script>
<script src="code/engine/controls/controlNetwork.js"></script>
<script src="code/engine/cameras/cameraIngame.js"></script>
<script src="code/engine/cameras/cameraSpectator.js"></script>
<script src="code/engine/cameras/cameraIntro.js"></script>
<script src="code/engine/scenes/sceneDrawer.js"></script>
<script src="code/engine/scenes/courseScene.js"></script>
<script src="code/engine/scenes/clientScene.js"></script>
<script src="code/engine/scenes/singleScene.js"></script>
<script src="code/ui/race3DUI.js"></script>
<script src="code/formats/net/netKart.js"></script>
<script src="code/entities/objDatabase.js"></script>
<script src="code/entities/trafficCar.js"></script>
<script src="code/entities/water.js"></script>
<script src="code/entities/itembox.js"></script>
<script src="code/entities/decorations.js"></script>
<script src="code/entities/rotatingGear.js"></script>
<script src="code/entities/bowserPlatforms.js"></script>
<script src="code/entities/soundMaker.js"></script>
<script src="code/particles/itemboxShard.js"></script>
<script src="code/particles/nitroParticle.js"></script>
<script src="code/particles/nitroEmitter.js"></script>
<script src="code/entities/shell.js"></script>
<script src="code/entities/kart.js"></script>
<script src="code/formats/kcl.js"></script>
<script src="code/formats/ndsFS.js"></script>
<script src="code/formats/nitro.js"></script>
<script src="code/formats/nsbtx.js"></script>
<script src="code/formats/nsbmd.js"></script>
<script src="code/formats/nsbta.js"></script>
<script src="code/formats/nsbca.js"></script>
<script src="code/formats/nsbtp.js"></script>
<script src="code/formats/nftr.js"></script>
<script src="code/formats/narc.js"></script>
<script src="code/formats/lz77.js"></script>
<script src="code/formats/spa.js"></script>
<script src="code/formats/nkm.js"></script>
<script src="code/formats/kartphysicalparam.js"></script>
<script src="code/formats/kartoffsetdata.js"></script>
<script src="code/render/nitroRender.js"></script>
<script src="code/render/nitroShaders.js"></script>
<script src="code/render/shadowRender.js"></script>
<script src="code/render/nitroAnimator.js"></script>
<script src="code/glmatrix/gl-matrix.js"></script>
<script src="code/formats/sdat.js"></script>
<script src="code/formats/swav.js"></script>
<script src="code/formats/swar.js"></script>
<script src="code/formats/sbnk.js"></script>
<script src="code/formats/sseq.js"></script>
<script src="code/formats/ssar.js"></script>
<script src="code/audio/sseqPlayer.js"></script>
<script src="code/audio/nitroAudio.js"></script>
<!-- Inline code (because that's always a good idea) -->
<script>
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
var files = {};
var fileQuota;
var filesLoaded = 0;
var mobile = (function(a,b){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|Line truncated
|
||||
Reference in new issue
Block a user