Tworzenie gry w C# z użyciem silnika Ogre - cz.5

28.03.2011 - Mateusz Osowski
TrudnośćTrudność
1
2
3
4
5
public void UpdateItem(int i)
{
  if (i >= ViewIndex && i < ViewIndex + SlotsCount)
    Slots[i - ViewIndex].SetItem(Character.Inventory[i]);
}
HUDInventory.cs


Metoda ta będzie przydatna, gdy np. gracz zdecyduje się ubrać wybrany przedmiot - wówczas zaktualizujemy jego kwadracik.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void UpdateDescription()
{
  if (SelectIndex != -1)
  {
    DescriptionLabel.Caption = 
    Character.Inventory[SelectIndex].DisplayName 
      + "\n\n" 
      + Character.Inventory[SelectIndex].Description;
    SelectedPicture.Panel.MaterialName = 
      Character.Inventory[SelectIndex].InventoryPictureMaterial;
  }
  else
  {
    DescriptionLabel.Caption = "";
    SelectedPicture.Panel.MaterialName = "QuadMaterial";
  }
}
HUDInventory.cs


Ta metoda będzie aktualizować wyświetlany opis. W przypadku gdy wybrany jest jakiś przedmiot - wyświetlamy jego obrazek, nazwę i opis. Ogre nie zapewnia nam przycinania tekstu w obiektach typu TextArea, więc będziemy musieli sami pilnować, by opis mieścił się w okienku. Inną opcją mogłoby być napisanie klasy kontrolki automatycznie dbającej o formatowanie tekstu i umożliwienie przewijania go użytkownikowi, jednak byłoby to bliskie tworzeniu własnego systemu GUI, czego wolelibyśmy uniknąć.
1
2
3
4
5
6
7
8
9
10
11
12
public int ViewIndex
{
  get { return _ViewIndex; }
  set
  {
    if (value != _ViewIndex)
    {                   
      _ViewIndex = System.Math.Max(0, value);
      UpdateView();
    }
  }
}
HUDInventory.cs


Właściwością ViewIndex będziemy mogli przewijać listę przedmiotów. Każda zmiana pociąga za sobą aktualizację kwadracików.
1
2
3
4
5
6
7
8
9
10
11
12
public int SelectIndex      
{
  get 
  {
    return (_SelectIndex >= Character.Inventory.Count ? -1 : _SelectIndex);
  }
  set
  {
    if (value < 0)
      value = -1;
    else if (value >= Character.Inventory.Count)
      value = Character.Inventory.Count - 1;
HUDInventory.cs


Właściwość ta ma wartość -1, gdy nie jest zaznaczony żaden obiekt. Ma to miejsce w przypadku, gdy postać nie będzie posiadać żadnego przedmiotu w ekwipunku. Podczas ustawiania pilnujemy, by indeks nie wyjechał poza tablicę.
1
2
3
4
5
6
7
8
9
10
    if (_SelectIndex >= ViewIndex + SlotsCount)
      ViewIndex = _SelectIndex - SlotsCount + 1;
    else if (_SelectIndex < ViewIndex)
      ViewIndex = _SelectIndex;
 
    SelectQuad.Panel.Top = 
      SlotsSpacing + (_SelectIndex - ViewIndex) * (InventorySlot.Size + SlotsSpacing);
    UpdateDescription();
  }
}
HUDInventory.cs, SelectIndex


Pilnujemy, by zaznaczony przedmiot był objęty przedziałem widoczności. W przypadku gdy zaznaczenie wyjdzie za obszar widoczności - przesuwamy zakres tak, by zaznaczony element był ostatnim widocznym. Gdy zaś zaznaczenie wyjdzie przed obszar - będzie ono pierwszym widocznym elementem. Po aktualizacji listy przesuwamy odpowiednio kwadracik podświetlający i aktualizujemy opis.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public bool IsVisible
{
  set
  {
    foreach (var slot in Slots) slot.IsVisible = value;
    SelectQuad.IsVisible = value;
    DescriptionBg.IsVisible = value;
    DescriptionLabel.IsVisible = value;
    SelectedPicture.IsVisible = value;
    if (value)
    {
      UpdateView();
      SelectIndex = SelectIndex;
    }
  }
}
HUDInventory.cs


Właściwością IsVisible szybko ukryjemy i odsłonimy wszystkie elementy interfejsu. W przypadku odsłaniania aktualizujemy listę, a także indeks zaznaczenia, ponieważ ekwipunek mógł ulec zmianie i poprzedni indeks mógłby wyjść poza zakres listy ekwipunku.

Przejdźmy do klasy HumanController:

1
2
3
4
5
6
public enum HumanControllerState
{
  FREE,
  TALK,
  INVENTORY
}
HumanController.cs


Obsługę interfejsu zaimplementujemy jako nowy stan kontrolera postaci.
1
2
3
4
5
6
7
8
...
HUDInventory HUDInventory;
...
public HumanController()
{
  ...
  HUDInventory = new HUDInventory();
}
HumanController.cs


Obiekt HUDInventory stworzymy w konstruktorze klasy HumanController.
1
2
3
4
5
6
7
8
9
10
private void HandleInventory()
{
  if (Engine.Singleton.IsKeyTyped(MOIS.KeyCode.KC_DOWN))
  HUDInventory.SelectIndex++;
  if (Engine.Singleton.IsKeyTyped(MOIS.KeyCode.KC_UP))
  HUDInventory.SelectIndex--;
 
  if (Engine.Singleton.IsKeyTyped(MOIS.KeyCode.KC_TAB))
    SwitchState(HumanControllerState.FREE);
}
HumanController.cs


Metoda obsługująca tryb ekwipunku na ten czas będzie umożliwiać poruszanie się po liście przedmiotów. Klawiszem Tab będziemy wchodzić i wychodzić z trybu ekwipunku.
1
2
3
4
5
6
7
8
9
10
11
  if (State == HumanControllerState.FREE)
  {
    ...
    else if (newState == HumanControllerState.INVENTORY)
      HUDInventory.IsVisible = true;
  }
  ...
  else if (State == HumanControllerState.INVENTORY)
    if (newState == HumanControllerState.FREE)
      HUDInventory.IsVisible = false;
  ...
HumanController.cs, SwitchState()


Przejścia między stanami przeglądania ekwipunku a grą będą pokazywac i ukrywać interfejs.
1
2
3
4
5
...
if (Engine.Singleton.IsKeyTyped(MOIS.KeyCode.KC_TAB)
  && Character.CanSwitchState(Character.CharacterState.INVENTORY))
  SwitchState(HumanControllerState.INVENTORY);
...
HumanController.cs, HandleMovement()


Do trybu INVENTORY przejść będzie można wciskając klawisz Tab w trybie poruszania się. Musimy też dodać stan przeglądania ekwipunku do klasy postaci, ponieważ chcemy móc określić, kiedy będzie można do niego przejść.
1
2
3
4
5
6
7
if (Character != null)
{
  ...
  else if (State == HumanControllerState.INVENTORY)
    HandleInventory();
}
...
HumanController.cs, Update()


Pamiętamy o wywołaniu odpowiedniej metody w stanie INVENTORY.

W klasie Character dopisujemy nowy stan i dodajemy przejście do niego z IDLE do mapy stanów:
1
2
3
...
StatesMap[CharacterState.IDLE].Add(CharacterState.INVENTORY);
...
Character.cs, InitStatesMap()


Ten "stan" działa na takiej samej zasadzie jak TURN - służy tylko do określenia, czy postać może wykonać daną akcję w danym stanie.

Na koniec rozbudujemy nieco opis miecza by sprawdzić działanie interfejsu:

1
2
3
4
5
6
7
8
9
10
  ...
  swordProfile.Description = 
@"A sword is a long, edged piece of 
forged metal, used in many civilizations 
throughout the world, primarily as a 
cutting or thrusting weapon and 
occasionally as a clubbing or 
bludgeoning weapon. The word sword 
comes from the Old English sweord"; // źródło:Wikipedia ;)
  swordProfile.InventoryPictureMaterial = "SpriteSword";
Program.cs, Main()


Interfejs powinien już działać. Możesz umieścić w grze więcej mieczy, by przetestować przewijanie listy.

Użyte materiały i tekstury

Aktualny kod źródłowy

5
Twoja ocena: Brak Ocena: 5 (3 ocen)

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com