ПрограммированиеФорумОбщее

Каким образом можно получить доступ к членам объекта (врага) при выделении его мышкой?

#0
8:30, 26 окт 2021

В шутерах есть такой луч пересекающий меш и в момент пересечения у противника отнимается хп. То есть при пересечении меша лучом мы получаем доступ к хп врага...

А если я выбираю противника мышкой это происходит с помощью того же луча? Мне надо чтобы при нажатии на спелл и следующем нажатии на противника работал каст фаербола в этого выбраного противника.

class character
{

string mesh;
bool ally;
string name;
int hp;
int atk;
}

такой код атаки:

character vrag;
if vrag.ally= false {
vrag.hp-=fireball();
}

Я вот не понимаю как с помощью луча получить доступ к переменным этого обьекта.
Сорян если глупо сформулировал вопрос, я немного слоупок)).

#1
9:49, 26 окт 2021

Kukuruz
> Я вот не понимаю как с помощью луча получить доступ к переменным этого обьекта.

Поскольку ты не стал сообщать о движке, яп, что там у тебя вообще, то можно ответить только в общем виде: рейкасты и меши - это геометрия.
Последние обычно оборачивается в объект-логическую сущность. Эту сущность (class character) тебе и надо уметь получать: тайпкастом, словарём,
но обычно доки к движку описывают.

А вообще это не "солидно", из луча иметь доступ к переменным пересекаемого класса, а тем более реализовывать логику типа манипуляций с HP.

#2
5:12, 27 окт 2021

rcsim, спасибо.

Движка пока нет, но он должен быть на C++, самописный. Скорее всего на DX11. Писать буду не я. Но мне интересно как это делается.

rcsim
> А вообще это не "солидно", из луча иметь доступ к переменным пересекаемого
> класса, а тем более реализовывать логику типа манипуляций с HP.

Почему не солидно? Ну а как по другому я не знаю, опыта у меня совсем нет.

#3
13:55, 27 окт 2021

Разумеется, я имел ввиду SOLID

#4
14:15, 27 окт 2021

Kukuruz
  Отправь сообщение классу НПС

#5
20:21, 27 окт 2021

Псевдокод:
fireball_damage = 10;
actors = world.raycast(ray);
foreach actor from actors
{
  асtor.apply_damage(fireball_damage);
}

#6
22:05, 28 окт 2021

Kukuruz
>Движка пока нет, но он должен быть на C++, самописный. Скорее всего на DX11.

На С++ в мире так мало движков, что обязательно писать ещё один новый! Чем больше сил потратишь на движок, тем меньше останется на игру. Если хочется своего, то форкай, например годот и дописывай в код что тебе надо.

#7
12:13, 29 окт 2021

Мне надо чтобы при нажатии на спелл и следующем нажатии на противника работал каст фаербола в этого выбраного противника.

То есть, по сути таргетная система. Тогда у персонажей необходимо сделать такую вещь, как фокус, который будет ссылкой на другого персонажа.

class Character
{
public:
...
  virtual ~Character();
...
  inline bool hasTarget() const;
  inline Character * getTarget() const;
  inline void setTarget(Character * character);
  inline void resetTarget();
private:
  Charater * target;
};

bool Character::hasTarget() const
{
  return target != NULL;
}

Character * Character::getTarget() const
{
  return target;
}

void Character::setTarget(Character * character)
{
  target = character;
}

void Character::resetTarget()
{
  target = NULL;
}

Это позволит запоминать, кто у персонажа в фокусе. Причём этот механизм можно использовать для разных персонажей, в том числе и NPC, что бы они могли кастовать на игрока

if vrag.ally= false {
vrag.hp-=fireball();
}

По-моему, лучше так:

if (!vrag.ally) {
vrag.hp-=fireball();
}

А ещё лучше проверку применяемости спелла сделать либо в классе спелла (либо вообще в шаблоне стратегия).

Внутри класса Spell:

class FireballSpell
{
public:
...
  bool canCast(const Character * character)
  {
    if (!character.hasTarget()) {
      return false;
    }

    //TODO: Проверить, можно ли применить к target
  }
...
};

Как проверить.
Вариант 1. Оставить флаг ally
Вариант 2. Ввести в игру группы персонажей (фракции). Фракции позволят не только союзных и враждебных персонажей иметь, но и нейтральных, если потребуется.

Вот простой пример жёстко зашитых вариантов фракций:

class Character
{
public:
  const int FRACTION_ALLIANCE = 0x1;
  const int FRACTION_HORDE = 0x2;
  const int FRACTION_CARTEL = 0x3;
  
  const int RELATION_FRIENDLY = 1;
  const int RELATION_NEUTRAL = 0;
  const int RELATION_HOSTILE =  -1;
...
  virtual ~Character();
...
  inline bool hasTarget() const;
  inline Character * getTarget() const;
  inline void setTarget(Character * character);
  inline void resetTarget();
  
  int getRelationTo(Character * character) const;
private:
  Charater * target;
  int fraction;
};

int Character::getRelationTo(Character * character) const
{
  if (fraction == character->fraction)
  {
    return RELATION_FRIENDLY;
  }

  if (fraction == FRACTION_CARTEL || character->fraction == FRACTION_CARTEL)
  {
    return RELATION_NEUTRAL;
  }

  return RELATION_HOSTILE;
}

Тогда метод canCast будет таким:

  bool FireballSpell::canCast(const Character * character)
  {
    if (!character->hasTarget()) {
      return false;
    }

    return character->getRelationTo(character->getTarget()) <= RELATION_NEUTRAL;
  }

Да, в классе Character можно сделать отдельный метода getRelationToTarget:

int Character::getRelationToTarget() const
{
  if (target == NULL)
  {
    return RELATION_FRIENDLY; // отношение персонажа к самому себе
  }

  return getRelationTo(target);
}
#8
12:24, 29 окт 2021

Kukuruz
> Я вот не понимаю как с помощью луча получить доступ к переменным этого обьекта.

Есть пара англоязычных статей:
Object picking with Vulkan

Mouse Picking with Ray Casting

Тут на gamedev есть очень древняя статья с применением glu:
Способ выделения объектов мышью в OpenGL приложениях

#9
8:30, 30 окт 2021

Morgend
спасибо большое!

всем спасибо.

ПрограммированиеФорумОбщее

Тема в архиве.