All courses now render properly. WIP items (shell, banana, fake item)
This commit is contained in:
1 parent
e010627b5d
commit
ff21142744
45 files changed
+3400
-1193
No files matched your search
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// bowserPlatforms.js
|
||||
//--------------------
|
||||
// Provides platforms for Bowser's Castle
|
||||
// Provides moving platforms for Bowser's Castle and Delfino
|
||||
// by RHY3756547
|
||||
//
|
||||
// includes:
|
||||
@@ -78,6 +78,133 @@ window.ObjRotaryRoom = function(obji, scene) {
|
||||
|
||||
}
|
||||
|
||||
window.ObjBridge = function(obji, scene) {
|
||||
var obji = obji;
|
||||
var res = [];
|
||||
|
||||
var t = this;
|
||||
|
||||
t.collidable = true;
|
||||
t.colMode = 0;
|
||||
t.colRad = 512;
|
||||
t.getCollision = getCollision;
|
||||
t.moveWith = moveWith;
|
||||
|
||||
t.pos = vec3.clone(obji.pos);
|
||||
t.angle = vec3.clone(obji.angle);
|
||||
t.scale = vec3.clone(obji.scale);
|
||||
|
||||
t.requireRes = requireRes;
|
||||
t.provideRes = provideRes;
|
||||
t.update = update;
|
||||
t.draw = draw;
|
||||
|
||||
t.largerUpAngle = obji.setting1&0xFFFF;
|
||||
t.upDuration = obji.setting1>>16;
|
||||
t.statDuration = obji.setting2&0xFFFF;
|
||||
t.downDuration = obji.setting2>>16;
|
||||
t.upAngle = obji.setting3&0xFFFF;
|
||||
t.unknown = obji.setting4>>16; //10001
|
||||
|
||||
t.obji = obji;
|
||||
t.colFrame = 0;
|
||||
|
||||
var dirVel = 0;
|
||||
var genCol;
|
||||
|
||||
var prevMat;
|
||||
var curMat;
|
||||
var colMat = mat4.create();
|
||||
prevMat = curMat;
|
||||
|
||||
var anim;
|
||||
var animMat;
|
||||
|
||||
var frame = 0;
|
||||
var mode = 0; //going up, stationary, going down, stationary
|
||||
|
||||
function setMat() {
|
||||
prevMat = curMat;
|
||||
var mat = mat4.create();
|
||||
mat4.translate(mat, mat, t.pos);
|
||||
|
||||
if (t.angle[2] != 0) mat4.rotateZ(mat, mat, t.angle[2]*(Math.PI/180));
|
||||
if (t.angle[1] != 0) mat4.rotateY(mat, mat, t.angle[1]*(Math.PI/180));
|
||||
if (t.angle[0] != 0) mat4.rotateX(mat, mat, t.angle[0]*(Math.PI/180));
|
||||
|
||||
mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
|
||||
mat4.scale(colMat, mat, [genCol.scale, genCol.scale, genCol.scale]);
|
||||
t.colFrame++;
|
||||
curMat = mat;
|
||||
}
|
||||
|
||||
function update(scene) {
|
||||
var angle = 0;
|
||||
frame++;
|
||||
switch (mode) {
|
||||
case 0:
|
||||
var p = frame / t.upDuration;
|
||||
angle = (0.5 - Math.cos(p * Math.PI) / 2) * t.largerUpAngle;
|
||||
if (frame >= t.upDuration) {
|
||||
mode = 1;
|
||||
frame = 0;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
angle = (mode == 1) ? t.largerUpAngle : 0;
|
||||
if (frame >= t.statDuration) {
|
||||
mode = (mode + 1) % 4;
|
||||
frame = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
var p = 1 - frame / t.downDuration;
|
||||
angle = (0.5 - Math.cos(p * Math.PI) / 2) * t.largerUpAngle;
|
||||
if (frame >= t.downDuration) {
|
||||
mode = 3;
|
||||
frame = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
t.angle[0] = -angle;
|
||||
animMat = anim.setFrame(0, 0, angle*1.5);
|
||||
setMat();
|
||||
}
|
||||
|
||||
function draw(view, pMatrix) {
|
||||
var mat = mat4.create();
|
||||
mat4.mul(mat, view, curMat);
|
||||
|
||||
res.mdl[0].draw(mat, pMatrix, animMat);
|
||||
}
|
||||
|
||||
function requireRes() { //scene asks what resources to load
|
||||
return {mdl:[{nsbmd:"bridge.nsbmd"}], other:[null, "bridge.nsbca"]};
|
||||
}
|
||||
|
||||
function provideRes(r) {
|
||||
res = r; //...and gives them to us. :)
|
||||
var inf = res.mdl[0].getCollisionModel(0, 1, 7<<8); //dash
|
||||
var inf2 = res.mdl[0].getCollisionModel(0, 0, 0); //regular
|
||||
anim = new nitroAnimator(r.mdl[0].bmd, r.other[1]);
|
||||
|
||||
genCol = {dat:JSON.parse(JSON.stringify(inf.dat.concat(inf2.dat))), scale:inf.scale};
|
||||
}
|
||||
|
||||
function getCollision() {
|
||||
return { tris: genCol.dat, mat: colMat, frame: t.colFrame };
|
||||
}
|
||||
|
||||
function moveWith(obj) { //used for collidable objects that move.
|
||||
//the most general way to move something with an object is to multiply its position by the inverse mv matrix of that object, and then the new mv matrix.
|
||||
vec3.transformMat4(obj.pos, obj.pos, mat4.invert([], prevMat))
|
||||
vec3.transformMat4(obj.pos, obj.pos, curMat)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
window.ObjRoutePlatform = function(obji, scene) {
|
||||
var obji = obji;
|
||||
var res = [];
|
||||
@@ -111,12 +238,14 @@ window.ObjRoutePlatform = function(obji, scene) {
|
||||
t.elapsedTime = 0;
|
||||
|
||||
t.mode = 0;
|
||||
t.colFrame = 0;
|
||||
|
||||
var movVel;
|
||||
|
||||
//t.speed = (obji.setting1&0xFFFF)/8192;
|
||||
|
||||
function update(scene) {
|
||||
t.colFrame++;
|
||||
if (t.mode == 0) {
|
||||
t.elapsedTime += t.routeSpeed;
|
||||
movVel = vec3.sub([], t.nextNode.pos, t.prevPos);
|
||||
@@ -159,15 +288,11 @@ window.ObjRoutePlatform = function(obji, scene) {
|
||||
function generateCol() {
|
||||
genCol = {dat: [
|
||||
{
|
||||
Vertex1: [25, 0, 11],
|
||||
Vertex2: [25, 0, -11],
|
||||
Vertex3: [-25, 0, -11],
|
||||
Vertices: [[25, 0, 11], [25, 0, -11], [-25, 0, -11]],
|
||||
Normal: [0, 1, 0]
|
||||
},
|
||||
{
|
||||
Vertex1: [-25, 0, -11],
|
||||
Vertex2: [-25, 0, 11],
|
||||
Vertex3: [25, 0, 11],
|
||||
Vertices: [[-25, 0, -11], [-25, 0, 11], [25, 0, 11]],
|
||||
Normal: [0, 1, 0]
|
||||
},
|
||||
], scale: 1};
|
||||
@@ -182,6 +307,7 @@ window.ObjRoutePlatform = function(obji, scene) {
|
||||
mat4.scale(mat, mat, vec3.mul([], [16*inf.scale, 16*inf.scale, 16*inf.scale], t.scale));
|
||||
|
||||
obj.mat = mat;
|
||||
obj.frame = t.colFrame;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
+184
-64
@@ -32,34 +32,44 @@ var itemTypes = {
|
||||
'$koura_w': BlueShellC
|
||||
}
|
||||
|
||||
window.Item = function(scene, owner, type) {
|
||||
window.Item = function(scene, owner, type, id) {
|
||||
var t = this;
|
||||
var minimumMove = 0.01;
|
||||
|
||||
this.id = 0;
|
||||
this.id = id;
|
||||
|
||||
this.pos = vec3.transformMat4([], [0, (-owner.params.colRadius)+1, 16], owner.mat);
|
||||
this.vel = vec3.create();
|
||||
this.gravity = [0, -0.17, 0]; //100% confirmed by me messing around with the gravity value in mkds
|
||||
this.minBounceVel = 0.5;
|
||||
this.airResist = 0.95;
|
||||
this.airResist = 0.99;
|
||||
this.enablePhysics = true;
|
||||
this.floorBounce = 0.5;
|
||||
this.held = true;
|
||||
this.type = type;
|
||||
this.owner = owner;
|
||||
this.holdTime = 20;
|
||||
this.dead = false;
|
||||
|
||||
this.angle = owner.angle;
|
||||
this.speed = 10;
|
||||
this.yvel = 0;
|
||||
this.xyScale = [1, 1];
|
||||
|
||||
this.colRadius = 4;
|
||||
this.holdDist = 16;
|
||||
this.holdDist = 2;
|
||||
this.safeKart = owner;
|
||||
var safeTimeMax = 4;
|
||||
this.safeTime = safeTimeMax; //time the object needs to not be colliding with the source to start considering collisions with it
|
||||
this.stuckTo = null;
|
||||
|
||||
var deadTimerLength = 20;
|
||||
var throwVelocity = 16;
|
||||
var throwAngle = (Math.PI / 3) * 2;
|
||||
this.groundTime = 0;
|
||||
|
||||
|
||||
var deadTimerLength = 30;
|
||||
var throwVelocity = 7; //xz velocity for throw. angle adds a y component
|
||||
var throwAngle = (Math.PI / 10) * 2;
|
||||
var working = vec3.create();
|
||||
this.deadTimer = 0; //animates death. goes to 20, then deletes for real. dead objects can't run update or otherwise
|
||||
|
||||
//a controller makes this item what it is...
|
||||
@@ -69,6 +79,8 @@ window.Item = function(scene, owner, type) {
|
||||
// update?: (scene: CourseScene) => void
|
||||
// draw?: (mvMatrix, pMatrix) => void // OVERRIDES NORMAL DRAW FUNCTION!
|
||||
// release?: (direction: number) => boolean //direction is 1 for forward, -1 for back. returns if the item has more uses
|
||||
// onRest?: (normal: vec3) => void //when the object comes to a rest (first time, or after leaving the ground for a while)
|
||||
// onDie?: (final: boolean) => void //when the object dies
|
||||
// collide?: (item: Item | Kart)
|
||||
// collideKart?: (item: Kart)
|
||||
var subtypeInd = type.indexOf('-');
|
||||
@@ -91,10 +103,16 @@ window.Item = function(scene, owner, type) {
|
||||
function updateHold(kart) {
|
||||
//move the object behind the kart (physical direction without drift off)
|
||||
//assuming this will only be called for something that can be held
|
||||
var dir = -kart.driftOff;
|
||||
var dir = kart.driftOff / 4;
|
||||
|
||||
//offset the kart's drift offset (on direction)
|
||||
var pos = [Math.sin(dir)*t.holdDist, 0, -Math.cos(dir)*t.holdDist];
|
||||
var pos;
|
||||
if (t.holdPos != null) {
|
||||
pos = vec3.clone(t.holdPos);
|
||||
} else {
|
||||
var dist = t.colRadius + kart.params.colRadius + t.holdDist;
|
||||
var pos = [Math.sin(dir)*dist, -kart.params.colRadius, -Math.cos(dir)*dist];
|
||||
}
|
||||
|
||||
//make relative to the kart's position
|
||||
vec3.transformMat4(pos, pos, kart.mat);
|
||||
@@ -105,18 +123,37 @@ window.Item = function(scene, owner, type) {
|
||||
|
||||
function release(forward) {
|
||||
//release the item, either forward or back
|
||||
if (t.canBeHeld()) t.updateHold(owner);
|
||||
t.holdTime = 0;
|
||||
if (t.canBeHeld()) {
|
||||
t.updateHold(owner);
|
||||
updateCollision(scene);
|
||||
}
|
||||
t.enablePhysics = true;
|
||||
if (t.controller.release) t.controller.release(forward);
|
||||
else {
|
||||
//default drop and throw. just here for template purposes
|
||||
if (forward >= 0) {
|
||||
var dir = owner.physicalDir;
|
||||
vec3.zero(t.vel);
|
||||
if (forward > 0) {
|
||||
nitroAudio.playSound(218, {volume: 2}, 0, owner);
|
||||
var dir = owner.driftOff / 4;
|
||||
|
||||
//offset the kart's drift offset (on direction). add y component
|
||||
var vel = [-Math.sin(dir)*throwVelocity, Math.tan(throwAngle) * throwVelocity, Math.cos(dir)*throwVelocity];
|
||||
var z = [0, 0, 0];
|
||||
|
||||
//make relative to the kart's orientation
|
||||
vec3.transformMat4(vel, vel, owner.mat);
|
||||
vec3.transformMat4(z, z, owner.mat);
|
||||
vec3.sub(vel, vel, z);
|
||||
var v2 = vec3.scale([], owner.vel, 2);
|
||||
vec3.add(vel, vel, v2);
|
||||
|
||||
t.vel = vel;
|
||||
} else {
|
||||
vec3.zero(t.vel);
|
||||
t.vel = vec3.create();
|
||||
t.safeKart = null;
|
||||
}
|
||||
}
|
||||
this.held = false;
|
||||
t.held = false;
|
||||
}
|
||||
|
||||
function canBeHeld() {
|
||||
@@ -124,7 +161,8 @@ window.Item = function(scene, owner, type) {
|
||||
}
|
||||
|
||||
function canBeDropped() {
|
||||
return t.controller.canBeDropped || true;
|
||||
if (t.controller.canBeDropped == null) return true;
|
||||
return t.controller.canBeDropped;
|
||||
}
|
||||
|
||||
function isDestructive() {
|
||||
@@ -132,13 +170,22 @@ window.Item = function(scene, owner, type) {
|
||||
}
|
||||
|
||||
function isSolid() {
|
||||
return t.controller.isSolid || true;
|
||||
if (t.controller.isSolid == null) return true;
|
||||
return t.controller.isSolid;
|
||||
}
|
||||
|
||||
function finalize() {
|
||||
//kill instantly
|
||||
if (t.controller.onDie) t.controller.onDie(true);
|
||||
t.deadTimer = deadTimerLength;
|
||||
scene.items.removeItem(t);
|
||||
t.dead = true;
|
||||
}
|
||||
|
||||
function intensityMax(targ, vec) {
|
||||
if (Math.abs(vec[0]) > Math.abs(targ[0])*0.5) targ[0] = vec[0];
|
||||
if (Math.abs(vec[1]) > Math.abs(targ[1])*0.5) targ[1] = vec[1];
|
||||
if (Math.abs(vec[2]) > Math.abs(targ[2])*0.5) targ[2] = vec[2];
|
||||
}
|
||||
|
||||
function collide(item) {
|
||||
@@ -152,15 +199,19 @@ window.Item = function(scene, owner, type) {
|
||||
if (item.isDestructive() || t.isDestructive()) {
|
||||
//mutual destruction. other side will deal with how they handle the collision
|
||||
t.deadTimer++;
|
||||
item.deadTimer++;
|
||||
} else if (item.isSolid() && t.isSolid()) {
|
||||
//bounce off other items that are not destructive
|
||||
//set our velocity to move away (not too intensely)
|
||||
//(only apply if our id is before, to avoid double adding the velocity)
|
||||
if (t.id < item.id) {
|
||||
var diff = vec3.sub([], t.pos, item.pos);
|
||||
vec3.scale(diff, diff, 0.5);
|
||||
vec3.add(t.vel, t.vel, diff);
|
||||
vec3.sub(item.vel, item.vel, diff);
|
||||
var diff = vec3.sub(working, t.pos, item.pos);
|
||||
vec3.scale(diff, diff, 0.33);
|
||||
intensityMax(t.vel, diff);
|
||||
vec3.scale(diff, diff, -1);
|
||||
intensityMax(item.vel, diff);
|
||||
//vec3.add(t.vel, t.vel, diff);
|
||||
//vec3.sub(item.vel, item.vel, diff);
|
||||
t.enablePhysics = true;
|
||||
item.enablePhysics = true;
|
||||
}
|
||||
@@ -175,77 +226,131 @@ window.Item = function(scene, owner, type) {
|
||||
|
||||
function update(scene) {
|
||||
if (t.controller.update) t.controller.update(scene);
|
||||
if (t.holdTime > 0 && t.holdTime-- > 7) {
|
||||
if (t.holdTime == 7) {
|
||||
nitroAudio.playSound(231, {volume: 2}, 0, owner);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (t.pos[2] < -10000) finalize(); //out of bounds failsafe
|
||||
|
||||
if (t.deadTimer > 0) {
|
||||
if (t.deadTimer == 1 && t.controller.onDie) t.controller.onDie(false);
|
||||
t.deadTimer++;
|
||||
if (t.deadTimer >= 20) t.finalize();
|
||||
t.sprMat = mat4.create();
|
||||
mat4.translate(t.sprMat, t.sprMat, [t.deadTimer/50, Math.sin((t.deadTimer/30) * Math.PI) * 0.5, 0]);
|
||||
mat4.rotateZ(t.sprMat, t.sprMat, (t.deadTimer/-15) * Math.PI);
|
||||
if (t.deadTimer >= 30) t.finalize();
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.held) {
|
||||
t.updateHold(owner);
|
||||
}
|
||||
|
||||
var hitSafe = false;
|
||||
//search for player collisions, collisions with other items
|
||||
for (var i=0; i<scene.karts.length; i++) {
|
||||
var ok = scene.karts[i];
|
||||
var dist = vec3.dist(vec3.add([], t.pos, [0,1,0]), ok.pos);
|
||||
if (dist < t.colRadius + 12) {
|
||||
|
||||
var dist = vec3.dist(vec3.add(working, t.pos, [0,t.colRadius/2,0]), ok.pos);
|
||||
if (dist < t.colRadius + ok.params.colRadius) {
|
||||
//colliding with a kart.
|
||||
//do we need to do something?
|
||||
if (ok === t.safeKart) {
|
||||
hitSafe = true;
|
||||
continue;
|
||||
}
|
||||
t.collide(ok);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i=0; i<scene.items.length; i++) {
|
||||
var ot = scene.items[i];
|
||||
var dist = vec3.dist(t.pos, ot.pos);
|
||||
if (dist < t.colRadius + ot.colRadius) {
|
||||
//two items are colliding.
|
||||
t.collide(ot);
|
||||
if (t.safeKart && !hitSafe && !t.held) {
|
||||
t.safeTime--;
|
||||
if (t.safeTime <= 0) {
|
||||
t.safeKart = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (t.enablePhysics) {
|
||||
if (!t.held) {
|
||||
vec3.add(t.vel, t.vel, t.gravity);
|
||||
vec3.scale(t.vel, t.vel, t.airResist);
|
||||
}
|
||||
|
||||
//by default, items use raycast collision against the world (rather than ellipse)
|
||||
//this speeds things up considerably
|
||||
|
||||
var steps = 0;
|
||||
var remainingT = 1;
|
||||
var velSeg = vec3.clone(t.vel);
|
||||
var posSeg = vec3.clone(t.pos);
|
||||
var ignoreList = [];
|
||||
while (steps++ < 10 && remainingT > 0.01) {
|
||||
var result = lsc.raycast(posSeg, velSeg, scene.kcl, 0.05, ignoreList);
|
||||
if (result != null) {
|
||||
if (t.controller.colResponse) t.controller.colResponse(posSeg, velSeg, result, ignoreList)
|
||||
else colResponse(posSeg, velSeg, result, ignoreList)
|
||||
remainingT -= result.t;
|
||||
if (remainingT > 0.01) {
|
||||
velSeg = vec3.scale(vec3.create(), t.vel, remainingT);
|
||||
}
|
||||
} else {
|
||||
vec3.add(posSeg, posSeg, velSeg);
|
||||
remainingT = 0;
|
||||
if (t.holdTime == 0) { //avoid mutual item destruction on the first frame
|
||||
for (var i=0; i<scene.items.items.length; i++) {
|
||||
var ot = scene.items.items[i];
|
||||
if (ot == t || (t.held && ot.held)) continue;
|
||||
var dist = vec3.dist(t.pos, ot.pos);
|
||||
if (dist < t.colRadius + ot.colRadius && ot.holdTime <= 7 && ot.deadTimer == 0) {
|
||||
//two items are colliding.
|
||||
t.collide(ot);
|
||||
}
|
||||
}
|
||||
t.pos = posSeg;
|
||||
}
|
||||
|
||||
if (t.groundTime > 0) t.groundTime++;
|
||||
|
||||
if (t.stuckTo != null) {
|
||||
if (t.stuckTo.moveWith != null) t.stuckTo.moveWith(t);
|
||||
t.enablePhysics = true;
|
||||
t.stuckTo = null;
|
||||
}
|
||||
|
||||
if (t.enablePhysics) {
|
||||
updateCollision(scene);
|
||||
}
|
||||
}
|
||||
|
||||
function updateCollision(scene) {
|
||||
if (!t.held) {
|
||||
vec3.add(t.vel, t.vel, t.gravity);
|
||||
vec3.scale(t.vel, t.vel, t.airResist);
|
||||
}
|
||||
|
||||
//by default, items use raycast collision against the world (rather than ellipse)
|
||||
//this speeds things up considerably
|
||||
|
||||
var steps = 0;
|
||||
var remainingT = 1;
|
||||
var velSeg = vec3.clone(t.vel);
|
||||
var posSeg = vec3.clone(t.pos);
|
||||
var ignoreList = [];
|
||||
while (steps++ < 10 && remainingT > 0.01) {
|
||||
var result = lsc.raycast(posSeg, velSeg, scene, 0.05, ignoreList);
|
||||
if (result != null) {
|
||||
if (t.controller.colResponse && !t.held) t.controller.colResponse(posSeg, velSeg, result, ignoreList)
|
||||
else colResponse(posSeg, velSeg, result, ignoreList)
|
||||
remainingT -= result.t;
|
||||
if (remainingT > 0.01) {
|
||||
velSeg = vec3.scale(velSeg, t.vel, remainingT);
|
||||
}
|
||||
} else {
|
||||
vec3.add(posSeg, posSeg, velSeg);
|
||||
remainingT = 0;
|
||||
}
|
||||
}
|
||||
t.pos = posSeg;
|
||||
}
|
||||
|
||||
function draw(mvMatrix, pMatrix) {
|
||||
if (t.holdTime > 7) return;
|
||||
if (t.deadTimer > 0) nitroRender.setColMult([1, 1, 1, 1-(t.deadTimer/deadTimerLength)]); //fade out
|
||||
if (t.controller.draw) {
|
||||
t.controller.draw(mvMatrix, pMatrix);
|
||||
} else {
|
||||
var mat = mat4.translate(mat4.create(), mvMatrix, vec3.add(vec3.create(), t.pos, [0, 3, 0]));
|
||||
var mat = mat4.translate(mat4.create(), mvMatrix, vec3.add(vec3.create(), t.pos, [0, t.colRadius * t.xyScale[1], 0]));
|
||||
|
||||
spritify(mat);
|
||||
mat4.scale(mat, mat, [16, 16, 16]);
|
||||
var scale = 6*t.colRadius * (1 - t.holdTime/7);
|
||||
mat4.scale(mat, mat, [scale, scale, scale]);
|
||||
|
||||
scene.gameRes.items[type].draw(mat, pMatrix);
|
||||
var mdl = scene.gameRes.items[type];
|
||||
//apply our custom mat (in sprite space), if it exists
|
||||
//used for destruction animation, scaling
|
||||
if (t.sprMat) {
|
||||
var oldMat = mdl.baseMat;
|
||||
mdl.setBaseMat(t.sprMat);
|
||||
mdl.draw(mat, pMatrix);
|
||||
mdl.setBaseMat(oldMat);
|
||||
} else {
|
||||
mdl.draw(mat, pMatrix);
|
||||
}
|
||||
}
|
||||
if (t.deadTimer > 0) nitroRender.setColMult([1, 1, 1, 1]);
|
||||
}
|
||||
@@ -272,13 +377,28 @@ window.Item = function(scene, owner, type) {
|
||||
//normally, item collision with a wall cause a perfect reflection of the velocity.
|
||||
var proj = vec3.dot(t.vel, n) * 2;
|
||||
vec3.sub(t.vel, t.vel, vec3.scale(vec3.create(), n, proj));
|
||||
|
||||
t.safeKart = null;
|
||||
} else if (colType == MKDS_COLTYPE.OOB || colType == MKDS_COLTYPE.FALL) {
|
||||
if (t.deadTimer == 0) t.deadTimer++;
|
||||
} else if (MKDS_COLTYPE.GROUP_ROAD.indexOf(colType) != -1) {
|
||||
//sliding plane
|
||||
var proj = vec3.dot(t.vel, n) * (1 + t.floorBounce);
|
||||
var bounce = t.held ? 0 : t.floorBounce;
|
||||
var proj = vec3.dot(t.vel, n) * (1 + bounce);
|
||||
vec3.sub(t.vel, t.vel, vec3.scale(vec3.create(), n, proj));
|
||||
|
||||
if (t.floorBounce == 0 || Math.abs(proj) < t.minBounceVel) t.enablePhysics = false;
|
||||
if (!t.held && (t.floorBounce == 0 || Math.abs(proj) < t.minBounceVel)) {
|
||||
t.vel[0] = 0;
|
||||
t.vel[1] = 0;
|
||||
t.vel[2] = 0;
|
||||
t.enablePhysics = false;
|
||||
if (t.groundTime == 0) {
|
||||
t.groundTime = 1;
|
||||
if (t.controller.onRest) {
|
||||
t.controller.onRest(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
t.stuckTo = dat.object;
|
||||
} else {
|
||||
adjustPos = false;
|
||||
ignoreList.push(plane);
|
||||
|
||||
@@ -98,12 +98,15 @@ window.ItemBox = function(obji, scene) {
|
||||
}
|
||||
|
||||
function sndUpdate(view) {
|
||||
/*
|
||||
t.soundProps.pos = vec3.transformMat4([], t.pos, view);
|
||||
if (t.soundProps.lastPos != null) t.soundProps.vel = vec3.sub([], t.soundProps.pos, t.soundProps.lastPos);
|
||||
else t.soundProps.vel = [0, 0, 0];
|
||||
*/
|
||||
t.soundProps.lastPos = t.soundProps.pos;
|
||||
t.soundProps.pos = t.pos; //todo: reintroduce doppler via emulation
|
||||
|
||||
t.soundProps.refDistance = 192/1024;
|
||||
t.soundProps.refDistance = 192;
|
||||
t.soundProps.rolloffFactor = 1;
|
||||
}
|
||||
|
||||
|
||||
+105
-16
@@ -1,15 +1,42 @@
|
||||
window.BananaC = function(item, scene, type) {
|
||||
var t = this;
|
||||
this.canBeHeld = true;
|
||||
this.canBeDropped = true;
|
||||
this.isDestructive = false;
|
||||
item.minBounceVel = 0;
|
||||
item.floorBounce = 0;
|
||||
|
||||
this.collideKart = collideKart;
|
||||
this.onRest = onRest;
|
||||
this.update = update;
|
||||
|
||||
function collideKart(kart) {
|
||||
item.deadTimerLength = 20;
|
||||
item.deadTimer = 1;
|
||||
kart.damage(MKDSCONST.DAMAGE_SPIN);
|
||||
}
|
||||
|
||||
function onRest(normal) {
|
||||
nitroAudio.playSound(219, {volume: 2}, 0, item);
|
||||
}
|
||||
|
||||
function update(argument) {
|
||||
if (!item.held && item.colRadius < 6) {
|
||||
item.colRadius += 0.2;
|
||||
if (item.colRadius > 6) item.colRadius = 6;
|
||||
}
|
||||
if (item.groundTime < 30) {
|
||||
var t = (1-item.groundTime/29);
|
||||
var s = Math.sin(item.groundTime * Math.PI/14);
|
||||
|
||||
var sprMat = mat4.create();
|
||||
mat4.translate(sprMat, sprMat, [0, -1/6, 0]);
|
||||
mat4.scale(sprMat, sprMat, [1 + s * 0.6 * t, 1 - s * 0.6 * t, 1]);
|
||||
mat4.translate(sprMat, sprMat, [0, 1/6, 0]);
|
||||
|
||||
item.sprMat = sprMat;
|
||||
} else {
|
||||
item.sprMat = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.BananaGroupC = function(item, scene, type) {
|
||||
@@ -28,27 +55,89 @@ window.BananaGroupC = function(item, scene, type) {
|
||||
}
|
||||
|
||||
window.FakeBoxC = function(item, scene, type) {
|
||||
var t = this;
|
||||
this.canBeHeld = true;
|
||||
this.canBeDropped = true;
|
||||
this.isDestructive = false;
|
||||
this.isSolid = true;
|
||||
var model = scene.gameRes.fakeBox;
|
||||
this.isSolid = false;
|
||||
item.floorBounce = 0;
|
||||
item.airResist = 0.98;
|
||||
|
||||
this.collideKart = collideKart;
|
||||
this.onRest = onRest;
|
||||
this.update = update;
|
||||
this.draw = draw;
|
||||
|
||||
function draw(view, pMatrix) {
|
||||
mat4.translate(mat, view, t.pos);
|
||||
mat4.translate(mat, view, [0, 16, 0]);
|
||||
this.xyScale = [1,1];
|
||||
this.dir = 0;
|
||||
|
||||
function collideKart(kart) {
|
||||
item.deadTimer = 1;
|
||||
nitroAudio.playSound(250, {volume: 2}, 0, item);
|
||||
kart.damage(MKDSCONST.DAMAGE_FLIP);
|
||||
}
|
||||
|
||||
function onRest(normal) {
|
||||
nitroAudio.playSound(251, {volume: 2}, 0, item);
|
||||
}
|
||||
|
||||
function update(argument) {
|
||||
if (item.held) {
|
||||
t.dir = -(item.owner.physicalDir + item.owner.driftOff / 4);
|
||||
}
|
||||
if (!item.held && item.colRadius < 8) {
|
||||
item.colRadius += 0.2;
|
||||
if (item.colRadius > 8) item.colRadius = 8;
|
||||
}
|
||||
if (item.groundTime < 20) {
|
||||
var linear = (1-item.groundTime/19);
|
||||
var s = Math.sin(item.groundTime * Math.PI/8);
|
||||
|
||||
t.xyScale = [1 + s * 0.25 * linear, 1 - s * 0.25 * linear];
|
||||
} else {
|
||||
t.xyScale = [1,1];
|
||||
}
|
||||
}
|
||||
|
||||
function draw(mvMatrix, pMatrix) {
|
||||
var mat = mat4.translate(mat4.create(), mvMatrix, vec3.add(vec3.create(), item.pos, [0, item.colRadius*1.5 * t.xyScale[1], 0]));
|
||||
|
||||
var scale = 2*item.colRadius * (1 - item.holdTime/7);
|
||||
mat4.scale(mat, mat, [scale*t.xyScale[0], scale*t.xyScale[1], scale*t.xyScale[0]]);
|
||||
mat4.rotateY(mat, mat, t.dir);
|
||||
mat4.rotateZ(mat, mat, Math.PI/-6);
|
||||
mat4.rotateY(mat, mat, Math.PI/6);
|
||||
mat4.rotateX(mat, mat, Math.PI/-6);
|
||||
|
||||
/* adjust to make it rest on a corner
|
||||
if (t.angle[2] != 0) mat4.rotateZ(mat, mat, t.angle[2]*(Math.PI/180));
|
||||
if (t.angle[1] != 0) mat4.rotateY(mat, mat, t.angle[1]*(Math.PI/180));
|
||||
if (t.angle[0] != 0) mat4.rotateX(mat, mat, t.angle[0]*(Math.PI/180));
|
||||
*/
|
||||
|
||||
mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
|
||||
model.draw(mat, pMatrix, animMat);
|
||||
var mdl = scene.gameRes.items.fakeBox;
|
||||
mdl.draw(mat, pMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
window.BombC = null;
|
||||
window.BombC = function(item, scene, type) {
|
||||
var t = this;
|
||||
this.canBeHeld = true;
|
||||
this.canBeDropped = true;
|
||||
this.isDestructive = true;
|
||||
|
||||
this.isExploding = false;
|
||||
|
||||
this.collideKart = collideKart;
|
||||
this.onRest = onRest;
|
||||
this.update = update;
|
||||
|
||||
function collideKart(kart) {
|
||||
item.deadTimer = 1;
|
||||
kart.damage(MKDSCONST.DAMAGE_EXPLODE);
|
||||
}
|
||||
|
||||
function onRest(normal) {
|
||||
}
|
||||
|
||||
function update(argument) {
|
||||
if (!item.held && item.colRadius < 6) {
|
||||
item.colRadius += 0.2;
|
||||
if (item.colRadius > 6) item.colRadius = 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,97 @@
|
||||
window.GreenShellC = function(item, scene) {
|
||||
var t = this;
|
||||
this.canBeHeld = true;
|
||||
this.canBeDropped = true;
|
||||
this.isDestructive = true;
|
||||
this.angle = 0;
|
||||
this.speed = 6; //base speed + kart speed
|
||||
this.sound = null;
|
||||
this.soundCooldown = 0;
|
||||
item.colRadius = 3;
|
||||
|
||||
var minimumMove = 0.17;
|
||||
this.gravity = [0, -0.17, 0]; //100% confirmed by me messing around with the gravity value in mkds
|
||||
|
||||
this.collideKart = collideKart;
|
||||
this.update = update;
|
||||
this.release = release;
|
||||
this.onDie = onDie;
|
||||
this.colResponse = colResponse;
|
||||
|
||||
function release(forward) {
|
||||
t.sound = nitroAudio.playSound(215, {volume: 1.5}, 0, item);
|
||||
t.speed = 6;
|
||||
t.angle = item.owner.physicalDir;
|
||||
if (forward < 0) {
|
||||
t.angle += Math.PI;
|
||||
t.angle %= Math.PI*2;
|
||||
} else {
|
||||
t.speed += item.owner.speed;
|
||||
}
|
||||
}
|
||||
|
||||
function onDie(final) {
|
||||
if (!final) {
|
||||
nitroAudio.playSound(214, {volume: 2}, 0, item);
|
||||
}
|
||||
if (t.sound) {
|
||||
nitroAudio.instaKill(t.sound);
|
||||
t.sound = null;
|
||||
}
|
||||
}
|
||||
|
||||
function collideKart(kart) {
|
||||
item.deadTimer = 1;
|
||||
kart.damage(MKDSCONST.DAMAGE_FLIP);
|
||||
}
|
||||
|
||||
function update(scene) {
|
||||
item.vel = [Math.sin(t.angle)*t.speed, item.vel[1], -Math.cos(t.angle)*t.speed]
|
||||
vec3.add(item.vel, item.vel, t.gravity);
|
||||
if (this.soundCooldown > 0) this.soundCooldown--;
|
||||
}
|
||||
|
||||
function colResponse(pos, pvel, dat, ignoreList) {
|
||||
var plane = dat.plane;
|
||||
var colType = (plane.CollisionType>>8)&31;
|
||||
vec3.add(pos, pos, vec3.scale(vec3.create(), pvel, dat.t));
|
||||
|
||||
var n = dat.normal;
|
||||
vec3.normalize(n, n);
|
||||
var gravS = Math.sqrt(vec3.dot(t.gravity, t.gravity));
|
||||
var angle = Math.acos(vec3.dot(vec3.scale(vec3.create(), t.gravity, -1/gravS), n));
|
||||
var adjustPos = true
|
||||
|
||||
if (MKDS_COLTYPE.GROUP_WALL.indexOf(colType) != -1) { //wall
|
||||
//shell reflection code - slide y vel across plane, bounce on xz
|
||||
if (this.soundCooldown <= 0) {
|
||||
nitroAudio.playSound(213, {volume: 2.5}, 0, item);
|
||||
this.soundCooldown = 30;
|
||||
}
|
||||
vec3.add(item.vel, vec3.scale(vec3.create(), n, -2*(vec3.dot(item.vel, n)/vec3.dot(n,n))), item.vel);
|
||||
item.vel[1] = 0;
|
||||
|
||||
var v = item.vel;
|
||||
t.angle = Math.atan2(v[0], -v[2]);
|
||||
} else if (colType == MKDS_COLTYPE.OOB || colType == MKDS_COLTYPE.FALL) {
|
||||
if (item.deadTimer == 0) item.deadTimer++;
|
||||
} else if (MKDS_COLTYPE.GROUP_ROAD.indexOf(colType) != -1) {
|
||||
//sliding plane
|
||||
var proj = vec3.dot(item.vel, n);
|
||||
vec3.sub(item.vel, item.vel, vec3.scale(vec3.create(), n, proj));
|
||||
} else {
|
||||
adjustPos = false;
|
||||
ignoreList.push(plane);
|
||||
}
|
||||
|
||||
var rVelMag = Math.sqrt(vec3.dot(item.vel, item.vel));
|
||||
vec3.scale(item.vel, item.vel, t.speed/rVelMag); //force speed to shell speed for green shells.
|
||||
|
||||
if (adjustPos) { //move back from plane slightly
|
||||
vec3.add(pos, pos, vec3.scale(vec3.create(), n, minimumMove));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
window.RedShellC = function(item, scene) {
|
||||
@@ -11,11 +101,100 @@ window.RedShellC = function(item, scene) {
|
||||
}
|
||||
|
||||
window.ShellGroupC = function(item, scene, type) {
|
||||
this.canBeHeld = false;
|
||||
this.canBeDropped = 'func';
|
||||
var t = this;
|
||||
this.canBeHeld = "func";
|
||||
this.canBeDropped = "func";
|
||||
this.rotationPeriod = 45;
|
||||
item.colRadius = -Infinity;
|
||||
|
||||
this.draw = draw;
|
||||
this.update = update;
|
||||
this.release = release;
|
||||
this.onDie = onDie;
|
||||
|
||||
this.children = [];
|
||||
|
||||
var itemType = "koura_g";
|
||||
var itemCount = 3;
|
||||
|
||||
if (type.length > 0) {
|
||||
var typeParse = type.split("-");
|
||||
if (typeParse.length == 1) {
|
||||
itemType = type;
|
||||
} else if (typeParse.length == 2 && !isNaN(typeParse[1]-0)) {
|
||||
itemType = typeParse[0];
|
||||
itemCount = typeParse[1]-0;
|
||||
}
|
||||
}
|
||||
|
||||
this.phase = 0;
|
||||
var spinDist = 6;
|
||||
|
||||
init();
|
||||
|
||||
function init() {
|
||||
t.remaining = itemCount;
|
||||
item.holdPos = [0, 0, 0];
|
||||
//create children
|
||||
for (var i=0; i<itemCount; i++) {
|
||||
var sub = scene.items.createItem(itemType, item.owner);
|
||||
sub.holdTime = 7;
|
||||
t.children.push(sub);
|
||||
}
|
||||
nitroAudio.playSound(231, {volume: 2}, 0, item);
|
||||
this.sound = nitroAudio.playSound(227, {volume: 1.5}, 0, item);
|
||||
}
|
||||
|
||||
function onDie(final) {
|
||||
if (t.sound) {
|
||||
nitroAudio.instaKill(t.sound);
|
||||
t.sound = null;
|
||||
}
|
||||
}
|
||||
|
||||
function update(scene) {
|
||||
for (var i=0; i<t.children.length; i++) {
|
||||
var child = t.children[i];
|
||||
if (child == null) continue;
|
||||
if (child.deadTimer > 0) {
|
||||
t.children[i] = null;
|
||||
t.remaining--;
|
||||
continue;
|
||||
}
|
||||
var angle = ((i / itemCount + t.phase / t.rotationPeriod) * Math.PI * 2);
|
||||
var rad = item.owner.params.colRadius;
|
||||
var dist = spinDist + rad;
|
||||
child.holdPos = [-Math.sin(angle) * dist, -item.owner.params.colRadius, Math.cos(angle) * dist];
|
||||
}
|
||||
t.phase++;
|
||||
t.phase %= t.rotationPeriod;
|
||||
}
|
||||
|
||||
function release(forward) {
|
||||
//forward the release to our last child
|
||||
var toUse;
|
||||
|
||||
for (var i=0; i<t.children.length; i++) {
|
||||
var child = t.children[i];
|
||||
if (child == null) continue;
|
||||
if (child.deadTimer > 0) {
|
||||
t.children[i] = null;
|
||||
t.remaining--;
|
||||
continue;
|
||||
}
|
||||
toUse = child;
|
||||
t.children[i] = null;
|
||||
t.remaining--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (toUse != null) {
|
||||
toUse.release(forward);
|
||||
}
|
||||
if (t.remaining == 0) {
|
||||
item.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
function draw(mvMatrix, pMatrix) {
|
||||
//the group itself is invisible - the shells draw individually
|
||||
|
||||
+253
-165
@@ -73,6 +73,11 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
this.getPosition = getPosition;
|
||||
this.playCharacterSound = playCharacterSound;
|
||||
|
||||
//functions for external objects to trigger
|
||||
this.damage = damage;
|
||||
this.damageTime = 0;
|
||||
this.damageType = -1;
|
||||
|
||||
this.trackAttach = null; //a normal for the kart to attach to (loop)
|
||||
this.boostMT = 0;
|
||||
this.boostNorm = 0;
|
||||
@@ -399,7 +404,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
mat4.rotateX(mat, mat, c.angle[0]*(-Math.PI/180));
|
||||
|
||||
k.pos = vec3.clone(c2.pos);
|
||||
vec3.add(k.pos, k.pos, vec3.transformMat4([], [0,16,16], mat));
|
||||
vec3.add(k.pos, k.pos, vec3.transformMat4([], [0,16,32], mat));
|
||||
k.airTime = 4;
|
||||
|
||||
k.physicalDir = (180-c2.angle[1])*(Math.PI/180);
|
||||
k.angle = k.physicalDir;
|
||||
@@ -438,7 +444,6 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
}
|
||||
}
|
||||
} else { //default kart mode
|
||||
|
||||
if (k.OOB > 0) {
|
||||
playCharacterSound(0);
|
||||
var current = checkpoints[k.checkPointNumber];
|
||||
@@ -466,180 +471,176 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
var top = params.topSpeed*effect.topSpeedMul; //if you let go of accel, drift ends anyway, so always accel in drift.
|
||||
|
||||
var boosting = (k.boostNorm + k.boostMT)>0;
|
||||
|
||||
if (boosting) {
|
||||
var top2
|
||||
if (k.boostNorm>0){
|
||||
top2 = params.topSpeed*1.3;
|
||||
k.boostNorm--;
|
||||
} else {
|
||||
top2 = params.topSpeed*((effect.topSpeedMul >= 1)?1.3:effect.topSpeedMul);
|
||||
}
|
||||
|
||||
if (k.boostMT>0) {
|
||||
k.boostMT--;
|
||||
}
|
||||
|
||||
if (k.speed <= top2) {
|
||||
k.speed += 1;
|
||||
if (k.speed > top2) k.speed = top2;
|
||||
} else {
|
||||
k.speed *= 0.95;
|
||||
}
|
||||
}
|
||||
|
||||
//kart controls
|
||||
if (k.drifting) {
|
||||
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;
|
||||
}
|
||||
if (k.driftPSMode == 3) {
|
||||
k.boostMT = params.miniTurbo;
|
||||
}
|
||||
k.driftPSMode = 0;
|
||||
k.driftPSTick = 0;
|
||||
}
|
||||
|
||||
if (k.driftMode == 0) {
|
||||
if (input.turn > 0.30) {
|
||||
k.driftMode = 2;
|
||||
} else if (input.turn < -0.30) {
|
||||
k.driftMode = 1;
|
||||
}
|
||||
} else {
|
||||
if (k.driftLanded) {
|
||||
var change = (((k.driftMode-1.5)*Math.PI/1.5)-k.driftOff)*0.05;
|
||||
k.driftOff += change;
|
||||
k.physicalDir -= change;
|
||||
if (k.specialControlHandler != null) k.specialControlHandler();
|
||||
else {
|
||||
if (boosting) {
|
||||
var top2
|
||||
if (k.boostNorm>0){
|
||||
top2 = params.topSpeed*1.3;
|
||||
k.boostNorm--;
|
||||
} else {
|
||||
top2 = params.topSpeed*((effect.topSpeedMul >= 1)?1.3:effect.topSpeedMul);
|
||||
}
|
||||
|
||||
//if we're above the initial y position, add a constant turn with a period of 180 frames.
|
||||
if (!k.driftLanded && k.ylock>=0) {
|
||||
k.physicalDir += (Math.PI*2/180)*(k.driftMode*2-3);
|
||||
if (k.boostMT>0) {
|
||||
k.boostMT--;
|
||||
}
|
||||
|
||||
if (k.speed <= top2) {
|
||||
k.speed += 1;
|
||||
if (k.speed > top2) k.speed = top2;
|
||||
} else {
|
||||
k.speed *= 0.95;
|
||||
}
|
||||
}
|
||||
|
||||
if (onGround) {
|
||||
if (!k.driftLanded) {
|
||||
if (k.driftMode == 0) {
|
||||
k.drifting = false;
|
||||
clearWheelParticles();
|
||||
//kart controls
|
||||
if (k.drifting) {
|
||||
if ((onGround) && !(input.accel && input.drift && (k.speed > 2 || !k.driftLanded))) {
|
||||
//end drift, execute miniturbo
|
||||
endDrift();
|
||||
if (k.driftPSMode == 3) {
|
||||
k.boostMT = params.miniTurbo;
|
||||
}
|
||||
else {
|
||||
k.driftPSMode = 0;
|
||||
k.driftPSTick = 0;
|
||||
k.driftLanded = true;
|
||||
if (k.drifting) setWheelParticles(20, 1); //20 = smoke, 1 = drift priority
|
||||
k.driftPSMode = 0;
|
||||
k.driftPSTick = 0;
|
||||
}
|
||||
|
||||
if (k.driftMode == 0) {
|
||||
if (input.turn > 0.30) {
|
||||
k.driftMode = 2;
|
||||
} else if (input.turn < -0.30) {
|
||||
k.driftMode = 1;
|
||||
}
|
||||
} else {
|
||||
if (k.driftLanded) {
|
||||
var change = (((k.driftMode-1.5)*Math.PI/1.5)-k.driftOff)*0.05;
|
||||
k.driftOff += change;
|
||||
k.physicalDir -= change;
|
||||
}
|
||||
|
||||
//if we're above the initial y position, add a constant turn with a period of 180 frames.
|
||||
if (!k.driftLanded && k.ylock>=0) {
|
||||
k.physicalDir += (Math.PI*2/180)*(k.driftMode*2-3);
|
||||
}
|
||||
}
|
||||
if (k.drifting) {
|
||||
|
||||
if (onGround) {
|
||||
if (!k.driftLanded) {
|
||||
if (k.driftMode == 0) {
|
||||
endDrift();
|
||||
}
|
||||
else {
|
||||
k.driftPSMode = 0;
|
||||
k.driftPSTick = 0;
|
||||
k.driftLanded = true;
|
||||
if (k.drifting) setWheelParticles(20, 1); //20 = smoke, 1 = drift priority
|
||||
}
|
||||
}
|
||||
if (k.drifting) {
|
||||
|
||||
if (!boosting) {
|
||||
if (k.speed <= top) {
|
||||
k.speed += (k.speed/top > params.driftAccelSwitch)?params.driftAccel2:params.driftAccel1;
|
||||
if (k.speed > top) k.speed = top;
|
||||
} else {
|
||||
k.speed *= 0.95;
|
||||
}
|
||||
}
|
||||
|
||||
var turn = ((k.driftMode == 1)?(input.turn-1):(input.turn+1))/2;
|
||||
|
||||
k.physicalDir += params.driftTurnRate*turn+((k.driftMode == 1)?-1:1)*(50/32768)*Math.PI; //what is this mystery number i hear you ask? well my friend, this is the turn rate for outward drift.
|
||||
|
||||
//miniturbo code
|
||||
if (input.turn != 0) {
|
||||
var inward = ((input.turn>0) == k.driftMode-1); //if we're turning
|
||||
|
||||
switch (k.driftPSMode) {
|
||||
case 0: //dpad away from direction for 10 frames
|
||||
if (!inward) k.driftPSTick++;
|
||||
else if (k.driftPSTick > 9) {
|
||||
k.driftPSMode++;
|
||||
k.driftPSTick = 1;
|
||||
|
||||
//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;
|
||||
|
||||
} else k.driftPSTick = 0;
|
||||
break;
|
||||
case 1: //dpad toward direction for 10 frames
|
||||
if (inward) k.driftPSTick++;
|
||||
else if (k.driftPSTick > 9) {
|
||||
k.driftPSMode++;
|
||||
k.driftPSTick = 1;
|
||||
|
||||
} else k.driftPSTick = 0;
|
||||
break;
|
||||
case 2: //dpad away from direction for 10 frames
|
||||
if (!inward) k.driftPSTick++;
|
||||
else if (k.driftPSTick > 9) {
|
||||
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 ... 18 is sparks that come out - but their mode is not working yet (spark mode)
|
||||
sounds.powerslide = nitroAudio.playSound(209, {}, 0, k);
|
||||
sounds.powerslide.gainN.gain.value = 2;
|
||||
} else k.driftPSTick = 0;
|
||||
break;
|
||||
case 3: //turbo charged
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!k.drifting) {
|
||||
if (onGround) {
|
||||
var effect = params.colParam[groundEffect];
|
||||
if (!boosting) {
|
||||
if (k.speed <= top) {
|
||||
k.speed += (k.speed/top > params.driftAccelSwitch)?params.driftAccel2:params.driftAccel1;
|
||||
if (k.speed > top) k.speed = top;
|
||||
if (input.accel) {
|
||||
if (k.speed <= top) {
|
||||
k.speed += (k.speed/top > params.accelSwitch)?params.accel2:params.accel1;
|
||||
if (k.speed > top) k.speed = top;
|
||||
} else {
|
||||
k.speed *= 0.95;
|
||||
}
|
||||
} else {
|
||||
k.speed *= 0.95;
|
||||
k.speed *= params.decel;
|
||||
}
|
||||
}
|
||||
|
||||
var turn = ((k.driftMode == 1)?(input.turn-1):(input.turn+1))/2;
|
||||
|
||||
k.physicalDir += params.driftTurnRate*turn+((k.driftMode == 1)?-1:1)*(50/32768)*Math.PI; //what is this mystery number i hear you ask? well my friend, this is the turn rate for outward drift.
|
||||
|
||||
//miniturbo code
|
||||
if (input.turn != 0) {
|
||||
var inward = ((input.turn>0) == k.driftMode-1); //if we're turning
|
||||
|
||||
switch (k.driftPSMode) {
|
||||
case 0: //dpad away from direction for 10 frames
|
||||
if (!inward) k.driftPSTick++;
|
||||
else if (k.driftPSTick > 9) {
|
||||
k.driftPSMode++;
|
||||
k.driftPSTick = 1;
|
||||
|
||||
//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;
|
||||
|
||||
} else k.driftPSTick = 0;
|
||||
break;
|
||||
case 1: //dpad toward direction for 10 frames
|
||||
if (inward) k.driftPSTick++;
|
||||
else if (k.driftPSTick > 9) {
|
||||
k.driftPSMode++;
|
||||
k.driftPSTick = 1;
|
||||
|
||||
} else k.driftPSTick = 0;
|
||||
break;
|
||||
case 2: //dpad away from direction for 10 frames
|
||||
if (!inward) k.driftPSTick++;
|
||||
else if (k.driftPSTick > 9) {
|
||||
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;
|
||||
break;
|
||||
case 3: //turbo charged
|
||||
break;
|
||||
}
|
||||
if ((input.accel && k.speed >= 0) || (k.speed > 0.1)) {
|
||||
k.physicalDir += params.turnRate*input.turn;
|
||||
} else if ( k.speed < -0.1) {
|
||||
k.physicalDir -= params.turnRate*input.turn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!k.drifting) {
|
||||
if (onGround) {
|
||||
var effect = params.colParam[groundEffect];
|
||||
if (!boosting) {
|
||||
if (input.accel) {
|
||||
if (k.speed <= top) {
|
||||
k.speed += (k.speed/top > params.accelSwitch)?params.accel2:params.accel1;
|
||||
if (k.speed > top) k.speed = top;
|
||||
} else {
|
||||
k.speed *= 0.95;
|
||||
}
|
||||
} else {
|
||||
k.speed *= params.decel;
|
||||
if (input.drift) {
|
||||
ylvel = 1.25;
|
||||
k.vel[1] += 1.25;
|
||||
k.airTime = 4;
|
||||
k.drifting = true;
|
||||
k.driftLanded = false;
|
||||
k.driftMode = 0;
|
||||
k.ylock = 0;
|
||||
onGround = false;
|
||||
|
||||
var boing = nitroAudio.playSound(207, {transpose: -4}, 0, k);
|
||||
boing.gainN.gain.value = 2;
|
||||
}
|
||||
} else {
|
||||
if (input.drift) {
|
||||
ylvel = 0;
|
||||
k.drifting = true;
|
||||
k.driftLanded = false;
|
||||
k.driftMode = 0;
|
||||
k.ylock = -0.001;
|
||||
}
|
||||
}
|
||||
|
||||
if ((input.accel && k.speed >= 0) || (k.speed > 0.1)) {
|
||||
k.physicalDir += params.turnRate*input.turn;
|
||||
} else if ( k.speed < -0.1) {
|
||||
k.physicalDir -= params.turnRate*input.turn;
|
||||
}
|
||||
|
||||
if (input.drift) {
|
||||
ylvel = 1.25;
|
||||
k.vel[1] += 1.25;
|
||||
k.airTime = 4;
|
||||
k.drifting = true;
|
||||
k.driftLanded = false;
|
||||
k.driftMode = 0;
|
||||
k.ylock = 0;
|
||||
onGround = false;
|
||||
|
||||
var boing = nitroAudio.playSound(207, {transpose: -4}, 0, k);
|
||||
boing.gainN.gain.value = 2;
|
||||
}
|
||||
} else {
|
||||
if (input.drift) {
|
||||
ylvel = 0;
|
||||
k.drifting = true;
|
||||
k.driftLanded = false;
|
||||
k.driftMode = 0;
|
||||
k.ylock = -0.001;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -708,8 +709,6 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
|
||||
//move kart.
|
||||
|
||||
|
||||
|
||||
var steps = 0;
|
||||
var remainingT = 1;
|
||||
var baseVel = k.vel;
|
||||
@@ -754,6 +753,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
var mat = mat4.create();
|
||||
mat4.translate(mat, mat, k.pos);
|
||||
k.mat = mat4.mul(mat, mat, k.basis);
|
||||
if (k.damageMat != null) mat4.mul(mat, mat, k.damageMat);
|
||||
|
||||
if (input.item) {
|
||||
scene.items.addItem(0, scene.karts.indexOf(k), {})
|
||||
@@ -763,6 +763,83 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
positionChanged(lastPos, k.pos);
|
||||
}
|
||||
|
||||
function endDrift() {
|
||||
k.drifting = false;
|
||||
clearWheelParticles();
|
||||
if (sounds.powerslide != null) {
|
||||
nitroAudio.instaKill(sounds.powerslide);
|
||||
sounds.powerslide = null;
|
||||
}
|
||||
}
|
||||
|
||||
function damage(damageType) {
|
||||
if (k.damageType >= damageType) {
|
||||
return; //we are already damaged
|
||||
}
|
||||
//TODO: check invuln state
|
||||
k.specialControlHandler = damagedControls;
|
||||
playCharacterSound((damageType == 0) ? 1 : 0);
|
||||
k.damageType = damageType;
|
||||
k.ylock = 0;
|
||||
|
||||
k.anim.setAnim(k.charRes.spinA);
|
||||
k.animMode = "spin";
|
||||
|
||||
if (k.drifting) {
|
||||
endDrift();
|
||||
}
|
||||
k.boostMT = 0;
|
||||
k.boostNorm = 0;
|
||||
|
||||
switch (damageType) {
|
||||
case 0:
|
||||
k.damageTime = 40;
|
||||
break;
|
||||
case 1:
|
||||
k.damageTime = 80;
|
||||
k.vel[1] += 3;
|
||||
ylvel = 3;
|
||||
k.airTime = 4;
|
||||
break;
|
||||
case 2:
|
||||
k.damageTime = 105;
|
||||
k.vel[1] += 8;
|
||||
ylvel = 8;
|
||||
k.airTime = 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function damagedControls(kart) {
|
||||
if (--k.damageTime == 0) {
|
||||
k.anim.setAnim(k.charRes.driveA);
|
||||
k.animMode = "drive";
|
||||
k.specialControlHandler = null;
|
||||
k.damageType = -1;
|
||||
k.damageMat = null;
|
||||
}
|
||||
vec3.scale(k.vel, k.vel, 0.98);
|
||||
k.speed *= 0.98;
|
||||
|
||||
var total = 40;
|
||||
switch (k.damageType) {
|
||||
case 1:
|
||||
total = 80;
|
||||
break;
|
||||
case 2:
|
||||
total = 105;
|
||||
break;
|
||||
}
|
||||
var anim = 1 - (k.damageTime / total);
|
||||
|
||||
k.damageMat = mat4.create();
|
||||
var flip = ((k.damageType%2) == 1)? 1 : -1;
|
||||
var animOff = Math.min(1, anim*1.75);
|
||||
mat4.rotateX(k.damageMat, k.damageMat, Math.PI*2 * animOff * k.damageType * flip);
|
||||
if (k.damageType == 0) mat4.rotateY(k.damageMat, k.damageMat, Math.PI*-2 * anim);
|
||||
else mat4.rotateY(k.damageMat, k.damageMat, Math.PI/12 * Math.sin(animOff*Math.PI));
|
||||
}
|
||||
|
||||
function triggerCannon(id) {
|
||||
if (k.cannon != null) return;
|
||||
k.cannon = id;
|
||||
@@ -923,7 +1000,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
|
||||
k.kartColVel[1] = 0;
|
||||
//play this kart's horn
|
||||
nitroAudio.playSound(192 + charRes.sndOff/14, { volume: 2 }, 0, k);
|
||||
nitroAudio.playSound(193 + charRes.sndOff/14, { volume: 2 }, 0, k);
|
||||
}
|
||||
|
||||
function fixDir(dir) {
|
||||
@@ -940,6 +1017,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
}
|
||||
|
||||
function updateKartSound(mode, input) {
|
||||
if (!k.local) return; //for now, don't play kart sounds from other racers.
|
||||
var turn = (onGround && !k.drifting)?(1-Math.abs(input.turn)/11):1;
|
||||
var transpose = (mode == 0)?0:(22*turn*Math.min(1.3, k.speed/params.topSpeed));
|
||||
|
||||
@@ -1028,12 +1106,15 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
}
|
||||
|
||||
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);
|
||||
else k.soundProps.vel = [0, 0, 0];
|
||||
*/
|
||||
k.soundProps.lastPos = k.soundProps.pos;
|
||||
k.soundProps.pos = k.pos; //todo: reintroduce doppler via emulation
|
||||
|
||||
k.soundProps.refDistance = 192/1024;
|
||||
k.soundProps.refDistance = 192;
|
||||
k.soundProps.rolloffFactor = 1;
|
||||
|
||||
var calcVol = (k.soundProps.refDistance / (k.soundProps.refDistance + k.soundProps.rolloffFactor * (Math.sqrt(vec3.dot(k.soundProps.pos, k.soundProps.pos)) - k.soundProps.refDistance)));
|
||||
@@ -1080,7 +1161,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
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) {
|
||||
if (MKDS_COLTYPE.GROUP_OOB.indexOf(colType) != -1) {
|
||||
k.OOB = 1;
|
||||
}
|
||||
|
||||
@@ -1101,12 +1182,18 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
}
|
||||
vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), adjN, proj));
|
||||
|
||||
if (colType == MKDS_COLTYPE.KNOCKBACK_DAMAGE && k.damageType == -1) {
|
||||
if (dat.object.vel) vec3.add(k.vel, k.vel, dat.object.vel);
|
||||
vec3.add(k.vel, k.vel, vec3.scale(vec3.create(), adjN, 1.25));
|
||||
k.damage(MKDSCONST.DAMAGE_FLIP);
|
||||
}
|
||||
|
||||
//convert back to angle + speed to keep change to kart vel
|
||||
|
||||
var v = k.vel;
|
||||
k.speed = Math.sqrt(v[0]*v[0]+v[2]*v[2]);
|
||||
k.angle = Math.atan2(v[0], -v[2]);
|
||||
stuckTo = dat.object;
|
||||
} else if (MKDS_COLTYPE.GROUP_ROAD.indexOf(colType) != -1) {
|
||||
//sliding plane
|
||||
if (MKDS_COLTYPE.GROUP_BOOST.indexOf(colType) != -1) {
|
||||
@@ -1117,7 +1204,8 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
|
||||
|
||||
if (k.vel[1] > 0) k.vel[1] = 0;
|
||||
var proj = vec3.dot(k.vel, an);
|
||||
if (!stick && proj < -4 && k.vel[1] < -2) { proj -= 1.5; }
|
||||
if (k.damageType > 0) proj *= 1.7;
|
||||
else 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) {
|
||||
|
||||
@@ -2,19 +2,20 @@
|
||||
|
||||
window.KartItems = function(kart, scene) {
|
||||
var t = this;
|
||||
t.heldItem = null; //of type Item
|
||||
t.heldItem = null; //held item, or item that is bound to us. (bound items have hold type 'func', eg. triple shell)
|
||||
t.currentItem = null; //string name for item
|
||||
t.specificItem = null;
|
||||
t.empty = true;
|
||||
t.cycleTime = 0;
|
||||
t.totalTime = 230;
|
||||
|
||||
var maxItemTime = 230;
|
||||
var minItemTime = 80;
|
||||
var carouselSfx = null;
|
||||
var lastItemState = false;
|
||||
var holdAppearDelay = 15;
|
||||
|
||||
var hurtExplodeDelay = 105 //turn right slightly, huge double backflip, small bounces.
|
||||
var hurtExplodeDelay = 105; //turn right slightly, huge double backflip, small bounces.
|
||||
var hurtFlipDelay = 80; //turn right slightly, bounce twice, forward flip
|
||||
var hurtSpinDelay = 40; //counter clockwise spin
|
||||
|
||||
@@ -43,8 +44,22 @@ window.KartItems = function(kart, scene) {
|
||||
}
|
||||
}
|
||||
|
||||
function createItem() {
|
||||
var item = scene.items.createItem(t.currentItem, kart);
|
||||
return item;
|
||||
}
|
||||
|
||||
function release(input) {
|
||||
if (t.heldItem != null) {
|
||||
t.heldItem.release(input.airTurn);
|
||||
}
|
||||
t.heldItem = null;
|
||||
kart.playCharacterSound(7);
|
||||
}
|
||||
|
||||
function update(input) {
|
||||
var pressed = (input.item && !lastItemState);
|
||||
var released = (lastItemState && !input.item);
|
||||
if (!t.empty) {
|
||||
if (t.currentItem == null) {
|
||||
//carousel
|
||||
@@ -53,24 +68,48 @@ window.KartItems = function(kart, scene) {
|
||||
if (carouselSfx != null) nitroAudio.kill(carouselSfx);
|
||||
|
||||
//decide on an item
|
||||
var item = "koura_g";
|
||||
var item = "banana"; //koura_g, banana, f_box, koura_group, koura_group-bomb-7
|
||||
sfx((specialItems.indexOf(item) == -1) ? 63 : 64);
|
||||
t.currentItem = item;
|
||||
} else {
|
||||
//if item button is pressed, we speed up the carousel
|
||||
if (pressed) {
|
||||
if (pressed && t.heldItem == null) {
|
||||
t.totalTime = Math.max(minItemTime, t.totalTime - 20);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (t.heldItem == null) {
|
||||
if (pressed) {
|
||||
//fire?
|
||||
t.currentItem = null;
|
||||
t.empty = true;
|
||||
kart.playCharacterSound(7);
|
||||
t.heldItem = createItem();
|
||||
//t.currentItem = null;
|
||||
//t.empty = true;
|
||||
|
||||
if (t.heldItem.canBeHeld()) {
|
||||
//begin holding
|
||||
} else {
|
||||
release(input);
|
||||
}
|
||||
pressed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//todo: if held item has been destroyed, stop holding it.
|
||||
|
||||
if (t.heldItem != null) {
|
||||
if (t.heldItem.dead) {
|
||||
t.heldItem = null;
|
||||
} else {
|
||||
//t.heldItem.updateHold(kart);
|
||||
if (released) {
|
||||
if (t.heldItem.canBeHeld() !== 'func') release(input);
|
||||
} else if (pressed) {
|
||||
//special release: triple shells, bananas. object stays bound when released
|
||||
t.heldItem.release(input.airTurn);
|
||||
kart.playCharacterSound(7);
|
||||
if (t.heldItem.dead) t.heldItem = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastItemState = input.item;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ window.objDatabase = new (function(){
|
||||
t[0x0195] = ObjBus;
|
||||
|
||||
|
||||
t[0x00CC] = ObjDecor; //DEBUG: pianta bridge
|
||||
t[0x00CC] = ObjBridge; //DEBUG: pianta bridge
|
||||
t[0x000D] = ObjDecor; //DEBUG: puddle
|
||||
|
||||
t[0x0158] = ObjDecor; //DEBUG: airship (routed)
|
||||
|
||||
@@ -41,11 +41,15 @@ window.ObjGear = function(obji, scene) {
|
||||
t.angle = 0;
|
||||
t.dir = (t.wB1 == 0)
|
||||
|
||||
t.colFrame = 0;
|
||||
|
||||
var colRes;
|
||||
|
||||
var dirVel = 0;
|
||||
|
||||
var prevMat;
|
||||
var curMat;
|
||||
setMat();
|
||||
var colMat = mat4.create();
|
||||
prevMat = curMat;
|
||||
|
||||
function setMat() {
|
||||
@@ -59,6 +63,8 @@ window.ObjGear = function(obji, scene) {
|
||||
mat4.rotateX(mat, mat, obji.angle[0]*(Math.PI/180));
|
||||
|
||||
mat4.rotateY(mat, mat, t.angle);
|
||||
mat4.scale(colMat, mat, [colRes.scale, colRes.scale, colRes.scale]);
|
||||
t.colFrame++;
|
||||
curMat = mat;
|
||||
}
|
||||
|
||||
@@ -119,43 +125,24 @@ window.ObjGear = function(obji, scene) {
|
||||
}
|
||||
}
|
||||
|
||||
function cloneKCL(kcl) {
|
||||
return JSON.parse(JSON.stringify(kcl));
|
||||
}
|
||||
|
||||
function provideRes(r) {
|
||||
res = r; //...and gives them to us. :)
|
||||
colRes = cloneKCL(res.mdl[0].getCollisionModel(0, 0));
|
||||
}
|
||||
|
||||
function getCollision() {
|
||||
var obj = {};
|
||||
var inf = res.mdl[0].getCollisionModel(0, 0);
|
||||
obj.tris = inf.dat;
|
||||
|
||||
var mat = mat4.translate([], mat4.create(), t.pos);
|
||||
mat4.scale(mat, mat, vec3.mul([], [16*inf.scale, 16*inf.scale, 16*inf.scale], t.scale));
|
||||
|
||||
mat4.rotateY(mat, mat, obji.angle[1]*(Math.PI/180));
|
||||
mat4.rotateX(mat, mat, obji.angle[0]*(Math.PI/180));
|
||||
mat4.rotateY(mat, mat, t.angle);
|
||||
|
||||
obj.mat = mat;
|
||||
return obj;
|
||||
return { tris: colRes.dat, mat: colMat, frame: t.colFrame };
|
||||
}
|
||||
|
||||
function moveWith(obj) { //used for collidable objects that move.
|
||||
|
||||
//the most general way to move something with an object is to multiply its position by the inverse mv matrix of that object, and then the new mv matrix.
|
||||
|
||||
vec3.transformMat4(obj.pos, obj.pos, mat4.invert([], prevMat))
|
||||
vec3.transformMat4(obj.pos, obj.pos, curMat)
|
||||
|
||||
/*var p = vec3.sub([], obj.pos, t.pos);
|
||||
|
||||
if (obji.ID == 0x00D1) { //todo: maybe something more general
|
||||
vec3.transformMat4(p, p, mat4.rotateX([], mat4.create(), dirVel));
|
||||
vec3.add(obj.pos, t.pos, p);
|
||||
} else {
|
||||
vec3.transformMat4(p, p, mat4.rotateY([], mat4.create(), dirVel));
|
||||
vec3.add(obj.pos, t.pos, p);
|
||||
obj.physicalDir -= dirVel;
|
||||
}*/
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,7 +34,7 @@ window.GreenShell = function(scene, owner, time, itemID, cliID, params) {
|
||||
var posSeg = vec3.clone(t.pos);
|
||||
var ignoreList = [];
|
||||
while (steps++ < 10 && remainingT > 0.01) {
|
||||
var result = lsc.raycast(posSeg, velSeg, scene.kcl, 0.05, ignoreList);
|
||||
var result = lsc.raycast(posSeg, velSeg, kcl, 0.05, ignoreList);
|
||||
if (result != null) {
|
||||
colResponse(posSeg, velSeg, result, ignoreList)
|
||||
remainingT -= result.t;
|
||||
@@ -87,7 +87,9 @@ window.GreenShell = function(scene, owner, time, itemID, cliID, params) {
|
||||
|
||||
var v = t.vel;
|
||||
t.angle = Math.atan2(v[0], -v[2]);
|
||||
|
||||
item.safeKart = null;
|
||||
} else if (colType == MKDS_COLTYPE.OOB || colType == MKDS_COLTYPE.FALL) {
|
||||
if (item.deadTimer == 0) item.deadTimer++;
|
||||
} else if (MKDS_COLTYPE.GROUP_ROAD.indexOf(colType) != -1) {
|
||||
//sliding plane
|
||||
var proj = vec3.dot(t.vel, n);
|
||||
|
||||
@@ -44,16 +44,20 @@ window.ObjSoundMaker = function(obji, scene) {
|
||||
}
|
||||
|
||||
function sndUpdate(view) {
|
||||
t.soundProps.pos = vec3.transformMat4([], t.pos, view);
|
||||
t.soundProps.pos = [0, 0, Math.sqrt(vec3.dot(t.soundProps.pos, t.soundProps.pos))]
|
||||
//t.soundProps.pos = vec3.transformMat4([], t.pos, view);
|
||||
//t.soundProps.pos = [0, 0, Math.sqrt(vec3.dot(t.soundProps.pos, t.soundProps.pos))]
|
||||
//if (t.soundProps.lastPos != null) t.soundProps.vel = vec3.sub([], t.soundProps.pos, t.soundProps.lastPos);
|
||||
//else t.soundProps.vel = [0, 0, 0];
|
||||
//t.soundProps.lastPos = t.soundProps.pos;
|
||||
|
||||
t.soundProps.refDistance = 1024/1024;
|
||||
t.soundProps.pos = t.pos; //todo: when reintroducing doppler, disable it on this source
|
||||
|
||||
t.soundProps.refDistance = 1024;
|
||||
//t.soundProps.rolloffFactor = 1;
|
||||
|
||||
var calcVol = (t.soundProps.refDistance / (t.soundProps.refDistance + t.soundProps.rolloffFactor * (t.soundProps.pos[2] - t.soundProps.refDistance)));
|
||||
var relPos = vec3.transformMat4([], t.pos, view);
|
||||
|
||||
var calcVol = (t.soundProps.refDistance / (t.soundProps.refDistance + t.soundProps.rolloffFactor * (relPos[2] - t.soundProps.refDistance)));
|
||||
|
||||
if (calcVol<threshold) {
|
||||
if (sound != null) {
|
||||
|
||||
+133
-18
@@ -17,6 +17,7 @@ window.ObjTruck = function(obji, scene) {
|
||||
t.pos = vec3.clone(obji.pos);
|
||||
//t.angle = vec3.clone(obji.angle);
|
||||
t.scale = vec3.clone(obji.scale);
|
||||
t.vel = vec3.create();
|
||||
|
||||
t.requireRes = requireRes;
|
||||
t.provideRes = provideRes;
|
||||
@@ -24,45 +25,138 @@ window.ObjTruck = function(obji, scene) {
|
||||
t.draw = draw;
|
||||
|
||||
t.route = scene.paths[obji.routeID];
|
||||
t.routeSpeed = (obji.setting1>>16)/100;
|
||||
t.routePos = (obji.setting1&0xFFFF)%t.route.length;
|
||||
t.routeSpeed = 0.01;
|
||||
t.unknown = (obji.setting1&0xFFFF);
|
||||
t.routePos = (obji.setting1>>16); //(obji.setting1&0xFFFF)%t.route.length;
|
||||
t.variant = (obji.setting2&0xFFFF); //sets design for this car (from nsbtp)
|
||||
t.variant2 = (obji.setting2>>16); //0 or 1. unknown purpose
|
||||
|
||||
t.routePos = (t.routePos+1)%t.route.length;
|
||||
|
||||
t.nodes = [
|
||||
t.route[(t.routePos+t.route.length-2)%t.route.length].pos,
|
||||
t.route[(t.routePos+t.route.length-1)%t.route.length].pos,
|
||||
t.route[t.routePos].pos,
|
||||
t.route[(t.routePos+1)%t.route.length].pos
|
||||
];
|
||||
|
||||
t.nextNode = t.route[t.routePos];
|
||||
t.prevPos = t.pos;
|
||||
t.elapsedTime = 0;
|
||||
|
||||
var facingNormal = [0, 1, 0];
|
||||
var curNormal = [0, 1, 0];
|
||||
var curFloorNormal = [0, 1, 0];
|
||||
var floorNormal = [0, 1, 0];
|
||||
|
||||
//collision stuff
|
||||
t.collidable = true;
|
||||
t.colMode = 0;
|
||||
t.colRad = 512;
|
||||
t.colFrame = 0;
|
||||
t.moveWith = moveWith;
|
||||
t.getCollision = getCollision;
|
||||
|
||||
var colRes;
|
||||
|
||||
var dirVel = 0;
|
||||
|
||||
var prevMat;
|
||||
var curMat;
|
||||
var colMat = mat4.create();
|
||||
prevMat = curMat;
|
||||
|
||||
function setMat() {
|
||||
prevMat = curMat;
|
||||
var mat = mat4.create();
|
||||
mat4.translate(mat, mat, t.pos);
|
||||
|
||||
mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
|
||||
|
||||
mat4.mul(mat, mat, mat4.invert([], mat4.lookAt([], [0, 0, 0], curNormal, curFloorNormal)));
|
||||
mat4.scale(colMat, mat, [colRes.scale, colRes.scale, colRes.scale]);
|
||||
t.colFrame++;
|
||||
curMat = mat;
|
||||
}
|
||||
|
||||
//end collision stuff
|
||||
|
||||
function cubic1D(y0, y1, y2, y3, i) {
|
||||
var a0, a1, a2, a3, i2;
|
||||
|
||||
i2 = i*i;
|
||||
a0 = -0.5*y0 + 1.5*y1 - 1.5*y2 + 0.5*y3;
|
||||
a1 = y0 - 2.5*y1 + 2*y2 - 0.5*y3;
|
||||
a2 = -0.5*y0 + 0.5*y2;
|
||||
a3 = y1;
|
||||
|
||||
return(a0 * i * i2 + a1 * i2 + a2 * i + a3);
|
||||
}
|
||||
|
||||
function cubic3D(points, i) { //note: i is 0-1 between point 1 and 2. (0 and 3 are used to better define the curve)
|
||||
var p0 = points[0];
|
||||
var p1 = points[1];
|
||||
var p2 = points[2];
|
||||
var p3 = points[3];
|
||||
return [
|
||||
cubic1D(p0[0], p1[0], p2[0], p3[0], i),
|
||||
cubic1D(p0[1], p1[1], p2[1], p3[1], i),
|
||||
cubic1D(p0[2], p1[2], p2[2], p3[2], i)
|
||||
];
|
||||
}
|
||||
|
||||
function update(scene) {
|
||||
//simple behaviour, just follow the path! piece of cake.
|
||||
|
||||
//recalculate our route speed using a target real world speed.
|
||||
var nextTime = t.elapsedTime + t.routeSpeed;
|
||||
for (var i=0; i<((t.elapsedTime == 0)?3:1); i++) {
|
||||
if (nextTime < 1) {
|
||||
var targSpeed = 2;
|
||||
var estimate = cubic3D(t.nodes, nextTime);
|
||||
var estDistance = vec3.dist(estimate, t.pos);
|
||||
t.routeSpeed *= targSpeed/estDistance; //correct
|
||||
if (t.routeSpeed > 0.2) t.routeSpeed = 0.2;
|
||||
}
|
||||
}
|
||||
if (t.routeSpeed <= 0) t.routeSpeed = 0.01;
|
||||
|
||||
t.elapsedTime += t.routeSpeed;
|
||||
t.pos = vec3.lerp([], t.prevPos, t.nextNode.pos, t.elapsedTime/t.nextNode.duration);
|
||||
if (t.elapsedTime >= t.nextNode.duration) {
|
||||
t.elapsedTime = 0;
|
||||
t.prevPos = t.nextNode.pos;
|
||||
var i = t.elapsedTime;
|
||||
|
||||
var newPos = cubic3D(t.nodes, i); //vec3.lerp([], t.prevPos, t.nextNode.pos, i);
|
||||
vec3.sub(t.vel, newPos, t.pos);
|
||||
t.pos = newPos;
|
||||
|
||||
if (t.elapsedTime >= 1) {
|
||||
t.elapsedTime -= 1;
|
||||
|
||||
t.routePos = (t.routePos+1)%t.route.length;
|
||||
t.nextNode = t.route[t.routePos];
|
||||
t.nodes.splice(0, 1);
|
||||
t.nodes.push(t.route[(t.routePos+1)%t.route.length].pos);
|
||||
t.routeSpeed = 0.25;
|
||||
}
|
||||
|
||||
facingNormal = vec3.sub([], t.prevPos, t.nextNode.pos)
|
||||
vec3.normalize(facingNormal, facingNormal);
|
||||
|
||||
var rate = 0.025
|
||||
curNormal[0] += (facingNormal[0]-curNormal[0])*rate;
|
||||
curNormal[1] += (facingNormal[1]-curNormal[1])*rate;
|
||||
curNormal[2] += (facingNormal[2]-curNormal[2])*rate;
|
||||
curNormal = vec3.sub([], t.prevPos, t.pos)
|
||||
t.prevPos = vec3.clone(t.pos);
|
||||
vec3.normalize(curNormal, curNormal);
|
||||
if (isNaN(curNormal[0])) curNormal = [0, 0, 1];
|
||||
|
||||
var spos = vec3.clone(t.pos);
|
||||
spos[1] += 32;
|
||||
var result = lsc.raycast(spos, [0, -100, 0], scene.kcl, 0.05, []);
|
||||
var result = lsc.raycast(spos, [0, -100, 0], scene, 0.05, []);
|
||||
if (result != null) {
|
||||
floorNormal = result.normal;
|
||||
} else {
|
||||
floorNormal = [0,1,0];
|
||||
}
|
||||
|
||||
var rate = 0.025;
|
||||
curFloorNormal[0] += (floorNormal[0]-curFloorNormal[0])*rate;
|
||||
curFloorNormal[1] += (floorNormal[1]-curFloorNormal[1])*rate;
|
||||
curFloorNormal[2] += (floorNormal[2]-curFloorNormal[2])*rate;
|
||||
vec3.normalize(curFloorNormal, curFloorNormal);
|
||||
setMat();
|
||||
}
|
||||
|
||||
function draw(view, pMatrix) {
|
||||
@@ -70,23 +164,44 @@ window.ObjTruck = function(obji, scene) {
|
||||
|
||||
mat4.scale(mat, mat, vec3.scale([], t.scale, 16));
|
||||
|
||||
mat4.mul(mat, mat, mat4.invert([], mat4.lookAt([], [0, 0, 0], curNormal, floorNormal)));
|
||||
mat4.mul(mat, mat, mat4.invert([], mat4.lookAt([], [0, 0, 0], curNormal, curFloorNormal)));
|
||||
res.mdl[0].setFrame(t.variant);
|
||||
res.mdl[0].draw(mat, pMatrix);
|
||||
}
|
||||
|
||||
function requireRes() { //scene asks what resources to load
|
||||
switch (obji.ID) {
|
||||
case 0x019A:
|
||||
return {mdl:[{nsbmd:"car_a.nsbmd"}]}; //one model, car
|
||||
return {mdl:[{nsbmd:"car_a.nsbmd"}], other:["car_a.nsbtp"]}; //one model, car
|
||||
case 0x019C:
|
||||
return {mdl:[{nsbmd:"truck_a.nsbmd"}]}; //one model, truck
|
||||
return {mdl:[{nsbmd:"truck_a.nsbmd"}], other:["truck_a.nsbtp"]}; //one model, truck
|
||||
case 0x0195:
|
||||
return {mdl:[{nsbmd:"bus_a.nsbmd"}]}; //one model, bus
|
||||
}
|
||||
}
|
||||
|
||||
function moveWith(obj) { //used for collidable objects that move.
|
||||
//the most general way to move something with an object is to multiply its position by the inverse mv matrix of that object, and then the new mv matrix.
|
||||
|
||||
vec3.transformMat4(obj.pos, obj.pos, mat4.invert([], prevMat))
|
||||
vec3.transformMat4(obj.pos, obj.pos, curMat);
|
||||
}
|
||||
|
||||
function getCollision() {
|
||||
return { tris: colRes.dat, mat: colMat, frame: t.colFrame };
|
||||
}
|
||||
|
||||
function provideRes(r) {
|
||||
res = r; //...and gives them to us. :)
|
||||
if (r.other != null) {
|
||||
if (r.other.length > 0 && r.other[0] != null) {
|
||||
res.mdl[0].loadTexPAnim(r.other[0]);
|
||||
}
|
||||
}
|
||||
colRes = res.mdl[0].getBoundingCollisionModel(0, 0);
|
||||
for (var i=0; i<colRes.dat.length; i++) {
|
||||
colRes.dat[i].CollisionType = MKDS_COLTYPE.KNOCKBACK_DAMAGE << 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-12
@@ -23,6 +23,10 @@ window.ObjWater = function(obji, scene) {
|
||||
t.update = update;
|
||||
t.draw = draw;
|
||||
var frame = 0;
|
||||
var wheight = 6.144;
|
||||
var wosc = 12.288;
|
||||
var wstay = 5*60;
|
||||
var wchange = 4*60;
|
||||
|
||||
function draw(view, pMatrix) {
|
||||
if (nitroRender.flagShadow) return;
|
||||
@@ -34,34 +38,35 @@ window.ObjWater = function(obji, scene) {
|
||||
gl.stencilFunc(gl.ALWAYS, 1, 0xFF);
|
||||
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE); //when depth test passes for water lower layer, pixel is already drawn, do not cover it with the white overlay (set stencil bit)
|
||||
|
||||
var height = (t.pos[1])+6.144+Math.sin(frame/150)*12.288 //0.106
|
||||
var height = (t.pos[1])+wheight+Math.sin(frame/150)*wosc //0.106
|
||||
|
||||
mat4.translate(waterM, view, [Math.sin(frame/180)*96, height-3.072, Math.cos(frame/146)*96])
|
||||
nitroRender.setAlpha(0x0A/31);
|
||||
mat4.translate(waterM, view, [Math.sin(frame/180)*96, height, Math.cos(frame/146)*96])
|
||||
nitroRender.setColMult([1, 1, 1, 0x0A/31]);
|
||||
res.mdl[0].drawPoly(mat4.scale([], waterM, [16, 16, 16]), pMatrix, 0, 0); //water
|
||||
|
||||
if (res.mdl[1] != null) {
|
||||
mat4.translate(waterM, view, [-Math.sin((frame+30)/180)*96, height-3, Math.cos((frame+100)/146)*96])
|
||||
nitroRender.setAlpha(0x02/31);
|
||||
res.mdl[1].draw(mat4.scale([], waterM, [16, 16, 16]), pMatrix); //water white detail part. stencil should do nothing here, since it's in the same position as the above.
|
||||
}
|
||||
|
||||
gl.stencilFunc(gl.EQUAL, 0, 0xFF);
|
||||
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
|
||||
|
||||
if (!obji.ID == 9) {
|
||||
if (obji.ID != 9) {
|
||||
mat4.translate(waterM, view, [0, height, 0])
|
||||
nitroRender.setAlpha(0x10/31);
|
||||
nitroRender.setColMult([1, 1, 1, 0x10/31]);
|
||||
res.mdl[0].drawPoly(mat4.scale([], waterM, [16, 16, 16]), pMatrix, 0, 1); //white shore wash part, water is stencil masked out
|
||||
}
|
||||
|
||||
gl.disable(gl.STENCIL_TEST);
|
||||
|
||||
nitroRender.setAlpha(1);
|
||||
if (res.mdl[1] != null) {
|
||||
mat4.translate(waterM, view, [-Math.sin((frame+30)/180)*96, height, Math.cos((frame+100)/146)*96])
|
||||
nitroRender.setColMult([1, 1, 1, 0x04/31]);
|
||||
res.mdl[1].draw(mat4.scale([], waterM, [16, 16, 16]), pMatrix); //water white detail part. stencil should do nothing here, since it's in the same position as the above.
|
||||
}
|
||||
|
||||
nitroRender.setColMult([1, 1, 1, 1]);
|
||||
}
|
||||
|
||||
function update() {
|
||||
frame = (frame+1)%197100; //it's a big number but yolo... we have the technology...
|
||||
//TODO: physics and void-out for karts
|
||||
}
|
||||
|
||||
function requireRes() { //scene asks what resources to load
|
||||
@@ -75,6 +80,8 @@ window.ObjWater = function(obji, scene) {
|
||||
case 0x0009:
|
||||
return {mdl:[{nsbmd:"hyudoro_waterC.nsbmd"}, {nsbmd:"hyudoro_waterA.nsbmd"}]};
|
||||
case 0x000C:
|
||||
wheight = 38;
|
||||
wosc = 16;
|
||||
return {mdl:[{nsbmd:"mini_stage3_waterC.nsbmd"}, {nsbmd:"mini_stage3_waterA.nsbmd"}]};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user