diff --git a/bin/Makefile b/bin/Makefile
index f69e2fd..4cd4473 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -1,13 +1,15 @@
 DEBUG = 1
 APPNAME = Lephisto
 
+VERSION = -DVMAJOR=0 -DVMINOR=0 -DVREV=1
+
 OBJS := $(shell find ../src/ -name '*.c' -print)
 OBJS := $(OBJS:../src/%.c=../src/%.o)
 
 DATA = data
 DATAFILES = $(shell find ../gfx/ ../dat/ -name '*.png' -o -name '*.xml' -print)
 
-CFLAGS = -Wall `sdl-config --cflags` `xml2-config --cflags`
+CFLAGS = -Wall `sdl-config --cflags` `xml2-config --cflags` $(VERSION)
 ifdef DEBUG
 CFLAGS += -g3 -DDEBUG
 else
diff --git a/dat/ship.xml b/dat/ship.xml
index e657d1c..f9ed5f2 100644
--- a/dat/ship.xml
+++ b/dat/ship.xml
@@ -5,7 +5,7 @@
 		<class>1</class>
 		<movement>
 			<thrust>400</thrust>
-			<turn>360</turn>
+			<turn>960</turn>
 			<speed>360</speed>
 		</movement>
 		<health>
diff --git a/src/def.h b/src/def.h
index 9b0e851..fae8351 100644
--- a/src/def.h
+++ b/src/def.h
@@ -3,6 +3,8 @@
 #define MALLOC_L(type)(malloc(sizeof(type)))
 #define CALLOC_L(type)(calloc(1, sizeof(type)))
 
+#define ABS(X) ((X<0)?-X:X)
+
 typedef float FP;
 
 #define DATA "data"
diff --git a/src/joystick.c b/src/joystick.c
index a402beb..0379909 100644
--- a/src/joystick.c
+++ b/src/joystick.c
@@ -3,14 +3,31 @@
 #include "log.h"
 #include "joystick.h"
 
-static SDL_Joystick* joystick;
+static SDL_Joystick* joystick = NULL;
+
+int joystick_use(int indjoystick) {
+  // Start using the joystick.
+  LOG("Using joystick %d", indjoystick);
+  joystick = SDL_JoystickOpen(indjoystick);
+  if(joystick == NULL) {
+    WARN("Error opening joystick %d [%s]", indjoystick, SDL_JoystickName(indjoystick));
+    return -1;
+  }
+  DEBUG("\t\tWith %d axes, %d buttons, %d balls, and %d hats",
+        SDL_JoystickNumAxes(joystick), SDL_JoystickNumButtons(joystick),
+        SDL_JoystickNumBalls(joystick), SDL_JoystickNumHats(joystick));
+
+  return 0;
+}
 
 int joystick_init(void) {
-  int indjoystick, numjoysticks, i;
-  indjoystick = 1;
+  int numjoysticks, i;
 
   // Init the SDL subsys.
-  SDL_InitSubSystem(SDL_INIT_JOYSTICK);
+  if(SDL_InitSubSystem(SDL_INIT_JOYSTICK)) {
+    WARN("Unable to init the joystick subsystem.");
+    return -1;
+  }
 
   // Figure out how many joysticks there are.
   numjoysticks = SDL_NumJoysticks();
@@ -18,10 +35,13 @@ int joystick_init(void) {
   for(i = 0; i < numjoysticks; i++)
     LOG("\t\t%d. %s", i, SDL_JoystickName(i));
 
-  // Start using that bitch.
-  LOG("Using joystick %d", indjoystick);
-  joystick = SDL_JoystickOpen(indjoystick);
+  // Enable joystick events.
+  SDL_JoystickEventState(SDL_ENABLE);
 
   return 0;
 }
 
+void joystick_exit(void) {
+  SDL_JoystickClose(joystick);
+}
+
diff --git a/src/joystick.h b/src/joystick.h
index d2081c1..f68fc66 100644
--- a/src/joystick.h
+++ b/src/joystick.h
@@ -1,2 +1,7 @@
-int joystick_init(void);
+#pragma once
+
+int joystick_use(int indjoystick);
+
+int joystick_init(void);
+void joystick_exit(void);
 
diff --git a/src/main.c b/src/main.c
index 2a08464..06551b6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,15 +1,15 @@
 #include <SDL.h>
-#include <stdlib.h>
+#include <unistd.h>
 
 #include "def.h"
 #include "log.h"
-#include "log.h"
 #include "physics.h"
 #include "opengl.h"
 #include "ship.h"
 #include "pilot.h"
 #include "player.h"
 #include "joystick.h"
+#include "rng.h"
 #include "pilot.h"
 
 static int quit = 0;
@@ -17,19 +17,54 @@ static int quit = 0;
 static unsigned int time = 0;
 
 // Prototypes.
-static void handle_keydown(SDLKey key);
-static void handle_keyup(SDLKey key);
 
 // Update.
 static void update_all(void);
 
-int main(int argc, const char** argv) {
+// Usage.
+void print_usage(char** argv) {
+  LOG("USAGE: %s [-f] [-j n] [-hv]", argv[0]);
+  LOG("Options are:");
+  LOG("\t-f   - Fullscreen");
+  LOG("\t-w n - Set width to (n)");
+  LOG("\t-h n - Set height to (n)");
+  LOG("\t-j n - Use joystick (n)");
+  LOG("\t-h   - Display this message and exit.");
+  LOG("\t-v   - Print the version and exit");
+}
+
+int main(int argc, char** argv) {
   SDL_Event event;
 
-  // Default window params.
+  // Default values..
   gl_screen.w = 800;
   gl_screen.h = 640;
   gl_screen.fullscreen = 0;
+  // Joystick.
+  int indjoystick = -1;
+
+  // Parse arguments.
+  int c = 0;
+  while((c = getopt(argc, argv, "fj:hv")) != -1) {
+    switch(c) {
+      case 'f':
+        gl_screen.fullscreen = 1;
+        break;
+      case 'j':
+        indjoystick = atoi(optarg);
+        break;
+      case 'v':
+        LOG("Lephisto: version %d.%d.%d\n", VMAJOR, VMINOR, VREV);
+      case 'h':
+        print_usage(argv);
+        exit(EXIT_SUCCESS);
+    }
+  }
+
+  // Random numbers.
+  rng_init();
+
+  // default window params.
   if(gl_init()) {
     // Initializes video output.
     WARN("Error initializing video output, exiting...");
@@ -37,8 +72,11 @@ int main(int argc, const char** argv) {
   }
 
   // Input.
-  if(joystick_init())
-    WARN("Error initializing joystick input");
+  if(indjoystick >= 0) {
+    if(joystick_init())
+      WARN("Error initializing joystick input");
+    joystick_use(indjoystick);
+  }
 
   // Data loading.
   ships_load();
@@ -56,70 +94,20 @@ int main(int argc, const char** argv) {
   while(!quit) {
     // Event loop.
     while(SDL_PollEvent(&event)) {
-      switch(event.type) {
-        case SDL_KEYDOWN:
-          handle_keydown(event.key.keysym.sym);
-          break;
-        case SDL_KEYUP:
-          handle_keyup(event.key.keysym.sym);
-          break;
-        case SDL_QUIT:
-          quit = 1;
-          break;
-      }
+      if(event.type == SDL_QUIT) quit = 1; // Handle quit.
+      handle_input(&event);
     }
     update_all();
   }
   // Unload data.
   pilots_free();
   ships_free();
+  // Exit subsystems.
+  joystick_exit();
   gl_exit(); // Kills video output.
   exit(EXIT_SUCCESS);
 }
 
-// Handle keydown events.
-static void handle_keydown(SDLKey key) {
-  switch(key) {
-    case SDLK_ESCAPE:
-      quit = 1;
-      break;
-    case SDLK_a:
-    case SDLK_LEFT:
-      player_setFlag(PLAYER_FLAG_MOV_LEFT);
-      break;
-    case SDLK_d:
-    case SDLK_RIGHT:
-      player_setFlag(PLAYER_FLAG_MOV_RIGHT);
-      break;
-    case SDLK_w:
-    case SDLK_UP:
-      player_setFlag(PLAYER_FLAG_MOV_ACC);
-      break;      
-    default:
-      break;
-  }
-}
-
-// Handle keyup events.
-static void handle_keyup(SDLKey key) {
-  switch(key) {
-    case SDLK_a:
-    case SDLK_LEFT:
-      player_rmFlag(PLAYER_FLAG_MOV_LEFT);
-      break;
-    case SDLK_d:
-    case SDLK_RIGHT:
-      player_rmFlag(PLAYER_FLAG_MOV_RIGHT);
-      break;
-    case SDLK_w:
-    case SDLK_UP:
-      player_rmFlag(PLAYER_FLAG_MOV_ACC);
-      break;
-    default:
-      break;
-  }
-}
-
 // Update all the things.
 // Pilots:
 //  -- Think (ai).
diff --git a/src/opengl.c b/src/opengl.c
index fff296f..c880447 100644
--- a/src/opengl.c
+++ b/src/opengl.c
@@ -4,19 +4,8 @@
 #include "log.h"
 #include "opengl.h"
 
-// Recommended for compatibility bullshit.
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-#  define RMASK 0xff000000
-#  define GMASK 0x00ff0000
-#  define BMASK 0x0000ff00
-#  define AMASK 0x000000ff
-#else
-#  define RMASK 0x000000ff
-#  define GMASK 0x0000ff00
-#  define BMASK 0x00ff0000
-#  define AMASK 0xff000000
-#endif
-#define RGBMASK RMASK,GMASK,BMASK,AMASK
+#define SCREEN_W    gl_screen.w
+#define SCREEN_H    gl_screen.h
 
 // The screen info, gives data of current opengl settings.
 gl_info gl_screen;
@@ -52,38 +41,19 @@ static int flip_surface(SDL_Surface* surface) {
   return 0;
 }
 
-// Load the image directly as an opengl texture.
-gl_texture* gl_newImage(const char* path) {
-  SDL_Surface* tmp, *surface;
+// Load the SDL_Surface to an opengl texture.
+gl_texture* gl_loadImage(SDL_Surface* surface) {
+  SDL_Surface* tmp;
   Uint32 saved_flags;
   Uint8  saved_alpha;
   int potw, poth;
 
-  tmp = IMG_Load(path); // Load the surface.
-  if(tmp == 0) {
-    WARN("'%s' could not be opened: %s", path, IMG_GetError());
-    return NULL;
-  }
-
-  surface = SDL_DisplayFormatAlpha(tmp); // Set the surface to what we use.
-  if(surface == 0) {
-    WARN("Error converting image to screen format: %s", SDL_GetError());
-    return NULL;
-  }
-
-  SDL_FreeSurface(tmp); // Free the temp surface.
-
-  if(flip_surface(surface)) {
-    WARN("Error flipping surface");
-    return NULL;
-  }
-
   // Set up the texture defaults.
   gl_texture* texture = MALLOC_L(gl_texture);
   texture->w = (FP)surface->w;
   texture->h = (FP)surface->h;
-  texture->sx = 1.0;
-  texture->sy = 1.0;
+  texture->sx = 1.;
+  texture->sy = 1.;
 
   // Ensure size is power of two.
   potw = surface->w;
@@ -132,6 +102,27 @@ gl_texture* gl_newImage(const char* path) {
 
     surface = tmp;
 
+    // Set saved alpha.
+    if((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA)
+      SDL_SetAlpha(surface, 0, 0);
+
+    // Create the temp POT surface.
+    tmp = SDL_CreateRGBSurface(SDL_SRCCOLORKEY,
+          texture->rw, texture->rh, surface->format->BytesPerPixel*8, RGBMASK);
+    if(tmp == NULL) {
+      WARN("Unable to create POT surface %s", SDL_GetError());
+      return NULL;
+    }
+    if(SDL_FillRect(tmp, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, SDL_ALPHA_TRANSPARENT))) {
+      WARN("Unable to fill rect: %s", SDL_GetError());
+      return NULL;
+    }
+
+    SDL_BlitSurface(surface, &rtemp, tmp, &rtemp);
+    SDL_FreeSurface(surface);
+
+    surface = tmp;
+  
     // Set saved alpha.
     if((saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA)
       SDL_SetAlpha(surface, saved_flags, saved_alpha);
@@ -142,8 +133,6 @@ gl_texture* gl_newImage(const char* path) {
 
   // Filtering, LINEAR is better for scaling, nearest looks nicer, LINEAR
   // also seems to create a bit of artifacts around the edges.
-  //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
@@ -154,9 +143,39 @@ gl_texture* gl_newImage(const char* path) {
   SDL_UnlockSurface(surface);
   SDL_FreeSurface(surface);
 
+  texture->sx = 1.;
+  texture->sy = 1.;
+  texture->sw = texture->w;
+  texture->sh = texture->h;
+  
   return texture;
 }
 
+// Load the image directly as an opengl texture.
+gl_texture* gl_newImage(const char* path) {
+  SDL_Surface* tmp, *surface;
+
+  tmp = IMG_Load(path); // Load the surface.
+  if(tmp == 0) {
+    WARN("'%s' could not be opened: %s", path, IMG_GetError());
+    return NULL;
+  }
+
+  surface = SDL_DisplayFormatAlpha(tmp); // Sets the surface to what we use.
+  if(surface == 0) {
+    WARN("Error converting image to screen format: %s", SDL_GetError());
+    return NULL;
+  }
+
+  SDL_FreeSurface(tmp); // Free the temp surface.
+
+  if(flip_surface(surface)) {
+    WARN("Error flipping surface");
+    return NULL;
+  }
+  return gl_loadImage(surface);
+}
+
 // Load the texture immediately, but also set is as a sprite.
 gl_texture* gl_newSprite(const char* path, const int sx, const int sy) {
   gl_texture* texture;
@@ -180,22 +199,23 @@ void gl_blitSprite(gl_texture* sprite, Vec2* pos, const int sx, const int sy) {
   glMatrixMode(GL_TEXTURE);
   glPushMatrix();
   glTranslatef(sprite->sw * (FP)(sx)/sprite->rw,
-        sprite->sh*(sprite->sy-(FP)sy-1)/sprite->rh, 0.0f);
+        sprite->sh*(sprite->sy-(FP)sy-1)/sprite->rh, 0.);
 
   glMatrixMode(GL_PROJECTION);
   glPushMatrix(); // Projection translation matrix.
-  glTranslatef(pos->x - gl_camera->x - sprite->sw/2.0,
-        pos->y - gl_camera->y - sprite->sh/2.0, 0.0f);
+  glTranslatef(pos->x - gl_camera->x - sprite->sw/2.,
+        pos->y - gl_camera->y - sprite->sh/2., 0.);
+  glScalef((FP)gl_screen.w/SCREEN_W, (FP)gl_screen.h/SCREEN_H, 0.);
 
   // Actual blitting....
   glBindTexture(GL_TEXTURE_2D, sprite->texture);
   glBegin(GL_TRIANGLE_STRIP);
-    glTexCoord2f(0.0f, 0.0f);
-      glVertex2f(0.0f, 0.0f);
-    glTexCoord2f(sprite->sw/sprite->rw, 0.0f);
-      glVertex2f(sprite->sw, 0.0f);
-    glTexCoord2f(0.0f, sprite->sh/sprite->rh);
-      glVertex2f(0.0f, sprite->sh);
+    glTexCoord2f(0., 0.);
+      glVertex2f(0., 0.);
+    glTexCoord2f(sprite->sw/sprite->rw, 0.);
+      glVertex2f(sprite->sw, 0.);
+    glTexCoord2f(0., sprite->sh/sprite->rh);
+      glVertex2f(0., sprite->sh);
     glTexCoord2f(sprite->sw/sprite->rw, sprite->sh/sprite->rh);
       glVertex2f(sprite->sw, sprite->sh);
   glEnd();
@@ -210,17 +230,18 @@ void gl_blitSprite(gl_texture* sprite, Vec2* pos, const int sx, const int sy) {
 void gl_blitStatic(gl_texture* texture, Vec2* pos) {
   glMatrixMode(GL_PROJECTION);
   glPushMatrix(); // Set up translation matrix.
-  glTranslatef(pos->x, pos->y, 0);
+  glTranslatef(pos->x - (FP)gl_screen.w/2., pos->y - (FP)gl_screen.h/2., 0);
+  glScalef((FP)gl_screen.w/SCREEN_W, (FP)gl_screen.h/SCREEN_H, 0.);
   
   // Actual blitting..
   glBindTexture(GL_TEXTURE_2D, texture->texture);
   glBegin(GL_TRIANGLE_STRIP);
-    glTexCoord2f(0.0f, 0.0f);
-      glVertex2f(0.0f, 0.0f);
-    glTexCoord2f(texture->w/texture->rw, 0.0f);
-      glVertex2f(texture->w, 0.0f);
-    glTexCoord2f(0.0f, texture->h/texture->rh);
-      glVertex2f(0.0f, texture->h);
+    glTexCoord2f(0., 0.);
+      glVertex2f(0., 0.);
+    glTexCoord2f(texture->w/texture->rw, 0.);
+      glVertex2f(texture->w, 0.);
+    glTexCoord2f(0., texture->h/texture->rh);
+      glVertex2f(0., texture->h);
     glTexCoord2f(texture->w/texture->rw, texture->h/texture->rh);
       glVertex2f(texture->w, texture->h);
   glEnd();
@@ -235,8 +256,10 @@ void gl_bindCamera(Vec2* pos) {
 
 // Initialize SDL/OpenGL etc.
 int gl_init(void) {
-  int depth;
+  int depth, i, supported = 0;
+  SDL_Rect** modes;
   int flags = SDL_OPENGL;
+  flags |= SDL_FULLSCREEN * gl_screen.fullscreen;
 
   // Initializes video.
   if(SDL_Init(SDL_INIT_VIDEO) < 0) {
@@ -248,8 +271,35 @@ int gl_init(void) {
   // -- Ok, Maybe for now.
   //SDL_ShowCursor(SDL_DISABLE);
 
-  flags |= SDL_FULLSCREEN* gl_screen.fullscreen;
-  depth = SDL_VideoModeOK(gl_screen.w, gl_screen.h, gl_screen.depth, flags); // Test set up.
+  // Get available fullscreen modes.
+  modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN);
+  if(modes == NULL) {
+    WARN("No fullscreen modes available");
+    if(flags & SDL_FULLSCREEN) {
+      WARN("Disabling fullscreen mode");
+      flags ^= SDL_FULLSCREEN;
+    }
+  }
+  else if(modes == (SDL_Rect**) -1)
+    DEBUG("All fullscreen modes available.");
+  else {
+    DEBUG("Available fullscreen modes:");
+    for(i = 0; modes[i]; ++i) {
+      DEBUG("\t\t%d x %d", modes[i]->w, modes[i]->h);
+      if(flags & SDL_FULLSCREEN && modes[i]->w == gl_screen.w && modes[i]->h == gl_screen.h)
+        supported = 1;
+    }
+  }
+  // Make sure fullscreen mode is supported.
+  if((flags & SDL_FULLSCREEN) && (!supported)) {
+    WARN("Fullscreen mode %d x %d is not supported by your current setup, switching to another mode.",
+          gl_screen.w, gl_screen.h);
+    gl_screen.w = modes[0]->w;
+    gl_screen.h = modes[0]->h;
+  }
+
+  // Test the setup.
+  depth = SDL_VideoModeOK(gl_screen.w, gl_screen.h, gl_screen.depth, flags);
   if(depth != gl_screen.depth)
     WARN("Depth: %d bpp unavailable, will use %d bpp", gl_screen.depth, depth);
 
@@ -278,17 +328,17 @@ int gl_init(void) {
   DEBUG("Renderer: %s", glGetString(GL_RENDERER));
 
   // Some openGL options.
-  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+  glClearColor(0., 0., 0., 0.);
   glDisable(GL_DEPTH_TEST); // Set for doing 2D shidazles.
   glEnable(GL_TEXTURE_2D);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
-  glOrtho(-gl_screen.w/2,   // Left edge.
-          gl_screen.w/2,    // Right edge.
-          -gl_screen.h/2,   // Bottom edge.
-          gl_screen.h/2,    // Top edge.
-          -1.0f,            // Near.
-          1.0f);            // Far.
+  glOrtho(-SCREEN_W /2,   // Left edge.
+          SCREEN_W  /2,   // Right edge.
+          -SCREEN_H /2,   // Bottom edge.
+          SCREEN_H  /2,   // Top edge.
+          -1.,            // Near.
+          1.);            // Far.
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Alpha.
   glEnable(GL_BLEND);
 
diff --git a/src/opengl.h b/src/opengl.h
index 1d41a24..42e8770 100644
--- a/src/opengl.h
+++ b/src/opengl.h
@@ -1,7 +1,22 @@
 #pragma once
-#include "SDL_opengl.h"
+#include <SDL.h>
+#include <SDL_opengl.h>
 #include "physics.h"
 
+// Recommended for compatibility bullshit.
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+#  define RMASK 0xff000000
+#  define GMASK 0x00ff0000
+#  define BMASK 0x0000ff00
+#  define AMASK 0x000000ff
+#else
+#  define RMASK 0x000000ff
+#  define GMASK 0x0000ff00
+#  define BMASK 0x00ff0000
+#  define AMASK 0xff000000
+#endif
+#define RGBMASK RMASK,GMASK,BMASK,AMASK
+
 #define WINDOW_CAPTION "Lephisto"
 
 // Info about opengl screen.
@@ -25,6 +40,7 @@ typedef struct {
 } gl_texture;
 
 // gl_texute loading/freeing.
+gl_texture* gl_loadImage(SDL_Surface* surface); // Frees the surface.
 gl_texture* gl_newImage(const char* path);
 gl_texture* gl_newSprite(const char* path, const int sx, const int sy);
 void gl_free(gl_texture* texture);
diff --git a/src/pilot.c b/src/pilot.c
index f39eaa8..f064657 100644
--- a/src/pilot.c
+++ b/src/pilot.c
@@ -81,7 +81,8 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, const Vec2* vel, const Vec
 
   if(flags & PILOT_PLAYER) {
     pilot->think = (void*)player_think; // Players don't need to thing! :P
-    pilot->think = NULL;
+    pilot->properties |= PILOT_PLAYER;
+    player = pilot;
   } else
     pilot->think = NULL;
 
diff --git a/src/pilot.h b/src/pilot.h
index 5f101ef..48016f6 100644
--- a/src/pilot.h
+++ b/src/pilot.h
@@ -22,6 +22,7 @@ struct Pilot {
 };
 typedef struct Pilot Pilot;
 
+extern Pilot* player; // The player.
 Pilot* get_pilot(unsigned int id);
 
 // Creation.
diff --git a/src/player.c b/src/player.c
index 3123e82..720de13 100644
--- a/src/player.c
+++ b/src/player.c
@@ -3,17 +3,25 @@
 #include "log.h"
 #include "player.h"
 
+Pilot* player = NULL;
 static unsigned int player_flags = PLAYER_FLAG_NULL;
 
+static FP player_turn = 0.;
+static FP player_acc  = 0.;
+
 // To be used in pilot.c
 void player_think(Pilot* player, const FP dt) {
-  player->solid->dir_vel = 0.0;
+  player->solid->dir_vel = 0.;
+  if(player_turn)
+    player->solid->dir_vel -= player->ship->turn*player_turn/(FP)(1<<15);
+#if 0
   if(player_isFlag(PLAYER_FLAG_MOV_LEFT))
     player->solid->dir_vel += player->ship->turn;
   if(player_isFlag(PLAYER_FLAG_MOV_RIGHT))
     player->solid->dir_vel -= player->ship->turn;
+#endif
 
-  player->solid->force = (player_isFlag(PLAYER_FLAG_MOV_ACC)) ? player->ship->thrust : 0.0;
+  player->solid->force = player->ship->thrust*player_acc/(FP)(1<<15);
 }
 
 // Flag manipulationz.
@@ -31,3 +39,89 @@ void player_rmFlag(unsigned int flag) {
     player_flags ^= flag;
 }
 
+// --Events--
+
+// Joystick.
+static void handle_joyaxis(int axis, int value) {
+  switch(axis) {
+    case 0:
+      player_turn = (FP)value;
+      break;
+    case 1:
+      if(value <= 0)
+        player_acc = (FP)-value;
+      break;
+  }
+}
+
+static void handle_joybutton(int button) {
+  switch(button) {
+    case 0:
+      break;
+    case 1:
+      break;
+  }
+}
+
+// Keyboard.
+static void handle_keydown(SDLKey key) {
+  SDL_Event quit;
+  switch(key) {
+    case SDLK_ESCAPE:
+      quit.type = SDL_QUIT;
+      SDL_PushEvent(&quit);
+      break;
+    case SDLK_LEFT:
+    case SDLK_a:
+      player_turn -= (FP)(1<<15);
+      break;
+    case SDLK_RIGHT:
+    case SDLK_d:
+      player_turn += (FP)(1<<15);
+      break;
+    case SDLK_UP:
+    case SDLK_w:
+      player_acc += (FP)(1<<15);
+      break;
+    default:
+      break;
+  }
+}
+
+static void handle_keyup(SDLKey key) {
+  switch(key) {
+    case SDLK_LEFT:
+    case SDLK_a:
+      player_turn += (FP)(1<<15);
+      break;
+    case SDLK_RIGHT:
+    case SDLK_d:
+      player_turn -= (FP)(1<<15);
+      break;
+    case SDLK_UP:
+    case SDLK_w:
+      player_acc -= (FP)(1<<15);
+      break;
+    default:
+      break;
+  }
+}
+
+// Global input.
+void handle_input(SDL_Event* event) {
+  switch(event->type) {
+    case SDL_JOYAXISMOTION:
+      handle_joyaxis(event->jaxis.axis, event->jaxis.value);
+      break;
+    case SDL_JOYBUTTONDOWN:
+      handle_joybutton(event->jbutton.button);
+      break;
+    case SDL_KEYDOWN:
+      handle_keydown(event->key.keysym.sym);
+      break;
+    case SDL_KEYUP:
+      handle_keyup(event->key.keysym.sym);
+      break;
+  }
+}
+
diff --git a/src/player.h b/src/player.h
index fe98097..4ed69d7 100644
--- a/src/player.h
+++ b/src/player.h
@@ -1,5 +1,7 @@
 #pragma once
+#include <SDL.h>
 
+// Flags.
 #define PLAYER_FLAG_NULL      (1<<0)
 #define PLAYER_FLAG_MOV_LEFT  (1<<1)
 #define PLAYER_FLAG_MOV_RIGHT (1<<2)
@@ -9,3 +11,6 @@ int player_isFlag(unsigned int flag);
 void player_setFlag(unsigned int flag);
 void player_rmFlag(unsigned int flag);
 
+// Input.
+void handle_input(SDL_Event* event);
+
diff --git a/src/rng.c b/src/rng.c
new file mode 100644
index 0000000..528ab0a
--- /dev/null
+++ b/src/rng.c
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include <SDL.h>
+#include "rng.h"
+
+void rng_init(void) {
+  srand(getpid() + SDL_GetTicks());
+}
+
diff --git a/src/rng.h b/src/rng.h
new file mode 100644
index 0000000..308350f
--- /dev/null
+++ b/src/rng.h
@@ -0,0 +1,7 @@
+#pragma once
+#include <stdlib.h>
+
+#define RNG(L,H) rand()%(H-L_1)+L
+
+void rng_init(void);
+