From f9cb55ad4e8ff6e6ec974f8aa1eb53c19c95c1b1 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Fri, 15 Jan 2010 14:57:02 +0100 Subject: [PATCH] Initial support for "haptic" (force feedback) devices. --- src/control/haptic_manager.cpp | 94 ++++++++++++++++++++++++++++++ src/control/haptic_manager.hpp | 51 ++++++++++++++++ src/control/joystickkeyboardcontroller.cpp | 3 + src/object/player.cpp | 5 ++ src/supertux/globals.cpp | 2 + src/supertux/globals.hpp | 4 ++ src/supertux/main.cpp | 7 ++- 7 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 src/control/haptic_manager.cpp create mode 100644 src/control/haptic_manager.hpp diff --git a/src/control/haptic_manager.cpp b/src/control/haptic_manager.cpp new file mode 100644 index 000000000..826d3ffb3 --- /dev/null +++ b/src/control/haptic_manager.cpp @@ -0,0 +1,94 @@ +/* + * SuperTux + * Copyright (C) 2010 Florian Forster + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "control/haptic_manager.hpp" +#include "util/log.hpp" + +HapticManager::HapticManager () /* {{{ */ +{ + int i; + + _device = NULL; + memset (_effects, 0, sizeof (_effects)); + for (i = 0; i < ST_HAPTIC_EFFECT_MAX; i++) + _effect_ids[i] = -1; +} /* }}} HapticManager */ + +/* Public methods */ +void HapticManager::addJoystick (SDL_Joystick *j) { /* {{{ */ + int supported; + + if (j == NULL) + return; + + if (_device != NULL) + return; + + if (SDL_JoystickIsHaptic (j) <= 0) + return; + + _device = SDL_HapticOpenFromJoystick (j); + if (_device == NULL) + return; + + supported = SDL_HapticQuery (_device); + if ((supported & SDL_HAPTIC_SINE) == 0) + { + SDL_HapticClose (_device); + _device = NULL; + return; + } + + /* Setup buttjump */ + _effects[ST_HAPTIC_EFFECT_BUTTJUMP].type = SDL_HAPTIC_SINE; + _effects[ST_HAPTIC_EFFECT_BUTTJUMP].periodic.direction.type = SDL_HAPTIC_POLAR; + _effects[ST_HAPTIC_EFFECT_BUTTJUMP].periodic.direction.dir[0] = 18000; /* south */ + _effects[ST_HAPTIC_EFFECT_BUTTJUMP].periodic.period = 50; + _effects[ST_HAPTIC_EFFECT_BUTTJUMP].periodic.magnitude = 0x4FFF; + _effects[ST_HAPTIC_EFFECT_BUTTJUMP].periodic.length = 250; + _effects[ST_HAPTIC_EFFECT_BUTTJUMP].periodic.attack_length = 0; + _effects[ST_HAPTIC_EFFECT_BUTTJUMP].periodic.fade_length = 0; + + _effect_ids[ST_HAPTIC_EFFECT_BUTTJUMP] = SDL_HapticNewEffect (_device, + &_effects[ST_HAPTIC_EFFECT_BUTTJUMP]); + if (_effect_ids[ST_HAPTIC_EFFECT_BUTTJUMP] < 0) + { + SDL_HapticClose (_device); + _device = NULL; + return; + } + + log_debug << "Haptic manager: Successfully added joystick." << std::endl; + return; +} /* }}} void addJoystick */ + +void HapticManager::playEffect (haptic_effect_t idx) { /* {{{ */ + if ((idx < 0) || (idx >= ST_HAPTIC_EFFECT_MAX)) + return; + + if (_device == NULL) + return; + + if (_effect_ids[idx] < 0) + return; + + SDL_HapticRunEffect (_device, _effect_ids[idx], + /* iterations = */ 1); +} /* }}} void playEffect */ + +/* vim: set sw=2 sts=2 et fdm=marker : */ diff --git a/src/control/haptic_manager.hpp b/src/control/haptic_manager.hpp new file mode 100644 index 000000000..8c9669bff --- /dev/null +++ b/src/control/haptic_manager.hpp @@ -0,0 +1,51 @@ +/* + * SuperTux + * Copyright (C) 2010 Florian Forster + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef CONTROL_HAPTIC_MANAGER_H +#define CONTROL_HAPTIC_MANAGER_H 1 + +#include + +#if SDL_VERSION_ATLEAST(1,3,0) +# include +#endif + +typedef enum +{ + ST_HAPTIC_EFFECT_BUTTJUMP, + ST_HAPTIC_EFFECT_MAX +} haptic_effect_t; + +class HapticManager +{ + public: + HapticManager (); + + void addJoystick (SDL_Joystick *j); + void playEffect (haptic_effect_t e); + + private: +#if SDL_VERSION_ATLEAST(1,3,0) + SDL_Haptic *_device; + SDL_HapticEffect _effects[ST_HAPTIC_EFFECT_MAX]; + int _effect_ids[ST_HAPTIC_EFFECT_MAX]; +#endif +}; /* class HapticManager */ + +#endif /* CONTROL_HAPTIC_MANAGER_H */ +/* vim: set sw=2 sts=2 et : */ diff --git a/src/control/joystickkeyboardcontroller.cpp b/src/control/joystickkeyboardcontroller.cpp index fa7d75fc9..784d18675 100644 --- a/src/control/joystickkeyboardcontroller.cpp +++ b/src/control/joystickkeyboardcontroller.cpp @@ -160,6 +160,9 @@ JoystickKeyboardController::updateAvailableJoysticks() max_joyhats = SDL_JoystickNumHats(joystick); joysticks.push_back(joystick); + + if (g_haptic_manager != NULL) + g_haptic_manager->addJoystick (joystick); } } diff --git a/src/object/player.cpp b/src/object/player.cpp index 3cc8a3c61..8d771a4ce 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -20,6 +20,7 @@ #include "audio/sound_manager.hpp" #include "badguy/badguy.hpp" #include "control/joystickkeyboardcontroller.hpp" +#include "control/haptic_manager.hpp" #include "math/random_generator.hpp" #include "object/bullet.hpp" #include "object/camera.hpp" @@ -1173,7 +1174,11 @@ Player::collision_solid(const CollisionHit& hit) 90-40, 90-20, Vector(280, -260), Vector(0, 300), 3, Color(.4f, .4f, .4f), 3, .8f, LAYER_OBJECTS+1)); + Sector::current()->camera->shake(.1f, 0, 5); + + if (g_haptic_manager != NULL) + g_haptic_manager->playEffect (ST_HAPTIC_EFFECT_BUTTJUMP); } } else if(hit.top) { diff --git a/src/supertux/globals.cpp b/src/supertux/globals.cpp index 4672875f4..44c16e360 100644 --- a/src/supertux/globals.cpp +++ b/src/supertux/globals.cpp @@ -14,11 +14,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include "control/haptic_manager.hpp" #include "supertux/globals.hpp" #include SDL_Surface* g_screen; JoystickKeyboardController* g_main_controller = 0; +HapticManager* g_haptic_manager = 0; tinygettext::DictionaryManager* dictionary_manager = 0; int SCREEN_WIDTH; diff --git a/src/supertux/globals.hpp b/src/supertux/globals.hpp index 08a48304e..5fcb632e8 100644 --- a/src/supertux/globals.hpp +++ b/src/supertux/globals.hpp @@ -17,6 +17,8 @@ #ifndef HEADER_SUPERTUX_SUPERTUX_GLOBALS_HPP #define HEADER_SUPERTUX_SUPERTUX_GLOBALS_HPP +#include "control/haptic_manager.hpp" + typedef struct SDL_Surface SDL_Surface; namespace tinygettext { class DictionaryManager; } class Config; @@ -42,6 +44,8 @@ extern int SCREEN_HEIGHT; // global variables extern JoystickKeyboardController* g_main_controller; +extern HapticManager* g_haptic_manager; + extern SDL_Surface* g_screen; extern ScreenManager* g_screen_manager; diff --git a/src/supertux/main.cpp b/src/supertux/main.cpp index 98a6cc3d6..48c2b7ebd 100644 --- a/src/supertux/main.cpp +++ b/src/supertux/main.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,7 @@ namespace supertux_apple { #include "addon/addon_manager.hpp" #include "audio/sound_manager.hpp" #include "control/joystickkeyboardcontroller.hpp" +#include "control/haptic_manager.hpp" #include "math/random_generator.hpp" #include "physfs/ifile_stream.hpp" #include "physfs/physfs_sdl.hpp" @@ -399,7 +401,7 @@ Main::parse_commandline(int argc, char** argv) void Main::init_sdl() { - if(SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { + if(SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC) < 0) { std::stringstream msg; msg << "Couldn't initialize SDL: " << SDL_GetError(); throw std::runtime_error(msg.str()); @@ -555,6 +557,9 @@ Main::run(int argc, char** argv) init_physfs(argv[0]); init_sdl(); + timelog("haptic"); + g_haptic_manager = new HapticManager(); + timelog("controller"); g_main_controller = new JoystickKeyboardController(); -- 2.11.0