mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 01:55:19 -04:00
Splitscreen: Tie camera input to controller ports
This commit is contained in:
parent
e83eea9ae9
commit
c3de1a30c4
@ -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)
|
||||
|
47
src/Camera.c
47
src/Camera.c
@ -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) {
|
||||
|
@ -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) */
|
||||
|
14
src/Entity.c
14
src/Entity.c
@ -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;
|
||||
|
14
src/Game.c
14
src/Game.c
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user