/* * $Id: output_sdl.cc,v 1.5 2002/09/18 21:46:22 stefan Exp $ * Copyright (c) 2002, Dominik Schnitzer * * JFK - JFK Fucking Killerz, a massive multiplayer 2d shoot'em-up game * http://relax.ath.cx/jfk/ * * 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 Library 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 "output_sdl.h" #include "debug.h" #include "exception.h" #include "SDL_image.h" #include "SDL.h" #include "output.h" #include "conffile.h" using namespace std; using namespace JFK::client; output_sdl::output_sdl(int width, int height, short bpp, const conffile& c) : cf(c) { LOG(("Initializing...")); if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0) { throw JFK::exception(string("Couldn't initialize SDL: ") + SDL_GetError()); } SDL_WM_SetCaption("JFK - you better get things done here, " "than in real life!", NULL); /* * Initialize the display in a width x height truecolor mode, * requesting a software surface */ screen = SDL_SetVideoMode(width, height, bpp, SDL_HWSURFACE|SDL_DOUBLEBUF); if (!screen) { screen = SDL_SetVideoMode(width, height, 0, SDL_SWSURFACE); if (!screen) { throw JFK::exception(string("Couldn't set video mode: ") + SDL_GetError()); } } screen_width = width; screen_height = height; screen_bpp = bpp; SDL_EnableKeyRepeat(0, 0); /* Filter just keyboard events */ SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE); SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE); SDL_EventState(SDL_MOUSEBUTTONUP, SDL_IGNORE); SDL_EventState(SDL_JOYAXISMOTION, SDL_IGNORE); SDL_EventState(SDL_JOYHATMOTION, SDL_IGNORE); SDL_EventState(SDL_JOYBUTTONDOWN, SDL_IGNORE); SDL_EventState(SDL_JOYBUTTONUP, SDL_IGNORE); SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE); SDL_EventState(SDL_USEREVENT, SDL_IGNORE); SDL_EventState(SDL_QUIT, SDL_ENABLE); SDL_EventState(SDL_KEYDOWN, SDL_ENABLE); SDL_EventState(SDL_KEYUP, SDL_ENABLE); SDL_EnableUNICODE(1); refcount = 0; drawn = false; msg_typing = false; msg_string = ""; } output_sdl::~output_sdl() { SDL_Quit(); if (refcount != 0) { LOG(("You forgot to unload %d images!", refcount)); } LOG(("Closed SDL video output plugin.")); } void output_sdl::show() { if (drawn) { SDL_Flip(screen); drawn = false; } } image output_sdl::load_image(string section, string file, int nr, bool hw) { SDL_Surface* imag; SDL_Surface* img; stringstream path; stringstream num; string new_file; num << nr; new_file = file; if (file.find("@") != file.npos) new_file = file.replace(file.find("@"), 1, num.str()); else if (nr != 0) return NULL; path << cf.getvar("artdir") << "/" << section << "/" << new_file; img = IMG_Load(path.str().c_str()); if (img) { LOG(("Loading image: \"%s\" [%p]", path.str().c_str(), (void*) img)); int flags = (img->flags & SDL_SRCALPHA) ? SDL_SRCALPHA : 0; if (hw) flags |= SDL_HWSURFACE; SDL_PixelFormat fmt; fmt.palette = NULL; fmt.BitsPerPixel = screen->format->BitsPerPixel; fmt.BytesPerPixel = screen->format->BytesPerPixel; fmt.Rmask = screen->format->Rmask; fmt.Gmask = screen->format->Gmask; fmt.Bmask = screen->format->Bmask; fmt.Amask = img->format->Amask; fmt.Rshift = screen->format->Rshift; fmt.Gshift = screen->format->Gshift; fmt.Bshift = screen->format->Bshift; fmt.Ashift = screen->format->Ashift; fmt.Rloss = screen->format->Rloss; fmt.Gloss = screen->format->Gloss; fmt.Bloss = screen->format->Bloss; fmt.Aloss = screen->format->Aloss; fmt.alpha = img->format->alpha; imag = SDL_ConvertSurface(img, &fmt, flags); if (imag) SDL_FreeSurface(img); else imag = img; refcount++; } else { imag = NULL; LOG(("Error loading image: \"%s\"", path.str().c_str())); } return (image) imag; } void output_sdl::free_image(image img) { if (img) { SDL_FreeSurface((SDL_Surface*) img); refcount--; LOG(("Freeing image: [%p]", (void*) img)); } } void output_sdl::draw_image(image img, int x, int y) { /* TODO: Throw exception */ if (!img) { LOG(("Tried drawing a NULL image")); return; } SDL_Rect dst; dst.x = x; dst.y = y; dst.w = ((SDL_Surface*)img)->w; dst.h = ((SDL_Surface*)img)->h; SDL_BlitSurface((SDL_Surface*)img, NULL, screen, &dst); drawn = true; } void output_sdl::draw_image_ext(image img, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh) { /* TODO: Throw exception */ if (!img) { LOG(("Tried drawing a NULL image")); return; } SDL_Rect dst; dst.x = dx; dst.y = dy; dst.w = dw; dst.h = dh; SDL_Rect src; src.x = sx; src.y = sy; src.w = sw; src.h = sh; SDL_BlitSurface((SDL_Surface*)img, &src, screen, &dst); drawn = true; } int output_sdl::get_image_width(image img) { if (img) return ((SDL_Surface*)img)->w; else { LOG(("NULL image")); return 0; } } int output_sdl::get_image_height(image img) { if (img) return ((SDL_Surface*)img)->h; else { LOG(("NULL image")); return 0; } } void output_sdl::poll_events(event_t *data) { SDL_Event event; int type; for (int i = 0; i < EVENT_MAX; i++) data->ev[i] = EVENTSTATE_NONE; while (SDL_PollEvent(&event)) { /* Look for a keypress */ if (event.type == SDL_KEYDOWN) type = EVENTSTATE_BEGIN; else if (event.type == SDL_KEYUP) type = EVENTSTATE_DONE; else continue; /* Check the SDLKey values and move change the coords */ switch (event.key.keysym.sym) { case SDLK_LEFT: data->ev[EVENT_LEFT] = type; break; case SDLK_RIGHT: data->ev[EVENT_RIGHT] = type; break; case SDLK_UP: data->ev[EVENT_UP] = type; break; case SDLK_DOWN: data->ev[EVENT_DOWN] = type; break; case SDLK_LCTRL: data->ev[EVENT_FIRE] = type; break; case SDLK_ESCAPE: data->ev[EVENT_ESC] = type; break; case SDLK_TAB: data->ev[EVENT_CHANGE_WEAPON] = type; break; case SDLK_RETURN: if (type == EVENTSTATE_DONE) { if (!msg_typing) { data->ev[EVENT_MESSAGE] = EVENTSTATE_BEGIN; msg_string = ""; data->msg = msg_string; } else { data->ev[EVENT_MESSAGE] = EVENTSTATE_DONE; data->msg = msg_string; } msg_typing = !msg_typing; } break; case SDLK_BACKSPACE: if ((msg_typing) && (type == EVENTSTATE_DONE) && (msg_string.size() > 0)) { msg_string.resize(msg_string.size() - 1); data->ev[EVENT_MESSAGE] = EVENTSTATE_BEGIN; } break; default: /* If we're in message mode and a key was pressed. We see * that any key was pressed in type */ if ((msg_typing) && (type == EVENTSTATE_BEGIN)) { if ((event.key.keysym.unicode & 0xFF80) == 0) { char ch = (char)(event.key.keysym.unicode & 0x7F); if (strchr("abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789.:,;-_#'+*~`°^\"§" "$%&/()=?{}<>|\\ ![]@", ch) != NULL) { msg_string += ch; data->ev[EVENT_MESSAGE] = EVENTSTATE_BEGIN; } } /* else it's an international char */ } break; } } /* Always send the message, if we're in messaging mode */ data->msg = msg_string; } void output_sdl::set_cliprect(int x, int y, int w, int h) { if (!x && !y && !w && !h) SDL_SetClipRect(screen, NULL); else { SDL_Rect clip; clip.x = x; clip.y = y; clip.w = w; clip.h = h; SDL_SetClipRect(screen, &clip); } }