16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
17 *) |
17 *) |
18 |
18 |
19 unit uWorld; |
19 unit uWorld; |
20 interface |
20 interface |
21 uses SDLh, uGears, uConsts; |
21 uses SDLh, uGears, uConsts, uFloat; |
22 {$INCLUDE options.inc} |
22 {$INCLUDE options.inc} |
23 const WorldDx: integer = -512; |
23 const WorldDx: integer = -512; |
24 WorldDy: integer = -256; |
24 WorldDy: integer = -256; |
25 |
25 |
26 procedure InitWorld; |
26 procedure InitWorld; |
37 bShowFinger: boolean = false; |
37 bShowFinger: boolean = false; |
38 Frames: Longword = 0; |
38 Frames: Longword = 0; |
39 |
39 |
40 implementation |
40 implementation |
41 uses uStore, uMisc, uTeams, uIO, uConsole, uKeys, uLocale, uSound; |
41 uses uStore, uMisc, uTeams, uIO, uConsole, uKeys, uLocale, uSound; |
42 const RealTicks: Longword = 0; |
42 const hwFloatTicks: Longword = 0; |
43 FPS: Longword = 0; |
43 FPS: Longword = 0; |
44 CountTicks: Longword = 0; |
44 CountTicks: Longword = 0; |
45 SoundTimerTicks: Longword = 0; |
45 SoundTimerTicks: Longword = 0; |
46 prevPoint: TPoint = (X: 0; Y: 0); |
46 prevPoint: TPoint = (X: 0; Y: 0); |
47 |
47 |
104 dec(y); |
104 dec(y); |
105 DrawSprite(sprAMBorders, x, y, 1, Surface); |
105 DrawSprite(sprAMBorders, x, y, 1, Surface); |
106 dec(y, 33); |
106 dec(y, 33); |
107 DrawSprite(sprAMSlotName, x, y, 0, Surface); |
107 DrawSprite(sprAMSlotName, x, y, 0, Surface); |
108 for i:= cMaxSlotIndex downto 0 do |
108 for i:= cMaxSlotIndex downto 0 do |
109 if Ammo[i, 0].Count > 0 then |
109 if Ammo^[i, 0].Count > 0 then |
110 begin |
110 begin |
111 if (CursorPoint.Y >= y - 33) and (CursorPoint.Y < y) then Slot:= i; |
111 if (CursorPoint.Y >= y - 33) and (CursorPoint.Y < y) then Slot:= i; |
112 dec(y, 33); |
112 dec(y, 33); |
113 inc(SlotsNum); |
113 inc(SlotsNum); |
114 DrawSprite(sprAMSlot, x, y, 0, Surface); |
114 DrawSprite(sprAMSlot, x, y, 0, Surface); |
115 DrawSprite(sprAMSlotKeys, x + 2, y + 1, i, Surface); |
115 DrawSprite(sprAMSlotKeys, x + 2, y + 1, i, Surface); |
116 t:= 0; |
116 t:= 0; |
117 while (t <= cMaxSlotAmmoIndex) and (Ammo[i, t].Count > 0) do |
117 while (t <= cMaxSlotAmmoIndex) and (Ammo^[i, t].Count > 0) do |
118 begin |
118 begin |
119 DrawSprite(sprAMAmmos, x + t * 33 + 35, y + 1, integer(Ammo[i, t].AmmoType), Surface); |
119 DrawSprite(sprAMAmmos, x + t * 33 + 35, y + 1, integer(Ammo^[i, t].AmmoType), Surface); |
120 if (Slot = i) and (CursorPoint.X >= x + t * 33 + 35) and (CursorPoint.X < x + t * 33 + 68) then |
120 if (Slot = i) and (CursorPoint.X >= x + t * 33 + 35) and (CursorPoint.X < x + t * 33 + 68) then |
121 begin |
121 begin |
122 DrawSprite(sprAMSelection, x + t * 33 + 35, y + 1, 0, Surface); |
122 DrawSprite(sprAMSelection, x + t * 33 + 35, y + 1, 0, Surface); |
123 Pos:= t; |
123 Pos:= t; |
124 end; |
124 end; |
127 end; |
127 end; |
128 dec(y, 1); |
128 dec(y, 1); |
129 DrawSprite(sprAMBorders, x, y, 0, Surface); |
129 DrawSprite(sprAMBorders, x, y, 0, Surface); |
130 |
130 |
131 if (Pos >= 0) then |
131 if (Pos >= 0) then |
132 if Ammo[Slot, Pos].Count > 0 then |
132 if Ammo^[Slot, Pos].Count > 0 then |
133 begin |
133 begin |
134 DXOutText(AMxCurr + 10, cScreenHeight - 68, fnt16, trAmmo[Ammoz[Ammo[Slot, Pos].AmmoType].NameId], Surface); |
134 DXOutText(AMxCurr + 10, cScreenHeight - 68, fnt16, trAmmo[Ammoz[Ammo^[Slot, Pos].AmmoType].NameId], Surface); |
135 if Ammo[Slot, Pos].Count < 10 then |
135 if Ammo^[Slot, Pos].Count < 10 then |
136 DXOutText(AMxCurr + 175, cScreenHeight - 68, fnt16, chr(Ammo[Slot, Pos].Count + 48) + 'x', Surface); |
136 DXOutText(AMxCurr + 175, cScreenHeight - 68, fnt16, chr(Ammo^[Slot, Pos].Count + 48) + 'x', Surface); |
137 if bSelected then |
137 if bSelected then |
138 begin |
138 begin |
139 bShowAmmoMenu:= false; |
139 bShowAmmoMenu:= false; |
140 SetWeapon(Ammo[Slot, Pos].AmmoType); |
140 SetWeapon(Ammo^[Slot, Pos].AmmoType); |
141 bSelected:= false; |
141 bSelected:= false; |
142 exit |
142 exit |
143 end; |
143 end; |
144 end; |
144 end; |
145 end; |
145 end; |
146 |
146 |
147 bSelected:= false; |
147 bSelected:= false; |
148 if AMxLeft = AMxCurr then DrawSprite(sprArrow, CursorPoint.X, CursorPoint.Y, (RealTicks shr 6) mod 8, Surface) |
148 if AMxLeft = AMxCurr then DrawSprite(sprArrow, CursorPoint.X, CursorPoint.Y, (hwFloatTicks shr 6) mod 8, Surface) |
149 end; |
149 end; |
150 |
150 |
151 procedure MoveCamera; forward; |
151 procedure MoveCamera; forward; |
152 |
152 |
153 procedure DrawWorld(Lag: integer; Surface: PSDL_Surface); |
153 procedure DrawWorld(Lag: integer; Surface: PSDL_Surface); |
188 DrawRepeated(sprSky, WorldDx * 3 div 8); |
188 DrawRepeated(sprSky, WorldDx * 3 div 8); |
189 DrawRepeated(sprHorizont, WorldDx * 3 div 5); |
189 DrawRepeated(sprHorizont, WorldDx * 3 div 5); |
190 |
190 |
191 // Waves |
191 // Waves |
192 {$WARNINGS OFF} |
192 {$WARNINGS OFF} |
193 for i:= -1 to cWaterSprCount do DrawSprite(sprWater, i * 256 + ((WorldDx + (RealTicks shr 6) ) and $FF), cWaterLine + WorldDy - 64, 0, Surface); |
193 for i:= -1 to cWaterSprCount do DrawSprite(sprWater, i * 256 + ((WorldDx + (hwFloatTicks shr 6) ) and $FF), cWaterLine + WorldDy - 64, 0, Surface); |
194 for i:= -1 to cWaterSprCount do DrawSprite(sprWater, i * 256 + ((WorldDx - (RealTicks shr 6) + 192) and $FF), cWaterLine + WorldDy - 48, 0, Surface); |
194 for i:= -1 to cWaterSprCount do DrawSprite(sprWater, i * 256 + ((WorldDx - (hwFloatTicks shr 6) + 192) and $FF), cWaterLine + WorldDy - 48, 0, Surface); |
195 {$WARNINGS ON} |
195 {$WARNINGS ON} |
196 |
196 |
197 DrawLand(WorldDx, WorldDy, Surface); |
197 DrawLand(WorldDx, WorldDy, Surface); |
198 // Water |
198 // Water |
199 r.y:= WorldDy + cWaterLine + 32; |
199 r.y:= WorldDy + cWaterLine + 32; |
208 |
208 |
209 DrawGears(Surface); |
209 DrawGears(Surface); |
210 |
210 |
211 // Waves |
211 // Waves |
212 {$WARNINGS OFF} |
212 {$WARNINGS OFF} |
213 for i:= -1 to cWaterSprCount do DrawSprite(sprWater, i * 256 + ((WorldDx + (RealTicks shr 6) + 64) and $FF), cWaterLine + WorldDy - 32, 0, Surface); |
213 for i:= -1 to cWaterSprCount do DrawSprite(sprWater, i * 256 + ((WorldDx + (hwFloatTicks shr 6) + 64) and $FF), cWaterLine + WorldDy - 32, 0, Surface); |
214 for i:= -1 to cWaterSprCount do DrawSprite(sprWater, i * 256 + ((WorldDx - (RealTicks shr 6) + 128) and $FF), cWaterLine + WorldDy - 16, 0, Surface); |
214 for i:= -1 to cWaterSprCount do DrawSprite(sprWater, i * 256 + ((WorldDx - (hwFloatTicks shr 6) + 128) and $FF), cWaterLine + WorldDy - 16, 0, Surface); |
215 for i:= -1 to cWaterSprCount do DrawSprite(sprWater, i * 256 + ((WorldDx + (RealTicks shr 6) ) and $FF), cWaterLine + WorldDy , 0, Surface); |
215 for i:= -1 to cWaterSprCount do DrawSprite(sprWater, i * 256 + ((WorldDx + (hwFloatTicks shr 6) ) and $FF), cWaterLine + WorldDy , 0, Surface); |
216 {$WARNINGS ON} |
216 {$WARNINGS ON} |
217 |
217 |
218 // Turn time |
218 // Turn time |
219 if TurnTimeLeft <> 0 then |
219 if TurnTimeLeft <> 0 then |
220 begin |
220 begin |
236 if CurrentTeam <> nil then |
236 if CurrentTeam <> nil then |
237 case AttackBar of |
237 case AttackBar of |
238 1: begin |
238 1: begin |
239 r:= StuffPoz[sPowerBar]; |
239 r:= StuffPoz[sPowerBar]; |
240 {$WARNINGS OFF} |
240 {$WARNINGS OFF} |
241 r.w:= (CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].Gear.Power * 256) div cPowerDivisor; |
241 r.w:= (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.Power * 256) div cPowerDivisor; |
242 {$WARNINGS ON} |
242 {$WARNINGS ON} |
243 DrawSpriteFromRect(r, cScreenWidth - 272, cScreenHeight - 48, 16, 0, Surface); |
243 DrawSpriteFromRect(r, cScreenWidth - 272, cScreenHeight - 48, 16, 0, Surface); |
244 end; |
244 end; |
245 2: with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do |
245 2: with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do |
246 begin |
246 begin |
247 tdx:= hwSign(Gear.dX) * Sin(Gear.Angle*pi/cMaxAngle); |
247 tdx:= hwSign(Gear^.dX) * Sin(Gear^.Angle * Pi / cMaxAngle); |
248 tdy:= - Cos(Gear.Angle*pi/cMaxAngle); |
248 tdy:= - Cos(Gear^.Angle * Pi / cMaxAngle); |
249 for i:= (Gear.Power * 24) div cPowerDivisor downto 0 do |
249 for i:= (Gear^.Power * 24) div cPowerDivisor downto 0 do |
250 DrawSprite(sprPower, round(Gear.X + WorldDx + tdx * (24 + i * 2)) - 16, |
250 DrawSprite(sprPower, Gear^.X.Round + system.round(WorldDx + tdx * (24 + i * 2)) - 16, |
251 round(Gear.Y + WorldDy + tdy * (24 + i * 2)) - 12, |
251 Gear^.Y.Round + system.round(WorldDy + tdy * (24 + i * 2)) - 12, |
252 i, Surface) |
252 i, Surface) |
253 end |
253 end |
254 end; |
254 end; |
255 |
255 |
256 // Target |
256 // Target |
261 for grp:= Low(TCapGroup) to High(TCapGroup) do |
261 for grp:= Low(TCapGroup) to High(TCapGroup) do |
262 with Captions[grp] do |
262 with Captions[grp] do |
263 if Surf <> nil then |
263 if Surf <> nil then |
264 begin |
264 begin |
265 DrawCentered(cScreenWidth div 2, i + cConsoleYAdd, Surf, Surface); |
265 DrawCentered(cScreenWidth div 2, i + cConsoleYAdd, Surf, Surface); |
266 inc(i, Surf.h + 2); |
266 inc(i, Surf^.h + 2); |
267 if EndTime <= RealTicks then |
267 if EndTime <= hwFloatTicks then |
268 begin |
268 begin |
269 SDL_FreeSurface(Surf); |
269 SDL_FreeSurface(Surf); |
270 Surf:= nil; |
270 Surf:= nil; |
271 EndTime:= 0 |
271 EndTime:= 0 |
272 end |
272 end |
274 |
274 |
275 // Teams Healths |
275 // Teams Healths |
276 team:= TeamsList; |
276 team:= TeamsList; |
277 while team <> nil do |
277 while team <> nil do |
278 begin |
278 begin |
279 r.x:= cScreenWidth div 2 - team.NameTag.w - 3; |
279 r.x:= cScreenWidth div 2 - team^.NameTag^.w - 3; |
280 r.y:= team.DrawHealthY; |
280 r.y:= team^.DrawHealthY; |
281 r.w:= team.NameTag.w; |
281 r.w:= team^.NameTag^.w; |
282 r.h:= team.NameTag.h; |
282 r.h:= team^.NameTag^.h; |
283 SDL_UpperBlit(team.NameTag, nil, Surface, @r); |
283 SDL_UpperBlit(team^.NameTag, nil, Surface, @r); |
284 r:= team.HealthRect; |
284 r:= team^.HealthRect; |
285 r.w:= 2 + team.TeamHealthBarWidth; |
285 r.w:= 2 + team^.TeamHealthBarWidth; |
286 DrawFromStoreRect(cScreenWidth div 2, |
286 DrawFromStoreRect(cScreenWidth div 2, |
287 Team.DrawHealthY, |
287 Team^.DrawHealthY, |
288 @r, Surface); |
288 @r, Surface); |
289 inc(r.x, cTeamHealthWidth + 2); |
289 inc(r.x, cTeamHealthWidth + 2); |
290 r.w:= 3; |
290 r.w:= 3; |
291 DrawFromStoreRect(cScreenWidth div 2 + team.TeamHealthBarWidth + 2, |
291 DrawFromStoreRect(cScreenWidth div 2 + team^.TeamHealthBarWidth + 2, |
292 Team.DrawHealthY, |
292 Team^.DrawHealthY, |
293 @r, Surface); |
293 @r, Surface); |
294 team:= team.Next |
294 team:= team^.Next |
295 end; |
295 end; |
296 |
296 |
297 // Lag alert |
297 // Lag alert |
298 if isInLag then DrawSprite(sprLag, 32, 32 + cConsoleYAdd, (RealTicks shr 7) mod 7, Surface); |
298 if isInLag then DrawSprite(sprLag, 32, 32 + cConsoleYAdd, (hwFloatTicks shr 7) mod 7, Surface); |
299 |
299 |
300 // Wind bar |
300 // Wind bar |
301 DrawGear(sWindBar, cScreenWidth - 180, cScreenHeight - 30, Surface); |
301 DrawGear(sWindBar, cScreenWidth - 180, cScreenHeight - 30, Surface); |
302 if WindBarWidth > 0 then |
302 if WindBarWidth > 0 then |
303 begin |
303 begin |
304 with StuffPoz[sWindR] do |
304 with StuffPoz[sWindR] do |
305 begin |
305 begin |
306 {$WARNINGS OFF} |
306 {$WARNINGS OFF} |
307 r.x:= x + 8 - (RealTicks shr 6) mod 8; |
307 r.x:= x + 8 - (hwFloatTicks shr 6) mod 8; |
308 {$WARNINGS ON} |
308 {$WARNINGS ON} |
309 r.y:= y; |
309 r.y:= y; |
310 r.w:= WindBarWidth; |
310 r.w:= WindBarWidth; |
311 r.h:= 13; |
311 r.h:= 13; |
312 end; |
312 end; |
328 |
328 |
329 // AmmoMenu |
329 // AmmoMenu |
330 if (AMxCurr < cScreenWidth) or bShowAmmoMenu then ShowAmmoMenu(Surface); |
330 if (AMxCurr < cScreenWidth) or bShowAmmoMenu then ShowAmmoMenu(Surface); |
331 |
331 |
332 // Cursor |
332 // Cursor |
333 if isCursorVisible then DrawSprite(sprArrow, CursorPoint.X, CursorPoint.Y, (RealTicks shr 6) mod 8, Surface); |
333 if isCursorVisible then DrawSprite(sprArrow, CursorPoint.X, CursorPoint.Y, (hwFloatTicks shr 6) mod 8, Surface); |
334 |
334 |
335 {$IFDEF COUNTTICKS} |
335 {$IFDEF COUNTTICKS} |
336 DXOutText(10, 10, fnt16, inttostr(cntTicks), Surface); |
336 DXOutText(10, 10, fnt16, inttostr(cntTicks), Surface); |
337 {$ENDIF} |
337 {$ENDIF} |
338 |
338 |
347 FPS:= Frames; |
347 FPS:= Frames; |
348 Frames:= 0; |
348 Frames:= 0; |
349 CountTicks:= 0; |
349 CountTicks:= 0; |
350 s:= inttostr(FPS) + ' fps'; |
350 s:= inttostr(FPS) + ' fps'; |
351 if fpsSurface <> nil then SDL_FreeSurface(fpsSurface); |
351 if fpsSurface <> nil then SDL_FreeSurface(fpsSurface); |
352 fpsSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, PChar(String(s)), $FFFFFF); |
352 fpsSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(s), $FFFFFF); |
353 end; |
353 end; |
354 r.x:= cScreenWidth - 50; |
354 r.x:= cScreenWidth - 50; |
355 r.y:= 10; |
355 r.y:= 10; |
356 SDL_UpperBlit(fpsSurface, nil, Surface, @r) |
356 SDL_UpperBlit(fpsSurface, nil, Surface, @r) |
357 end; |
357 end; |
372 begin |
372 begin |
373 if Group in [capgrpGameState, capgrpNetSay] then WriteLnToConsole(s); |
373 if Group in [capgrpGameState, capgrpNetSay] then WriteLnToConsole(s); |
374 if Captions[Group].Surf <> nil then SDL_FreeSurface(Captions[Group].Surf); |
374 if Captions[Group].Surf <> nil then SDL_FreeSurface(Captions[Group].Surf); |
375 |
375 |
376 Captions[Group].Surf:= RenderString(s, Color, fntBig); |
376 Captions[Group].Surf:= RenderString(s, Color, fntBig); |
377 Captions[Group].EndTime:= RealTicks + 1500 |
377 Captions[Group].EndTime:= hwFloatTicks + 1500 |
378 end; |
378 end; |
379 |
379 |
380 procedure MoveCamera; |
380 procedure MoveCamera; |
381 const PrevSentPointTime: LongWord = 0; |
381 const PrevSentPointTime: LongWord = 0; |
382 var EdgesDist: integer; |
382 var EdgesDist: integer; |
383 begin |
383 begin |
384 if not (CurrentTeam.ExtDriven and isCursorVisible) then SDL_GetMouseState(@CursorPoint.X, @CursorPoint.Y); |
384 if not (CurrentTeam^.ExtDriven and isCursorVisible) then SDL_GetMouseState(@CursorPoint.X, @CursorPoint.Y); |
385 if (FollowGear <> nil) then |
385 if (FollowGear <> nil) then |
386 if abs(CursorPoint.X - prevPoint.X) + abs(CursorPoint.Y - prevpoint.Y) > 4 then |
386 if abs(CursorPoint.X - prevPoint.X) + abs(CursorPoint.Y - prevpoint.Y) > 4 then |
387 begin |
387 begin |
388 FollowGear:= nil; |
388 FollowGear:= nil; |
389 exit |
389 exit |
390 end |
390 end |
391 else begin |
391 else begin |
392 CursorPoint.x:= (CursorPoint.x * 7 + (round(FollowGear.X + hwSign(FollowGear.dX) * 100) + WorldDx)) div 8; |
392 CursorPoint.x:= (CursorPoint.x * 7 + (hwRound(FollowGear^.X + hwSign(FollowGear^.dX) * 100) + WorldDx)) div 8; |
393 CursorPoint.y:= (CursorPoint.y * 7 + (round(FollowGear.Y) + WorldDy)) div 8 |
393 CursorPoint.y:= (CursorPoint.y * 7 + (hwRound(FollowGear^.Y) + WorldDy)) div 8 |
394 end; |
394 end; |
395 |
395 |
396 if ((CursorPoint.X = prevPoint.X)and(CursorPoint.Y = prevpoint.Y)) then exit; |
396 if ((CursorPoint.X = prevPoint.X)and(CursorPoint.Y = prevpoint.Y)) then exit; |
397 |
397 |
398 if AMxCurr < cScreenWidth then |
398 if AMxCurr < cScreenWidth then |
406 exit |
406 exit |
407 end; |
407 end; |
408 |
408 |
409 if isCursorVisible then |
409 if isCursorVisible then |
410 begin |
410 begin |
411 if (not CurrentTeam.ExtDriven)and(GameTicks >= PrevSentPointTime + cSendCursorPosTime) then |
411 if (not CurrentTeam^.ExtDriven)and(GameTicks >= PrevSentPointTime + cSendCursorPosTime) then |
412 begin |
412 begin |
413 SendIPCXY('P', CursorPoint.X - WorldDx, CursorPoint.Y - WorldDy); |
413 SendIPCXY('P', CursorPoint.X - WorldDx, CursorPoint.Y - WorldDy); |
414 PrevSentPointTime:= GameTicks |
414 PrevSentPointTime:= GameTicks |
415 end; |
415 end; |
416 end; |
416 end; |
417 |
417 |
418 if isCursorVisible or (FollowGear <> nil) then |
418 if isCursorVisible or (FollowGear <> nil) then |
419 begin |
419 begin |
420 if isCursorVisible then EdgesDist:= cCursorEdgesDist |
420 if isCursorVisible then EdgesDist:= cCursorEdgesDist |
421 else EdgesDist:= cGearScrEdgesDist; |
421 else EdgesDist:= cGearScrEdgesDist; |
422 if CursorPoint.X < EdgesDist then |
422 if CursorPoint.X < EdgesDist then |
445 WorldDx:= WorldDx - CursorPoint.X + prevPoint.X; |
445 WorldDx:= WorldDx - CursorPoint.X + prevPoint.X; |
446 WorldDy:= WorldDy - CursorPoint.Y + prevPoint.Y; |
446 WorldDy:= WorldDy - CursorPoint.Y + prevPoint.Y; |
447 CursorPoint.X:= (cScreenWidth shr 1); |
447 CursorPoint.X:= (cScreenWidth shr 1); |
448 CursorPoint.Y:= (cScreenHeight shr 1); |
448 CursorPoint.Y:= (cScreenHeight shr 1); |
449 end; |
449 end; |
450 |
450 |
451 if cHasFocus then SDL_WarpMouse(CursorPoint.X, CursorPoint.Y); |
451 if cHasFocus then SDL_WarpMouse(CursorPoint.X, CursorPoint.Y); |
452 prevPoint:= CursorPoint; |
452 prevPoint:= CursorPoint; |
453 if WorldDy < cScreenHeight - cWaterLine - cVisibleWater then WorldDy:= cScreenHeight - cWaterLine - cVisibleWater; |
453 if WorldDy < cScreenHeight - cWaterLine - cVisibleWater then WorldDy:= cScreenHeight - cWaterLine - cVisibleWater; |
454 if WorldDy > 2048 then WorldDy:= 2048; |
454 if WorldDy > 2048 then WorldDy:= 2048; |
455 if WorldDx < -2048 then WorldDx:= -2048; |
455 if WorldDx < -2048 then WorldDx:= -2048; |