/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * 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 3 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, see . * */ #ifndef ULTIMA4_GFX_SCREEN_H #define ULTIMA4_GFX_SCREEN_H #include "common/file.h" #include "graphics/screen.h" #include "ultima/ultima4/core/config.h" #include "ultima/ultima4/core/types.h" #include "ultima/ultima4/gfx/scale.h" #include "ultima/ultima4/map/direction.h" #include "ultima/ultima4/map/map_tile.h" namespace Ultima { namespace Ultima4 { #define SCR_CYCLE_PER_SECOND 4 #define SCR_CYCLE_MAX 16 #define SCREEN_FRAME_TIME 50 #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 200 /* * bitmasks for LOS shadows */ #define ____H 0x01 // obscured along the horizontal face #define ___C_ 0x02 // obscured at the center #define __V__ 0x04 // obscured along the vertical face #define _N___ 0x80 // start of new raster #define ___CH 0x03 #define __VCH 0x07 #define __VC_ 0x06 #define _N__H 0x81 #define _N_CH 0x83 #define _NVCH 0x87 #define _NVC_ 0x86 #define _NV__ 0x84 enum LayoutType { LAYOUT_STANDARD, LAYOUT_GEM, LAYOUT_DUNGEONGEM }; enum MouseCursor { MC_DEFAULT, MC_WEST, MC_NORTH, MC_EAST, MC_SOUTH }; class Image; class Map; class Tile; class TileView; class Coords; class TileAnimSet; class ImageInfo; struct MouseCursorSurface : public Graphics::ManagedSurface { Common::Point _hotspot; }; struct MouseArea { int _nPoints; struct { int x, y; } _point[3]; MouseCursor _cursor; Direction _direction; }; struct Layout { Common::String _name; LayoutType _type; Common::Point _tileShape; Common::Rect _viewport; }; class Screen : public Graphics::Screen { private: MouseCursorSurface *_mouseCursors[5]; int _currentMouseCursor; Std::vector _tileAnimSets; Layout *_gemLayout; Common::HashMap _dungeonTileChars; ImageInfo *_charSetInfo; ImageInfo *_gemTilesInfo; int _needPrompt; Common::Point _cursorPos; int _cursorStatus; int _cursorEnabled; int _los[VIEWPORT_W][VIEWPORT_H]; //bool _continueScreenRefresh; uint32 _priorFrameTime; public: Std::vector _gemLayoutNames; Std::vector _filterNames; Std::vector _lineOfSightStyles; int _currentCycle; TileAnimSet *_tileAnims; private: /** * Load the cursors */ void loadMouseCursors(); /** * Loads the data for a single cursor from the passed file */ MouseCursorSurface *loadMouseCursor(Common::File &src); void screenLoadGraphicsFromConf(); Layout *screenLoadLayoutFromConf(const ConfigElement &conf); /** * Draw a tile graphic on the screen. */ void screenShowGemTile(Layout *layout, Map *map, MapTile &t, bool focus, int x, int y); /** * Finds which tiles in the viewport are visible from the avatars * location in the middle. (original DOS algorithm) */ void screenFindLineOfSight(Std::vector viewportTiles[VIEWPORT_W][VIEWPORT_H]); /** * Finds which tiles in the viewport are visible from the avatars * location in the middle. (original DOS algorithm) */ void screenFindLineOfSightDOS(Std::vector viewportTiles[VIEWPORT_W][VIEWPORT_H]); /** * Finds which tiles in the viewport are visible from the avatars * location in the middle. * * A new, more accurate LOS function * * Based somewhat off Andy McFadden's 1994 article, * "Improvements to a Fast Algorithm for Calculating Shading * and Visibility in a Two-Dimensional Field" * ----- * https://fadden.com/tech/fast-los.html * * This function uses a lookup table to get the correct shadowmap, * therefore, the table will need to be updated if the viewport * dimensions increase. Also, the function assumes that the * viewport width and height are odd values and that the player * is always at the center of the screen. */ void screenFindLineOfSightEnhanced(Std::vector viewportTiles[VIEWPORT_W][VIEWPORT_H]); /** * Generates terms a and b for equation "ax + b = y" that defines the * line containing the two given points. Vertical lines are special * cased to return DBL_MAX for a and the x coordinate as b since they * cannot be represented with the above formula. */ void screenGetLineTerms(int x1, int y1, int x2, int y2, double *a, double *b); /** * Determine if two points are on the same side of a line (or both on * the line). The line is defined by the terms a and b of the * equation "ax + b = y". */ int screenPointsOnSameSideOfLine(int x1, int y1, int x2, int y2, double a, double b); int screenPointInTriangle(int x, int y, int tx1, int ty1, int tx2, int ty2, int tx3, int ty3); Layout *screenGetGemLayout(const Map *map); public: Std::vector _layouts; Scaler _filterScaler; public: Screen(); ~Screen(); void init(); /** * Reset the screen */ void clear(); /** * Sets a given mouse cursor */ void setMouseCursor(MouseCursor cursor); /** * Re-initializes the screen and implements any changes made in settings */ void screenReInit(); void screenWait(int numberOfAnimationFrames); /** * Draw an image or subimage on the screen. */ void screenDrawImage(const Common::String &name, int x = 0, int y = 0); void screenDrawImageInMapArea(const Common::String &bkgd); void screenFrame(); void screenCycle(); void screenEraseMapArea(); void screenEraseTextArea(int x, int y, int width, int height); void screenGemUpdate(); void screenMessage(const char *fmt, ...); void screenPrompt(); void screenRedrawMapArea(); void screenRedrawTextArea(int x, int y, int width, int height); /** * Scroll the text in the message area up one position. */ void screenScrollMessageArea(); /** * Do the tremor spell effect where the screen shakes. */ void screenShake(int iterations); /** * Draw a character from the charset onto the screen. */ void screenShowChar(int chr, int x, int y); void screenTextAt(int x, int y, const char *fmt, ...); /** * Change the current text color */ void screenTextColor(int color); bool screenTileUpdate(TileView *view, const Coords &coords, bool redraw = true); //Returns true if the screen was affected /** * Redraw the screen. If showmap is set, the normal map is drawn in * the map area. If blackout is set, the map area is blacked out. If * neither is set, the map area is left untouched. */ void screenUpdate(TileView *view, bool showmap, bool blackout); void screenUpdateCursor(); void screenUpdateMoons(); void screenUpdateWind(); Std::vector screenViewportTile(uint width, uint height, int x, int y, bool &focus); void screenShowCursor(); void screenHideCursor(); void screenEnableCursor(); void screenDisableCursor(); void screenSetCursorPos(int x, int y); /** * Determine if the given point is within a mouse area. */ int screenPointInMouseArea(int x, int y, const MouseArea *area); /** * Scale an image up. The resulting image will be scale * the * original dimensions. The original image is no longer deleted. * n is the number of tiles in the image; each tile is filtered * separately. filter determines whether or not to filter the * resulting image. */ Image *screenScale(Image *src, int scale, int n, int filter); /** * Scale an image down. The resulting image will be 1/scale * the * original dimensions. The original image is no longer deleted. */ Image *screenScaleDown(Image *src, int scale); }; extern Screen *g_screen; extern const Std::vector &screenGetGemLayoutNames(); extern const Std::vector &screenGetFilterNames(); extern const Std::vector &screenGetLineOfSightStyles(); } // End of namespace Ultima4 } // End of namespace Ultima #endif