More race stuff

- Loop track type
- Simple respawn when falling off track
- col limit
pull/5/head
RHY3756547 2018-03-25 16:08:09 +01:00
parent 4af42625a0
commit 5f89b4518b
4 changed files with 163 additions and 20 deletions

View File

@ -42,7 +42,14 @@ window.cameraIngame = function(kart) {
camNormal[2] += (kart.kartNormal[2]-camNormal[2])*0.075; camNormal[2] += (kart.kartNormal[2]-camNormal[2])*0.075;
vec3.normalize(camNormal, camNormal); vec3.normalize(camNormal, camNormal);
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 += dirDiff(kart.physicalDir+kart.driftOff/2, camAngle)*0.075;
}
camAngle = fixDir(camAngle); camAngle = fixDir(camAngle);
boostOff += (((kart.boostNorm+kart.boostMT > 0)?5:0) - boostOff)*0.075 boostOff += (((kart.boostNorm+kart.boostMT > 0)?5:0) - boostOff)*0.075
@ -59,7 +66,16 @@ window.cameraIngame = function(kart) {
function buildBasis() { function buildBasis() {
//order y, x, z //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]; var temp = basis[0];
basis[0] = basis[1]; basis[0] = basis[1];
basis[1] = temp; //todo: cleanup basis[1] = temp; //todo: cleanup

View File

@ -19,6 +19,7 @@ window.controlRaceCPU = function(nkm) {
} }
this.fetchInput = fetchInput; this.fetchInput = fetchInput;
this.setRouteID = setRouteID;
var battleMode = (nkm.sections["EPAT"] == null); var battleMode = (nkm.sections["EPAT"] == null);
@ -53,11 +54,30 @@ window.controlRaceCPU = function(nkm) {
var dist = vec3.dot(destNorm, kart.pos) + destConst; var dist = vec3.dot(destNorm, kart.pos) + destConst;
if (dist < ePoi.pointSize) advancePoint(); if (dist < ePoi.pointSize) advancePoint();
if (ePath.loop) debugger;
destPoint = vec3.add([], ePoi.pos, vec3.scale([], vec3.lerp([], posOffset, destOff, offTrans), ePoi.pointSize)); 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 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); var turn = Math.min(Math.max(-1, (diff*3)), 1);
offTrans += 1/240; offTrans += 1/240;
@ -94,6 +114,11 @@ window.controlRaceCPU = function(nkm) {
} }
function setRouteID(routeID) {
ePoiInd = routeID-1
advancePoint();
}
function advancePoint() { function advancePoint() {
if (++ePoiInd < ePath.startInd+ePath.pathLen) { if (++ePoiInd < ePath.startInd+ePath.pathLen) {
//next within this path //next within this path

View File

@ -72,6 +72,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
this.kartColVel = vec3.create(); this.kartColVel = vec3.create();
this.kartColTimer = 0; this.kartColTimer = 0;
this.kartWallTimer = 0;
var charRes = scene.gameRes.getChar(charN); var charRes = scene.gameRes.getChar(charN);
var kartRes = scene.gameRes.getKart(kartN); var kartRes = scene.gameRes.getKart(kartN);
@ -98,6 +99,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
this.lapNumber = 1; this.lapNumber = 1;
this.passedKTP2 = false; this.passedKTP2 = false;
this.checkPointNumber = 0; this.checkPointNumber = 0;
this.OOB = 0;
this.wheelParticles = [ this.wheelParticles = [
new NitroEmitter(scene, k, -1, [1, 1.5, -1]), new NitroEmitter(scene, k, -1, [1, 1.5, -1]),
@ -111,7 +113,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
var startLine = nkm.sections["KTPS"].entries[0]; var startLine = nkm.sections["KTPS"].entries[0];
var passLine = nkm.sections["KTP2"].entries[0]; var passLine = nkm.sections["KTP2"].entries[0];
var checkpoints = nkm.sections["CPOI"].entries; var checkpoints = nkm.sections["CPOI"].entries;
var respawns = nkm.sections["CPOI"].entries; var respawns = nkm.sections["KTPJ"].entries;
var futureChecks = [1]; var futureChecks = [1];
var hitGroundAnim = [ //length 13, on y axis var hitGroundAnim = [ //length 13, on y axis
@ -403,6 +405,17 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
} }
} else { //default kart mode } else { //default kart mode
if (k.OOB > 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);
if (k.controller.setRouteID != null) k.controller.setRouteID(respawn.id1);
k.OOB = 0;
}
var groundEffect = 0; var groundEffect = 0;
if (lastCollided != -1) { if (lastCollided != -1) {
groundEffect = MKDS_COLTYPE.PHYS_MAP[lastCollided]; groundEffect = MKDS_COLTYPE.PHYS_MAP[lastCollided];
@ -608,6 +621,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
if (!onGround) { if (!onGround) {
this.kartTargetNormal = [0, 1, 0]; 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) vec3.add(k.vel, k.vel, k.gravity)
if (k.ylock >= 0) { if (k.ylock >= 0) {
ylvel += k.gravity[1]; ylvel += k.gravity[1];
@ -630,6 +644,7 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
} }
if (k.kartColTimer > 0) k.kartColTimer--; if (k.kartColTimer > 0) k.kartColTimer--;
if (k.kartWallTimer > 0) k.kartWallTimer--;
wheelTurn += k.speed/16; wheelTurn += k.speed/16;
wheelTurn = fixDir(wheelTurn); wheelTurn = fixDir(wheelTurn);
@ -648,7 +663,15 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
var steps = 0; var steps = 0;
var remainingT = 1; 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 posSeg = vec3.clone(k.pos);
var ignoreList = []; var ignoreList = [];
while (steps++ < 10 && remainingT > 0.01) { while (steps++ < 10 && remainingT > 0.01) {
@ -657,7 +680,10 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
colResponse(posSeg, velSeg, result, ignoreList) colResponse(posSeg, velSeg, result, ignoreList)
remainingT -= result.t; remainingT -= result.t;
if (remainingT > 0.01) { 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 { } else {
vec3.add(posSeg, posSeg, velSeg); vec3.add(posSeg, posSeg, velSeg);
@ -834,7 +860,13 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
function buildBasis() { function buildBasis() {
//order y, x, z //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 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]; var temp = basis[0];
basis[0] = basis[1]; basis[0] = basis[1];
basis[1] = temp; //todo: cleanup basis[1] = temp; //todo: cleanup
@ -847,6 +879,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) { function sndUpdate(view) {
k.soundProps.pos = vec3.transformMat4([], k.pos, 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); if (k.soundProps.lastPos != null) k.soundProps.vel = vec3.sub([], k.soundProps.pos, k.soundProps.lastPos);
@ -892,26 +974,36 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
lastColSounds = colSound(lastCollided, colBE); lastColSounds = colSound(lastCollided, colBE);
var n = vec3.normalize([], dat.normal); 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 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 angle = Math.acos(vec3.dot(vec3.scale(vec3.create(), k.gravity, -1/gravS), n));
var adjustPos = true; var adjustPos = true;
if (colType == MKDS_COLTYPE.OOB || colType == MKDS_COLTYPE.FALL) {
k.OOB = 1;
}
if (MKDS_COLTYPE.GROUP_WALL.indexOf(colType) != -1) { //wall 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) //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 xz = Math.sqrt(an[0]*an[0]+an[2]*an[2])
var adjN = [n[0]/xz, 0, n[2]/xz] var adjN = [an[0]/xz, 0, an[2]/xz]
var proj = vec3.dot(k.vel, adjN); var proj = vec3.dot(k.vel, adjN);
if (proj < -1) { if (proj < -1) {
if (k.kartWallTimer == 0) {
if (lastColSounds.hit != null) nitroAudio.playSound(lastColSounds.hit, {volume:1}, 0, k) if (lastColSounds.hit != null) nitroAudio.playSound(lastColSounds.hit, {volume:1}, 0, k)
var colObj = {pos:pos, vel:[0,0,0], mat: mat4.fromTranslation([], pos)}; 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, 13));
scene.particles.push(new NitroEmitter(scene, colObj, 14)); 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 //convert back to angle + speed to keep change to kart vel
var v = k.vel; var v = k.vel;
@ -923,10 +1015,21 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
k.boostNorm = BOOSTTIME; k.boostNorm = BOOSTTIME;
} }
var stick = (colType == MKDS_COLTYPE.STICKY || colType == MKDS_COLTYPE.LOOP);
if (k.vel[1] > 0) k.vel[1] = 0; if (k.vel[1] > 0) k.vel[1] = 0;
var proj = vec3.dot(k.vel, n); var proj = vec3.dot(k.vel, an);
if (proj < -4 && k.vel[1] < -2) { proj -= 1.5; } if (!stick && proj < -4 && k.vel[1] < -2) { proj -= 1.5; }
vec3.sub(k.vel, k.vel, vec3.scale(vec3.create(), n, proj)); 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; k.kartTargetNormal = dat.pNormal;
if (change) { if (change) {
@ -937,7 +1040,6 @@ window.Kart = function(pos, angle, speed, kartN, charN, controller, scene) {
setWheelParticles(particle, 0); setWheelParticles(particle, 0);
} }
if (!onGround) { if (!onGround) {
console.log("ground: "+colType+", "+colBE);
groundAnim = 0; groundAnim = 0;
if (lastColSounds.land != null) nitroAudio.playSound(lastColSounds.land, {volume:1}, 0, k) if (lastColSounds.land != null) nitroAudio.playSound(lastColSounds.land, {volume:1}, 0, k)
} }

File diff suppressed because one or more lines are too long