Splitscreen: Tie camera input to controller ports

This commit is contained in:
UnknownShadow200 2024-07-14 10:57:28 +10:00
parent e83eea9ae9
commit c3de1a30c4
12 changed files with 72 additions and 44 deletions

View File

@ -61,11 +61,11 @@ _ClipEdge:
mov IN1, TM1 ! MT, tmp = &v1
fldi0 fr4 ! LS, fr4 = 0
add #12, TM1 ! EX, tmp = &v1->z
fmov.s @r1, fr2 ! LS, fr2 = v1->z
fmov.s @TM1, fr2 ! LS, fr2 = v1->z
mov IN2, TM1 ! MT, tmp = &v2
fldi0 fr5 ! LS, fr5 = 0
add #12, TM1 ! EX, tmp = &v2->z
fmov.s @r1,fr11 ! LS, fr11 = v2->z
fmov.s @TM1,fr11 ! LS, fr11 = v2->z
fsub fr2,fr11 ! FE, fr11 = v2->z - v1->z
fldi0 fr8 ! LS, fr8 = 0
fmul fr11,fr11 ! FE, fr11 = (v2->z - v1->z) * (v2->z * v1->z)
@ -120,11 +120,11 @@ _ClipEdge:
fmov.s fr3,@OUT ! LS, OUT->w = lerp
add #-4, OUT ! EX, OUT -= 4
mov.l @IN1+,CL1 ! LS, ACOLOR = v1->bgra
mov.l @IN1,CL1 ! LS, ACOLOR = v1->bgra
extu.b CL1,TM1 ! EX, val = ACOLOR.b
lds TM1,fpul ! CO, FPUL = val
float fpul,fr2 ! EX, fr2 = float(FPUL)
mov.l @IN2+,CL2 ! LS, BCOLOR = v2->bgra
mov.l @IN2,CL2 ! LS, BCOLOR = v2->bgra
extu.b CL2,TM1 ! EX, val = BCOLOR.b
lds TM1,fpul ! CO, FPUL = val
float fpul,fr3 ! EX, fr3 = float(FPUL)

View File

@ -17,21 +17,27 @@ struct _CameraData Camera;
static struct RayTracer cameraClipPos;
static Vec2 cam_rotOffset;
static cc_bool cam_isForwardThird;
static float cam_deltaX, cam_deltaY;
static void Camera_OnRawMovement(float deltaX, float deltaY) {
cam_deltaX += deltaX; cam_deltaY += deltaY;
static struct CameraState {
float deltaX, deltaY;
} states[MAX_LOCAL_PLAYERS];
static void Camera_OnRawMovement(float deltaX, float deltaY, int deviceIndex) {
int i = Game_MapState(deviceIndex);
states[i].deltaX += deltaX;
states[i].deltaY += deltaY;
}
void Camera_KeyLookUpdate(float delta) {
if (Gui.InputGrab) return;
/* divide by 25 to have reasonable sensitivity for default mouse sens */
float amount = (Camera.Sensitivity / 25.0f) * (1000 * delta);
int i = Game.CurrentState;
if (Bind_IsTriggered[BIND_LOOK_UP]) cam_deltaY -= amount;
if (Bind_IsTriggered[BIND_LOOK_DOWN]) cam_deltaY += amount;
if (Bind_IsTriggered[BIND_LOOK_LEFT]) cam_deltaX -= amount;
if (Bind_IsTriggered[BIND_LOOK_RIGHT]) cam_deltaX += amount;
if (Bind_IsTriggered[BIND_LOOK_UP]) states[i].deltaY -= amount;
if (Bind_IsTriggered[BIND_LOOK_DOWN]) states[i].deltaY += amount;
if (Bind_IsTriggered[BIND_LOOK_LEFT]) states[i].deltaX -= amount;
if (Bind_IsTriggered[BIND_LOOK_RIGHT]) states[i].deltaX += amount;
}
/*########################################################################################################################*
@ -64,11 +70,12 @@ static void PerspectiveCamera_GetPickedBlock(struct RayTracer* t) {
static Vec2 PerspectiveCamera_GetMouseDelta(float delta) {
float sensitivity = CAMERA_SENSI_FACTOR * Camera.Sensitivity;
static float speedX, speedY, newSpeedX, newSpeedY, accelX, accelY;
int i = Game.CurrentState;
Vec2 v;
if (Camera.Smooth) {
accelX = (cam_deltaX - speedX) * 35 / Camera.Mass;
accelY = (cam_deltaY - speedY) * 35 / Camera.Mass;
accelX = (states[i].deltaX - speedX) * 35 / Camera.Mass;
accelY = (states[i].deltaY - speedY) * 35 / Camera.Mass;
newSpeedX = accelX * delta + speedX;
newSpeedY = accelY * delta + speedY;
@ -79,11 +86,12 @@ static Vec2 PerspectiveCamera_GetMouseDelta(float delta) {
if (newSpeedY * speedY < 0) speedY = 0;
else speedY = newSpeedY;
} else {
speedX = cam_deltaX;
speedY = cam_deltaY;
speedX = states[i].deltaX;
speedY = states[i].deltaY;
}
v.x = speedX * sensitivity; v.y = speedY * sensitivity;
v.x = speedX * sensitivity;
v.y = speedY * sensitivity;
if (Camera.Invert) v.y = -v.y;
return v;
}
@ -94,7 +102,8 @@ static void PerspectiveCamera_UpdateMouseRotation(struct LocalPlayer* p, float d
Vec2 rot = PerspectiveCamera_GetMouseDelta(delta);
if (Input_IsAltPressed() && Camera.Active->isThirdPerson) {
cam_rotOffset.x += rot.x; cam_rotOffset.y += rot.y;
cam_rotOffset.x += rot.x;
cam_rotOffset.y += rot.y;
return;
}
@ -111,17 +120,19 @@ static void PerspectiveCamera_UpdateMouseRotation(struct LocalPlayer* p, float d
}
static void PerspectiveCamera_UpdateMouse(struct LocalPlayer* p, float delta) {
int i = Game.CurrentState;
if (!Gui.InputGrab && Window_Main.Focused) Window_UpdateRawMouse();
PerspectiveCamera_UpdateMouseRotation(p, delta);
cam_deltaX = 0; cam_deltaY = 0;
states[i].deltaX = 0;
states[i].deltaY = 0;
}
static void PerspectiveCamera_CalcViewBobbing(struct LocalPlayer* p, float t, float velTiltScale) {
struct Entity* e = &p->Base;
struct Matrix tiltY, velX;
float vel, fall;
if (!Game_ViewBobbing) {
Camera.TiltM = Matrix_Identity;
Camera.TiltPitch = 0.0f;
@ -153,7 +164,7 @@ static Vec2 FirstPersonCamera_GetOrientation(void) {
struct LocalPlayer* p = Entities.CurPlayer;
struct Entity* e = &p->Base;
Vec2 v;
Vec2 v;
v.x = e->Yaw * MATH_DEG2RAD;
v.y = e->Pitch * MATH_DEG2RAD;
return v;
@ -261,14 +272,14 @@ static struct Camera cam_ForwardThird = {
*-----------------------------------------------------General camera------------------------------------------------------*
*#########################################################################################################################*/
static void OnRawMovement(void* obj, float deltaX, float deltaY) {
Camera.Active->OnRawMovement(deltaX, deltaY);
Camera.Active->OnRawMovement(deltaX, deltaY, 0);
}
static void OnAxisUpdate(void* obj, int port, int axis, float x, float y) {
if (!Input.RawMode) return;
if (Gamepad_AxisBehaviour[axis] != AXIS_BEHAVIOUR_CAMERA) return;
Camera.Active->OnRawMovement(x, y);
Camera.Active->OnRawMovement(x, y, port);
}
static void OnHacksChanged(void* obj) {

View File

@ -57,7 +57,7 @@ struct Camera {
/* Typically, this is used to adjust yaw/pitch based on accumulated mouse movement. */
void (*UpdateMouse)(struct LocalPlayer* p, float delta);
/* Called when mouse/pointer has moved. */
void (*OnRawMovement)(float deltaX, float deltaY);
void (*OnRawMovement)(float deltaX, float deltaY, int deviceIndex);
/* Called when user closes all menus, and is interacting with camera again. */
void (*AcquireFocus)(void);
/* Called when user is no longer interacting with camera. (e.g. opened menu) */

View File

@ -775,7 +775,7 @@ static void LocalPlayer_Reset(struct LocalPlayer* p) {
static void LocalPlayers_Reset(void) {
int i;
for (i = 0; i < Game_NumLocalPlayers; i++)
for (i = 0; i < Game_NumStates; i++)
{
LocalPlayer_Reset(&LocalPlayer_Instances[i]);
}
@ -793,18 +793,14 @@ static void LocalPlayer_OnNewMap(struct LocalPlayer* p) {
static void LocalPlayers_OnNewMap(void) {
int i;
for (i = 0; i < Game_NumLocalPlayers; i++)
for (i = 0; i < Game_NumStates; i++)
{
LocalPlayer_OnNewMap(&LocalPlayer_Instances[i]);
}
}
static struct LocalPlayer* LocalPlayer_Get(int deviceIndex) {
if (Game_NumLocalPlayers >= 4 && deviceIndex == 3) return &LocalPlayer_Instances[3];
if (Game_NumLocalPlayers >= 3 && deviceIndex == 2) return &LocalPlayer_Instances[2];
if (Game_NumLocalPlayers >= 2 && deviceIndex == 1) return &LocalPlayer_Instances[1];
return &LocalPlayer_Instances[0];
return &LocalPlayer_Instances[Game_MapState(deviceIndex)];
}
static cc_bool LocalPlayer_IsSolidCollide(BlockID b) { return Blocks.Collide[b] == COLLIDE_SOLID; }
@ -1036,7 +1032,7 @@ void LocalPlayers_MoveToSpawn(struct LocationUpdate* update) {
struct LocalPlayer* p;
int i;
for (i = 0; i < Game_NumLocalPlayers; i++)
for (i = 0; i < Game_NumStates; i++)
{
p = &LocalPlayer_Instances[i];
p->Base.VTABLE->SetLocation(&p->Base, update);
@ -1128,7 +1124,7 @@ static void Entities_Init(void) {
ShadowMode_Names, Array_Elems(ShadowMode_Names));
if (Game_ClassicMode) Entities.ShadowsMode = SHADOW_MODE_NONE;
for (i = 0; i < Game_NumLocalPlayers; i++)
for (i = 0; i < Game_NumStates; i++)
{
LocalPlayer_Init(&LocalPlayer_Instances[i], i);
Entities.List[MAX_NET_PLAYERS + i] = &LocalPlayer_Instances[i].Base;

View File

@ -71,7 +71,7 @@ static char mppassBuffer[STRING_SIZE];
cc_string Game_Username = String_FromArray(usernameBuffer);
cc_string Game_Mppass = String_FromArray(mppassBuffer);
#ifdef CC_BUILD_SPLITSCREEN
int Game_NumLocalPlayers = 1;
int Game_NumStates = 1;
#endif
const char* const FpsLimit_Names[FPS_LIMIT_COUNT] = {
@ -697,6 +697,7 @@ static CC_INLINE void Game_DrawFrame(float delta, float t) {
static void DrawSplitscreen(float delta, float t, int i, int x, int y, int w, int h) {
Gfx_SetViewport(x, y, w, h);
Gfx_SetScissor( x, y, w, h);
Game.CurrentState = i;
Entities.CurPlayer = &LocalPlayer_Instances[i];
LocalPlayer_SetInterpPosition(Entities.CurPlayer, t);
@ -704,6 +705,14 @@ static void DrawSplitscreen(float delta, float t, int i, int x, int y, int w, in
Game_DrawFrame(delta, t);
}
int Game_MapState(int deviceIndex) {
if (Game_NumStates >= 4 && deviceIndex == 3) return 3;
if (Game_NumStates >= 3 && deviceIndex == 2) return 2;
if (Game_NumStates >= 2 && deviceIndex == 1) return 1;
return 0;
}
#endif
static CC_INLINE void Game_RenderFrame(void) {
@ -763,7 +772,7 @@ static CC_INLINE void Game_RenderFrame(void) {
Gfx_ClearBuffers(GFX_BUFFER_COLOR | GFX_BUFFER_DEPTH);
#ifdef CC_BUILD_SPLITSCREEN
switch (Game_NumLocalPlayers) {
switch (Game_NumStates) {
case 1:
Game_DrawFrame(delta, t); break;
case 2:
@ -855,6 +864,7 @@ void Game_Run(int width, int height, const cc_string* title) {
Window_SetTitle(title);
Window_Show();
gameRunning = true;
Game.CurrentState = 0;
Game_Load();
Event_RaiseVoid(&WindowEvents.Resized);

View File

@ -14,6 +14,8 @@ CC_VAR extern struct _GameData {
double Time;
/* Number of chunks updated within last second. Resets to 0 after every second. */
int ChunkUpdates;
/* Index of current game state being used (for splitscreen multiplayer) */
int CurrentState;
} Game;
extern struct RayTracer Game_SelectedPos;
@ -25,9 +27,11 @@ typedef void (*Game_Draw2DHook)(void);
extern Game_Draw2DHook Game_Draw2DHooks[4];
#ifdef CC_BUILD_SPLITSCREEN
extern int Game_NumLocalPlayers;
int Game_MapState(int deviceIndex);
extern int Game_NumStates;
#else
#define Game_NumLocalPlayers 1
static CC_INLINE int Game_MapState(int deviceIndex) { return 0; }
#define Game_NumStates 1
#endif
#if defined CC_BUILD_N64

View File

@ -58,7 +58,7 @@ static void PlayerInputGamepad(struct LocalPlayer* p, float* xMoving, float* zMo
for (port = 0; port < INPUT_MAX_GAMEPADS; port++)
{
/* In splitscreen mode, tie a controller to a specific player*/
if (Game_NumLocalPlayers > 1 && p->index != port) continue;
if (Game_NumStates > 1 && p->index != port) continue;
PlayerInputPad(port, PAD_AXIS_LEFT, p, xMoving, zMoving);
PlayerInputPad(port, PAD_AXIS_RIGHT, p, xMoving, zMoving);
@ -928,7 +928,7 @@ static void Player_ReleaseDown(int key, struct InputDevice* device) {
static void PlayerInputNormal(struct LocalPlayer* p, float* xMoving, float* zMoving) {
int flags = 0, port;
if (Game_NumLocalPlayers == 1) {
if (Game_NumStates == 1) {
for (port = 0; port < INPUT_MAX_GAMEPADS; port++)
flags |= moveFlags[port];
} else {

View File

@ -650,7 +650,7 @@ LAYOUTS sps_btnBack[] = { { ANCHOR_CENTRE, 0 }, { ANCHOR_CENTRE, 170 } };
static void SplitScreen_Start(int players) {
static const cc_string user = String_FromConst(DEFAULT_USERNAME);
Game_NumLocalPlayers = players;
Game_NumStates = players;
Launcher_StartGame(&user, &String_Empty, &String_Empty, &String_Empty, &String_Empty);
}

View File

@ -112,7 +112,7 @@ static void JNICALL java_processKeyDown(JNIEnv* env, jobject o, jint code) {
Input.Sources |= INPUT_SOURCE_GAMEPAD;
int port = Gamepad_Connect(0xAD01D, PadBind_Defaults);
Gamepad_SetButton(port, key);
Gamepad_SetButton(port, key, true);
} else {
if (key) Input_SetPressed(key);
}
@ -121,7 +121,15 @@ static void JNICALL java_processKeyDown(JNIEnv* env, jobject o, jint code) {
static void JNICALL java_processKeyUp(JNIEnv* env, jobject o, jint code) {
int key = MapNativeKey(code);
Platform_Log2("KEY - UP %i,%i", &code, &key);
if (key) Input_SetReleased(key);
if (Input_IsPadButton(key)) {
Input.Sources |= INPUT_SOURCE_GAMEPAD;
int port = Gamepad_Connect(0xAD01D, PadBind_Defaults);
Gamepad_SetButton(port, key, false);
} else {
if (key) Input_SetReleased(key);
}
}
static void JNICALL java_processKeyChar(JNIEnv* env, jobject o, jint code) {

View File

@ -126,7 +126,7 @@ static void ProcessCircleInput(int port, SceCtrlData* pad, float delta) {
}
void Gamepads_Process(float delta) {
int port = Gamepad_Connect(0x5O3, PadBind_Defaults);
int port = Gamepad_Connect(0x503, PadBind_Defaults);
SceCtrlData pad;
/* TODO implement */

View File

@ -176,7 +176,7 @@ static void ProcessCircleInput(int port, int axis, int x, int y, float delta) {
}
static void ProcessPadInput(float delta) {
int port = Gamepad_Connect(0x5O3, PadBind_Defaults);
int port = Gamepad_Connect(0x503, PadBind_Defaults);
SceCtrlData pad;
// sceCtrlReadBufferPositive is blocking (seems to block until vblank), and don't want that

View File

@ -49,7 +49,6 @@ static UINT (WINAPI *_GetRawInputData)(HRAWINPUT hRawInput, UINT cmd, void* data
static BOOL (WINAPI* _SetProcessDPIAware)(void);
static HINSTANCE win_instance;
static HWND win_handle;
static HDC win_DC;
static cc_bool suppress_resize;
static cc_bool is_ansiWindow, grabCursor;