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 * Background handling code.
22 */
23
24 #include "tinsel/background.h"
25 #include "tinsel/cliprect.h" // object clip rect defs
26 #include "tinsel/graphics.h"
27 #include "tinsel/sched.h" // process sheduler defs
28 #include "tinsel/object.h"
29 #include "tinsel/pid.h" // process identifiers
30 #include "tinsel/tinsel.h"
31
32 namespace Tinsel {
33
34 // FIXME: Avoid non-const global vars
35
36 // current background
37 const BACKGND *g_pCurBgnd = NULL;
38
39 /**
40 * Called to initialize a background.
41 * @param pBgnd Pointer to data struct for current background
42 */
43
InitBackground(const BACKGND * pBgnd)44 void InitBackground(const BACKGND *pBgnd) {
45 int i; // playfield counter
46 PLAYFIELD *pPlayfield; // pointer to current playfield
47
48 // set current background
49 g_pCurBgnd = pBgnd;
50
51 // init background sky color
52 SetBgndColor(pBgnd->rgbSkyColor);
53
54 // start of playfield array
55 pPlayfield = pBgnd->fieldArray;
56
57 // for each background playfield
58 for (i = 0; i < pBgnd->numPlayfields; i++, pPlayfield++) {
59 // init playfield pos
60 pPlayfield->fieldX = intToFrac(pBgnd->ptInitWorld.x);
61 pPlayfield->fieldY = intToFrac(pBgnd->ptInitWorld.y);
62
63 // no scrolling
64 pPlayfield->fieldXvel = intToFrac(0);
65 pPlayfield->fieldYvel = intToFrac(0);
66
67 // clear playfield display list
68 pPlayfield->pDispList = NULL;
69
70 // clear playfield moved flag
71 pPlayfield->bMoved = false;
72 }
73 }
74
75 /**
76 * Sets the xy position of the specified playfield in the current background.
77 * @param which Which playfield
78 * @param newXpos New x position
79 * @param newYpos New y position
80 */
81
PlayfieldSetPos(int which,int newXpos,int newYpos)82 void PlayfieldSetPos(int which, int newXpos, int newYpos) {
83 PLAYFIELD *pPlayfield; // pointer to relavent playfield
84
85 // make sure there is a background
86 assert(g_pCurBgnd != NULL);
87
88 // make sure the playfield number is in range
89 assert(which >= 0 && which < g_pCurBgnd->numPlayfields);
90
91 // get playfield pointer
92 pPlayfield = g_pCurBgnd->fieldArray + which;
93
94 // set new integer position
95 pPlayfield->fieldX = intToFrac(newXpos);
96 pPlayfield->fieldY = intToFrac(newYpos);
97
98 // set moved flag
99 pPlayfield->bMoved = true;
100 }
101
102 /**
103 * Returns the xy position of the specified playfield in the current background.
104 * @param which Which playfield
105 * @param pXpos Returns current x position
106 * @param pYpos Returns current y position
107 */
108
PlayfieldGetPos(int which,int * pXpos,int * pYpos)109 void PlayfieldGetPos(int which, int *pXpos, int *pYpos) {
110 PLAYFIELD *pPlayfield; // pointer to relavent playfield
111
112 // make sure there is a background
113 assert(g_pCurBgnd != NULL);
114
115 // make sure the playfield number is in range
116 assert(which >= 0 && which < g_pCurBgnd->numPlayfields);
117
118 // get playfield pointer
119 pPlayfield = g_pCurBgnd->fieldArray + which;
120
121 // get current integer position
122 *pXpos = fracToInt(pPlayfield->fieldX);
123 *pYpos = fracToInt(pPlayfield->fieldY);
124 }
125
126 /**
127 * Returns the x position of the center of the specified playfield
128 * @param which Which playfield
129 */
130
PlayfieldGetCenterX(int which)131 int PlayfieldGetCenterX(int which) {
132 PLAYFIELD *pPlayfield; // pointer to relavent playfield
133
134 // make sure there is a background
135 assert(g_pCurBgnd != NULL);
136
137 // make sure the playfield number is in range
138 assert(which >= 0 && which < g_pCurBgnd->numPlayfields);
139
140 // get playfield pointer
141 pPlayfield = g_pCurBgnd->fieldArray + which;
142
143 // get current integer position
144 return fracToInt(pPlayfield->fieldX) + SCREEN_WIDTH/2;
145 }
146
147 /**
148 * Returns the display list for the specified playfield.
149 * @param which Which playfield
150 */
151
GetPlayfieldList(int which)152 OBJECT **GetPlayfieldList(int which) {
153 PLAYFIELD *pPlayfield; // pointer to relavent playfield
154
155 // make sure there is a background
156 assert(g_pCurBgnd != NULL);
157
158 // make sure the playfield number is in range
159 assert(which >= 0 && which < g_pCurBgnd->numPlayfields);
160
161 // get playfield pointer
162 pPlayfield = g_pCurBgnd->fieldArray + which;
163
164 // return the display list pointer for this playfield
165 return &pPlayfield->pDispList;
166 }
167
168 /**
169 * Draws all the playfield object lists for the current background.
170 * The playfield velocity is added to the playfield position in order
171 * to scroll each playfield before it is drawn.
172 */
173
DrawBackgnd()174 void DrawBackgnd() {
175 int i; // playfield counter
176 PLAYFIELD *pPlay; // playfield pointer
177 int prevX, prevY; // save interger part of position
178 Common::Point ptWin; // window top left
179
180 if (g_pCurBgnd == NULL)
181 return; // no current background
182
183 // scroll each background playfield
184 for (i = 0; i < g_pCurBgnd->numPlayfields; i++) {
185 // get pointer to correct playfield
186 pPlay = g_pCurBgnd->fieldArray + i;
187
188 // save integer part of position
189 prevX = fracToInt(pPlay->fieldX);
190 prevY = fracToInt(pPlay->fieldY);
191
192 // update scrolling
193 pPlay->fieldX += pPlay->fieldXvel;
194 pPlay->fieldY += pPlay->fieldYvel;
195
196 // convert fixed point window pos to a int
197 ptWin.x = fracToInt(pPlay->fieldX);
198 ptWin.y = fracToInt(pPlay->fieldY);
199
200 // set the moved flag if the playfield has moved
201 if (prevX != ptWin.x || prevY != ptWin.y)
202 pPlay->bMoved = true;
203
204 // sort the display list for this background - just in case somebody has changed object Z positions
205 SortObjectList(&pPlay->pDispList);
206
207 // generate clipping rects for all objects that have moved etc.
208 FindMovingObjects(&pPlay->pDispList, &ptWin,
209 &pPlay->rcClip, false, pPlay->bMoved);
210
211 // clear playfield moved flag
212 pPlay->bMoved = false;
213 }
214
215 // merge the clipping rectangles
216 MergeClipRect();
217
218 // redraw all playfields within the clipping rectangles
219 const RectList &clipRects = GetClipRects();
220 for (RectList::const_iterator r = clipRects.begin(); r != clipRects.end(); ++r) {
221 // clear the clip rectangle on the virtual screen
222 // for each background playfield
223 for (i = 0; i < g_pCurBgnd->numPlayfields; i++) {
224 Common::Rect rcPlayClip; // clip rect for this playfield
225
226 // get pointer to correct playfield
227 pPlay = g_pCurBgnd->fieldArray + i;
228
229 // convert fixed point window pos to a int
230 ptWin.x = fracToInt(pPlay->fieldX);
231 ptWin.y = fracToInt(pPlay->fieldY);
232
233 if (IntersectRectangle(rcPlayClip, pPlay->rcClip, *r))
234 // redraw all objects within this clipping rect
235 UpdateClipRect(&pPlay->pDispList, &ptWin, &rcPlayClip);
236 }
237 }
238
239 // transfer any new palettes to the video DAC
240 PalettesToVideoDAC();
241
242 // update the screen within the clipping rectangles
243 for (RectList::const_iterator r = clipRects.begin(); r != clipRects.end(); ++r) {
244 UpdateScreenRect(*r);
245 }
246
247 g_system->updateScreen();
248
249 // delete all the clipping rectangles
250 ResetClipRect();
251 }
252
253 } // End of namespace Tinsel
254