- moved tilemanager into its own class
authorIngo Ruhnke <grumbel@gmx.de>
Mon, 14 Jun 2004 22:45:24 +0000 (22:45 +0000)
committerIngo Ruhnke <grumbel@gmx.de>
Mon, 14 Jun 2004 22:45:24 +0000 (22:45 +0000)
- renamed texture.h to surface.h

SVN-Revision: 1490

32 files changed:
src/Makefile.am
src/background.h
src/badguy.h
src/button.h
src/gameobjs.cpp
src/gameobjs.h
src/high_scores.cpp
src/level.h
src/leveleditor.cpp
src/leveleditor.h
src/menu.h
src/mousecursor.h
src/particlesystem.h
src/player.h
src/scene.h
src/screen/drawing_context.cpp
src/screen/font.h
src/screen/screen.h
src/screen/surface.cpp [new file with mode: 0644]
src/screen/surface.h [new file with mode: 0644]
src/sector.cpp
src/setup.cpp
src/special.h
src/sprite.h
src/supertux.cpp
src/tile.cpp
src/tile.h
src/tile_manager.cpp [new file with mode: 0644]
src/tile_manager.h [new file with mode: 0644]
src/tilemap.cpp
src/title.cpp
src/worldmap.cpp

index 3cff78b..6fc28fd 100644 (file)
@@ -11,8 +11,8 @@ screen/font.h \
 screen/font.cpp \
 screen/screen.h \
 screen/screen.cpp \
-screen/texture.cpp \
-screen/texture.h \
+screen/surface.cpp \
+screen/surface.h \
 lispwriter.h \
 lispwriter.cpp \
 badguy.cpp \
@@ -85,6 +85,8 @@ worldmap.cpp \
 worldmap.h \
 tile.h \
 tile.cpp \
+tile_manager.h \
+tile_manager.cpp \
 resources.h \
 resources.cpp \
 gameobjs.h \
index 91df5ae..bafb77c 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef SUPERTUX_BACKGROUND_H
 #define SUPERTUX_BACKGROUND_H
 
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "screen/drawing_context.h"
 #include "game_object.h"
 #include "lispreader.h"
index b9c2d12..6e53ec9 100644 (file)
@@ -26,7 +26,7 @@
 #include "SDL.h"
 
 #include "timer.h"
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "physic.h"
 #include "sprite.h"
 #include "defines.h"
index 1290ff1..a42254e 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <vector>
 
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "timer.h"
 
 enum ButtonState {
index cd9d1c0..674c89a 100644 (file)
@@ -23,7 +23,9 @@
 #include <iostream>
 #include <cmath>
 
+#include "globals.h"
 #include "tile.h"
+#include "tile_manager.h"
 #include "gameloop.h"
 #include "gameobjs.h"
 #include "sprite_manager.h"
index 16106b4..c19a724 100644 (file)
@@ -23,7 +23,7 @@
 #define SUPERTUX_GAMEOBJS_H
 
 #include "type.h"
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "timer.h"
 #include "scene.h"
 #include "physic.h"
index db3cbfe..ae49086 100644 (file)
@@ -28,7 +28,7 @@
 #include "menu.h"
 #include "screen/drawing_context.h"
 #include "screen/screen.h"
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "setup.h"
 #include "lispreader.h"
 
index 091d9b2..e9bb6f0 100644 (file)
@@ -24,7 +24,7 @@
 #include <map>
 #include <string>
 
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "lispreader.h"
 #include "musicref.h"
 
index 71135d0..6b1b9aa 100644 (file)
@@ -44,6 +44,7 @@
 #include "player.h"
 #include "scene.h"
 #include "tile.h"
+#include "tile_manager.h"
 #include "resources.h"
 #include "background.h"
 #include "camera.h"
index 6598994..4ded83f 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "screen/drawing_context.h"
 #include "game_object.h"
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "level.h"
 #include "button.h"
 #include "menu.h"
index eb596dd..a3b99e0 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "SDL.h"
 
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "timer.h"
 #include "type.h"
 #include "mousecursor.h"
index cd86977..a35b96c 100644 (file)
@@ -23,7 +23,7 @@
 #include <string>
 
 #include "timer.h"
-#include "screen/texture.h"
+#include "screen/surface.h"
 
 #define MC_FRAME_PERIOD 800  // in ms
 
index e27930e..80b3e73 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <vector>
 
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "game_object.h"
 #include "serializable.h"
 
index 0d17af3..2d06465 100644 (file)
@@ -25,7 +25,7 @@
 #include "bitmask.h"
 #include "type.h"
 #include "timer.h"
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "collision.h"
 #include "sound.h"
 #include "moving_object.h"
index 7527198..57745d2 100644 (file)
@@ -20,7 +20,7 @@
 #ifndef SUPERTUX_SCENE_H
 #define SUPERTUX_SCENE_H
 
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "timer.h"
 
 #define FRAME_RATE 10 // 100 Frames per second (10ms)
index 13d260d..9a22274 100644 (file)
@@ -21,7 +21,7 @@
 #include <iostream>
 
 #include "drawing_context.h"
-#include "texture.h"
+#include "surface.h"
 #include "globals.h"
 #include "font.h"
 
index 5b44f6e..f3f31cd 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <string>
 
-#include "texture.h"
+#include "surface.h"
 #include "vector.h"
 
 void display_text_file(const std::string& file, const std::string& surface, float scroll_speed);
index 2383573..7932391 100644 (file)
@@ -49,7 +49,7 @@ public:
   Uint8 red, green, blue, alpha;
 };
 
-#include "texture.h"
+#include "surface.h"
 
 class Vector;
 
diff --git a/src/screen/surface.cpp b/src/screen/surface.cpp
new file mode 100644 (file)
index 0000000..0353b3d
--- /dev/null
@@ -0,0 +1,874 @@
+//  $Id$
+//
+//  SuperTux
+//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
+//
+//  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 2
+//  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, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+//  02111-1307, USA.
+
+#include <cassert>
+#include <iostream>
+#include <algorithm>
+
+#include "SDL.h"
+#include "SDL_image.h"
+
+#include "surface.h"
+#include "globals.h"
+#include "setup.h"
+
+Surface::Surfaces Surface::surfaces;
+
+SurfaceData::SurfaceData(SDL_Surface* temp, int use_alpha_)
+    : type(SURFACE), surface(0), use_alpha(use_alpha_)
+{
+  // Copy the given surface and make sure that it is not stored in
+  // video memory
+  surface = SDL_CreateRGBSurface(temp->flags & (~SDL_HWSURFACE),
+                                 temp->w, temp->h,
+                                 temp->format->BitsPerPixel,
+                                 temp->format->Rmask,
+                                 temp->format->Gmask,
+                                 temp->format->Bmask,
+                                 temp->format->Amask);
+  if(!surface)
+    st_abort("No memory left.", "");
+  SDL_SetAlpha(temp,0,0);
+  SDL_BlitSurface(temp, NULL, surface, NULL);
+}
+
+SurfaceData::SurfaceData(const std::string& file_, int use_alpha_)
+    : type(LOAD), surface(0), file(file_), use_alpha(use_alpha_)
+{}
+
+SurfaceData::SurfaceData(const std::string& file_, int x_, int y_, int w_, int h_, int use_alpha_)
+    : type(LOAD_PART), surface(0), file(file_), use_alpha(use_alpha_),
+    x(x_), y(y_), w(w_), h(h_)
+{}
+
+SurfaceData::SurfaceData(Color top_gradient_, Color bottom_gradient_, int w_, int h_)
+    : type(GRADIENT), surface(0), use_alpha(false), w(w_), h(h_)
+{
+top_gradient = top_gradient_;
+bottom_gradient = bottom_gradient_;
+}
+
+
+SurfaceData::~SurfaceData()
+{
+  SDL_FreeSurface(surface);
+}
+
+SurfaceImpl*
+SurfaceData::create()
+{
+#ifndef NOOPENGL
+  if (use_gl)
+    return create_SurfaceOpenGL();
+  else
+    return create_SurfaceSDL();
+#else
+  return create_SurfaceSDL();
+#endif
+}
+
+SurfaceSDL*
+SurfaceData::create_SurfaceSDL()
+{
+  switch(type)
+  {
+  case LOAD:
+    return new SurfaceSDL(file, use_alpha);
+  case LOAD_PART:
+    return new SurfaceSDL(file, x, y, w, h, use_alpha);
+  case SURFACE:
+    return new SurfaceSDL(surface, use_alpha);
+  case GRADIENT:
+    return new SurfaceSDL(top_gradient, bottom_gradient, w, h);
+  }
+  assert(0);
+}
+
+SurfaceOpenGL*
+SurfaceData::create_SurfaceOpenGL()
+{
+#ifndef NOOPENGL
+  switch(type)
+  {
+  case LOAD:
+    return new SurfaceOpenGL(file, use_alpha);
+  case LOAD_PART:
+    return new SurfaceOpenGL(file, x, y, w, h, use_alpha);
+  case SURFACE:
+    return new SurfaceOpenGL(surface, use_alpha);
+  case GRADIENT:
+    return new SurfaceOpenGL(top_gradient, bottom_gradient, w, h);
+  }
+#endif
+  assert(0);
+}
+
+#ifndef NOOPENGL
+/* Quick utility function for texture creation */
+static int power_of_two(int input)
+{
+  int value = 1;
+
+  while ( value < input )
+  {
+    value <<= 1;
+  }
+  return value;
+}
+#endif
+
+Surface::Surface(SDL_Surface* surf, int use_alpha)
+    : data(surf, use_alpha), w(0), h(0)
+{
+  impl = data.create();
+  if (impl)
+  {
+    w = impl->w;
+    h = impl->h;
+  }
+  surfaces.push_back(this);
+}
+
+Surface::Surface(const std::string& file, int use_alpha)
+    : data(file, use_alpha), w(0), h(0)
+{
+  impl = data.create();
+  if (impl)
+  {
+    w = impl->w;
+    h = impl->h;
+  }
+  surfaces.push_back(this);
+}
+
+Surface::Surface(const std::string& file, int x, int y, int w, int h, int use_alpha)
+    : data(file, x, y, w, h, use_alpha), w(0), h(0)
+{
+  impl = data.create();
+  if (impl)
+  {
+    w = impl->w;
+    h = impl->h;
+  }
+  surfaces.push_back(this);
+}
+
+Surface::Surface(Color top_background, Color bottom_background, int w, int h)
+    : data(top_background, bottom_background, w, h), w(0), h(0)
+{
+  impl = data.create();
+  if (impl)
+  {
+    w = impl->w;
+    h = impl->h;
+  }
+  surfaces.push_back(this);
+}
+
+void
+Surface::reload()
+{
+  delete impl;
+  impl = data.create();
+  if (impl)
+  {
+    w = impl->w;
+    h = impl->h;
+  }
+}
+
+Surface::~Surface()
+{
+#ifdef DEBUG
+  bool found = false;
+  for(std::list<Surface*>::iterator i = surfaces.begin(); i != surfaces.end();
+      ++i)
+  {
+    if(*i == this)
+    {
+      found = true; break;
+    }
+  }
+  if(!found)
+    printf("Error: Surface freed twice!!!\n");
+#endif
+  surfaces.remove(this);
+  delete impl;
+}
+
+void
+Surface::reload_all()
+{
+  for(Surfaces::iterator i = surfaces.begin(); i != surfaces.end(); ++i)
+  {
+    (*i)->reload();
+  }
+}
+
+void
+Surface::debug_check()
+{
+  for(Surfaces::iterator i = surfaces.begin(); i != surfaces.end(); ++i)
+  {
+    printf("Surface not freed: T:%d F:%s.\n", (*i)->data.type,
+           (*i)->data.file.c_str());
+  }
+}
+
+void
+Surface::resize(int w_, int h_)
+{
+  if (impl)
+  {
+    w = w_;
+    h = h_;
+    if (impl->resize(w_,h_) == -2)
+      reload();
+  }
+}
+
+SDL_Surface*
+sdl_surface_part_from_file(const std::string& file, int x, int y, int w, int h,  int use_alpha)
+{
+  SDL_Rect src;
+  SDL_Surface * sdl_surface;
+  SDL_Surface * temp;
+  SDL_Surface * conv;
+
+  temp = IMG_Load(file.c_str());
+
+  if (temp == NULL)
+    st_abort("Can't load", file);
+
+  /* Set source rectangle for conv: */
+
+  src.x = x;
+  src.y = y;
+  src.w = w;
+  src.h = h;
+
+  conv = SDL_CreateRGBSurface(temp->flags, w, h, temp->format->BitsPerPixel,
+                              temp->format->Rmask,
+                              temp->format->Gmask,
+                              temp->format->Bmask,
+                              temp->format->Amask);
+
+  /* #if SDL_BYTEORDER == SDL_BIG_ENDIAN
+     0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
+     #else
+
+     0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
+     #endif*/
+
+  SDL_SetAlpha(temp,0,0);
+
+  SDL_BlitSurface(temp, &src, conv, NULL);
+  if(use_alpha == IGNORE_ALPHA && !use_gl)
+    sdl_surface = SDL_DisplayFormat(conv);
+  else
+    sdl_surface = SDL_DisplayFormatAlpha(conv);
+
+  if (sdl_surface == NULL)
+    st_abort("Can't covert to display format", file);
+
+  if (use_alpha == IGNORE_ALPHA && !use_gl)
+    SDL_SetAlpha(sdl_surface, 0, 0);
+
+  SDL_FreeSurface(temp);
+  SDL_FreeSurface(conv);
+
+  return sdl_surface;
+}
+
+SDL_Surface*
+sdl_surface_from_file(const std::string& file, int use_alpha)
+{
+  SDL_Surface* sdl_surface;
+  SDL_Surface* temp;
+
+  temp = IMG_Load(file.c_str());
+
+  if (temp == NULL)
+    st_abort("Can't load", file);
+
+  if(use_alpha == IGNORE_ALPHA && !use_gl)
+    sdl_surface = SDL_DisplayFormat(temp);
+  else
+    sdl_surface = SDL_DisplayFormatAlpha(temp);
+
+  if (sdl_surface == NULL)
+    st_abort("Can't covert to display format", file);
+
+  if (use_alpha == IGNORE_ALPHA && !use_gl)
+    SDL_SetAlpha(sdl_surface, 0, 0);
+
+  SDL_FreeSurface(temp);
+
+  return sdl_surface;
+}
+
+SDL_Surface*
+sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf, int use_alpha)
+{
+  SDL_Surface* sdl_surface;
+  Uint32 saved_flags;
+  Uint8  saved_alpha;
+
+  /* Save the alpha blending attributes */
+  saved_flags = sdl_surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
+  saved_alpha = sdl_surf->format->alpha;
+  if ( (saved_flags & SDL_SRCALPHA)
+       == SDL_SRCALPHA )
+  {
+    SDL_SetAlpha(sdl_surf, 0, 0);
+  }
+
+  if(use_alpha == IGNORE_ALPHA && !use_gl)
+    sdl_surface = SDL_DisplayFormat(sdl_surf);
+  else
+    sdl_surface = SDL_DisplayFormatAlpha(sdl_surf);
+
+  /* Restore the alpha blending attributes */
+  if ( (saved_flags & SDL_SRCALPHA)
+       == SDL_SRCALPHA )
+  {
+    SDL_SetAlpha(sdl_surface, saved_flags, saved_alpha);
+  }
+
+  if (sdl_surface == NULL)
+    st_abort("Can't covert to display format", "SURFACE");
+
+  if (use_alpha == IGNORE_ALPHA && !use_gl)
+    SDL_SetAlpha(sdl_surface, 0, 0);
+
+  return sdl_surface;
+}
+
+SDL_Surface*
+sdl_surface_from_gradient(Color top, Color bottom, int w, int h)
+{
+  SDL_Surface* sdl_surface;
+
+  sdl_surface = SDL_CreateRGBSurface(screen->flags, w, h,
+                    screen->format->BitsPerPixel, screen->format->Rmask,
+                    screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
+
+  if(sdl_surface == NULL)
+      st_abort("Cannot create surface for the gradient", "SURFACE");
+
+  if(top == bottom)
+    {
+    SDL_FillRect(sdl_surface, NULL, SDL_MapRGB(sdl_surface->format,
+        top.red, top.green, top.blue));
+    }
+  else
+    {
+    float redstep = (float(bottom.red)-float(top.red)) / float(h);
+    float greenstep = (float(bottom.green)-float(top.green)) / float(h);
+    float bluestep = (float(bottom.blue) - float(top.blue)) / float(h);
+
+    SDL_Rect rect;
+    rect.x = 0;
+    rect.w = w;
+    rect.h = 1;
+    for(float y = 0; y < h; y++)
+      {
+      rect.y = (int)y;
+      SDL_FillRect(sdl_surface, &rect, SDL_MapRGB(sdl_surface->format,
+          int(float(top.red) + redstep * y),
+          int(float(top.green) + greenstep * y),
+          int(float(top.blue) + bluestep * y)));
+      }
+    }
+
+  return sdl_surface;
+}
+
+//---------------------------------------------------------------------------
+
+SurfaceImpl::SurfaceImpl()
+{}
+
+SurfaceImpl::~SurfaceImpl()
+{
+  SDL_FreeSurface(sdl_surface);
+}
+
+SDL_Surface* SurfaceImpl::get_sdl_surface() const
+{
+  return sdl_surface;
+}
+
+int SurfaceImpl::resize(int w_, int h_)
+{
+  w = w_;
+  h = h_;
+  SDL_Rect dest;
+  dest.x = 0;
+  dest.y = 0;
+  dest.w = w;
+  dest.h = h;
+  int ret = SDL_SoftStretch(sdl_surface, NULL,
+                            sdl_surface, &dest);
+  return ret;
+}
+
+#ifndef NOOPENGL
+SurfaceOpenGL::SurfaceOpenGL(SDL_Surface* surf, int use_alpha)
+{
+  sdl_surface = sdl_surface_from_sdl_surface(surf, use_alpha);
+  create_gl(sdl_surface,&gl_texture);
+
+  w = sdl_surface->w;
+  h = sdl_surface->h;
+}
+
+SurfaceOpenGL::SurfaceOpenGL(const std::string& file, int use_alpha)
+{
+  sdl_surface = sdl_surface_from_file(file, use_alpha);
+  create_gl(sdl_surface,&gl_texture);
+
+  w = sdl_surface->w;
+  h = sdl_surface->h;
+}
+
+SurfaceOpenGL::SurfaceOpenGL(const std::string& file_, int x_, int y_, int w_, int h_, int use_alpha_)
+{
+  sdl_surface = sdl_surface_part_from_file(file_,x_,y_,w_,h_,use_alpha_);
+  
+  create_gl(sdl_surface, &gl_texture);
+
+  w = sdl_surface->w;
+  h = sdl_surface->h;
+}
+
+SurfaceOpenGL::SurfaceOpenGL(Color top_gradient, Color bottom_gradient, int w, int h)
+{
+  sdl_surface = sdl_surface_from_gradient(top_gradient, bottom_gradient, w, h);
+  create_gl(sdl_surface, &gl_texture);
+
+  w = sdl_surface->w;
+  h = sdl_surface->h;
+}
+
+SurfaceOpenGL::~SurfaceOpenGL()
+{
+  glDeleteTextures(1, &gl_texture);
+}
+
+void
+SurfaceOpenGL::create_gl(SDL_Surface * surf, GLuint * tex)
+{
+  Uint32 saved_flags;
+  Uint8  saved_alpha;
+  int w, h;
+  SDL_Surface *conv;
+
+  w = power_of_two(surf->w);
+  h = power_of_two(surf->h),
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+      conv = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surf->format->BitsPerPixel,
+                                  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
+#else
+      conv = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surf->format->BitsPerPixel,
+                                  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
+#endif
+
+  /* Save the alpha blending attributes */
+  saved_flags = surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
+  saved_alpha = surf->format->alpha;
+  if ( (saved_flags & SDL_SRCALPHA)
+       == SDL_SRCALPHA )
+  {
+    SDL_SetAlpha(surf, 0, 0);
+  }
+
+  SDL_BlitSurface(surf, 0, conv, 0);
+
+  /* Restore the alpha blending attributes */
+  if ( (saved_flags & SDL_SRCALPHA)
+       == SDL_SRCALPHA )
+  {
+    SDL_SetAlpha(surf, saved_flags, saved_alpha);
+  }
+
+  // We check all the pixels of the surface to figure out which
+  // internal format OpenGL should use for storing it, ie. if no alpha
+  // is present store in RGB instead of RGBA, this saves a few bytes
+  // of memory, but much more importantly it makes the game look
+  // *much* better in 16bit color mode
+  int internal_format = GL_RGB10_A2;
+  bool has_alpha = false;
+
+  unsigned char* buf = static_cast<unsigned char*>(conv->pixels);
+  for (int y = 0; y < surf->h; ++y)
+    for (int x = 0; x < surf->w; ++x)
+      {
+        if (buf[(conv->pitch*y + x*4) + 3] != 255)
+          {
+            has_alpha = true;
+            break;
+          }
+      }
+
+  if (!has_alpha)
+    {
+      internal_format = GL_RGB;
+    }
+
+  glGenTextures(1, &*tex);
+  glBindTexture(GL_TEXTURE_2D , *tex);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, conv->pitch / conv->format->BytesPerPixel);
+  glTexImage2D(GL_TEXTURE_2D, 0, internal_format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, conv->pixels);
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+
+  SDL_FreeSurface(conv);
+}
+
+int
+SurfaceOpenGL::draw(float x, float y, Uint8 alpha, Uint32 effect)
+{
+  float pw = power_of_two(w);
+  float ph = power_of_two(h);
+
+  if(effect & SEMI_TRANSPARENT)
+    alpha = 128;
+
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  glColor4ub(alpha, alpha, alpha, alpha);
+
+  glBindTexture(GL_TEXTURE_2D, gl_texture);
+
+  glBegin(GL_QUADS);
+
+  if(effect & VERTICAL_FLIP)
+    {
+    glTexCoord2f(0, 0);
+    glVertex2f(x, (float)h+y);
+
+    glTexCoord2f((float)w / pw, 0);
+    glVertex2f((float)w+x, (float)h+y);
+
+    glTexCoord2f((float)w / pw, (float)h / ph);
+    glVertex2f((float)w+x, y);
+    
+    glTexCoord2f(0, (float)h / ph);
+    glVertex2f(x, y);
+    }
+  else
+    {
+    glTexCoord2f(0, 0);
+    glVertex2f(x, y);
+
+    glTexCoord2f((float)w / pw, 0);
+    glVertex2f((float)w+x, y);
+
+    glTexCoord2f((float)w / pw, (float)h / ph);
+    glVertex2f((float)w+x, (float)h+y);
+
+    glTexCoord2f(0, (float)h / ph);
+    glVertex2f(x, (float)h+y);
+    }
+  glEnd();
+
+  glDisable(GL_TEXTURE_2D);
+  glDisable(GL_BLEND);
+
+  return 0;
+}
+
+int
+SurfaceOpenGL::draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, Uint32 effect)
+{
+  float pw = power_of_two(int(this->w));
+  float ph = power_of_two(int(this->h));
+
+  if(effect & SEMI_TRANSPARENT)
+    alpha = 128;
+
+  glBindTexture(GL_TEXTURE_2D, gl_texture);
+
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  glColor4ub(alpha, alpha, alpha, alpha);
+
+  glEnable(GL_TEXTURE_2D);
+
+
+  glBegin(GL_QUADS);
+
+  if(effect & VERTICAL_FLIP)
+    {
+    glTexCoord2f(sx / pw, sy / ph);
+    glVertex2f(x, y);
+
+    glTexCoord2f((float)(sx + w) / pw, sy / ph);
+    glVertex2f(w+x, y);
+
+    glTexCoord2f((sx+w) / pw, (sy+h) / ph);
+    glVertex2f(w +x, h+y);
+
+    glTexCoord2f(sx / pw, (float)(sy+h) / ph);
+    glVertex2f(x, h+y);
+    }
+  else
+    {
+    glTexCoord2f(sx / pw, (float)(sy+h) / ph);
+    glVertex2f(x, h+y);
+
+    glTexCoord2f((sx+w) / pw, (sy+h) / ph);
+    glVertex2f(w +x, h+y);
+
+    glTexCoord2f((float)(sx + w) / pw, sy / ph);
+    glVertex2f(w+x, y);
+
+    glTexCoord2f(sx / pw, sy / ph);
+    glVertex2f(x, y);
+    }
+
+  glEnd();
+
+  glDisable(GL_TEXTURE_2D);
+  glDisable(GL_BLEND);
+
+  return 0;
+}
+
+#if 0
+int
+SurfaceOpenGL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha)
+{
+  float pw = power_of_two(int(this->w));
+  float ph = power_of_two(int(this->h));
+
+  glBindTexture(GL_TEXTURE_2D, gl_texture);
+
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  glColor4ub(alpha, alpha, alpha, alpha);
+
+  glEnable(GL_TEXTURE_2D);
+
+
+  glBegin(GL_QUADS);
+  glTexCoord2f(0, 0);
+  glVertex2f(x, y);
+  glTexCoord2f((float)w / pw, 0);
+  glVertex2f(sw+x, y);
+  glTexCoord2f((float)w / pw, (float)h / ph);  glVertex2f((float)sw+x, (float)sh+y);
+  glVertex2f(sw +x, sh+y);
+  glTexCoord2f(0, (float)h / ph);
+  glVertex2f(x, sh+y);
+  glEnd();
+
+  glDisable(GL_TEXTURE_2D);
+  glDisable(GL_BLEND);
+
+  return 0;
+}
+#endif
+
+#endif
+
+SurfaceSDL::SurfaceSDL(SDL_Surface* surf, int use_alpha)
+{
+  sdl_surface = sdl_surface_from_sdl_surface(surf, use_alpha);
+  w = sdl_surface->w;
+  h = sdl_surface->h;
+}
+
+SurfaceSDL::SurfaceSDL(const std::string& file, int use_alpha)
+{
+  sdl_surface = sdl_surface_from_file(file, use_alpha);
+  w = sdl_surface->w;
+  h = sdl_surface->h;
+}
+
+SurfaceSDL::SurfaceSDL(const std::string& file, int x, int y, int w, int h,  int use_alpha)
+{
+  sdl_surface = sdl_surface_part_from_file(file, x, y, w, h, use_alpha);
+  w = sdl_surface->w;
+  h = sdl_surface->h;
+}
+
+SurfaceSDL::SurfaceSDL(Color top_gradient, Color bottom_gradient, int w, int h)
+{
+  sdl_surface = sdl_surface_from_gradient(top_gradient, bottom_gradient, w, h);
+  w = sdl_surface->w;
+  h = sdl_surface->h;
+}
+
+int
+SurfaceSDL::draw(float x, float y, Uint8 alpha, Uint32 effect)
+{
+  SDL_Rect dest;
+
+  dest.x = (int)x;
+  dest.y = (int)y;
+  dest.w = w;
+  dest.h = h;
+
+  if(effect & SEMI_TRANSPARENT)
+    alpha = 128;
+
+  if(effect & VERTICAL_FLIP)    // FIXME: feel free to replace this hack
+    {
+    for(float sy = 0; sy < h; sy++)
+      if(draw_part(0, sy, x, y+(h-sy), w, 1, alpha, NONE_EFFECT) == -2)
+        return -2;
+    return 0;
+    }
+
+  if(alpha != 255)
+    {
+    /* Create a Surface, make it using colorkey, blit surface into temp, apply alpha
+      to temp sur, blit the temp into the screen */
+    /* Note: this has to be done, since SDL doesn't allow to set alpha to surfaces that
+      already have an alpha mask yet... */
+
+    SDL_Surface* sdl_surface_copy = SDL_CreateRGBSurface (sdl_surface->flags,
+                                    sdl_surface->w, sdl_surface->h, sdl_surface->format->BitsPerPixel,
+                                    sdl_surface->format->Rmask, sdl_surface->format->Gmask,
+                                    sdl_surface->format->Bmask,
+                                    0);
+    int colorkey = SDL_MapRGB(sdl_surface_copy->format, 255, 0, 255);
+    SDL_FillRect(sdl_surface_copy, NULL, colorkey);
+    SDL_SetColorKey(sdl_surface_copy, SDL_SRCCOLORKEY, colorkey);
+
+
+    SDL_BlitSurface(sdl_surface, NULL, sdl_surface_copy, NULL);
+    SDL_SetAlpha(sdl_surface_copy ,SDL_SRCALPHA,alpha);
+
+    int ret = SDL_BlitSurface(sdl_surface_copy, NULL, screen, &dest);
+
+    SDL_FreeSurface (sdl_surface_copy);
+    return ret;
+    }
+
+  int ret = SDL_BlitSurface(sdl_surface, NULL, screen, &dest);
+
+  return ret;
+}
+
+int
+SurfaceSDL::draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, Uint32 effect)
+{
+  SDL_Rect src, dest;
+
+  src.x = (int)sx;
+  src.y = (int)sy;
+  src.w = (int)w;
+  src.h = (int)h;
+
+  dest.x = (int)x;
+  dest.y = (int)y;
+  dest.w = (int)w;
+  dest.h = (int)h;
+
+  if(effect & SEMI_TRANSPARENT)
+    alpha = 128;
+
+  if(effect & VERTICAL_FLIP)    // FIXME: feel free to replace this hack
+    {
+    for(float sy_ = sy; sy_ < h; sy_++)
+      if(draw_part(sx, sy_, x, y+(h-sy_), w, 1, alpha, NONE_EFFECT) == -2)
+        return -2;
+    return 0;
+    }
+
+  if(alpha != 255)
+    {
+    /* Create a Surface, make it using colorkey, blit surface into temp, apply alpha
+      to temp sur, blit the temp into the screen */
+    /* Note: this has to be done, since SDL doesn't allow to set alpha to surfaces that
+      already have an alpha mask yet... */
+
+    SDL_Surface* sdl_surface_copy = SDL_CreateRGBSurface (sdl_surface->flags,
+                                    sdl_surface->w, sdl_surface->h, sdl_surface->format->BitsPerPixel,
+                                    sdl_surface->format->Rmask, sdl_surface->format->Gmask,
+                                    sdl_surface->format->Bmask,
+                                    0);
+    int colorkey = SDL_MapRGB(sdl_surface_copy->format, 255, 0, 255);
+    SDL_FillRect(sdl_surface_copy, NULL, colorkey);
+    SDL_SetColorKey(sdl_surface_copy, SDL_SRCCOLORKEY, colorkey);
+
+
+    SDL_BlitSurface(sdl_surface, NULL, sdl_surface_copy, NULL);
+    SDL_SetAlpha(sdl_surface_copy ,SDL_SRCALPHA,alpha);
+
+    int ret = SDL_BlitSurface(sdl_surface_copy, NULL, screen, &dest);
+
+    SDL_FreeSurface (sdl_surface_copy);
+    return ret;
+    }
+
+  int ret = SDL_BlitSurface(sdl_surface, &src, screen, &dest);
+
+  return ret;
+}
+
+#if 0
+int
+SurfaceSDL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, bool update)
+{
+  SDL_Rect dest;
+
+  dest.x = (int)x;
+  dest.y = (int)y;
+  dest.w = (int)sw;
+  dest.h = (int)sh;
+
+  if(alpha != 255)
+    SDL_SetAlpha(sdl_surface ,SDL_SRCALPHA,alpha);
+
+
+  SDL_Surface* sdl_surface_copy = SDL_CreateRGBSurface (sdl_surface->flags,
+                                  sw, sh, sdl_surface->format->BitsPerPixel,
+                                  sdl_surface->format->Rmask, sdl_surface->format->Gmask,
+                                  sdl_surface->format->Bmask,
+                                  0);
+
+  SDL_BlitSurface(sdl_surface, NULL, sdl_surface_copy, NULL);
+  SDL_SoftStretch(sdl_surface_copy, NULL, sdl_surface_copy, &dest);
+
+  int ret = SDL_BlitSurface(sdl_surface_copy,NULL,screen,&dest);
+  SDL_FreeSurface(sdl_surface_copy);
+
+  if (update == UPDATE)
+    update_rect(screen, dest.x, dest.y, dest.w, dest.h);
+
+  return ret;
+}
+#endif
+
+SurfaceSDL::~SurfaceSDL()
+{}
+
+/* EOF */
diff --git a/src/screen/surface.h b/src/screen/surface.h
new file mode 100644 (file)
index 0000000..6fe26e3
--- /dev/null
@@ -0,0 +1,180 @@
+//  $Id$
+// 
+//  SuperTux
+//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
+//
+//  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 2
+//  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, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+//  02111-1307, USA.
+
+#ifndef SUPERTUX_TEXTURE_H
+#define SUPERTUX_TEXTURE_H
+
+#include <string>
+#include <list>
+
+#ifndef NOOPENGL
+#include "SDL_opengl.h"
+#endif
+
+#include "SDL.h"
+
+#include "screen.h"
+#include "vector.h"
+
+SDL_Surface* sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf, int use_alpha);
+SDL_Surface* sdl_surface_from_nothing();
+
+class SurfaceImpl;
+class SurfaceSDL;
+class SurfaceOpenGL;
+class DrawingContext;
+
+/// bitset for drawing effects
+enum {
+      /** Don't apply anything */
+      NONE_EFFECT       = 0x0000,
+      /** Draw the Surface upside down */
+      VERTICAL_FLIP     = 0x0001,
+      /** Draw the Surface with alpha equal to 128 */
+      SEMI_TRANSPARENT  = 0x0002
+  };
+
+/** This class holds all the data necessary to construct a surface */
+class SurfaceData 
+{
+public:
+  enum ConstructorType { LOAD, LOAD_PART, SURFACE, GRADIENT };
+  ConstructorType type;
+  SDL_Surface* surface;
+  std::string file;
+  int use_alpha;
+  int x;
+  int y;
+  int w;
+  int h;
+  Color top_gradient;
+  Color bottom_gradient;
+
+  SurfaceData(SDL_Surface* surf, int use_alpha_);
+  SurfaceData(const std::string& file_, int use_alpha_);
+  SurfaceData(const std::string& file_, int x_, int y_, int w_, int h_, int use_alpha_);
+  SurfaceData(Color top_gradient_, Color bottom_gradient_, int w_, int h_);
+  ~SurfaceData();
+
+  SurfaceSDL* create_SurfaceSDL();
+  SurfaceOpenGL* create_SurfaceOpenGL();
+  SurfaceImpl* create();
+};
+
+/** Container class that holds a surface, necessary so that we can
+    switch Surface implementations (OpenGL, SDL) on the fly */
+class Surface
+{
+public:
+  SurfaceData data;
+  SurfaceImpl* impl;
+  int w; 
+  int h;
+  
+  typedef std::list<Surface*> Surfaces;
+  static Surfaces surfaces;
+public:
+  static void reload_all();
+  static void debug_check();
+
+  Surface(SDL_Surface* surf, int use_alpha);  
+  Surface(const std::string& file, int use_alpha);  
+  Surface(const std::string& file, int x, int y, int w, int h, int use_alpha);
+  Surface(Color top_gradient, Color bottom_gradient, int w, int h);
+  ~Surface();
+  
+  /** Reload the surface, which is necesarry in case of a mode swich */
+  void reload();
+
+  void resize(int widht, int height);
+};
+
+/** Surface implementation, all implementation have to inherit from
+    this class */
+class SurfaceImpl
+{
+protected:
+  SDL_Surface* sdl_surface;
+
+public:
+  int w;
+  int h;
+
+public:
+  SurfaceImpl();
+  virtual ~SurfaceImpl();
+  
+  /** Return 0 on success, -2 if surface needs to be reloaded */
+  virtual int draw(float x, float y, Uint8 alpha, Uint32 effect = NONE_EFFECT) = 0;
+  virtual int draw_part(float sx, float sy, float x, float y, float w, float h,  Uint8 alpha, Uint32 effect = NONE_EFFECT) = 0;
+#if 0
+  virtual int draw_stretched(float x, float y, int w, int h, Uint8 alpha, bool update) = 0;
+#endif
+  int resize(int w_, int h_);
+
+  SDL_Surface* get_sdl_surface() const; // @evil@ try to avoid this function
+};
+
+class SurfaceSDL : public SurfaceImpl
+{
+public:
+  SurfaceSDL(SDL_Surface* surf, int use_alpha);
+  SurfaceSDL(const std::string& file, int use_alpha);  
+  SurfaceSDL(const std::string& file, int x, int y, int w, int h, int use_alpha);
+  SurfaceSDL(Color top_gradient, Color bottom_gradient, int w, int h);
+  virtual ~SurfaceSDL();
+
+  int draw(float x, float y, Uint8 alpha, Uint32 effect = NONE_EFFECT);
+  int draw_part(float sx, float sy, float x, float y, float w, float h,  Uint8 alpha, Uint32 effect = NONE_EFFECT);
+#if 0
+  int draw_stretched(float x, float y, int w, int h, Uint8 alpha);
+#endif
+};
+
+#ifndef NOOPENGL
+class SurfaceOpenGL : public SurfaceImpl
+{
+public:
+  GLuint gl_texture;
+
+public:
+  SurfaceOpenGL(SDL_Surface* surf, int use_alpha);
+  SurfaceOpenGL(const std::string& file, int use_alpha);  
+  SurfaceOpenGL(const std::string& file, int x, int y, int w, int h, int use_alpha);
+  SurfaceOpenGL(Color top_gradient, Color bottom_gradient, int w, int h);
+
+  virtual ~SurfaceOpenGL();
+
+  int draw(float x, float y, Uint8 alpha, Uint32 effect = NONE_EFFECT);
+  int draw_part(float sx, float sy, float x, float y, float w, float h,  Uint8 alpha, Uint32 effect = NONE_EFFECT);
+#if 0
+  int draw_stretched(float x, float y, int w, int h, Uint8 alpha);
+#endif
+
+private:
+  void create_gl(SDL_Surface * surf, GLuint * tex);
+};
+#endif 
+
+#endif /*SUPERTUX_TEXTURE_H*/
+
+/* Local Variables: */
+/* mode: c++ */
+/* End: */
index dc24cbe..1636118 100644 (file)
@@ -24,6 +24,7 @@
 #include <fstream>
 #include <stdexcept>
 
+#include "globals.h"
 #include "sector.h"
 #include "lispreader.h"
 #include "badguy.h"
index 7654c3f..19ac305 100644 (file)
@@ -45,7 +45,7 @@
 #include "globals.h"
 #include "setup.h"
 #include "screen/screen.h"
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "menu.h"
 #include "gameloop.h"
 #include "configfile.h"
index e4b09c5..cbf33e5 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "bitmask.h"
 #include "type.h"
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "collision.h"
 #include "player.h"
 #include "physic.h"
index 61a6d95..47ab31a 100644 (file)
@@ -24,7 +24,7 @@
 #include <vector>
 
 #include "lispreader.h"
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "vector.h"
 
 class Sprite
index cf5b042..588639a 100644 (file)
@@ -34,8 +34,8 @@
 #include "screen/screen.h"
 #include "worldmap.h"
 #include "resources.h"
-#include "screen/texture.h"
-#include "tile.h"
+#include "screen/surface.h"
+#include "tile_manager.h"
 #include "gettext.h"
 
 int main(int argc, char * argv[])
index 674cf78..bdb82b1 100644 (file)
 #include <cassert>
 #include <iostream>
 
+#include "globals.h"
 #include "tile.h"
 #include "scene.h"
+#include "lispreader.h"
+#include "vector.h"
 #include "screen/drawing_context.h"
 
-TileManager* TileManager::instance_  = 0;
-std::set<TileGroup>* TileManager::tilegroups_  = 0;
-
 Tile::Tile()
   : id(-1), attributes(0), data(0), next_tile(0), anim_speed(25)
 {
@@ -115,129 +115,5 @@ Tile::read(LispReader& reader)
   return id;
 }
 
-//---------------------------------------------------------------------------
-
-TileManager::TileManager()
-{
-  std::string filename = datadir + "/images/tilesets/supertux.stgt";
-  load_tileset(filename);
-}
-
-TileManager::~TileManager()
-{
-  for(std::vector<Tile*>::iterator i = tiles.begin(); i != tiles.end(); ++i) {
-    delete *i;                                                                  
-  }
-
-  delete tilegroups_;
-}
-
-void TileManager::load_tileset(std::string filename)
-{
-  if(filename == current_tileset)
-    return;
-  
-  // free old tiles
-  for(std::vector<Tile*>::iterator i = tiles.begin(); i != tiles.end(); ++i) {
-    delete *i;
-  }
-  tiles.clear();
-  lisp_object_t* root_obj = lisp_read_from_file(filename);
-
-  if (!root_obj)
-    st_abort("Couldn't load file", filename);
-
-  if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-tiles") == 0)
-    {
-      lisp_object_t* cur = lisp_cdr(root_obj);
-      int tileset_id = 0;
-
-      while(!lisp_nil_p(cur))
-        {
-          lisp_object_t* element = lisp_car(cur);
-
-          if (strcmp(lisp_symbol(lisp_car(element)), "tile") == 0)
-            {
-              LispReader reader(lisp_cdr(element));
-
-              Tile* tile = new Tile;
-              int tile_id = tile->read(reader);
-              if(tile_id < 0) {
-                std::cerr 
-                  << "Warning: parse error when reading a tile, skipping.\n";
-                continue;
-              }
-
-              tile_id += tileset_id;
-
-              if(tile_id >= int(tiles.size()))
-                tiles.resize(tile_id+1);
-              tiles[tile_id] = tile;
-            }
-          else if (strcmp(lisp_symbol(lisp_car(element)), "tileset") == 0)
-            {
-              LispReader reader(lisp_cdr(element));
-              std::string filename;
-              reader.read_string("file", filename);
-              filename = datadir + "/images/tilesets/" + filename;
-              load_tileset(filename);
-            }
-          else if (strcmp(lisp_symbol(lisp_car(element)), "tilegroup") == 0)
-            {
-              TileGroup new_;
-              LispReader reader(lisp_cdr(element));
-              reader.read_string("name", new_.name);
-              reader.read_int_vector("tiles", new_.tiles);           
-              if(!tilegroups_)
-                tilegroups_ = new std::set<TileGroup>;
-              tilegroups_->insert(new_).first;
-            }
-          else if (strcmp(lisp_symbol(lisp_car(element)), "properties") == 0)
-            {
-              LispReader reader(lisp_cdr(element));
-              reader.read_int("id", tileset_id);
-              tileset_id *= 1000;
-            }
-          else
-            {
-              std::cerr << "Unknown symbol: " << 
-                lisp_symbol(lisp_car(element)) << "\n";
-            }
-
-          cur = lisp_cdr(cur);
-        }
-    }
-  else
-    {
-      assert(0);
-    }
-
-  lisp_free(root_obj);
-  current_tileset = filename;
-}
-
-void
-TileManager::draw_tile(DrawingContext& context, unsigned int c,
-    const Vector& pos, int layer)
-{
-  if(c == 0)
-    return;
-
-  Tile& tile = get(c);
-
-  if(!tile.images.size())
-    return;
-
-  if(tile.images.size() > 1)
-  {
-    size_t frame 
-      = ((global_frame_counter*25) / tile.anim_speed) % tile.images.size();
-    context.draw_surface(tile.images[frame], pos, layer);
-  }
-  else if (tile.images.size() == 1)
-  {
-    context.draw_surface(tile.images[0], pos, layer);
-  }
-}
+/* EOF */
 
index 80de062..cf809aa 100644 (file)
 #ifndef TILE_H
 #define TILE_H
 
-#include <set>
-#include <map>
 #include <vector>
+#include "SDL.h"
+#include "screen/surface.h"
 
-#include "screen/texture.h"
-#include "globals.h"
-#include "lispreader.h"
-#include "setup.h"
-#include "vector.h"
-
+class Vector;
 class LispReader;
 
 /**
@@ -107,54 +102,6 @@ public:
   }
 };
 
-struct TileGroup
-{
-  friend bool operator<(const TileGroup& lhs, const TileGroup& rhs)
-  { return lhs.name < rhs.name; };
-  friend bool operator>(const TileGroup& lhs, const TileGroup& rhs)
-  { return lhs.name > rhs.name; };
-
-  std::string name;
-  std::vector<int> tiles;
-};
-
-class TileManager
-{
- private:
-  TileManager();
-  ~TileManager();
-  
-  std::vector<Tile*> tiles;
-  static TileManager* instance_ ;
-  static std::set<TileGroup>* tilegroups_;
-  void load_tileset(std::string filename);
-
-  std::string current_tileset;
-  
- public:
-  static TileManager* instance()
-  { return instance_ ? instance_ : instance_ = new TileManager(); }
-  static void destroy_instance()
-  { delete instance_; instance_ = 0; }
-
-  void draw_tile(DrawingContext& context, unsigned int id,
-      const Vector& pos, int layer);
-  
-  static std::set<TileGroup>* tilegroups() { if(!instance_) { instance_ = new TileManager(); } return tilegroups_ ? tilegroups_ : tilegroups_ = new std::set<TileGroup>; }
-  Tile& get(unsigned int id) {
-
-    if(id < tiles.size())
-      {
-        return *tiles[id]; 
-      }
-    else
-      {
-        // Never return 0, but return the 0th tile instead so that
-        // user code doesn't have to check for NULL pointers all over
-        // the place
-        return *tiles[0]; 
-      } 
-  }
-};
-
 #endif
+
+/* EOF */
diff --git a/src/tile_manager.cpp b/src/tile_manager.cpp
new file mode 100644 (file)
index 0000000..f9ad0c2
--- /dev/null
@@ -0,0 +1,156 @@
+//  $Id$
+// 
+//  SuperTux
+//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
+//
+//  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 2
+//  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, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+//  02111-1307, USA.
+
+#include <assert.h>
+#include "screen/drawing_context.h"
+#include "setup.h"
+#include "globals.h"
+#include "lispreader.h"
+#include "tile.h"
+#include "tile_manager.h"
+
+TileManager* TileManager::instance_  = 0;
+std::set<TileGroup>* TileManager::tilegroups_  = 0;
+
+TileManager::TileManager()
+{
+  std::string filename = datadir + "/images/tilesets/supertux.stgt";
+  load_tileset(filename);
+}
+
+TileManager::~TileManager()
+{
+  for(std::vector<Tile*>::iterator i = tiles.begin(); i != tiles.end(); ++i) {
+    delete *i;                                                                  
+  }
+
+  delete tilegroups_;
+}
+
+void TileManager::load_tileset(std::string filename)
+{
+  if(filename == current_tileset)
+    return;
+  
+  // free old tiles
+  for(std::vector<Tile*>::iterator i = tiles.begin(); i != tiles.end(); ++i) {
+    delete *i;
+  }
+  tiles.clear();
+  lisp_object_t* root_obj = lisp_read_from_file(filename);
+
+  if (!root_obj)
+    st_abort("Couldn't load file", filename);
+
+  if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-tiles") == 0)
+    {
+      lisp_object_t* cur = lisp_cdr(root_obj);
+      int tileset_id = 0;
+
+      while(!lisp_nil_p(cur))
+        {
+          lisp_object_t* element = lisp_car(cur);
+
+          if (strcmp(lisp_symbol(lisp_car(element)), "tile") == 0)
+            {
+              LispReader reader(lisp_cdr(element));
+
+              Tile* tile = new Tile;
+              int tile_id = tile->read(reader);
+              if(tile_id < 0) {
+                std::cerr 
+                  << "Warning: parse error when reading a tile, skipping.\n";
+                continue;
+              }
+
+              tile_id += tileset_id;
+
+              if(tile_id >= int(tiles.size()))
+                tiles.resize(tile_id+1);
+              tiles[tile_id] = tile;
+            }
+          else if (strcmp(lisp_symbol(lisp_car(element)), "tileset") == 0)
+            {
+              LispReader reader(lisp_cdr(element));
+              std::string filename;
+              reader.read_string("file", filename);
+              filename = datadir + "/images/tilesets/" + filename;
+              load_tileset(filename);
+            }
+          else if (strcmp(lisp_symbol(lisp_car(element)), "tilegroup") == 0)
+            {
+              TileGroup new_;
+              LispReader reader(lisp_cdr(element));
+              reader.read_string("name", new_.name);
+              reader.read_int_vector("tiles", new_.tiles);           
+              if(!tilegroups_)
+                tilegroups_ = new std::set<TileGroup>;
+              tilegroups_->insert(new_).first;
+            }
+          else if (strcmp(lisp_symbol(lisp_car(element)), "properties") == 0)
+            {
+              LispReader reader(lisp_cdr(element));
+              reader.read_int("id", tileset_id);
+              tileset_id *= 1000;
+            }
+          else
+            {
+              std::cerr << "Unknown symbol: " << 
+                lisp_symbol(lisp_car(element)) << "\n";
+            }
+
+          cur = lisp_cdr(cur);
+        }
+    }
+  else
+    {
+      assert(0);
+    }
+
+  lisp_free(root_obj);
+  current_tileset = filename;
+}
+
+void
+TileManager::draw_tile(DrawingContext& context, unsigned int c,
+    const Vector& pos, int layer)
+{
+  if(c == 0)
+    return;
+
+  Tile& tile = get(c);
+
+  if(!tile.images.size())
+    return;
+
+  if(tile.images.size() > 1)
+  {
+    size_t frame 
+      = ((global_frame_counter*25) / tile.anim_speed) % tile.images.size();
+    context.draw_surface(tile.images[frame], pos, layer);
+  }
+  else if (tile.images.size() == 1)
+  {
+    context.draw_surface(tile.images[0], pos, layer);
+  }
+}
+
+/* EOF */
diff --git a/src/tile_manager.h b/src/tile_manager.h
new file mode 100644 (file)
index 0000000..a55fcb8
--- /dev/null
@@ -0,0 +1,82 @@
+//  $Id$
+// 
+//  SuperTux
+//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
+//
+//  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 2
+//  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, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+//  02111-1307, USA.
+
+#ifndef HEADER_TILE_MANAGER_HXX
+#define HEADER_TILE_MANAGER_HXX
+
+#include <set>
+#include <vector>
+#include <string>
+
+class Tile;
+
+struct TileGroup
+{
+  friend bool operator<(const TileGroup& lhs, const TileGroup& rhs)
+  { return lhs.name < rhs.name; };
+  friend bool operator>(const TileGroup& lhs, const TileGroup& rhs)
+  { return lhs.name > rhs.name; };
+
+  std::string name;
+  std::vector<int> tiles;
+};
+
+class TileManager
+{
+ private:
+  TileManager();
+  ~TileManager();
+  
+  std::vector<Tile*> tiles;
+  static TileManager* instance_ ;
+  static std::set<TileGroup>* tilegroups_;
+  void load_tileset(std::string filename);
+
+  std::string current_tileset;
+  
+ public:
+  static TileManager* instance()
+  { return instance_ ? instance_ : instance_ = new TileManager(); }
+  static void destroy_instance()
+  { delete instance_; instance_ = 0; }
+
+  void draw_tile(DrawingContext& context, unsigned int id,
+      const Vector& pos, int layer);
+  
+  static std::set<TileGroup>* tilegroups() { if(!instance_) { instance_ = new TileManager(); } return tilegroups_ ? tilegroups_ : tilegroups_ = new std::set<TileGroup>; }
+  Tile& get(unsigned int id) {
+
+    if(id < tiles.size())
+      {
+        return *tiles[id]; 
+      }
+    else
+      {
+        // Never return 0, but return the 0th tile instead so that
+        // user code doesn't have to check for NULL pointers all over
+        // the place
+        return *tiles[0]; 
+      } 
+  }
+};
+
+#endif
+
+/* EOF */
index 571a6f3..11ebde4 100644 (file)
@@ -27,6 +27,7 @@
 #include "screen/drawing_context.h"
 #include "level.h"
 #include "tile.h"
+#include "tile_manager.h"
 #include "globals.h"
 #include "lispreader.h"
 #include "lispwriter.h"
index 21ec64e..7d75ef1 100644 (file)
@@ -37,7 +37,7 @@
 #include "globals.h"
 #include "title.h"
 #include "screen/screen.h"
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "high_scores.h"
 #include "menu.h"
 #include "timer.h"
index 373dec2..811274a 100644 (file)
@@ -24,7 +24,7 @@
 #include <unistd.h>
 
 #include "globals.h"
-#include "screen/texture.h"
+#include "screen/surface.h"
 #include "screen/screen.h"
 #include "screen/drawing_context.h"
 #include "lispreader.h"