mirror of
https://github.com/GayPizzaSpecifications/padlab.git
synced 2025-08-03 21:21:33 +00:00
Separate stick functionality from main file
This commit is contained in:
@ -5,6 +5,7 @@ set(TARGET padlab)
|
|||||||
set(SOURCES
|
set(SOURCES
|
||||||
maths.c maths.h
|
maths.c maths.h
|
||||||
draw.c draw.h
|
draw.c draw.h
|
||||||
|
stick.c stick.h
|
||||||
analogue.c)
|
analogue.c)
|
||||||
|
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
|
286
analogue.c
286
analogue.c
@ -1,5 +1,6 @@
|
|||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
#include "stick.h"
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@ -8,295 +9,22 @@
|
|||||||
#define WINDOW_WIDTH 512
|
#define WINDOW_WIDTH 512
|
||||||
#define WINDOW_HEIGHT 288
|
#define WINDOW_HEIGHT 288
|
||||||
|
|
||||||
#define DISPLAY_SCALE 0.8889
|
|
||||||
|
|
||||||
SDL_Window* window = NULL;
|
SDL_Window* window = NULL;
|
||||||
SDL_JoystickID joyid = -1;
|
SDL_JoystickID joyid = -1;
|
||||||
SDL_GameController* pad = NULL;
|
SDL_GameController* pad = NULL;
|
||||||
|
|
||||||
bool UseGamepad(int a_joyid)
|
bool UseGamepad(int aJoyid)
|
||||||
{
|
{
|
||||||
pad = SDL_GameControllerOpen(a_joyid);
|
pad = SDL_GameControllerOpen(aJoyid);
|
||||||
joyid = SDL_JoystickGetDeviceInstanceID(a_joyid);
|
joyid = SDL_JoystickGetDeviceInstanceID(aJoyid);
|
||||||
if (pad != NULL)
|
if (pad != NULL)
|
||||||
{
|
{
|
||||||
printf("using gamepad #%d, \"%s\"\n", a_joyid, SDL_GameControllerName(pad));
|
printf("using gamepad #%d, \"%s\"\n", aJoyid, SDL_GameControllerName(pad));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector RadialDeadzone(vector v, double min, double max)
|
|
||||||
{
|
|
||||||
double mag = sqrt(v.x * v.x + v.y * v.y);
|
|
||||||
if (mag == 0.0 || mag < min)
|
|
||||||
{
|
|
||||||
return (vector){0.0, 0.0};
|
|
||||||
}
|
|
||||||
else if (mag > max)
|
|
||||||
{
|
|
||||||
return (vector){v.x / mag, v.y / mag};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double rescale = (mag - min) / (max - min);
|
|
||||||
return (vector){v.x / mag * rescale, v.y / mag * rescale};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vector DigitalEight(vector v, double angle, double deadzone)
|
|
||||||
{
|
|
||||||
vector res = {0, 0};
|
|
||||||
|
|
||||||
if (fabs(v.x) * angle > fabs(v.y))
|
|
||||||
{
|
|
||||||
if (fabs(v.x) > deadzone)
|
|
||||||
res.x = copysign(1.0, v.x);
|
|
||||||
}
|
|
||||||
else if (fabs(v.y) * angle > fabs(v.x))
|
|
||||||
{
|
|
||||||
if (fabs(v.y) > deadzone)
|
|
||||||
res.y = copysign(1.0, v.y);
|
|
||||||
}
|
|
||||||
else if (fabs(v.x) + fabs(v.y) > deadzone * (1.0 + angle))
|
|
||||||
{
|
|
||||||
const double dscale = 1/sqrt(2);
|
|
||||||
res.x = copysign(dscale, v.x);
|
|
||||||
res.y = copysign(dscale, v.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector ApplyAcceleration(vector v, double y)
|
|
||||||
{
|
|
||||||
double mag = sqrt(v.x * v.x + v.y * v.y);
|
|
||||||
if (mag > 0.0)
|
|
||||||
{
|
|
||||||
double curve = AccelCurve(mag, y);
|
|
||||||
return (vector){v.x / mag * curve, v.y / mag * curve};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (vector){0.0, 0.0};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
// common
|
|
||||||
vector rawpos, compos;
|
|
||||||
bool recalc;
|
|
||||||
|
|
||||||
// analogue
|
|
||||||
double preaccel, postacel;
|
|
||||||
double accelpow;
|
|
||||||
double deadzone;
|
|
||||||
|
|
||||||
// digital
|
|
||||||
double digiangle;
|
|
||||||
double digideadzone;
|
|
||||||
} StickState;
|
|
||||||
|
|
||||||
void InitDefaults(StickState* p)
|
|
||||||
{
|
|
||||||
p->rawpos = (vector){0.0, 0.0};
|
|
||||||
p->compos = (vector){0.0, 0.0};
|
|
||||||
|
|
||||||
p->recalc = true;
|
|
||||||
p->preaccel = 0.0;
|
|
||||||
p->postacel = 0.0;
|
|
||||||
p->accelpow = 1.25;
|
|
||||||
p->deadzone = 0.125;
|
|
||||||
|
|
||||||
p->digiangle = sqrt(2.0) - 1.0;
|
|
||||||
p->digideadzone = 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawAnalogue(const SDL_Rect* win, StickState* p)
|
|
||||||
{
|
|
||||||
if (p->recalc)
|
|
||||||
{
|
|
||||||
p->compos = RadialDeadzone(p->rawpos, p->deadzone, 0.99);
|
|
||||||
p->preaccel = sqrt(p->compos.x * p->compos.x + p->compos.y * p->compos.y);
|
|
||||||
p->compos = ApplyAcceleration(p->compos, p->accelpow);
|
|
||||||
p->postacel = sqrt(p->compos.x * p->compos.x + p->compos.y * p->compos.y);
|
|
||||||
|
|
||||||
p->recalc = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
double size = (double)(win->w > win->h ? win->h : win->w) * DISPLAY_SCALE;
|
|
||||||
|
|
||||||
// range rect
|
|
||||||
SetDrawColour(0x3F3F3FFF);
|
|
||||||
const int rectSz = (int)round(size);
|
|
||||||
DrawRect(
|
|
||||||
win->x + (win->w - rectSz) / 2,
|
|
||||||
win->y + (win->h - rectSz) / 2,
|
|
||||||
rectSz, rectSz);
|
|
||||||
|
|
||||||
const int ox = win->x + win->w / 2;
|
|
||||||
const int oy = win->y + win->h / 2;
|
|
||||||
|
|
||||||
// acceleration curve
|
|
||||||
SetDrawColour(0x4F4F4FFF);
|
|
||||||
const int accelsamp = (int)(sqrt(size) * 4.20);
|
|
||||||
const double step = 1.0 / (double)accelsamp;
|
|
||||||
double y1 = AccelCurve(0.0, p->accelpow);
|
|
||||||
for (int i = 1; i <= accelsamp; ++i)
|
|
||||||
{
|
|
||||||
double y2 = AccelCurve(step * i, p->accelpow);
|
|
||||||
DrawLine(
|
|
||||||
win->x + (int)(step * (i - 1) * size) + (win->w - (int)round(size)) / 2,
|
|
||||||
win->y + (int)((1.0 - y1) * size) + (win->h - (int)round(size)) / 2,
|
|
||||||
win->x + (int)(step * i * size) + (win->w - (int)round(size)) / 2,
|
|
||||||
win->y + (int)((1.0 - y2) * size) + (win->h - (int)round(size)) / 2);
|
|
||||||
y1 = y2;
|
|
||||||
}
|
|
||||||
const int tickerx = (int)((p->preaccel - 0.5) * size);
|
|
||||||
const int tickery = (int)((0.5 - p->postacel) * size);
|
|
||||||
SetDrawColour(0x2F3F1FFF);
|
|
||||||
DrawLine(
|
|
||||||
ox + tickerx,
|
|
||||||
win->y + (win->h - (int)round(size)) / 2,
|
|
||||||
ox + tickerx,
|
|
||||||
win->y + (win->h + (int)round(size)) / 2);
|
|
||||||
SetDrawColour(0x2F5F2FFF);
|
|
||||||
DrawLine(
|
|
||||||
win->x + (win->w - (int)round(size)) / 2,
|
|
||||||
oy + tickery,
|
|
||||||
win->x + (win->w + (int)round(size)) / 2,
|
|
||||||
oy + tickery);
|
|
||||||
|
|
||||||
// guide circle
|
|
||||||
SetDrawColour(0x4F4F4FFF);
|
|
||||||
DrawCircle(ox, oy, (int)round(size) / 2);
|
|
||||||
|
|
||||||
SetDrawColour(0x3F3F3FFF);
|
|
||||||
DrawCircle(ox, oy, (int)round(p->deadzone * size) / 2);
|
|
||||||
|
|
||||||
// 0,0 line axis'
|
|
||||||
SetDrawColour(0x2F2F2FFF);
|
|
||||||
DrawLine(
|
|
||||||
win->x, oy,
|
|
||||||
win->x + win->w, oy);
|
|
||||||
DrawLine(
|
|
||||||
ox, win->y,
|
|
||||||
ox, win->y + win->h);
|
|
||||||
|
|
||||||
// compensated position
|
|
||||||
SetDrawColour(0x1FFF1FFF);
|
|
||||||
DrawCircleSteps(
|
|
||||||
ox + (int)round(p->compos.x * size / 2.0),
|
|
||||||
oy + (int)round(p->compos.y * size / 2.0),
|
|
||||||
8, 16);
|
|
||||||
DrawPoint(
|
|
||||||
ox + (int)round(p->compos.x * size / 2.0),
|
|
||||||
oy + (int)round(p->compos.y * size / 2.0));
|
|
||||||
|
|
||||||
// raw position
|
|
||||||
SetDrawColour(0xFFFFFFFF);
|
|
||||||
DrawLine(
|
|
||||||
ox + (int)round(p->rawpos.x * size / 2.0) - 4,
|
|
||||||
oy + (int)round(p->rawpos.y * size / 2.0),
|
|
||||||
ox + (int)round(p->rawpos.x * size / 2.0) + 4,
|
|
||||||
oy + (int)round(p->rawpos.y * size / 2.0));
|
|
||||||
DrawLine(
|
|
||||||
ox + (int)round(p->rawpos.x * size / 2.0),
|
|
||||||
oy + (int)round(p->rawpos.y * size / 2.0) - 4,
|
|
||||||
ox + (int)round(p->rawpos.x * size / 2.0),
|
|
||||||
oy + (int)round(p->rawpos.y * size / 2.0) + 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawDigital(const SDL_Rect* win, StickState* p)
|
|
||||||
{
|
|
||||||
if (p->recalc)
|
|
||||||
{
|
|
||||||
p->compos = DigitalEight(p->rawpos, p->digiangle, p->digideadzone);
|
|
||||||
p->recalc = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const double size = (double)(win->w > win->h ? win->h : win->w) * DISPLAY_SCALE;
|
|
||||||
|
|
||||||
// range rect
|
|
||||||
SetDrawColour(0x3F3F3FFF);
|
|
||||||
const int rectSz = (int)round(size);
|
|
||||||
DrawRect(
|
|
||||||
win->x + (win->w - rectSz) / 2,
|
|
||||||
win->y + (win->h - rectSz) / 2,
|
|
||||||
rectSz, rectSz);
|
|
||||||
|
|
||||||
// window centre
|
|
||||||
const int ox = win->x + win->w / 2;
|
|
||||||
const int oy = win->y + win->h / 2;
|
|
||||||
|
|
||||||
// guide circle
|
|
||||||
SetDrawColour(0x4F4F4FFF);
|
|
||||||
DrawCircle(ox, oy, (int)round(size) / 2);
|
|
||||||
|
|
||||||
// 0,0 line axis'
|
|
||||||
SetDrawColour(0x2F2F2FFF);
|
|
||||||
DrawLine(
|
|
||||||
win->x, oy,
|
|
||||||
win->x + win->w, oy);
|
|
||||||
DrawLine(
|
|
||||||
ox, win->y,
|
|
||||||
ox, win->y + win->h);
|
|
||||||
|
|
||||||
// calcuate points for the zone previews
|
|
||||||
const double outerinvmag = 1.0 / sqrt(1.0 + p->digiangle * p->digiangle);
|
|
||||||
const int outh = (int)round((size * outerinvmag) / 2.0);
|
|
||||||
const int outq = (int)round((size * outerinvmag) / 2.0 * p->digiangle);
|
|
||||||
const int innh = (int)round(p->digideadzone * size / 2.0);
|
|
||||||
const int innq = (int)round(p->digideadzone * size / 2.0 * p->digiangle);
|
|
||||||
|
|
||||||
SetDrawColour(0x3F3F3FFF);
|
|
||||||
|
|
||||||
// angles preview
|
|
||||||
DrawLine(ox - outq, oy - outh, ox - innq, oy - innh);
|
|
||||||
DrawLine(ox + outq, oy - outh, ox + innq, oy - innh);
|
|
||||||
DrawLine(ox + outh, oy - outq, ox + innh, oy - innq);
|
|
||||||
DrawLine(ox + outh, oy + outq, ox + innh, oy + innq);
|
|
||||||
DrawLine(ox + outq, oy + outh, ox + innq, oy + innh);
|
|
||||||
DrawLine(ox - outq, oy + outh, ox - innq, oy + innh);
|
|
||||||
DrawLine(ox - outh, oy + outq, ox - innh, oy + innq);
|
|
||||||
DrawLine(ox - outh, oy - outq, ox - innh, oy - innq);
|
|
||||||
|
|
||||||
// deadzone octagon
|
|
||||||
DrawLine(ox - innq, oy - innh, ox + innq, oy - innh);
|
|
||||||
DrawLine(ox + innq, oy - innh, ox + innh, oy - innq);
|
|
||||||
DrawLine(ox + innh, oy - innq, ox + innh, oy - innq);
|
|
||||||
DrawLine(ox + innh, oy - innq, ox + innh, oy + innq);
|
|
||||||
DrawLine(ox + innh, oy + innq, ox + innq, oy + innh);
|
|
||||||
DrawLine(ox + innq, oy + innh, ox - innq, oy + innh);
|
|
||||||
DrawLine(ox - innq, oy + innh, ox - innh, oy + innq);
|
|
||||||
DrawLine(ox - innh, oy + innq, ox - innh, oy - innq);
|
|
||||||
DrawLine(ox - innh, oy - innq, ox - innq, oy - innh);
|
|
||||||
|
|
||||||
// compensated position
|
|
||||||
SetDrawColour(0x1FFF1FFF);
|
|
||||||
DrawCircleSteps(
|
|
||||||
ox + (int)round(p->compos.x * size / 2.0),
|
|
||||||
oy + (int)round(p->compos.y * size / 2.0),
|
|
||||||
8, 16);
|
|
||||||
DrawPoint(
|
|
||||||
ox + (int)round(p->compos.x * size / 2.0),
|
|
||||||
oy + (int)round(p->compos.y * size / 2.0));
|
|
||||||
|
|
||||||
// raw position
|
|
||||||
SetDrawColour(0xFFFFFFFF);
|
|
||||||
DrawLine(
|
|
||||||
ox + (int)round(p->rawpos.x * size / 2.0) - 4,
|
|
||||||
oy + (int)round(p->rawpos.y * size / 2.0),
|
|
||||||
ox + (int)round(p->rawpos.x * size / 2.0) + 4,
|
|
||||||
oy + (int)round(p->rawpos.y * size / 2.0));
|
|
||||||
DrawLine(
|
|
||||||
ox + (int)round(p->rawpos.x * size / 2.0),
|
|
||||||
oy + (int)round(p->rawpos.y * size / 2.0) - 4,
|
|
||||||
ox + (int)round(p->rawpos.x * size / 2.0),
|
|
||||||
oy + (int)round(p->rawpos.y * size / 2.0) + 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
@ -504,8 +232,8 @@ int main(int argc, char** argv)
|
|||||||
DrawClear();
|
DrawClear();
|
||||||
|
|
||||||
const int hrw = rw / 2;
|
const int hrw = rw / 2;
|
||||||
DrawDigital(&(SDL_Rect){ 0, 0, hrw, rh }, &stickl);
|
DrawDigital(&(rect){0, 0, hrw, rh}, &stickl);
|
||||||
DrawAnalogue(&(SDL_Rect){hrw, 0, hrw, rh}, &stickr);
|
DrawAnalogue(&(rect){hrw, 0, hrw, rh}, &stickr);
|
||||||
|
|
||||||
// test player thingo
|
// test player thingo
|
||||||
if (showavatar)
|
if (showavatar)
|
||||||
|
2
draw.h
2
draw.h
@ -1,6 +1,8 @@
|
|||||||
#ifndef DRAW_H
|
#ifndef DRAW_H
|
||||||
#define DRAW_H
|
#define DRAW_H
|
||||||
|
|
||||||
|
#define DISPLAY_SCALE 0.8889
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct SDL_Renderer SDL_Renderer;
|
typedef struct SDL_Renderer SDL_Renderer;
|
||||||
|
2
maths.c
2
maths.c
@ -4,5 +4,3 @@ static inline vector VecAdd(vector l, vector r);
|
|||||||
static inline vector VecScale(vector v, vec_t x);
|
static inline vector VecScale(vector v, vec_t x);
|
||||||
|
|
||||||
static inline double pfmod(double x, double d);
|
static inline double pfmod(double x, double d);
|
||||||
|
|
||||||
double AccelCurve(double x, double y);
|
|
||||||
|
9
maths.h
9
maths.h
@ -12,7 +12,9 @@
|
|||||||
#define SATURATE(X) (CLAMP(X, 0, 1))
|
#define SATURATE(X) (CLAMP(X, 0, 1))
|
||||||
|
|
||||||
typedef double vec_t;
|
typedef double vec_t;
|
||||||
typedef struct {vec_t x, y;} vector;
|
typedef struct { vec_t x, y; } vector;
|
||||||
|
|
||||||
|
typedef struct { int x, y, w, h; } rect;
|
||||||
|
|
||||||
static inline vector VecAdd(vector l, vector r)
|
static inline vector VecAdd(vector l, vector r)
|
||||||
{
|
{
|
||||||
@ -29,9 +31,4 @@ static inline double pfmod(double x, double d)
|
|||||||
return fmod(fmod(x, d) + d, (d));
|
return fmod(fmod(x, d) + d, (d));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double AccelCurve(double x, double y)
|
|
||||||
{
|
|
||||||
return (x * (x + y)) / (1.0 + y);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif//MATHS_H
|
#endif//MATHS_H
|
||||||
|
243
stick.c
Normal file
243
stick.c
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
#include "stick.h"
|
||||||
|
#include "draw.h"
|
||||||
|
|
||||||
|
extern inline void InitDefaults(StickState* p);
|
||||||
|
|
||||||
|
vector RadialDeadzone(vector v, double min, double max)
|
||||||
|
{
|
||||||
|
double mag = sqrt(v.x * v.x + v.y * v.y);
|
||||||
|
|
||||||
|
if (mag <= min)
|
||||||
|
return (vector){0.0, 0.0};
|
||||||
|
|
||||||
|
if (mag >= max)
|
||||||
|
return (vector){v.x / mag, v.y / mag};
|
||||||
|
|
||||||
|
double rescale = (mag - min) / (max - min);
|
||||||
|
return (vector){v.x / mag * rescale, v.y / mag * rescale};
|
||||||
|
}
|
||||||
|
|
||||||
|
vector DigitalEight(vector v, double angle, double deadzone)
|
||||||
|
{
|
||||||
|
vector res = {0, 0};
|
||||||
|
|
||||||
|
if (fabs(v.x) * angle > fabs(v.y))
|
||||||
|
{
|
||||||
|
if (fabs(v.x) > deadzone)
|
||||||
|
res.x = copysign(1.0, v.x);
|
||||||
|
}
|
||||||
|
else if (fabs(v.y) * angle > fabs(v.x))
|
||||||
|
{
|
||||||
|
if (fabs(v.y) > deadzone)
|
||||||
|
res.y = copysign(1.0, v.y);
|
||||||
|
}
|
||||||
|
else if (fabs(v.x) + fabs(v.y) > deadzone * (1.0 + angle))
|
||||||
|
{
|
||||||
|
const double dscale = 1/sqrt(2);
|
||||||
|
res.x = copysign(dscale, v.x);
|
||||||
|
res.y = copysign(dscale, v.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double AccelCurve(double x, double y)
|
||||||
|
{
|
||||||
|
return (x * (x + y)) / (1.0 + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector ApplyAcceleration(vector v, double y)
|
||||||
|
{
|
||||||
|
double mag = sqrt(v.x * v.x + v.y * v.y);
|
||||||
|
if (mag <= 0.0)
|
||||||
|
return (vector){0.0, 0.0};
|
||||||
|
|
||||||
|
double curve = AccelCurve(mag, y);
|
||||||
|
return (vector){v.x / mag * curve, v.y / mag * curve};
|
||||||
|
}
|
||||||
|
|
||||||
|
extern inline void InitDefaults(StickState* p);
|
||||||
|
|
||||||
|
void DrawAnalogue(const rect* win, StickState* p)
|
||||||
|
{
|
||||||
|
if (p->recalc)
|
||||||
|
{
|
||||||
|
p->compos = RadialDeadzone(p->rawpos, p->deadzone, 0.99);
|
||||||
|
p->preaccel = sqrt(p->compos.x * p->compos.x + p->compos.y * p->compos.y);
|
||||||
|
p->compos = ApplyAcceleration(p->compos, p->accelpow);
|
||||||
|
p->postacel = sqrt(p->compos.x * p->compos.x + p->compos.y * p->compos.y);
|
||||||
|
|
||||||
|
p->recalc = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double size = (double)(win->w > win->h ? win->h : win->w) * DISPLAY_SCALE;
|
||||||
|
|
||||||
|
// range rect
|
||||||
|
SetDrawColour(0x3F3F3FFF);
|
||||||
|
const int rectSz = (int)round(size);
|
||||||
|
DrawRect(
|
||||||
|
win->x + (win->w - rectSz) / 2,
|
||||||
|
win->y + (win->h - rectSz) / 2,
|
||||||
|
rectSz, rectSz);
|
||||||
|
|
||||||
|
const int ox = win->x + win->w / 2;
|
||||||
|
const int oy = win->y + win->h / 2;
|
||||||
|
|
||||||
|
// acceleration curve
|
||||||
|
SetDrawColour(0x4F4F4FFF);
|
||||||
|
const int accelsamp = (int)(sqrt(size) * 4.20);
|
||||||
|
const double step = 1.0 / (double)accelsamp;
|
||||||
|
double y1 = AccelCurve(0.0, p->accelpow);
|
||||||
|
for (int i = 1; i <= accelsamp; ++i)
|
||||||
|
{
|
||||||
|
double y2 = AccelCurve(step * i, p->accelpow);
|
||||||
|
DrawLine(
|
||||||
|
win->x + (int)(step * (i - 1) * size) + (win->w - (int)round(size)) / 2,
|
||||||
|
win->y + (int)((1.0 - y1) * size) + (win->h - (int)round(size)) / 2,
|
||||||
|
win->x + (int)(step * i * size) + (win->w - (int)round(size)) / 2,
|
||||||
|
win->y + (int)((1.0 - y2) * size) + (win->h - (int)round(size)) / 2);
|
||||||
|
y1 = y2;
|
||||||
|
}
|
||||||
|
const int tickerx = (int)((p->preaccel - 0.5) * size);
|
||||||
|
const int tickery = (int)((0.5 - p->postacel) * size);
|
||||||
|
SetDrawColour(0x2F3F1FFF);
|
||||||
|
DrawLine(
|
||||||
|
ox + tickerx,
|
||||||
|
win->y + (win->h - (int)round(size)) / 2,
|
||||||
|
ox + tickerx,
|
||||||
|
win->y + (win->h + (int)round(size)) / 2);
|
||||||
|
SetDrawColour(0x2F5F2FFF);
|
||||||
|
DrawLine(
|
||||||
|
win->x + (win->w - (int)round(size)) / 2,
|
||||||
|
oy + tickery,
|
||||||
|
win->x + (win->w + (int)round(size)) / 2,
|
||||||
|
oy + tickery);
|
||||||
|
|
||||||
|
// guide circle
|
||||||
|
SetDrawColour(0x4F4F4FFF);
|
||||||
|
DrawCircle(ox, oy, (int)round(size) / 2);
|
||||||
|
|
||||||
|
SetDrawColour(0x3F3F3FFF);
|
||||||
|
DrawCircle(ox, oy, (int)round(p->deadzone * size) / 2);
|
||||||
|
|
||||||
|
// 0,0 line axis'
|
||||||
|
SetDrawColour(0x2F2F2FFF);
|
||||||
|
DrawLine(
|
||||||
|
win->x, oy,
|
||||||
|
win->x + win->w, oy);
|
||||||
|
DrawLine(
|
||||||
|
ox, win->y,
|
||||||
|
ox, win->y + win->h);
|
||||||
|
|
||||||
|
// compensated position
|
||||||
|
SetDrawColour(0x1FFF1FFF);
|
||||||
|
DrawCircleSteps(
|
||||||
|
ox + (int)round(p->compos.x * size / 2.0),
|
||||||
|
oy + (int)round(p->compos.y * size / 2.0),
|
||||||
|
8, 16);
|
||||||
|
DrawPoint(
|
||||||
|
ox + (int)round(p->compos.x * size / 2.0),
|
||||||
|
oy + (int)round(p->compos.y * size / 2.0));
|
||||||
|
|
||||||
|
// raw position
|
||||||
|
SetDrawColour(0xFFFFFFFF);
|
||||||
|
DrawLine(
|
||||||
|
ox + (int)round(p->rawpos.x * size / 2.0) - 4,
|
||||||
|
oy + (int)round(p->rawpos.y * size / 2.0),
|
||||||
|
ox + (int)round(p->rawpos.x * size / 2.0) + 4,
|
||||||
|
oy + (int)round(p->rawpos.y * size / 2.0));
|
||||||
|
DrawLine(
|
||||||
|
ox + (int)round(p->rawpos.x * size / 2.0),
|
||||||
|
oy + (int)round(p->rawpos.y * size / 2.0) - 4,
|
||||||
|
ox + (int)round(p->rawpos.x * size / 2.0),
|
||||||
|
oy + (int)round(p->rawpos.y * size / 2.0) + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawDigital(const rect* win, StickState* p)
|
||||||
|
{
|
||||||
|
if (p->recalc)
|
||||||
|
{
|
||||||
|
p->compos = DigitalEight(p->rawpos, p->digiangle, p->digideadzone);
|
||||||
|
p->recalc = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const double size = (double)(win->w > win->h ? win->h : win->w) * DISPLAY_SCALE;
|
||||||
|
|
||||||
|
// range rect
|
||||||
|
SetDrawColour(0x3F3F3FFF);
|
||||||
|
const int rectSz = (int)round(size);
|
||||||
|
DrawRect(
|
||||||
|
win->x + (win->w - rectSz) / 2,
|
||||||
|
win->y + (win->h - rectSz) / 2,
|
||||||
|
rectSz, rectSz);
|
||||||
|
|
||||||
|
// window centre
|
||||||
|
const int ox = win->x + win->w / 2;
|
||||||
|
const int oy = win->y + win->h / 2;
|
||||||
|
|
||||||
|
// guide circle
|
||||||
|
SetDrawColour(0x4F4F4FFF);
|
||||||
|
DrawCircle(ox, oy, (int)round(size) / 2);
|
||||||
|
|
||||||
|
// 0,0 line axis'
|
||||||
|
SetDrawColour(0x2F2F2FFF);
|
||||||
|
DrawLine(
|
||||||
|
win->x, oy,
|
||||||
|
win->x + win->w, oy);
|
||||||
|
DrawLine(
|
||||||
|
ox, win->y,
|
||||||
|
ox, win->y + win->h);
|
||||||
|
|
||||||
|
// calcuate points for the zone previews
|
||||||
|
const double outerinvmag = 1.0 / sqrt(1.0 + p->digiangle * p->digiangle);
|
||||||
|
const int outh = (int)round((size * outerinvmag) / 2.0);
|
||||||
|
const int outq = (int)round((size * outerinvmag) / 2.0 * p->digiangle);
|
||||||
|
const int innh = (int)round(p->digideadzone * size / 2.0);
|
||||||
|
const int innq = (int)round(p->digideadzone * size / 2.0 * p->digiangle);
|
||||||
|
|
||||||
|
SetDrawColour(0x3F3F3FFF);
|
||||||
|
|
||||||
|
// angles preview
|
||||||
|
DrawLine(ox - outq, oy - outh, ox - innq, oy - innh);
|
||||||
|
DrawLine(ox + outq, oy - outh, ox + innq, oy - innh);
|
||||||
|
DrawLine(ox + outh, oy - outq, ox + innh, oy - innq);
|
||||||
|
DrawLine(ox + outh, oy + outq, ox + innh, oy + innq);
|
||||||
|
DrawLine(ox + outq, oy + outh, ox + innq, oy + innh);
|
||||||
|
DrawLine(ox - outq, oy + outh, ox - innq, oy + innh);
|
||||||
|
DrawLine(ox - outh, oy + outq, ox - innh, oy + innq);
|
||||||
|
DrawLine(ox - outh, oy - outq, ox - innh, oy - innq);
|
||||||
|
|
||||||
|
// deadzone octagon
|
||||||
|
DrawLine(ox - innq, oy - innh, ox + innq, oy - innh);
|
||||||
|
DrawLine(ox + innq, oy - innh, ox + innh, oy - innq);
|
||||||
|
DrawLine(ox + innh, oy - innq, ox + innh, oy - innq);
|
||||||
|
DrawLine(ox + innh, oy - innq, ox + innh, oy + innq);
|
||||||
|
DrawLine(ox + innh, oy + innq, ox + innq, oy + innh);
|
||||||
|
DrawLine(ox + innq, oy + innh, ox - innq, oy + innh);
|
||||||
|
DrawLine(ox - innq, oy + innh, ox - innh, oy + innq);
|
||||||
|
DrawLine(ox - innh, oy + innq, ox - innh, oy - innq);
|
||||||
|
DrawLine(ox - innh, oy - innq, ox - innq, oy - innh);
|
||||||
|
|
||||||
|
// compensated position
|
||||||
|
SetDrawColour(0x1FFF1FFF);
|
||||||
|
DrawCircleSteps(
|
||||||
|
ox + (int)round(p->compos.x * size / 2.0),
|
||||||
|
oy + (int)round(p->compos.y * size / 2.0),
|
||||||
|
8, 16);
|
||||||
|
DrawPoint(
|
||||||
|
ox + (int)round(p->compos.x * size / 2.0),
|
||||||
|
oy + (int)round(p->compos.y * size / 2.0));
|
||||||
|
|
||||||
|
// raw position
|
||||||
|
SetDrawColour(0xFFFFFFFF);
|
||||||
|
DrawLine(
|
||||||
|
ox + (int)round(p->rawpos.x * size / 2.0) - 4,
|
||||||
|
oy + (int)round(p->rawpos.y * size / 2.0),
|
||||||
|
ox + (int)round(p->rawpos.x * size / 2.0) + 4,
|
||||||
|
oy + (int)round(p->rawpos.y * size / 2.0));
|
||||||
|
DrawLine(
|
||||||
|
ox + (int)round(p->rawpos.x * size / 2.0),
|
||||||
|
oy + (int)round(p->rawpos.y * size / 2.0) - 4,
|
||||||
|
ox + (int)round(p->rawpos.x * size / 2.0),
|
||||||
|
oy + (int)round(p->rawpos.y * size / 2.0) + 4);
|
||||||
|
}
|
41
stick.h
Normal file
41
stick.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef STICK_H
|
||||||
|
#define STICK_H
|
||||||
|
|
||||||
|
#include "maths.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// common
|
||||||
|
vector rawpos, compos;
|
||||||
|
bool recalc;
|
||||||
|
|
||||||
|
// analogue
|
||||||
|
double preaccel, postacel;
|
||||||
|
double accelpow;
|
||||||
|
double deadzone;
|
||||||
|
|
||||||
|
// digital
|
||||||
|
double digiangle;
|
||||||
|
double digideadzone;
|
||||||
|
} StickState;
|
||||||
|
|
||||||
|
inline void InitDefaults(StickState* p)
|
||||||
|
{
|
||||||
|
p->rawpos = (vector){0.0, 0.0};
|
||||||
|
p->compos = (vector){0.0, 0.0};
|
||||||
|
|
||||||
|
p->recalc = true;
|
||||||
|
p->preaccel = 0.0;
|
||||||
|
p->postacel = 0.0;
|
||||||
|
p->accelpow = 1.25;
|
||||||
|
p->deadzone = 0.125;
|
||||||
|
|
||||||
|
p->digiangle = sqrt(2.0) - 1.0;
|
||||||
|
p->digideadzone = 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawAnalogue(const rect* win, StickState* p);
|
||||||
|
void DrawDigital(const rect* win, StickState* p);
|
||||||
|
|
||||||
|
#endif//STICK_H
|
Reference in New Issue
Block a user