From: Matthias Braun Date: Sun, 30 May 2004 01:08:50 +0000 (+0000) Subject: -Changed drawing model. Everything is handled through DrawingContext now and X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=03fe5c560a616e7d38a8b1d5d11bfe4675fa8896;p=supertux.git -Changed drawing model. Everything is handled through DrawingContext now and has an additional layer argument. So now you can paint into background/foreground as you like. The DrawingContext will queue app all commands, sort them and execute them in 1 go. SVN-Revision: 1361 --- diff --git a/data/CREDITS b/data/CREDITS index 1160e15b8..17d6a1b09 100644 --- a/data/CREDITS +++ b/data/CREDITS @@ -79,14 +79,14 @@ -Contact Visit our webpage at -http://super-tux.sf.net +*http://super-tux.sf.net Or visit us directly at IRC: -#supertux at irc.freenode.net +*#supertux at irc.freenode.net Comments, ideas and suggestions go to our mailing list -super-tux-devel@lists.sourceforge.net +*super-tux-devel@lists.sourceforge.net diff --git a/src/Makefile.am b/src/Makefile.am index 8c230e72b..bbe31307f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,14 @@ bin_PROGRAMS = supertux supertux_SOURCES = \ +screen/drawing_context.h \ +screen/drawing_context.cpp \ +screen/font.h \ +screen/font.cpp \ +screen/screen.h \ +screen/screen.cpp \ +screen/texture.cpp \ +screen/texture.h \ lispwriter.h \ lispwriter.cpp \ badguy.cpp \ @@ -38,8 +46,6 @@ player.cpp \ player.h \ scene.cpp \ scene.h \ -screen.cpp \ -screen.h \ setup.cpp \ setup.h \ sound.cpp \ @@ -47,10 +53,6 @@ sound.h \ special.cpp \ special.h \ supertux.cpp \ -text.cpp \ -text.h \ -texture.cpp \ -texture.h \ timer.cpp \ timer.h \ title.cpp \ @@ -81,8 +83,6 @@ camera.cpp \ camera.h \ game_object.cpp \ game_object.h \ -display_manager.h \ -display_manager.cpp \ drawable.h \ background.h \ background.cpp \ diff --git a/src/background.cpp b/src/background.cpp index 975bff959..14584e967 100644 --- a/src/background.cpp +++ b/src/background.cpp @@ -20,15 +20,16 @@ #include "globals.h" #include "camera.h" -#include "display_manager.h" +#include "screen/drawing_context.h" -Background::Background(DisplayManager& displaymanager) +Background::Background() + : type(INVALID), image(0) { - displaymanager.add_drawable(this, LAYER_BACKGROUND0); } Background::~Background() { + delete image; } void @@ -37,34 +38,39 @@ Background::action(float) } void -Background::set_image(Surface* image, float speed) +Background::set_image(const std::string& name, float speed) { - bgtype = BACKGROUND_IMAGE; - this->image = image; + type = IMAGE; this->speed = speed; + + delete image; + image = new Surface(datadir + "/images/background/" + name, IGNORE_ALPHA); } void Background::set_gradient(Color top, Color bottom) { - bgtype = BACKGROUND_GRADIENT; + type = GRADIENT; gradient_top = top; gradient_bottom = bottom; } void -Background::draw(Camera& viewport, int ) +Background::draw(DrawingContext& context) { - if(bgtype == BACKGROUND_GRADIENT) { - drawgradient(gradient_top, gradient_bottom); - } else if(bgtype == BACKGROUND_IMAGE) { - int sx = int(-viewport.get_translation().x * float(speed/100.)) + if(type == GRADIENT) { + context.draw_gradient(gradient_top, gradient_bottom, LAYER_BACKGROUND0); + } else if(type == IMAGE) { + int sx = int(-context.get_translation().x * float(speed/100.)) % image->w - image->w; - int sy = int(-viewport.get_translation().y * float(speed/100.)) + int sy = int(-context.get_translation().y * float(speed/100.)) % image->h - image->h; + context.push_transform(); + context.set_translation(Vector(0, 0)); for(int x = sx; x < screen->w; x += image->w) for(int y = sy; y < screen->h; y += image->h) - image->draw(x, y); + context.draw_surface(image, Vector(x, y), LAYER_BACKGROUND0); + context.pop_transform(); } } diff --git a/src/background.h b/src/background.h index 45af0e09e..c441c50d4 100644 --- a/src/background.h +++ b/src/background.h @@ -19,33 +19,32 @@ #ifndef __BACKGROUND_H__ #define __BACKGROUND_H__ -#include "texture.h" +#include "screen/texture.h" +#include "screen/drawing_context.h" #include "game_object.h" -#include "drawable.h" - -enum { - BACKGROUND_GRADIENT, - BACKGROUND_IMAGE -}; class DisplayManager; -class Background : public GameObject, public Drawable +class Background : public GameObject { public: - Background(DisplayManager& displaymanager); + Background(); virtual ~Background(); - void set_image(Surface* image, float bkgd_speed); + void set_image(const std::string& name, float bkgd_speed); void set_gradient(Color top, Color bottom); virtual void action(float elapsed_time); - virtual void draw(Camera& viewport, int layer); + virtual void draw(DrawingContext& context); private: - int bgtype; + enum Type { + INVALID, GRADIENT, IMAGE + }; + + Type type; float speed; Surface* image; Color gradient_top, gradient_bottom; diff --git a/src/badguy.cpp b/src/badguy.cpp index c075dd1ad..87ef1b75a 100644 --- a/src/badguy.cpp +++ b/src/badguy.cpp @@ -26,16 +26,13 @@ #include "globals.h" #include "defines.h" #include "badguy.h" -#include "scene.h" -#include "screen.h" -#include "world.h" #include "tile.h" #include "resources.h" #include "sprite_manager.h" -#include "gameloop.h" -#include "display_manager.h" -#include "lispwriter.h" +#include "world.h" #include "camera.h" +#include "lispwriter.h" +#include "level.h" Sprite* img_mriceblock_flat_left; Sprite* img_mriceblock_flat_right; @@ -158,12 +155,9 @@ std::string badguykind_to_string(BadGuyKind kind) } } -BadGuy::BadGuy(DisplayManager& display_manager, BadGuyKind kind_, - LispReader& lispreader) +BadGuy::BadGuy(BadGuyKind kind_, LispReader& lispreader) : removable(false), squishcount(0) { - display_manager.add_drawable(this, LAYER_OBJECTS); - lispreader.read_float("x", &start_position.x); lispreader.read_float("y", &start_position.y); @@ -175,11 +169,9 @@ BadGuy::BadGuy(DisplayManager& display_manager, BadGuyKind kind_, init(); } -BadGuy::BadGuy(DisplayManager& display_manager, BadGuyKind kind_, - float x, float y) +BadGuy::BadGuy(BadGuyKind kind_, float x, float y) + : removable(false), squishcount(0) { - display_manager.add_drawable(this, LAYER_OBJECTS); - start_position.x = x; start_position.y = y; stay_on_platform = false; @@ -662,8 +654,9 @@ BadGuy::action_fish(double elapsed_time) static const int WAITTIME = 1000; // go in wait mode when back in water - if(dying == DYING_NOT && gettile(base.x, base.y+ base.height)->water - && physic.get_velocity_y() <= 0 && mode == NORMAL) + if(dying == DYING_NOT + && gettile(base.x, base.y+ base.height)->attributes & Tile::WATER + && physic.get_velocity_y() <= 0 && mode == NORMAL) { mode = FISH_WAIT; set_sprite(0, 0); @@ -866,7 +859,6 @@ BadGuy::action_walkingtree(double elapsed_time) remove_me(); } - void BadGuy::action(float elapsed_time) { @@ -981,27 +973,24 @@ BadGuy::action(float elapsed_time) } void -BadGuy::draw(Camera& viewport, int) +BadGuy::draw(DrawingContext& context) { - float scroll_x = viewport.get_translation().x; - float scroll_y = viewport.get_translation().y; - - // Don't try to draw stuff that is outside of the screen - if(base.x <= scroll_x - base.width || base.x >= scroll_x + screen->w) + Sprite* sprite = (dir == LEFT) ? sprite_left : sprite_right; + if(sprite == 0) return; - - if(sprite_left == 0 || sprite_right == 0) - { - return; - } + sprite->draw(context, Vector(base.x, base.y), LAYER_OBJECTS); +#if 0 Sprite* sprite = (dir == LEFT) ? sprite_left : sprite_right; if(dying == DYING_FALLING && physic.get_velocity_y() < 0) sprite->draw(viewport.world2screen(Vector(base.x, base.y)), SD_VERTICAL_FLIP); else sprite->draw(viewport.world2screen(Vector(base.x, base.y))); +#endif - if (debug_mode) + float scroll_x = context.get_translation().x; + float scroll_y = context.get_translation().y; + if(debug_mode) fillrect(base.x - scroll_x, base.y - scroll_y, base.width, base.height, 75,0,75, 150); } diff --git a/src/badguy.h b/src/badguy.h index f5cd806d9..d1a6b843d 100644 --- a/src/badguy.h +++ b/src/badguy.h @@ -24,16 +24,12 @@ #define SUPERTUX_BADGUY_H #include "SDL.h" -#include "defines.h" -#include "bitmask.h" -#include "type.h" #include "timer.h" -#include "texture.h" +#include "screen/texture.h" #include "physic.h" -#include "collision.h" #include "sprite.h" #include "moving_object.h" -#include "drawable.h" +#include "collision.h" #include "serializable.h" /* Bad guy kinds: */ @@ -62,7 +58,7 @@ void free_badguy_gfx(); class Player; /* Badguy type: */ -class BadGuy : public MovingObject, public Drawable, public Serializable +class BadGuy : public MovingObject, public Serializable { public: /* Enemy modes: */ @@ -118,14 +114,14 @@ private: int animation_offset; public: - BadGuy(DisplayManager& display_manager, BadGuyKind kind, float x, float y); - BadGuy(DisplayManager& display_manager, BadGuyKind kind, LispReader& reader); + BadGuy(BadGuyKind kind, float x, float y); + BadGuy(BadGuyKind kind, LispReader& reader); virtual ~BadGuy(); virtual void write(LispWriter& writer); virtual void action(float frame_ratio); - virtual void draw(Camera& viewport, int layer); + virtual void draw(DrawingContext& context); virtual void collision(const MovingObject& other, int type); void collision(void* p_c_object, int c_object, diff --git a/src/button.cpp b/src/button.cpp index 3c1d08327..15b2be10b 100644 --- a/src/button.cpp +++ b/src/button.cpp @@ -21,19 +21,45 @@ #include #include #include "setup.h" -#include "screen.h" +#include "screen/screen.h" #include "globals.h" #include "button.h" #include "camera.h" +// TODO +#if 0 + Timer Button::popup_timer; -Button::Button(std::string icon_file, std::string ninfo, SDLKey nshortcut, int x, int y, int mw, int mh) +Button::Button(Surface* button_image, const std::string& ninfo, + SDLKey nshortcut, int x, int y, int mw, int mh) { popup_timer.init(false); - add_icon(icon_file,mw,mh); + if(button_image) + icon.push_back(button_image); + + info = ninfo; + + shortcut = nshortcut; + + rect.x = x; + rect.y = y; + rect.w = icon[0]->w; + rect.h = icon[0]->h; + tag = -1; + state = BUTTON_NONE; + show_info = false; + drawable = NULL; +} + +Button::Button(const std::string& imagefilename, const std::string& ninfo, + SDLKey nshortcut, int x, int y, int mw, int mh) +{ + popup_timer.init(false); + add_icon(imagefilename, mw, mh); + info = ninfo; shortcut = nshortcut; @@ -48,7 +74,7 @@ Button::Button(std::string icon_file, std::string ninfo, SDLKey nshortcut, int x drawable = NULL; } -void Button::add_icon(std::string icon_file, int mw, int mh) +void Button::add_icon(const std::string& icon_file, int mw, int mh) { char filename[1024]; @@ -300,5 +326,6 @@ void ButtonPanel::highlight_last(bool b) { hlast = b; } +#endif diff --git a/src/button.h b/src/button.h index 950e898d5..28b777411 100644 --- a/src/button.h +++ b/src/button.h @@ -22,8 +22,10 @@ #define SUPERTUX_BUTTON_H #include -#include "texture.h" -#include "drawable.h" +#include "screen/texture.h" + +// TODO +#if 0 enum ButtonState { BUTTON_NONE = -1, @@ -42,13 +44,17 @@ class Button friend class ButtonPanel; public: - Button(std::string icon_file, std::string info, SDLKey shortcut, int x, int y, int mw = -1, int h = -1); + Button(Surface* icon_file, const std::string& info, SDLKey shortcut, + int x, int y, int mw = -1, int h = -1); + Button(const std::string& icon_name, const std::string& info, SDLKey shortcut, + int x, int y, int mw = -1, int h = -1); + ~Button(); void event(SDL_Event& event); void draw(); int get_state(); void set_active(bool active) { active ? state = BUTTON_NONE : state = BUTTON_DEACTIVE; }; - void add_icon(std::string icon_file, int mw, int mh); + void add_icon(const std::string& imagefile, int mw, int mh); SDL_Rect get_pos() { return rect; } int get_tag(){return tag; } void set_drawable(Drawable* newdrawable) @@ -89,5 +95,6 @@ private: std::vector item; std::vector::iterator last_clicked; }; +#endif #endif /*SUPERTUX_BUTTON_H*/ diff --git a/src/camera.cpp b/src/camera.cpp index 3fdf3ac4e..e8cd4f5cd 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -25,6 +25,7 @@ #include "player.h" #include "level.h" #include "globals.h" +#include "world.h" Camera::Camera(Player* newplayer, Level* newlevel) : player(newplayer), level(newlevel), do_backscrolling(true), @@ -40,10 +41,10 @@ Camera::~Camera() { } -void -Camera::set_translation(const Vector& newtranslation) +const Vector& +Camera::get_translation() const { - translation = newtranslation; + return World::current()->context.get_translation(); } void @@ -128,10 +129,12 @@ static const float max_speed_y = 1.4; void Camera::action(float elapsed_time) { + translation = World::current()->context.get_translation(); if(mode == NORMAL) scroll_normal(elapsed_time); else if(mode == AUTOSCROLL) scroll_autoscroll(elapsed_time); + World::current()->context.set_translation(translation); } void diff --git a/src/camera.h b/src/camera.h index 453a06a8f..b64e71d89 100644 --- a/src/camera.h +++ b/src/camera.h @@ -35,28 +35,21 @@ public: Camera(Player* player = 0, Level* level = 0); virtual ~Camera(); - /** transforms a coordinate in world space to screen space. - * Basically you have to apply this function to each coordinate that you want - * to display on screen. - */ - Vector world2screen(const Vector& worldpos) const - { - return worldpos - translation; - } - /// parse camera mode from lisp file void read(LispReader& reader); /// write camera mode to a lisp file virtual void write(LispWriter& writer); - /** returns the current translation (=scroll) vector of the viewport */ - const Vector& get_translation() const - { return translation; } - /** set the curren translation vector of the viewport */ - void set_translation(const Vector& translation); + /** @deprecated@ */ + const Vector& get_translation() const; virtual void action(float elapsed_time); + virtual void draw(DrawingContext& context) + { + (void) context; + } + enum CameraMode { NORMAL, AUTOSCROLL, MANUAL diff --git a/src/collision.cpp b/src/collision.cpp index 58c48c6bd..d431f40a2 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -59,7 +59,7 @@ bool collision_object_map(const base_type& base) for(int x = starttilex; x*32 < max_x; ++x) { for(int y = starttiley; y*32 < max_y; ++y) { Tile* tile = tilemanager.get(level.get_tile_at(x, y)); - if(tile && tile->solid) + if(tile && (tile->attributes & Tile::SOLID)) return true; } } @@ -91,7 +91,7 @@ void* collision_func(const base_type& base, tiletestfunction function) static void* test_goal_tile_function(Tile* tile) { - if(tile && tile->goal) + if(tile && (tile->attributes & Tile::GOAL)) return tile; return 0; } @@ -248,44 +248,37 @@ Tile* gettile(float x, float y) bool issolid(float x, float y) { Tile* tile = gettile(x,y); - return tile && tile->solid; + return tile && (tile->attributes & Tile::SOLID); } -bool isunisolid(float x, float y) -{ - Tile* tile = gettile(x,y); - return tile && tile->unisolid; -} - - bool isbrick(float x, float y) { Tile* tile = gettile(x,y); - return tile && tile->brick; + return tile && (tile->attributes & Tile::BRICK); } bool isice(float x, float y) { Tile* tile = gettile(x,y); - return tile && tile->ice; + return tile && (tile->attributes & Tile::ICE); } bool isspike(float x, float y) { Tile* tile = gettile(x,y); - return tile && tile->spike; + return tile && (tile->attributes & Tile::SPIKE); } bool isfullbox(float x, float y) { Tile* tile = gettile(x,y); - return tile && tile->fullbox; + return tile && (tile->attributes & Tile::FULLBOX); } -bool isdistro(float x, float y) +bool iscoin(float x, float y) { Tile* tile = gettile(x,y); - return tile && tile->distro; + return tile && (tile->attributes & Tile::COIN); } /* EOF */ diff --git a/src/collision.h b/src/collision.h index a30451b9f..b6c243e2e 100644 --- a/src/collision.h +++ b/src/collision.h @@ -53,7 +53,6 @@ Tile* gettile(float x, float y); // Some little helper function to check for tile properties bool issolid(float x, float y); -bool isunisolid(float x, float y); bool isbrick(float x, float y); bool isice(float x, float y); bool isspike(float x, float y); diff --git a/src/display_manager.cpp b/src/display_manager.cpp deleted file mode 100644 index 3a9b660d9..000000000 --- a/src/display_manager.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// $Id$ -// -// SuperTux - A Jump'n Run -// Copyright (C) 2004 Matthias Braun - -DisplayManager::DisplayManager() -{ -} - -DisplayManager::~DisplayManager() -{ -} - -void -DisplayManager::add_drawable(Drawable* drawable, int layer) -{ - DisplayList::iterator i - = std::lower_bound(displaylist.begin(), displaylist.end(), layer); - if(i == displaylist.end()) - displaylist.push_back(DrawingQueueEntry(drawable, layer)); - else - displaylist.insert(i, DrawingQueueEntry(drawable, layer)); -} - -void -DisplayManager::remove_drawable(Drawable* drawable) -{ - for(DisplayList::iterator i = displaylist.begin(); i != displaylist.end();) { - if(i->object == drawable) - i = displaylist.erase(i); - else - ++i; - } -} - -void -DisplayManager::draw(Camera& camera) -{ - for(DisplayList::iterator i = displaylist.begin(); i != displaylist.end(); - ++i) - i->object->draw(camera, i->layer); -} - diff --git a/src/display_manager.h b/src/display_manager.h deleted file mode 100644 index 29cc10b1b..000000000 --- a/src/display_manager.h +++ /dev/null @@ -1,77 +0,0 @@ -// $Id$ -// -// SuperTux - A Jump'n Run -// Copyright (C) 2004 Matthias Braun -// -// 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 __DISPLAY_MANAGER_H__ -#define __DISPLAY_MANAGER_H__ - -#include - -#include "drawable.h" -#include "camera.h" - -// some constants for predefined layer values -enum { - LAYER_BACKGROUND0 = -300, - LAYER_BACKGROUND1 = -200, - LAYER_BACKGROUNDTILES = -100, - LAYER_TILES = 0, - LAYER_OBJECTS = 100, - LAYER_FOREGROUNDTILES = 200, - LAYER_FOREGROUND0 = 300, - LAYER_FOREGROUND1 = 400 -}; - -/** This class holds a list of all things that should be drawn to screen - */ -class DisplayManager -{ -public: - DisplayManager(); - ~DisplayManager(); - - /** adds an object to the list of stuff that should be drawn each frame. - * The layer argument specifies how early an object is drawn. - */ - void add_drawable(Drawable* object, int layer); - - void remove_drawable(Drawable* object); - - void draw(Camera& camera); - -private: - class DrawingQueueEntry { - public: - DrawingQueueEntry(Drawable* newobject, int newlayer) - : object(newobject), layer(newlayer) - { } - - bool operator <(int olayer) const - { - return layer < olayer; - } - - Drawable* object; - int layer; - }; - - typedef std::vector DisplayList; - DisplayList displaylist; -}; - -#endif - diff --git a/src/drawable.h b/src/drawable.h deleted file mode 100644 index d96f20047..000000000 --- a/src/drawable.h +++ /dev/null @@ -1,35 +0,0 @@ -// $Id$ -// -// SuperTux - A Jump'n Run -// Copyright (C) 2004 Matthias Braun -// -// 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 __DRAWABLE_H__ -#define __DRAWABLE_H__ - -class Camera; - -/** interface for all game objects that can be drawn on screen. - */ -class Drawable -{ -public: - /** This function draws the object on screen. - */ - virtual void draw(Camera& viewport, int layer) = 0; -}; - -#endif - diff --git a/src/game_object.h b/src/game_object.h index d2824b59d..fe81d95af 100644 --- a/src/game_object.h +++ b/src/game_object.h @@ -21,7 +21,7 @@ #include -class DisplayManager; +class DrawingContext; /** * Base class for all game objects. This contains functions for: @@ -47,6 +47,11 @@ public: */ virtual void action(float elapsed_time) = 0; + /** The GameObject should draw itself onto the provided DrawingContext if this + * function is called. + */ + virtual void draw(DrawingContext& context) = 0; + /** returns true if the object is not scheduled to be removed yet */ bool is_valid() const { return !wants_to_die; } diff --git a/src/gameloop.cpp b/src/gameloop.cpp index c50f53b46..a39342df7 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -39,7 +39,7 @@ #include "defines.h" #include "globals.h" #include "gameloop.h" -#include "screen.h" +#include "screen/screen.h" #include "setup.h" #include "high_scores.h" #include "menu.h" @@ -147,20 +147,19 @@ GameSession::levelintro(void) char str[60]; - Camera dummy; - world->background->draw(dummy, LAYER_BACKGROUND0); + DrawingContext context; + world->background->draw(context); sprintf(str, "%s", world->get_level()->name.c_str()); - gold_text->drawf(str, 0, 220, A_HMIDDLE, A_TOP, 1); + context.draw_text_center(gold_text, str, Vector(0, 220), 0); sprintf(str, "TUX x %d", player_status.lives); - white_text->drawf(str, 0, 240, A_HMIDDLE, A_TOP, 1); + context.draw_text_center(white_text, str, Vector(0, 240), 0); sprintf(str, "by %s", world->get_level()->author.c_str()); - white_small_text->drawf(str, 0, 400, A_HMIDDLE, A_TOP, 1); - + context.draw_text_center(white_small_text, str, Vector(0, 400), 0); - flipscreen(); + context.do_drawing(); SDL_Event event; wait_for_event(event,1000,3000,true); @@ -492,27 +491,37 @@ GameSession::action(double frame_ratio) void GameSession::draw() { + DrawingContext& context = world->context; + world->draw(); - drawstatus(); + drawstatus(context); if(game_pause) { int x = screen->h / 20; for(int i = 0; i < x; ++i) { - fillrect(i % 2 ? (pause_menu_frame * i)%screen->w : -((pause_menu_frame * i)%screen->w) ,(i*20+pause_menu_frame)%screen->h,screen->w,10,20,20,20, rand() % 20 + 1); + context.draw_filled_rect( + Vector(i % 2 ? (pause_menu_frame * i)%screen->w : + -((pause_menu_frame * i)%screen->w) + ,(i*20+pause_menu_frame)%screen->h), + Vector(screen->w,10), + Color(20,20,20, rand() % 20 + 1), LAYER_FOREGROUND1+1); } - fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128); - blue_text->drawf("PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1); + context.draw_filled_rect( + Vector(0,0), Vector(screen->w, screen->h), + Color(rand() % 50, rand() % 50, rand() % 50, 128), LAYER_FOREGROUND1); + world->context.draw_text_center(blue_text, "PAUSE - Press 'P' To Play", + Vector(0, 230), LAYER_FOREGROUND1+2); } if(Menu::current()) { - Menu::current()->draw(); - mouse_cursor->draw(); + Menu::current()->draw(context); + mouse_cursor->draw(context); } - updatescreen(); + context.do_drawing(); } void @@ -668,50 +677,68 @@ void bumpbrick(float x, float y) /* (Status): */ void -GameSession::drawstatus() +GameSession::drawstatus(DrawingContext& context) { + context.push_transform(); + context.set_translation(Vector(0, 0)); + char str[60]; - + snprintf(str, 60, "%d", player_status.score); - white_text->draw("SCORE", 0, 0, 1); - gold_text->draw(str, 96, 0, 1); + context.draw_text(white_text, "SCORE", Vector(0, 0), LAYER_FOREGROUND1); + context.draw_text(gold_text, str, Vector(96, 0), LAYER_FOREGROUND1); if(st_gl_mode == ST_GL_TEST) { - white_text->draw("Press ESC To Return",0,20,1); + context.draw_text(white_text, "Press ESC To Return", Vector(0,20), + LAYER_FOREGROUND1); } if(!time_left.check()) { - white_text->draw("TIME'S UP", screen->w/2 - white_text->w*8, 0, 1); + context.draw_text_center(white_text, "TIME's UP", Vector(0, 0), + LAYER_FOREGROUND1); } else if (time_left.get_left() > TIME_WARNING || (global_frame_counter % 10) < 5) { sprintf(str, "%d", time_left.get_left() / 1000 ); - white_text->draw("TIME", screen->w/2 - white_text->w*4, 0, 1); - gold_text->draw(str, screen->w/2 + gold_text->w, 0, 1); + context.draw_text_center(white_text, "TIME", + Vector(0, 0), LAYER_FOREGROUND1); + context.draw_text_center(gold_text, str, + Vector(4*16, 0), LAYER_FOREGROUND1); } sprintf(str, "%d", player_status.distros); - white_text->draw("COINS", screen->w - white_text->w*9, 0, 1); - gold_text->draw(str, screen->w - gold_text->w*2, 0, 1); + context.draw_text(white_text, "COINS", + Vector(screen->w - white_text->w*9, 0), LAYER_FOREGROUND1); + context.draw_text(gold_text, str, + Vector(screen->w - gold_text->w*2, 0), LAYER_FOREGROUND1); - white_text->draw("LIVES", screen->w - white_text->w*9, 20); + context.draw_text(white_text, "LIVES", + Vector(screen->w - white_text->w*9, 20), LAYER_FOREGROUND1); if (player_status.lives >= 5) { sprintf(str, "%dx", player_status.lives); - gold_text->draw_align(str, screen->w - gold_text->w, 20, A_RIGHT, A_TOP); - tux_life->draw(screen->w - gold_text->w, 20); + float x = screen->w - gold_text->get_text_width(str) - tux_life->w; + context.draw_text(gold_text, str, Vector(x, 20), LAYER_FOREGROUND1); + context.draw_surface(tux_life, Vector(screen->w - 16, 20), + LAYER_FOREGROUND1); } else { for(int i= 0; i < player_status.lives; ++i) - tux_life->draw(screen->w - tux_life->w*4 +(tux_life->w*i), 20); + context.draw_surface(tux_life, + Vector(screen->w - tux_life->w*4 +(tux_life->w*i), 20), + LAYER_FOREGROUND1); } if(show_fps) { sprintf(str, "%2.1f", fps_fps); - white_text->draw("FPS", screen->w - white_text->w*9, 40, 1); - gold_text->draw_align(str, screen->w, 40, A_RIGHT, A_TOP); + context.draw_text(white_text, "FPS", + Vector(screen->w - white_text->w*9, 40), LAYER_FOREGROUND1); + context.draw_text(gold_text, str, + Vector(screen->w-4*16, 40), LAYER_FOREGROUND1); } + + context.pop_transform(); } void @@ -719,18 +746,19 @@ GameSession::drawresultscreen(void) { char str[80]; - Camera dummy; - world->background->draw(dummy, LAYER_BACKGROUND0); + DrawingContext context; + world->background->draw(context); - blue_text->drawf("Result:", 0, 200, A_HMIDDLE, A_TOP, 1); + context.draw_text_center(blue_text, "Result:", Vector(0, 200), + LAYER_FOREGROUND1); sprintf(str, "SCORE: %d", player_status.score); - gold_text->drawf(str, 0, 224, A_HMIDDLE, A_TOP, 1); + context.draw_text_center(gold_text, str, Vector(0, 224), LAYER_FOREGROUND1); sprintf(str, "COINS: %d", player_status.distros); - gold_text->drawf(str, 0, 256, A_HMIDDLE, A_TOP, 1); + context.draw_text_center(gold_text, str, Vector(0, 256), LAYER_FOREGROUND1); - flipscreen(); + context.do_drawing(); SDL_Event event; wait_for_event(event,2000,5000,true); diff --git a/src/gameloop.h b/src/gameloop.h index 42f338534..a2eb7c722 100644 --- a/src/gameloop.h +++ b/src/gameloop.h @@ -103,7 +103,7 @@ class GameSession void process_events(); void levelintro(); - void drawstatus(); + void drawstatus(DrawingContext& context); void drawendscreen(); void drawresultscreen(void); diff --git a/src/gameobjs.cpp b/src/gameobjs.cpp index 76722c708..9c8e79cfc 100644 --- a/src/gameobjs.cpp +++ b/src/gameobjs.cpp @@ -20,6 +20,7 @@ // 02111-1307, USA. #include #include +#include #include "world.h" #include "tile.h" #include "gameloop.h" @@ -27,13 +28,11 @@ #include "sprite_manager.h" #include "resources.h" #include "level.h" -#include "display_manager.h" -BouncyDistro::BouncyDistro(DisplayManager& displaymanager, const Vector& pos) +BouncyDistro::BouncyDistro(const Vector& pos) : position(pos) { ym = -2; - displaymanager.add_drawable(this, LAYER_OBJECTS); } void @@ -47,17 +46,15 @@ BouncyDistro::action(float elapsed_time) } void -BouncyDistro::draw(Camera& viewport, int ) +BouncyDistro::draw(DrawingContext& context) { - img_distro[0]->draw(viewport.world2screen(position)); + context.draw_surface(img_distro[0], position, LAYER_OBJECTS); } -BrokenBrick::BrokenBrick(DisplayManager& displaymanager, Tile* ntile, - const Vector& pos, const Vector& nmovement) +BrokenBrick::BrokenBrick(Tile* ntile,const Vector& pos, const Vector& nmovement) : tile(ntile), position(pos), movement(nmovement) { - displaymanager.add_drawable(this, LAYER_OBJECTS); timer.start(200); } @@ -71,27 +68,18 @@ BrokenBrick::action(float elapsed_time) } void -BrokenBrick::draw(Camera& viewport, int ) +BrokenBrick::draw(DrawingContext& context) { - SDL_Rect src, dest; - src.x = rand() % 16; - src.y = rand() % 16; - src.w = 16; - src.h = 16; - - dest.x = (int)(position.x - viewport.get_translation().x); - dest.y = (int)(position.y - viewport.get_translation().y); - dest.w = 16; - dest.h = 16; - if (tile->images.size() > 0) - tile->images[0]->draw_part(src.x,src.y,dest.x,dest.y,dest.w,dest.h); + context.draw_surface_part(tile->images[0], + Vector(rand() % 16, rand() % 16), + Vector(16, 16), + position, LAYER_OBJECTS + 1); } -BouncyBrick::BouncyBrick(DisplayManager& displaymanager, const Vector& pos) +BouncyBrick::BouncyBrick(const Vector& pos) : position(pos), offset(0), offset_m(-BOUNCY_BRICK_SPEED) { - displaymanager.add_drawable(this, LAYER_OBJECTS); shape = World::current()->get_level()->gettileid(pos.x, pos.y); } @@ -110,16 +98,15 @@ BouncyBrick::action(float elapsed_time) } void -BouncyBrick::draw(Camera& viewport, int) +BouncyBrick::draw(DrawingContext& context) { - Tile::draw(viewport.world2screen(position + Vector(0, offset)), shape); + TileManager::instance()-> + draw_tile(context, shape, position + Vector(0, offset), LAYER_TILES+1); } -FloatingScore::FloatingScore(DisplayManager& displaymanager, - const Vector& pos, int score) +FloatingScore::FloatingScore(const Vector& pos, int score) : position(pos) { - displaymanager.add_drawable(this, LAYER_OBJECTS); timer.start(1000); snprintf(str, 10, "%d", score); position.x -= strlen(str) * 8; @@ -135,9 +122,9 @@ FloatingScore::action(float elapsed_time) } void -FloatingScore::draw(Camera& viewport, int ) +FloatingScore::draw(DrawingContext& context) { - gold_text->draw(str, viewport.world2screen(position)); + context.draw_text(gold_text, str, position, LAYER_OBJECTS); } /* Trampoline */ @@ -145,10 +132,8 @@ FloatingScore::draw(Camera& viewport, int ) #define TRAMPOLINE_FRAMES 4 Sprite *img_trampoline[TRAMPOLINE_FRAMES]; -Trampoline::Trampoline(DisplayManager& displaymanager, LispReader& reader) +Trampoline::Trampoline(LispReader& reader) { - displaymanager.add_drawable(this, LAYER_OBJECTS); - reader.read_float("x", &base.x); reader.read_float("y", &base.y); base.width = 32; @@ -174,9 +159,9 @@ Trampoline::write(LispWriter& writer) } void -Trampoline::draw(Camera& viewport, int ) +Trampoline::draw(DrawingContext& context) { - img_trampoline[frame]->draw(viewport.world2screen(Vector(base.x, base.y))); + img_trampoline[frame]->draw(context, Vector(base.x, base.y), LAYER_OBJECTS); frame = 0; } @@ -284,10 +269,8 @@ Trampoline::collision(void *p_c_object, int c_object, CollisionType type) Sprite *img_flying_platform; -FlyingPlatform::FlyingPlatform(DisplayManager& displaymanager, LispReader& reader) +FlyingPlatform::FlyingPlatform(LispReader& reader) { - displaymanager.add_drawable(this, LAYER_OBJECTS); - reader.read_int_vector("x", &pos_x); reader.read_int_vector("y", &pos_y); @@ -323,9 +306,9 @@ FlyingPlatform::write(LispWriter& writer) } void -FlyingPlatform::draw(Camera& viewport, int ) +FlyingPlatform::draw(DrawingContext& context) { -img_flying_platform->draw(viewport.world2screen(Vector(base.x, base.y))); + img_flying_platform->draw(context, Vector(base.x, base.y), LAYER_OBJECTS); } void diff --git a/src/gameobjs.h b/src/gameobjs.h index 49515a345..c4ce9ffd2 100644 --- a/src/gameobjs.h +++ b/src/gameobjs.h @@ -23,13 +23,12 @@ #define SUPERTUX_GAMEOBJS_H #include "type.h" -#include "texture.h" +#include "screen/texture.h" #include "timer.h" #include "scene.h" #include "physic.h" #include "collision.h" #include "game_object.h" -#include "drawable.h" #include "moving_object.h" #include "lispwriter.h" @@ -37,12 +36,12 @@ #define NO_BOUNCE 0 #define BOUNCE 1 -class BouncyDistro : public GameObject, public Drawable +class BouncyDistro : public GameObject { public: - BouncyDistro(DisplayManager& displaymanager, const Vector& pos); + BouncyDistro(const Vector& pos); virtual void action(float elapsed_time); - virtual void draw(Camera& viewport, int layer); + virtual void draw(DrawingContext& context); private: Vector position; @@ -56,14 +55,13 @@ extern Surface* img_distro[4]; class Tile; -class BrokenBrick : public GameObject, public Drawable +class BrokenBrick : public GameObject { public: - BrokenBrick(DisplayManager& displaymanager, Tile* tile, - const Vector& pos, const Vector& movement); + BrokenBrick(Tile* tile, const Vector& pos, const Vector& movement); virtual void action(float elapsed_time); - virtual void draw(Camera& viewport, int layer); + virtual void draw(DrawingContext& context); private: Timer timer; @@ -72,12 +70,12 @@ private: Vector movement; }; -class BouncyBrick : public GameObject, public Drawable +class BouncyBrick : public GameObject { public: - BouncyBrick(DisplayManager& displaymanager, const Vector& pos); + BouncyBrick(const Vector& pos); virtual void action(float elapsed_time); - virtual void draw(Camera& viewport, int layer); + virtual void draw(DrawingContext& context); private: Vector position; @@ -86,13 +84,13 @@ private: int shape; }; -class FloatingScore : public GameObject, public Drawable +class FloatingScore : public GameObject { public: - FloatingScore(DisplayManager& displaymanager, const Vector& pos, int s); + FloatingScore(const Vector& pos, int s); virtual void action(float elapsed_time); - virtual void draw(Camera& viewport, int layer); + virtual void draw(DrawingContext& context); private: Vector position; @@ -100,14 +98,14 @@ private: Timer timer; }; -class Trampoline : public MovingObject, public Drawable, public Serializable +class Trampoline : public MovingObject, public Serializable { public: - Trampoline(DisplayManager& displaymanager, LispReader& reader); + Trampoline(LispReader& reader); virtual void write(LispWriter& writer); virtual void action(float frame_ratio); - virtual void draw(Camera& viewport, int layer); + virtual void draw(DrawingContext& context); virtual void collision(const MovingObject& other, int); void collision(void *p_c_object, int c_object, CollisionType type); @@ -120,14 +118,14 @@ public: unsigned int frame; }; -class FlyingPlatform : public MovingObject, public Drawable, public Serializable +class FlyingPlatform : public MovingObject, public Serializable { public: - FlyingPlatform(DisplayManager& displaymanager, LispReader& reader); + FlyingPlatform(LispReader& reader); virtual void write(LispWriter& writer); virtual void action(float frame_ratio); - virtual void draw(Camera& viewport, int layer); + virtual void draw(DrawingContext& context); virtual void collision(const MovingObject& other, int); void collision(void *p_c_object, int c_object, CollisionType type); diff --git a/src/globals.cpp b/src/globals.cpp index 1da3e4a4b..0c16a3097 100644 --- a/src/globals.cpp +++ b/src/globals.cpp @@ -38,16 +38,16 @@ JoystickKeymap::JoystickKeymap() JoystickKeymap joystick_keymap; SDL_Surface * screen; -Text* black_text; -Text* gold_text; -Text* silver_text; -Text* blue_text; -Text* red_text; -Text* green_text; -Text* yellow_nums; -Text* white_text; -Text* white_small_text; -Text* white_big_text; +Font* black_text; +Font* gold_text; +Font* silver_text; +Font* blue_text; +Font* red_text; +Font* green_text; +Font* yellow_nums; +Font* white_text; +Font* white_small_text; +Font* white_big_text; MouseCursor * mouse_cursor; diff --git a/src/globals.h b/src/globals.h index 0dcb117ba..a30e66a70 100644 --- a/src/globals.h +++ b/src/globals.h @@ -24,7 +24,7 @@ #include #include -#include "text.h" +#include "screen/font.h" #include "menu.h" #include "mousecursor.h" @@ -47,16 +47,16 @@ struct JoystickKeymap extern JoystickKeymap joystick_keymap; extern SDL_Surface * screen; -extern Text* black_text; -extern Text* gold_text; -extern Text* silver_text; -extern Text* white_text; -extern Text* white_small_text; -extern Text* white_big_text; -extern Text* blue_text; -extern Text* red_text; -extern Text* green_text; -extern Text* yellow_nums; +extern Font* black_text; +extern Font* gold_text; +extern Font* silver_text; +extern Font* white_text; +extern Font* white_small_text; +extern Font* white_big_text; +extern Font* blue_text; +extern Font* red_text; +extern Font* green_text; +extern Font* yellow_nums; extern MouseCursor * mouse_cursor; diff --git a/src/high_scores.cpp b/src/high_scores.cpp index cb3d41068..044c882f2 100644 --- a/src/high_scores.cpp +++ b/src/high_scores.cpp @@ -26,8 +26,9 @@ #include "globals.h" #include "high_scores.h" #include "menu.h" -#include "screen.h" -#include "texture.h" +#include "screen/drawing_context.h" +#include "screen/screen.h" +#include "screen/texture.h" #include "setup.h" #include "lispreader.h" @@ -84,6 +85,7 @@ void save_hs(int score) Surface* bkgd; SDL_Event event; + DrawingContext context; bkgd = new Surface(datadir + "/images/highscore/highscore.png", IGNORE_ALPHA); hs_score = score; @@ -98,17 +100,19 @@ void save_hs(int score) /* ask for player's name */ while(Menu::current()) { - bkgd->draw_bg(); + context.draw_surface(bkgd, Vector(0, 0), LAYER_BACKGROUND0); - blue_text->drawf("Congratulations", 0, 130, A_HMIDDLE, A_TOP, 2, NO_UPDATE); - blue_text->draw("Your score:", 150, 180, 1, NO_UPDATE); + context.draw_text_center(blue_text, "Congratulations", + Vector(0, 130), LAYER_FOREGROUND1); + context.draw_text(blue_text, "Your score:", Vector(150, 180), + LAYER_FOREGROUND1); sprintf(str, "%d", hs_score); - yellow_nums->draw(str, 350, 170, 1, NO_UPDATE); + context.draw_text(yellow_nums, str, Vector(250, 170), LAYER_FOREGROUND1); - Menu::current()->draw(); + Menu::current()->draw(context); Menu::current()->action(); - flipscreen(); + context.do_drawing(); while(SDL_PollEvent(&event)) if(event.type == SDL_KEYDOWN) @@ -156,18 +160,4 @@ void save_hs(int score) fprintf( fi,")"); fclose(fi); } - -/* - fi = opendata(highscore_filename, "w"); - if (fi != NULL) - { - fprintf(fi, "# Supertux highscore file\n\n"); - - fprintf(fi, "name=%s\n", hs_name); - fprintf(fi, "highscore=%d\n", hs_score); - - fprintf(fi, "# (File automatically created.)\n"); - - fclose(fi); - }*/ } diff --git a/src/intro.cpp b/src/intro.cpp index 991c77f7f..a0aa61895 100644 --- a/src/intro.cpp +++ b/src/intro.cpp @@ -16,25 +16,14 @@ // 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 -#include -#include -#include -#include -#include -#include -#include - -#include "defines.h" -#include "globals.h" #include "intro.h" -#include "text.h" - -#include "screen.h" +#include "globals.h" +#include "defines.h" +#include "screen/font.h" +#include "screen/screen.h" void draw_intro() { -display_text_file("intro.txt", "/images/background/arctis.jpg", SCROLL_SPEED_MESSAGE); + display_text_file("intro.txt", "/images/background/arctis.jpg", SCROLL_SPEED_MESSAGE); } diff --git a/src/level.cpp b/src/level.cpp index 485e5e82d..ab90191c5 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -26,7 +26,8 @@ #include #include "globals.h" #include "setup.h" -#include "screen.h" +#include "camera.h" +#include "screen/screen.h" #include "level.h" #include "physic.h" #include "scene.h" @@ -36,6 +37,7 @@ #include "music_manager.h" #include "gameobjs.h" #include "world.h" +#include "background.h" #include "lispwriter.h" using namespace std; @@ -220,20 +222,12 @@ Level::init_defaults() name = "UnNamed"; author = "UnNamed"; song_title = "Mortimers_chipdisko.mod"; - bkgd_image = "arctis.jpg"; width = 0; height = 0; start_pos.x = 100; start_pos.y = 170; time_left = 100; gravity = 10.; - bkgd_speed = 50; - bkgd_top.red = 0; - bkgd_top.green = 0; - bkgd_top.blue = 0; - bkgd_bottom.red = 255; - bkgd_bottom.green = 255; - bkgd_bottom.blue = 255; resize(21, 19); } @@ -288,19 +282,40 @@ Level::load(const std::string& filename, World* world) if(!reader.read_int("height", &height)) { printf("Warning: no height specified for level.\n"); } - - bkgd_speed = 50; + + + // read old background stuff + int bkgd_speed = 50; reader.read_int("bkgd_speed", &bkgd_speed); - bkgd_top.red = bkgd_top.green = bkgd_top.blue = 0; - reader.read_int("bkgd_red_top", &bkgd_top.red); - reader.read_int("bkgd_green_top", &bkgd_top.green); - reader.read_int("bkgd_blue_top", &bkgd_top.blue); + Color bkgd_top, bkgd_bottom; + int r, g, b; + reader.read_int("bkgd_red_top", &r); + reader.read_int("bkgd_green_top", &g); + reader.read_int("bkgd_blue_top", &b); + bkgd_top.red = r; + bkgd_top.green = g; + bkgd_top.blue = b; + + reader.read_int("bkgd_red_bottom", &r); + reader.read_int("bkgd_green_bottom", &g); + reader.read_int("bkgd_blue_bottom", &b); + bkgd_bottom.red = r; + bkgd_bottom.green = g; + bkgd_bottom.blue = b; + + std::string bkgd_image; + reader.read_string("background", &bkgd_image); - bkgd_bottom.red = bkgd_bottom.green = bkgd_bottom.blue = 0; - reader.read_int("bkgd_red_bottom", &bkgd_bottom.red); - reader.read_int("bkgd_green_bottom", &bkgd_bottom.green); - reader.read_int("bkgd_blue_bottom", &bkgd_bottom.blue); + if(world) { + Background* background = new Background(); + if(bkgd_image != "") + background->set_image(bkgd_image, bkgd_speed); + else + background->set_gradient(bkgd_top, bkgd_bottom); + + world->add_object(background); + } gravity = 10; reader.read_float("gravity", &gravity); @@ -310,8 +325,6 @@ Level::load(const std::string& filename, World* world) reader.read_string("author", &author); song_title = ""; reader.read_string("music", &song_title); - bkgd_image = ""; - reader.read_string("background", &bkgd_image); particle_system = ""; reader.read_string("particle_system", &particle_system); @@ -408,13 +421,6 @@ Level::save(const std::string& subset, int level, World* world) writer.write_string("music", song_title); writer.write_string("background", bkgd_image); writer.write_string("particle_system", particle_system); - writer.write_int("bkgd_speed", bkgd_speed); - writer.write_int("bkgd_red_top", bkgd_top.red); - writer.write_int("bkgd_green_top", bkgd_top.green); - writer.write_int("bkgd_blue_top", bkgd_top.blue); - writer.write_int("bkgd_red_bottom", bkgd_bottom.red); - writer.write_int("bkgd_green_bottom", bkgd_bottom.green); - writer.write_int("bkgd_blue_bottom", bkgd_bottom.blue); writer.write_int("time", time_left); writer.write_int("width", width); writer.write_int("height", height); @@ -461,26 +467,6 @@ Level::cleanup() name = ""; author = ""; song_title = ""; - bkgd_image = ""; -} - -void -Level::load_gfx() -{ - if(!bkgd_image.empty()) - { - char fname[1024]; - snprintf(fname, 1024, "%s/background/%s", st_dir, bkgd_image.c_str()); - if(!faccessible(fname)) - snprintf(fname, 1024, "%s/images/background/%s", datadir.c_str(), bkgd_image.c_str()); - delete img_bkgd; - img_bkgd = new Surface(fname, IGNORE_ALPHA); - } - else - { - delete img_bkgd; - img_bkgd = 0; - } } /* Load a level-specific graphic... */ diff --git a/src/level.h b/src/level.h index 1f2fe9486..be51d5ab0 100644 --- a/src/level.h +++ b/src/level.h @@ -22,11 +22,9 @@ #define SUPERTUX_LEVEL_H #include -#include "texture.h" -#include "badguy.h" +#include "screen/texture.h" #include "lispreader.h" #include "musicref.h" -#include "gameobjs.h" class Tile; class World; @@ -34,33 +32,32 @@ class World; /** This type holds meta-information about a level-subset. It could be extended to handle manipulation of subsets. */ class LevelSubset - { - public: - LevelSubset(); - ~LevelSubset(); - - static void create(const std::string& subset_name); - void load(char *subset); - void save(); - - std::string name; - std::string title; - std::string description; - Surface* image; - int levels; +{ +public: + LevelSubset(); + ~LevelSubset(); + + static void create(const std::string& subset_name); + void load(char *subset); + void save(); + + std::string name; + std::string title; + std::string description; + Surface* image; + int levels; - private: - void parse(lisp_object_t* cursor); - }; +private: + void parse(lisp_object_t* cursor); +}; #define LEVEL_NAME_MAX 20 - enum TileMapType { TM_BG, TM_IA, TM_FG - }; +}; struct ResetPoint { @@ -70,7 +67,7 @@ struct ResetPoint class Level { - public: +public: Surface* img_bkgd; MusicRef level_song; MusicRef level_song_fast; @@ -81,17 +78,11 @@ class Level std::string bkgd_image; std::string particle_system; std::vector bg_tiles; /* Tiles in the background */ - std::vector ia_tiles; /* Tiles which can interact in the game (solids for example)*/ + std::vector ia_tiles; /* solid Tiles in the game */ std::vector fg_tiles; /* Tiles in the foreground */ -// std::vector bg_tiles[15]; /* Tiles in the background */ -// std::vector ia_tiles[15]; /* Tiles which can interact in the game (solids for example)*/ -// std::vector fg_tiles[15]; /* Tiles in the foreground */ int time_left; - Color bkgd_top; - Color bkgd_bottom; int width; int height; - int bkgd_speed; Vector start_pos; float gravity; @@ -121,8 +112,6 @@ class Level */ int load(const std::string& filename, World* world); - void load_gfx(); - void load_song(); void free_song(); MusicRef get_level_music(); diff --git a/src/leveleditor.cpp b/src/leveleditor.cpp index 67182b874..bb163d8c0 100644 --- a/src/leveleditor.cpp +++ b/src/leveleditor.cpp @@ -31,7 +31,7 @@ #include #include "leveleditor.h" -#include "screen.h" +#include "screen/screen.h" #include "defines.h" #include "globals.h" #include "setup.h" @@ -45,7 +45,9 @@ #include "resources.h" #include "music_manager.h" #include "background.h" -#include "display_manager.h" + +// TODO +#if 0 /* definitions to aid development */ @@ -472,29 +474,18 @@ void le_init_menus() for(std::vector::const_iterator sit = (*it).tiles.begin(); sit != (*it).tiles.end(); ++sit, ++i) { - std::string imagefile = "/images/tilesets/" ; - bool only_editor_image = false; - if(!TileManager::instance()->get(*sit)->filenames.empty()) - { - imagefile += TileManager::instance()->get(*sit)->filenames[0]; - } - else if(!TileManager::instance()->get(*sit)->editor_filenames.empty()) - { - imagefile += TileManager::instance()->get(*sit)->editor_filenames[0]; - only_editor_image = true; - } + Tile& tile = *(TileManager::instance()->get(*sit)); + Surface* image; + if(tile.editor_images.size() > 0) + image = tile.editor_images[0]; + else if(tile.images.size() > 0) + image = tile.images[0]; else - { - imagefile += "notile.png"; - } - Button* button = new Button(imagefile, it->name, SDLKey(SDLK_a + i), + // TODO use some notile image... + image = 0; + + Button* button = new Button(image, it->name, SDLKey(SDLK_a + i), 0, 0, 32, 32); - if(!only_editor_image) - if(!TileManager::instance()->get(*sit)->editor_filenames.empty()) - { - imagefile = "/images/tilesets/" + TileManager::instance()->get(*sit)->editor_filenames[0]; - button->add_icon(imagefile,32,32); - } tilegroups_map[it->name]->additem(button, *sit); } } @@ -511,7 +502,7 @@ void le_init_menus() for(int i = 0; i < NUM_BadGuyKinds; ++i) { BadGuy bad_tmp(dummy, BadGuyKind(i), 0, 0); - objects_map["BadGuys"]->additem(new Button("", "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i); + objects_map["BadGuys"]->additem(new Button(0, "BadGuy",(SDLKey)(i+'a'),0,0,32,32),1000000+i); objects_map["BadGuys"]->manipulate_button(i)->set_drawable(new BadGuy(dummy, BadGuyKind(i), @@ -1033,7 +1024,8 @@ void le_drawlevel() void le_change_object_properties(GameObject *pobj) { - Surface* cap_screen = Surface::CaptureScreen(); + //Surface* cap_screen = Surface::CaptureScreen(); + Menu* object_properties_menu = new Menu(); bool loop = true; @@ -1069,7 +1061,7 @@ void le_change_object_properties(GameObject *pobj) object_properties_menu->event(event); } - cap_screen->draw(0,0); + //cap_screen->draw(0,0); object_properties_menu->draw(); object_properties_menu->action(); @@ -1099,7 +1091,7 @@ void le_change_object_properties(GameObject *pobj) SDL_Delay(25); } - delete cap_screen; + //delete cap_screen; Menu::set_current(0); delete object_properties_menu; } @@ -1935,3 +1927,5 @@ void le_showhelp() le_selection_mode = temp_le_selection_mode; le_help_shown = false; } + +#endif diff --git a/src/leveleditor.h b/src/leveleditor.h index 48b8a6e18..d2774169d 100644 --- a/src/leveleditor.h +++ b/src/leveleditor.h @@ -23,6 +23,8 @@ #ifndef SUPERTUX_LEVELEDITOR_H #define SUPERTUX_LEVELEDITOR_H +#if 0 // TODO + struct square { int x1, y1, x2, y2; @@ -40,4 +42,6 @@ void testlevel(void); int le_init(void); void le_checkevents(void); +#endif + #endif /*SUPERTUX_LEVELEDITOR_H*/ diff --git a/src/lispreader.cpp b/src/lispreader.cpp index 3edb5ca93..7f9f7a5fa 100644 --- a/src/lispreader.cpp +++ b/src/lispreader.cpp @@ -1195,17 +1195,11 @@ LispReader::read_bool (const char* name, bool* b) return false; } -#if 0 -void mygzungetc(char c, void* file) -{ - gzungetc(c, file); -} - -lisp_stream_t* lisp_stream_init_gzfile (lisp_stream_t *stream, gzFile file) +lisp_object_t* +LispReader::get_lisp() { - return lisp_stream_init_any (stream, file, gzgetc, mygzungetc); + return lst; } -#endif lisp_object_t* lisp_read_from_gzfile(const char* filename) { diff --git a/src/lispreader.h b/src/lispreader.h index bde266c84..81f2c40be 100644 --- a/src/lispreader.h +++ b/src/lispreader.h @@ -170,24 +170,27 @@ void lisp_dump (lisp_object_t *obj, FILE *out); /** */ class LispReader - { - private: - lisp_object_t* lst; - - lisp_object_t* search_for(const char* name); - public: - /** cur == ((pos 1 2 3) (id 12 3 4)...) */ - LispReader (lisp_object_t* l); - - bool read_int_vector (const char* name, std::vector* vec); - bool read_int_vector (const char* name, std::vector* vec); - bool read_char_vector (const char* name, std::vector* vec); - bool read_string_vector (const char* name, std::vector* vec); - bool read_string (const char* name, std::string* str); - bool read_int (const char* name, int* i); - bool read_float (const char* name, float* f); - bool read_bool (const char* name, bool* b); - bool read_lisp (const char* name, lisp_object_t** b); - }; +{ +private: + lisp_object_t* lst; + + lisp_object_t* search_for(const char* name); +public: + /** cur == ((pos 1 2 3) (id 12 3 4)...) */ + LispReader (lisp_object_t* l); + + bool read_int_vector (const char* name, std::vector* vec); + bool read_int_vector (const char* name, std::vector* vec); + bool read_char_vector (const char* name, std::vector* vec); + bool read_string_vector (const char* name, std::vector* vec); + bool read_string (const char* name, std::string* str); + bool read_int (const char* name, int* i); + bool read_float (const char* name, float* f); + bool read_bool (const char* name, bool* b); + bool read_lisp (const char* name, lisp_object_t** b); + + lisp_object_t* get_lisp(); +}; #endif + diff --git a/src/menu.cpp b/src/menu.cpp index f9fc8ae4c..34dd5297b 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -32,7 +32,8 @@ #include "defines.h" #include "globals.h" #include "menu.h" -#include "screen.h" +#include "screen/screen.h" +#include "screen/drawing_context.h" #include "setup.h" #include "sound.h" #include "scene.h" @@ -66,7 +67,9 @@ Menu* Menu::current_ = 0; /* just displays a Yes/No text that can be used to confirm stuff */ bool confirm_dialog(std::string text) { - Surface* cap_screen = Surface::CaptureScreen(); + // TODO +#if 0 + //Surface* cap_screen = Surface::CaptureScreen(); Menu* dialog = new Menu; dialog->additem(MN_DEACTIVE, text,0,0); @@ -86,7 +89,7 @@ bool confirm_dialog(std::string text) dialog->event(event); } - cap_screen->draw(0,0); + //cap_screen->draw(0,0); dialog->draw(); dialog->action(); @@ -94,13 +97,13 @@ bool confirm_dialog(std::string text) switch (dialog->check()) { case true: - delete cap_screen; + //delete cap_screen; Menu::set_current(0); delete dialog; return true; break; case false: - delete cap_screen; + //delete cap_screen; Menu::set_current(0); delete dialog; return false; @@ -113,8 +116,8 @@ bool confirm_dialog(std::string text) flipscreen(); SDL_Delay(25); } - - +#endif + return false; } void @@ -506,13 +509,12 @@ Menu::check() } void -Menu::draw_item(int index, // Position of the current item in the menu - int menu_width, - int menu_height) +Menu::draw_item(DrawingContext& context, + int index, // Position of the current item in the menu + int menu_width, int menu_height) { MenuItem& pitem = item[index]; - int font_width = 16; int effect_offset = 0; { int effect_time = 0; @@ -523,13 +525,14 @@ Menu::draw_item(int index, // Position of the current item in the menu effect_offset = (index % 2) ? effect_time : -effect_time; } + Font* text_font = white_text; int x_pos = pos_x; int y_pos = pos_y + 24*index - menu_height/2 + 12 + effect_offset; int shadow_size = 2; - int text_width = strlen(pitem.text) * font_width; - int input_width = (strlen(pitem.input)+ 1) * font_width; - int list_width = strlen(string_list_active(pitem.list)) * font_width; - Text* text_font = white_text; + int text_width = int(text_font->get_text_width(pitem.text)); + int input_width = int(text_font->get_text_width(pitem.input) + 10); + int list_width = + int(text_font->get_text_width(string_list_active(pitem.list))); if (arrange_left) x_pos += 24 - menu_width/2 + (text_width + input_width + list_width)/2; @@ -544,30 +547,29 @@ Menu::draw_item(int index, // Position of the current item in the menu { case MN_DEACTIVE: { - black_text->draw_align(pitem.text, - x_pos, y_pos, - A_HMIDDLE, A_VMIDDLE, 2); + context.draw_text_center(blue_text, pitem.text, + Vector(0, y_pos - int(blue_text->get_height()/2)), + LAYER_FOREGROUND1); break; } case MN_HL: { + // TODO int x = pos_x - menu_width/2; int y = y_pos - 12 - effect_offset; /* Draw a horizontal line with a little 3d effect */ - fillrect(x, y + 6, - menu_width, 4, - 150,200,255,225); - fillrect(x, y + 6, - menu_width, 2, - 255,255,255,255); + context.draw_filled_rect(Vector(x, y + 6), + Vector(menu_width, 4), Color(150,200,255,225), LAYER_FOREGROUND1); + context.draw_filled_rect(Vector(x, y + 6), + Vector(menu_width, 2), Color(255,255,255,255), LAYER_FOREGROUND1); break; } case MN_LABEL: { - white_big_text->draw_align(pitem.text, - x_pos, y_pos, - A_HMIDDLE, A_VMIDDLE, 2); + context.draw_text_center(white_big_text, + pitem.text, Vector(0, y_pos - int(white_big_text->get_height()/2)), + LAYER_FOREGROUND1); break; } case MN_TEXTFIELD: @@ -575,15 +577,18 @@ Menu::draw_item(int index, // Position of the current item in the menu case MN_CONTROLFIELD_KB: case MN_CONTROLFIELD_JS: { - int input_pos = input_width/2; - int text_pos = (text_width + font_width)/2; - - fillrect(x_pos - input_pos + text_pos - 1, y_pos - 10, - input_width + font_width + 2, 20, - 255,255,255,255); - fillrect(x_pos - input_pos + text_pos, y_pos - 9, - input_width + font_width, 18, - 0,0,0,128); + int width = text_width + input_width + 5; + int text_pos = screen->w/2 - width/2; + int input_pos = text_pos + text_width + 10; + + context.draw_filled_rect( + Vector(input_pos - 5, y_pos - 10), + Vector(input_width + 10, 20), + Color(255,255,255,255), LAYER_FOREGROUND1-5); + context.draw_filled_rect( + Vector(input_pos - 4, y_pos - 9), + Vector(input_width + 8, 18), + Color(0,0,0,128), LAYER_FOREGROUND1-4); if(pitem.kind == MN_CONTROLFIELD_KB) get_controlfield_key_into_input(&pitem); @@ -593,74 +598,95 @@ Menu::draw_item(int index, // Position of the current item in the menu if(pitem.kind == MN_TEXTFIELD || pitem.kind == MN_NUMFIELD) { if(active_item == index) - gold_text->draw_align((pitem.get_input_with_symbol(true)).c_str(), x_pos + text_pos, y_pos, A_HMIDDLE, A_VMIDDLE, 2); + context.draw_text(gold_text, + pitem.get_input_with_symbol(true), + Vector(input_pos, y_pos - int(gold_text->get_height()/2)), + LAYER_FOREGROUND1); else - gold_text->draw_align((pitem.get_input_with_symbol(false)).c_str(), x_pos + text_pos, y_pos, A_HMIDDLE, A_VMIDDLE, 2); + context.draw_text(gold_text, + pitem.get_input_with_symbol(false), + Vector(input_pos, y_pos - int(gold_text->get_height()/2)), + LAYER_FOREGROUND1); } else - gold_text->draw_align(pitem.input, - x_pos + text_pos, y_pos, - A_HMIDDLE, A_VMIDDLE, 2); + context.draw_text(gold_text, pitem.input, + Vector(input_pos, y_pos - int(gold_text->get_height()/2)), + LAYER_FOREGROUND1); - text_font->draw_align(pitem.text, - x_pos - (input_width + font_width)/2, y_pos, - A_HMIDDLE, A_VMIDDLE, shadow_size); + context.draw_text(text_font, pitem.text, + Vector(text_pos, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); break; } case MN_STRINGSELECT: { - int list_pos_2 = list_width + font_width; + int list_pos_2 = list_width + 16; int list_pos = list_width/2; - int text_pos = (text_width + font_width)/2; + int text_pos = (text_width + 16)/2; /* Draw arrows */ - arrow_left->draw( x_pos - list_pos + text_pos - 17, y_pos - 8); - arrow_right->draw( x_pos - list_pos + text_pos - 1 + list_pos_2, y_pos - 8); + context.draw_surface(arrow_left, + Vector(x_pos - list_pos + text_pos - 17, y_pos - 8), + LAYER_FOREGROUND1); + context.draw_surface(arrow_right, + Vector(x_pos - list_pos + text_pos - 1 + list_pos_2, y_pos - 8), + LAYER_FOREGROUND1); /* Draw input background */ - fillrect(x_pos - list_pos + text_pos - 1, y_pos - 10, - list_pos_2 + 2, 20, - 255,255,255,255); - fillrect(x_pos - list_pos + text_pos, y_pos - 9, - list_pos_2, 18, - 0,0,0,128); - - gold_text->draw_align(string_list_active(pitem.list), - x_pos + text_pos, y_pos, - A_HMIDDLE, A_VMIDDLE,2); - - text_font->draw_align(pitem.text, - x_pos - list_pos_2/2, y_pos, - A_HMIDDLE, A_VMIDDLE, shadow_size); + context.draw_filled_rect( + Vector(x_pos - list_pos + text_pos - 1, y_pos - 10), + Vector(list_pos_2 + 2, 20), + Color(255,255,255,255), LAYER_FOREGROUND1 - 4); + context.draw_filled_rect( + Vector(x_pos - list_pos + text_pos, y_pos - 9), + Vector(list_pos_2, 18), + Color(0,0,0,128), LAYER_FOREGROUND1 - 5); + + context.draw_text_center(text_font, string_list_active(pitem.list), + Vector(text_pos, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); + context.draw_text_center(text_font, pitem.text, + Vector(list_pos_2/2, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); break; } case MN_BACK: { - text_font->draw_align(pitem.text, x_pos, y_pos, A_HMIDDLE, A_VMIDDLE, shadow_size); - back->draw( x_pos + text_width/2 + font_width, y_pos - 8); + context.draw_text_center(text_font, pitem.text, + Vector(0, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); + context.draw_surface(back, + Vector(x_pos + text_width/2 + 16, y_pos - 8), + LAYER_FOREGROUND1); break; } case MN_TOGGLE: { - text_font->draw_align(pitem.text, x_pos, y_pos, A_HMIDDLE, A_VMIDDLE, shadow_size); + context.draw_text_center(text_font, pitem.text, + Vector(0, y_pos - (text_font->get_height()/2)), + LAYER_FOREGROUND1); if(pitem.toggled) - checkbox_checked->draw( - x_pos + (text_width+font_width)/2, - y_pos - 8); + context.draw_surface(checkbox_checked, + Vector(x_pos + (text_width+16)/2, y_pos - 8), + LAYER_FOREGROUND1 + 1); else - checkbox->draw( - x_pos + (text_width+font_width)/2, - y_pos - 8); + context.draw_surface(checkbox, + Vector(x_pos + (text_width+16)/2, y_pos - 8), + LAYER_FOREGROUND1 + 1); break; } case MN_ACTION: - text_font->draw_align(pitem.text, x_pos, y_pos, A_HMIDDLE, A_VMIDDLE, shadow_size); + context.draw_text_center(text_font, pitem.text, + Vector(0, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); break; case MN_GOTO: - text_font->draw_align(pitem.text, x_pos, y_pos, A_HMIDDLE, A_VMIDDLE, shadow_size); + context.draw_text_center(text_font, pitem.text, + Vector(0, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); break; } } @@ -691,21 +717,25 @@ int Menu::get_height() const /* Draw the current menu. */ void -Menu::draw() +Menu::draw(DrawingContext& context) { int menu_height = get_height(); int menu_width = get_width(); + context.push_transform(); + context.set_translation(Vector(0, 0)); + /* Draw a transparent background */ - fillrect(pos_x - menu_width/2, - pos_y - 24*item.size()/2 - 10, - menu_width,menu_height + 20, - 150,180,200,125); + context.draw_filled_rect( + Vector(pos_x - menu_width/2, pos_y - 24*item.size()/2 - 10), + Vector(menu_width,menu_height + 20), + Color(150,180,200,125), LAYER_FOREGROUND1-10); for(unsigned int i = 0; i < item.size(); ++i) { - draw_item(i, menu_width, menu_height); + draw_item(context, i, menu_width, menu_height); } + context.pop_transform(); } MenuItem& diff --git a/src/menu.h b/src/menu.h index 4ac921dd8..c77777fe6 100644 --- a/src/menu.h +++ b/src/menu.h @@ -22,7 +22,7 @@ #include #include -#include "texture.h" +#include "screen/texture.h" #include "timer.h" #include "type.h" #include "mousecursor.h" @@ -213,8 +213,9 @@ public: void Menu::get_controlfield_key_into_input(MenuItem *item); void Menu::get_controlfield_js_into_input(MenuItem *item); - void draw (); - void draw_item(int index, int menu_width, int menu_height); + void draw(DrawingContext& context); + void draw_item(DrawingContext& context, + int index, int menu_width, int menu_height); void set_pos(int x, int y, float rw = 0, float rh = 0); /** translate a SDL_Event into a menu_action */ diff --git a/src/mousecursor.cpp b/src/mousecursor.cpp index ff794b206..a0735651c 100644 --- a/src/mousecursor.cpp +++ b/src/mousecursor.cpp @@ -16,8 +16,7 @@ // 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 "screen.h" +#include "screen/drawing_context.h" #include "mousecursor.h" MouseCursor* MouseCursor::current_ = 0; @@ -59,7 +58,7 @@ void MouseCursor::set_mid(int x, int y) mid_y = y; } -void MouseCursor::draw() +void MouseCursor::draw(DrawingContext& context) { int x,y,w,h; Uint8 ispressed = SDL_GetMouseState(&x,&y); @@ -88,5 +87,9 @@ void MouseCursor::draw() timer.start(MC_FRAME_PERIOD); } - cursor->draw_part(w*cur_frame, h*cur_state , x-mid_x, y-mid_y, w, h); + context.push_transform(); + context.set_translation(Vector(0, 0)); + context.draw_surface_part(cursor, Vector(w*cur_frame, h*cur_state), Vector(w, + h), Vector(x-mid_x, y-mid_y), LAYER_FOREGROUND1+100); + context.pop_transform(); } diff --git a/src/mousecursor.h b/src/mousecursor.h index 16b0ba603..a9b89bcdd 100644 --- a/src/mousecursor.h +++ b/src/mousecursor.h @@ -22,7 +22,7 @@ #include #include "timer.h" -#include "texture.h" +#include "screen/texture.h" #define MC_FRAME_PERIOD 800 // in ms @@ -34,26 +34,26 @@ enum { }; class MouseCursor - { - public: - MouseCursor(std::string cursor_file, int frames); - ~MouseCursor(); - int state(); - void set_state(int nstate); - void set_mid(int x, int y); - void draw(); +{ +public: + MouseCursor(std::string cursor_file, int frames); + ~MouseCursor(); + int state(); + void set_state(int nstate); + void set_mid(int x, int y); + void draw(DrawingContext& context); - static MouseCursor* current() { return current_; }; - static void set_current(MouseCursor* pcursor) { current_ = pcursor; }; + static MouseCursor* current() { return current_; }; + static void set_current(MouseCursor* pcursor) { current_ = pcursor; }; - private: - int mid_x, mid_y; - static MouseCursor* current_; - int state_before_click; - int cur_state; - int cur_frame, tot_frames; - Surface* cursor; - Timer timer; - }; +private: + int mid_x, mid_y; + static MouseCursor* current_; + int state_before_click; + int cur_state; + int cur_frame, tot_frames; + Surface* cursor; + Timer timer; +}; #endif /*SUPERTUX_MOUSECURSOR_H*/ diff --git a/src/particlesystem.cpp b/src/particlesystem.cpp index 7604d32df..88b728841 100644 --- a/src/particlesystem.cpp +++ b/src/particlesystem.cpp @@ -26,14 +26,11 @@ #include "level.h" #include "scene.h" #include "camera.h" -#include "display_manager.h" -ParticleSystem::ParticleSystem(DisplayManager& displaymanager) +ParticleSystem::ParticleSystem() { virtual_width = screen->w; virtual_height = screen->h; - - displaymanager.add_drawable(this, LAYER_BACKGROUND1); } ParticleSystem::~ParticleSystem() @@ -44,39 +41,34 @@ ParticleSystem::~ParticleSystem() } } -void ParticleSystem::draw(Camera& viewport, int layer) +void ParticleSystem::draw(DrawingContext& context) { + float scrollx = context.get_translation().x; + float scrolly = context.get_translation().y; + + context.push_transform(); + context.set_translation(Vector(0,0)); + std::vector::iterator i; for(i = particles.begin(); i != particles.end(); ++i) { Particle* particle = *i; - if(particle->layer != layer) - continue; - float scrollx = viewport.get_translation().x; - float scrolly = viewport.get_translation().y; - // remap x,y coordinates onto screencoordinates - float x = fmodf(particle->x - scrollx, virtual_width); - if(x < 0) x += virtual_width; - float y = fmodf(particle->y - scrolly, virtual_height); - if(y < 0) y += virtual_height; - float xmax = fmodf(x + particle->texture->w, virtual_width); - float ymax = fmodf(y + particle->texture->h, virtual_height); - - // particle on screen - if(x >= screen->w && xmax >= screen->w) - continue; - if(y >= screen->h && ymax >= screen->h) - continue; - - if(x > screen->w) x -= virtual_width; - if(y > screen->h) y -= virtual_height; - particle->texture->draw(x, y); + Vector pos; + pos.x = fmodf(particle->pos.x - scrollx, virtual_width); + if(pos.x < 0) pos.x += virtual_width; + pos.y = fmodf(particle->pos.y - scrolly, virtual_height); + if(pos.y < 0) pos.y += virtual_height; + + if(pos.x > screen->w) pos.x -= virtual_width; + if(pos.y > screen->h) pos.y -= virtual_height; + context.draw_surface(particle->texture, pos, LAYER_BACKGROUND1); } + + context.pop_transform(); } -SnowParticleSystem::SnowParticleSystem(DisplayManager& displaymanager) - : ParticleSystem(displaymanager) +SnowParticleSystem::SnowParticleSystem() { snowimages[0] = new Surface(datadir+"/images/shared/snow0.png", USE_ALPHA); snowimages[1] = new Surface(datadir+"/images/shared/snow1.png", USE_ALPHA); @@ -88,9 +80,8 @@ SnowParticleSystem::SnowParticleSystem(DisplayManager& displaymanager) size_t snowflakecount = size_t(virtual_width/10.0); for(size_t i=0; ix = rand() % int(virtual_width); - particle->y = rand() % screen->h; - particle->layer = LAYER_BACKGROUND1; + particle->pos.x = rand() % int(virtual_width); + particle->pos.y = rand() % screen->h; int snowsize = rand() % 3; particle->texture = snowimages[snowsize]; do { @@ -113,16 +104,15 @@ void SnowParticleSystem::action(float elapsed_time) std::vector::iterator i; for(i = particles.begin(); i != particles.end(); ++i) { SnowParticle* particle = (SnowParticle*) *i; - particle->y += particle->speed * elapsed_time; - if(particle->y > screen->h) { - particle->y = fmodf(particle->y , virtual_height); - particle->x = rand() % int(virtual_width); + particle->pos.y += particle->speed * elapsed_time; + if(particle->pos.y > screen->h) { + particle->pos.y = fmodf(particle->pos.y , virtual_height); + particle->pos.x = rand() % int(virtual_width); } } } -CloudParticleSystem::CloudParticleSystem(DisplayManager& displaymanager) - : ParticleSystem(displaymanager) +CloudParticleSystem::CloudParticleSystem() { cloudimage = new Surface(datadir + "/images/shared/cloud.png", USE_ALPHA); @@ -131,9 +121,8 @@ CloudParticleSystem::CloudParticleSystem(DisplayManager& displaymanager) // create some random clouds for(size_t i=0; i<15; ++i) { CloudParticle* particle = new CloudParticle; - particle->x = rand() % int(virtual_width); - particle->y = rand() % int(virtual_height); - particle->layer = LAYER_BACKGROUND1; + particle->pos.x = rand() % int(virtual_width); + particle->pos.y = rand() % int(virtual_height); particle->texture = cloudimage; particle->speed = -float(250 + rand() % 200) / 1000.0; @@ -151,6 +140,6 @@ void CloudParticleSystem::action(float elapsed_time) std::vector::iterator i; for(i = particles.begin(); i != particles.end(); ++i) { CloudParticle* particle = (CloudParticle*) *i; - particle->x += particle->speed * elapsed_time; + particle->pos.x += particle->speed * elapsed_time; } } diff --git a/src/particlesystem.h b/src/particlesystem.h index 8bd117afe..11bff4a00 100644 --- a/src/particlesystem.h +++ b/src/particlesystem.h @@ -21,8 +21,7 @@ #define SUPERTUX_PARTICLESYSTEM_H #include -#include "texture.h" -#include "drawable.h" +#include "screen/texture.h" #include "game_object.h" class DisplayManager; @@ -42,13 +41,13 @@ class DisplayManager; * initialize particles in the constructor and move them in the simulate * function. */ -class ParticleSystem : public GameObject, public Drawable +class ParticleSystem : public GameObject { public: - ParticleSystem(DisplayManager& displaymanager); + ParticleSystem(); virtual ~ParticleSystem(); - virtual void draw(Camera& view, int layer); + virtual void draw(DrawingContext& context); protected: class Particle @@ -57,8 +56,7 @@ protected: virtual ~Particle() { } - float x, y; - int layer; + Vector pos; Surface* texture; }; @@ -69,7 +67,7 @@ protected: class SnowParticleSystem : public ParticleSystem { public: - SnowParticleSystem(DisplayManager& displaymanager); + SnowParticleSystem(); virtual ~SnowParticleSystem(); virtual void action(float elapsed_time); @@ -90,7 +88,7 @@ private: class CloudParticleSystem : public ParticleSystem { public: - CloudParticleSystem(DisplayManager& displaymanager); + CloudParticleSystem(); virtual ~CloudParticleSystem(); virtual void action(float elapsed_time); diff --git a/src/player.cpp b/src/player.cpp index e041dd50f..379257d04 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -27,7 +27,8 @@ #include "scene.h" #include "tile.h" #include "sprite.h" -#include "screen.h" +#include "gameobjs.h" +#include "screen/screen.h" // behavior definitions: #define TILES_FOR_BUTTJUMP 3 @@ -71,10 +72,8 @@ void player_input_init(player_input_type* pplayer_input) pplayer_input->old_up = UP; } -Player::Player(DisplayManager& display_manager) +Player::Player() { - display_manager.add_drawable(this, LAYER_OBJECTS-1); // for tux himself - display_manager.add_drawable(this, LAYER_OBJECTS+1); // for the arm init(); } @@ -262,7 +261,7 @@ Player::action(float elapsed_time) if (isbrick(base.x, base.y) || isfullbox(base.x, base.y)) { - World::current()->trygrabdistro(base.x, base.y - 32,BOUNCE); + World::current()->trygrabdistro(base.x, base.y - 32, BOUNCE); World::current()->trybumpbadguy(base.x, base.y - 64); World::current()->trybreakbrick(base.x, base.y, size == SMALL); @@ -313,10 +312,7 @@ Player::on_ground() { return ( issolid(base.x + base.width / 2, base.y + base.height) || issolid(base.x + 1, base.y + base.height) || - issolid(base.x + base.width - 1, base.y + base.height) || - isunisolid(base.x + base.width / 2, base.y + base.height) || - isunisolid(base.x + 1, base.y + base.height) || - isunisolid(base.x + base.width - 1, base.y + base.height) ); + issolid(base.x + base.width - 1, base.y + base.height)); } bool @@ -624,7 +620,7 @@ Player::grabdistros() } void -Player::draw(Camera& viewport, int layer) +Player::draw(DrawingContext& context) { PlayerSprite* sprite; @@ -637,98 +633,97 @@ Player::draw(Camera& viewport, int layer) else sprite = &largetux; - Vector pos = viewport.world2screen(Vector(base.x, base.y)); + int layer = LAYER_OBJECTS - 1; + Vector pos = Vector(base.x, base.y); - if(layer == LAYER_OBJECTS + 1) { - // Draw arm overlay graphics when Tux is holding something - if ((holding_something && physic.get_velocity_y() == 0) || shooting_timer.check() && !duck) - { - if (dir == RIGHT) - sprite->grab_right->draw(pos); - else - sprite->grab_left->draw(pos); - } - - // Draw blinking star overlay - if (invincible_timer.started() && - (invincible_timer.get_left() > TUX_INVINCIBLE_TIME_WARNING || global_frame_counter % 3)) - { - if (size == SMALL || duck) - smalltux_star->draw(pos); - else - largetux_star->draw(pos); - } - - return; - } - if (!safe_timer.started() || (global_frame_counter % 2) == 0) { if (dying == DYING_SQUISHED) { - smalltux_gameover->draw(pos); + smalltux_gameover->draw(context, pos, LAYER_OBJECTS); } else { if(growing_timer.check()) { if (dir == RIGHT) - growingtux_right->draw(pos); + growingtux_right->draw(context, pos, layer); else - growingtux_left->draw(pos); + growingtux_left->draw(context, pos, layer); } else if (duck && size != SMALL) { if (dir == RIGHT) - sprite->duck_right->draw(pos); + sprite->duck_right->draw(context, pos, layer); else - sprite->duck_left->draw(pos); + sprite->duck_left->draw(context, pos, layer); } else if (skidding_timer.started()) { if (dir == RIGHT) - sprite->skid_right->draw(pos); + sprite->skid_right->draw(context, pos, layer); else - sprite->skid_left->draw(pos); + sprite->skid_left->draw(context, pos, layer); } else if (kick_timer.started()) { if (dir == RIGHT) - sprite->kick_right->draw(pos); + sprite->kick_right->draw(context, pos, layer); else - sprite->kick_left->draw(pos); + sprite->kick_left->draw(context, pos, layer); } else if (physic.get_velocity_y() != 0) { if (dir == RIGHT) - sprite->jump_right->draw(pos); + sprite->jump_right->draw(context, pos, layer); else - sprite->jump_left->draw(pos); + sprite->jump_left->draw(context, pos, layer); } else { if (fabsf(physic.get_velocity_x()) < 1.0f) // standing { if (dir == RIGHT) - sprite->stand_right->draw(pos); + sprite->stand_right->draw(context, pos, layer); else - sprite->stand_left->draw(pos); + sprite->stand_left->draw(context, pos, layer); } else // moving { if (dir == RIGHT) - sprite->walk_right->draw(pos); + sprite->walk_right->draw(context, pos, layer); else - sprite->walk_left->draw(pos); + sprite->walk_left->draw(context, pos, layer); } } } } - + + // Draw arm overlay graphics when Tux is holding something + if ((holding_something && physic.get_velocity_y() == 0) || shooting_timer.check() && !duck) + { + if (dir == RIGHT) + sprite->grab_right->draw(context, pos, LAYER_OBJECTS + 1); + else + sprite->grab_left->draw(context, pos, LAYER_OBJECTS + 1); + } + + // Draw blinking star overlay + if (invincible_timer.started() && + (invincible_timer.get_left() > TUX_INVINCIBLE_TIME_WARNING || global_frame_counter % 3)) + { + if (size == SMALL || duck) + smalltux_star->draw(context, pos, LAYER_OBJECTS + 2); + else + largetux_star->draw(context, pos, LAYER_OBJECTS + 2); + } + +#if 0 // TODO if (debug_mode) fillrect(base.x - viewport.get_translation().x, base.y - viewport.get_translation().y, base.width, base.height, 75,75,75, 150); +#endif } void @@ -908,7 +903,7 @@ Player::move(const Vector& vector) } void -Player::check_bounds(Camera& viewport) +Player::check_bounds(DrawingContext& viewport) { /* Keep tux in bounds: */ if (base.x < 0) diff --git a/src/player.h b/src/player.h index 21a00a2dc..b3496ebca 100644 --- a/src/player.h +++ b/src/player.h @@ -24,11 +24,10 @@ #include "bitmask.h" #include "type.h" #include "timer.h" -#include "texture.h" +#include "screen/texture.h" #include "collision.h" #include "sound.h" #include "moving_object.h" -#include "drawable.h" #include "physic.h" /* Times: */ @@ -109,7 +108,7 @@ extern PlayerSprite largetux; extern PlayerSprite firetux; extern PlayerSprite icetux; -class Player : public MovingObject, public Drawable +class Player : public MovingObject { public: enum HurtMode { KILL, SHRINK }; @@ -148,7 +147,7 @@ public: Physic physic; public: - Player(DisplayManager& display_manager); + Player(); virtual ~Player(); int key_event(SDLKey key, int state); @@ -157,14 +156,14 @@ public: void grabdistros(); virtual void action(float elapsed_time); - virtual void draw(Camera& viewport, int layer); + virtual void draw(DrawingContext& context); virtual void collision(const MovingObject& other_object, int collision_type); void collision(void* p_c_object, int c_object); void kill(HurtMode mode); void player_remove_powerups(); - void check_bounds(Camera& viewport); + void check_bounds(DrawingContext& context); bool on_ground(); bool under_solid(); bool tiles_on_air(int tiles); diff --git a/src/scene.h b/src/scene.h index a4f7215f2..75271985b 100644 --- a/src/scene.h +++ b/src/scene.h @@ -20,7 +20,7 @@ #ifndef SUPERTUX_SCENE_H #define SUPERTUX_SCENE_H -#include "texture.h" +#include "screen/texture.h" #include "timer.h" #define FRAME_RATE 10 // 100 Frames per second (10ms) diff --git a/src/screen.cpp b/src/screen.cpp deleted file mode 100644 index 8e99e9b13..000000000 --- a/src/screen.cpp +++ /dev/null @@ -1,361 +0,0 @@ -// $Id$ -// -// SuperTux - A Jump'n Run -// Copyright (C) 2000 Bill Kendrick -// -// 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 -#include -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 -#include -#include -#endif - -#include "defines.h" -#include "globals.h" -#include "screen.h" -#include "setup.h" -#include "type.h" - -/* Needed for line calculations */ -#define SGN(x) ((x)>0 ? 1 : ((x)==0 ? 0:(-1))) -#define ABS(x) ((x)>0 ? (x) : (-x)) - -/* --- CLEAR SCREEN --- */ - -void clearscreen(int r, int g, int b) -{ -#ifndef NOOPENGL - if(use_gl) - { - glClearColor(r/256, g/256, b/256, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - } - else - { -#endif - - SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, r, g, b)); -#ifndef NOOPENGL - - } -#endif -} - -/* --- DRAWS A VERTICAL GRADIENT --- */ - -void drawgradient(Color top_clr, Color bot_clr) -{ -#ifndef NOOPENGL - if(use_gl) - { - glBegin(GL_QUADS); - glColor3ub(top_clr.red, top_clr.green, top_clr.blue); - glVertex2f(0, 0); - glVertex2f(screen->w, 0); - glColor3ub(bot_clr.red, bot_clr.green, bot_clr.blue); - glVertex2f(screen->w, screen->h); - glVertex2f(0, screen->h); - glEnd(); - } - else - { -#endif - - for(float y = 0; y < screen->h; y += 2) - fillrect(0, (int)y, screen->w, 2, - (int)(((float)(top_clr.red-bot_clr.red)/(0-screen->h)) * y + top_clr.red), - (int)(((float)(top_clr.green-bot_clr.green)/(0-screen->h)) * y + top_clr.green), - (int)(((float)(top_clr.blue-bot_clr.blue)/(0-screen->h)) * y + top_clr.blue), - 255); -/* calculates the color for each line, based in the generic equation for functions: y = mx + b */ - -#ifndef NOOPENGL - - } -#endif -} - -/** This fade shrinks to the given point */ - -#define LOOP_DELAY 20 -void shrink_fade(Point point, int fade_time) -{ -float left_inc = (float)point.x / ((float)fade_time / LOOP_DELAY); -float right_inc = ((float)screen->w - point.x) / ((float)fade_time / LOOP_DELAY); -float up_inc = (float)point.y / ((float)fade_time / LOOP_DELAY); -float down_inc = ((float)screen->h - point.y) / ((float)fade_time / LOOP_DELAY); - -float left_cor = 0, right_cor = 0, up_cor = 0, down_cor = 0; - -while(left_cor < point.x && right_cor < screen->w - point.x && - up_cor < point.y && down_cor < screen->h - point.y) - { - left_cor += left_inc; - right_cor += right_inc; - up_cor += up_inc; - down_cor += down_inc; - - fillrect(0, 0, left_cor, screen->h, 0,0,0); // left side - fillrect(screen->w - right_cor, 0, right_cor, screen->h, 0,0,0); // right side - fillrect(0, 0, screen->w, up_cor, 0,0,0); // up side - fillrect(0, screen->h - down_cor, screen->w, down_cor+1, 0,0,0); // down side - - flipscreen(); - SDL_Delay(LOOP_DELAY); - } -} - -/* 'Stolen' from the SDL documentation. - * Set the pixel at (x, y) to the given value - * NOTE: The surface must be locked before calling this! - */ -void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) -{ - int bpp = surface->format->BytesPerPixel; - /* Here p is the address to the pixel we want to set */ - Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; - - switch(bpp) - { - case 1: - *p = pixel; - break; - - case 2: - *(Uint16 *)p = pixel; - break; - - case 3: - if(SDL_BYTEORDER == SDL_BIG_ENDIAN) - { - p[0] = (pixel >> 16) & 0xff; - p[1] = (pixel >> 8) & 0xff; - p[2] = pixel & 0xff; - } - else - { - p[0] = pixel & 0xff; - p[1] = (pixel >> 8) & 0xff; - p[2] = (pixel >> 16) & 0xff; - } - break; - - case 4: - *(Uint32 *)p = pixel; - break; - } -} - -/* Draw a single pixel on the screen. */ -void drawpixel(int x, int y, Uint32 pixel) -{ - /* Lock the screen for direct access to the pixels */ - if ( SDL_MUSTLOCK(screen) ) - { - if ( SDL_LockSurface(screen) < 0 ) - { - fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); - return; - } - } - - if(!(x < 0 || y < 0 || x > screen->w || y > screen->h)) - putpixel(screen, x, y, pixel); - - if ( SDL_MUSTLOCK(screen) ) - { - SDL_UnlockSurface(screen); - } - /* Update just the part of the display that we've changed */ - SDL_UpdateRect(screen, x, y, 1, 1); -} - -void drawline(int x1, int y1, int x2, int y2, int r, int g, int b, int a) -{ -#ifndef NOOPENGL - if(use_gl) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4ub(r, g, b,a); - - glBegin(GL_LINES); - glVertex2f(x1, y1); - glVertex2f(x2, y2); - glEnd(); - glDisable(GL_BLEND); - } - else - { -#endif - - /* Basic unantialiased Bresenham line algorithm */ - int lg_delta, sh_delta, cycle, lg_step, sh_step; - Uint32 color = SDL_MapRGBA(screen->format, r, g, b, a); - - lg_delta = x2 - x1; - sh_delta = y2 - y1; - lg_step = SGN(lg_delta); - lg_delta = ABS(lg_delta); - sh_step = SGN(sh_delta); - sh_delta = ABS(sh_delta); - if (sh_delta < lg_delta) - { - cycle = lg_delta >> 1; - while (x1 != x2) - { - drawpixel(x1, y1, color); - cycle += sh_delta; - if (cycle > lg_delta) - { - cycle -= lg_delta; - y1 += sh_step; - } - x1 += lg_step; - } - drawpixel(x1, y1, color); - } - cycle = sh_delta >> 1; - while (y1 != y2) - { - drawpixel(x1, y1, color); - cycle += lg_delta; - if (cycle > sh_delta) - { - cycle -= sh_delta; - x1 += lg_step; - } - y1 += sh_step; - } - drawpixel(x1, y1, color); -#ifndef NOOPENGL - - } -#endif -} - -/* --- FILL A RECT --- */ - -void fillrect(float x, float y, float w, float h, int r, int g, int b, int a) -{ -if(w < 0) - { - x += w; - w = -w; - } -if(h < 0) - { - y += h; - h = -h; - } - -#ifndef NOOPENGL - if(use_gl) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4ub(r, g, b,a); - - glBegin(GL_POLYGON); - glVertex2f(x, y); - glVertex2f(x+w, y); - glVertex2f(x+w, y+h); - glVertex2f(x, y+h); - glEnd(); - glDisable(GL_BLEND); - } - else - { -#endif - SDL_Rect src, rect; - SDL_Surface *temp = NULL; - - rect.x = (int)x; - rect.y = (int)y; - rect.w = (int)w; - rect.h = (int)h; - - if(a != 255) - { - temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, - screen->format->Rmask, - screen->format->Gmask, - screen->format->Bmask, - screen->format->Amask); - - - src.x = 0; - src.y = 0; - src.w = rect.w; - src.h = rect.h; - - SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, r, g, b)); - - SDL_SetAlpha(temp, SDL_SRCALPHA, a); - - SDL_BlitSurface(temp,0,screen,&rect); - - SDL_FreeSurface(temp); - } - else - SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b)); - -#ifndef NOOPENGL - - } -#endif -} - - -/* --- UPDATE SCREEN --- */ - -void updatescreen(void) -{ - if(use_gl) /*clearscreen(0,0,0);*/ - SDL_GL_SwapBuffers(); - else - SDL_UpdateRect(screen, 0, 0, screen->w, screen->h); -} - -void flipscreen(void) -{ - if(use_gl) - SDL_GL_SwapBuffers(); - else - SDL_Flip(screen); -} - -void fadeout() -{ - clearscreen(0, 0, 0); - white_text->draw_align("Loading...", screen->w/2, screen->h/2, A_HMIDDLE, A_TOP); - flipscreen(); -} - -void update_rect(SDL_Surface *scr, Sint32 x, Sint32 y, Sint32 w, Sint32 h) -{ - if(!use_gl) - SDL_UpdateRect(scr, x, y, w, h); -} - diff --git a/src/screen.h b/src/screen.h deleted file mode 100644 index 466fe7ecf..000000000 --- a/src/screen.h +++ /dev/null @@ -1,76 +0,0 @@ -// $Id$ -// -// SuperTux - A Jump'n Run -// Copyright (C) 2000 Bill Kendrick -// -// 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_SCREEN_H -#define SUPERTUX_SCREEN_H - -#include -#ifndef NOOPENGL -#include -#endif -#include "texture.h" - -#define NO_UPDATE false -#define UPDATE true -#define USE_ALPHA 0 -#define IGNORE_ALPHA 1 - -struct Color -{ - Color() - : red(0), green(0), blue(0) - {} - - Color(int red_, int green_, int blue_) - : red(red_), green(green_), blue(blue_) - {} - - int red, green, blue; -}; - -struct Point -{ - Point() : x(0), y(0) {} - - Point(const Point& pos) - : x(pos.x), y(pos.y) {} - - Point& operator=(const Point& pos) - { x = pos.x; - y = pos.y; - return *this; } - - Point(int x_, int y_) - : x(x_), y(y_) {} - - int x; - int y; -}; - -void drawline(int x1, int y1, int x2, int y2, int r, int g, int b, int a); -void clearscreen(int r, int g, int b); -void drawgradient(Color top_clr, Color bot_clr); -void fillrect(float x, float y, float w, float h, int r, int g, int b, int a = 255); -void shrink_fade(Point point, int fade_time); -void updatescreen(void); -void flipscreen(void); -void update_rect(SDL_Surface *scr, Sint32 x, Sint32 y, Sint32 w, Sint32 h); -void fadeout(); - -#endif /*SUPERTUX_SCREEN_H*/ diff --git a/src/screen/drawing_context.cpp b/src/screen/drawing_context.cpp new file mode 100644 index 000000000..c01d13f82 --- /dev/null +++ b/src/screen/drawing_context.cpp @@ -0,0 +1,314 @@ +#include "drawing_context.h" + +#include +#include +#include "texture.h" +#include "globals.h" +#include "font.h" + +DrawingContext::DrawingContext() +{ +} + +DrawingContext::~DrawingContext() +{ +} + +void +DrawingContext::draw_surface(const Surface* surface, const Vector& position, + int layer) +{ + assert(surface != 0); + + DrawingRequest request; + + request.type = SURFACE; + request.layer = layer; + request.request_data = const_cast (surface); + request.pos = transform.apply(position); + + drawingrequests.push_back(request); +} + +void +DrawingContext::draw_surface_part(const Surface* surface, const Vector& source, + const Vector& size, const Vector& dest, int layer) +{ + assert(surface != 0); + + DrawingRequest request; + + request.type = SURFACE_PART; + request.layer = layer; + request.pos = transform.apply(dest); + + SurfacePartRequest* surfacepartrequest = new SurfacePartRequest(); + surfacepartrequest->size = size; + surfacepartrequest->source = source; + surfacepartrequest->surface = surface; + request.request_data = surfacepartrequest; + + drawingrequests.push_back(request); +} + +void +DrawingContext::draw_text(Font* font, const std::string& text, + const Vector& position, int layer) +{ + DrawingRequest request; + + request.type = TEXT; + request.layer = layer; + request.pos = transform.apply(position); + + TextRequest* textrequest = new TextRequest; + textrequest->font = font; + textrequest->text = text; + request.request_data = textrequest; + + drawingrequests.push_back(request); +} + +void +DrawingContext::draw_text_center(Font* font, const std::string& text, + const Vector& position, int layer) +{ + DrawingRequest request; + + request.type = TEXT; + request.layer = layer; + request.pos = transform.apply(position) + Vector(screen->w/2 - + font->get_text_width(text)/2, 0); + + TextRequest* textrequest = new TextRequest; + textrequest->font = font; + textrequest->text = text; + request.request_data = textrequest; + + drawingrequests.push_back(request); +} + +void +DrawingContext::draw_gradient(Color top, Color bottom, int layer) +{ + DrawingRequest request; + + request.type = GRADIENT; + request.layer = layer; + request.pos = Vector(0,0); + + GradientRequest* gradientrequest = new GradientRequest; + gradientrequest->top = top; + gradientrequest->bottom = bottom; + request.request_data = gradientrequest; + + drawingrequests.push_back(request); +} + +void +DrawingContext::draw_filled_rect(const Vector& topleft, const Vector& size, + Color color, int layer) +{ + DrawingRequest request; + + request.type = FILLRECT; + request.layer = layer; + request.pos = topleft; + + FillRectRequest* fillrectrequest = new FillRectRequest; + fillrectrequest->size = size; + fillrectrequest->color = color; + request.request_data = fillrectrequest; + + drawingrequests.push_back(request); +} + +void +DrawingContext::draw_surface_part(DrawingRequest& request) +{ + SurfacePartRequest* surfacepartrequest + = (SurfacePartRequest*) request.request_data; + + surfacepartrequest->surface->impl->draw_part( + surfacepartrequest->source.x, surfacepartrequest->source.y, + request.pos.x, request.pos.y, + surfacepartrequest->size.x, surfacepartrequest->size.y, 255); + + delete surfacepartrequest; +} + +void +DrawingContext::draw_gradient(DrawingRequest& request) +{ + GradientRequest* gradientrequest = (GradientRequest*) request.request_data; + const Color& top = gradientrequest->top; + const Color& bottom = gradientrequest->bottom; + +#ifndef NOOPENGL + if(use_gl) + { + glBegin(GL_QUADS); + glColor3ub(top.red, top.green, top.blue); + glVertex2f(0, 0); + glVertex2f(screen->w, 0); + glColor3ub(bottom.red, bottom.green, bottom.blue); + glVertex2f(screen->w, screen->h); + glVertex2f(0, screen->h); + glEnd(); + } + else + { +#endif + float redstep = (float(bottom.red)-float(top.red)) / float(screen->h); + float greenstep = (float(bottom.green)-float(top.green)) / float(screen->h); + float bluestep = (float(bottom.blue) - float(top.blue)) / float(screen->h); + + for(float y = 0; y < screen->h; y += 2) + fillrect(0, (int)y, screen->w, 2, + int(float(top.red) + redstep * y), + int(float(top.green) + greenstep * y), + int(float(top.blue) + bluestep * y), 255); +#ifndef NOOPENGL + + } +#endif + + delete gradientrequest; +} + +void +DrawingContext::draw_text(DrawingRequest& request) +{ + TextRequest* textrequest = (TextRequest*) request.request_data; + + textrequest->font->draw(textrequest->text, request.pos); + + delete textrequest; +} + +void +DrawingContext::draw_filled_rect(DrawingRequest& request) +{ + FillRectRequest* fillrectrequest = (FillRectRequest*) request.request_data; + + float x = request.pos.x; + float y = request.pos.y; + float w = fillrectrequest->size.x; + float h = fillrectrequest->size.y; +#ifndef NOOPENGL + if(use_gl) + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4ub(fillrectrequest->color.red, fillrectrequest->color.green, + fillrectrequest->color.blue, fillrectrequest->color.alpha); + + glBegin(GL_POLYGON); + glVertex2f(x, y); + glVertex2f(x+w, y); + glVertex2f(x+w, y+h); + glVertex2f(x, y+h); + glEnd(); + glDisable(GL_BLEND); + } + else + { +#endif + SDL_Rect src, rect; + SDL_Surface *temp = NULL; + + rect.x = (int)x; + rect.y = (int)y; + rect.w = (int)w; + rect.h = (int)h; + + if(fillrectrequest->color.alpha != 255) + { + temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, + screen->format->Rmask, + screen->format->Gmask, + screen->format->Bmask, + screen->format->Amask); + + + src.x = 0; + src.y = 0; + src.w = rect.w; + src.h = rect.h; + + SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, + fillrectrequest->color.red, fillrectrequest->color.green, + fillrectrequest->color.blue)); + + SDL_SetAlpha(temp, SDL_SRCALPHA, fillrectrequest->color.alpha); + + SDL_BlitSurface(temp,0,screen,&rect); + + SDL_FreeSurface(temp); + } + else + SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, + fillrectrequest->color.red, fillrectrequest->color.green, + fillrectrequest->color.blue)); + +#ifndef NOOPENGL + + } +#endif + + delete fillrectrequest; +} + +void +DrawingContext::do_drawing() +{ + std::sort(drawingrequests.begin(), drawingrequests.end()); + + for(DrawingRequests::iterator i = drawingrequests.begin(); + i != drawingrequests.end(); ++i) { + switch(i->type) { + case SURFACE: + { + const Surface* surface = (const Surface*) i->request_data; + surface->impl->draw(i->pos.x, i->pos.y, 255); + break; + } + case SURFACE_PART: + draw_surface_part(*i); + break; + case GRADIENT: + draw_gradient(*i); + break; + case TEXT: + draw_text(*i); + break; + case FILLRECT: + draw_filled_rect(*i); + break; + } + } + + // update screen + if(use_gl) + SDL_GL_SwapBuffers(); + else + SDL_Flip(screen); + + drawingrequests.clear(); +} + +void +DrawingContext::push_transform() +{ + transformstack.push_back(transform); +} + +void +DrawingContext::pop_transform() +{ + assert(!transformstack.empty()); + + transform = transformstack.back(); + transformstack.pop_back(); +} + diff --git a/src/screen/drawing_context.h b/src/screen/drawing_context.h new file mode 100644 index 000000000..c763cfb2b --- /dev/null +++ b/src/screen/drawing_context.h @@ -0,0 +1,151 @@ +#ifndef __DRAWINGCONTEXT_H__ +#define __DRAWINGCONTEXT_H__ + +#include +#include +#include "vector.h" +#include + +class Surface; +class Font; + +// some constants for predefined layer values +enum { + LAYER_BACKGROUND0 = -300, + LAYER_BACKGROUND1 = -200, + LAYER_BACKGROUNDTILES = -100, + LAYER_TILES = 0, + LAYER_OBJECTS = 100, + LAYER_FOREGROUNDTILES = 200, + LAYER_FOREGROUND0 = 300, + LAYER_FOREGROUND1 = 400 +}; + +class Color +{ +public: + Color() + : red(0), green(0), blue(0), alpha(0) + {} + + Color(Uint8 red_, Uint8 green_, Uint8 blue_, Uint8 alpha_ = 0) + : red(red_), green(green_), blue(blue_), alpha(alpha_) + {} + + Color(const Color& o) + : red(o.red), green(o.green), blue(o.blue), alpha(o.alpha) + { } + + Uint8 red, green, blue, alpha; +}; + +/** + * This class provides functions for drawing things on screen. It also + * maintains a stack of transforms that are applied to graphics. + */ +class DrawingContext +{ +public: + DrawingContext(); + ~DrawingContext(); + + /** Adds a drawing request for a surface into the request list */ + void draw_surface(const Surface* surface, const Vector& position, int layer); + /** Adds a drawing request for part of a surface */ + void draw_surface_part(const Surface* surface, const Vector& source, + const Vector& size, const Vector& dest, int layer); + /** draws a text */ + void draw_text(Font* font, const std::string& text, const Vector& position, + int layer); + /** draws aligned text */ + void draw_text_center(Font* font, const std::string& text, + const Vector& position, int layer); + /** draws a color gradient onto the whole screen */ + void draw_gradient(Color from, Color to, int layer); + /** fills a rectangle */ + void draw_filled_rect(const Vector& topleft, const Vector& downright, + Color color, int layer); + + /** Processes all pending drawing requests and flushes the list */ + void do_drawing(); + + const Vector& get_translation() const + { return transform.translation; } + void set_translation(const Vector& newtranslation) + { transform.translation = newtranslation; } + + void push_transform(); + void pop_transform(); + +private: + class Transform + { + public: + Vector translation; // only translation for now... + + Vector apply(const Vector& v) const + { + return v - translation; + } + }; + + /// the transform stack + std::vector transformstack; + /// the currently active transform + Transform transform; + + enum RequestType + { + SURFACE, SURFACE_PART, TEXT, GRADIENT, FILLRECT + }; + + struct SurfacePartRequest + { + const Surface* surface; + Vector source, size; + }; + + struct TextRequest + { + Font* font; + std::string text; + }; + + struct GradientRequest + { + Color top, bottom; + Vector size; + }; + + struct FillRectRequest + { + Color color; + Vector size; + }; + + struct DrawingRequest + { + int layer; + + RequestType type; + Vector pos; + + void* request_data; + + bool operator<(const DrawingRequest& other) const + { + return layer < other.layer; + } + }; + + void draw_surface_part(DrawingRequest& request); + void draw_text(DrawingRequest& request); + void draw_gradient(DrawingRequest& request); + void draw_filled_rect(DrawingRequest& request); + + typedef std::vector DrawingRequests; + DrawingRequests drawingrequests; +}; + +#endif + diff --git a/src/screen/font.cpp b/src/screen/font.cpp new file mode 100644 index 000000000..45f9e93a5 --- /dev/null +++ b/src/screen/font.cpp @@ -0,0 +1,283 @@ +// $Id$ +// +// SuperTux +// Copyright (C) 2004 Tobias Glaesser +// +// 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 +#include +#include "globals.h" +#include "defines.h" +#include "screen.h" +#include "font.h" +#include "drawing_context.h" + +Font::Font(const std::string& file, int kind_, int w_, int h_, int shadowsize_) +{ + kind = kind_; + w = w_; + h = h_; + shadowsize = shadowsize_; + + int mx, my; + SDL_Surface *conv; + int pixels; + int i; + + if(kind == TEXT_TEXT) + { + mx = 26; + my = 3; + } + else if(kind == TEXT_NUM) + { + mx = 10; + my = 1; + } + else + { + mx = 0; + my = 0; + } + + chars = new Surface(file, USE_ALPHA); + + // Load shadow font. + conv = SDL_DisplayFormatAlpha(chars->impl->get_sdl_surface()); + pixels = conv->w * conv->h; + SDL_LockSurface(conv); + for(i = 0; i < pixels; ++i) + { + Uint32 *p = (Uint32 *)conv->pixels + i; + *p = *p & conv->format->Amask; + } + SDL_UnlockSurface(conv); + SDL_SetAlpha(conv, SDL_SRCALPHA, 128); + shadow_chars = new Surface(conv, USE_ALPHA); + + SDL_FreeSurface(conv); +} + +Font::~Font() +{ + delete chars; + delete shadow_chars; +} + +float +Font::get_height() const +{ + return h; +} + +float +Font::get_text_width(const std::string& text) const +{ + return text.size() * w; +} + +void +Font::draw(const std::string& text, const Vector& pos) +{ + if(shadowsize != 0) + draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize)); + + draw_chars(chars, text, pos); +} + +void +Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos) +{ + size_t i, j; + + SurfaceImpl* impl = pchars->impl; + + int x = int(pos.x); + int y = int(pos.y); + if(kind == TEXT_TEXT) + { + for( i = 0, j = 0; i < text.size(); ++i,++j) + { + if( text[i] >= ' ' && text[i] <= '/') + impl->draw_part((int)(text[i] - ' ')*w, 0 , x+(j*w), y, w, h, 255); + else if( text[i] >= '0' && text[i] <= '?') + impl->draw_part((int)(text[i] - '0')*w, h*1, x+(j*w), y, w, h, 255); + else if ( text[i] >= '@' && text[i] <= 'O') + impl->draw_part((int)(text[i] - '@')*w, h*2, x+(j*w), y, w, h, 255); + else if ( text[i] >= 'P' && text[i] <= '_') + impl->draw_part((int)(text[i] - 'P')*w, h*3, x+(j*w), y, w, h, 255); + else if ( text[i] >= '`' && text[i] <= 'o') + impl->draw_part((int)(text[i] - '`')*w, h*4, x+(j*w), y, w, h, 255); + else if ( text[i] >= 'p' && text[i] <= '~') + impl->draw_part((int)(text[i] - 'p')*w, h*5, x+(j*w), y, w, h, 255); + else if ( text[i] == '\n') + { + y += h + 2; + j = 0; + } + } + } + else if(kind == TEXT_NUM) + { + for( i = 0, j = 0; i < text.size(); ++i, ++j) + { + if ( text[i] >= '0' && text[i] <= '9') + impl->draw_part((int)(text[i] - '0')*w, 0, x+(j*w), y, w, h, 255); + else if ( text[i] == '\n') + { + y += h + 2; + j = 0; + } + } + } +} + +/* --- SCROLL TEXT FUNCTION --- */ + +#define MAX_VEL 10 +#define SPEED_INC 0.01 +#define SCROLL 60 +#define ITEMS_SPACE 4 + +void display_text_file(const std::string& file, const std::string& surface, float scroll_speed) +{ + Surface* sur = new Surface(datadir + surface, IGNORE_ALPHA); + display_text_file(file, sur, scroll_speed); + delete sur; +} + +void display_text_file(const std::string& file, Surface* surface, float scroll_speed) +{ + int done; + float scroll; + float speed; + FILE* fi; + char temp[1024]; + std::vector names; + char filename[1024]; + + sprintf(filename,"%s/%s", datadir.c_str(), file.c_str()); + if((fi = fopen(filename,"r")) != NULL) + { + while(fgets(temp, sizeof(temp), fi) != NULL) + { + temp[strlen(temp)-1]='\0'; + names.push_back(temp); + } + fclose(fi); + } + else + { + names.push_back("File was not found!"); + names.push_back(filename); + names.push_back("Shame on the guy, who"); + names.push_back("forgot to include it"); + names.push_back("in your SuperTux distribution."); + } + + scroll = 0; + speed = scroll_speed / 50; + done = 0; + + DrawingContext context; + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + + Uint32 lastticks = SDL_GetTicks(); + while(!done) + { + /* in case of input, exit */ + SDL_Event event; + while(SDL_PollEvent(&event)) + switch(event.type) + { + case SDL_KEYDOWN: + switch(event.key.keysym.sym) + { + case SDLK_UP: + speed -= SPEED_INC; + break; + case SDLK_DOWN: + speed += SPEED_INC; + break; + case SDLK_SPACE: + case SDLK_RETURN: + if(speed >= 0) + scroll += SCROLL; + break; + case SDLK_ESCAPE: + done = 1; + break; + default: + break; + } + break; + case SDL_QUIT: + done = 1; + break; + default: + break; + } + + if(speed > MAX_VEL) + speed = MAX_VEL; + else if(speed < -MAX_VEL) + speed = -MAX_VEL; + + /* draw the credits */ + context.draw_surface(surface, Vector(0,0), 0); + + float y = 0; + for(size_t i = 0; i < names.size(); i++) { + if(names[i].size() == 0) { + y += white_text->get_height() + ITEMS_SPACE; + continue; + } + + Font* font = 0; + switch(names[i][0]) + { + case ' ': font = white_small_text; break; + case '\t': font = white_text; break; + case '-': font = white_big_text; break; + case '*': font = blue_text; break; + default: font = blue_text; break; + } + + context.draw_text_center(font, + names[i].substr(1, names[i].size()-1), + Vector(0, screen->h + y - scroll), LAYER_FOREGROUND1); + y += font->get_height() + ITEMS_SPACE; + } + + context.do_drawing(); + + if(screen->h+y-scroll < 0 && 20+screen->h+y-scroll < 0) + done = 1; + + Uint32 ticks = SDL_GetTicks(); + scroll += speed * (ticks - lastticks); + lastticks = ticks; + if(scroll < 0) + scroll = 0; + + SDL_Delay(10); + } + + SDL_EnableKeyRepeat(0, 0); // disables key repeating + Menu::set_current(main_menu); +} + diff --git a/src/screen/font.h b/src/screen/font.h new file mode 100644 index 000000000..7f398bc82 --- /dev/null +++ b/src/screen/font.h @@ -0,0 +1,63 @@ +// $Id$ +// +// SuperTux +// Copyright (C) 2004 Tobias Glaesser +// +// 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_TEXT_H +#define SUPERTUX_TEXT_H + +#include +#include "texture.h" +#include "vector.h" + +void display_text_file(const std::string& file, const std::string& surface, float scroll_speed); +void display_text_file(const std::string& file, Surface* surface, float scroll_speed); + +/* Kinds of texts. */ +enum { + TEXT_TEXT, + TEXT_NUM +}; + +/* Text type */ +class Font +{ +public: + Surface* chars; + Surface* shadow_chars; + int kind; + int w; + int h; + int shadowsize; +public: + Font(const std::string& file, int kind, int w, int h, int shadowsize = 2); + ~Font(); + + float get_height() const; + float get_text_width(const std::string& text) const; + +private: + friend class DrawingContext; + + void draw(const std::string& text, const Vector& pos); + void draw_chars(Surface* pchars, const std::string& text, + const Vector& position); +}; + +#endif /*SUPERTUX_TEXT_H*/ + diff --git a/src/screen/screen.cpp b/src/screen/screen.cpp new file mode 100644 index 000000000..a9cf2bced --- /dev/null +++ b/src/screen/screen.cpp @@ -0,0 +1,329 @@ +// $Id$ +// +// SuperTux - A Jump'n Run +// Copyright (C) 2000 Bill Kendrick +// +// 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 +#include +#include +#include +#include +#include +#include +#include + +#ifndef WIN32 +#include +#include +#endif + +#include "defines.h" +#include "globals.h" +#include "screen.h" +#include "setup.h" +#include "drawing_context.h" +#include "type.h" + +/* Needed for line calculations */ +#define SGN(x) ((x)>0 ? 1 : ((x)==0 ? 0:(-1))) +#define ABS(x) ((x)>0 ? (x) : (-x)) + +/* --- FADE IN --- */ + +/** Fades the given surface into a black one. If fade_out is true, it will fade out, else +it will fade in */ + +#if 0 +void fade(Surface *surface, int seconds, bool fade_out); + +void fade(const std::string& surface, int seconds, bool fade_out) +{ +Surface* sur = new Surface(datadir + surface, IGNORE_ALPHA); +fade(sur, seconds, fade_out); +delete sur; +} + +void fade(Surface *surface, int seconds, bool fade_out) +{ +float alpha; +if (fade_out) + alpha = 0; +else + alpha = 255; + + int cur_time, old_time; + cur_time = SDL_GetTicks(); + + while(alpha >= 0 && alpha < 256) + { + surface->draw(0,0,(int)alpha); + flipscreen(); + + old_time = cur_time; + cur_time = SDL_GetTicks(); + + /* Calculate the next alpha value */ + float calc = (float) ((cur_time - old_time) / seconds); + if(fade_out) + alpha += 255 * calc; + else + alpha -= 255 * calc; + } +} +#endif + +/* 'Stolen' from the SDL documentation. + * Set the pixel at (x, y) to the given value + * NOTE: The surface must be locked before calling this! + */ +void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) +{ + int bpp = surface->format->BytesPerPixel; + /* Here p is the address to the pixel we want to set */ + Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; + + switch(bpp) + { + case 1: + *p = pixel; + break; + + case 2: + *(Uint16 *)p = pixel; + break; + + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) + { + p[0] = (pixel >> 16) & 0xff; + p[1] = (pixel >> 8) & 0xff; + p[2] = pixel & 0xff; + } + else + { + p[0] = pixel & 0xff; + p[1] = (pixel >> 8) & 0xff; + p[2] = (pixel >> 16) & 0xff; + } + break; + + case 4: + *(Uint32 *)p = pixel; + break; + } +} + +/* Draw a single pixel on the screen. */ +void drawpixel(int x, int y, Uint32 pixel) +{ + /* Lock the screen for direct access to the pixels */ + if ( SDL_MUSTLOCK(screen) ) + { + if ( SDL_LockSurface(screen) < 0 ) + { + fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); + return; + } + } + + if(!(x < 0 || y < 0 || x > screen->w || y > screen->h)) + putpixel(screen, x, y, pixel); + + if ( SDL_MUSTLOCK(screen) ) + { + SDL_UnlockSurface(screen); + } + /* Update just the part of the display that we've changed */ + SDL_UpdateRect(screen, x, y, 1, 1); +} + +void drawline(int x1, int y1, int x2, int y2, int r, int g, int b, int a) +{ +#ifndef NOOPENGL + if(use_gl) + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4ub(r, g, b,a); + + glBegin(GL_LINES); + glVertex2f(x1, y1); + glVertex2f(x2, y2); + glEnd(); + glDisable(GL_BLEND); + } + else + { +#endif + + /* Basic unantialiased Bresenham line algorithm */ + int lg_delta, sh_delta, cycle, lg_step, sh_step; + Uint32 color = SDL_MapRGBA(screen->format, r, g, b, a); + + lg_delta = x2 - x1; + sh_delta = y2 - y1; + lg_step = SGN(lg_delta); + lg_delta = ABS(lg_delta); + sh_step = SGN(sh_delta); + sh_delta = ABS(sh_delta); + if (sh_delta < lg_delta) + { + cycle = lg_delta >> 1; + while (x1 != x2) + { + drawpixel(x1, y1, color); + cycle += sh_delta; + if (cycle > lg_delta) + { + cycle -= lg_delta; + y1 += sh_step; + } + x1 += lg_step; + } + drawpixel(x1, y1, color); + } + cycle = sh_delta >> 1; + while (y1 != y2) + { + drawpixel(x1, y1, color); + cycle += lg_delta; + if (cycle > sh_delta) + { + cycle -= sh_delta; + x1 += lg_step; + } + y1 += sh_step; + } + drawpixel(x1, y1, color); +#ifndef NOOPENGL + + } +#endif +} + +/* --- FILL A RECT --- */ + +void fillrect(float x, float y, float w, float h, int r, int g, int b, int a) +{ +if(w < 0) + { + x += w; + w = -w; + } +if(h < 0) + { + y += h; + h = -h; + } + +#ifndef NOOPENGL + if(use_gl) + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4ub(r, g, b,a); + + glBegin(GL_POLYGON); + glVertex2f(x, y); + glVertex2f(x+w, y); + glVertex2f(x+w, y+h); + glVertex2f(x, y+h); + glEnd(); + glDisable(GL_BLEND); + } + else + { +#endif + SDL_Rect src, rect; + SDL_Surface *temp = NULL; + + rect.x = (int)x; + rect.y = (int)y; + rect.w = (int)w; + rect.h = (int)h; + + if(a != 255) + { + temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, + screen->format->Rmask, + screen->format->Gmask, + screen->format->Bmask, + screen->format->Amask); + + + src.x = 0; + src.y = 0; + src.w = rect.w; + src.h = rect.h; + + SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, r, g, b)); + + SDL_SetAlpha(temp, SDL_SRCALPHA, a); + + SDL_BlitSurface(temp,0,screen,&rect); + + SDL_FreeSurface(temp); + } + else + SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b)); + +#ifndef NOOPENGL + + } +#endif +} + + +void fadeout() +{ + fillrect(0, 0, screen->w, screen->h, 0, 0, 0, 255); + + DrawingContext context; + context.draw_text_center(white_text, "Loading...", + Vector(0, screen->h/2), LAYER_FOREGROUND1); + context.do_drawing(); +} + +#define LOOP_DELAY 20.0 +void shrink_fade(const Vector& point, float fade_time) +{ + float left_inc = point.x / (fade_time / LOOP_DELAY); + float right_inc = (screen->w - point.x) / (fade_time / LOOP_DELAY); + float up_inc = point.y / (fade_time / LOOP_DELAY); + float down_inc = (screen->h - point.y) / (fade_time / LOOP_DELAY); + + float left_cor = 0, right_cor = 0, up_cor = 0, down_cor = 0; + + while(left_cor < point.x && right_cor < screen->w - point.x && + up_cor < point.y && down_cor < screen->h - point.y) + { + left_cor += left_inc; + right_cor += right_inc; + up_cor += up_inc; + down_cor += down_inc; + + fillrect(0, 0, left_cor, screen->h, 0,0,0); // left side + fillrect(screen->w - right_cor, 0, right_cor, screen->h, 0,0,0); // right side + fillrect(0, 0, screen->w, up_cor, 0,0,0); // up side + fillrect(0, screen->h - down_cor, screen->w, down_cor+1, 0,0,0); // down side + DrawingContext context; // ugly... + context.do_drawing(); + + SDL_Delay(int(LOOP_DELAY)); + } +} + diff --git a/src/screen/screen.h b/src/screen/screen.h new file mode 100644 index 000000000..64c42c2aa --- /dev/null +++ b/src/screen/screen.h @@ -0,0 +1,45 @@ +// $Id$ +// +// SuperTux - A Jump'n Run +// Copyright (C) 2000 Bill Kendrick +// +// 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_SCREEN_H +#define SUPERTUX_SCREEN_H + +#include +#ifndef NOOPENGL +#include +#endif +#include "texture.h" + +class Vector; + +#define NO_UPDATE false +#define UPDATE true +#define USE_ALPHA 0 +#define IGNORE_ALPHA 1 + +void drawline(int x1, int y1, int x2, int y2, int r, int g, int b, int a); +void fillrect(float x, float y, float w, float h, int r, int g, int b, + int a = 255); +void shrink_fade(const Vector& point, float fade_time); +//void black_fade(Surface* surface, int seconds, bool fade_out); +void fade(const std::string& surface, int seconds, bool fade_out); +void update_rect(SDL_Surface *scr, Sint32 x, Sint32 y, Sint32 w, Sint32 h); +void fadeout(); + +#endif /*SUPERTUX_SCREEN_H*/ diff --git a/src/screen/texture.cpp b/src/screen/texture.cpp new file mode 100644 index 000000000..681329673 --- /dev/null +++ b/src/screen/texture.cpp @@ -0,0 +1,695 @@ +// $Id$ +// +// SuperTux +// Copyright (C) 2004 Tobias Glaesser +// +// 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 +#include +#include +#include "SDL.h" +#include "SDL_image.h" +#include "texture.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() +{ + 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); + } + 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); + } +#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); +} + +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::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; +} + +//--------------------------------------------------------------------------- + +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() +{ + 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); + } + + 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, GL_RGB10_A2, 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) +{ + float pw = power_of_two(w); + float ph = power_of_two(h); + + 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); + 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) +{ + 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(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); + 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; +} + +int +SurfaceSDL::draw(float x, float y, Uint8 alpha) +{ + SDL_Rect dest; + + dest.x = (int)x; + dest.y = (int)y; + dest.w = w; + dest.h = h; + + 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) +{ + 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(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/texture.h b/src/screen/texture.h new file mode 100644 index 000000000..3f65a8864 --- /dev/null +++ b/src/screen/texture.h @@ -0,0 +1,160 @@ +// $Id$ +// +// SuperTux +// Copyright (C) 2004 Tobias Glaesser +// +// 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 +#include +#ifndef NOOPENGL +#include +#endif + +#include +#include "screen.h" +#include "vector.h" + +SDL_Surface* sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf, int use_alpha); + +class SurfaceImpl; +class SurfaceSDL; +class SurfaceOpenGL; +class DrawingContext; + +/** This class holds all the data necessary to construct a surface */ +class SurfaceData +{ +public: + enum ConstructorType { LOAD, LOAD_PART, SURFACE }; + ConstructorType type; + SDL_Surface* surface; + std::string file; + int use_alpha; + int x; + int y; + int w; + int h; + + 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(); + + 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 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(); + + /** 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) = 0; + virtual int draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha) = 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); + virtual ~SurfaceSDL(); + + int draw(float x, float y, Uint8 alpha); + int draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha); +#if 0 + int draw_stretched(float x, float y, int w, int h, Uint8 alpha); +#endif +}; + +#ifndef NOOPENGL +class SurfaceOpenGL : public SurfaceImpl +{ +public: + unsigned 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); + virtual ~SurfaceOpenGL(); + + int draw(float x, float y, Uint8 alpha); + int draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha); +#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: */ diff --git a/src/setup.cpp b/src/setup.cpp index 4b9d28302..98cc84cf7 100644 --- a/src/setup.cpp +++ b/src/setup.cpp @@ -42,8 +42,8 @@ #include "defines.h" #include "globals.h" #include "setup.h" -#include "screen.h" -#include "texture.h" +#include "screen/screen.h" +#include "screen/texture.h" #include "menu.h" #include "gameloop.h" #include "configfile.h" @@ -505,7 +505,7 @@ bool process_load_game_menu() draw_intro(); } - shrink_fade(Point((screen->w/2),(screen->h/2)), 1000); + // shrink_fade(Point((screen->w/2),(screen->h/2)), 1000); fadeout(); WorldMapNS::WorldMap worldmap; @@ -582,16 +582,19 @@ void st_general_setup(void) /* Load global images: */ - black_text = new Text(datadir + "/images/status/letters-black.png", TEXT_TEXT, 16,18); - gold_text = new Text(datadir + "/images/status/letters-gold.png", TEXT_TEXT, 16,18); - silver_text = new Text(datadir + "/images/status/letters-silver.png", TEXT_TEXT, 16,18); - blue_text = new Text(datadir + "/images/status/letters-blue.png", TEXT_TEXT, 16,18); - red_text = new Text(datadir + "/images/status/letters-red.png", TEXT_TEXT, 16,18); - green_text = new Text(datadir + "/images/status/letters-green.png", TEXT_TEXT, 16,18); - white_text = new Text(datadir + "/images/status/letters-white.png", TEXT_TEXT, 16,18); - white_small_text = new Text(datadir + "/images/status/letters-white-small.png", TEXT_TEXT, 8,9); - white_big_text = new Text(datadir + "/images/status/letters-white-big.png", TEXT_TEXT, 20,22); - yellow_nums = new Text(datadir + "/images/status/numbers.png", TEXT_NUM, 32,32); + black_text = new Font(datadir + "/images/status/letters-black.png", TEXT_TEXT, 16,18); + gold_text = new Font(datadir + "/images/status/letters-gold.png", TEXT_TEXT, 16,18); + silver_text = new Font(datadir + "/images/status/letters-silver.png", TEXT_TEXT, 16,18); + blue_text = new Font(datadir + "/images/status/letters-blue.png", TEXT_TEXT, + 16,18, 3); + red_text = new Font(datadir + "/images/status/letters-red.png", TEXT_TEXT, 16,18); + green_text = new Font(datadir + "/images/status/letters-green.png", TEXT_TEXT, 16,18); + white_text = new Font(datadir + "/images/status/letters-white.png", TEXT_TEXT, 16,18); + white_small_text = new Font(datadir + + "/images/status/letters-white-small.png", TEXT_TEXT, 8,9, 1); + white_big_text = new Font(datadir + "/images/status/letters-white-big.png", + TEXT_TEXT, 20,22, 3); + yellow_nums = new Font(datadir + "/images/status/numbers.png", TEXT_NUM, 32,32); /* Load GUI/menu images: */ checkbox = new Surface(datadir + "/images/status/checkbox.png", USE_ALPHA); diff --git a/src/special.cpp b/src/special.cpp index adfebe0f6..8dd89ae61 100644 --- a/src/special.cpp +++ b/src/special.cpp @@ -22,8 +22,9 @@ #include "SDL.h" #include "defines.h" #include "special.h" +#include "camera.h" #include "gameloop.h" -#include "screen.h" +#include "screen/screen.h" #include "sound.h" #include "scene.h" #include "globals.h" @@ -44,11 +45,8 @@ Sprite* img_1up; #define BULLET_STARTING_YM 0 #define BULLET_XM 6 -Bullet::Bullet(DisplayManager& display_manager, const Vector& pos, float xm, - int dir, int kind_) +Bullet::Bullet(const Vector& pos, float xm, int dir, int kind_) { - display_manager.add_drawable(this, LAYER_OBJECTS); - life_count = 3; base.width = 4; base.height = 4; @@ -112,12 +110,11 @@ Bullet::action(float elapsed_time) } void -Bullet::draw(Camera& viewport, int ) +Bullet::draw(DrawingContext& context) { - if(kind == FIRE_BULLET) - img_firebullet->draw(viewport.world2screen(Vector(base.x, base.y))); - else if(kind == ICE_BULLET) - img_icebullet->draw(viewport.world2screen(Vector(base.x, base.y))); + Sprite* sprite = kind == FIRE_BULLET ? img_firebullet : img_icebullet; + + sprite->draw(context, Vector(base.x, base.y), LAYER_OBJECTS); } void @@ -136,11 +133,8 @@ Bullet::collision(int c_object) //--------------------------------------------------------------------------- -Upgrade::Upgrade(DisplayManager& display_manager, const Vector& pos, - Direction dir_, UpgradeKind kind_) +Upgrade::Upgrade(const Vector& pos, Direction dir_, UpgradeKind kind_) { - display_manager.add_drawable(this, LAYER_OBJECTS); - kind = kind_; dir = dir_; @@ -243,53 +237,24 @@ Upgrade::action(float elapsed_time) } void -Upgrade::draw(Camera& viewport, int) +Upgrade::draw(DrawingContext& context) { - SDL_Rect dest; - - if (base.height < 32) - { - /* Rising up... */ - - dest.x = (int)(base.x - viewport.get_translation().x); - dest.y = (int)(base.y + 32 - base.height - viewport.get_translation().y); - dest.w = 32; - dest.h = (int)base.height; + Sprite* sprite; + switch(kind) { + case UPGRADE_GROWUP: sprite = img_growup; break; + case UPGRADE_ICEFLOWER: sprite = img_iceflower; break; + case UPGRADE_FIREFLOWER: sprite = img_fireflower; break; + case UPGRADE_HERRING: sprite = img_star; break; + case UPGRADE_1UP: sprite = img_1up; break; + default: + assert(!"wrong type in Powerup::draw()"); + } - if (kind == UPGRADE_GROWUP) - img_growup->draw_part(0,0,dest.x,dest.y,dest.w,dest.h); - else if (kind == UPGRADE_ICEFLOWER) - img_iceflower->draw_part(0,0,dest.x,dest.y,dest.w,dest.h); - else if (kind == UPGRADE_FIREFLOWER) - img_fireflower->draw_part(0,0,dest.x,dest.y,dest.w,dest.h); - else if (kind == UPGRADE_HERRING) - img_star->draw_part(0,0,dest.x,dest.y,dest.w,dest.h); - else if (kind == UPGRADE_1UP) - img_1up->draw_part( 0, 0, dest.x, dest.y, dest.w, dest.h); - } + if(base.height < 32) // still raising up? + sprite->draw(context, Vector(base.x, base.y + (32 - base.height)), + LAYER_TILES - 10); else - { - if (kind == UPGRADE_GROWUP) - { - img_growup->draw(viewport.world2screen(Vector(base.x, base.y))); - } - else if (kind == UPGRADE_ICEFLOWER) - { - img_iceflower->draw(viewport.world2screen(Vector(base.x, base.y))); - } - else if (kind == UPGRADE_FIREFLOWER) - { - img_fireflower->draw(viewport.world2screen(Vector(base.x, base.y))); - } - else if (kind == UPGRADE_HERRING) - { - img_star->draw(viewport.world2screen(Vector(base.x, base.y))); - } - else if (kind == UPGRADE_1UP) - { - img_1up->draw(viewport.world2screen(Vector(base.x, base.y))); - } - } + sprite->draw(context, Vector(base.x, base.y), LAYER_OBJECTS); } void diff --git a/src/special.h b/src/special.h index 304d20907..550e2a424 100644 --- a/src/special.h +++ b/src/special.h @@ -23,7 +23,7 @@ #include #include "bitmask.h" #include "type.h" -#include "texture.h" +#include "screen/texture.h" #include "collision.h" #include "player.h" #include "physic.h" @@ -41,19 +41,18 @@ enum UpgradeKind { void load_special_gfx(); void free_special_gfx(); -class Upgrade : public MovingObject, public Drawable +class Upgrade : public MovingObject { public: UpgradeKind kind; Direction dir; Physic physic; - Upgrade(DisplayManager& display_manager, const Vector& pos, Direction dir, - UpgradeKind kind); + Upgrade(const Vector& pos, Direction dir, UpgradeKind kind); virtual ~Upgrade(); virtual void action(float frame_ratio); - virtual void draw(Camera& viewport, int layer); + virtual void draw(DrawingContext& context); virtual void collision(const MovingObject& other, int); void collision(void* p_c_object, int c_object, CollisionType type); @@ -67,14 +66,14 @@ enum BulletsKind { ICE_BULLET }; -class Bullet : public MovingObject, public Drawable +class Bullet : public MovingObject { public: - Bullet(DisplayManager& manager, const Vector& pos, float xm, int dir, + Bullet(const Vector& pos, float xm, int dir, int kind); virtual void action(float frame_ratio); - virtual void draw(Camera& viewport, int layer); + virtual void draw(DrawingContext& context); void collision(int c_object); virtual void collision(const MovingObject& other_object, int type); diff --git a/src/sprite.cpp b/src/sprite.cpp index f5f1f6570..c4d552fd5 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -22,6 +22,7 @@ #include "globals.h" #include "sprite.h" #include "setup.h" +#include "screen/drawing_context.h" Sprite::Sprite(lisp_object_t* cur) { @@ -73,22 +74,29 @@ Sprite::update(float /*delta*/) } void -Sprite::draw(float x, float y, int special_drawing) +Sprite::draw(DrawingContext& context, const Vector& pos, int layer, + int special_drawing) { time = SDL_GetTicks(); unsigned int frame = get_current_frame(); if (frame < surfaces.size()) - { + { + Surface* surface = surfaces[frame]; + +#if 0 // TODO if(special_drawing == SD_SEMI_TRANSPARENT) surfaces[frame]->draw(x - x_hotspot, y - y_hotspot, 128); if(special_drawing == SD_VERTICAL_FLIP) surfaces[frame]->draw(x - x_hotspot, y - y_hotspot, 255, true); else surfaces[frame]->draw(x - x_hotspot, y - y_hotspot); - } +#endif + context.draw_surface(surface, pos - Vector(x_hotspot, y_hotspot), layer); + } } +#if 0 void Sprite::draw_part(float sx, float sy, float x, float y, float w, float h) { @@ -98,6 +106,7 @@ Sprite::draw_part(float sx, float sy, float x, float y, float w, float h) if (frame < surfaces.size()) surfaces[frame]->draw_part(sx, sy, x - x_hotspot, y - y_hotspot, w, h); } +#endif void Sprite::reset() diff --git a/src/sprite.h b/src/sprite.h index 2a4acf355..1c5361806 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -23,7 +23,7 @@ #include #include #include "lispreader.h" -#include "texture.h" +#include "screen/texture.h" #include "vector.h" enum SpecialDrawing { SD_NONE, SD_VERTICAL_FLIP, SD_SEMI_TRANSPARENT }; @@ -58,16 +58,13 @@ class Sprite /** Update the sprite and process to the next frame */ void update(float delta); - void draw(float x, float y, int special_drawing = SD_NONE); - void draw_part(float sx, float sy, float x, float y, float w, float h); + void draw(DrawingContext& context, const Vector& pos, int layer, + int special_drawing = SD_NONE); int get_current_frame() const; float get_fps() { return fps; } ; int get_frames() { return surfaces.size(); } ; - void draw(const Vector& pos, int special_drawing = SD_NONE) - { draw(pos.x, pos.y, special_drawing); } - std::string get_name() const { return name; } int get_width() const; int get_height() const; diff --git a/src/supertux.cpp b/src/supertux.cpp index 8cbc3bee6..6d17be697 100644 --- a/src/supertux.cpp +++ b/src/supertux.cpp @@ -32,10 +32,10 @@ #include "title.h" #include "gameloop.h" #include "leveleditor.h" -#include "screen.h" +#include "screen/screen.h" #include "worldmap.h" #include "resources.h" -#include "texture.h" +#include "screen/texture.h" #include "tile.h" int main(int argc, char * argv[]) @@ -53,7 +53,8 @@ int main(int argc, char * argv[]) if (launch_leveleditor_mode && level_startup_file) { - leveleditor(level_startup_file); + // TODO + // leveleditor(level_startup_file); } else if (level_startup_file) { @@ -65,8 +66,8 @@ int main(int argc, char * argv[]) title(); } - clearscreen(0, 0, 0); - updatescreen(); + SDL_FillRect(screen, 0, 0); + SDL_Flip(screen); unloadshared(); st_general_free(); diff --git a/src/text.cpp b/src/text.cpp deleted file mode 100644 index 6e66f3dc5..000000000 --- a/src/text.cpp +++ /dev/null @@ -1,370 +0,0 @@ -// $Id$ -// -// SuperTux -// Copyright (C) 2004 Tobias Glaesser -// -// 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 -#include -#include "globals.h" -#include "defines.h" -#include "screen.h" -#include "text.h" - -Text::Text(const std::string& file, int kind_, int w_, int h_) -{ - kind = kind_; - w = w_; - h = h_; - - int mx, my; - SDL_Surface *conv; - int pixels; - int i; - - if(kind == TEXT_TEXT) - { - mx = 26; - my = 3; - } - else if(kind == TEXT_NUM) - { - mx = 10; - my = 1; - } - else - { - mx = 0; - my = 0; - } - - chars = new Surface(file, USE_ALPHA); - - // Load shadow font. - conv = SDL_DisplayFormatAlpha(chars->impl->get_sdl_surface()); - pixels = conv->w * conv->h; - SDL_LockSurface(conv); - for(i = 0; i < pixels; ++i) - { - Uint32 *p = (Uint32 *)conv->pixels + i; - *p = *p & conv->format->Amask; - } - SDL_UnlockSurface(conv); - SDL_SetAlpha(conv, SDL_SRCALPHA, 128); - shadow_chars = new Surface(conv, USE_ALPHA); - - SDL_FreeSurface(conv); -} - -Text::~Text() -{ - delete chars; - delete shadow_chars; -} - -void -Text::draw(const char* text, int x, int y, int shadowsize, int update) -{ - if(text != NULL) - { - if(shadowsize != 0) - draw_chars(shadow_chars, text,x+shadowsize,y+shadowsize, update); - - draw_chars(chars, text,x,y, update); - } -} - -void -Text::draw_chars(Surface* pchars,const char* text, int x, int y, int update) -{ - int i,j,len; - - len = strlen(text); - int w = this->w; - int h = this->h; - - if(kind == TEXT_TEXT) - { - for( i = 0, j = 0; i < len; ++i,++j) - { - if( text[i] >= ' ' && text[i] <= '/') - pchars->draw_part((int)(text[i] - ' ')*w, 0 , x+(j*w), y, w, h, 255, update); - else if( text[i] >= '0' && text[i] <= '?') - pchars->draw_part((int)(text[i] - '0')*w, h*1, x+(j*w), y, w, h, 255, update); - else if ( text[i] >= '@' && text[i] <= 'O') - pchars->draw_part((int)(text[i] - '@')*w, h*2, x+(j*w), y, w, h, 255, update); - else if ( text[i] >= 'P' && text[i] <= '_') - pchars->draw_part((int)(text[i] - 'P')*w, h*3, x+(j*w), y, w, h, 255, update); - else if ( text[i] >= '`' && text[i] <= 'o') - pchars->draw_part((int)(text[i] - '`')*w, h*4, x+(j*w), y, w, h, 255, update); - else if ( text[i] >= 'p' && text[i] <= '~') - pchars->draw_part((int)(text[i] - 'p')*w, h*5, x+(j*w), y, w, h, 255, update); - else if ( text[i] == '\n') - { - y += h + 2; - j = 0; - } - } - } - else if(kind == TEXT_NUM) - { - for( i = 0, j = 0; i < len; ++i, ++j) - { - if ( text[i] >= '0' && text[i] <= '9') - pchars->draw_part((int)(text[i] - '0')*w, 0, x+(j*w), y, w, h, 255, update); - else if ( text[i] == '\n') - { - y += h + 2; - j = 0; - } - } - } -} - -void -Text::draw_align(const char* text, int x, int y, - TextHAlign halign, TextVAlign valign, int shadowsize, int update) -{ - if(text != NULL) - { - switch (halign) - { - case A_RIGHT: - x += -(strlen(text)*w); - break; - case A_HMIDDLE: - x += -((strlen(text)*w)/2); - break; - case A_LEFT: - // default - break; - } - - switch (valign) - { - case A_BOTTOM: - y -= h; - break; - - case A_VMIDDLE: - y -= h/2; - - case A_TOP: - // default - break; - } - - draw(text, x, y, shadowsize, update); - } -} - -void -Text::drawf(const char* text, int x, int y, - TextHAlign halign, TextVAlign valign, int shadowsize, int update) -{ - if(text != NULL) - { - if(halign == A_RIGHT) /* FIXME: this doesn't work correctly for strings with newlines.*/ - x += screen->w - (strlen(text)*w); - else if(halign == A_HMIDDLE) - x += screen->w/2 - ((strlen(text)*w)/2); - - if(valign == A_BOTTOM) - y += screen->h - h; - else if(valign == A_VMIDDLE) - y += screen->h/2 - h/2; - - draw(text,x,y,shadowsize, update); - } -} - -/* --- ERASE TEXT: --- */ - -void -Text::erasetext(const char * text, int x, int y, Surface * ptexture, int update, int shadowsize) -{ - SDL_Rect dest; - - dest.x = x; - dest.y = y; - dest.w = strlen(text) * w + shadowsize; - dest.h = h; - - if (dest.w > screen->w) - dest.w = screen->w; - - ptexture->draw_part(dest.x,dest.y,dest.x,dest.y,dest.w,dest.h, 255, update); - - if (update == UPDATE) - update_rect(screen, dest.x, dest.y, dest.w, dest.h); -} - - -/* --- ERASE CENTERED TEXT: --- */ - -void -Text::erasecenteredtext(const char * text, int y, Surface * ptexture, int update, int shadowsize) -{ - erasetext(text, screen->w / 2 - (strlen(text) * 8), y, ptexture, update, shadowsize); -} - - -/* --- SCROLL TEXT FUNCTION --- */ - -#define MAX_VEL 10 -#define SPEED_INC 0.01 -#define SCROLL 60 -#define ITEMS_SPACE 4 - -void display_text_file(const std::string& file, const std::string& surface, float scroll_speed) -{ - Surface* sur = new Surface(datadir + surface, IGNORE_ALPHA); - display_text_file(file, sur, scroll_speed); - delete sur; -} - -void display_text_file(const std::string& file, Surface* surface, float scroll_speed) -{ - int done; - float scroll; - float speed; - int y; - int length; - FILE* fi; - char temp[1024]; - string_list_type names; - char filename[1024]; - string_list_init(&names); - sprintf(filename,"%s/%s", datadir.c_str(), file.c_str()); - if((fi = fopen(filename,"r")) != NULL) - { - while(fgets(temp, sizeof(temp), fi) != NULL) - { - temp[strlen(temp)-1]='\0'; - string_list_add_item(&names,temp); - } - fclose(fi); - } - else - { - string_list_add_item(&names,"File was not found!"); - string_list_add_item(&names,filename); - string_list_add_item(&names,"Shame on the guy, who"); - string_list_add_item(&names,"forgot to include it"); - string_list_add_item(&names,"in your SuperTux distribution."); - } - - - scroll = 0; - speed = scroll_speed / 50; - done = 0; - - length = names.num_items; - - SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); - - Uint32 lastticks = SDL_GetTicks(); - while(done == 0) - { - /* in case of input, exit */ - SDL_Event event; - while(SDL_PollEvent(&event)) - switch(event.type) - { - case SDL_KEYDOWN: - switch(event.key.keysym.sym) - { - case SDLK_UP: - speed -= SPEED_INC; - break; - case SDLK_DOWN: - speed += SPEED_INC; - break; - case SDLK_SPACE: - case SDLK_RETURN: - if(speed >= 0) - scroll += SCROLL; - break; - case SDLK_ESCAPE: - done = 1; - break; - default: - break; - } - break; - case SDL_QUIT: - done = 1; - break; - default: - break; - } - - if(speed > MAX_VEL) - speed = MAX_VEL; - else if(speed < -MAX_VEL) - speed = -MAX_VEL; - - /* draw the credits */ - surface->draw_bg(); - - y = 0; - for(int i = 0; i < length; i++) - { - switch(names.item[i][0]) - { - case ' ': - white_small_text->drawf(names.item[i]+1, 0, screen->h+y-int(scroll), - A_HMIDDLE, A_TOP, 1); - y += white_small_text->h+ITEMS_SPACE; - break; - case ' ': - white_text->drawf(names.item[i]+1, 0, screen->h+y-int(scroll), - A_HMIDDLE, A_TOP, 1); - y += white_text->h+ITEMS_SPACE; - break; - case '-': - white_big_text->drawf(names.item[i]+1, 0, screen->h+y-int(scroll), - A_HMIDDLE, A_TOP, 3); - y += white_big_text->h+ITEMS_SPACE; - break; - default: - blue_text->drawf(names.item[i], 0, screen->h+y-int(scroll), - A_HMIDDLE, A_TOP, 1); - y += blue_text->h+ITEMS_SPACE; - break; - } - } - - flipscreen(); - - if(screen->h+y-scroll < 0 && 20+screen->h+y-scroll < 0) - done = 1; - - Uint32 ticks = SDL_GetTicks(); - scroll += speed * (ticks - lastticks); - lastticks = ticks; - if(scroll < 0) - scroll = 0; - - SDL_Delay(10); - } - string_list_free(&names); - - SDL_EnableKeyRepeat(0, 0); // disables key repeating - Menu::set_current(main_menu); -} - diff --git a/src/text.h b/src/text.h deleted file mode 100644 index 0e6d7ce30..000000000 --- a/src/text.h +++ /dev/null @@ -1,78 +0,0 @@ -// $Id$ -// -// SuperTux -// Copyright (C) 2004 Tobias Glaesser -// -// 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_TEXT_H -#define SUPERTUX_TEXT_H - -#include -#include "texture.h" -#include "vector.h" - -void display_text_file(const std::string& file, const std::string& surface, float scroll_speed); -void display_text_file(const std::string& file, Surface* surface, float scroll_speed); - -/* Kinds of texts. */ -enum { - TEXT_TEXT, - TEXT_NUM -}; - -enum TextHAlign { - A_LEFT, - A_HMIDDLE, - A_RIGHT, -}; - -enum TextVAlign { - A_TOP, - A_VMIDDLE, - A_BOTTOM, -}; - -/* Text type */ -class Text -{ - public: - Surface* chars; - Surface* shadow_chars; - int kind; - int w; - int h; - public: - Text(const std::string& file, int kind, int w, int h); - ~Text(); - - void draw(const char* text, int x, int y, int shadowsize = 1, int update = NO_UPDATE); - void draw_chars(Surface* pchars, const char* text, int x, int y, int update = NO_UPDATE); - void drawf(const char* text, int x, int y, TextHAlign halign, TextVAlign valign, int shadowsize, int update = NO_UPDATE); - void draw_align(const char* text, int x, int y, TextHAlign halign, TextVAlign valign, int shadowsize = 1, int update = NO_UPDATE); - void erasetext(const char * text, int x, int y, Surface* surf, int update, int shadowsize); - void erasecenteredtext(const char * text, int y, Surface* surf, int update, int shadowsize); - - /// conveniance function - void draw(const char* text, const Vector& pos, int shadowsize = 1, int update - = NO_UPDATE) - { - draw(text, int(pos.x), int(pos.y), shadowsize, update); - } -}; - -#endif /*SUPERTUX_TEXT_H*/ - diff --git a/src/texture.cpp b/src/texture.cpp deleted file mode 100644 index ae09bb358..000000000 --- a/src/texture.cpp +++ /dev/null @@ -1,899 +0,0 @@ -// $Id$ -// -// SuperTux -// Copyright (C) 2004 Tobias Glaesser -// -// 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 -#include -#include -#include "SDL.h" -#include "SDL_image.h" -#include "texture.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() -{ - 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); - } - 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); - } -#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); -} - -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::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::draw(float x, float y, Uint8 alpha, bool upside_down, bool update) -{ - if (impl) - { - if (impl->draw(x, y, alpha, upside_down, update) == -2) - reload(); - } -} - -void -Surface::draw_bg(Uint8 alpha, bool update) -{ - if (impl) - { - if (impl->draw_bg(alpha, update) == -2) - reload(); - } -} - -void -Surface::draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, bool update) -{ - if (impl) - { - if (impl->draw_part(sx, sy, x, y, w, h, alpha, update) == -2) - reload(); - } -} - -void -Surface::draw_stretched(float x, float y, int w, int h, Uint8 alpha, bool update) -{ - if (impl) - { - if (impl->draw_stretched(x, y, w, h, alpha, update) == -2) - reload(); - } -} - -void -Surface::resize(int w_, int h_) -{ - if (impl) - { - w = w_; - h = h_; - if (impl->resize(w_,h_) == -2) - reload(); - } -} - -Surface* Surface::CaptureScreen() -{ - Surface *cap_screen; - - if (!(screen->flags & SDL_OPENGL)) - { - cap_screen = new Surface(SDL_GetVideoSurface(),false); - } - -#ifndef NOOPENGL - if (use_gl) - { - SDL_Surface *temp; - unsigned char *pixels; - int i; - temp = SDL_CreateRGBSurface(SDL_SWSURFACE, screen->w, screen->h, 24, -#if SDL_BYTEORDER == SDL_LIL_ENDIAN - 0x000000FF, 0x0000FF00, 0x00FF0000, 0 -#else - 0x00FF0000, 0x0000FF00, 0x000000FF, 0 -#endif - ); - if (temp == NULL) - st_abort("Error while trying to capture the screen in OpenGL mode",""); - - pixels = (unsigned char*) malloc(3 * screen->w * screen->h); - if (pixels == NULL) - { - SDL_FreeSurface(temp); - st_abort("Error while trying to capture the screen in OpenGL mode",""); - } - - glReadPixels(0, 0, screen->w, screen->h, GL_RGB, GL_UNSIGNED_BYTE, pixels); - - for (i=0; ih; i++) - memcpy(((char *) temp->pixels) + temp->pitch * i, pixels + 3*screen->w * (screen->h-i-1), screen->w*3); - free(pixels); - - cap_screen = new Surface(temp,false); - SDL_FreeSurface(temp); - - } -#endif - -return cap_screen; -} - -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; -} - -//--------------------------------------------------------------------------- - -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() -{ - 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); - } - - 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, GL_RGB10_A2, 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, bool upside_down, bool update) -{ - float pw = power_of_two(w); - float ph = power_of_two(h); - - 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(upside_down) - { - 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); - - (void) update; // avoid compiler warning - - return 0; -} - -int -SurfaceOpenGL::draw_bg(Uint8 alpha, bool update) -{ - float pw = power_of_two(w); - float ph = power_of_two(h); - - glColor3ub(alpha, alpha, alpha); - - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, gl_texture); - - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(0, 0); - glTexCoord2f((float)w / pw, 0); - glVertex2f(screen->w, 0); - glTexCoord2f((float)w / pw, (float)h / ph); - glVertex2f(screen->w, screen->h); - glTexCoord2f(0, (float)h / ph); - glVertex2f(0, screen->h); - glEnd(); - - glDisable(GL_TEXTURE_2D); - - (void) update; // avoid compiler warning - - return 0; -} - -int -SurfaceOpenGL::draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, bool update) -{ - 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(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); - glEnd(); - - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - - (void) update; // avoid warnings - return 0; -} - -int -SurfaceOpenGL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, bool update) -{ - 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); - - (void) update; // avoid warnings - return 0; -} - -#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; -} - -int -SurfaceSDL::draw(float x, float y, Uint8 alpha, bool upside_down, bool update) -{ - SDL_Rect dest; - - dest.x = (int)x; - dest.y = (int)y; - dest.w = w; - dest.h = h; - - if(upside_down) // 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, update) == -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); - - if (update == UPDATE) - SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h); - - SDL_FreeSurface (sdl_surface_copy); - return ret; - } - - int ret = SDL_BlitSurface(sdl_surface, NULL, screen, &dest); - - if (update == UPDATE) - SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h); - - return ret; -} - -int -SurfaceSDL::draw_bg(Uint8 alpha, bool update) -{ - SDL_Rect dest; - - dest.x = 0; - dest.y = 0; - dest.w = screen->w; - dest.h = screen->h; - - 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); - - if (update == UPDATE) - SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h); - - SDL_FreeSurface (sdl_surface_copy); - return ret; - } - - int ret = SDL_SoftStretch(sdl_surface, NULL, screen, &dest); - - if (update == UPDATE) - SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h); - - return ret; -} - -int -SurfaceSDL::draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, bool update) -{ - 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(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); - - if (update == UPDATE) - SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h); - - SDL_FreeSurface (sdl_surface_copy); - return ret; - } - - int ret = SDL_BlitSurface(sdl_surface, &src, screen, &dest); - - if (update == UPDATE) - update_rect(screen, dest.x, dest.y, dest.w, dest.h); - - return ret; -} - -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; -} - -SurfaceSDL::~SurfaceSDL() -{} - -/* EOF */ diff --git a/src/texture.h b/src/texture.h deleted file mode 100644 index 0e68e7000..000000000 --- a/src/texture.h +++ /dev/null @@ -1,169 +0,0 @@ -// $Id$ -// -// SuperTux -// Copyright (C) 2004 Tobias Glaesser -// -// 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 -#include -#ifndef NOOPENGL -#include -#endif - -#include -#include "screen.h" -#include "vector.h" - -SDL_Surface* sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf, int use_alpha); - -class SurfaceImpl; -class SurfaceSDL; -class SurfaceOpenGL; - -/** This class holds all the data necessary to construct a surface */ -class SurfaceData -{ -public: - enum ConstructorType { LOAD, LOAD_PART, SURFACE }; - ConstructorType type; - SDL_Surface* surface; - std::string file; - int use_alpha; - int x; - int y; - int w; - int h; - - 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(); - - 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 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(); - - /** Captures the screen and returns it as Surface*, the user is expected to call the destructor. */ - static Surface* CaptureScreen(); - - /** Reload the surface, which is necesarry in case of a mode swich */ - void reload(); - - void draw(float x, float y, Uint8 alpha = 255, bool upside_down = false, bool update = false); - void draw_bg(Uint8 alpha = 255, bool update = false); - void draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha = 255, bool update = false); - void draw_stretched(float x, float y, int w, int h, Uint8 alpha, bool update = false); - void resize(int w_, int h_); - - /// conveniance function - void draw(const Vector& pos, Uint8 alpha = 255, bool upside_down = false, bool update = false) - { - draw(pos.x, pos.y, alpha, upside_down, update); - } -}; - -/** 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, bool upside_down, bool update) = 0; - virtual int draw_bg(Uint8 alpha, bool update) = 0; - virtual int draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, bool update) = 0; - virtual int draw_stretched(float x, float y, int w, int h, Uint8 alpha, bool update) = 0; - 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); - virtual ~SurfaceSDL(); - - int draw(float x, float y, Uint8 alpha, bool upside_down, bool update); - int draw_bg(Uint8 alpha, bool update); - int draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, bool update); - int draw_stretched(float x, float y, int w, int h, Uint8 alpha, bool update); -}; - -#ifndef NOOPENGL -class SurfaceOpenGL : public SurfaceImpl -{ -public: - unsigned 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); - virtual ~SurfaceOpenGL(); - - int draw(float x, float y, Uint8 alpha, bool upside_down, bool update); - int draw_bg(Uint8 alpha, bool update); - int draw_part(float sx, float sy, float x, float y, float w, float h, Uint8 alpha, bool update); - int draw_stretched(float x, float y, int w, int h, Uint8 alpha, bool update); - -private: - void create_gl(SDL_Surface * surf, GLuint * tex); -}; -#endif - -#endif /*SUPERTUX_TEXTURE_H*/ - -/* Local Variables: */ -/* mode: c++ */ -/* End: */ diff --git a/src/tile.cpp b/src/tile.cpp index 3cb7427d0..d38ff62ff 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -20,12 +20,15 @@ #include "tile.h" #include "scene.h" -#include "assert.h" +#include +#include +#include "screen/drawing_context.h" TileManager* TileManager::instance_ = 0; std::set* TileManager::tilegroups_ = 0; Tile::Tile() + : id(-1), attributes(0), data(0), next_tile(0), anim_speed(25) { } @@ -41,6 +44,62 @@ Tile::~Tile() } } +int +Tile::read(LispReader& reader) +{ + if(!reader.read_int("id", &id)) { + std::cerr << "Missing tile-id.\n"; + return -1; + } + + bool value; + if(reader.read_bool("solid", &value) && value) + attributes |= SOLID; + if(reader.read_bool("unisolid", &value) && value) + attributes |= GOAL; + if(reader.read_bool("brick", &value) && value) + attributes |= BRICK; + if(reader.read_bool("ice", &value) && value) + attributes |= ICE; + if(reader.read_bool("water", &value) && value) + attributes |= WATER; + if(reader.read_bool("spike", &value) && value) + attributes |= SPIKE; + if(reader.read_bool("fullbox", &value) && value) + attributes |= FULLBOX; + if(reader.read_bool("distro", &value) && value) + attributes |= COIN; + if(reader.read_bool("coin", &value) && value) + attributes |= COIN; + if(reader.read_bool("goal", &value) && value) + attributes |= GOAL; + + reader.read_int("data", &data); + reader.read_int("anim-speed", &anim_speed); + reader.read_int("next-tile", &next_tile); + + std::vector filenames; + reader.read_string_vector("images", &filenames); + std::vector editor_filenames; + reader.read_string_vector("editor-images", &editor_filenames); + + // read images + for(std::vector::iterator i = filenames.begin(); + i != filenames.end(); ++i) { + Surface* surface + = new Surface(datadir + "/images/tilesets/" + *i, USE_ALPHA); + images.push_back(surface); + } + for(std::vector::iterator i = editor_filenames.begin(); + i != editor_filenames.end(); ++i) { + Surface* surface + = new Surface(datadir + "/images/tilesets/" + *i, USE_ALPHA); + editor_images.push_back(surface); + } + + return id; +} + //--------------------------------------------------------------------------- TileManager::TileManager() @@ -83,67 +142,21 @@ void TileManager::load_tileset(std::string filename) if (strcmp(lisp_symbol(lisp_car(element)), "tile") == 0) { - - - Tile* tile = new Tile; - tile->id = -1; - tile->solid = false; - tile->unisolid = false; - tile->brick = false; - tile->ice = false; - tile->water = false; - tile->spike = false; - tile->fullbox = false; - tile->distro = false; - tile->goal = false; - tile->data = 0; - tile->next_tile = 0; - tile->anim_speed = 25; - LispReader reader(lisp_cdr(element)); - assert(reader.read_int("id", &tile->id)); - reader.read_bool("solid", &tile->solid); - reader.read_bool("unisolid", &tile->unisolid); - reader.read_bool("brick", &tile->brick); - reader.read_bool("ice", &tile->ice); - reader.read_bool("water", &tile->water); - reader.read_bool("spike", &tile->spike); - reader.read_bool("fullbox", &tile->fullbox); - reader.read_bool("distro", &tile->distro); - reader.read_bool("goal", &tile->goal); - reader.read_int("data", &tile->data); - reader.read_int("anim-speed", &tile->anim_speed); - reader.read_int("next-tile", &tile->next_tile); - reader.read_string_vector("images", &tile->filenames); - reader.read_string_vector("editor-images", &tile->editor_filenames); - - for(std::vector::iterator it = tile-> - filenames.begin(); - it != tile->filenames.end(); - ++it) - { - Surface* cur_image; - tile->images.push_back(cur_image); - tile->images[tile->images.size()-1] = new Surface( - datadir + "/images/tilesets/" + (*it), - USE_ALPHA); - } - for(std::vector::iterator it = tile->editor_filenames.begin(); - it != tile->editor_filenames.end(); - ++it) - { - Surface* cur_image; - tile->editor_images.push_back(cur_image); - tile->editor_images[tile->editor_images.size()-1] = new Surface( - datadir + "/images/tilesets/" + (*it), - USE_ALPHA); - } - - if (tile->id + tileset_id >= int(tiles.size()) - ) - tiles.resize(tile->id + tileset_id+1); - - tiles[tile->id + tileset_id] = tile; + + 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) { @@ -171,7 +184,8 @@ void TileManager::load_tileset(std::string filename) } else { - puts("Unhandled symbol"); + std::cerr << "Unknown symbol: " << + lisp_symbol(lisp_car(element)) << "\n"; } cur = lisp_cdr(cur); @@ -187,52 +201,28 @@ void TileManager::load_tileset(std::string filename) } void -Tile::draw(float x, float y, unsigned int c, Uint8 alpha) +TileManager::draw_tile(DrawingContext& context, unsigned int c, + const Vector& pos, int layer) { - if (c != 0) - { - Tile* ptile = TileManager::instance()->get(c); - if(ptile) - { - if(ptile->images.size() > 1) - { - ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))]->draw(x,y, alpha); - } - else if (ptile->images.size() == 1) - { - ptile->images[0]->draw(x,y, alpha); - } - else - { - //printf("Tile not dravable %u\n", c); - } - } - } -} + if(c == 0) + return; -void -Tile::draw_stretched(float x, float y, int w, int h, unsigned int c, Uint8 alpha) -{ - if (c != 0) - { - Tile* ptile = TileManager::instance()->get(c); - if(ptile) - { - if(ptile->images.size() > 1) - { - ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))]->draw_stretched(x,y,w,h, alpha); - } - else if (ptile->images.size() == 1) - { - ptile->images[0]->draw_stretched(x,y, w, h, alpha); - } - else - { - //printf("Tile not dravable %u\n", c); - } - } - } -} + Tile* tile = get(c); + if(!tile) + return; -// EOF // + 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); + } +} diff --git a/src/tile.h b/src/tile.h index 9123422c5..e72fbee06 100644 --- a/src/tile.h +++ b/src/tile.h @@ -24,12 +24,15 @@ #include #include #include -#include "texture.h" +#include "screen/texture.h" #include "globals.h" #include "lispreader.h" #include "setup.h" +#include "polygon.h" #include "vector.h" +class LispReader; + /** Tile Class */ @@ -39,46 +42,43 @@ public: Tile(); ~Tile(); + /// parses the tile and returns it's id number + int read(LispReader& reader); + int id; std::vector images; std::vector editor_images; - std::vector filenames; - std::vector editor_filenames; + /// bitset for tileflags + enum { + /** solid tile that is indestructable by Tux */ + SOLID = 0x0001, + /** uni-directional solid tile */ + UNISOLID = 0x0002, + /** a brick that can be destroyed by jumping under it */ + BRICK = 0x0004, + /** an ice brick that makes tux sliding more than usual */ + ICE = 0x0008, + /** a water tile in which tux starts to swim */ + WATER = 0x0010, + /** a tile that hurts the player if he touches it */ + SPIKE = 0x0020, + /** Bonusbox, content is stored in \a data */ + FULLBOX = 0x0040, + /** Tile is a coin */ + COIN = 0x0080, + /** the level should be finished when touching a goaltile. + * if data is 0 then the endsequence should be triggered, if data is 1 + * then we can finish the level instantly. + */ + GOAL = 0x0100 + }; + + /** tile attributes */ + uint32_t attributes; - /** solid tile that is indestructable by Tux */ - bool solid; - - /** uni-directional solid tile */ - bool unisolid; - - /** a brick that can be destroyed by jumping under it */ - bool brick; - - /** FIXME: ? */ - bool ice; - - /** water */ - bool water; - - /** spike - kills player on contact */ - bool spike; - - /** Bonusbox, content is stored in \a data */ - bool fullbox; - - /** Tile is a distro/coin */ - bool distro; - - - /** the level should be finished when touching a goaltile. - * if data is 0 then the endsequence should be triggered, if data is 1 - * then we can finish the level instantly. - */ - bool goal; - - /** General purpose data attached to a tile (content of a box, type of coin) */ + /** General purpose data attached to a tile (content of a box, type of coin)*/ int data; /** Id of the tile that is going to replace this tile once it has @@ -88,12 +88,22 @@ public: int anim_speed; /** Draw a tile on the screen: */ - static void draw(float x, float y, unsigned int c, Uint8 alpha = 255); - static void draw_stretched(float x, float y, int w, int h, unsigned int c, Uint8 alpha = 255); + static void draw(const Vector& pos, unsigned int c, Uint8 alpha = 255); + + /// returns the width of the tile in pixels + int getWidth() const + { + if(!images.size()) + return 0; + return images[0]->w; + } - static void draw(const Vector& pos, unsigned int c, Uint8 alpha = 255) + /// returns the height of the tiles in pixels + int getHeight() const { - draw(pos.x, pos.y, c, alpha); + if(!images.size()) + return 0; + return images[0]->h; } }; @@ -122,8 +132,13 @@ class TileManager std::string current_tileset; public: - static TileManager* instance() { return instance_ ? instance_ : instance_ = new TileManager(); } - static void destroy_instance() { delete instance_; instance_ = 0; } + 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* tilegroups() { if(!instance_) { instance_ = new TileManager(); } return tilegroups_ ? tilegroups_ : tilegroups_ = new std::set; } Tile* get(unsigned int id) { diff --git a/src/tilemap.cpp b/src/tilemap.cpp index bb6a0badc..6741d742e 100644 --- a/src/tilemap.cpp +++ b/src/tilemap.cpp @@ -16,20 +16,19 @@ // 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 - #include "tilemap.h" -#include "display_manager.h" + +#include +#include +#include "screen/drawing_context.h" #include "level.h" #include "tile.h" #include "globals.h" -TileMap::TileMap(DisplayManager& display_manager, Level* newlevel) +TileMap::TileMap(Level* newlevel) : level(newlevel) { - display_manager.add_drawable(this, LAYER_BACKGROUNDTILES); - display_manager.add_drawable(this, LAYER_TILES); - display_manager.add_drawable(this, LAYER_FOREGROUNDTILES); + tilemanager = TileManager::instance(); } TileMap::~TileMap() @@ -42,29 +41,31 @@ TileMap::action(float ) } void -TileMap::draw(Camera& viewport, int layer) +TileMap::draw(const std::vector& tiles, DrawingContext& context, + int layer) { - std::vector* tiles; - switch(layer) { - case LAYER_BACKGROUNDTILES: - tiles = &level->bg_tiles; break; - case LAYER_TILES: - tiles = &level->ia_tiles; break; - case LAYER_FOREGROUNDTILES: - tiles = &level->fg_tiles; break; - default: - assert(!"Wrong layer when drawing tilemap."); - } - - int tsx = int(viewport.get_translation().x / 32); // tilestartindex x - int tsy = int(viewport.get_translation().y / 32); // tilestartindex y - int sx = - (int(viewport.get_translation().x) % 32); - int sy = - (int(viewport.get_translation().y) % 32); - for(int x = sx, tx = tsx; x < screen->w && tx < level->width; - x += 32, ++tx) { - for(int y = sy, ty = tsy; y < screen->h && ty < level->height; - y += 32, ++ty) { - Tile::draw(x, y, (*tiles) [ty * level->width + tx]); + float start_x = context.get_translation().x; + float start_y = context.get_translation().y; + float end_x = std::min(start_x + screen->w, float(level->width * 32)); + float end_y = std::min(start_y + screen->h, float(level->height * 32)); + start_x -= int(start_x) % 32; + start_y -= int(start_y) % 32; + int tsx = int(start_x / 32); // tilestartindex x + int tsy = int(start_y / 32); // tilestartindex y + + Vector pos; + int tx, ty; + for(pos.x = start_x, tx = tsx; pos.x < end_x; pos.x += 32, ++tx) { + for(pos.y = start_y, ty = tsy; pos.y < end_y; pos.y += 32, ++ty) { + tilemanager->draw_tile(context, tiles[ty*level->width + tx], pos, layer); } } } + +void +TileMap::draw(DrawingContext& context) +{ + draw(level->bg_tiles, context, LAYER_BACKGROUNDTILES); + draw(level->ia_tiles, context, LAYER_TILES); + draw(level->fg_tiles, context, LAYER_FOREGROUNDTILES); +} diff --git a/src/tilemap.h b/src/tilemap.h index a1cc142a1..8d8f291f3 100644 --- a/src/tilemap.h +++ b/src/tilemap.h @@ -19,24 +19,29 @@ #ifndef __TILEMAP_H__ #define __TILEMAP_H__ +#include #include "game_object.h" -#include "drawable.h" +#include "serializable.h" class Level; +class TileManager; /** * This class is reponsible for drawing the level tiles */ -class TileMap : public GameObject, public Drawable +class TileMap : public GameObject { public: - TileMap(DisplayManager& manager, Level* level); + TileMap(Level* level); virtual ~TileMap(); virtual void action(float elapsed_time); - virtual void draw(Camera& viewport, int layer); + virtual void draw(const std::vector& tiles, + DrawingContext& context, int layer); + virtual void draw(DrawingContext& context); private: + TileManager* tilemanager; Level* level; }; diff --git a/src/title.cpp b/src/title.cpp index a2fa61923..9ef6a6ddf 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -36,10 +36,10 @@ #include "defines.h" #include "globals.h" #include "title.h" -#include "screen.h" +#include "screen/screen.h" +#include "screen/texture.h" #include "high_scores.h" #include "menu.h" -#include "texture.h" #include "timer.h" #include "setup.h" #include "level.h" @@ -117,8 +117,6 @@ void check_contrib_menu() current_contrib_subset = subset.name; - std::cout << "Updating the contrib subset menu..." << subset.levels << std::endl; - contrib_subset_menu->clear(); contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0); @@ -156,13 +154,6 @@ void check_contrib_subset_menu() } } -void draw_background() -{ - /* Draw the title background: */ - - bkg_title->draw_bg(); -} - void draw_demo(GameSession* session, double frame_ratio) { World* world = session->get_world(); @@ -221,9 +212,6 @@ void title(void) GameSession session(datadir + "/levels/misc/menu.stl", 0, ST_GL_DEMO_GAME); - clearscreen(0, 0, 0); - updatescreen(); - /* Load images: */ bkg_title = new Surface(datadir + "/images/background/arctis.jpg", IGNORE_ALPHA); logo = new Surface(datadir + "/images/title/logo.png", USE_ALPHA); @@ -232,13 +220,11 @@ void title(void) /* --- Main title loop: --- */ frame = 0; - /* Draw the title background: */ - bkg_title->draw_bg(); - update_time = st_get_ticks(); random_timer.start(rand() % 2000 + 2000); Menu::set_current(main_menu); + DrawingContext& context = World::current()->context; while (Menu::current()) { // if we spent to much time on a menu entry @@ -266,22 +252,26 @@ void title(void) /* Draw the background: */ draw_demo(&session, frame_ratio); - + + context.push_transform(); + context.set_translation(Vector(0, 0)); if (Menu::current() == main_menu) - logo->draw(screen->w/2 - logo->w/2, 30); + context.draw_surface(logo, Vector(screen->w/2 - logo->w/2, 30), + LAYER_FOREGROUND1+1); - white_small_text->draw(" SuperTux " VERSION "\n" - "Copyright (c) 2003 SuperTux Devel Team\n" - "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n" - "are welcome to redistribute it under certain conditions; see the file COPYING\n" - "for details.\n", - 0, screen->h - 70, 0); + context.draw_text(white_small_text, + " SuperTux " VERSION "\n" + "Copyright (c) 2003 SuperTux Devel Team\n" + "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n" + "are welcome to redistribute it under certain conditions; see the file COPYING\n" + "for details.\n", Vector(0, screen->h - 70), LAYER_FOREGROUND1); + context.pop_transform(); /* Don't draw menu, if quit is true */ Menu* menu = Menu::current(); if(menu) { - menu->draw(); + menu->draw(context); menu->action(); if(menu == main_menu) @@ -298,7 +288,8 @@ void title(void) generate_contrib_menu(); break; case MNID_LEVELEDITOR: - leveleditor(); + // TODO + //leveleditor(); Menu::set_current(main_menu); break; case MNID_CREDITS: @@ -322,8 +313,6 @@ void title(void) char str[1024]; sprintf(str,"Are you sure you want to delete slot %d?", slot); - draw_background(); - if(confirm_dialog(str)) { sprintf(str,"%s/slot%d.stsg", st_save_dir, slot); @@ -352,9 +341,9 @@ void title(void) } } - mouse_cursor->draw(); - - flipscreen(); + mouse_cursor->draw(context); + + context.do_drawing(); /* Set the time of the last update and the time of the current update */ last_update_time = update_time; diff --git a/src/type.cpp b/src/type.cpp index 9638500e8..9b4438560 100644 --- a/src/type.cpp +++ b/src/type.cpp @@ -23,7 +23,7 @@ #include "stdlib.h" #include "setup.h" #include "globals.h" -#include "screen.h" +#include "screen/screen.h" #include "defines.h" #include "type.h" #include "scene.h" diff --git a/src/vector.h b/src/vector.h index 21f4a6ada..699a4cc5e 100644 --- a/src/vector.h +++ b/src/vector.h @@ -46,6 +46,11 @@ public: return Vector(x / s, y / s); } + Vector operator-() const + { + return Vector(-x, -y); + } + const Vector& operator +=(const Vector& other) { x += other.x; diff --git a/src/world.cpp b/src/world.cpp index 98b1ed57c..3f63a2ed1 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -26,7 +26,7 @@ #include #include "globals.h" #include "scene.h" -#include "screen.h" +#include "screen/screen.h" #include "defines.h" #include "world.h" #include "level.h" @@ -34,7 +34,6 @@ #include "resources.h" #include "gameobjs.h" #include "camera.h" -#include "display_manager.h" #include "background.h" #include "tilemap.h" @@ -49,10 +48,10 @@ World::World(const std::string& filename, int level_nr) // world calls child functions current_ = this; - tux = new Player(displaymanager); + tux = new Player; add_object(tux); - level = new Level(); + level = new Level; camera = new Camera(tux, level); add_object(camera); @@ -65,19 +64,11 @@ World::World(const std::string& filename, int level_nr) set_defaults(); - level->load_gfx(); // add background activate_particle_systems(); - background = new Background(displaymanager); - if(level->img_bkgd) { - background->set_image(level->img_bkgd, level->bkgd_speed); - } else { - background->set_gradient(level->bkgd_top, level->bkgd_bottom); - } - add_object(background); // add tilemap - add_object(new TileMap(displaymanager, level)); + add_object(new TileMap(level)); level->load_song(); apply_bonuses(); @@ -145,6 +136,9 @@ World::add_object(GameObject* object) FlyingPlatform* flying_platform = dynamic_cast (object); if(flying_platform) flying_platforms.push_back(flying_platform); + Background* background = dynamic_cast (object); + if(background) + this->background = background; gameobjects.push_back(object); } @@ -159,14 +153,14 @@ World::parse_objects(lisp_object_t* cur) LispReader reader(lisp_cdr(data)); if(object_type == "trampoline") { - add_object(new Trampoline(displaymanager, reader)); + add_object(new Trampoline(reader)); } else if(object_type == "flying-platform") { - add_object(new FlyingPlatform(displaymanager, reader)); + add_object(new FlyingPlatform(reader)); } else { BadGuyKind kind = badguykind_from_string(object_type); - add_object(new BadGuy(displaymanager, kind, reader)); + add_object(new BadGuy(kind, reader)); } cur = lisp_cdr(cur); @@ -178,11 +172,11 @@ World::activate_particle_systems() { if (level->particle_system == "clouds") { - add_object(new CloudParticleSystem(displaymanager)); + add_object(new CloudParticleSystem); } else if (level->particle_system == "snow") { - add_object(new SnowParticleSystem(displaymanager)); + add_object(new SnowParticleSystem); } else if (level->particle_system != "") { @@ -194,13 +188,16 @@ void World::draw() { /* Draw objects */ - displaymanager.draw(*camera); + for(std::vector::iterator i = gameobjects.begin(); + i != gameobjects.end(); ++i) + if((*i)->is_valid()) + (*i)->draw(context); } void World::action(float elapsed_time) { - tux->check_bounds(*camera); + tux->check_bounds(context); /* update objects (don't use iterators here, because the list might change * during the iteration) @@ -216,9 +213,6 @@ World::action(float elapsed_time) for(std::vector::iterator i = gameobjects.begin(); i != gameobjects.end(); /* nothing */) { if((*i)->is_valid() == false) { - Drawable* drawable = dynamic_cast (*i); - if(drawable) - displaymanager.remove_drawable(drawable); BadGuy* badguy = dynamic_cast (*i); if(badguy) { bad_guys.erase(std::remove(bad_guys.begin(), bad_guys.end(), badguy), @@ -383,13 +377,13 @@ World::add_score(const Vector& pos, int s) { player_status.score += s; - add_object(new FloatingScore(displaymanager, pos, s)); + add_object(new FloatingScore(pos, s)); } void World::add_bouncy_distro(const Vector& pos) { - add_object(new BouncyDistro(displaymanager, pos)); + add_object(new BouncyDistro(pos)); } void @@ -406,19 +400,19 @@ void World::add_broken_brick_piece(const Vector& pos, const Vector& movement, Tile* tile) { - add_object(new BrokenBrick(displaymanager, tile, pos, movement)); + add_object(new BrokenBrick(tile, pos, movement)); } void World::add_bouncy_brick(const Vector& pos) { - add_object(new BouncyBrick(displaymanager, pos)); + add_object(new BouncyBrick(pos)); } BadGuy* World::add_bad_guy(float x, float y, BadGuyKind kind) { - BadGuy* badguy = new BadGuy(displaymanager, kind, x, y); + BadGuy* badguy = new BadGuy(kind, x, y); add_object(badguy); return badguy; } @@ -426,7 +420,7 @@ World::add_bad_guy(float x, float y, BadGuyKind kind) void World::add_upgrade(const Vector& pos, Direction dir, UpgradeKind kind) { - add_object(new Upgrade(displaymanager, pos, dir, kind)); + add_object(new Upgrade(pos, dir, kind)); } bool @@ -445,9 +439,9 @@ World::add_bullet(const Vector& pos, float xm, Direction dir) Bullet* new_bullet = 0; if(tux->got_power == Player::FIRE_POWER) - new_bullet = new Bullet(displaymanager, pos, xm, dir, FIRE_BULLET); + new_bullet = new Bullet(pos, xm, dir, FIRE_BULLET); else if(tux->got_power == Player::ICE_POWER) - new_bullet = new Bullet(displaymanager, pos, xm, dir, ICE_BULLET); + new_bullet = new Bullet(pos, xm, dir, ICE_BULLET); else st_abort("wrong bullet type.", ""); add_object(new_bullet); @@ -490,7 +484,7 @@ World::trybreakbrick(float x, float y, bool small) Level* plevel = get_level(); Tile* tile = gettile(x, y); - if (tile->brick) + if (tile->attributes & Tile::BRICK) { if (tile->data > 0) { @@ -546,7 +540,7 @@ void World::tryemptybox(float x, float y, Direction col_side) { Tile* tile = gettile(x,y); - if (!tile->fullbox) + if (!(tile->attributes & Tile::FULLBOX)) return; // according to the collision side, set the upgrade direction @@ -602,7 +596,7 @@ void World::trygrabdistro(float x, float y, int bounciness) { Tile* tile = gettile(x, y); - if (tile && tile->distro) + if (tile && (tile->attributes & Tile::COIN)) { level->change(x, y, TM_IA, tile->next_tile); play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); diff --git a/src/world.h b/src/world.h index 072386f69..d886cd3a4 100644 --- a/src/world.h +++ b/src/world.h @@ -29,11 +29,13 @@ #include "special.h" #include "badguy.h" #include "particlesystem.h" -#include "gameobjs.h" -#include "display_manager.h" +#include "screen/drawing_context.h" +class Camera; class Level; class Background; +class Trampoline; +class FlyingPlatform; /** The World class holds a level and all the game objects (badguys, bouncy distros, etc) that are needed to run a game. */ @@ -63,7 +65,7 @@ public: std::vector gameobjects; Camera* camera; - DisplayManager displaymanager; + DrawingContext context; public: static World* current() diff --git a/src/worldmap.cpp b/src/worldmap.cpp index 1132edd23..944a39cf7 100644 --- a/src/worldmap.cpp +++ b/src/worldmap.cpp @@ -23,8 +23,9 @@ #include #include #include "globals.h" -#include "texture.h" -#include "screen.h" +#include "screen/texture.h" +#include "screen/screen.h" +#include "screen/drawing_context.h" #include "lispreader.h" #include "gameloop.h" #include "setup.h" @@ -186,28 +187,28 @@ Tux::~Tux() } void -Tux::draw(const Point& offset) +Tux::draw(DrawingContext& context, const Vector& offset) { - Point pos = get_pos(); + Vector pos = get_pos(); switch (player_status.bonus) { case PlayerStatus::GROWUP_BONUS: - largetux_sprite->draw(pos.x + offset.x, - pos.y + offset.y - 10); + context.draw_surface(largetux_sprite, + Vector(pos.x + offset.x, pos.y + offset.y - 10), LAYER_OBJECTS); break; case PlayerStatus::FLOWER_BONUS: - firetux_sprite->draw(pos.x + offset.x, - pos.y + offset.y - 10); + context.draw_surface(firetux_sprite, + Vector(pos.x + offset.x, pos.y + offset.y - 10), LAYER_OBJECTS); break; case PlayerStatus::NO_BONUS: - smalltux_sprite->draw(pos.x + offset.x, - pos.y + offset.y - 10); + context.draw_surface(smalltux_sprite, + Vector(pos.x + offset.x, pos.y + offset.y - 10), LAYER_OBJECTS); break; } } -Point +Vector Tux::get_pos() { float x = tile_pos.x * 32; @@ -231,7 +232,7 @@ Tux::get_pos() break; } - return Point((int)x, (int)y); + return Vector((int)x, (int)y); } void @@ -243,7 +244,7 @@ Tux::stop() } void -Tux::update(float delta) +Tux::action(float delta) { if (!moving) { @@ -252,7 +253,7 @@ Tux::update(float delta) WorldMap::Level* level = worldmap->at_level(); // We got a new direction, so lets start walking when possible - Point next_tile; + Vector next_tile; if ((!level || level->solved) && worldmap->path_ok(input_direction, tile_pos, &next_tile)) { @@ -314,7 +315,7 @@ Tux::update(float delta) } // Walk automatically to the next tile - Point next_tile; + Vector next_tile; if (worldmap->path_ok(direction, tile_pos, &next_tile)) { tile_pos = next_tile; @@ -426,8 +427,6 @@ WorldMap::load_map() reader.read_int("x", &level.x); reader.read_int("y", &level.y); - get_level_title(&level); // get level's title - levels.push_back(level); } @@ -446,17 +445,17 @@ WorldMap::load_map() lisp_free(root_obj); } -void WorldMap::get_level_title(Levels::pointer level) +void WorldMap::get_level_title(Level& level) { /** get level's title */ - level->title = ""; + level.title = ""; FILE * fi; lisp_object_t* root_obj = 0; - fi = fopen((datadir + "/levels/" + level->name).c_str(), "r"); + fi = fopen((datadir + "/levels/" + level.name).c_str(), "r"); if (fi == NULL) { - perror((datadir + "/levels/" + level->name).c_str()); + perror((datadir + "/levels/" + level.name).c_str()); return; } @@ -466,13 +465,13 @@ void WorldMap::get_level_title(Levels::pointer level) if (root_obj->type == LISP_TYPE_EOF || root_obj->type == LISP_TYPE_PARSE_ERROR) { - printf("World: Parse Error in file %s", level->name.c_str()); + printf("World: Parse Error in file %s", level.name.c_str()); } if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-level") == 0) { LispReader reader(lisp_cdr(root_obj)); - reader.read_string("name", &level->title); + reader.read_string("name", &level.title); } lisp_free(root_obj); @@ -571,8 +570,8 @@ WorldMap::get_input() } } -Point -WorldMap::get_next_tile(Point pos, Direction direction) +Vector +WorldMap::get_next_tile(Vector pos, Direction direction) { switch(direction) { @@ -595,7 +594,7 @@ WorldMap::get_next_tile(Point pos, Direction direction) } bool -WorldMap::path_ok(Direction direction, Point old_pos, Point* new_pos) +WorldMap::path_ok(Direction direction, Vector old_pos, Vector* new_pos) { *new_pos = get_next_tile(old_pos, direction); @@ -642,7 +641,8 @@ WorldMap::update(float delta) std::cout << "Enter the current level: " << level->name << std::endl; // do a shriking fade to the level - shrink_fade(Point((level->x*32 + 16 + offset.x),(level->y*32 + 16 + offset.y)), 2000); + shrink_fade(Vector((level->x*32 + 16 + offset.x),(level->y*32 + 16 + + offset.y)), 500); GameSession session(datadir + "/levels/" + level->name, 1, ST_GL_LOAD_LEVEL_FILE); @@ -707,23 +707,29 @@ WorldMap::update(float delta) player_status = old_player_status; break; case GameSession::ES_GAME_OVER: + { /* draw an end screen */ /* in the future, this should make a dialog a la SuperMario, asking if the player wants to restart the world map with no score and from level 1 */ char str[80]; - drawgradient(Color (0, 255, 0), Color (255, 0, 255)); + DrawingContext context; + context.draw_gradient(Color (0, 255, 0), Color (255, 0, 255), + LAYER_BACKGROUND0); - blue_text->drawf("GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1); + context.draw_text_center(blue_text, "GAMEOVER", + Vector(0, 200), LAYER_FOREGROUND1); sprintf(str, "SCORE: %d", player_status.score); - gold_text->drawf(str, 0, 224, A_HMIDDLE, A_TOP, 1); + context.draw_text_center(gold_text, str, + Vector(0, 224), LAYER_FOREGROUND1); sprintf(str, "COINS: %d", player_status.distros); - gold_text->drawf(str, 0, screen->w - gold_text->w*2, A_HMIDDLE, A_TOP, 1); + context.draw_text_center(gold_text, str, + Vector(0, screen->w - 32), LAYER_FOREGROUND1); - flipscreen(); + context.do_drawing(); SDL_Event event; wait_for_event(event,2000,5000,true); @@ -731,7 +737,9 @@ WorldMap::update(float delta) quit = true; player_status.reset(); break; + } case GameSession::ES_NONE: + assert(false); // Should never be reached break; } @@ -751,7 +759,7 @@ WorldMap::update(float delta) } else { - tux->update(delta); + tux->action(delta); tux->set_direction(input_direction); } @@ -779,14 +787,16 @@ WorldMap::update(float delta) } Tile* -WorldMap::at(Point p) +WorldMap::at(Vector p) { assert(p.x >= 0 && p.x < width && p.y >= 0 && p.y < height); - return tile_manager->get(tilemap[width * p.y + p.x]); + int x = int(p.x); + int y = int(p.y); + return tile_manager->get(tilemap[width * y + x]); } WorldMap::Level* @@ -804,53 +814,66 @@ WorldMap::at_level() void -WorldMap::draw(const Point& offset) +WorldMap::draw(DrawingContext& context, const Vector& offset) { for(int y = 0; y < height; ++y) for(int x = 0; x < width; ++x) { - Tile* tile = at(Point(x, y)); - tile->sprite->draw(x*32 + offset.x, - y*32 + offset.y); + Tile* tile = at(Vector(x, y)); + context.draw_surface(tile->sprite, + Vector(x*32 + offset.x, y*32 + offset.y), LAYER_TILES); } for(Levels::iterator i = levels.begin(); i != levels.end(); ++i) { if (i->solved) - leveldot_green->draw(i->x*32 + offset.x, - i->y*32 + offset.y); + context.draw_surface(leveldot_green, + Vector(i->x*32 + offset.x, i->y*32 + offset.y), LAYER_TILES+1); else - leveldot_red->draw(i->x*32 + offset.x, - i->y*32 + offset.y); + context.draw_surface(leveldot_red, + Vector(i->x*32 + offset.x, i->y*32 + offset.y), LAYER_TILES+1); } - tux->draw(offset); - draw_status(); + tux->draw(context, offset); + draw_status(context); } void -WorldMap::draw_status() +WorldMap::draw_status(DrawingContext& context) { + context.push_transform(); + context.set_translation(Vector(0, 0)); + char str[80]; sprintf(str, "%d", player_status.score); - white_text->draw("SCORE", 0, 0); - gold_text->draw(str, 96, 0); - sprintf(str, "%d", player_status.distros); - white_text->draw_align("COINS", screen->w/2 - white_text->w*5, 0, A_LEFT, A_TOP); - gold_text->draw_align(str, screen->w/2 + (white_text->w*5)/2, 0, A_RIGHT, A_TOP); + context.draw_text(white_text, "SCORE", Vector(0, 0), LAYER_FOREGROUND1); + context.draw_text(gold_text, str, Vector(96, 0), LAYER_FOREGROUND1); - white_text->draw("LIVES", screen->w - white_text->w*9, 0); + sprintf(str, "%d", player_status.distros); + context.draw_text(white_text, "COINS", Vector(screen->w/2 - 16*5, 0), + LAYER_FOREGROUND1); + context.draw_text(gold_text, str, Vector(screen->w/2 + (16*5)/2, 0), + LAYER_FOREGROUND1); + + context.draw_text(white_text, "LIVES", + Vector(screen->w - white_text->get_text_width("LIVES")*2, 0), + LAYER_FOREGROUND1); if (player_status.lives >= 5) { sprintf(str, "%dx", player_status.lives); - gold_text->draw_align(str, screen->w - gold_text->w, 0, A_RIGHT, A_TOP); - tux_life->draw(screen->w - gold_text->w, 0); + context.draw_text(gold_text, str, + Vector(screen->w - gold_text->get_text_width(str) - tux_life->w, 0), + LAYER_FOREGROUND1); + context.draw_surface(tux_life, Vector(screen->w - gold_text->w, 0), + LAYER_FOREGROUND1); } else { for(int i= 0; i < player_status.lives; ++i) - tux_life->draw(screen->w - tux_life->w*4 +(tux_life->w*i),0); + context.draw_surface(tux_life, + Vector(screen->w - tux_life->w*4 + (tux_life->w*i), 0), + LAYER_FOREGROUND1); } if (!tux->is_moving()) @@ -860,7 +883,13 @@ WorldMap::draw_status() if (i->x == tux->get_tile_pos().x && i->y == tux->get_tile_pos().y) { - white_text->draw_align(i->title.c_str(), screen->w/2, screen->h, A_HMIDDLE, A_BOTTOM); + if(i->title == "") + get_level_title(*i); + + context.draw_text(white_text, i->title, + Vector(screen->w/2 - white_text->get_text_width(i->title)/2, + screen->h - white_text->get_height() - 50), + LAYER_FOREGROUND1); break; } } @@ -882,6 +911,7 @@ WorldMap::display() last_update_time = update_time = st_get_ticks(); + DrawingContext context; while(!quit) { float delta = ((float)(update_time-last_update_time))/100.0; @@ -894,7 +924,7 @@ WorldMap::display() last_update_time = update_time; update_time = st_get_ticks(); - Point tux_pos = tux->get_pos(); + Vector tux_pos = tux->get_pos(); if (1) { offset.x = -tux_pos.x + screen->w/2; @@ -907,16 +937,17 @@ WorldMap::display() if (offset.y < screen->h - height*32) offset.y = screen->h - height*32; } - draw(offset); + draw(context, offset); get_input(); update(delta); if(Menu::current()) { - Menu::current()->draw(); - mouse_cursor->draw(); + Menu::current()->draw(context); + mouse_cursor->draw(context); } - flipscreen(); + + context.do_drawing(); SDL_Delay(20); } @@ -993,13 +1024,13 @@ WorldMap::loadgame(const std::string& filename) lisp_object_t* tux_cur = 0; if (reader.read_lisp("tux", &tux_cur)) { - Point p; + Vector p; std::string back_str = "none"; std::string bonus_str = "none"; LispReader tux_reader(tux_cur); - tux_reader.read_int("x", &p.x); - tux_reader.read_int("y", &p.y); + tux_reader.read_float("x", &p.x); + tux_reader.read_float("y", &p.y); tux_reader.read_string("back", &back_str); tux_reader.read_string("bonus", &bonus_str); diff --git a/src/worldmap.h b/src/worldmap.h index 0fb10214d..b1077711a 100644 --- a/src/worldmap.h +++ b/src/worldmap.h @@ -23,8 +23,9 @@ #include #include +#include "vector.h" #include "musicref.h" -#include "screen.h" +#include "screen/screen.h" namespace WorldMapNS { @@ -83,7 +84,7 @@ private: Direction input_direction; Direction direction; - Point tile_pos; + Vector tile_pos; /** Length by which tux is away from its current tile, length is in input_direction direction */ float offset; @@ -94,15 +95,15 @@ public: Tux(WorldMap* worldmap_); ~Tux(); - void draw(const Point& offset); - void update(float delta); + void draw(DrawingContext& context, const Vector& offset); + void action(float elapsed_time); void set_direction(Direction d) { input_direction = d; } bool is_moving() const { return moving; } - Point get_pos(); - Point get_tile_pos() const { return tile_pos; } - void set_tile_pos(Point p) { tile_pos = p; } + Vector get_pos(); + Vector get_tile_pos() const { return tile_pos; } + void set_tile_pos(Vector p) { tile_pos = p; } }; /** */ @@ -155,12 +156,12 @@ private: Direction input_direction; bool enter_level; - Point offset; + Vector offset; std::string savegame_file; - void get_level_title(Levels::pointer level); + void get_level_title(Level& level); - void draw_status(); + void draw_status(DrawingContext& context); public: WorldMap(); ~WorldMap(); @@ -176,15 +177,15 @@ public: void update(float delta); /** Draw one frame */ - void draw(const Point& offset); + void draw(DrawingContext& context, const Vector& offset); - Point get_next_tile(Point pos, Direction direction); - Tile* at(Point pos); + Vector get_next_tile(Vector pos, Direction direction); + Tile* at(Vector pos); WorldMap::Level* at_level(); /** Check if it is possible to walk from \a pos into \a direction, if possible, write the new position to \a new_pos */ - bool path_ok(Direction direction, Point pos, Point* new_pos); + bool path_ok(Direction direction, Vector pos, Vector* new_pos); void savegame(const std::string& filename); void loadgame(const std::string& filename);