Robię grę testową, w której chcę, aby poziom ciągle się przewijał. Aby stworzyć ten efekt, stworzyłem klasę kamery, która po prostu przechowuje pozycję vector2 i kierunek wyliczania. Zawiera także publiczną metodę „przemieszczania się”, która po prostu zmienia pozycję według stałej stawki. Następnie używam tej pozycji, gdy przeglądam moją tablicę kafelków. To wszystko działa dobrze.
Jednak powiedziano mi, że powinienem używać matrycy transformacji do poruszania kamerą i że powinienem to zapewnić, kiedy uruchamiam spritebatch. Jestem trochę zdezorientowany.) Jak to działa? tak jakbym dawał to dopiero, gdy spritebatch zaczyna się, skąd wiadomo, że ciągle zmienia pozycję? b.) Dlaczego robię to tak pewnie, że nadal potrzebuję pozycji kamery, gdy przechodzę przez płytki?
W tej chwili nie mogę zmusić go do działania, ale nie jest to zaskoczeniem, ponieważ nie do końca rozumiem, jak to ma działać. Obecnie w mojej próbie (kod do naśladowania) narysowane kafelki zmieniają się, co oznacza, że zmienia się pozycja kamer, ale pozycja rzutni pozostaje niezmieniona (tj. W punkcie początkowym kamery). Byłbym naprawdę wdzięczny za porady / wskazówki, w jaki sposób powinno się go używać?
Aparat fotograficzny:
class Camera {
// The position of the camera.
public Vector2 Position {
get { return mCameraPosition; }
set { mCameraPosition = value; }
}
Vector2 mCameraPosition;
public Vector2 Origin { get; set; }
public float Zoom { get; set; }
public float Rotation { get; set; }
public ScrollDirection Direction { get; set; }
private Vector2 mScrollSpeed = new Vector2(20, 18);
public Camera() {
Position = Vector2.Zero;
Origin = Vector2.Zero;
Zoom = 1;
Rotation = 0;
}
public Matrix GetTransform() {
return Matrix.CreateTranslation(new Vector3(mCameraPosition, 0.0f)) *
Matrix.CreateRotationZ(Rotation) *
Matrix.CreateScale(Zoom, Zoom, 1.0f) *
Matrix.CreateTranslation(new Vector3(Origin, 0.0f));
}
public void MoveCamera(Level level) {
if (Direction == ScrollDirection.Up)
{
mCameraPosition.Y = MathHelper.Clamp(mCameraPosition.Y - mScrollSpeed.Y, 0, (level.Height * Tile.Height - level.mViewport.Height));
}
}
Poziom:
public void Update(GameTime gameTime, TouchCollection touchState) {
Camera.MoveCamera(this);
}
public void Draw(SpriteBatch spriteBatch) {
//spriteBatch.Begin();
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullCounterClockwise, null, mCamera.GetTransform());
DrawTiles(spriteBatch);
spriteBatch.End();
}
Gra - po prostu sprawdza losowanie na poziomie:
protected override void Draw(GameTime gameTime) {
mGraphics.GraphicsDevice.Clear(Color.Black);
//mSpriteBatch.Begin();
// Draw the level.
mLevel.Draw(mSpriteBatch);
//mSpriteBatch.End();
base.Draw(gameTime);
}
================================================== =============================== EDYCJA:
Po pierwsze, dziękuję gry rzemieślnicze za pomoc do tej pory.
Bawiłem się z sugestią. Kiedy narysowałem wszystkie płytki, fr zagrał do około 15 z 30 - prawdopodobnie dlatego, że poziomy są dość duże.
Więc zastosowałem macierz i poruszałem się w aktualizacji (zgodnie z sugestią), ale w losowaniu używam pozycji kamery do zapętlania płytek (tj. Start licznika po lewej i koniec po prawej płytce). To wszystko działa dobrze i jestem z tego zadowolony :-)
Mój nowy problem leży w odtwarzaczu. Oczywiście, ponieważ teraz poruszam kamerą, a nie poziomem, gracz zostaje w tyle za kamerą, gdy jego pozycja pozostaje stała. Pomyślałem o dwóch rozwiązaniach tego problemu. Pierwszym z nich jest po prostu wzięcie pod uwagę położenia kamery podczas rysowania odtwarzacza. Tj. W funkcji losowania po prostu dodaj pozycję kamery do pozycji gracza. Drugim jest rozpoczęcie nowej partii sprite dla gracza, który nie ma transformacji. tzn. zakończ sprite po wylosowaniu kafelków, a następnie rozpocznij nowy podczas losowania gracza. Wiem, że oba będą działać, ale nie mogę zrobić ogonów, które byłyby lepsze pod względem wydajności / dobrego kodowania? Nie jestem pewien, jakie są konsekwencje dla wydajności od dwukrotnego uruchomienia partii?
Odpowiedzi:
Transformacje matrycy kamery są łatwe
Stworzenie podstawowego aparatu jest łatwe. Poniżej zapoznasz się z podstawami. Poruszanie, obracanie, skalowanie. Przenoszenie każdego duszka 2d nie stanowi większego problemu, ale jeśli weźmiesz pod uwagę skalowanie lub obrót, bardzo trudno będzie zastosować go indywidualnie do każdego duszka.
Ułatwia to konwersję między definicjami układu współrzędnych
Aby przejść z ekranu do przestrzeni świata po prostu. Jest to powszechnie używane do uzyskiwania położenia myszy na świecie do wybierania obiektów.
Aby przejść ze świata do miejsca na ekranie, po prostu postępuj odwrotnie.
Korzystanie z matrycy innej niż wady nie wymaga wcześniejszej nauki.
Łatwo jest uzyskać widoczny obszar
Możesz po prostu przekształcić kąty kamer i uzyskać ich lokalizację w przestrzeni świata. Min. Maks. Wartości x, y, możesz uzyskać prostokąt wokół widocznej przestrzeni. Bardzo przydatny do eliminacji i optymalizacji połączeń losujących.
źródło
Zastosowanie macierzy do SpriteBatch przekształca jednocześnie całe wywołanie losowania. Oznacza to, że w ogóle nie musisz używać aparatu w metodzie DrawTiles.
Może to stać się o wiele prostsze:
Tak więc sens używania macierzy jest taki, że nie musisz o tym myśleć. Po prostu rysuj i przesuwaj aparat niezależnie.
Ponadto metoda MoveCamera wygląda trochę dziwnie. Bardzo rzadkie jest posiadanie klasy kamery, która bierze poziom jako zależność. Bardziej typowa implementacja wyglądałaby następująco:
Następnie w metodzie aktualizacji możesz zrobić coś takiego:
Ogólnie proponuję, aby było to proste. Spraw, by działał w najprostszy sposób i buduj na nim. Staraj się nie pisać wysoce zoptymalizowanego kodu, dopóki nie zaczniesz od podstaw. Może się okazać, że renderowanie każdej płytki każdej klatki nie jest takie złe.
EDYCJA: Do drugiej części pytania.
Chociaż prawdą jest, że chcesz utrzymać niską liczbę partii, posiadanie 2 lub 3 nie powinno stanowić żadnego problemu. Więc jeśli masz dobry powód, aby utworzyć drugą partię duszka, po prostu zrób to.
To powiedziawszy, prawdopodobnie nie ma dobrego powodu, aby w tym przypadku użyć drugiej partii duszka. Bardziej prawdopodobne jest, że chcesz narysować swojego gracza dokładnie tak samo, jak narysujesz płytki w tej samej partii duszka z zastosowaną transformacją kamery.
Trochę trudno jest powiedzieć, dlaczego twój gracz zostaje w tyle bez patrzenia na jakiś kod, ale jest oczywiste, że jeśli narysujesz swojego gracza dokładnie w tej samej pozycji co kafelek, pojawi się na tej samej pozycji z tą samą pozycją partia duszka.
Na przykład, jeśli chcesz, aby odtwarzacz pojawiał się na polu 10, 10, możesz to zrobić:
Postaraj się myśleć o rysowaniu rzeczy tam, gdzie są, a kamera dosłownie przesuwa całą „scenę” na widok. Właśnie to robi twoja transformacja macierzowa.
źródło