Skip to content

Commit

Permalink
#15 gamepad support on web platform, PSX-like Lara controls
Browse files Browse the repository at this point in the history
  • Loading branch information
XProger committed Oct 11, 2016
1 parent bf5c3a3 commit c22ffa8
Show file tree
Hide file tree
Showing 19 changed files with 155 additions and 66 deletions.
Binary file modified bin/OpenLara.exe
Binary file not shown.
3 changes: 3 additions & 0 deletions src/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ struct Camera : Controller {
angleAdv.y += delta.x * 0.01f;
Input::mouse.start.R = Input::mouse.pos;
}

angleAdv.x -= Input::joy.L.y * 2.0f * Core::deltaTime;
angleAdv.y += Input::joy.L.x * 2.0f * Core::deltaTime;

angle = owner->angle + angleAdv;
angle.z = 0.0f;
Expand Down
4 changes: 2 additions & 2 deletions src/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ namespace Debug {

vec3 v = ((Controller*)level.entities[0].controller)->getDir();
vec3 p = v - n * n.dot(v);
vec3 c = b + p.normal() * 256.0f;
vec3 d = b + p.normal() * 256.0f;

glBegin(GL_LINES);
glColor3f(1, 1, 1);
Expand All @@ -312,7 +312,7 @@ namespace Debug {

glColor3f(1, 1, 0);
glVertex3fv((GLfloat*)&b);
glVertex3fv((GLfloat*)&c);
glVertex3fv((GLfloat*)&d);
glEnd();
}

Expand Down
27 changes: 14 additions & 13 deletions src/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ enum InputKey { ikNone,
// touch
ikTouchA, ikTouchB,
// gamepad
ikJoyA, ikJoyB, ikJoyX, ikJoyY, ikJoyLB, ikJoyRB, ikJoyL, ikJoyR, ikJoySelect, ikJoyStart, ikJoyLT, ikJoyRT, ikJoyDP,
ikJoyA, ikJoyB, ikJoyX, ikJoyY, ikJoyLB, ikJoyRB, ikJoyL, ikJoyR, ikJoySelect, ikJoyStart, ikJoyLT, ikJoyRT, ikJoyPOV,
ikMAX };

namespace Input {
Expand All @@ -30,7 +30,8 @@ namespace Input {

struct {
vec2 L, R;
float LT, RT, DP;
float LT, RT;
int POV;
} joy;

struct {
Expand Down Expand Up @@ -58,27 +59,27 @@ namespace Input {
case ikMouseR : mouse.start.R = mouse.pos; break;
case ikMouseM : mouse.start.M = mouse.pos; break;
case ikTouchA : touch.start.A = touch.A; break;
case ikTouchB : touch.start.B = touch.B; break;
case ikTouchB : touch.start.B = touch.B; break;
default : ;
}

down[key] = value;
}

void setPos(InputKey key, const vec2 &pos) {
switch (key) {
case ikMouseL :
case ikMouseR :
case ikMouseM : mouse.pos = pos; break;
case ikJoyL : joy.L = pos; break;
case ikJoyR : joy.R = pos; break;
case ikJoyLT : joy.LT = pos.x; break;
case ikJoyRT : joy.RT = pos.x; break;
case ikJoyDP : joy.DP = pos.x; break;
case ikTouchA : touch.A = pos; break;
case ikTouchB : touch.B = pos; break;
default : ;
case ikMouseM : mouse.pos = pos; return;
case ikJoyL : joy.L = pos; return;
case ikJoyR : joy.R = pos; return;
case ikTouchA : touch.A = pos; return;
case ikTouchB : touch.B = pos; return;
case ikJoyLT : joy.LT = pos.x; break;
case ikJoyRT : joy.RT = pos.x; break;
case ikJoyPOV : joy.POV = (int)pos.x; break;
default : return;
}
setDown(key, pos.x > 0.0f);
}
}

Expand Down
18 changes: 11 additions & 7 deletions src/lara.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ struct Lara : Controller {
TR::Level::FloorInfo info;
level->getFloorInfo(getRoomIndex(), (int)p.x, (int)p.z, info);

if (abs(info.floor - (p.y - 768.0f + 64.0f)) < 32) {
if (abs(int(info.floor - (p.y - 768.0f + 64.0f))) < 32) {
turnToWall();
pos = pos - getDir() * 128.0f; // TODO: collision wall offset
pos.y = info.floor + 768.0f - 64.0f;
Expand Down Expand Up @@ -556,18 +556,23 @@ struct Lara : Controller {
case STAND_HANG : return STATE_HANG;
case STAND_ONWATER : return STATE_SURF_TREAD;
case STAND_UNDERWATER : return STATE_TREAD;
default : ;
}
return STATE_FALL;
}

virtual int getInputMask() {
mask = 0;
if (Input::down[ikW] || Input::joy.L.y < 0) mask |= FORTH;
if (Input::down[ikS] || Input::joy.L.y > 0) mask |= BACK;
if (Input::down[ikA] || Input::joy.L.x < 0) mask |= LEFT;
if (Input::down[ikD] || Input::joy.L.x > 0) mask |= RIGHT;
int &p = Input::joy.POV;
if (Input::down[ikW] || p == 8 || p == 1 || p == 2) mask |= FORTH;
if (Input::down[ikD] || p == 2 || p == 3 || p == 4) mask |= RIGHT;
if (Input::down[ikS] || p == 4 || p == 5 || p == 6) mask |= BACK;
if (Input::down[ikA] || p == 6 || p == 7 || p == 8) mask |= LEFT;
if (Input::down[ikJoyB]) mask = FORTH | BACK; // roll
if (Input::down[ikJoyRT]) mask = WALK | RIGHT; // step right
if (Input::down[ikJoyLT]) mask = WALK | LEFT; // step left
if (Input::down[ikSpace] || Input::down[ikJoyX]) mask |= JUMP;
if (Input::down[ikShift] || Input::down[ikJoyLT]) mask |= WALK;
if (Input::down[ikShift] || Input::down[ikJoyLB]) mask |= WALK;
if (Input::down[ikE] || Input::down[ikMouseL] || Input::down[ikJoyA]) mask |= ACTION;
if (Input::down[ikQ] || Input::down[ikMouseR] || Input::down[ikJoyY]) mask |= WEAPON;
if (health <= 0) mask = DEATH;
Expand Down Expand Up @@ -839,7 +844,6 @@ struct Lara : Controller {
pos.y += DESCENT_SPEED * Core::deltaTime;
}


updateEntity();
}
}
Expand Down
7 changes: 3 additions & 4 deletions src/libs/stb_vorbis/stb_vorbis.c
Original file line number Diff line number Diff line change
Expand Up @@ -1022,11 +1022,10 @@ static float float32_unpack(uint32 x)
}
*/
float ldexpi(int m, int e) {
return m * pow(2, e);
return (float)(m * pow(2, e));
}

static float float32_unpack(uint32 x)
{
static float float32_unpack(uint32 x) {
// from the specification
uint32 s = x & 0x80000000;
int32 m = x & 0x1fffff;
Expand Down Expand Up @@ -1223,7 +1222,7 @@ static int lookup1_values(int a, int b)
int r = 0, p = 0;
do {
r++;
p = pow(r, b);
p = (int)pow(r, b);
} while (p <= a);
return r - 1;
}
Expand Down
2 changes: 0 additions & 2 deletions src/nix/build.sh

This file was deleted.

2 changes: 2 additions & 0 deletions src/platform/nix/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
clang++ -std=c++11 -Os -s -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -Wl,--gc-sections -DNDEBUG main.cpp ../../libs/stb_vorbis/stb_vorbis.c -I../../ -o../../../bin/OpenLara -lX11 -lGL -lm -lpthread -lpulse-simple -lpulse
strip ../../../bin/OpenLara --strip-all --remove-section=.comment --remove-section=.note
4 changes: 3 additions & 1 deletion src/nix/howto.txt → src/platform/nix/howto.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
sudo apt-get install git clang libx11-dev libgl1-mesa-dev libpulse-dev
git clone https://github.com/XProger/OpenLara
cd OpenLara/src/nix
cd OpenLara/src/platform/nix
./build.sh
cd ../../../bin/
./OpenLara
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions src/platform/web/build.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@echo off
cls
set SRC=main.cpp
set PROJ=OpenLara
set FLAGS=-O3 -Wno-deprecated-register --llvm-opts 2 -std=c++11 -I../../
set PRELOAD=./LEVEL2_DEMO.PHD
echo.
call em++ %SRC% %FLAGS% -o %PROJ%.js --preload-file %PRELOAD%
gzip.exe -9 -f %PROJ%.data %PROJ%.js %PROJ%.js.mem
File renamed without changes.
67 changes: 66 additions & 1 deletion src/web/main.cpp → src/platform/web/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,72 @@ extern "C" {
}
}

InputKey joyToInputKey(int code) {
static const int codes[] = { 0, 1, 2, 3, 4, 5, 10, 11, 8, 9, 6, 7 };

for (int i = 0; i < sizeof(codes) / sizeof(codes[0]); i++)
if (codes[i] == code)
return (InputKey)(ikJoyA + i);

return ikNone;
}

int joyGetPOV(int mask) {
switch (mask) {
case 0b0001 : return 1;
case 0b1001 : return 2;
case 0b1000 : return 3;
case 0b1010 : return 4;
case 0b0010 : return 5;
case 0b0110 : return 6;
case 0b0100 : return 7;
case 0b0101 : return 8;
}
return 0;
}

#define JOY_DEAD_ZONE_STICK 0.3f
#define JOY_DEAD_ZONE_TRIGGER 0.01f

vec2 joyAxis(float x, float y) {
if (fabsf(x) > JOY_DEAD_ZONE_STICK || fabsf(y) > JOY_DEAD_ZONE_STICK)
return vec2(x, y);
return vec2(0.0f);
}

vec2 joyTrigger(float x) {
return vec2(x > JOY_DEAD_ZONE_TRIGGER ? x : 0.0f, 0.0f);
}

void joyUpdate() {
int count = emscripten_get_num_gamepads();
if (count <= 0)
return;

EmscriptenGamepadEvent state;
if (emscripten_get_gamepad_status(0, &state) != EMSCRIPTEN_RESULT_SUCCESS)
return;

for (int i = 0; i < max(state.numButtons, 12); i++) {
InputKey key = joyToInputKey(i);
Input::setDown(key, state.digitalButton[i]);
if (key == ikJoyLT || key == ikJoyRT)
Input::setPos(key, joyTrigger(state.analogButton[i]));
}

if (state.numButtons > 15) { // get POV
auto &b = state.digitalButton;
int pov = joyGetPOV(b[12] | (b[13] << 1) | (b[14] << 2) | (b[15] << 3));
Input::setPos(ikJoyPOV, vec2((float)pov, 0.0f));
}

if (state.numAxes > 1) Input::setPos(ikJoyL, joyAxis(state.axis[0], state.axis[1]));
if (state.numAxes > 3) Input::setPos(ikJoyR, joyAxis(state.axis[2], state.axis[3]));
}

void main_loop() {
joyUpdate();

int time = getTime();

if (time - lastTime <= 0)
Expand Down Expand Up @@ -82,7 +147,7 @@ void freeGL() {
}

InputKey keyToInputKey(int code) {
int codes[] = {
static const int codes[] = {
0x25, 0x27, 0x26, 0x28, 0x20, 0x0D, 0x1B, 0x10, 0x11, 0x12,
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
Expand Down
File renamed without changes.
50 changes: 25 additions & 25 deletions src/win/OpenLara.vcxproj → src/platform/win/OpenLara.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\bin\</OutDir>
<IncludePath>..\;$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);</IncludePath>
<OutDir>..\..\..\bin\</OutDir>
<IncludePath>..\..\;$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>..\..\bin\</OutDir>
<OutDir>..\..\..\bin\</OutDir>
<GenerateManifest>false</GenerateManifest>
<IncludePath>..\;$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);</IncludePath>
<IncludePath>..\..\;$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
Expand Down Expand Up @@ -97,32 +97,32 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\libs\minimp3\minimp3.cpp" />
<ClCompile Include="..\libs\stb_vorbis\stb_vorbis.c" />
<ClCompile Include="..\..\libs\minimp3\minimp3.cpp" />
<ClCompile Include="..\..\libs\stb_vorbis\stb_vorbis.c" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\camera.h" />
<ClInclude Include="..\controller.h" />
<ClInclude Include="..\core.h" />
<ClInclude Include="..\debug.h" />
<ClInclude Include="..\enemy.h" />
<ClInclude Include="..\game.h" />
<ClInclude Include="..\input.h" />
<ClInclude Include="..\lara.h" />
<ClInclude Include="..\level.h" />
<ClInclude Include="..\libs\minimp3\libc.h" />
<ClInclude Include="..\libs\minimp3\minimp3.h" />
<ClInclude Include="..\mesh.h" />
<ClInclude Include="..\shader.h" />
<ClInclude Include="..\sound.h" />
<ClInclude Include="..\texture.h" />
<ClInclude Include="..\format.h" />
<ClInclude Include="..\trigger.h" />
<ClInclude Include="..\utils.h" />
<ClInclude Include="..\..\camera.h" />
<ClInclude Include="..\..\controller.h" />
<ClInclude Include="..\..\core.h" />
<ClInclude Include="..\..\debug.h" />
<ClInclude Include="..\..\enemy.h" />
<ClInclude Include="..\..\game.h" />
<ClInclude Include="..\..\input.h" />
<ClInclude Include="..\..\lara.h" />
<ClInclude Include="..\..\level.h" />
<ClInclude Include="..\..\libs\minimp3\libc.h" />
<ClInclude Include="..\..\libs\minimp3\minimp3.h" />
<ClInclude Include="..\..\mesh.h" />
<ClInclude Include="..\..\shader.h" />
<ClInclude Include="..\..\sound.h" />
<ClInclude Include="..\..\texture.h" />
<ClInclude Include="..\..\format.h" />
<ClInclude Include="..\..\trigger.h" />
<ClInclude Include="..\..\utils.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\shader.glsl" />
<None Include="..\..\shader.glsl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
25 changes: 17 additions & 8 deletions src/win/main.cpp → src/platform/win/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ DWORD getTime() {

// common input functions
InputKey keyToInputKey(int code) {
int codes[] = {
static const int codes[] = {
VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_SPACE, VK_RETURN, VK_ESCAPE, VK_SHIFT, VK_CONTROL, VK_MENU,
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
Expand Down Expand Up @@ -61,7 +61,7 @@ void joyInit() {
void joyFree() {
joyReady = false;
memset(&Input::joy, 0, sizeof(Input::joy));
for (int ik = ikJoyA; ik <= ikJoyDP; ik++)
for (int ik = ikJoyA; ik <= ikJoyPOV; ik++)
Input::down[ik] = false;
}

Expand All @@ -72,7 +72,7 @@ float joyAxis(int x, int xMin, int xMax) {
vec2 joyDir(float ax, float ay) {
vec2 dir = vec2(ax, ay);
float dist = min(1.0f, dir.length());
if (dist < JOY_DEAD_ZONE_STICK) dist = 0;
if (dist < JOY_DEAD_ZONE_STICK) dist = 0.0f;

return dir.normal() * dist;
}
Expand All @@ -96,13 +96,22 @@ void joyUpdate() {
joyAxis(info.dwRpos, caps.wRmin, caps.wRmax)));

if (caps.wCaps & JOYCAPS_HASZ) {
float z = joyAxis(info.dwZpos, caps.wZmin, caps.wZmax);
if (fabsf(z) > JOY_DEAD_ZONE_TRIGGER)
Input::setPos(z > 0.0f ? ikJoyLT : ikJoyRT, vec2(fabsf(z), 0.0f));
float z = joyAxis(info.dwZpos, caps.wZmin, caps.wZmax);
InputKey key = z > JOY_DEAD_ZONE_TRIGGER ? ikJoyLT : (z < -JOY_DEAD_ZONE_TRIGGER ? ikJoyRT : ikNone);
if (key != ikNone) {
Input::setPos(key, vec2(fabsf(z), 0.0f));
Input::setPos(key == ikJoyLT ? ikJoyRT : ikJoyLT, vec2(0.0f)); // release opposite trigger
} else {
Input::setPos(ikJoyLT, vec2(0.0f));
Input::setPos(ikJoyRT, vec2(0.0f));
}
}

if (caps.wCaps & JOYCAPS_HASPOV && info.dwPOV != JOY_POVCENTERED)
Input::setPos(ikJoyDP, vec2((float)(1 + info.dwPOV / 4500), 0));
if (caps.wCaps & JOYCAPS_HASPOV)
if (info.dwPOV == JOY_POVCENTERED)
Input::setPos(ikJoyPOV, vec2(0.0f));
else
Input::setPos(ikJoyPOV, vec2(float(1 + info.dwPOV / 4500), 0.0f));

for (int i = 0; i < 10; i++)
Input::setDown((InputKey)(ikJoyA + i), (info.dwButtons & (1 << i)) > 0);
Expand Down
File renamed without changes.
3 changes: 0 additions & 3 deletions src/web/build.bat

This file was deleted.

0 comments on commit c22ffa8

Please sign in to comment.