Jypeli 10
The simple game programming library
Game.cs
Siirry tämän tiedoston dokumentaatioon.
1#region MIT License
2/*
3 * Copyright (c) 2018 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 */
24using System.IO;
25
26
27#endregion
28
29/*
30 * Authors: Tero Jäntti, Tomi Karppinen, Janne Nikkanen, Rami Pasanen.
31 */
32
33using System;
34using System.ComponentModel;
35using System.Linq;
36using Microsoft.Xna.Framework;
37using Microsoft.Xna.Framework.Graphics;
38using Jypeli.Devices;
39
40using XnaColor = Microsoft.Xna.Framework.Color;
41using XnaRectangle = Microsoft.Xna.Framework.Rectangle;
42#if ANDROID
44#endif
45
46namespace Jypeli
47{
48 [Save]
49 public partial class Game : Microsoft.Xna.Framework.Game, GameObjectContainer
50 {
51 private bool loadContentHasBeenCalled = false;
52 private bool beginHasBeenCalled = false;
53
58 public int TotalFramesToRun { get; private set; }
59
63 public int FrameCounter { get; private set; }
64
68 public int SavedFrameCounter { get; private set; }
69
73 public int FramesToSkip { get; private set; }
74
75 private int skipcounter = 0;
76
81 public bool SaveOutput { get; private set; }
82
86 public bool SaveOutputToConsole { get; private set; }
87
91 public bool Headless { get; private set; }
92
96 public static Game Instance { get; private set; }
97
101 public static Device Device { get; private set; }
102
107 public static FileManager DataStorage { get { return Device.Storage; } }
108
113 public bool FarseerGame { get; set; }
114
118 [EditorBrowsable(EditorBrowsableState.Never)]
119 [Obsolete( "Käytä Device-oliota" )]
121 {
122 get { return Device; }
123 }
124
129 [Save]
130 public Camera Camera { get; set; }
131
135 public static string Name { get; private set; }
136
140 public static bool AudioEnabled { get; private set; }
141
145 public Level Level { get; private set; }
146
147 private Stream CurrentFrameStream => !SaveOutputToConsole ? new FileStream(Path.Combine("Output", $"{SavedFrameCounter}.bmp"), FileMode.Create) : standardOutStream.Value;
148
149 private readonly Lazy<Stream> standardOutStream = new Lazy<Stream>(Console.OpenStandardOutput);
150
151
152#if ANDROID
156 internal VirtualKeyboard VirtualKeyboard { get; private set; }
157#endif
158
162 public Game()
163 : base()
164 {
165 InitGlobals();
168 InitAudio();
169 }
170
178 public void Run(bool headless = false, bool save = false, int frames = 0, int skip = 1)
179 {
180 if (frames < 0) throw new ArgumentException("n must be greater than 0!");
181 TotalFramesToRun = frames;
182 SaveOutput = save;
183 Headless = headless;
184 FramesToSkip = skip;
185
186 ApplyCMDArgs();
187
188 if (SaveOutput && !Directory.Exists("Output"))
189 {
190 Directory.CreateDirectory("Output");
191 }
192 base.Run();
193 }
194
195 private void ApplyCMDArgs()
196 {
197 string[] args = Environment.GetCommandLineArgs();
198 if (args.Contains("--save"))
199 {
200 if (bool.TryParse(args[Array.IndexOf(args, "--save") + 1], out bool save))
201 SaveOutput = save;
202 else
203 throw new ArgumentException("Invalid value for --save");
204 }
205 if (args.Contains("--framesToRun"))
206 {
207 if (int.TryParse(args[Array.IndexOf(args, "--framesToRun") + 1], out int frames))
208 TotalFramesToRun = frames;
209 else
210 throw new ArgumentException("Invalid value for --framesToRun");
211 }
212 if (args.Contains("--headless"))
213 {
214 if (bool.TryParse(args[Array.IndexOf(args, "--headless") + 1], out bool headless))
215 Headless = headless;
216 else
217 throw new ArgumentException("Invalid value for --headless");
218 }
219 if (args.Contains("--skipFrames"))
220 {
221 if (int.TryParse(args[Array.IndexOf(args, "--skipFrames") + 1], out int skip))
222 FramesToSkip = skip;
223 else
224 throw new ArgumentException("Invalid value for --skipFrames");
225 }
226 if (args.Contains("--saveToStdout"))
227 {
228 if (bool.TryParse(args[Array.IndexOf(args, "--saveToStdout") + 1], out bool saveToStdout))
229 SaveOutputToConsole = saveToStdout;
230 else
231 throw new ArgumentException("Invalid value for --saveToStdout");
232 }
233 }
234
235 internal static void DisableAudio()
236 {
237 AudioEnabled = false;
238 }
239
244 public void RunOneFrame( string bmpOutName )
245 {
246 base.RunOneFrame();
247 FileStream screenFile = new FileStream( bmpOutName, FileMode.Create );
248 Screencap.WriteBmp( screenFile, Screen.Image );
249 screenFile.Close();
250 OnExiting(this, EventArgs.Empty);
251 UnloadContent();
252 Exit();
253 }
254
255
257 {
258 Name = this.GetType().Assembly.FullName.Split( ',' )[0];
259 Instance = this;
260 Device = Device.Create();
261 }
262
263 private void InitXnaGraphics()
264 {
266 GraphicsDeviceManager.PreferredDepthStencilFormat = Jypeli.Graphics.SelectStencilMode();
267
268#if ANDROID
269 GraphicsDeviceManager.PreferredBackBufferWidth = 800;
270 GraphicsDeviceManager.PreferredBackBufferHeight = 480;
271#endif
272 }
273
274 private void InitAudio()
275 {
276 if(!Headless)
277 AudioEnabled = true;
278 }
279
281 {
282 MessageDisplay.Add( "No audio hardware was detected. All sound is disabled." );
283 //TODO: Can this still happen?
284#if WINDOWS
285 MessageDisplay.Add( "You might need to install OpenAL drivers." );
286 MessageDisplay.Add( "Press Ctrl+Alt+I to try downloading and installing them now." );
287
288 Keyboard.Listen( Key.I, ButtonState.Pressed, TryInstallOpenAL, null );
289#endif
290 }
291
292#if WINDOWS
293 private void TryInstallOpenAL()
294 {
295 if ( !Keyboard.IsCtrlDown() || !Keyboard.IsAltDown() )
296 return;
297
298 MessageDisplay.Add( "Starting download of OpenAL installer..." );
299 HttpWebRequest request = (HttpWebRequest)WebRequest.Create( "https://github.com/Mono-Game/MonoGame.Dependencies/raw/master/oalinst.exe" );
300 request.BeginGetResponse( OpenALDownloaded, request );
301 }
302
303 private void OpenALDownloaded(IAsyncResult result)
304 {
305 HttpWebResponse response = ( result.AsyncState as HttpWebRequest ).EndGetResponse( result ) as HttpWebResponse;
306
307 if ( response == null )
308 {
309 MessageDisplay.Add( "Download failed." );
310 return;
311 }
312
313 MessageDisplay.Add( "Download completed. Launching installer..." );
314 Stream resStream = response.GetResponseStream();
315
316 string fileName = Path.Combine( Path.GetTempPath(), "oalinst.exe" );
317 FileStream fs = new FileStream( fileName, FileMode.Create, FileAccess.Write );
318 resStream.CopyTo( fs );
319 fs.Close();
320
321 var startInfo = new System.Diagnostics.ProcessStartInfo( fileName );
322 startInfo.Verb = "runas";
323 var process = System.Diagnostics.Process.Start( startInfo );
324 process.WaitForExit();
325
326 MessageDisplay.Add( "Installation complete. Trying to enable sound..." );
327 InitAudio();
328 }
329#endif
330
336 [EditorBrowsable( EditorBrowsableState.Never )]
337 protected override void Initialize()
338 {
339 if ( !windowSizeSet )
341
342 if ( !windowPositionSet )
343 CenterWindow();
344
345 Level = new Level( this );
346 base.Initialize();
347
348#if ANDROID
349 VirtualKeyboard = new VirtualKeyboard(this);
350 Components.Add(VirtualKeyboard);
351 VirtualKeyboard.Initialize();
352 VirtualKeyboard.Hide();
353#endif
354
355 //Activated += (e, sender) => { IsActive = true; };
356 //Deactivated += (e, sender) => { IsActive = false; };
357 }
358
362 protected override void LoadContent()
363 {
364 // Graphics initialization is best done here when window size is set for certain
365 InitGraphics();
367 InitControls();
368 InitLayers();
370
371 if ( InstanceInitialized != null )
373
374 base.LoadContent();
377 CallBegin();
378 }
379
384 [EditorBrowsable( EditorBrowsableState.Never )]
385 protected override void Draw( GameTime gameTime )
386 {
387 //Console.WriteLine(gameTime.ElapsedGameTime.Milliseconds);
388 UpdateFps(gameTime);
389 GraphicsDevice.SetRenderTarget( Screen.RenderTarget );
391
392 if ( Level.Background.Image != null && !Level.Background.MovesWithCamera )
393 {
394 SpriteBatch spriteBatch = Jypeli.Graphics.SpriteBatch;
395 spriteBatch.Begin( SpriteSortMode.Deferred, BlendState.AlphaBlend );
396 spriteBatch.Draw( Level.Background.Image.XNATexture, new XnaRectangle( 0, 0, (int)Screen.Width, (int)Screen.Height ), XnaColor.White );
397 spriteBatch.End();
398 }
399
400 // The world matrix adjusts the position and size of objects according to the camera angle.
401 var worldMatrix =
402 Matrix.CreateTranslation( (float)-Camera.Position.X, (float)-Camera.Position.Y, 0 )
403 * Matrix.CreateScale( (float)Camera.ZoomFactor, (float)Camera.ZoomFactor, 1f );
404
405 // If the background should move with camera, draw it here.
406 Level.Background.Draw( worldMatrix, Matrix.Identity );
407
408 // Draw the layers containing the GameObjects
409 Layers.ForEach( l => l.Draw( Camera ) );
410
411 // Draw on the canvas
412 Graphics.Canvas.Begin( ref worldMatrix, Level );
415
416 // Draw the debug information screen
418
419 // Render the scene on screen
420 Screen.Render();
421
422 base.Draw( gameTime );
423
424 if (SaveOutput)
425 {
426 if (FrameCounter != 0) // Ekaa framea ei voi tallentaa?
427 if(skipcounter == 0)
428 {
432 }
433 else
434 {
435 skipcounter--;
436 }
437 }
438
440 {
441 OnExiting(this, EventArgs.Empty);
442 UnloadContent();
443 Exit();
444 }
445
446 FrameCounter++;
447 }
448
452 public virtual void ClearAll()
453 {
454 Level.Clear();
455 ResetLayers();
456 ClearTimers();
457 ClearLights();
459 GC.Collect();
460 ControlContext.Enable();
462 Camera.Reset();
463 IsPaused = false;
464 }
465
470 internal void CallBegin()
471 {
472 Begin();
473 beginHasBeenCalled = true;
474 }
475
479 public virtual void Begin()
480 {
481 }
482
487 protected virtual void Paint( Canvas canvas )
488 {
489 }
490 }
491}
Microsoft.Xna.Framework.Rectangle XnaRectangle
Microsoft.Xna.Framework.Color XnaColor
Kamera. Määrittää mikä osa pelitasosta on kerralla näkyvissä.
Definition: Camera.cs:40
Vector Position
Kameran sijainti.
Definition: Camera.cs:53
double ZoomFactor
Kameran zoomauskerroin. Oletuksena 1.0. Mitä suurempi zoomauskerroin, sitä lähempänä kamera on (esim ...
Definition: Camera.cs:99
void Reset()
Resetoi kameran (keskittää, laittaa zoomin oletusarvoon ja lopettaa seuraamisen).
Definition: Camera.cs:232
Piirtoalusta.
Definition: Canvas.cs:39
void End()
Lopettaa piirtämisen. Sinun ei tarvitse kutsua tätä.
Definition: Canvas.cs:111
void Begin(ref Matrix worldMatrix, Dimensional dimensionSource)
Aloittaa canvaksen piirtämisen. Sinun ei tarvitse kutsua tätä.
Definition: Canvas.cs:99
Fyysinen laite.
Definition: Device.cs:37
FileManager Storage
Tiedostojen säilytyspaikka.
Definition: Device.cs:49
static Device Create()
Definition: Device.cs:110
virtual void ResetScreen()
Definition: Device.cs:170
void InitControls()
Definition: Controls.cs:118
int FramesToSkip
Kuinka monenen framen yli hypätään peliä nauhoittaessa.
Definition: Game.cs:73
bool loadContentHasBeenCalled
Definition: Game.cs:51
void InitXnaGraphics()
Definition: Game.cs:263
override void OnExiting(object sender, EventArgs args)
Suoritetaan kun peli on sulkeutumassa
MessageDisplay MessageDisplay
Viestinäyttö, johon voi laittaa viestejä.
Definition: Widgets.cs:9
static bool AudioEnabled
Voiko ääniä soittaa.
Definition: Game.cs:140
Level Level
Aktiivinen kenttä.
Definition: Game.cs:145
Game()
Alustaa pelin.
Definition: Game.cs:162
static new GraphicsDevice GraphicsDevice
XNA:n grafiikkakortti.
Definition: Graphics.cs:49
ListenContext ControlContext
Pelin pääohjainkonteksti.
Definition: Controls.cs:98
void ClearControls()
Poistaa kaikki ohjainkuuntelijat.
Definition: Controls.cs:159
Device Phone
Phone-olio esim. puhelimen tärisyttämiseen.
Definition: Game.cs:121
override void Draw(GameTime gameTime)
XNA:n piirtorutiinit.
Definition: Game.cs:385
static GraphicsDeviceManager GraphicsDeviceManager
XNA:n grafiikkakorttien hallintaolio.
Definition: Graphics.cs:61
bool FarseerGame
Onko käytössä Farseer-fysiikkamoottori HUOM: Tämä saattaa poistua tulevaisuudessa jos/kun siitä tehdä...
Definition: Game.cs:113
void addMessageDisplay(bool force=false)
Definition: Widgets.cs:11
void ClearLights()
Poistaa kaikki valoefektit.
Definition: Effects.cs:42
void Run(bool headless=false, bool save=false, int frames=0, int skip=1)
Ajaa pelin. Kutsutaan Ohjelma.cs:stä.
Definition: Game.cs:178
void OnNoAudioHardwareException()
Definition: Game.cs:280
Stream CurrentFrameStream
Definition: Game.cs:147
virtual void Begin()
Tässä alustetaan peli.
Definition: Game.cs:479
bool SaveOutput
Tallennetaanko pelin kuvaa. Vie oletusresoluutiolla noin 3MB/frame
Definition: Game.cs:81
override void Initialize()
This gets called after the GraphicsDevice has been created. So, this is the place to initialize the r...
Definition: Game.cs:337
void ApplyCMDArgs()
Definition: Game.cs:195
static void DisableAudio()
Definition: Game.cs:235
void InitGlobals()
Definition: Game.cs:256
virtual void ClearAll()
Tuhoaa kaikki pelioliot, ajastimet ja näppäinkuuntelijat, sekä resetoi kameran.
Definition: Game.cs:452
void DrawDebugScreen()
Definition: DebugScreen.cs:195
int FrameCounter
Kuinka monta pelinpäivitystä on tähän mennessä ajettu.
Definition: Game.cs:63
bool windowSizeSet
Definition: Graphics.cs:41
void CenterWindow()
Asettaa ikkunan ruudun keskelle.
Definition: Graphics.cs:120
bool beginHasBeenCalled
Definition: Game.cs:52
void InitXnaContent()
Definition: Content.cs:69
int TotalFramesToRun
Kuinka monen pelinpäivityksen jälkeen peli suljetaan automaattisesti. Jos 0, peli pyörii ikuisesti
Definition: Game.cs:58
static string Name
Pelin nimi.
Definition: Game.cs:135
void InitGraphics()
Alustaa grafiikat. Suorita vasta kun ikkuna on lopullisessa koossaan.
Definition: Graphics.cs:229
override void LoadContent()
XNA:n sisällön alustus (Initializen jälkeen)
Definition: Game.cs:362
virtual void Paint(Canvas canvas)
Canvakselle piirto.
Definition: Game.cs:487
bool IsPaused
Onko peli pysähdyksissä.
Definition: Time.cs:17
void CallBegin()
Aloittaa pelin kutsumalla Begin-metodia. Tärkeää: kutsu tätä, älä Beginiä suoraan,...
Definition: Game.cs:470
void ClearTimers()
Poistaa kaikki ajastimet.
Definition: Time.cs:51
static FileManager DataStorage
Tietovarasto, johon voi tallentaa tiedostoja pidempiaikaisesti. Sopii esimerkiksi pelitilanteen lataa...
Definition: Game.cs:107
SynchronousList< Layer > Layers
Kerrokset, joilla pelioliot viihtyvät.
Definition: Layers.cs:14
void RunOneFrame(string bmpOutName)
Ajaa yhden päivityksen ja tallentaa ruudun tiedostoon.
Definition: Game.cs:244
static Game Instance
Käynnissä olevan pelin pääolio.
Definition: Game.cs:96
void SetDefaultResolution()
Definition: Graphics.cs:97
bool SaveOutputToConsole
Kirjoitetaanko kuvatiedosto standarditulosteeseen jos SaveOutput on päällä.
Definition: Game.cs:86
bool windowPositionSet
Definition: Graphics.cs:42
void InitLayers()
Definition: Layers.cs:78
static ScreenView Screen
Näytön dimensiot, eli koko ja reunat.
Definition: Graphics.cs:90
static Device Device
Laite jolla peliä pelataan.
Definition: Game.cs:101
int SavedFrameCounter
Kuinka monta pelinpäivitystä on tähän mennessä tallennettu.
Definition: Game.cs:68
void ResetLayers()
Nollaa oliokerrokset. Huom. tuhoaa kaikki pelioliot!
Definition: Layers.cs:248
void UpdateFps(GameTime gameTime)
Jypelin aika pitää sisällään tiedon edellisestä pelin päivityksestä, MonoGamen aika edellisestä ruudu...
Definition: DebugScreen.cs:142
void InitDebugScreen()
Definition: DebugScreen.cs:99
static Action InstanceInitialized
Tapahtuu kun Game.Instance on alustettu.
readonly Lazy< Stream > standardOutStream
Definition: Game.cs:149
void InitAudio()
Definition: Game.cs:274
int skipcounter
Definition: Game.cs:75
bool Headless
Ajetaanko peli ilman ääntä (esim. TIMissä)
Definition: Game.cs:91
Contains graphics resources.
Definition: Graphics.cs:36
static DepthFormat SelectStencilMode()
Definition: Graphics.cs:111
static SpriteBatch SpriteBatch
Definition: Graphics.cs:40
static Canvas Canvas
Definition: Graphics.cs:51
Näppäimistö.
Definition: Keyboard.cs:41
Listener Listen(Key k, ButtonState state, Action handler, string helpText)
Kuuntelee näppäinten painalluksia.
Definition: Keyboard.cs:161
bool IsAltDown()
Tarkistaa, onko kumpikaan alt-näppäimistä painettuna.
Definition: Keyboard.cs:149
bool IsCtrlDown()
Tarkistaa, onko kumpikaan ctrl-näppäimistä painettuna.
Definition: Keyboard.cs:138
Pelikenttä, johon voi lisätä olioita. Kentällä voi myös olla reunat ja taustaväri tai taustakuva.
Definition: Borders.cs:6
Background Background
Kentän taustakuva.
Definition: Level.cs:103
void Clear()
Definition: Level.cs:182
Color BackgroundColor
Kentän taustaväri.
Definition: Level.cs:95
Viestikenttä, jolla voi laittaa tekstiä ruudulle. Tätä sinun tuskin tarvitsee itse muodostaa.
void Add(string message)
Lisää uuden viestin näkymään.
double Width
Näytön leveys x-suunnassa.
Definition: View.cs:222
double Height
Näytön korkeus y-suunnassa.
Definition: View.cs:235
RenderTarget2D RenderTarget
Tekstuuri johon näkymä piirretään.
Definition: View.cs:69
Image Image
Ruudulla näkyvä kuva.
Definition: View.cs:100
void Render()
Definition: View.cs:442
static void WriteBmp(Stream outStream, Jypeli.Image image)
Definition: Screencap.cs:10
ButtonState
Napin (minkä tahansa) asento.
Definition: ButtonState.cs:37
Key
Näppäimistön näppäin.
Definition: Key.cs:39
@ Exit
Poistumassa olion päältä.
Microsoft.Xna.Framework.Matrix Matrix
Definition: Mouse.cs:36
XnaColor AsXnaColor()
Definition: Color.cs:46
double Y
Vektorin Y-komponentti
Definition: Vector.cs:339
double X
Vektorin X-komponentti.
Definition: Vector.cs:334