# HG changeset patch # User Tero Marttila # Date 1231881347 -7200 # Node ID 5dd4d782cf3a8190ca2a8aff95737d6bd07d699b # Parent 6c4dc68360eb3f56a0bba4511245cda86105690f a basic implementation of game messages, plus some weird GameStateEvent stuff diff -r 6c4dc68360eb -r 5dd4d782cf3a src/Config.hh --- a/src/Config.hh Tue Jan 13 21:36:43 2009 +0200 +++ b/src/Config.hh Tue Jan 13 23:15:47 2009 +0200 @@ -119,6 +119,10 @@ const uint16_t GRAPHICS_UPDATE_INTERVAL_MS = 20; const bool GRAPHICS_FULLSCREEN = false; +/** + * Number of pixels between lines + */ +const PixelDimension GRAPHICS_INFO_TEXT_LINE_OFFSET = 5; // Filesystem paths const std::string PLAYER_SKIN_PATH = (PROJECT_DATA_DIR "/skin.png"); diff -r 6c4dc68360eb -r 5dd4d782cf3a src/GameMessageView.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/GameMessageView.cc Tue Jan 13 23:15:47 2009 +0200 @@ -0,0 +1,56 @@ + +#include "GameMessageView.hh" +#include "Graphics.hh" +#include "Engine.hh" + +GameMessageView::GameMessageView (PixelArea area) : + area(area), messages() +{ + +} + +void GameMessageView::add_message (CL_Color color, std::string message) { + GameMessage msg (color, message); + + messages.push_back(msg); +} + +void GameMessageView::draw (Graphics *g) { + // get font + CL_Font &font = g->getSimpleFont(); + + // remember color + CL_Color font_color = font.get_color(); + + // maximum width + CL_Size max_size = CL_Size(area.right - area.left, 0); + + // starting point for drawing + PixelDimension offset_prev = area.bottom; + + // render messages, bottom up + for (std::vector::reverse_iterator it = messages.rbegin(); it != messages.rend(); it++) { + // set message color + font.set_color(it->color); + + // calculate height + PixelDimension height = font.get_height(it->message, max_size) + GRAPHICS_INFO_TEXT_LINE_OFFSET; + + // new draw_point + PixelDimension offset_this = offset_prev - height; + + // break if it doesn't fit anymore + if (offset_this < area.top) + break; + + // draw text + font.draw(CL_Rect(area.left, offset_this, area.right, offset_prev), it->message, g->get_gc()); + + // advance offset + offset_prev = offset_this; + } + + // restore font color + font.set_color(font_color); +} + diff -r 6c4dc68360eb -r 5dd4d782cf3a src/GameMessageView.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/GameMessageView.hh Tue Jan 13 23:15:47 2009 +0200 @@ -0,0 +1,42 @@ +#ifndef GRAPHICS_INFO_TEXT_HH +#define GRAPHICS_INFO_TEXT_HH + +#include "GraphicsPointer.hh" +#include "Types.hh" + +#include +#include +#include + +struct GameMessage { + CL_Color color; + std::string message; + + GameMessage (CL_Color color, std::string message) : color(color), message(message) { } + GameMessage (const GameMessage ©) : color(copy.color), message(copy.message) { } + GameMessage &operator= (const GameMessage ©) { color = copy.color; message = copy.message; return *this; } +}; + +class GameMessageView { + protected: + PixelArea area; + std::vector messages; + + public: + /** + * Define the area where messages are drawn + */ + GameMessageView (PixelArea area); + + /** + * Add a message to the list of messages displayed + */ + void add_message (CL_Color color, std::string message); + + /** + * Draw as many messages as fits + */ + void draw (Graphics *g); +}; + +#endif diff -r 6c4dc68360eb -r 5dd4d782cf3a src/GameState.cc --- a/src/GameState.cc Tue Jan 13 21:36:43 2009 +0200 +++ b/src/GameState.cc Tue Jan 13 23:15:47 2009 +0200 @@ -4,10 +4,17 @@ #include "Config.hh" GameState::GameState (void) : - world(Vector(0, MAP_GRAVITY), Vector(MAP_WIDTH, MAP_HEIGHT)), local_player(NULL) + world(Vector(0, MAP_GRAVITY), Vector(MAP_WIDTH, MAP_HEIGHT)), local_player(NULL), event_handler(NULL) { } + +void GameState::setEventHandler (GameStateEventHandler *handler) { + if (handler && event_handler != NULL) + throw Error("event_handler already set"); + + event_handler = handler; +} void GameState::addProjectile (Projectile *projectile) { projectiles.push_back(projectile); @@ -26,6 +33,9 @@ void GameState::addPlayer (Player *player) { player_list.push_back(player); + + if (event_handler) + event_handler->on_player_joined(player); } void GameState::removePlayer (Player *player) { @@ -33,6 +43,9 @@ local_player = NULL; player_list.remove(player); + + if (event_handler) + event_handler->on_player_left(player); } void GameState::draw(Graphics *g, PixelCoordinate camera, bool displayWeapon) { diff -r 6c4dc68360eb -r 5dd4d782cf3a src/GameState.hh --- a/src/GameState.hh Tue Jan 13 21:36:43 2009 +0200 +++ b/src/GameState.hh Tue Jan 13 23:15:47 2009 +0200 @@ -15,6 +15,14 @@ #include #include +class GameStateEventHandler { + friend class GameState; + + protected: + virtual void on_player_joined (Player *p) = 0; + virtual void on_player_left (Player *p) = 0; +}; + class GameState { public: std::list player_list; @@ -26,12 +34,24 @@ */ LocalPlayer *local_player; +protected: + /** + * Notify someone about events? + */ + GameStateEventHandler *event_handler; + +public: /** * ... * * This should take some arguments */ GameState (void); + + /** + * Set event handler, only one can be set + */ + void setEventHandler (GameStateEventHandler *handler); /** * Adds projectile to our list of projectiles to draw diff -r 6c4dc68360eb -r 5dd4d782cf3a src/Graphics.cc --- a/src/Graphics.cc Tue Jan 13 21:36:43 2009 +0200 +++ b/src/Graphics.cc Tue Jan 13 23:15:47 2009 +0200 @@ -4,6 +4,18 @@ #include #include +/* + * XXX: until we figure out a better way to layout stuff + */ +static PixelArea getMessageViewArea (PixelCoordinate resolution) { + return PixelArea( + 400, + resolution.y - 100, + resolution.x, + resolution.y + ); +} + Graphics::Graphics (Engine &engine, GameState &state, PixelCoordinate resolution, bool fullscreen) : CL_DisplayWindow(GRAPHICS_WINDOW_TITLE, resolution.x, resolution.y, fullscreen), engine(engine), @@ -11,7 +23,8 @@ resolution(resolution), update_timer(GRAPHICS_UPDATE_INTERVAL_MS), input(get_ic()->get_keyboard()), - simple_font("Font2", engine.getResourceManager()) + simple_font("Font2", engine.getResourceManager()), + message_view(getMessageViewArea(resolution)) { // connect timer signal @@ -19,6 +32,12 @@ // enable update_timer.start(); + + // push something to message_view + message_view.add_message(CL_Color::white, "Hello World"); + + // GameState events.... + state.setEventHandler(this); } const std::vector & Graphics::getDisplayModes (void) { @@ -75,8 +94,11 @@ } // dump player debug info on stderr - if ((flags & GUI_INPUT_DEBUG_PLAYER) && state.getLocalPlayer()) + if ((flags & GUI_INPUT_DEBUG_PLAYER) && state.getLocalPlayer()) { state.getLocalPlayer()->printDebugInfo(); + + message_view.add_message(CL_Color::green, "..."); + } // toggle fullscreen? if (flags & GUI_INPUT_TOGGLE_FULLSCREEN) { @@ -128,11 +150,14 @@ // Draw the game state.draw(this, camera, flags & GUI_INPUT_DISPLAY_WEAPON); - + + // draw player info box if (player != NULL) { - // draw player info box draw_player_info(gc, player); } + + // draw messages + message_view.draw(this); // Flip window buffer, sync flip(1); @@ -261,5 +286,14 @@ p->getCurrentWeapon()->getName(), get_gc() ); + } + +void Graphics::on_player_joined (Player *p) { + message_view.add_message(CL_Color::white, " *** Player joined"); +} + +void Graphics::on_player_left (Player *p) { + message_view.add_message(CL_Color::white, " *** Player left"); +} diff -r 6c4dc68360eb -r 5dd4d782cf3a src/Graphics.hh --- a/src/Graphics.hh Tue Jan 13 21:36:43 2009 +0200 +++ b/src/Graphics.hh Tue Jan 13 23:15:47 2009 +0200 @@ -9,6 +9,8 @@ #include "Engine.hh" #include "Config.hh" +#include "GameMessageView.hh" + #include #include #include @@ -17,7 +19,7 @@ * This handles drawing the GameState with an appropriate camera view each frame, loading fonts, and currently, * handling the input from Input to GameState. */ -class Graphics : public CL_DisplayWindow { +class Graphics : public GameStateEventHandler, public CL_DisplayWindow { private: Engine &engine; GameState &state; @@ -36,6 +38,9 @@ // basic fonts CL_Font simple_font; + // view components + GameMessageView message_view; + public: Graphics (Engine &engine, GameState &state, PixelCoordinate resolution, bool fullscreen); @@ -73,6 +78,11 @@ void on_update (TimeMS tick_length); void draw_player_info(CL_GraphicContext *gc, Player *p); + +protected: + /* GameStateEventHandler */ + virtual void on_player_joined (Player *p); + virtual void on_player_left (Player *p); }; #endif /* GRAPHICS_HH */ diff -r 6c4dc68360eb -r 5dd4d782cf3a src/Player.hh --- a/src/Player.hh Tue Jan 13 21:36:43 2009 +0200 +++ b/src/Player.hh Tue Jan 13 23:15:47 2009 +0200 @@ -45,7 +45,7 @@ Timer respawn_timer; CL_Slot respawn_slot; - // XXX: hmm... updated where? + // XXX: updated where? int animation_step; //Player stats diff -r 6c4dc68360eb -r 5dd4d782cf3a src/Types.hh --- a/src/Types.hh Tue Jan 13 21:36:43 2009 +0200 +++ b/src/Types.hh Tue Jan 13 23:15:47 2009 +0200 @@ -30,6 +30,17 @@ typedef VectorType PixelCoordinate; /** + * A rectangular area of pixels + */ +struct PixelArea { + PixelDimension left, top, right, bottom; + + PixelArea (PixelDimension left, PixelDimension top, PixelDimension right, PixelDimension bottom) : + left(left), top(top), right(right), bottom(bottom) + { } +}; + +/** * A time interval, measured in real milliseconds */ typedef signed long TimeMS;