1 | #region MIT License |
---|
2 | /* |
---|
3 | * Copyright (c) 2009 University of Jyväskylä, Department of Mathematical |
---|
4 | * Information Technology. |
---|
5 | * |
---|
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
---|
7 | * of this software and associated documentation files (the "Software"), to deal |
---|
8 | * in the Software without restriction, including without limitation the rights |
---|
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
---|
10 | * copies of the Software, and to permit persons to whom the Software is |
---|
11 | * furnished to do so, subject to the following conditions: |
---|
12 | * |
---|
13 | * The above copyright notice and this permission notice shall be included in |
---|
14 | * all copies or substantial portions of the Software. |
---|
15 | * |
---|
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
---|
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
---|
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
---|
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
---|
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
---|
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
---|
22 | * THE SOFTWARE. |
---|
23 | */ |
---|
24 | #endregion |
---|
25 | |
---|
26 | /* |
---|
27 | * Authors: Tero Jäntti, Tomi Karppinen, Janne Nikkanen. |
---|
28 | */ |
---|
29 | |
---|
30 | using System; |
---|
31 | using System.ComponentModel; |
---|
32 | using System.Xml; |
---|
33 | using System.Xml.Serialization; |
---|
34 | using Microsoft.Xna.Framework; |
---|
35 | using Microsoft.Xna.Framework.Graphics; |
---|
36 | using System.Collections.Generic; |
---|
37 | using System.Linq; |
---|
38 | using Microsoft.Xna.Framework.Content; |
---|
39 | |
---|
40 | #if WINDOWS |
---|
41 | using System.Runtime.InteropServices; |
---|
42 | #endif |
---|
43 | |
---|
44 | #if XBOX |
---|
45 | using Microsoft.Xna.Framework.GamerServices; |
---|
46 | #endif |
---|
47 | |
---|
48 | using Jypeli.Widgets; |
---|
49 | using Jypeli.Effects; |
---|
50 | using Jypeli.Controls; |
---|
51 | using Jypeli.WP7; |
---|
52 | |
---|
53 | using XnaColor = Microsoft.Xna.Framework.Color; |
---|
54 | using XnaSoundEffect = Microsoft.Xna.Framework.Audio.SoundEffect; |
---|
55 | using XnaRectangle = Microsoft.Xna.Framework.Rectangle; |
---|
56 | using System.Reflection; |
---|
57 | using System.Diagnostics; |
---|
58 | |
---|
59 | |
---|
60 | namespace Jypeli |
---|
61 | { |
---|
62 | /// <summary> |
---|
63 | /// Peliluokka reaaliaikaisille peleille. |
---|
64 | /// </summary> |
---|
65 | [Save] |
---|
66 | public class Game : Microsoft.Xna.Framework.Game, ControlContexted, IDisposable, GameObjectContainer |
---|
67 | { |
---|
68 | #if WINDOWS |
---|
69 | [DllImport( "user32.dll" )] |
---|
70 | private static extern int GetSystemMetrics( int smIndex ); |
---|
71 | #endif |
---|
72 | |
---|
73 | Queue<Action> PendingActions = new Queue<Action>(); |
---|
74 | |
---|
75 | /// <summary> |
---|
76 | /// Onko peli pysähdyksissä. |
---|
77 | /// </summary> |
---|
78 | public bool IsPaused { get; set; } |
---|
79 | |
---|
80 | /// <summary> |
---|
81 | /// Kerrokset, joilla pelioliot viihtyvät. |
---|
82 | /// </summary> |
---|
83 | public SynchronousList<Layer> Layers { get; private set; } |
---|
84 | |
---|
85 | /// <summary> |
---|
86 | /// Kerrokset, joilla olevat pelioliot eivät liiku kameran mukana. |
---|
87 | /// </summary> |
---|
88 | public IList<Layer> StaticLayers |
---|
89 | { |
---|
90 | get { return Layers.FindAll( l => l.IgnoresZoom && l.RelativeTransition == Vector.Zero ).AsReadOnly(); } |
---|
91 | } |
---|
92 | |
---|
93 | /// <summary> |
---|
94 | /// Kerrokset, joilla olevat pelioliot liikkuvat kameran mukana. |
---|
95 | /// </summary> |
---|
96 | public IList<Layer> DynamicLayers |
---|
97 | { |
---|
98 | get { return Layers.FindAll( l => !l.IgnoresZoom || l.RelativeTransition != Vector.Zero ).AsReadOnly(); } |
---|
99 | } |
---|
100 | |
---|
101 | /// <summary> |
---|
102 | /// Pienin mahdollinen kerros. |
---|
103 | /// </summary> |
---|
104 | public int MinLayer |
---|
105 | { |
---|
106 | get { return Layers.FirstIndex; } |
---|
107 | } |
---|
108 | |
---|
109 | /// <summary> |
---|
110 | /// Suurin mahdollinen kerros. |
---|
111 | /// </summary> |
---|
112 | public int MaxLayer |
---|
113 | { |
---|
114 | get { return Layers.LastIndex; } |
---|
115 | } |
---|
116 | |
---|
117 | /// <summary> |
---|
118 | /// Kerrosten määrä. |
---|
119 | /// </summary> |
---|
120 | public int LayerCount |
---|
121 | { |
---|
122 | get { return Layers.Count; } |
---|
123 | } |
---|
124 | |
---|
125 | /// <summary> |
---|
126 | /// Pelin nimi. |
---|
127 | /// </summary> |
---|
128 | public static string Name { get; private set; } |
---|
129 | |
---|
130 | // TJ: Since there is only one isntance of the |
---|
131 | // game class in practice, its useful to have it available as |
---|
132 | // a static member. This way, we avoid passing a reference to the |
---|
133 | // game in lots of places. |
---|
134 | // |
---|
135 | // In addition, some often-used things, such as Time or GraphicsDevice, |
---|
136 | // are available as static properties (public or internal) as well. |
---|
137 | public static Game Instance { get; private set; } |
---|
138 | |
---|
139 | /// <summary> |
---|
140 | /// Tapahtuu kun Game.Instance on alustettu. |
---|
141 | /// </summary> |
---|
142 | public static event Action InstanceInitialized; |
---|
143 | |
---|
144 | /// <summary> |
---|
145 | /// Tapahtuu kun peli lopetetaan. |
---|
146 | /// </summary> |
---|
147 | public static new event Action Exiting; |
---|
148 | |
---|
149 | /// <summary> |
---|
150 | /// Kamera, joka näyttää ruudulla näkyvän osan kentästä. |
---|
151 | /// Kameraa voidaan siirtää, zoomata tai asettaa seuraamaan tiettyä oliota. |
---|
152 | /// </summary> |
---|
153 | [Save] |
---|
154 | public Camera Camera { get; set; } |
---|
155 | |
---|
156 | /// <summary> |
---|
157 | /// Kentän reunat näkyvissä tai pois näkyvistä. |
---|
158 | /// Huomaa, että tämä ominaisuus ei vaikuta reunojen törmäyskäsittelyyn. |
---|
159 | /// </summary> |
---|
160 | public bool DrawPerimeter { get; set; } |
---|
161 | |
---|
162 | /// <summary> |
---|
163 | /// Väri, jolla kentän reunat piirretään. |
---|
164 | /// </summary> |
---|
165 | public Color PerimeterColor { get; set; } |
---|
166 | |
---|
167 | /// <summary> |
---|
168 | /// Tekstuurien (kuvien) reunanpehmennys skaalattaessa (oletus päällä). |
---|
169 | /// </summary> |
---|
170 | public static bool SmoothTextures { get; set; } |
---|
171 | |
---|
172 | /// <summary> |
---|
173 | /// Kirjaston mukana tuleva sisältö. |
---|
174 | /// Voidaan käyttää esimerkiksi tekstuurien lataamiseen. |
---|
175 | /// </summary> |
---|
176 | internal static ResourceContentManager ResourceContent { get; private set; } |
---|
177 | |
---|
178 | /// <summary> |
---|
179 | /// Näytön dimensiot, eli koko ja reunat. |
---|
180 | /// </summary> |
---|
181 | public static ScreenView Screen |
---|
182 | { |
---|
183 | get { return Instance.screen; } |
---|
184 | } |
---|
185 | |
---|
186 | /// <summary> |
---|
187 | /// Ikkuna. |
---|
188 | /// </summary> |
---|
189 | public static new JypeliWindow Window { get; private set; } |
---|
190 | |
---|
191 | /// <summary> |
---|
192 | /// Pelin kontrollit. |
---|
193 | /// </summary> |
---|
194 | public static Jypeli.Controls.Controls Controls |
---|
195 | { |
---|
196 | get { return Instance.controls; } |
---|
197 | } |
---|
198 | |
---|
199 | private ListenContext _context = new ListenContext() { Active = true }; |
---|
200 | |
---|
201 | /// <summary> |
---|
202 | /// Pelin pääohjainkonteksti. |
---|
203 | /// </summary> |
---|
204 | public ListenContext ControlContext |
---|
205 | { |
---|
206 | get { return Instance._context; } |
---|
207 | } |
---|
208 | |
---|
209 | public bool IsModal |
---|
210 | { |
---|
211 | get { return false; } |
---|
212 | } |
---|
213 | |
---|
214 | /// <summary> |
---|
215 | /// Viestinäyttö, johon voi laittaa viestejä. |
---|
216 | /// </summary> |
---|
217 | /// <value>Viestinäyttö.</value> |
---|
218 | public MessageDisplay MessageDisplay { get; set; } |
---|
219 | |
---|
220 | /// <summary> |
---|
221 | /// Tietovarasto, johon voi tallentaa tiedostoja pidempiaikaisesti. |
---|
222 | /// Sopii esimerkiksi pelitilanteen lataamiseen ja tallentamiseen. |
---|
223 | /// </summary> |
---|
224 | public static FileManager DataStorage { get { return Instance.dataStorage; } } |
---|
225 | |
---|
226 | /// <summary> |
---|
227 | /// Onko olio valittavissa. |
---|
228 | /// Vain valittu (fokusoitu) olio voii kuunnella näppäimistöä ja muita ohjainlaitteita. |
---|
229 | /// Peliolio on aina valittavissa. |
---|
230 | /// </summary> |
---|
231 | public bool AcceptsFocus { get { return true; } } |
---|
232 | |
---|
233 | /// <summary> |
---|
234 | /// Näppäimistö. |
---|
235 | /// </summary> |
---|
236 | public Keyboard Keyboard { get { return controls.Keyboard; } } |
---|
237 | |
---|
238 | /// <summary> |
---|
239 | /// Hiiri. |
---|
240 | /// </summary> |
---|
241 | public Mouse Mouse { get { return controls.Mouse; } } |
---|
242 | |
---|
243 | /// <summary> |
---|
244 | /// Kosketusnäyttö. Vain kännykässä. |
---|
245 | /// </summary> |
---|
246 | public TouchPanel TouchPanel { get { return controls.TouchPanel; } } |
---|
247 | |
---|
248 | public PhoneBackButton PhoneBackButton { get { return controls.PhoneBackButton; } } |
---|
249 | |
---|
250 | /// <summary> |
---|
251 | /// Peliohjain yksi. |
---|
252 | /// </summary> |
---|
253 | public GamePad ControllerOne { get { return controls.GameControllers[0]; } } |
---|
254 | |
---|
255 | /// <summary> |
---|
256 | /// Peliohjain kaksi. |
---|
257 | /// </summary> |
---|
258 | public GamePad ControllerTwo { get { return controls.GameControllers[1]; } } |
---|
259 | |
---|
260 | /// <summary> |
---|
261 | /// Peliohjain kolme. |
---|
262 | /// </summary> |
---|
263 | public GamePad ControllerThree { get { return controls.GameControllers[2]; } } |
---|
264 | |
---|
265 | /// <summary> |
---|
266 | /// Peliohjain neljä. |
---|
267 | /// </summary> |
---|
268 | public GamePad ControllerFour { get { return controls.GameControllers[3]; } } |
---|
269 | |
---|
270 | /// <summary> |
---|
271 | /// Kiihtyvyysanturi. Vain kännykässä. |
---|
272 | /// </summary> |
---|
273 | public Accelerometer Accelerometer { get { return controls.Accelerometer; } } |
---|
274 | |
---|
275 | private Phone phone; |
---|
276 | |
---|
277 | /// <summary> |
---|
278 | /// Phone-olio esim. puhelimen tärisyttämiseen. |
---|
279 | /// </summary> |
---|
280 | public Phone Phone { get { return phone; } } |
---|
281 | |
---|
282 | |
---|
283 | /// <summary> |
---|
284 | /// Aktiivinen kenttä. |
---|
285 | /// </summary> |
---|
286 | public Level Level |
---|
287 | { |
---|
288 | get { return theLevel; } |
---|
289 | } |
---|
290 | |
---|
291 | /// <summary> |
---|
292 | /// Peliaika. Sisältää tiedon siitä, kuinka kauan peliä on pelattu (Time.SinceStartOfGame) |
---|
293 | /// ja kuinka kauan on viimeisestä pelin päivityksestä (Time.SinceLastUpdate). |
---|
294 | /// Tätä päivitetään noin 30 kertaa sekunnissa kun peli ei ole pause-tilassa. |
---|
295 | /// </summary> |
---|
296 | public static Time Time |
---|
297 | { |
---|
298 | get { return currentTime; } |
---|
299 | } |
---|
300 | |
---|
301 | /// <summary> |
---|
302 | /// Todellinen peliaika. Sisältää tiedon siitä, kuinka kauan peliä on pelattu (Time.SinceStartOfGame) |
---|
303 | /// ja kuinka kauan on viimeisestä pelin päivityksestä (Time.SinceLastUpdate). |
---|
304 | /// Tätä päivitetään noin 30 kertaa sekunnissa, myös pause-tilassa. |
---|
305 | /// </summary> |
---|
306 | public static Time RealTime |
---|
307 | { |
---|
308 | get { return currentTime; } |
---|
309 | } |
---|
310 | |
---|
311 | /// <summary> |
---|
312 | /// Tuuli. Vaikuttaa vain efekteihin |
---|
313 | /// </summary> |
---|
314 | public static Vector Wind { get; set; } |
---|
315 | |
---|
316 | /// <summary> |
---|
317 | /// Teksti, joka näkyy pelin ikkunassa (jos peli ei ole koko ruudun tilassa). |
---|
318 | /// </summary> |
---|
319 | public string Title |
---|
320 | { |
---|
321 | get { return Window.Title; } |
---|
322 | set { Window.Title = value; } |
---|
323 | } |
---|
324 | |
---|
325 | /// <summary> |
---|
326 | /// Kuinka monta pelioliota pelissä on (ei laske widgettejä). |
---|
327 | /// </summary> |
---|
328 | internal int ObjectCount |
---|
329 | { |
---|
330 | get |
---|
331 | { |
---|
332 | return Layers.Sum<Layer>( l => l.Objects.Count ); |
---|
333 | } |
---|
334 | } |
---|
335 | |
---|
336 | /// <summary> |
---|
337 | /// Onko peli kokoruututilassa. |
---|
338 | /// </summary> |
---|
339 | public bool IsFullScreen |
---|
340 | { |
---|
341 | get { return Window.Fullscreen; } |
---|
342 | set { Window.Fullscreen = value; } |
---|
343 | } |
---|
344 | |
---|
345 | /// <summary> |
---|
346 | /// Mediasoitin. |
---|
347 | /// </summary> |
---|
348 | public MediaPlayer MediaPlayer { get; private set; } |
---|
349 | |
---|
350 | private Jypeli.Controls.Controls controls; |
---|
351 | private FileManager dataStorage; |
---|
352 | private ScreenView screen; |
---|
353 | |
---|
354 | [EditorBrowsable( EditorBrowsableState.Never )] |
---|
355 | public static new GraphicsDevice GraphicsDevice |
---|
356 | { |
---|
357 | get { return ( (Microsoft.Xna.Framework.Game)Instance ).GraphicsDevice; } |
---|
358 | } |
---|
359 | |
---|
360 | internal static GraphicsDeviceManager GraphicsDeviceManager { get; private set; } |
---|
361 | |
---|
362 | #if !WINDOWS_PHONE |
---|
363 | internal static List<Light> Lights { get { return lights; } } |
---|
364 | #endif |
---|
365 | |
---|
366 | #if DEBUG |
---|
367 | private BarGauge[] objectCountDisplays; |
---|
368 | private Label fpsDisplay; |
---|
369 | private string fpsText = "00"; |
---|
370 | private int fpsSkipCounter; |
---|
371 | private bool isDebugScreenShown = false; |
---|
372 | #endif |
---|
373 | |
---|
374 | #if !WINDOWS_PHONE |
---|
375 | private static List<Light> lights = new List<Light>(); |
---|
376 | #endif |
---|
377 | |
---|
378 | private Level theLevel; |
---|
379 | |
---|
380 | private bool loadContentHasBeenCalled = false; |
---|
381 | private bool beginHasBeenCalled = false; |
---|
382 | |
---|
383 | // Real time passed, including paused time |
---|
384 | private static Time currentRealTime = new Time(); |
---|
385 | |
---|
386 | // Game time passed |
---|
387 | private static Time currentTime = new Time(); |
---|
388 | |
---|
389 | |
---|
390 | /// <summary> |
---|
391 | /// Alustaa uuden peliluokan. |
---|
392 | /// </summary> |
---|
393 | public Game() |
---|
394 | : this( 1 ) |
---|
395 | { |
---|
396 | } |
---|
397 | |
---|
398 | /// <summary> |
---|
399 | /// Alustaa uuden peliluokan. |
---|
400 | /// </summary> |
---|
401 | /// <param name="device">Mikä monitori käytössä, 1=ensimmäinen</param> |
---|
402 | public Game( int device ) |
---|
403 | { |
---|
404 | if ( Instance != null ) |
---|
405 | throw new Exception( "Only one instance of the Game class can be created." ); |
---|
406 | |
---|
407 | Instance = this; |
---|
408 | Name = this.GetType().Assembly.FullName.Split( ',' )[0]; |
---|
409 | |
---|
410 | InitializeLayers(); |
---|
411 | InitializeContent(); |
---|
412 | |
---|
413 | Camera = new Camera(); |
---|
414 | controls = new Jypeli.Controls.Controls(); |
---|
415 | |
---|
416 | InitializeGraphics( device ); |
---|
417 | Window = new JypeliWindow( base.Window, Game.GraphicsDeviceManager ); |
---|
418 | Window.Resized += new JypeliWindow.ResizeEvent( WindowResized ); |
---|
419 | |
---|
420 | #if WINDOWS |
---|
421 | this.dataStorage = new WindowsFileManager( WindowsLocation.DataPath, WindowsLocation.MyDocuments ); ; |
---|
422 | #elif WINDOWS_PHONE |
---|
423 | dataStorage = new IsolatedStorageManager(); |
---|
424 | #elif XBOX |
---|
425 | Components.Add( new GamerServicesComponent( this ) ); |
---|
426 | dataStorage = new XboxFileManager(); |
---|
427 | #endif |
---|
428 | |
---|
429 | dataStorage.ReadAccessDenied += delegate (Exception ex) |
---|
430 | { |
---|
431 | ShowErrorMessage("Could not read from data directory. " + ex.Message); |
---|
432 | }; |
---|
433 | dataStorage.WriteAccessDenied += delegate (Exception ex) |
---|
434 | { |
---|
435 | ShowErrorMessage("Could not write to data directory. " + ex.Message); |
---|
436 | }; |
---|
437 | |
---|
438 | DrawPerimeter = false; |
---|
439 | PerimeterColor = Color.DarkGray; |
---|
440 | |
---|
441 | phone = new Phone(); |
---|
442 | Phone.Tombstoning = true; |
---|
443 | } |
---|
444 | |
---|
445 | private void WindowResized( int oldWidth, int oldHeight, int newWidth, int newHeight ) |
---|
446 | { |
---|
447 | if ( GraphicsDevice == null ) |
---|
448 | return; |
---|
449 | |
---|
450 | if ( Mouse != null ) |
---|
451 | Mouse.Viewport = GraphicsDevice.Viewport; |
---|
452 | |
---|
453 | if ( screen != null ) |
---|
454 | screen.viewPort = GraphicsDevice.Viewport; |
---|
455 | } |
---|
456 | |
---|
457 | private void ShowErrorMessage(string message) |
---|
458 | { |
---|
459 | MessageDisplay.Add( "ERROR: " + message, Color.Red ); |
---|
460 | |
---|
461 | /*bool mouseVisible = IsMouseVisible; |
---|
462 | IsMouseVisible = true; |
---|
463 | |
---|
464 | MessageWindow errWindow = new MessageWindow( message ); |
---|
465 | errWindow.Color = Color.Red; |
---|
466 | errWindow.Message.TextColor = Color.White; |
---|
467 | errWindow.Closed += delegate { IsMouseVisible = mouseVisible; }; |
---|
468 | Add( errWindow );*/ |
---|
469 | } |
---|
470 | |
---|
471 | /// <summary> |
---|
472 | /// Näyttää viesti-ikkunan. |
---|
473 | /// </summary> |
---|
474 | /// <param name="message">Viesti</param> |
---|
475 | public void ShowMessageWindow( string message ) |
---|
476 | { |
---|
477 | MessageWindow w = new MessageWindow( message ); |
---|
478 | Add( w ); |
---|
479 | } |
---|
480 | |
---|
481 | private void InitializeLayers() |
---|
482 | { |
---|
483 | Layers = new SynchronousList<Layer>( -3 ); |
---|
484 | Layers.ItemAdded += OnLayerAdded; |
---|
485 | Layers.ItemRemoved += OnLayerRemoved; |
---|
486 | |
---|
487 | for ( int i = 0; i < 7; i++ ) |
---|
488 | { |
---|
489 | Layers.Add( new Layer() ); |
---|
490 | } |
---|
491 | |
---|
492 | // This is the widget layer |
---|
493 | Layers.Add( Layer.CreateStaticLayer() ); |
---|
494 | |
---|
495 | Layers.UpdateChanges(); |
---|
496 | } |
---|
497 | |
---|
498 | private void InitializeContent() |
---|
499 | { |
---|
500 | #if WINDOWS_PHONE |
---|
501 | |
---|
502 | ResourceContent = new ResourceContentManager( this.Services, WindowsPhoneResources.ResourceManager ); |
---|
503 | #elif XBOX |
---|
504 | ResourceContent = new ResourceContentManager( this.Services, XBox360Resources.ResourceManager ); |
---|
505 | #else |
---|
506 | ResourceContent = new ResourceContentManager( this.Services, Resources.ResourceManager ); |
---|
507 | #endif |
---|
508 | |
---|
509 | Content.RootDirectory = "Content"; |
---|
510 | } |
---|
511 | |
---|
512 | private void InitializeGraphics( int device ) |
---|
513 | { |
---|
514 | #if WINDOWS |
---|
515 | if ( device == 1 ) |
---|
516 | GraphicsDeviceManager = new GraphicsDeviceManager( this ); |
---|
517 | else |
---|
518 | GraphicsDeviceManager = new TargetedGraphicsDeviceManager( this, device ); |
---|
519 | #else |
---|
520 | GraphicsDeviceManager = new GraphicsDeviceManager( this ); |
---|
521 | #endif |
---|
522 | GraphicsDeviceManager.PreferredDepthStencilFormat = Jypeli.Graphics.SelectStencilMode(); |
---|
523 | SmoothTextures = true; |
---|
524 | } |
---|
525 | |
---|
526 | private void ActivateObject( ControlContexted obj ) |
---|
527 | { |
---|
528 | obj.ControlContext.Active = true; |
---|
529 | |
---|
530 | if ( obj.IsModal ) |
---|
531 | { |
---|
532 | Game.Instance.ControlContext.SaveFocus(); |
---|
533 | Game.Instance.ControlContext.Active = false; |
---|
534 | |
---|
535 | foreach ( Layer l in Layers ) |
---|
536 | { |
---|
537 | foreach ( IGameObject lo in l.Objects ) |
---|
538 | { |
---|
539 | ControlContexted co = lo as ControlContexted; |
---|
540 | if ( lo == obj || co == null ) |
---|
541 | continue; |
---|
542 | |
---|
543 | co.ControlContext.SaveFocus(); |
---|
544 | co.ControlContext.Active = false; |
---|
545 | } |
---|
546 | } |
---|
547 | } |
---|
548 | } |
---|
549 | |
---|
550 | private void DeactivateObject( ControlContexted obj ) |
---|
551 | { |
---|
552 | obj.ControlContext.Active = false; |
---|
553 | |
---|
554 | if ( obj.IsModal ) |
---|
555 | { |
---|
556 | Game.Instance.ControlContext.RestoreFocus(); |
---|
557 | |
---|
558 | foreach ( Layer l in Layers ) |
---|
559 | { |
---|
560 | foreach ( IGameObject lo in l.Objects ) |
---|
561 | { |
---|
562 | ControlContexted co = lo as ControlContexted; |
---|
563 | if ( lo == obj || co == null ) |
---|
564 | continue; |
---|
565 | |
---|
566 | co.ControlContext.RestoreFocus(); |
---|
567 | } |
---|
568 | } |
---|
569 | } |
---|
570 | } |
---|
571 | |
---|
572 | protected virtual void OnObjectAdded( IGameObject obj ) |
---|
573 | { |
---|
574 | IGameObjectInternal iObj = obj as IGameObjectInternal; |
---|
575 | if ( iObj == null ) return; |
---|
576 | iObj.IsAddedToGame = true; |
---|
577 | iObj.OnAddedToGame(); |
---|
578 | |
---|
579 | ControlContexted cObj = obj as ControlContexted; |
---|
580 | if ( cObj != null ) ActivateObject( cObj ); |
---|
581 | } |
---|
582 | |
---|
583 | protected virtual void OnObjectRemoved( IGameObject obj ) |
---|
584 | { |
---|
585 | IGameObjectInternal iObj = obj as IGameObjectInternal; |
---|
586 | if ( iObj == null ) return; |
---|
587 | iObj.IsAddedToGame = false; |
---|
588 | iObj.OnRemoved(); |
---|
589 | |
---|
590 | ControlContexted cObj = obj as ControlContexted; |
---|
591 | if ( cObj != null ) DeactivateObject( cObj ); |
---|
592 | } |
---|
593 | |
---|
594 | internal static void OnAddObject( IGameObject obj ) |
---|
595 | { |
---|
596 | Debug.Assert( Instance != null ); |
---|
597 | Instance.OnObjectAdded( obj ); |
---|
598 | } |
---|
599 | |
---|
600 | internal static void OnRemoveObject( IGameObject obj ) |
---|
601 | { |
---|
602 | Debug.Assert( Instance != null ); |
---|
603 | Instance.OnObjectRemoved( obj ); |
---|
604 | } |
---|
605 | |
---|
606 | private void OnLayerAdded( Layer l ) |
---|
607 | { |
---|
608 | l.Objects.ItemAdded += this.OnObjectAdded; |
---|
609 | l.Objects.ItemRemoved += this.OnObjectRemoved; |
---|
610 | } |
---|
611 | |
---|
612 | private void OnLayerRemoved( Layer l ) |
---|
613 | { |
---|
614 | l.Objects.ItemAdded -= this.OnObjectAdded; |
---|
615 | l.Objects.ItemRemoved -= this.OnObjectRemoved; |
---|
616 | } |
---|
617 | |
---|
618 | /// <summary> |
---|
619 | /// Suorittaa aliohjelman kun peli on varmasti alustettu. |
---|
620 | /// </summary> |
---|
621 | /// <param name="actionMethod">Suoritettava aliohjelma.</param> |
---|
622 | public static void AssertInitialized( Action actionMethod ) |
---|
623 | { |
---|
624 | if ( Instance != null ) |
---|
625 | actionMethod(); |
---|
626 | else |
---|
627 | InstanceInitialized += actionMethod; |
---|
628 | } |
---|
629 | |
---|
630 | /// <summary> |
---|
631 | /// Suorittaa aliohjelman seuraavalla päivityksellä. |
---|
632 | /// </summary> |
---|
633 | /// <param name="action"></param> |
---|
634 | public static void DoNextUpdate( Action action ) |
---|
635 | { |
---|
636 | if ( Instance != null ) |
---|
637 | Instance.PendingActions.Enqueue( action ); |
---|
638 | else |
---|
639 | InstanceInitialized += action; |
---|
640 | } |
---|
641 | |
---|
642 | /// <summary> |
---|
643 | /// Suorittaa aliohjelman seuraavalla päivityksellä. |
---|
644 | /// </summary> |
---|
645 | /// <typeparam name="T1"></typeparam> |
---|
646 | /// <param name="action"></param> |
---|
647 | /// <param name="p1"></param> |
---|
648 | public static void DoNextUpdate<T1>( Action<T1> action, T1 p1 ) |
---|
649 | { |
---|
650 | DoNextUpdate( delegate { action( p1 ); } ); |
---|
651 | } |
---|
652 | |
---|
653 | /// <summary> |
---|
654 | /// Suorittaa aliohjelman seuraavalla päivityksellä. |
---|
655 | /// </summary> |
---|
656 | /// <typeparam name="T1"></typeparam> |
---|
657 | /// <typeparam name="T2"></typeparam> |
---|
658 | /// <param name="action"></param> |
---|
659 | /// <param name="p1"></param> |
---|
660 | /// <param name="p2"></param> |
---|
661 | public static void DoNextUpdate<T1, T2>( Action<T1, T2> action, T1 p1, T2 p2 ) |
---|
662 | { |
---|
663 | DoNextUpdate( delegate { action( p1, p2 ); } ); |
---|
664 | } |
---|
665 | |
---|
666 | /// <summary> |
---|
667 | /// Suorittaa aliohjelman kun peli on varmasti alustettu. |
---|
668 | /// </summary> |
---|
669 | /// <param name="actionMethod">Suoritettava aliohjelma.</param> |
---|
670 | public static void AssertInitialized<T1>( Action<T1> actionMethod, T1 o1 ) |
---|
671 | { |
---|
672 | if ( Instance != null ) |
---|
673 | actionMethod( o1 ); |
---|
674 | else |
---|
675 | InstanceInitialized += delegate { actionMethod( o1 ); }; |
---|
676 | } |
---|
677 | |
---|
678 | /// <summary> |
---|
679 | /// Lisää olion peliin. |
---|
680 | /// Tavalliset oliot tulevat automaattisesti kerrokselle 0 |
---|
681 | /// ja ruutuoliot päällimmäiselle kerrokselle. |
---|
682 | /// </summary> |
---|
683 | public void Add( IGameObject o ) |
---|
684 | { |
---|
685 | if ( o.Layer != null && o.Layer.Objects.WillContain( o ) ) |
---|
686 | { |
---|
687 | if ( o.Layer == Layers[0] ) |
---|
688 | { |
---|
689 | throw new NotSupportedException( "Object cannot be added twice" ); |
---|
690 | } |
---|
691 | else |
---|
692 | throw new NotSupportedException( "Object cannot be added to multiple layers" ); |
---|
693 | } |
---|
694 | |
---|
695 | if ( o is Widget ) Add( o, MaxLayer ); |
---|
696 | else Add( o, 0 ); |
---|
697 | } |
---|
698 | |
---|
699 | #if !WINDOWS_PHONE |
---|
700 | /// <summary> |
---|
701 | /// Lisää valon peliin. Nykyisellään valoja voi olla ainoastaan |
---|
702 | /// yksi kappale. |
---|
703 | /// </summary> |
---|
704 | public void Add( Light light ) |
---|
705 | { |
---|
706 | if ( light == null ) throw new NullReferenceException( "Tried to add a null light to game" ); |
---|
707 | |
---|
708 | if ( lights.Count >= 1 ) |
---|
709 | throw new NotSupportedException( "Only one light is supported" ); |
---|
710 | |
---|
711 | lights.Add( light ); |
---|
712 | } |
---|
713 | #endif |
---|
714 | |
---|
715 | /// <summary> |
---|
716 | /// Lisää peliolion peliin, tiettyyn kerrokseen. |
---|
717 | /// </summary> |
---|
718 | /// <param name="o">Lisättävä olio.</param> |
---|
719 | /// <param name="layer">Kerros, luku väliltä [-3, 3].</param> |
---|
720 | public virtual void Add( IGameObject o, int layer ) |
---|
721 | { |
---|
722 | if ( o == null ) throw new NullReferenceException( "Tried to add a null object to game" ); |
---|
723 | Layers[layer].Add( o ); |
---|
724 | } |
---|
725 | |
---|
726 | internal static IList<IGameObject> GetObjectsAboutToBeAdded() |
---|
727 | { |
---|
728 | List<IGameObject> result = new List<IGameObject>(); |
---|
729 | |
---|
730 | foreach ( Layer layer in Game.Instance.Layers ) |
---|
731 | { |
---|
732 | layer.GetObjectsAboutToBeAdded( result ); |
---|
733 | } |
---|
734 | |
---|
735 | return result; |
---|
736 | } |
---|
737 | |
---|
738 | /// <summary> |
---|
739 | /// Lisää oliokerroksen peliin. |
---|
740 | /// </summary> |
---|
741 | /// <param name="l"></param> |
---|
742 | public void Add( Layer l ) |
---|
743 | { |
---|
744 | Layers.Add( l ); |
---|
745 | Layers.UpdateChanges(); |
---|
746 | } |
---|
747 | |
---|
748 | /// <summary> |
---|
749 | /// Poistaa olion pelistä. Jos haluat tuhota olion, |
---|
750 | /// kutsu mielummin olion <c>Destroy</c>-metodia. |
---|
751 | /// </summary> |
---|
752 | /// <remarks> |
---|
753 | /// Oliota ei poisteta välittömästi, vaan viimeistään seuraavan |
---|
754 | /// päivityksen jälkeen. |
---|
755 | /// </remarks> |
---|
756 | public void Remove( IGameObject o ) |
---|
757 | { |
---|
758 | if ( !o.IsAddedToGame ) |
---|
759 | return; |
---|
760 | |
---|
761 | foreach ( Layer l in Layers ) |
---|
762 | l.Remove( o ); |
---|
763 | } |
---|
764 | |
---|
765 | /// <summary> |
---|
766 | /// Poistaa oliokerroksen pelistä. |
---|
767 | /// </summary> |
---|
768 | /// <param name="l"></param> |
---|
769 | public void Remove( Layer l ) |
---|
770 | { |
---|
771 | Layers.Remove( l ); |
---|
772 | Layers.UpdateChanges(); |
---|
773 | } |
---|
774 | |
---|
775 | /// <summary> |
---|
776 | /// Palauttaa listan kaikista peliolioista jotka toteuttavat ehdon. |
---|
777 | /// Lista on järjestetty päällimmäisestä alimmaiseen. |
---|
778 | /// </summary> |
---|
779 | /// <param name="condition">Ehto</param> |
---|
780 | /// <returns>Lista olioista</returns> |
---|
781 | public List<GameObject> GetObjects( Predicate<GameObject> condition ) |
---|
782 | { |
---|
783 | List<GameObject> objs = new List<GameObject>(); |
---|
784 | |
---|
785 | for ( int i = MaxLayer; i >= MinLayer; i-- ) |
---|
786 | { |
---|
787 | foreach ( var obj in Layers[i].Objects ) |
---|
788 | { |
---|
789 | GameObject gobj = obj as GameObject; |
---|
790 | |
---|
791 | if ( gobj != null && condition( gobj ) ) |
---|
792 | objs.Add( gobj ); |
---|
793 | } |
---|
794 | } |
---|
795 | |
---|
796 | return objs; |
---|
797 | } |
---|
798 | |
---|
799 | /// <summary> |
---|
800 | /// Palauttaa listan kaikista peliolioista joilla on tietty tagi. |
---|
801 | /// Lista on järjestetty päällimmäisestä alimmaiseen. |
---|
802 | /// </summary> |
---|
803 | /// <param name="tags">Tagi(t)</param> |
---|
804 | /// <returns>Lista olioista</returns> |
---|
805 | public List<GameObject> GetObjectsWithTag( params string[] tags ) |
---|
806 | { |
---|
807 | return GetObjects( o => tags.Contains<string>( o.Tag as string ) ); |
---|
808 | } |
---|
809 | |
---|
810 | /// <summary> |
---|
811 | /// Palauttaa ensimmäisen peliolion joka toteuttaa ehdon (null jos mikään ei toteuta). |
---|
812 | /// </summary> |
---|
813 | /// <param name="condition">Ehto</param> |
---|
814 | /// <returns>Olio</returns> |
---|
815 | public GameObject GetFirstObject( Predicate<GameObject> condition ) |
---|
816 | { |
---|
817 | for ( int i = MaxLayer; i >= MinLayer; i-- ) |
---|
818 | { |
---|
819 | foreach ( var obj in Layers[i].Objects ) |
---|
820 | { |
---|
821 | GameObject gobj = obj as GameObject; |
---|
822 | |
---|
823 | if ( gobj != null && condition( gobj ) ) |
---|
824 | return gobj; |
---|
825 | } |
---|
826 | } |
---|
827 | |
---|
828 | return null; |
---|
829 | } |
---|
830 | |
---|
831 | /// <summary> |
---|
832 | /// Palauttaa ensimmäisen ruutuolion joka toteuttaa ehdon (null jos mikään ei toteuta). |
---|
833 | /// </summary> |
---|
834 | /// <param name="condition">Ehto</param> |
---|
835 | /// <returns>Lista olioista</returns> |
---|
836 | public Widget GetFirstWidget( Predicate<Widget> condition ) |
---|
837 | { |
---|
838 | return (Widget)GetFirstObject( obj => obj is Widget && condition( (Widget)obj ) ); |
---|
839 | } |
---|
840 | |
---|
841 | /// <summary> |
---|
842 | /// Palauttaa listan peliolioista, jotka ovat annetussa paikassa. |
---|
843 | /// Jos paikassa ei ole mitään pelioliota, palautetaan tyhjä lista. |
---|
844 | /// Lista on järjestetty päällimmäisestä alimmaiseen. |
---|
845 | /// </summary> |
---|
846 | /// <param name="position">Paikkakoordinaatit</param> |
---|
847 | /// <returns>Lista olioista</returns> |
---|
848 | public List<GameObject> GetObjectsAt( Vector position ) |
---|
849 | { |
---|
850 | return GetObjects( obj => obj.IsInside( position ) ); |
---|
851 | } |
---|
852 | |
---|
853 | /// <summary> |
---|
854 | /// Palauttaa peliolion, joka on annetussa paikassa. |
---|
855 | /// Jos paikassa ei ole mitään pelioliota, palautetaan null. |
---|
856 | /// Jos olioita on useampia, palautetaan päällimmäinen. |
---|
857 | /// </summary> |
---|
858 | /// <param name="position">Paikkakoordinaatit</param> |
---|
859 | /// <returns>Mahdollinen olio</returns> |
---|
860 | public GameObject GetObjectAt( Vector position ) |
---|
861 | { |
---|
862 | return GetFirstObject( obj => obj.IsInside( position ) && !(obj is MessageDisplay) ); |
---|
863 | } |
---|
864 | |
---|
865 | /// <summary> |
---|
866 | /// Palauttaa ruutuolion, joka on annetussa paikassa. |
---|
867 | /// Jos paikassa ei ole mitään oliota, palautetaan null. |
---|
868 | /// Jos olioita on useampia, palautetaan päällimmäinen. |
---|
869 | /// </summary> |
---|
870 | /// <param name="position">Paikkakoordinaatit</param> |
---|
871 | /// <returns>Mahdollinen ruutuolio</returns> |
---|
872 | public Widget GetWidgetAt( Vector position ) |
---|
873 | { |
---|
874 | return (Widget)GetFirstObject( obj => obj is Widget && obj.IsInside( position ) && !( obj is MessageDisplay ) ); |
---|
875 | } |
---|
876 | |
---|
877 | /// <summary> |
---|
878 | /// Palauttaa listan peliolioista, jotka ovat annetussa paikassa tietyllä säteellä. |
---|
879 | /// Jos paikassa ei ole mitään pelioliota, palautetaan tyhjä lista. |
---|
880 | /// Lista on järjestetty päällimmäisestä alimmaiseen. |
---|
881 | /// </summary> |
---|
882 | /// <param name="position">Paikkakoordinaatit</param> |
---|
883 | /// <param name="radius">Säde jolla etsitään</param> |
---|
884 | /// <returns>Lista olioista</returns> |
---|
885 | public List<GameObject> GetObjectsAt( Vector position, double radius ) |
---|
886 | { |
---|
887 | Predicate<GameObject> isInsideRadius = delegate ( GameObject obj ) |
---|
888 | { |
---|
889 | if ( obj is MessageDisplay ) return false; |
---|
890 | |
---|
891 | Vector positionUp = new Vector( position.X, position.Y + radius ); |
---|
892 | Vector positionDown = new Vector( position.X, position.Y - radius ); |
---|
893 | Vector positionLeft = new Vector( position.X - radius, position.Y ); |
---|
894 | Vector positionRight = new Vector( position.X + radius, position.Y ); |
---|
895 | |
---|
896 | if ( obj.IsInside( position ) ) return true; |
---|
897 | if ( obj.IsInside( positionUp ) ) return true; |
---|
898 | if ( obj.IsInside( positionDown ) ) return true; |
---|
899 | if ( obj.IsInside( positionLeft ) ) return true; |
---|
900 | if ( obj.IsInside( positionRight ) ) return true; |
---|
901 | |
---|
902 | return false; |
---|
903 | }; |
---|
904 | |
---|
905 | return GetObjects( isInsideRadius ); |
---|
906 | } |
---|
907 | |
---|
908 | /// <summary> |
---|
909 | /// Palauttaa peliolion, joka on annetussa paikassa tietyllä säteellä. |
---|
910 | /// Jos paikassa ei ole mitään pelioliota, palautetaan null. |
---|
911 | /// Jos olioita on useampia, palautetaan ensin lisätty. |
---|
912 | /// </summary> |
---|
913 | /// <param name="position">Paikkakoordinaatit</param> |
---|
914 | /// <param name="radius">Säde jolla etsitään</param> |
---|
915 | /// <returns>Mahdollinen olio</returns> |
---|
916 | public GameObject GetObjectAt( Vector position, double radius ) |
---|
917 | { |
---|
918 | var objs = GetObjectsAt( position, radius ); |
---|
919 | return objs.Count > 0 ? objs[0] : null; |
---|
920 | } |
---|
921 | |
---|
922 | /// <summary> |
---|
923 | /// Palauttaa listan peliolioista, jotka ovat annetussa paikassa tietyllä säteellä. |
---|
924 | /// Jos paikassa ei ole mitään pelioliota, palautetaan tyhjä lista. |
---|
925 | /// Lista on järjestetty päällimmäisestä alimmaiseen. |
---|
926 | /// Vain annetulla tagilla varustetut oliot huomioidaan. |
---|
927 | /// </summary> |
---|
928 | /// <param name="position">Paikkakoordinaatit</param> |
---|
929 | /// <param name="tag">Etsittävän olion tagi.</param> |
---|
930 | /// <returns>Lista olioista</returns> |
---|
931 | public List<GameObject> GetObjectsAt( Vector position, object tag ) |
---|
932 | { |
---|
933 | return GetObjectsAt( position ).FindAll( obj => obj.Tag == tag ); |
---|
934 | } |
---|
935 | |
---|
936 | /// <summary> |
---|
937 | /// Palauttaa peliolion, joka on annetussa paikassa. |
---|
938 | /// Vain annetulla tagilla varustetut oliot huomioidaan. |
---|
939 | /// Jos paikassa ei ole mitään pelioliota, palautetaan null. |
---|
940 | /// Jos olioita on useampia, palautetaan ensin lisätty. |
---|
941 | /// </summary> |
---|
942 | /// <param name="position">Paikkakoordinaatit</param> |
---|
943 | /// <param name="tag">Etsittävän olion tagi.</param> |
---|
944 | /// <returns>Mahdollinen olio</returns> |
---|
945 | public GameObject GetObjectAt( Vector position, object tag ) |
---|
946 | { |
---|
947 | return GetObjectsAt( position ).Find( obj => obj.Tag == tag ); |
---|
948 | } |
---|
949 | |
---|
950 | /// <summary> |
---|
951 | /// Palauttaa listan peliolioista, jotka ovat annetussa paikassa tietyllä säteellä. |
---|
952 | /// Jos paikassa ei ole mitään pelioliota, palautetaan tyhjä lista. |
---|
953 | /// Lista on järjestetty päällimmäisestä alimmaiseen. |
---|
954 | /// Vain annetulla tagilla varustetut oliot huomioidaan. |
---|
955 | /// </summary> |
---|
956 | /// <param name="position">Paikkakoordinaatit</param> |
---|
957 | /// <param name="tag">Etsittävän olion tagi.</param> |
---|
958 | /// <param name="radius">Säde jolla etsitään</param> |
---|
959 | /// <returns>Lista olioista</returns> |
---|
960 | public List<GameObject> GetObjectsAt( Vector position, object tag, double radius ) |
---|
961 | { |
---|
962 | return GetObjectsAt( position, radius ).FindAll<GameObject>( obj => obj.Tag == tag ); |
---|
963 | } |
---|
964 | |
---|
965 | /// <summary> |
---|
966 | /// Palauttaa peliolion, joka on annetussa paikassa tietyllä säteellä. |
---|
967 | /// Vain annetulla tagilla varustetut oliot huomioidaan. |
---|
968 | /// Jos paikassa ei ole mitään pelioliota, palautetaan null. |
---|
969 | /// Jos olioita on useampia, palautetaan ensin lisätty. |
---|
970 | /// </summary> |
---|
971 | /// <param name="position">Paikkakoordinaatit</param> |
---|
972 | /// <param name="tag">Etsittävän olion tagi.</param> |
---|
973 | /// <param name="radius">Säde jolla etsitään</param> |
---|
974 | /// <returns>Mahdollinen olio</returns> |
---|
975 | public GameObject GetObjectAt( Vector position, object tag, double radius ) |
---|
976 | { |
---|
977 | return GetObjectsAt( position, radius ).Find( obj => obj.Tag == tag ); |
---|
978 | } |
---|
979 | |
---|
980 | /// <summary> |
---|
981 | /// Palauttaa pelioliot kahden pisteen välillä. |
---|
982 | /// </summary> |
---|
983 | /// <param name="pos1"></param> |
---|
984 | /// <param name="pos2"></param> |
---|
985 | /// <returns></returns> |
---|
986 | public List<GameObject> GetObjectsBetween( Vector pos1, Vector pos2 ) |
---|
987 | { |
---|
988 | return GetObjects( obstacle => !( obstacle is Widget ) && obstacle.IsBlocking( pos1, pos2 ) ); |
---|
989 | } |
---|
990 | |
---|
991 | /// <summary> |
---|
992 | /// Lataa animaation contentista. |
---|
993 | /// </summary> |
---|
994 | /// <param name="name">Animaation nimi (ei tarkennetta)</param> |
---|
995 | /// <returns>Animation-olio</returns> |
---|
996 | public static Animation LoadAnimation( string name ) |
---|
997 | { |
---|
998 | return Instance.Content.Load<Animation>( name ); |
---|
999 | } |
---|
1000 | |
---|
1001 | /// <summary> |
---|
1002 | /// Lataa kuvan contentista. |
---|
1003 | /// </summary> |
---|
1004 | /// <param name="name">Kuvan nimi (ei tarkennetta)</param> |
---|
1005 | /// <returns>Image-olio</returns> |
---|
1006 | public static Image LoadImage( string name ) |
---|
1007 | { |
---|
1008 | return new Image( name ); |
---|
1009 | } |
---|
1010 | |
---|
1011 | /// <summary> |
---|
1012 | /// Lataa taulukon kuvia contentista. |
---|
1013 | /// </summary> |
---|
1014 | /// <param name="name">Kuvien nimet ilman tarkennetta pilkuin eroiteltuna</param> |
---|
1015 | /// <returns>Taulukko Image-olioita</returns> |
---|
1016 | public static Image[] LoadImages( params string[] names ) |
---|
1017 | { |
---|
1018 | Image[] result = new Image[names.Length]; |
---|
1019 | for ( int i = 0; i < names.Length; i++ ) |
---|
1020 | result[i] = LoadImage( names[i] ); |
---|
1021 | return result; |
---|
1022 | } |
---|
1023 | |
---|
1024 | /// <summary> |
---|
1025 | /// Lataa taulukon kuvia contentista. |
---|
1026 | /// </summary> |
---|
1027 | /// <param name="baseName">Ennen numeroa tuleva osa nimestä.</param> |
---|
1028 | /// <param name="startIndex">Ensimmäisen kuvan numero.</param> |
---|
1029 | /// <param name="endIndex">Viimeisen kuvan numero.</param> |
---|
1030 | /// <param name="zeroPad">Onko numeron edessä täytenollia.</param> |
---|
1031 | /// <returns></returns> |
---|
1032 | public static Image[] LoadImages( string baseName, int startIndex, int endIndex, bool zeroPad = false ) |
---|
1033 | { |
---|
1034 | if ( startIndex > endIndex ) throw new ArgumentException("Starting index must be smaller than ending index."); |
---|
1035 | |
---|
1036 | Image[] result = new Image[endIndex - startIndex]; |
---|
1037 | string format; |
---|
1038 | |
---|
1039 | if ( zeroPad ) |
---|
1040 | { |
---|
1041 | int digits = endIndex.ToString().Length; |
---|
1042 | format = "{0}{1:" + "0".Repeat( digits ) + "}"; |
---|
1043 | } |
---|
1044 | else |
---|
1045 | { |
---|
1046 | format = "{0}{1}"; |
---|
1047 | } |
---|
1048 | |
---|
1049 | for ( int i = startIndex; i < endIndex; i++ ) |
---|
1050 | { |
---|
1051 | string imgName = String.Format( format, baseName, i ); |
---|
1052 | result[i - startIndex] = LoadImage( imgName ); |
---|
1053 | } |
---|
1054 | |
---|
1055 | return result; |
---|
1056 | } |
---|
1057 | |
---|
1058 | /// <summary> |
---|
1059 | /// Soittaa ääniefektin. |
---|
1060 | /// </summary> |
---|
1061 | /// <param name="name">Äänen nimi (ei tarkennetta)</param> |
---|
1062 | public static void PlaySound( string name ) |
---|
1063 | { |
---|
1064 | LoadSoundEffect( name ).Play(); |
---|
1065 | } |
---|
1066 | |
---|
1067 | /// <summary> |
---|
1068 | /// Lataa ääniefektin contentista. |
---|
1069 | /// </summary> |
---|
1070 | /// <param name="name">Äänen nimi (ei tarkennetta)</param> |
---|
1071 | /// <returns>SoundEffect-olio</returns> |
---|
1072 | public static SoundEffect LoadSoundEffect( string name ) |
---|
1073 | { |
---|
1074 | return new SoundEffect( name ); |
---|
1075 | } |
---|
1076 | |
---|
1077 | /// <summary> |
---|
1078 | /// Lataa taulukon ääniefektejä contentista. |
---|
1079 | /// </summary> |
---|
1080 | /// <param name="names">Äänien nimet ilman tarkennetta pilkuin eroiteltuna</param> |
---|
1081 | /// <returns>Taulukko SoundEffect-olioita</returns> |
---|
1082 | public static SoundEffect[] LoadSoundEffects( params string[] names ) |
---|
1083 | { |
---|
1084 | SoundEffect[] result = new SoundEffect[names.Length]; |
---|
1085 | for ( int i = 0; i < names.Length; i++ ) |
---|
1086 | result[i] = LoadSoundEffect( names[i] ); |
---|
1087 | return result; |
---|
1088 | } |
---|
1089 | |
---|
1090 | /// <summary> |
---|
1091 | /// Poistaa kaikki ajastimet. |
---|
1092 | /// </summary> |
---|
1093 | public void ClearTimers() |
---|
1094 | { |
---|
1095 | Timer.ClearAll(); |
---|
1096 | } |
---|
1097 | |
---|
1098 | /// <summary> |
---|
1099 | /// Nollaa kaiken. |
---|
1100 | /// </summary> |
---|
1101 | public virtual void ClearAll() |
---|
1102 | { |
---|
1103 | Level.Clear(); |
---|
1104 | ResetLayers(); |
---|
1105 | ClearTimers(); |
---|
1106 | #if !WINDOWS_PHONE |
---|
1107 | ClearLights(); |
---|
1108 | #endif |
---|
1109 | ClearControls(); |
---|
1110 | GC.Collect(); |
---|
1111 | addMessageDisplay(); |
---|
1112 | ControlContext.Enable(); |
---|
1113 | Camera.Reset(); |
---|
1114 | } |
---|
1115 | |
---|
1116 | /// <summary> |
---|
1117 | /// Nollaa oliokerrokset. Huom. tuhoaa kaikki pelioliot! |
---|
1118 | /// </summary> |
---|
1119 | /// <param name="l"></param> |
---|
1120 | public void ResetLayers() |
---|
1121 | { |
---|
1122 | ClearGameObjects(); |
---|
1123 | InitializeLayers(); |
---|
1124 | } |
---|
1125 | |
---|
1126 | /// <summary> |
---|
1127 | /// Poistaa kaikki oliokerrokset. Huom. tuhoaa kaikki pelioliot! |
---|
1128 | /// </summary> |
---|
1129 | /// <param name="l"></param> |
---|
1130 | public void RemoveAllLayers() |
---|
1131 | { |
---|
1132 | ClearGameObjects(); |
---|
1133 | Layers.Clear(); |
---|
1134 | } |
---|
1135 | |
---|
1136 | /// <summary> |
---|
1137 | /// Palauttaa kontrollit alkutilaansa. |
---|
1138 | /// </summary> |
---|
1139 | public void ClearControls() |
---|
1140 | { |
---|
1141 | controls.Clear(); |
---|
1142 | TouchPanel.Clear(); |
---|
1143 | #if DEBUG && !WINDOWS_PHONE |
---|
1144 | Keyboard.Listen( Key.F12, ButtonState.Pressed, ToggleDebugScreen, null ); |
---|
1145 | #endif |
---|
1146 | } |
---|
1147 | |
---|
1148 | #if DEBUG |
---|
1149 | private void ToggleDebugScreen() |
---|
1150 | { |
---|
1151 | if ( isDebugScreenShown ) |
---|
1152 | isDebugScreenShown = false; |
---|
1153 | else |
---|
1154 | isDebugScreenShown = true; |
---|
1155 | } |
---|
1156 | #endif |
---|
1157 | |
---|
1158 | /// <summary> |
---|
1159 | /// Tuhoaa ja poistaa pelistä kaikki pelioliot (ml. fysiikkaoliot). |
---|
1160 | /// </summary> |
---|
1161 | public void ClearGameObjects() |
---|
1162 | { |
---|
1163 | foreach ( var layer in Layers ) |
---|
1164 | layer.Clear(); |
---|
1165 | |
---|
1166 | addMessageDisplay(); |
---|
1167 | } |
---|
1168 | |
---|
1169 | #if !WINDOWS_PHONE |
---|
1170 | public void ClearLights() |
---|
1171 | { |
---|
1172 | lights.Clear(); |
---|
1173 | } |
---|
1174 | #endif |
---|
1175 | |
---|
1176 | /// <summary> |
---|
1177 | /// Ajetaan Updaten sijaan kun peli on pysähdyksissä. |
---|
1178 | /// </summary> |
---|
1179 | protected virtual void PausedUpdate( Time time ) |
---|
1180 | { |
---|
1181 | foreach ( var layer in Layers ) |
---|
1182 | { |
---|
1183 | // Update the UI components only |
---|
1184 | layer.Objects.Update( time, o => o is Widget ); |
---|
1185 | } |
---|
1186 | |
---|
1187 | Timer.UpdateAll( time, t => t.IgnorePause ); |
---|
1188 | } |
---|
1189 | |
---|
1190 | /// <summary> |
---|
1191 | /// Ajetaan kun pelin tilannetta päivitetään. Päivittämisen voi toteuttaa perityssä luokassa |
---|
1192 | /// toteuttamalla tämän metodin. Perityn luokan metodissa tulee kutsua kantaluokan metodia. |
---|
1193 | /// </summary> |
---|
1194 | protected virtual void Update( Time time ) |
---|
1195 | { |
---|
1196 | this.Camera.Update( time ); |
---|
1197 | Layers.Update( time ); |
---|
1198 | Timer.UpdateAll( time ); |
---|
1199 | |
---|
1200 | while (PendingActions.Count > 0) |
---|
1201 | { |
---|
1202 | PendingActions.Dequeue()(); |
---|
1203 | } |
---|
1204 | } |
---|
1205 | |
---|
1206 | /// <summary> |
---|
1207 | /// This gets called after the GraphicsDevice has been created. So, this is |
---|
1208 | /// the place to initialize the resources needed in the game. Except the graphics content, |
---|
1209 | /// which should be called int LoadContent(), according to the XNA docs. |
---|
1210 | /// </summary> |
---|
1211 | [EditorBrowsable( EditorBrowsableState.Never )] |
---|
1212 | protected override void Initialize() |
---|
1213 | { |
---|
1214 | Jypeli.Graphics.Initialize(); |
---|
1215 | screen = new ScreenView( GraphicsDevice.Viewport ); |
---|
1216 | |
---|
1217 | #if WINDOWS_PHONE |
---|
1218 | Phone.ResetScreen(); |
---|
1219 | #else |
---|
1220 | Point defaultSize = GetDefaultWindowSize(); |
---|
1221 | Window.Width = defaultSize.X; |
---|
1222 | Window.Height = defaultSize.Y; |
---|
1223 | Window.Update(); |
---|
1224 | #endif |
---|
1225 | |
---|
1226 | theLevel = new Level( this ); |
---|
1227 | |
---|
1228 | MediaPlayer = new MediaPlayer( Content ); |
---|
1229 | |
---|
1230 | addMessageDisplay(); |
---|
1231 | |
---|
1232 | #if DEBUG |
---|
1233 | double barWidth = 20; |
---|
1234 | double barHeight = Screen.Height; |
---|
1235 | fpsDisplay = new Label( "00" ); |
---|
1236 | fpsDisplay.Color = Color.Gray; |
---|
1237 | fpsDisplay.X = Level.Right - barWidth / 2 - fpsDisplay.Width; |
---|
1238 | fpsDisplay.Y = Screen.Top - fpsDisplay.Height / 2; |
---|
1239 | |
---|
1240 | double left = Screen.Right - Layers.Count * barWidth; |
---|
1241 | |
---|
1242 | objectCountDisplays = new BarGauge[Layers.Count]; |
---|
1243 | |
---|
1244 | for ( int i = 0; i < Layers.Count; i++ ) |
---|
1245 | { |
---|
1246 | var gauge = new BarGauge( barWidth, Screen.Height ); |
---|
1247 | gauge.X = left + i * barWidth + barWidth / 2; |
---|
1248 | gauge.Y = Screen.Center.Y; |
---|
1249 | gauge.BarColor = Color.DarkGreen; |
---|
1250 | gauge.BindTo( Layers[i + Layers.FirstIndex].ObjectCount ); |
---|
1251 | objectCountDisplays[i] = gauge; |
---|
1252 | } |
---|
1253 | |
---|
1254 | Keyboard.Listen( Key.F12, ButtonState.Pressed, ToggleDebugScreen, null ); |
---|
1255 | #endif |
---|
1256 | |
---|
1257 | base.Initialize(); |
---|
1258 | } |
---|
1259 | |
---|
1260 | /// <summary> |
---|
1261 | /// XNA calls this when graphics resources need to be loaded. |
---|
1262 | /// Note that this can be called multiple times (whenever the graphics device is reset). |
---|
1263 | /// </summary> |
---|
1264 | [EditorBrowsable( EditorBrowsableState.Never )] |
---|
1265 | protected override void LoadContent() |
---|
1266 | { |
---|
1267 | if ( !loadContentHasBeenCalled ) |
---|
1268 | { |
---|
1269 | if ( InstanceInitialized != null ) |
---|
1270 | InstanceInitialized(); |
---|
1271 | |
---|
1272 | #if !WINDOWS_PHONE |
---|
1273 | CallBegin(); |
---|
1274 | #endif |
---|
1275 | loadContentHasBeenCalled = true; |
---|
1276 | } |
---|
1277 | |
---|
1278 | #if DEBUG && !WINDOWS_PHONE |
---|
1279 | MessageDisplay.Add( "F12 - Debug view" ); |
---|
1280 | #endif |
---|
1281 | base.LoadContent(); |
---|
1282 | |
---|
1283 | GC.Collect(); |
---|
1284 | } |
---|
1285 | |
---|
1286 | /// <summary> |
---|
1287 | /// Aloittaa pelin kutsumalla Begin-metodia. |
---|
1288 | /// Tärkeää: kutsu tätä, älä Beginiä suoraan, sillä muuten peli ei päivity! |
---|
1289 | /// </summary> |
---|
1290 | internal void CallBegin() |
---|
1291 | { |
---|
1292 | Begin(); |
---|
1293 | beginHasBeenCalled = true; |
---|
1294 | } |
---|
1295 | |
---|
1296 | /// <summary> |
---|
1297 | /// Tässä alustetaan peli. |
---|
1298 | /// </summary> |
---|
1299 | public virtual void Begin() |
---|
1300 | { |
---|
1301 | } |
---|
1302 | |
---|
1303 | /// <summary> |
---|
1304 | /// Tässä alustetaan peli tombstoning-tilasta. |
---|
1305 | /// Jos metodia ei ole määritelty, kutsutaan Begin. |
---|
1306 | /// </summary> |
---|
1307 | public virtual void Continue() |
---|
1308 | { |
---|
1309 | } |
---|
1310 | |
---|
1311 | protected override void OnExiting( object sender, EventArgs args ) |
---|
1312 | { |
---|
1313 | if ( Exiting != null ) |
---|
1314 | Exiting(); |
---|
1315 | |
---|
1316 | base.OnExiting( sender, args ); |
---|
1317 | } |
---|
1318 | |
---|
1319 | private void addMessageDisplay() |
---|
1320 | { |
---|
1321 | MessageDisplay = new MessageDisplay(); |
---|
1322 | MessageDisplay.BackgroundColor = Color.LightGray; |
---|
1323 | Add( MessageDisplay ); |
---|
1324 | } |
---|
1325 | |
---|
1326 | [EditorBrowsable( EditorBrowsableState.Never )] |
---|
1327 | protected override void Update( GameTime gameTime ) |
---|
1328 | { |
---|
1329 | if ( !loadContentHasBeenCalled || !beginHasBeenCalled ) |
---|
1330 | { |
---|
1331 | // No updates until both LoadContent and Begin have been called |
---|
1332 | base.Update( gameTime ); |
---|
1333 | return; |
---|
1334 | } |
---|
1335 | |
---|
1336 | Window.Update(); |
---|
1337 | currentRealTime.Advance( gameTime ); |
---|
1338 | |
---|
1339 | if ( this.IsActive ) controls.Update(); |
---|
1340 | if ( DataStorage.IsUpdated ) |
---|
1341 | DataStorage.Update( currentRealTime ); |
---|
1342 | |
---|
1343 | // The update in derived classes. |
---|
1344 | if ( !IsPaused ) |
---|
1345 | { |
---|
1346 | currentTime.Advance( gameTime ); |
---|
1347 | this.Update( currentTime ); |
---|
1348 | } |
---|
1349 | else |
---|
1350 | { |
---|
1351 | this.PausedUpdate( currentRealTime ); |
---|
1352 | } |
---|
1353 | |
---|
1354 | base.Update( gameTime ); |
---|
1355 | } |
---|
1356 | |
---|
1357 | protected virtual void Paint( Canvas canvas ) |
---|
1358 | { |
---|
1359 | } |
---|
1360 | |
---|
1361 | [EditorBrowsable( EditorBrowsableState.Never )] |
---|
1362 | protected override void Draw( GameTime gameTime ) |
---|
1363 | { |
---|
1364 | Time time = new Time( gameTime ); |
---|
1365 | |
---|
1366 | GraphicsDevice.Clear( ClearOptions.Target, Level.Background.Color.AsXnaColor(), 1.0f, 0 ); |
---|
1367 | |
---|
1368 | if ( Level.Background.Image != null && !Level.Background.MovesWithCamera ) |
---|
1369 | { |
---|
1370 | SpriteBatch spriteBatch = Jypeli.Graphics.SpriteBatch; |
---|
1371 | spriteBatch.Begin( SpriteSortMode.Deferred, BlendState.AlphaBlend ); |
---|
1372 | spriteBatch.Draw( Level.Background.Image.XNATexture, new XnaRectangle( 0, 0, (int)screen.Width, (int)screen.Height ), XnaColor.White ); |
---|
1373 | spriteBatch.End(); |
---|
1374 | } |
---|
1375 | |
---|
1376 | // The world matrix adjusts the position and size of objects according to the camera angle. |
---|
1377 | var worldMatrix = |
---|
1378 | Matrix.CreateTranslation( (float)-Camera.Position.X, (float)-Camera.Position.Y, 0 ) |
---|
1379 | * Matrix.CreateScale( (float)Camera.ZoomFactor, (float)Camera.ZoomFactor, 1f ); |
---|
1380 | |
---|
1381 | Renderer.LightingEnabled = true; |
---|
1382 | // If the background should move with camera, draw it here. |
---|
1383 | Level.Background.Draw( worldMatrix, Matrix.Identity ); |
---|
1384 | Renderer.LightingEnabled = false; |
---|
1385 | |
---|
1386 | if ( DrawPerimeter ) |
---|
1387 | { |
---|
1388 | Matrix m = Matrix.CreateScale( (float)Level.Width, (float)Level.Height, 1 ) * worldMatrix; |
---|
1389 | Renderer.DrawRectangle( ref m, PerimeterColor ); |
---|
1390 | } |
---|
1391 | |
---|
1392 | foreach ( var layer in Layers ) |
---|
1393 | { |
---|
1394 | layer.Draw( Camera ); |
---|
1395 | } |
---|
1396 | |
---|
1397 | Graphics.LineBatch.Begin( ref worldMatrix ); |
---|
1398 | Graphics.Canvas.Reset( Level ); |
---|
1399 | Paint( Graphics.Canvas ); |
---|
1400 | Graphics.LineBatch.End(); |
---|
1401 | |
---|
1402 | #if DEBUG |
---|
1403 | if ( isDebugScreenShown ) |
---|
1404 | { |
---|
1405 | DrawDebugView(); |
---|
1406 | } |
---|
1407 | #endif |
---|
1408 | |
---|
1409 | base.Draw( gameTime ); |
---|
1410 | } |
---|
1411 | |
---|
1412 | #if DEBUG |
---|
1413 | private void DrawDebugView() |
---|
1414 | { |
---|
1415 | for ( int i = 0; i < Layers.Count; i++ ) |
---|
1416 | { |
---|
1417 | objectCountDisplays[i].Draw( Matrix.Identity ); |
---|
1418 | } |
---|
1419 | |
---|
1420 | if ( fpsSkipCounter++ > 10 ) |
---|
1421 | { |
---|
1422 | fpsSkipCounter = 0; |
---|
1423 | fpsText = ( 1.0 / Time.SinceLastUpdate.TotalSeconds ).ToString( "F2" ); |
---|
1424 | } |
---|
1425 | |
---|
1426 | fpsDisplay.Text = fpsText; |
---|
1427 | fpsDisplay.Draw( Matrix.Identity ); |
---|
1428 | } |
---|
1429 | #endif |
---|
1430 | |
---|
1431 | /// <summary> |
---|
1432 | /// Asettaa ikkunan koon. |
---|
1433 | /// </summary> |
---|
1434 | /// <param name="width">Leveys.</param> |
---|
1435 | /// <param name="height">Korkeus.</param> |
---|
1436 | /// <param name="height">Käyttääkö peli koko ruutua.</param> |
---|
1437 | [Obsolete( "Please set Window.Width, Window.Height and Window.Fullscreen instead." )] |
---|
1438 | public bool SetWindowSize( int width, int height, bool fullscreen ) |
---|
1439 | { |
---|
1440 | Window.Width = width; |
---|
1441 | Window.Height = height; |
---|
1442 | Window.Fullscreen = fullscreen; |
---|
1443 | return true; |
---|
1444 | } |
---|
1445 | |
---|
1446 | /// <summary> |
---|
1447 | /// Asettaa ikkunan koon. |
---|
1448 | /// </summary> |
---|
1449 | /// <param name="width">Leveys.</param> |
---|
1450 | /// <param name="height">Korkeus.</param> |
---|
1451 | [Obsolete("Please set Window.Width and Window.Height instead.")] |
---|
1452 | public bool SetWindowSize( int width, int height ) |
---|
1453 | { |
---|
1454 | Window.Width = width; |
---|
1455 | Window.Height = height; |
---|
1456 | return true; |
---|
1457 | } |
---|
1458 | |
---|
1459 | private Point GetDefaultWindowSize() |
---|
1460 | { |
---|
1461 | int xres = GraphicsDevice.DisplayMode.Width; |
---|
1462 | int yres = GraphicsDevice.DisplayMode.Height; |
---|
1463 | |
---|
1464 | #if WINDOWS |
---|
1465 | int borderwidth = GetSystemMetrics( 32 ); // SM_CXFRAME |
---|
1466 | int titleheight = GetSystemMetrics( 30 ); // SM_CXSIZE |
---|
1467 | yres -= borderwidth + titleheight; |
---|
1468 | #endif |
---|
1469 | |
---|
1470 | /*if ( xres > 1024 && yres > 768 ) return new Point( 1024, 768 ); |
---|
1471 | if ( xres > 800 && yres > 600 ) return new Point( 800, 600 ); |
---|
1472 | |
---|
1473 | return new Point( 640, 480 );*/ |
---|
1474 | |
---|
1475 | return new Point( xres, yres ); |
---|
1476 | } |
---|
1477 | |
---|
1478 | /// <summary> |
---|
1479 | /// Pysäyttää pelin tai jatkaa sitä, jos se on jo pysäytetty. |
---|
1480 | /// </summary> |
---|
1481 | public void Pause() |
---|
1482 | { |
---|
1483 | IsPaused = !IsPaused; |
---|
1484 | } |
---|
1485 | |
---|
1486 | /// <summary> |
---|
1487 | /// Lopettaa pelin. |
---|
1488 | /// </summary> |
---|
1489 | public void Exit() |
---|
1490 | { |
---|
1491 | Phone.StopVibrating(); |
---|
1492 | base.Exit(); |
---|
1493 | } |
---|
1494 | |
---|
1495 | /// <summary> |
---|
1496 | /// Kysyy haluaako lopettaa pelin ja lopettaa jos vastataan kyllä. |
---|
1497 | /// </summary> |
---|
1498 | public void ConfirmExit() |
---|
1499 | { |
---|
1500 | bool cursorVisible = IsMouseVisible; |
---|
1501 | IsMouseVisible = true; |
---|
1502 | |
---|
1503 | YesNoWindow kyselyIkkuna = new YesNoWindow( "Do you want to quit?" ); |
---|
1504 | kyselyIkkuna.Yes += Exit; |
---|
1505 | kyselyIkkuna.Closed += delegate { IsMouseVisible = cursorVisible; IsPaused = false; }; |
---|
1506 | Add( kyselyIkkuna ); |
---|
1507 | |
---|
1508 | IsPaused = true; |
---|
1509 | } |
---|
1510 | |
---|
1511 | /// <summary> |
---|
1512 | /// Tallentaa pelin. |
---|
1513 | /// </summary> |
---|
1514 | /// <param name="tagName">Pelitilanteen nimi.</param> |
---|
1515 | public void SaveGame( string tagName ) |
---|
1516 | { |
---|
1517 | Type gameType = this.GetType(); |
---|
1518 | SaveState state = DataStorage.BeginSave( tagName ); |
---|
1519 | |
---|
1520 | foreach ( PropertyInfo property in gameType.GetProperties( BindingFlags.GetProperty | StorageFile.AllOfInstance ) ) |
---|
1521 | { |
---|
1522 | if ( property.GetCustomAttributes( typeof( SaveAttribute ), true ).Length == 0 ) |
---|
1523 | continue; |
---|
1524 | |
---|
1525 | object propValue = property.GetValue( this, null ); |
---|
1526 | Type propType = property.PropertyType; |
---|
1527 | //DataStorage.Save( propValue, propType, tagName + FileManager.SanitizeFileName( property.Name ) ); |
---|
1528 | state.Save( propValue, propType, FileManager.SanitizeFileName( property.Name ) + "Property" ); |
---|
1529 | } |
---|
1530 | |
---|
1531 | foreach ( FieldInfo field in gameType.GetFields( BindingFlags.GetField | StorageFile.AllOfInstance ) ) |
---|
1532 | { |
---|
1533 | if ( field.GetCustomAttributes( typeof( SaveAttribute ), true ).Length == 0 ) |
---|
1534 | continue; |
---|
1535 | |
---|
1536 | object fieldValue = field.GetValue( this ); |
---|
1537 | Type fieldType = field.FieldType; |
---|
1538 | //DataStorage.Save( fieldValue, fieldType, tagName + FileManager.SanitizeFileName( field.Name ) ); |
---|
1539 | state.Save( fieldValue, fieldType, FileManager.SanitizeFileName( field.Name ) + "Field" ); |
---|
1540 | } |
---|
1541 | |
---|
1542 | state.EndSave(); |
---|
1543 | } |
---|
1544 | |
---|
1545 | /// <summary> |
---|
1546 | /// Lataa pelin. |
---|
1547 | /// </summary> |
---|
1548 | /// <param name="tagName">Pelitilanteen nimi.</param> |
---|
1549 | public void LoadGame( string tagName ) |
---|
1550 | { |
---|
1551 | if ( !DataStorage.Exists( tagName ) ) |
---|
1552 | return; |
---|
1553 | |
---|
1554 | Type gameType = this.GetType(); |
---|
1555 | |
---|
1556 | LoadState state = DataStorage.BeginLoad( tagName ); |
---|
1557 | |
---|
1558 | foreach ( PropertyInfo property in gameType.GetProperties( BindingFlags.GetProperty | StorageFile.AllOfInstance ) ) |
---|
1559 | { |
---|
1560 | if ( property.GetCustomAttributes( typeof( SaveAttribute ), true ).Length == 0 ) |
---|
1561 | continue; |
---|
1562 | |
---|
1563 | object oldValue = property.GetValue( this, null ); |
---|
1564 | Type propType = property.PropertyType; |
---|
1565 | //object newValue = DataStorage.Load( oldValue, propType, tagName + FileManager.SanitizeFileName( property.Name ) ); |
---|
1566 | object newValue = state.Load( oldValue, propType, FileManager.SanitizeFileName( property.Name ) + "Property" ); |
---|
1567 | property.SetValue( this, newValue, null ); |
---|
1568 | } |
---|
1569 | |
---|
1570 | foreach ( FieldInfo field in gameType.GetFields( BindingFlags.GetField | StorageFile.AllOfInstance ) ) |
---|
1571 | { |
---|
1572 | if ( field.GetCustomAttributes( typeof( SaveAttribute ), true ).Length == 0 ) |
---|
1573 | continue; |
---|
1574 | |
---|
1575 | object oldValue = field.GetValue( this ); |
---|
1576 | Type fieldType = field.FieldType; |
---|
1577 | //object newValue = DataStorage.Load( oldValue, fieldType, tagName + FileManager.SanitizeFileName( field.Name ) ); |
---|
1578 | object newValue = state.Load( oldValue, fieldType, FileManager.SanitizeFileName( field.Name ) + "Field" ); |
---|
1579 | field.SetValue( this, newValue ); |
---|
1580 | } |
---|
1581 | |
---|
1582 | state.EndLoad(); |
---|
1583 | } |
---|
1584 | |
---|
1585 | public void AddFactory<T>( string tag, Factory.FactoryMethod method ) |
---|
1586 | { |
---|
1587 | Factory.AddFactory<T>( tag, method ); |
---|
1588 | } |
---|
1589 | |
---|
1590 | public void RemoveFactory<T>( string tag, Factory.FactoryMethod method ) |
---|
1591 | { |
---|
1592 | Factory.RemoveFactory<T>( tag, method ); |
---|
1593 | } |
---|
1594 | |
---|
1595 | public T FactoryCreate<T>( string tag ) |
---|
1596 | { |
---|
1597 | return Factory.FactoryCreate<T>( tag ); |
---|
1598 | } |
---|
1599 | |
---|
1600 | /// <summary> |
---|
1601 | /// Näyttää kontrollien ohjetekstit. |
---|
1602 | /// </summary> |
---|
1603 | public void ShowControlHelp() |
---|
1604 | { |
---|
1605 | MessageDisplay.Add( "Ohjeet:" ); |
---|
1606 | |
---|
1607 | foreach ( String message in controls.GetHelpTexts() ) |
---|
1608 | { |
---|
1609 | MessageDisplay.Add( message ); |
---|
1610 | } |
---|
1611 | } |
---|
1612 | |
---|
1613 | [EditorBrowsable( EditorBrowsableState.Never )] |
---|
1614 | public void Dispose() |
---|
1615 | { |
---|
1616 | } |
---|
1617 | |
---|
1618 | /// <summary> |
---|
1619 | /// Sitoo kontrollien ohjeet viestinäyttöön ja haluttuihin nappeihin. |
---|
1620 | /// Tämän jälkeen nappeja painamalla pelaaja saa automaattisesti ohjeen esille. |
---|
1621 | /// </summary> |
---|
1622 | /// <param name="keysOrButtons">Napit, joita painamalla ohjeen saa näkyviin.</param> |
---|
1623 | private void BindControlHelp( params object[] keysOrButtons ) |
---|
1624 | { |
---|
1625 | String nappaimet = ""; |
---|
1626 | |
---|
1627 | foreach ( object o in keysOrButtons ) |
---|
1628 | { |
---|
1629 | if ( o is Key ) |
---|
1630 | { |
---|
1631 | Key k = (Key)o; |
---|
1632 | controls.Keyboard.Listen( k, ButtonState.Pressed, ShowControlHelp, null ); |
---|
1633 | |
---|
1634 | nappaimet += k.ToString(); |
---|
1635 | } |
---|
1636 | |
---|
1637 | if ( o is Button ) |
---|
1638 | { |
---|
1639 | Button b = (Button)o; |
---|
1640 | for ( int i = 0; i < controls.GameControllers.Length; i++ ) |
---|
1641 | { |
---|
1642 | controls.GameControllers[i].Listen( b, ButtonState.Pressed, ShowControlHelp, null ); |
---|
1643 | } |
---|
1644 | |
---|
1645 | nappaimet += b.ToString(); |
---|
1646 | } |
---|
1647 | |
---|
1648 | nappaimet += " / "; |
---|
1649 | } |
---|
1650 | |
---|
1651 | MessageDisplay.Add( "Katso näppäinohje painamalla " + nappaimet.Substring( 0, nappaimet.Length - 3 ) ); |
---|
1652 | } |
---|
1653 | |
---|
1654 | public static Image LoadImageFromResources( string name ) |
---|
1655 | { |
---|
1656 | return new Image( ResourceContent.Load<Texture2D>( name ) ); |
---|
1657 | } |
---|
1658 | |
---|
1659 | public static SoundEffect LoadSoundEffectFromResources( string name ) |
---|
1660 | { |
---|
1661 | return new SoundEffect( ResourceContent.Load<XnaSoundEffect>( name ) ); |
---|
1662 | } |
---|
1663 | |
---|
1664 | /// <summary> |
---|
1665 | /// Lataa fontin. Fontin tulee olla lisätty content-hakemistoon. |
---|
1666 | /// </summary> |
---|
1667 | /// <param name="name">Fontin tiedoston nimi, ilman päätettä.</param> |
---|
1668 | public static Font LoadFont( string name ) |
---|
1669 | { |
---|
1670 | return new Font( name, ContentSource.GameContent ); |
---|
1671 | } |
---|
1672 | } |
---|
1673 | } |
---|
1674 | |
---|