273 lines
7.3 KiB
C
273 lines
7.3 KiB
C
#include "./physics.h"
|
|
|
|
#include "./configurableConstants.h"
|
|
#include "./main.h"
|
|
#include "./maths.h"
|
|
#include "./buttons.h"
|
|
#include "./state.h"
|
|
#include "./data.h"
|
|
#include "./particles.h"
|
|
#include "./tilemap.h"
|
|
|
|
#include <stdbool.h>
|
|
|
|
#define angleWidth 192
|
|
|
|
// #define maxPower 0.075
|
|
// #define maxPower 0.125
|
|
// #define maxPower 0.1
|
|
bool applyBoost = false;
|
|
|
|
// double maxPower = 0.1;
|
|
// double powerFactor = 0.001;
|
|
|
|
extern double maxPower;
|
|
extern double powerFactor;
|
|
extern double boostMaxPower;
|
|
extern double boostPowerFactor;
|
|
|
|
#define maxReverse 0.0375
|
|
// #define powerFactor 0.001#include "./configurableConstants.h"
|
|
#define reverseFactor 0.0005
|
|
|
|
// #define drag 0.9
|
|
bool applyOffRoadDrag = false;
|
|
|
|
extern double drag;
|
|
extern double offRoadDrag;
|
|
extern double angularDrag;
|
|
extern double turnSpeed;
|
|
|
|
#define WIDTH 500
|
|
#define HEIGHT 500
|
|
|
|
double sin2(double x) {
|
|
return (double)fpsin(x / 3.1415926 * 2 * angleWidth) / 32768;
|
|
}
|
|
|
|
double cos2(double x) {
|
|
return sin2(x + (3.1415926 / 2));
|
|
}
|
|
|
|
double fmin(double a, double b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
double fmax(double a, double b) {
|
|
return a > b ? a : b;
|
|
}
|
|
|
|
double dmod(double a, double b) {
|
|
return a - (int)(a / b) * b;
|
|
}
|
|
|
|
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
|
|
#define MAX(X, Y) (((X) < (Y)) ? (Y) : (X))
|
|
|
|
// #define maxSteerNormal 1
|
|
// #define minSteerDrift 0.2 * (1.7 / 2.2)
|
|
// #define neutralSteerDrift (1.7 / 2.2)
|
|
// #define maxSteerDrift 1.7
|
|
extern double maxSteerNormal;
|
|
extern double minSteerDrift;
|
|
extern double neutralSteerDrift;
|
|
extern double maxSteerDrift;
|
|
|
|
void boostKart(Kart *kart, int amount) {
|
|
kart->boostTime = MAX(kart->boostTime, amount);
|
|
if (!kart->isPlayer) return;
|
|
if (amount >= 100) {
|
|
addParticle(2, LCD_WIDTH_PX / 2 - 28, LCD_HEIGHT_PX - 70, 0, 0);
|
|
} else if (amount >= 50) {
|
|
addParticle(1, LCD_WIDTH_PX / 2 - 28, LCD_HEIGHT_PX - 70, 0, 0);
|
|
} else {
|
|
addParticle(3, LCD_WIDTH_PX / 2 - 28, LCD_HEIGHT_PX - 70, 0, 0);
|
|
}
|
|
}
|
|
|
|
// TODO: Remove this somehow or make it more clear
|
|
#define scale 4
|
|
|
|
void updateWithControls(Kart *kart, ButtonState controls) {
|
|
// Save the previous position, to restore if we hit a wall
|
|
double oldKartY = kart->y;
|
|
double oldKartX = kart->x;
|
|
|
|
// Get the tile the kart is on, and its type.
|
|
// TODO: Use all the tiles the kart is touching?
|
|
unsigned char currentTile = getTileID(kart->x / scale, kart->y / scale);
|
|
enum TileType tileType = getTileType(currentTile);
|
|
|
|
bool isOffRoad = tileType == Offroad || tileType == Grass || tileType == ShallowWater;
|
|
|
|
if (tileType == BoostPad) {
|
|
boostKart(kart, 100);
|
|
} else if (tileType == JumpBar) {
|
|
controls.hop = true;
|
|
}
|
|
|
|
// If the kart is still drifting...
|
|
if (kart->drifting && !isOffRoad) {
|
|
if ((controls.left && kart->driftDir == -1) || (controls.right && kart->driftDir == 1)) {
|
|
// Drift charge builds faster when holding the same direction as the drift
|
|
kart->driftCharge += 2;
|
|
} else {
|
|
kart->driftCharge++;
|
|
}
|
|
} else {
|
|
// If the kart is not drifting, or is off road, reset the drift charge to 0
|
|
kart->driftCharge = 0;
|
|
}
|
|
|
|
if (!controls.hop) {
|
|
// When the player lets go of the drift button...
|
|
if (kart->drifting && kart->driftCharge >= 60) {
|
|
// apply the relevant boost...
|
|
if (kart->driftCharge > 360) {
|
|
boostKart(kart, 100);
|
|
} else if (kart->driftCharge >= 180) {
|
|
boostKart(kart, 50);
|
|
} else {
|
|
boostKart(kart, 20);
|
|
}
|
|
}
|
|
// ...and cancel the drift
|
|
kart->drifting = false;
|
|
}
|
|
|
|
// If the hop button was pressed, and the kart is not currently hopping...
|
|
if (controls.hop && !kart->lastHop && kart->hopStage == 0) {
|
|
// ...start the hop animation.
|
|
kart->hopStage = 1;
|
|
if (controls.left || controls.right) {
|
|
// If a direction is held, start a drift (this can also be done when the hop finishes)
|
|
kart->drifting = true;
|
|
kart->driftDir = controls.left ? -1 : 1;
|
|
}
|
|
}
|
|
|
|
// If a hop is in progress...
|
|
if (kart->hopStage != 0) {
|
|
// ...continue the hop animation.
|
|
kart->hopStage++;
|
|
if (kart->hopStage >= 15) {
|
|
kart->hopStage = 0;
|
|
if (!kart->drifting && (controls.left || controls.right)) {
|
|
// If a direction is held, start a drift
|
|
kart->drifting = true;
|
|
kart->driftDir = controls.left ? -1 : 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool boosting = false;
|
|
if (kart->boostTime >= 0) {
|
|
// If we are boosting, set a flag and decrement the remaining time
|
|
kart->boostTime--;
|
|
boosting = true;
|
|
}
|
|
|
|
if (boosting) {
|
|
// TODO: Remove this seemingly duplicate variable
|
|
applyBoost = true;
|
|
kart->power = maxPower;
|
|
controls.accel = true;
|
|
} else {
|
|
applyBoost = false;
|
|
}
|
|
|
|
if (!boosting && isOffRoad) {
|
|
applyOffRoadDrag = true;
|
|
} else {
|
|
applyOffRoadDrag = false;
|
|
}
|
|
|
|
bool canTurn = kart->power > 0.0025/* || car->reverse*/;
|
|
|
|
// Controls are reversed for now
|
|
bool isTurningLeft = canTurn && /*controls.left*/ controls.right;
|
|
bool isTurningRight = canTurn && /*controls.right*/ controls.left;
|
|
|
|
if (controls.accel) {
|
|
kart->power += applyBoost ? boostMaxPower : maxPower;
|
|
} else {
|
|
kart->power -= applyBoost ? boostPowerFactor : powerFactor;
|
|
}
|
|
/* if (car->isReversing) {
|
|
car->reverse += reverseFactor;
|
|
} else {
|
|
car->reverse -= reverseFactor;
|
|
} */
|
|
|
|
kart->power = fmax(0, fmin(applyBoost ? boostMaxPower: maxPower, kart->power));
|
|
// car->reverse = fmax(0, fmin(maxReverse, car->reverse));
|
|
|
|
// double direction = car->power > car->reverse ? 1 : -1;
|
|
int direction = 1;
|
|
|
|
// double change = isTurningLeft ? -1 : isTurningRight ? 1 : 0;
|
|
// if (kart->drifting) {
|
|
// if (kart->driftDir == -1) {
|
|
// change += 1.2;
|
|
// } else {
|
|
// change -= 1.2;
|
|
// }
|
|
// change *= 1.7 / 2.2;
|
|
// }
|
|
double change = 0;
|
|
if (!kart->drifting) {
|
|
change = isTurningLeft ? -maxSteerNormal : isTurningRight ? maxSteerNormal : 0;
|
|
} else {
|
|
// This is negated from what you'd expect, hence the - (pretend it's not there if you want to understand this)
|
|
// I need to fix the coordinate system so it's less broken and inconsistent
|
|
if (-kart->driftDir == 1) {
|
|
if (isTurningRight) {
|
|
// Steering matches drift direction - maximum steering angle
|
|
change = maxSteerDrift;
|
|
} else if (isTurningLeft) {
|
|
change = minSteerDrift;
|
|
} else {
|
|
change = neutralSteerDrift;
|
|
}
|
|
} else {
|
|
change = -maxSteerDrift;
|
|
if (isTurningLeft) {
|
|
change = maxSteerDrift;
|
|
} else if (isTurningRight) {
|
|
change = minSteerDrift;
|
|
} else {
|
|
change = neutralSteerDrift;
|
|
}
|
|
change = -change;
|
|
}
|
|
}
|
|
change *= direction * turnSpeed;
|
|
kart->angularVelocity += change;
|
|
|
|
kart->xVelocity += sin2(kart->angle) * (kart->power /* - kart->reverse */);
|
|
kart->yVelocity += cos2(kart->angle) * (kart->power /* - kart->reverse */);
|
|
|
|
kart->x += kart->xVelocity * 12;
|
|
kart->y -= kart->yVelocity * 12;
|
|
double calcDrag = applyOffRoadDrag ? offRoadDrag : drag;
|
|
kart->xVelocity *= calcDrag;
|
|
kart->yVelocity *= calcDrag;
|
|
kart->angle += kart->angularVelocity;
|
|
kart->angle = dmod(kart->angle, 3.1415926 * 2);
|
|
kart->angularVelocity *= angularDrag;
|
|
|
|
unsigned char newTile = getTileID(kart->x / scale, kart->y / scale);
|
|
|
|
if (getTileType(newTile) == SolidBlock) {
|
|
kart->x = oldKartX;
|
|
kart->y = oldKartY;
|
|
}
|
|
|
|
// Finish line is tile 254
|
|
if (newTile == 254 && currentTile != 254) {
|
|
kart->lapCount++;
|
|
}
|
|
|
|
kart->lastHop = controls.hop;
|
|
}
|