Initial support for "haptic" (force feedback) devices.
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Fri, 15 Jan 2010 13:57:02 +0000 (14:57 +0100)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Sun, 21 Feb 2010 07:58:50 +0000 (08:58 +0100)
src/control/haptic_manager.cpp [new file with mode: 0644]
src/control/haptic_manager.hpp [new file with mode: 0644]
src/control/joystickkeyboardcontroller.cpp
src/object/player.cpp
src/supertux/globals.cpp
src/supertux/globals.hpp
src/supertux/main.cpp

diff --git a/src/control/haptic_manager.cpp b/src/control/haptic_manager.cpp
new file mode 100644 (file)
index 0000000..826d3ff
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *  SuperTux
+ *  Copyright (C) 2010 Florian Forster <octo at verplant.org>
+ *
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 (file)
index 0000000..8c9669b
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  SuperTux
+ *  Copyright (C) 2010 Florian Forster <octo at verplant.org>
+ *
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CONTROL_HAPTIC_MANAGER_H
+#define CONTROL_HAPTIC_MANAGER_H 1
+
+#include <SDL.h>
+
+#if SDL_VERSION_ATLEAST(1,3,0)
+# include <SDL_haptic.h>
+#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 : */
index fa7d75f..784d186 100644 (file)
@@ -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);
     }
   }
 
index 3cc8a3c..8d771a4 100644 (file)
@@ -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) {
index 4672875..44c16e3 100644 (file)
 //  You should have received a copy of the GNU General Public License
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+#include "control/haptic_manager.hpp"
 #include "supertux/globals.hpp"
 #include <tinygettext/tinygettext.hpp>
 
 SDL_Surface* g_screen;
 JoystickKeyboardController* g_main_controller = 0;
+HapticManager* g_haptic_manager = 0;
 tinygettext::DictionaryManager* dictionary_manager = 0;
 
 int SCREEN_WIDTH;
index 08a4830..5fcb632 100644 (file)
@@ -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;
index 98a6cc3..48c2b7e 100644 (file)
@@ -17,6 +17,7 @@
 #include <config.h>
 #include <version.h>
 
+#include <SDL.h>
 #include <SDL_image.h>
 #include <physfs.h>
 #include <iostream>
@@ -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();