1 /*
2 * This file is part of Dune Legacy.
3 *
4 * Dune Legacy is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * Dune Legacy is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Dune Legacy. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <RadarView.h>
19
20 #include <globals.h>
21
22 #include <FileClasses/GFXManager.h>
23
24 #include <Game.h>
25 #include <Map.h>
26 #include <House.h>
27 #include <ScreenBorder.h>
28 #include <Tile.h>
29 #include <SoundPlayer.h>
30
31 #include <globals.h>
32
33 #include <misc/draw_util.h>
34
35
RadarView()36 RadarView::RadarView()
37 : RadarViewBase(), currentRadarMode(RadarMode::RadarOff), animFrame(NUM_STATIC_FRAMES - 1), animCounter(NUM_STATIC_FRAME_TIME)
38 {
39 radarStaticAnimation = pGFXManager->getUIGraphic(UI_RadarAnimation);
40
41 if((radarSurface = SDL_CreateRGBSurface(0, 128, 128, SCREEN_BPP, RMASK, GMASK, BMASK, AMASK)) == nullptr) {
42 THROW(std::runtime_error, "RadarView::RadarView(): Cannot create new surface!");
43 }
44 SDL_FillRect(radarSurface, nullptr, COLOR_BLACK);
45
46 radarTexture = SDL_CreateTexture(renderer, SCREEN_FORMAT, SDL_TEXTUREACCESS_STREAMING, 128, 128);
47 }
48
49
~RadarView()50 RadarView::~RadarView()
51 {
52 SDL_FreeSurface(radarSurface);
53 SDL_DestroyTexture(radarTexture);
54 }
55
getMapSizeX() const56 int RadarView::getMapSizeX() const {
57 return currentGameMap->getSizeX();
58 }
59
getMapSizeY() const60 int RadarView::getMapSizeY() const {
61 return currentGameMap->getSizeY();
62 }
63
64
draw(Point position)65 void RadarView::draw(Point position)
66 {
67 SDL_Rect radarPosition = { position.x + RADARVIEW_BORDERTHICKNESS, position.y + RADARVIEW_BORDERTHICKNESS, RADARWIDTH, RADARHEIGHT};
68
69 switch(currentRadarMode) {
70 case RadarMode::RadarOff:
71 case RadarMode::RadarOn: {
72 int mapSizeX = currentGameMap->getSizeX();
73 int mapSizeY = currentGameMap->getSizeY();
74
75 int scale = 1;
76 int offsetX = 0;
77 int offsetY = 0;
78
79 calculateScaleAndOffsets(mapSizeX, mapSizeY, scale, offsetX, offsetY);
80
81 updateRadarSurface(mapSizeX, mapSizeY, scale, offsetX, offsetY);
82
83 SDL_UpdateTexture(radarTexture, nullptr, radarSurface->pixels, radarSurface->pitch);
84
85 SDL_Rect dest = calcDrawingRect(radarTexture, radarPosition.x, radarPosition.y);
86 SDL_RenderCopy(renderer, radarTexture, nullptr, &dest);
87
88 SDL_Rect radarRect;
89 radarRect.x = (screenborder->getLeft() * mapSizeX*scale) / (mapSizeX*TILESIZE) + offsetX;
90 radarRect.y = (screenborder->getTop() * mapSizeY*scale) / (mapSizeY*TILESIZE) + offsetY;
91 radarRect.w = ((screenborder->getRight() - screenborder->getLeft()) * mapSizeX*scale) / (mapSizeX*TILESIZE);
92 radarRect.h = ((screenborder->getBottom() - screenborder->getTop()) * mapSizeY*scale) / (mapSizeY*TILESIZE);
93
94 if(radarRect.x < offsetX) {
95 radarRect.w -= radarRect.x;
96 radarRect.x = offsetX;
97 }
98
99 if(radarRect.y < offsetY) {
100 radarRect.h -= radarRect.y;
101 radarRect.y = offsetY;
102 }
103
104 int offsetFromRightX = 128 - mapSizeX*scale - offsetX;
105 if(radarRect.x + radarRect.w > radarPosition.w - offsetFromRightX) {
106 radarRect.w = radarPosition.w - offsetFromRightX - radarRect.x - 1;
107 }
108
109 int offsetFromBottomY = 128 - mapSizeY*scale - offsetY;
110 if(radarRect.y + radarRect.h > radarPosition.h - offsetFromBottomY) {
111 radarRect.h = radarPosition.h - offsetFromBottomY - radarRect.y - 1;
112 }
113
114 renderDrawRect( renderer,
115 radarPosition.x + radarRect.x,
116 radarPosition.y + radarRect.y,
117 radarPosition.x + (radarRect.x + radarRect.w),
118 radarPosition.y + (radarRect.y + radarRect.h),
119 COLOR_WHITE);
120
121 } break;
122
123 case RadarMode::AnimationRadarOff:
124 case RadarMode::AnimationRadarOn: {
125 SDL_Rect source = calcSpriteSourceRect( radarStaticAnimation,
126 animFrame % NUM_STATIC_ANIMATIONS_PER_ROW,
127 NUM_STATIC_ANIMATIONS_PER_ROW,
128 animFrame / NUM_STATIC_ANIMATIONS_PER_ROW,
129 (NUM_STATIC_FRAMES + NUM_STATIC_ANIMATIONS_PER_ROW - 1) / NUM_STATIC_ANIMATIONS_PER_ROW);
130 SDL_Rect dest = calcSpriteDrawingRect( radarStaticAnimation,
131 radarPosition.x,
132 radarPosition.y,
133 NUM_STATIC_ANIMATIONS_PER_ROW,
134 (NUM_STATIC_FRAMES + NUM_STATIC_ANIMATIONS_PER_ROW - 1) / NUM_STATIC_ANIMATIONS_PER_ROW);
135 SDL_RenderCopy(renderer, radarStaticAnimation, &source, &dest);
136 } break;
137 }
138 }
139
update()140 void RadarView::update() {
141 if(pLocalHouse->hasRadarOn()) {
142 if(currentRadarMode != RadarMode::RadarOn && currentRadarMode != RadarMode::AnimationRadarOn && currentRadarMode != RadarMode::AnimationRadarOff) {
143 switchRadarMode(true);
144 }
145 } else {
146 if(currentRadarMode != RadarMode::RadarOff && currentRadarMode != RadarMode::AnimationRadarOn && currentRadarMode != RadarMode::AnimationRadarOff) {
147 switchRadarMode(false);
148 }
149 }
150
151 switch(currentRadarMode) {
152 case RadarMode::RadarOff: {
153
154 } break;
155
156 case RadarMode::RadarOn: {
157
158 } break;
159
160 case RadarMode::AnimationRadarOff: {
161 if(animFrame >= NUM_STATIC_FRAMES-1) {
162 currentRadarMode = RadarMode::RadarOff;
163 } else {
164 animCounter--;
165 if(animCounter <= 0) {
166 animFrame++;
167 animCounter = NUM_STATIC_FRAME_TIME;
168 }
169 }
170 } break;
171
172 case RadarMode::AnimationRadarOn: {
173 if(animFrame <= 0) {
174 currentRadarMode = RadarMode::RadarOn;
175 } else {
176 animCounter--;
177 if(animCounter <= 0) {
178 animFrame--;
179 animCounter = NUM_STATIC_FRAME_TIME;
180 }
181 }
182 } break;
183 }
184 }
185
switchRadarMode(bool bOn)186 void RadarView::switchRadarMode(bool bOn) {
187 soundPlayer->playSound(Sound_RadarNoise);
188
189 if(bOn == true) {
190 soundPlayer->playVoice(RadarActivated,pLocalHouse->getHouseID());
191 currentRadarMode = RadarMode::AnimationRadarOn;
192 } else {
193 soundPlayer->playVoice(RadarDeactivated,pLocalHouse->getHouseID());
194 currentRadarMode = RadarMode::AnimationRadarOff;
195 }
196 }
197
updateRadarSurface(int mapSizeX,int mapSizeY,int scale,int offsetX,int offsetY)198 void RadarView::updateRadarSurface(int mapSizeX, int mapSizeY, int scale, int offsetX, int offsetY) {
199
200 // Lock radarSurface for direct access to the pixels
201 if(!SDL_MUSTLOCK(radarSurface) || (SDL_LockSurface(radarSurface) == 0)) {
202 for(int x = 0; x < mapSizeX; x++) {
203 for(int y = 0; y < mapSizeY; y++) {
204
205 Tile* pTile = currentGameMap->getTile(x,y);
206
207 /* Selecting the right color is handled in Tile::getRadarColor() */
208 Uint32 color = pTile->getRadarColor(pLocalHouse, ((currentRadarMode == RadarMode::RadarOn) || (currentRadarMode == RadarMode::AnimationRadarOff)));
209 color = MapRGBA(radarSurface->format, color);
210
211 for(int j = 0; j < scale; j++) {
212 Uint32* p = ((Uint32*) ((Uint8 *) radarSurface->pixels + (offsetY + scale*y + j) * radarSurface->pitch)) + (offsetX + scale*x);
213
214 for(int i = 0; i < scale; i++, p++) {
215 // Do not use putPixel here to avoid overhead
216 *p = color;
217 }
218 }
219 }
220 }
221
222 if(SDL_MUSTLOCK(radarSurface)) {
223 SDL_UnlockSurface(radarSurface);
224 }
225 }
226 }
227