1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "ultima/shared/gfx/dungeon_surface.h"
24 #include "ultima/shared/maps/map.h"
25 #include "ultima/shared/early/game.h"
26
27 namespace Ultima {
28 namespace Shared {
29
30 const byte ARRAY_X[] = { 0, 72, 108, 126, 135, 144 };
31 const byte ARRAY_Y[] = { 0, 36, 54, 63, 68, 72 };
32
DungeonSurface(const Graphics::ManagedSurface & src,const Rect & bounds,Game * game,DrawWidgetFn widgetFn)33 DungeonSurface::DungeonSurface(const Graphics::ManagedSurface &src, const Rect &bounds, Game *game, DrawWidgetFn widgetFn) :
34 Gfx::VisualSurface(src, bounds), _widgetFn(widgetFn) {
35 _edgeColor = game->_edgeColor;
36 _highlightColor = game->_highlightColor;
37 _widgetColor = 0;
38 }
39
drawWall(uint distance)40 void DungeonSurface::drawWall(uint distance) {
41 int offsetX = !distance ? 8 : 0, offsetY = !distance ? 8 : 0;
42
43 if (distance <= 5) {
44 hLine(ARRAY_X[distance] + 16 + offsetX, ARRAY_Y[distance] + 8 + offsetY,
45 303 - ARRAY_X[distance] - offsetX, _edgeColor);
46 hLine(ARRAY_X[distance] + 16 + offsetX, 151 - ARRAY_Y[distance] - offsetY,
47 303 - ARRAY_X[distance] - offsetX, _edgeColor);
48 }
49 }
50
drawDoorway(uint distance)51 void DungeonSurface::drawDoorway(uint distance) {
52 int offsetY = !distance ? 8 : 0;
53 byte color = !distance ? 0 : _edgeColor;
54
55 if (distance < 5) {
56 drawWall(distance);
57 drawLine(ARRAY_X[distance + 1] + 16, 151 - ARRAY_Y[distance] - offsetY,
58 ARRAY_X[distance + 1] + 16, ARRAY_Y[distance + 1] + 8, _edgeColor);
59 drawLineTo(303 - ARRAY_X[distance + 1], ARRAY_Y[distance + 1] + 8, _edgeColor);
60 drawLineTo(303 - ARRAY_X[distance + 1], 151 - ARRAY_Y[distance] - offsetY, _edgeColor);
61 drawLineTo(ARRAY_X[distance + 1] + 16, 151 - ARRAY_Y[distance] - offsetY, color);
62 }
63 }
64
drawLeftEdge(uint distance)65 void DungeonSurface::drawLeftEdge(uint distance) {
66 if (distance <= 5) {
67 vLine(ARRAY_X[distance] + 16, ARRAY_Y[distance] + 8, 151 - ARRAY_Y[distance], _edgeColor);
68 }
69 }
70
drawRightEdge(uint distance)71 void DungeonSurface::drawRightEdge(uint distance) {
72 if (distance <= 5) {
73 vLine(303 - ARRAY_X[distance], ARRAY_Y[distance] + 8, 151 - ARRAY_Y[distance], _edgeColor);
74 }
75 }
76
drawWidget(uint widgetId,uint distance,byte color)77 void DungeonSurface::drawWidget(uint widgetId, uint distance, byte color) {
78 _widgetFn(*this, widgetId, distance, color);
79 }
80
drawLadderDownFaceOn(uint distance)81 void DungeonSurface::drawLadderDownFaceOn(uint distance) {
82 if (distance <= 5) {
83 drawWidget(27, distance, _edgeColor);
84 drawWidget(28, distance, _edgeColor);
85 }
86 }
87
drawLadderDownSideOn(uint distance)88 void DungeonSurface::drawLadderDownSideOn(uint distance) {
89 if (distance <= 5) {
90 drawWidget(27, distance, _edgeColor);
91 drawWidget(29, distance, _edgeColor);
92 }
93 }
94
drawLadderUpFaceOn(uint distance)95 void DungeonSurface::drawLadderUpFaceOn(uint distance) {
96 if (distance <= 5) {
97 drawWidget(26, distance, _edgeColor);
98 drawWidget(28, distance, _edgeColor);
99 }
100 }
101
drawLadderUpSideOn(uint distance)102 void DungeonSurface::drawLadderUpSideOn(uint distance) {
103 if (distance <= 5) {
104 drawWidget(26, distance, _edgeColor);
105 drawWidget(29, distance, _edgeColor);
106 }
107 }
108
drawLeftDoor(uint distance)109 void DungeonSurface::drawLeftDoor(uint distance) {
110 if (distance <= 5) {
111 drawLeftWall(distance);
112
113 Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
114 p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
115 Point diff = p1 - p2;
116 diff.x /= 9;
117 diff.y /= 5;
118
119 drawLine(p2.x + diff.x * 2 + 16, 151 - diff.y - p2.y - 1, p2.x + diff.x * 2 + 16,
120 p1.y + 8 - diff.y, _edgeColor);
121 drawLineTo(p2.x + diff.x * 6 + 16, p1.y + diff.y + 8, _edgeColor);
122 drawLineTo(p2.x + diff.x * 6 + 16, 151 - p1.y + diff.y * 2 - (distance == 1 ? 2 : 0), _edgeColor);
123 }
124 }
125
drawLeftWall(uint distance)126 void DungeonSurface::drawLeftWall(uint distance) {
127 if (distance <= 5) {
128 Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
129 p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
130 drawLine(p2.x + 16, p2.y + 8, p1.x + 16, p1.y + 8, _edgeColor);
131 drawLine(p2.x + 16, 151 - p2.y, p1.x + 16, 151 - p1.y, _edgeColor);
132 }
133 }
134
drawLeftBlank(uint distance)135 void DungeonSurface::drawLeftBlank(uint distance) {
136 if (distance <= 5) {
137 Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
138 p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
139 drawLine(p2.x + 16, p1.y + 8, p1.x + 16, p1.y + 8, _edgeColor);
140 drawLine(p2.x + 16, 151 - p1.y, p1.x + 16, 151 - p1.y, _edgeColor);
141 }
142 }
143
drawRightDoor(uint distance)144 void DungeonSurface::drawRightDoor(uint distance) {
145 if (distance <= 5) {
146 drawRightWall(distance);
147
148 Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
149 p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
150 Point diff = p1 - p2;
151 diff.x /= 9;
152 diff.y /= 5;
153
154 drawLine(303 - (p2.x + diff.x * 2), 151 - diff.y - p2.y - 1, 303 - (p2.x + diff.x * 2),
155 p1.y + 8 - diff.y, _edgeColor);
156 drawLineTo(303 - (diff.x * 6 + p2.x), p1.y + 8 + diff.y, _edgeColor);
157 drawLineTo(303 - (diff.x * 6 + p2.x), 151 - p1.y + diff.y * 2 - (distance == 1 ? 2 : 0), _edgeColor);
158 }
159 }
160
drawRightWall(uint distance)161 void DungeonSurface::drawRightWall(uint distance) {
162 if (distance <= 5) {
163 Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
164 p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
165
166 drawLine(303 - p2.x, p2.y + 8, 303 - p1.x, p1.y + 8, _edgeColor);
167 drawLine(303 - p2.x, 151 - p2.y, 303 - p1.x, 151 - p1.y, _edgeColor);
168 }
169 }
170
drawRightBlank(uint distance)171 void DungeonSurface::drawRightBlank(uint distance) {
172 if (distance <= 5) {
173 Point p1(ARRAY_X[distance], ARRAY_Y[distance]),
174 p2(ARRAY_X[distance - 1], ARRAY_Y[distance - 1]);
175 drawLine(303 - p2.x, p1.y + 8, 303 - p1.x, p1.y + 8, _edgeColor);
176 drawLine(303 - p2.x, 151 - p1.y, 303 - p1.x, 151 - p1.y, _edgeColor);
177 }
178 }
179
drawBeams(uint distance)180 void DungeonSurface::drawBeams(uint distance) {
181 if (distance <= 5) {
182 // Figure out the Y difference between each beam
183 const int Y_START = ARRAY_Y[distance] + 8;
184 const int Y_END = 151 - ARRAY_Y[distance];
185 const int HEIGHT = (Y_END - Y_START) / 4;
186
187 for (int beamNum = 0; beamNum < 4; ++beamNum) {
188 const int YP = Y_START + HEIGHT * beamNum + (distance / 2);
189
190 drawLine(ARRAY_X[distance] + 16, YP, 303 - ARRAY_X[distance], YP, _highlightColor);
191 }
192 }
193 }
194
195 } // End of namespace Shared
196 } // End of namespace Ultima
197