Пятница, 29 Марта 2024, 01:58

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Форум игроделов » Программирование » C/C++ » Массив содержащий компоненты игрового обьекта
Массив содержащий компоненты игрового обьекта
zaicev9797Дата: Пятница, 14 Июня 2019, 20:26 | Сообщение # 1
AbRaKaDaBrA
Сейчас нет на сайте
как можно сделать чтоб внутри класса GameObject можно было хранить массив или список наследников класса Component (например TransfromComponent : public Component или Collider : public Component и т.д.)
У Component есть метод Update. соответственно я хочу чтоб GameObject который содержит набор экземпляров разных наследников Component мог вызывать их Update.
Как такое можно сделать?

В данный момент, если я придумываю новый компонент который можно было бы прицепить к GameObject мне приходится прописывать однотипные методы которые отличаются только типом компонента, а так же отдельные поля для хранения каждого типа компонента.

Короче выглядит это вот так, и что то мне подсказывает, что это лютая дичь
Код
class GameObject{
    TransformComponent *transform;
    Body *body;
    Collider *collider;
    DrawComponent *draw;
    Spacecraft *spacecraft;
    ParticleController *particleController;
    ParticleSystem *particleSystem;
    BackgroundController *backgroundController;
    FireController *fireController;
    Button *button;
    TextWindow *textWindow;
    FireLight *fireLightController;
    WeaponLight *weaponLightController;
    ExplosionLight *explosionLightController;
    Asteroid *asteroidController;
    ExplosionController *explosionController;
    PlayerController *playerController;
    EngineParticleController *engineParticleController;
    Bullet *bulletController;
    Weapon *weaponController;
    AsteroidSpawner *asteroidSpawnerController;
    bool destroy = false;
    String tag;
public:
    GameObject()
    {
  transform = NULL;
  body = NULL;
  collider = NULL;
  draw = NULL;
  spacecraft = NULL;
  particleSystem = NULL;
  particleController = NULL;
  backgroundController = NULL;
  fireController = NULL;
  button = NULL;
  textWindow = NULL;
  fireLightController = NULL;
  asteroidController = NULL;
  explosionController = NULL;
  playerController = NULL;
  bulletController = NULL;
  weaponController = NULL;
  weaponLightController = NULL;
  explosionLightController = NULL;
  asteroidSpawnerController = NULL;
    }

    void SetTransform(TransformComponent *_trnasform)
    {
  transform = _trnasform;
  tag = transform->GetTag();
    }
    void SetDrawComponent(DrawComponent *_draw){draw = _draw;}
    void SetCollider(Collider *_collider){collider = _collider;}
    void SetBody(Body *_body){body = _body;}
    void SetSpacecraft(Spacecraft *_spacecraft){spacecraft = _spacecraft;}
    void SetParticleController(ParticleController *_particleController){particleController = _particleController;}
    void SetBackgroundController(BackgroundController *_backgroundController){backgroundController = _backgroundController;}
    void SetButtonController(Button *_button){button = _button;}
    void SetParticleSystem(ParticleSystem *_particleSystem){particleSystem = _particleSystem;}
    void SetFireController(FireController *_fireController){fireController = _fireController;}
    void SetTextWindowController(TextWindow *_textWindow){textWindow = _textWindow;}
    void SetFireLitghtController(FireLight *_fireLightController){fireLightController = _fireLightController;}
    void SetAteroidController(Asteroid *_asteriodController){asteroidController = _asteriodController;}
    void SetExplosionController(ExplosionController *_explosionController){explosionController = _explosionController;}
    void SetPlayerController(PlayerController *_playerController){playerController = _playerController;}
    void SetEngineParticleController(EngineParticleController *_engineParticleController){engineParticleController = _engineParticleController;}
    void SetBulletController(Bullet *_bulletController){bulletController = _bulletController;}
    void SetWeaponController(Weapon *_weapon) { weaponController = _weapon; }
    void SetWeaponLightController(WeaponLight *_weaponLight) { weaponLightController = _weaponLight; }
    void SetExplosionLightController(ExplosionLight *_explosionLight) { explosionLightController = _explosionLight; }
    void SetAsteroidSpawnerController(AsteroidSpawner *_asteroidSpawner) { asteroidSpawnerController = _asteroidSpawner; }

    TransformComponent* GetTransformComponent(){return transform;}
    DrawComponent* GetDrawComonent(){return draw;}
    Collider* GetCollider() {return collider;}
    Body *GetBody(){return body;}
    Spacecraft *GetSpacecraft(){return spacecraft;}
    ParticleController *GetParticleController(){return particleController;}
    BackgroundController *GetBackgroundController(){return backgroundController;}
    Button *GetButton() { return button; }
    TextWindow *GetTextWindow(){return textWindow;}
    FireLight *GetFireLightController(){return fireLightController;}
    Asteroid *GetAsteroidController(){return asteroidController;}
    ExplosionController *GetExplosionController(){return explosionController;}
    PlayerController *GetPlayerController(){return playerController;}
    EngineParticleController *GetEngineParticleController(){return engineParticleController;}
    bool GetDestroy(){return destroy;}
    ParticleSystem *GetParticleSystem(){return particleSystem;}
    FireController *GetFireController(){return fireController;}
    Bullet *GetBulletController(){return bulletController;}
    Weapon *GetWeaponController() { return weaponController; }
    WeaponLight *GetWeaponLightController() { return weaponLightController; }
    ExplosionLight *GetExplosionLightController() { return explosionLightController; }
    AsteroidSpawner *GetAsteroidSpwnerController() { return asteroidSpawnerController; }
    String *GetTag(){return &tag;}
    void Update(RenderWindow &window)
    {
  //printf("\n\n%s \n", transform->GetName().toAnsiString().c_str());
  if (backgroundController != NULL){backgroundController->Update();}
  if (textWindow != NULL){textWindow->Update(window);}
  if (button != NULL){button->Update(window);}
  if (body != NULL){body->Update();}
  if (spacecraft != NULL){spacecraft->Update();}
  if (particleSystem != NULL){particleSystem->Update();}
  if (particleController != NULL){particleController->Update();}
  if (fireController != NULL){fireController->Update();}
  if (fireLightController != NULL){fireLightController->Update();}
  if (asteroidController != NULL){asteroidController->Update();}
  if (explosionController != NULL){explosionController->Update();}
  if (playerController != NULL){playerController->Update();}
  if (engineParticleController != NULL){engineParticleController->Update();}
  if (bulletController != NULL){bulletController->Update();}
  if (weaponController != NULL) { weaponController->Update(); }
  if (weaponLightController != NULL) { weaponLightController->Update(); }
  if (explosionLightController != NULL) { explosionLightController->Update(); }
  if (asteroidSpawnerController != NULL) { asteroidSpawnerController->Update(); }
  if (draw != NULL){draw->Draw(window);}
    }

    void Destroy()
    {
  if (transform != NULL){transform->Destroy();}
  if (collider != NULL){collider->Destroy();}
  if (draw != NULL){draw->Destroy();}
  if (body != NULL){body->Destroy();}
  if (spacecraft != NULL){spacecraft->Destroy();}
  if (particleController != NULL){particleController->Destroy();}
  if (particleSystem != NULL){particleSystem->Destroy();}
  if (backgroundController != NULL) { backgroundController->Destroy(); }
  if (button != NULL){button->Destroy();}
  if (textWindow != NULL){textWindow->Destroy();}
  if (fireController != NULL){fireController->Destroy();}
  if (asteroidController != NULL){asteroidController->Destroy();}
  if (fireLightController != NULL){fireLightController->Destroy();}
  if (explosionController != NULL){explosionController->Destroy();}
  if (playerController != NULL){playerController->Destroy();}
  if (engineParticleController != NULL){engineParticleController->Destroy();}
  if (bulletController != NULL){bulletController->Destroy();}
  if (weaponController != NULL) { weaponController->Destroy(); }
  if (weaponLightController != NULL) { weaponLightController->Destroy(); }
  if (explosionLightController != NULL) { explosionLightController->Destroy(); }
  if (asteroidSpawnerController != NULL) { asteroidSpawnerController->Destroy(); }
  destroy = true;
    }
};


проект Mysterious Space. The losted moment

Сообщение отредактировал zaicev9797 - Пятница, 14 Июня 2019, 20:27
drcrackДата: Пятница, 14 Июня 2019, 21:15 | Сообщение # 2
старожил
Сейчас нет на сайте
Чел, вот глядя на этот код, могу тебе с уверенностью сказать, что тебе рано писать свой движок
Кроме того, что ты не готов (серьезно, не знаешь про виртуальные методы?), в юнити очень многое завязано на рефлексию и сделать аналогичный функционал на чистом С++ для С++ скриптов у тебя вряд ли получится
zaicev9797Дата: Пятница, 14 Июня 2019, 21:40 | Сообщение # 3
AbRaKaDaBrA
Сейчас нет на сайте
про виртуальные методы знаю. Но все дело в отсутствии практики с ними.
Вроде уже на втором курсе, и половине одногрупников курсачи на сях писать умудряюсь, а вот виртуальными методами так и не научился пользоваться.
В общем то я за помощью сюда и прибыл. Точно не за отправлением в детский садик. Вот если покажете пример решения и улучшения такого говнокода, вот это будет действительно круто.


проект Mysterious Space. The losted moment

Сообщение отредактировал zaicev9797 - Пятница, 14 Июня 2019, 21:41
drcrackДата: Пятница, 14 Июня 2019, 22:37 | Сообщение # 4
старожил
Сейчас нет на сайте
возьми любой учебник по C++ и почитай главу про ООП, там все обьясняется с примерами

PS
Цитата
Точно не за отправлением в детский садик.

если к тебе подойдет ребенок с игрушечным бульдозером и совочком для песка, и скажет что хочет построить 100-этажный небоскреб, ты ему начнешь обьяснить как это сделать или отправишь обратно в детский садик?


Сообщение отредактировал drcrack - Пятница, 14 Июня 2019, 22:44
pixeyeДата: Пятница, 14 Июня 2019, 23:12 | Сообщение # 5
Red Winter Software
Сейчас нет на сайте
Цитата zaicev9797 ()
Вроде уже на втором курсе, и половине одногрупников курсачи на сях писать умудряюсь,

Не путай продакшен код с курсачом который пишется чтобы выброситься. То что ты можешь университетские задачки на сях не говорит ни о чем.

Повторять юнитивскую архитектуру игровой логики так себе. Она не самая удачная и обусловлена тем что юнити нацелены на макс широкую аудиторию и жанровую направленность.

Неочевидны твои задачи. Ты пишешь движок или игру? Если игру то тебе действительно нужен настолько большой уровень абстракции ?


ACTORS - мой фреймворк на Unity
Until We Die - игра над которой работаю



Сообщение отредактировал pixeye - Суббота, 15 Июня 2019, 00:05
zaicev9797Дата: Суббота, 15 Июня 2019, 05:59 | Сообщение # 6
AbRaKaDaBrA
Сейчас нет на сайте
Цитата drcrack ()
ООП, там все обьясняется с примерами

Дак вот читал же ведь. И в унике читали курс по ООП, но как правило примеры и там и там ограничиваются двумя - тремя классами с простейшими примерами типа банковских счетов, по которым сложно представить как работает тот или иной тип классов или паттерн. Может плохо искал, но вот не видел я более крупных примеров, где разрабатывается более менее обьемная взаимосвязанная система.
Цитата pixeye ()
Если игру то тебе действительно нужен настолько большой уровень абстракции ?

А вот это уже хороший вопрос, может и действительно не нужен, я сам еще в раздумиях так сказать. С одной стороны хочется разобраться в том, как это у крупных дядек работает, с другой стороны супер навороченых игр я вроде тоже не собираюсь делать (покрайней мере не на самописных велосипедах)


проект Mysterious Space. The losted moment
afqДата: Суббота, 15 Июня 2019, 09:20 | Сообщение # 7
Разработчик
Сейчас нет на сайте
Цитата
если к тебе подойдет ребенок с игрушечным бульдозером и совочком для песка, и скажет что хочет построить 100-этажный небоскреб, ты ему начнешь обьяснить как это сделать или отправишь обратно в детский садик?

Хахаха
zaicev9797, я тут набрасал код на c++. Не знаю, поможет ли он тебе чем нибудь. Но мне стала интересна твоя задачка. Я исходил из того что вроде все объекты в unity исходят из gameobject. Вот как я реализовал это.
Код

#pragma once
#include "mem.h"
#include "base.h"
#include "two.h"

class Object {
    public:
  Object ( ) {
   mem = nullptr;
  }
  void set_attr ( Base *b, int i ) {
   Base *base = b->get();
   base->set ( i );
  }
  int get_attr ( Base *b ) {
   return b->get_int();
  }
    protected:
    private:
  Mem *mem;
  Two *two;

};

Видишь я сделал один set_attr, и он в зависимости от типа присваивает переменные либо mem, либо two.
В main это выглядит вот так.
Код

#include <stdio.h>
#include "object.h"
#include "mem.h"
#include "base.h"
#include "two.h"

int main ( )
{
    Object *obj = new Object ( );
    Mem *mem = new Mem ( );
    Two *two = new Two ( );

    obj->set_attr ( mem, 4 );
    obj->set_attr ( two, 8 );

    printf ( "1: %d\n", obj->get_attr ( mem ) );
    printf ( "2: %d\n", obj->get_attr ( two ) );
}

Первый выведет 4, потому что для mem я так записал, а второй выведет 8. Вообще это работает, если типы каждого вида есть в единственном экземпляре. Может мой код и далёк от совершенства, но это первое что мне пришло в голову.
Вот остальной код.
Код

#pragma once

class Base {
    public:
  Base ( ) { }
  virtual void set ( int i ) = 0;
  virtual Base *get ( ) = 0;
  virtual int get_int ( ) = 0;
    private:
    protected:
};

Здесь я использовал виртуальные функции, чтобы в произовдном классе использовать их. Из-за того, что в base определены эти виртуальные методы, а в производном их решение, я могу делать так.
Код

void set ( Base &m ) {
  printf ( "%d\n", m.get_int ( ) );
}
Mem mem;
set ( mem );

И вызовется код именно mem а не base. Ну код get_int ( ). Ладно это был пример, если ты не знаешь как использовать виртуальные функции. Теперь далее.
Код
#pragma once
#include "base.h"

class Mem : public Base {
    public:
  Mem ( ) { }
  void set ( int i ) { this->i = i; }
  Mem *get ( ) {
   Mem *m = this;
   return m;
  }
  int get_int ( ) {
   return i;
  }
    private:
  int i;
    protected:
};

Здесь я переопределяю вызов get, чтобы он возвращал тот тип, который надо.
Код

#pragma once
#include "base.h"

class Two : public Base {
    public:
  Two ( ) { }
  void set ( int i ) { this->i = i; }
  Two *get ( ) {
   Two *m = this;
   return m;
  }
  int get_int ( ) {
   return i;
  }
    protected:
    private:
  int i;
};

Здесь тоже переопределяю метод get.

Надеюсь тебе понятно. Мне понравилось моё решение, надеюсь и тебе тоже. Попробуй реализовать это в unity, Тогда не придётся писать для каждого атрибута setter и getter.

Добавлено (15 Июня 2019, 09:51)
---------------------------------------------
АААА БЛИН, я какую то фигню написал, я же не присвоил атрибутам object значения. ааааа.

Добавлено (15 Июня 2019, 10:02)
---------------------------------------------
zaicev9797, в android studio например для каждого свойства класса можно с помощью команды задать геттеры и сеттеры. Может и в твоей ide можно такое сделать?

Добавлено (15 Июня 2019, 10:41)
---------------------------------------------
zaicev9797 всё, я смог реализовать это на c++, только пока вот так.

Код

#pragma once
#include <map>
#include <string>
#include <iostream>
#include "mem.h"
#include "base.h"
#include "two.h"

class Object {
    public:
  Object ( ) {
   map[typeid( Mem ).name() ] = new Mem ( );
   map[typeid( Two ).name() ] = new Two ( );
  }
  void set_attr ( Base *b, int i ) {
   Base *base = map [ typeid( *b->get()).name() ];
   base->set ( i );
  }
  int get_attr ( Base *b ) {
   return map[typeid(*b->get()).name()]->get_int();
  }
    protected:
    private:
  std::map<std::string, Base*> map;

};

Это изменения в коде. То есть тебе свойства так и так придётся создать. Их я занёс в map. С помощью typeid я узнаю имя класса. Далее в main вот так.
Код

#include <stdio.h>
#include "object.h"
#include "mem.h"
#include "base.h"
#include "two.h"

int main ( )
{
    Object *obj = new Object ( );
    Mem *mem = new Mem();
    Two *two = new Two();

    obj->set_attr ( mem, 4 );
    obj->set_attr ( two, 8 );

    printf ( "1: %d\n", obj->get_attr ( mem ) );
    printf ( "2: %d\n", obj->get_attr ( two ) );
    printf ( "3: %d\n", obj->get_attr ( mem ) );
}

По другому я не смог сделать, то есть надо и здесь и здесь создавать объекты. Но в твоём случае там надо получить ссылку типа такого вроде GetComponent<typename>(). Чтобы получить имя класса, указателя не достаточно, надо проверять целый класс.

Добавлено (15 Июня 2019, 10:43)
---------------------------------------------
Думаю в c# тоже можно узнать имя класса.

pixeyeДата: Суббота, 15 Июня 2019, 10:58 | Сообщение # 8
Red Winter Software
Сейчас нет на сайте
Цитата zaicev9797 ()
А вот это уже хороший вопрос, может и действительно не нужен, я сам еще в раздумиях так сказать. С одной стороны хочется разобраться в том, как это у крупных дядек работает, с другой стороны супер навороченых игр я вроде тоже не собираюсь делать (покрайней мере не на самописных велосипедах)


*****во порой у крупных дядек работает XD Хочешь C/C++ код крупных игр смотреть смотри тогда сорсы кваки 3, думов и прочая. Они давно уже выложены.
Юнити пилят годами штат прогеров. Задача юнити - привлечь больше разработчиков и сделать их движок самым популярным и зарабатывать деньги :) . Многие их решениях это попытка выразить сложное через простое идя на кучу компромиссов.

Как разработчику игр тебе в общем-то должно быть пофиг. Ты берешь инструмент по своим скилам и выжимаешь максимум из него. ( Юнити замечательный двиг и много классных игр было сделано на нем )
Если тебе больше нра движки то просто устройся на работу в юнити : )

Ну и иди от простого к сложному.


ACTORS - мой фреймворк на Unity
Until We Die - игра над которой работаю

drcrackДата: Суббота, 15 Июня 2019, 11:08 | Сообщение # 9
старожил
Сейчас нет на сайте
Цитата
По другому я не смог сделать, то есть надо и здесь и здесь создавать объекты. Но в твоём случае там надо получить ссылку типа такого вроде GetComponent<typename>(). Чтобы получить имя класса, указателя не достаточно, надо проверять целый класс.
Добавлено (15 Июня 2019, 10:43)
---------------------------------------------
Думаю в c# тоже можно узнать имя класса.

кажеца ты начинаешь понимать что без рефлексии и дженериков тебя ждет только боль и страдания при попытке повторить архитектуру юнити на с++
вот бы тс еще понял


Сообщение отредактировал drcrack - Суббота, 15 Июня 2019, 11:09
afqДата: Суббота, 15 Июня 2019, 12:53 | Сообщение # 10
Разработчик
Сейчас нет на сайте
zaicev9797, а ты на c++ это делал, я думал что ты на c# на unity делаешь. Тот метод, который я написал, он медленный, потому что ассоциативный массив. Лучше создавать все свойства и методы. Сделай основной объект с виртуальными функциями. Наследуй каждый объект от этого объекта. А дальше думай ещё что нибудь.

Добавлено (15 Июня 2019, 13:19)
---------------------------------------------
Всё, теперь можно создавать объекты, только в main.
Код

#pragma once
#include <map>
#include <string>
#include <iostream>
#include "mem.h"
#include "base.h"
#include "two.h"

class Object {
    public:
  Object ( ) {
   map[typeid( Mem ).name() ];
   map[typeid( Two ).name() ];
  }
  void set_attr ( Base *b, int i ) {
   map [ typeid( *b->get()).name() ] = b->get();
   Base *base = b->get();
   base->set ( i );
  }
  int get_attr ( Base *b ) {
   return map[typeid(*b->get()).name()]->get_int();
  }
    protected:
    private:
  std::map<std::string, Base*> map;

};


Сообщение отредактировал afq - Суббота, 15 Июня 2019, 13:20
Форум игроделов » Программирование » C/C++ » Массив содержащий компоненты игрового обьекта
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг