Jypeli  5
The simple game programming library
Camera.cs
Siirry tämän tiedoston dokumentaatioon.
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 Microsoft.Xna.Framework;
32 using AdvanceMath;
33 using Microsoft.Xna.Framework.Graphics;
34 using System.Collections.Generic;
35 
36 namespace Jypeli
37 {
41  [Save]
42  public class Camera
43  {
44  // Huom. tätä käytetään vain jos seurataan useita olioita kerralla
45  private List<GameObject> followedObjects = null;
46 
47  [Save]
48  internal bool _stayInLevel = false;
49  [Save]
50  internal double _zoomFactor = 1.0;
51 
55  [Save]
57 
61  [Save]
63 
67  public double X
68  {
69  get
70  {
71  return Position.X;
72  }
73  set
74  {
75  Position = new Vector( value, Position.Y );
76  }
77  }
78 
82  public double Y
83  {
84  get
85  {
86  return Position.Y;
87  }
88  set
89  {
90  Position = new Vector( Position.X, value );
91  }
92  }
93 
98  public double ZoomFactor
99  {
100  get { return _zoomFactor; }
101  set { _zoomFactor = value; }
102  }
103 
107  public bool StayInLevel
108  {
109  get { return _stayInLevel; }
110  set { _stayInLevel = value; }
111  }
112 
116  public GameObject FollowedObject { get; set; }
117 
121  public bool FollowsX { get; set; }
122 
126  public bool FollowsY { get; set; }
127 
140  [Save]
141  public Vector FollowOffset { get; set; }
142 
147  public double FollowXMargin { get; set; }
148 
153  public double FollowYMargin { get; set; }
154 
158  internal Camera()
159  {
160  FollowsX = true;
161  FollowsY = true;
163  }
164 
168  public Vector ScreenToWorld( Vector point )
169  {
170  return Position + ( 1 / ZoomFactor ) * point;
171  }
172 
176  public Vector WorldToScreen( Vector point )
177  {
178  return ( point - Position ) * ZoomFactor;
179  }
180 
185  public Vector ScreenToWorld( Vector point, Layer layer )
186  {
187  if ( layer == null )
188  return ScreenToWorld( point );
189  if ( layer.IgnoresZoom )
190  return Vector.ComponentProduct( Position, layer.RelativeTransition ) + point;
191 
192  return Vector.ComponentProduct( Position, layer.RelativeTransition ) + ( 1 / ZoomFactor ) * point;
193  }
194 
199  public Vector WorldToScreen( Vector point, Layer layer )
200  {
201  if ( layer == null )
202  return WorldToScreen( point );
203  if ( layer.IgnoresZoom )
204  return point - Vector.ComponentProduct( Position, layer.RelativeTransition );
205 
206  return ( point - Vector.ComponentProduct( Position, layer.RelativeTransition ) ) * ZoomFactor;
207  }
208 
213  public void Move( Vector v )
214  {
215  Position += new Vector( v.X / ZoomFactor, v.Y / ZoomFactor );
216  }
217 
225  public void Zoom( double zoom )
226  {
227  ZoomFactor *= zoom;
228  }
229 
233  public void Reset()
234  {
235  Position = Vector.Zero;
236  Velocity = Vector.Zero;
237  ZoomFactor = 1.0f;
238  StopFollowing();
239  }
240 
245  public void Follow( params GameObject[] gameobjects )
246  {
247  FollowsX = true;
248  FollowsY = true;
249 
250  if ( gameobjects.Length == 0 ) return;
251  if ( gameobjects.Length == 1 )
252  {
253  FollowedObject = gameobjects[0];
254  return;
255  }
256 
257  FollowedObject = new GameObject( 1.0, 1.0 );
258  followedObjects = new List<GameObject>( gameobjects );
259  updateAvgPoint();
260  }
261 
266  public void FollowX( params GameObject[] gameobjects )
267  {
268  Follow( gameobjects );
269  FollowsX = true;
270  FollowsY = false;
271  }
272 
277  public void FollowY( params GameObject[] gameobjects )
278  {
279  Follow( gameobjects );
280  FollowsX = false;
281  FollowsY = true;
282  }
283 
287  public void StopFollowing()
288  {
289  if ( followedObjects != null )
290  {
291  followedObjects = null;
293  }
294 
295  FollowedObject = null;
296  }
297 
298  private void updateAvgPoint()
299  {
300  FollowedObject.Position = followedObjects.ConvertAll<GameObject, Vector>( ( GameObject o ) => { return o.Position; } ).Average();
301 
302  double maxDx = followedObjects.ConvertAll<GameObject, double>( ( GameObject o ) => { return Math.Abs( o.X - FollowedObject.X ); } ).Max();
303  double maxDy = followedObjects.ConvertAll<GameObject, double>( ( GameObject o ) => { return Math.Abs( o.Y - FollowedObject.Y ); } ).Max();
304 
305  double zoomX = Game.Screen.Width / ( 2 * maxDx + FollowXMargin );
306  double zoomY = Game.Screen.Height / ( 2 * maxDy + FollowYMargin );
307 
308  ZoomFactor = Math.Min( zoomX, zoomY );
309  }
310 
316  public void ZoomTo( Vector bottomLeft, Vector topRight )
317  {
318  ZoomTo( bottomLeft.X, bottomLeft.Y, topRight.X, topRight.Y );
319  }
320 
321  public void ZoomTo( BoundingRectangle rectangle )
322  {
323  ZoomTo( rectangle.Left, rectangle.Bottom, rectangle.Right, rectangle.Top );
324  }
325 
326  public void ZoomTo( BoundingRectangle rectangle, double borderSize )
327  {
328  ZoomTo( rectangle.Left, rectangle.Bottom, rectangle.Right, rectangle.Top, borderSize );
329  }
330 
331  public void ZoomToAllObjects()
332  {
333  ZoomToAllObjects( 0 );
334  }
335 
340  public void ZoomToAllObjects( double borderSize )
341  {
342  // Do the real zoom next update so all objects waiting to be added are added before that
343  Game.DoNextUpdate( doZoomToAllObjects, borderSize );
344  }
345 
346  private void doZoomToAllObjects( double borderSize )
347  {
348  if ( Game.Instance.ObjectCount > 0 )
349  ZoomTo( Game.Instance.Level.FindObjectLimits(), borderSize );
350  }
351 
359  public void ZoomTo( double left, double bottom, double right, double top )
360  {
361  ZoomTo( left, bottom, right, top, 0 );
362  }
363 
364  internal void ZoomTo( double left, double bottom, double right, double top, double borderSize )
365  {
366  double screenWidth = (double)Game.Screen.Width;
367  double screenHeight = (double)Game.Screen.Height;
368  double width = right - left;
369  double height = top - bottom;
370 
371  Position = new Vector( left + width / 2, bottom + height / 2 );
372 
373  if ( ( width / height ) >= ( screenWidth / screenHeight ) )
374  this.ZoomFactor = screenWidth / ( width + borderSize );
375  else
376  this.ZoomFactor = screenHeight / ( height + borderSize );
377  }
378 
382  public void ZoomToLevel()
383  {
384  ZoomToLevel( 0 );
385  }
386 
391  public void ZoomToLevel( double borderSize )
392  {
393  FollowedObject = null;
394  Level level = Game.Instance.Level;
395  ZoomTo( level.Left, level.Bottom, level.Right, level.Top, borderSize );
396  }
397 
402  internal void Update( Time time )
403  {
404  Position += Velocity * time.SinceLastUpdate.TotalSeconds;
405 
406  if ( FollowedObject != null )
407  {
408  Vector center = ScreenToWorld( Vector.Zero );
409  Vector worldOffset = ScreenToWorld( FollowOffset );
410 
411  // Update the average point if following multiple objects
412  if ( followedObjects != null ) updateAvgPoint();
413 
414  if ( FollowsX && FollowsY )
415  Position = FollowedObject.Position + ( worldOffset - center );
416  else if ( FollowsX )
417  X = FollowedObject.X + ( worldOffset.X - center.X );
418  else if ( FollowsY )
419  Y = FollowedObject.Y + ( worldOffset.Y - center.Y );
420  }
421 
422  if ( StayInLevel )
423  {
424  double screenWidth = (double)Game.Screen.Width;
425  double screenHeight = (double)Game.Screen.Height;
426  Level level = Game.Instance.Level;
427 
428  double screenAspectRatio = screenWidth / screenHeight;
429  double levelAspectRatio = level.Width / level.Height;
430 
431  double zoomedWidth = level.Width * ZoomFactor;
432  double zoomedHeight = level.Height * ZoomFactor;
433 
434  double viewAreaWidth = screenWidth / ZoomFactor;
435  double viewAreaHeight = screenHeight / ZoomFactor;
436 
437  if ( zoomedWidth < screenWidth || zoomedHeight < screenHeight )
438  {
439  ZoomFactor = Math.Max( screenWidth / level.Width, screenHeight / level.Height );
440  }
441 
442  if ( ( Position.X - ( viewAreaWidth / 2 ) ) < level.Left )
443  {
444  Position.X = level.Left + ( viewAreaWidth / 2 );
445  }
446  else if ( Position.X + ( viewAreaWidth / 2 ) > level.Right )
447  {
448  Position.X = level.Right - ( viewAreaWidth / 2 );
449  }
450 
451  if ( Position.Y - ( viewAreaHeight / 2 ) < level.Bottom )
452  {
453  Position.Y = level.Bottom + ( viewAreaHeight / 2 );
454  }
455  else if ( Position.Y + ( viewAreaHeight / 2 ) > level.Top )
456  {
457  Position.Y = level.Top - ( viewAreaHeight / 2 );
458  }
459  }
460  }
461  }
462 }
void FollowY(params GameObject[] gameobjects)
Seuraa jotakin peliobjektia Y- eli pystysuunnassa.
Definition: Camera.cs:277
void ZoomToAllObjects(double borderSize)
Zoomaa ja sijoittaa kameran siten, että kaikki pelioliot ovat yhtäaikaa näkyvissä.
Definition: Camera.cs:340
Vector WorldToScreen(Vector point, Layer layer)
Muuntaa annetun pisteen maailmankoordinaateista ruutukoordinaatteihin ottaen huomioon oliokerroksen s...
Definition: Camera.cs:199
static void DoNextUpdate(Action action)
Suorittaa aliohjelman seuraavalla päivityksellä.
Definition: Game.cs:642
double X
Olion paikan X-koordinaatti.
double X
Kameran paikan X-koordinaatti.
Definition: Camera.cs:68
Vector RelativeTransition
Kuinka paljon tämän kerroksen olioiden paikka muuttuu kameran siirtyessä suhteessa muihin kerroksiin...
Definition: Layer.cs:110
double Y
Olion paikan Y-koordinaatti.
Vector ScreenToWorld(Vector point, Layer layer)
Muuntaa annetun pisteen ruutukoordinaateista maailmankoordinaatteihin ottaen huomioon oliokerroksen s...
Definition: Camera.cs:185
double Top
Kentän yläreunan y-koordinaatti.
Definition: Level.cs:160
void ZoomTo(double left, double bottom, double right, double top)
Zoomaa ja sijoittaa kameran niin, että parametreina annettua alue näkyy kokonaan ruudulla.
Definition: Camera.cs:359
void Follow(params GameObject[] gameobjects)
Seuraa yhtä tai useampaa peliobjektia.
Definition: Camera.cs:245
void Move(Vector v)
Kohdistaa kameran.
Definition: Camera.cs:213
double Bottom
Suorakaiteen alareunen Y
void Reset()
Resetoi kameran (keskittää, laittaa zoomin oletusarvoon ja lopettaa seuraamisen). ...
Definition: Camera.cs:233
double ZoomFactor
Kameran zoomauskerroin. Oletuksena 1.0. Mitä suurempi zoomauskerroin, sitä lähempänä kamera on (esim ...
Definition: Camera.cs:99
BoundingRectangle FindObjectLimits()
Laskee pienimmän alueen, jonka sisälle kaikki kentän oliot mahtuvat.
Definition: Level.cs:202
void FollowX(params GameObject[] gameobjects)
Seuraa jotakin peliobjektia X- eli vaakasuunnassa.
Definition: Camera.cs:266
double Right
Suorakaiteen oikean reunan X
static Game Instance
Definition: Game.cs:149
TimeSpan SinceLastUpdate
Aika joka on kulunut viime päivityksestä.
Definition: Time.cs:24
void Zoom(double zoom)
Zoomaa.
Definition: Camera.cs:225
static readonly Vector Zero
Nollavektori.
Definition: Vector.cs:61
Sisältää tiedon ajasta, joka on kulunut pelin alusta ja viime päivityksestä.
Definition: Time.cs:13
Kamera. Määrittää mikä osa pelitasosta on kerralla näkyvissä.
Definition: Camera.cs:42
bool FollowsY
Seurataanko oliota (FollowedObject) y- eli pystysuunnassa.
Definition: Camera.cs:126
double Height
Näytön korkeus y-suunnassa.
Definition: View.cs:74
Vector FollowOffset
Jos kamera seuraa oliota, tällä voi säätää missä kohtaa ruutua pelaaja näkyy. Toisin sanoen ruutukoor...
Definition: Camera.cs:141
bool StayInLevel
Jos tosi, kamera ei mene koskaan kentän ulkopuolelle.
Definition: Camera.cs:108
void ZoomTo(BoundingRectangle rectangle)
Definition: Camera.cs:321
double FollowYMargin
Jos kamera seuraa useita olioita, tällä voi säätää kuinka paljon ylä- ja alareunaan jätetään tyhjää t...
Definition: Camera.cs:153
Pelikenttä, johon voi lisätä olioita. Kentällä voi myös olla reunat ja taustaväri tai taustakuva...
Definition: Level.cs:78
double Left
Suorakaiteen vasemman reunan X
static ScreenView Screen
Näytön dimensiot, eli koko ja reunat.
Definition: Game.cs:194
Vector Position
Kameran sijainti.
Definition: Camera.cs:56
double Y
Definition: Vector.cs:275
bool IgnoresZoom
Jättää kameran zoomin huomiotta jos asetettu.
Definition: Layer.cs:118
Peliluokka reaaliaikaisille peleille.
Definition: DebugScreen.cs:10
double Top
Suorakaiteen yläreunan Y
double Bottom
Kentän alareunan y-koordinaatti.
Definition: Level.cs:168
Kerros. Vastaa olioiden piirtämisestä.
Definition: Layer.cs:36
double X
Definition: Vector.cs:274
double Height
Kentän korkeus.
Definition: Level.cs:126
bool FollowsX
Seurataanko oliota (FollowedObject) x- eli vaakasuunnassa.
Definition: Camera.cs:121
Level Level
Aktiivinen kenttä.
Definition: Game.cs:299
void ZoomToLevel(double borderSize)
Zoomaa ja keskittää kameran siten, että koko kenttä on näkyvissä kerralla. Tällöin kamera ei seuraa m...
Definition: Camera.cs:391
void ZoomTo(Vector bottomLeft, Vector topRight)
Zoomaa ja sijoittaa kameran niin, että parametreina annettua alue näkyy kokonaan ruudulla.
Definition: Camera.cs:316
override void Destroy()
Tuhoaa olion. Tuhottu olio poistuu pelistä.
double Width
Kentän leveys.
Definition: Level.cs:117
double Y
Kameran paikan Y-koordinaatti.
Definition: Camera.cs:83
Vector Velocity
Kameran liikkumisnopeus.
Definition: Camera.cs:62
double FollowXMargin
Jos kamera seuraa useita olioita, tällä voi säätää kuinka paljon vasempaan ja oikeaan reunaan jätetää...
Definition: Camera.cs:147
void StopFollowing()
Lopettaa olio(iden) seuraamisen.
Definition: Camera.cs:287
GameObject FollowedObject
Olio, jota kamera seuraa. Jos null, mitään oliota ei seurata.
Definition: Camera.cs:116
double Right
Kentän oikean reunan x-koordinaatti.
Definition: Level.cs:152
void ZoomToAllObjects()
Definition: Camera.cs:331
2D-vektori.
Definition: Vector.cs:56
void ZoomTo(BoundingRectangle rectangle, double borderSize)
Definition: Camera.cs:326
Vector WorldToScreen(Vector point)
Muuntaa annetun pisteen maailmankoordinaateista ruutukoordinaatteihin.
Definition: Camera.cs:176
double Width
Näytön leveys x-suunnassa.
Definition: View.cs:66
Pelialueella liikkuva olio. Käytä fysiikkapeleissä PhysicsObject-olioita.
Definition: __GameObject.cs:54
Vector ScreenToWorld(Vector point)
Muuntaa annetun pisteen ruutukoordinaateista maailmankoordinaatteihin.
Definition: Camera.cs:168
void ZoomToLevel()
Zoomaa ja keskittää kameran siten, että koko kenttä on näkyvissä kerralla.
Definition: Camera.cs:382
virtual Vector Position
Olion paikka. Jos olio on jonkun toisen peliolion lapsi, paikka on suhteessa tämän vanhempaan (Parent...
static Vector ComponentProduct(Vector a, Vector b)
Kertoo kaksi vektoria komponenteittain.
Definition: Vector.cs:164
double Left
Kentän vasemman reunan x-koordinaatti.
Definition: Level.cs:144