játékfejlesztés.hu
FórumGarázsprojectekCikkekSegédletekJf.hu versenyekKapcsolatokEgyebek
Legaktívabb fórumozók:
Asylum:    5484
FZoli:    4893
Kuz:    4455
gaborlabor:    4449
kicsy:    4304
TPG:    3402
monostoria:    3284
DMG:    3172
HomeGnome:    2919
Matzi:    2526

Pretender:    2498
szeki:    2440
Seeting:    2306
Geri:    2196
Orphy:    1893
Joga:    1791
Bacce:    1783
MaNiAc:    1735
ddbwo:    1654
syam:    1491
Frissebbek | Korábbi postok
[1] [2] > 3 < [4] [5] [6] [7] [8] [9] [10] [15] [20] [25] [30] [35] [40] [45] [50] [55] [60] [65] [70] [75] [80] [85] [90] [95] [100] [105] [110] [115] [120] [125] [130] [135] [140] [142]
Instalok - Tag | 607 hsz       Online status #210579   2016.12.02 11:59 GMT+1 óra  
@Parallax:
Igen, ez a része tényleg jó, viszont azon a problémán agyaltam mostanában, hogy hogyan lehetne a scene load részét kikerülni a gameplay futtatásakor. Úgy értem, hogy tök jó dolog ez a scripting, de ez csak azt a részt oldja meg, hogy miként módosítsunk már meglévő dolgokat. Ha viszont az editorban oda szeretnék tenni egy dobozt, vagy akármit, akkor ahhoz el kell menteni a scene-t, majd újra kell tölteni a pályát (avagy újra kell indítani a programot) a tényleges gameplay esetén. Persze ez a kisebbik baj, azért az igen kényelmes a Unity-ben, hogy futás közben nyomhatok egy pause-t, és megnézhetem ott helyben az összes objektum állapotát, ha akarom módosíthatom, és folytathatom úgy a futást.

Valami olyasmi megoldáson gondolkoztam, hogy dev-time a gameplay kódból egy dll készülne, de maga az engine maradna static lib. Ez ugye annyiban lenne gond, hogy, ha betöltöm a dll-t, akkor a hozzálinkelt engine "duplázódva" lenne. Azonban sikerült átírnom az engine egy részét úgy, hogy Dependency Injectiont használjon. Ekkor viszont megtehetem azt, hogy az editor alkalmazáshoz már létrehozott systemek pointerjeit "átpasszolom a dll-nek", így az nem hozna létre pl. egy új renderert, hanem a már meglévőt használná.

Így viszont megoldható a hot-reload is, hiszen csak az adott dll-t kell újratölteni, és meghívni néhány entry point-jellegű függvényét.

Nem tudom, hogy ez így mennyire működne, de nem lenne rossz, mert akkor maradhatnék c++ban a "scripteléshez" is, az összes feature-jével együtt.

   
Parallax - Tag | 606 hsz       Online status #210577   2016.12.02 00:11 GMT+1 óra  
Idézet
Instalok :
Be kell vallani azért, hogy a Unity megoldása elég kényelmes. Adott egy editor, amiben ott helyben lehet futtatni és kipróbálni a gameplay kódot.


Ezért jó a Lua. Könnyű bindolni és hozzá editort írni és bármire lefordítható, amire van C compiler.

   
Instalok - Tag | 607 hsz       Online status #210446   2016.10.26 20:53 GMT+1 óra  
Az alapvető gond ezzel a megosztott dologgal ugye az, hogy a gameplay kód függ az engine liben, de ugyan úgy az editor is. Az engine jelenleg egy statikus lib, amit szimplán összelinkelek a gameplay kóddal, így nyugodtan használható az engine funkcionalitása. Viszont mivel "duplikált kódot" nem szeretnék, így nem lett volna elég, ha a gameplay kódból csináltam volna shared libet, az engine is az kellett volna, hogy legyen. Onnantól kezdve pedig ugye csak egyre bonyolultabb minden, végül ezért elvetettem az egész megközelítést. Be kell vallani azért, hogy a Unity megoldása elég kényelmes. Adott egy editor, amiben ott helyben lehet futtatni és kipróbálni a gameplay kódot.

Persze, lehet egy ahhoz hasonló megoldás is, amit írtál. Készülne a gameplay-ből egy olyan futtatható bináris is, ami tud kommunikálni az editorral. Pontosabban az editor tud vele. Így például különböző signalokat tudna neki küldeni, amivel az editorból lehet resetelni egy scene-t, megállítani az update-et, stb. Persze mehet a visszafelé kommunikáció is, hasonlóan ahogy írtad (be kell valljam, a socketes kommunikáció eszembe sem jutott ), csak ugye egy egyszerű signalt küldeni könnyebb, mint egy "teljes objektumot" átküldeni. Persze az is megoldható, csak kell egy jó serializer/deserializer hozzá, így az editor bizonyos eseményekkor lekérhetné a jelenlegi adatokat egy entity-ről / komponensről (mint például az objektum pozíciója). Végül is megoldható ez a socketes kommunikáció, nem is olyan rossz ötlet, bár ezt szerintem csak egy későbbi változatnál csinálom meg, ha úgy alakul - néha tényleg muszáj egyszerűsíteni, mert így sem készül el sohasem az ember. Köszi az ötletet!

Ja és az automatikus DI dolgot dícséretnek szántam. Mostanában néztem google talk videókat, ahol nagyon nyomatták a DI-t meg Law of Demeter-t meg minden ehhez hasonlót, és rájöttem, hogy eddig én is teljesen rosszul csináltam. (továbbá megnézve az UE4 forráskódját, ők is teljesen rosszul csinálták, hehe csak hát ugye csinálni egy singleton-t, amit elér az ember mindenhonnan könnyebb, mint normális design-t kitalálni).

Nem akartalak amúgy elbizonytalanítani. Anno én is csináltam valami hasonlót, de egy UE4 ötletet követtem: module managert írtam, de a lényege végső soron ugyan az volt, mint amit te csináltál. És én is azt tapasztaltam, hogy működött, bár én csak MSVC-vel próbáltam ki. Szóval, ha működik, akkor tök jó! Ők egyébként a következő kódrészletet használták:
Kód:
// If we're linking monolithically we assume all modules are linked in with the main binary.
#define IMPLEMENT_MODULE( ModuleImplClass, ModuleName ) \
    /** Global registrant object for this module when linked statically */ \
    static FStaticallyLinkedModuleRegistrant< ModuleImplClass > ModuleRegistrant##ModuleName( #ModuleName ); \
    /** Implement an empty function so that if this module is built as a statically linked lib, */ \
    /** static initialization for this lib can be forced by referencing this symbol */ \
    void EmptyLinkFunctionForStaticInitialization##ModuleName(){} \
    PER_MODULE_BOILERPLATE_ANYLINK(ModuleImplClass, ModuleName)


szerk.:
Apropó, egy apró ötlet a kódhoz, amit csináltál: Lehetne egy csak debug módban használt guarding, ami figyelné azt, hogy az implementáció ne hívja meg az szülőosztály adott függvényét, mert az jó kis végtelen ciklushoz vezetne. Erre gondolok:
Kód:
class ServiceA
{
public:
    virtual void foo()
    {
        if (impl)
            impl->foo();
    }

private:
    ServiceA* impl;
};

class ServiceAImpl : public ServiceA
{
public:
    void foo() override
    {
        ServiceA::foo(); // inf loop
    }
};

A szülő osztályban ha lenne egy check, akkor ez elkerülhető. Persze, a programozó bármikor tökön tudja magát lőni, ha akarja, ettől függetlenül. Szóval lehet, h csak én vagyok túl óvatos önmagammal szemben is.

Ezt a hozzászólást Instalok módosította (2016.10.26 21:03 GMT+1 óra, 992 nap)

   
Prenex - Tag | 15 hsz       Online status #210443   2016.10.26 18:48 GMT+1 óra  
@Instalok:
Hát végül is még ezzel is lehetne dinamikusat csinálni. Ugyebár a kis példából jól látszik, hogy nem nagyon tudod mit injektálsz, ezért akár csinálhatnál valami ilyesmit:

- Adott az editor (ilyesmi komponensalapú szerkezetben). Ott meg vannak adva miféle interfészeket lehet megvalósítani. Ez egy standalone alkalmazás exe, vagy linux bináris.
- Adott egy másik ilyen projekt, ami az összes "szkriptet" tartalmazza. Persze köztes halmazt képeznek a nyilvános interfész header-ek ilyenkor.
- Ebben a másik projektben a main és az alap dolgok adnak szolgáltatásokat az editorral / runtime-al való protobufos, vagy socket-es kapcsolathoz.
- Ez a kapcsolat kézfogás-alapú, de fel van készítve arra, hogy felépül és leépül, miközben az editor várakozó helyzetbe tehető.

Ezek mellett már lehet olyat, hogy az editoron belül egy kis ablakban (vagy persze külső szerkesztőben írod a tényleg igazi c++ kódot, ami persze a másik projekt fájljait módosítja és akkor van egy gombnyomás, ami leállítja a másik socketes progit, majd az összes ottani scriptet make-eli. Ugyebár a make-elés eleve figyeli, hogy csak az új dolgokra fusson így fel a struktúra miatt és ha visszajött a shell, akkor elindul az editor másik fele, ami szól, hogy készen vagyunk.

Persze ez már nem csak a barátom tartaná szerintem kicsit overcomplicated-nek, de szerintem működne. A dolog előnye ugye, hogy használhatod ugyanazt a c++ fordítódat, amit egyébként is (a legújabb lambdákkal, meg unique pointerekkel), de itt már nem lehet std::vector paramétereket átadni meg hasonlók... ez itt legalábbis nehezebb lenne akárcsak egy DLL-nél.

Ami esetleg még érdekes lehet, hogy ha magad akarsz valamit és nem mondjuk Lua-t, hogy esetleg valami FORTH variációt magadnak tudsz implementálni. Ahhoz persze megírod a fordítód és még kifejező is, viszont az tuti ziher, hogy szerintem valami meglévő megoldás jobban optimalizál majd...

Az se rossz mondjuk, ahogy most van a leírásod alapján. Végülis tetszik. Elsőre én is mindig valami bonyolultat akarok, aztán lesz valami olyan, ami egyszerű és meg is felel. Majd persze az is tud szépen fejlődni ;-)

ui.:
"Látom azért automatikus dependency injection is van a frameworkben."

- Túl sok volt az enterspájz programming már és ilyeneket csinálok )

"Arra kell figyelni, hogy vannak fordítók, amik az "unused object"-eket kioptimalizálják, azaz a static registernél erre lehet, hogy figyelni kell majd."

- Amikor kitaláltam, akkor meg voltam győződve, hogy szabványosan meg kell hívódjon ez a kód. Szoktam több fordítón is tesztelni optimalizálva is ezeket a kódjaimat és nem volt még ezzel baj, de ez persze nem jelenti, hogy nincs ezzel talán szopás. Most el is bizonytalanodtam :-)

Ezt a hozzászólást Prenex módosította (2016.10.26 18:55 GMT+1 óra, 992 nap)

   
Instalok - Tag | 607 hsz       Online status #210441   2016.10.26 10:23 GMT+1 óra  
@Prenex:
Igen, ez a megközelítés már eddig is megvolt/megvan - csak saját implementációval -, csak pont az lett volna a lényege, hogy a hot reload lehetséges legyen. Látom azért automatikus dependency injection is van a frameworkben. Arra kell figyelni, hogy vannak fordítók, amik az "unused object"-eket kioptimalizálják, azaz a static registernél erre lehet, hogy figyelni kell majd.

Azóta már találtam az editorhoz egy másik megközelítést. Próbáltam ugye azt elérni, hogy hasonlóan működhessen majd, mint a Unity: átírom a scriptet/komponenst/akármit, lefordítom dll-be, az editor újratölti, és máris látom az editorban a változtatásokat. Ez viszont magával húzná a dll-ek bonyolultságát, így végül elvetettem.

Azt a kevésbé "szép" megközelítést választottam, hogy az editor ilyen szempontból buta, és direktben nem tud a gameplay komponensekről. Cserébe az editor csak egy adatszolgáltató. Azaz egy objektumra definiál egy új komponenst xy névvel, amihez fel tud venni értékeket [key, value] alakban. Maguknak a komponenseknek a feladata parse-olni és használni az adatot. Magyarán megfordítottam az irányt: az editornak továbbiakban nem lesz függősége a gameplay lib, csupán adatokat szolgáltat, amit a gameplay lib felhasznál. Így legalább nem kell megoldanom azt sem, hogy hogyan olvassam ki a komponensekből az editor számára látható elemeket.

   
Prenex - Tag | 15 hsz       Online status #210439   2016.10.26 06:49 GMT+1 óra  
Instalok:

Az általad felvetett két alternatíva mellett egy engine esetén még talán érdekes lehet a komponensalapú megközelítés is. Lényegében a DLL / shared object is ilyen (runtime komponens), de mostanában azzal szoktam kísérletezgetni, hogy fordítási idejű komponens-architekturákkal mókolok. Arról van szó, hogy ez egy ugyan olyan plugin szerkezet, mintha DLL, SO, vagy OSGi lenne és a hasonló heavyweight dolgok, de nem runtime - sőt amikor egy plugint ki akarok cserélni, vagy mondjuk letöltesz egy komponenst, akkor újra kell fordítani a kódot.

Tudom ez nem teljesen drag&drop, viszont nagyon egyszerű megcsinálni és átlátható szerintem az architektúra. A minimalista barátomnak, már így is "túl overcomplicated" lett és egyébként is kíváncsi vagyok kinek mi a véleménye.

https://github.com/prenex/LightWeightComponents

- Itt megtalálható a jelenlegi változat (direkt egy minimál példa van csak megvalósítva, de majd csinálok ezzel valami nagyobb progit is).
- Ez még szerintem változni fog. Például bekerülnek a komponensekbe tehető bináris asset-ek és filozofálok a make-elés egyszerűsítésén.

Ha nem kell mindenáron dinamikusnak lennie, akkor szerintem ez egy engine esetén is járható út lehet. Az ötlet teljesen ingyenes és opensource, csak említs meg ha használod ;-)

   
Parallax - Tag | 606 hsz       Online status #209940   2016.08.01 07:46 GMT+1 óra  
A Lua beépített módon támogatja az OOP-t, de annyira rugalmas, hogy osztály, egységbe zárás és öröklkés könnyen megoldható. Lehet AngelScript-et is használni, ami már majdnem olyan, mint a C++, de ott asszem a futás közbeni kód módosítás nem annyira rugalmas, mint Lua alatt, pedig ez a script egyik alap lényege.

Ezt a hozzászólást Parallax módosította (2016.08.01 07:52 GMT+1 óra, 1079 nap)

   
Instalok - Tag | 607 hsz       Online status #209939   2016.08.01 06:59 GMT+1 óra  
A legnagyobb gondom talán csak az marad így, hogy hogyan rendeljek egy adott scriptet egy objektumhoz. Mert ugye a script követheti a komponenses megközelítést (van néhány "eseménykezelője", és igazából ennyi), csak valahogy ezt társítani is kell egy adott objecthez.

Ráadásul a Lua-t nem ismerem, de amennyit foglalkoztam gameplay kóddal, ott előfordult, hogy kellett (érdemes) volt használni öröklődést, stb., amit egy c-alapú programozási nyelv nyilván biztosít.

   
syam - Törzstag | 1491 hsz       Online status #209938   2016.07.31 23:18 GMT+1 óra  
Egy ésszerű határt érdemes meghúzni a drag&drop és a szövegszerkesztő között
alias aalberik
   
Instalok - Tag | 607 hsz       Online status #209937   2016.07.31 23:06 GMT+1 óra  
Igen, lehet, hogy valami ilyesmiben fogok én is kikötni. :/

Bár, megfelelő mennyiségű UE4 és/vagy Unity után nagyon szimpatikus az a módszer, hogy saját komponenseket alkothatunk, amiket az editorban is látunk, és csak simán "rádobjuk" a game objectekre.

   
syam - Törzstag | 1491 hsz       Online status #209936   2016.07.31 22:57 GMT+1 óra  
Én simán luából engedem rommá scriptelni az enginemet, editoromat és a guimat.
alias aalberik
   
Instalok - Tag | 607 hsz       Online status #209934   2016.07.31 10:37 GMT+1 óra  
Anno a cégnél használtunk valamiféle lazy dll load dolgot. Ha jól rémlik, valami olyasmi volt a lényege, hogy megmondtuk a linkernek, hogy semmi gond, hogy nem találja a függvényt, majd menet közben betöltünk egy dll-t, amiben benne lesz.

Megközelítem másképp: scriptelésen gondolkozok, és a leggyakoribb megoldás, amit láttam, az az, hogy az engine-t dll-be fordítják, és nagy részét exportálják (amit ugye használhatóvá akarnak tenni a kliens által). Előnye az, hogy használhatsz egy jól megszokott programozási nyelvet, le tudod fordítani, és gyors (főleg, ha c++ban írod a scripteket is). Hátránya meg nyilván az, hogy shared lib lesz az engine, mindenféle dolgot ki kell exportálni, arról nem is beszélve, hogy az STL-t nem használhatod, mert még a vector-t sem lehet értelmesen kiexportálni.

A másik megközelítés az, hogy az engine-t nem bántjuk ilyen szempontból, maradhat akár statikus lib is, cserébe a script az, amit runtime betöltünk, és futtatunk.

Ezen belül ugye lehet több megoldás is:

Lehet valamilyen virtuális gép / interpreter, ami egy saját nyelvet dolgoz fel, és meghívja az engine megfelelő részét. Ennek több hátránya is van. Például az, hogy amennyiben egy új funkció bekerül az engine kódba, azt majdhogynem duplikálni kell. Megírjuk magát a kódot, meg azt a kódot is, ami ezt futtatja a scriptből. Továbbá egy saját VM/Interpreter megírása akár bonyolult is lehet, és lassabbá is teheti a futást.

A másik, ami eszembe jutott az a fent említett lazy dll loading. Olyat lehet-e valahogy csinálni, hogy az engine marad statikus lib, a scripteket szintén c++ban írom (felhasználva az engine headeröket), de valahogy megmondom neki, hogy ne aggódjon a linkeléskor, mert menet közben meg fogja találni a függvényeket / objektumokat?

Szóval valahogy így nézne ki a dolog:
Engine - lib
Application - exe
Game - dll
Természetesen az Application-be belefordítom az Engine-t. Az alkalmazás indításakor pedig fogná a Game.dll-t, és betöltené. Azonban a Game.dll-hez nem lehet hozzálinkelve az Engine.lib, mert akkor ugye minden "duplikálva lenne". Itt kellene az, hogy amikor a Game.dll-t fordítom, akkor ne hasaljon el a linker, hogy nem találja a függvényeket, amiket meg akarok hívni.

   
Instalok - Tag | 607 hsz       Online status #209700   2016.05.31 14:10 GMT+1 óra  
Így gondoltam én is, azért kérdeztem. Azután javasolni akartam, hogy azon projekt beállításait nézze át, amelyikből a dll fordul. Hülye azért nem vagyok.

   
Matzi - Szerkesztő | 2526 hsz       Online status #209699   2016.05.31 13:51 GMT+1 óra  
Úgy lesz egy dll ahogyan egy exe. Egyszeruen a projektek nagy része lib-be fordul, a dll meg azokat beépíti.
If your game idea starts with the story it’s not a game idea.
Stories in games are optional.
   
Elodin - Tag | 184 hsz       Online status #209698   2016.05.31 13:49 GMT+1 óra  
Közben megtaláltam, hogy az egyik project újrafordítása gyanúsan magával rántja az összes többi projectet, és ez hozza létre a dll-t a többiből

Itt forceolom a pdb generálást, és így műkszik.

   
Instalok - Tag | 607 hsz       Online status #209697   2016.05.31 13:34 GMT+1 óra  
Hogy lesz a halom projektből egyetlen dll?

   
Elodin - Tag | 184 hsz       Online status #209696   2016.05.31 13:29 GMT+1 óra  
Visual studio-ban van egy solutionben egy halom project, az egészből lesz egy dll. A dll-hez kéne pdb fájl, de nem sikerült rájönnöm, hogy tudok csinálni.

A projecteknél be van állítva, hogy generáljanak, minden project saját build mappájába kerül is egy, de azokat nem lehet használni a dll-el, egy közös meg nincs.

Kb. semmit nem találtam az interneten ezzel kapcsolatban, bárkinek bármi tapasztalata/ötlete a témában?

   
Instalok - Tag | 607 hsz       Online status #209618   2016.05.18 16:26 GMT+1 óra  
Akkor inkább maradok annál, hogy egy quadtreem lesz, úgyse lesz túl sok layer, ha meg mégis, akkor ez van. Úgysem osztok egy bizonyos méretnél kisebbre.

   
Asylum - Törzstag | 5484 hsz       Online status #209615   2016.05.18 13:28 GMT+1 óra  
Kód:
template <typename T>
class QuadTree
{
    // ...
};


Így.
C++ fordítóval és macival alszom
http://darthasylum.blog.hu/
   
Instalok - Tag | 607 hsz       Online status #209614   2016.05.18 10:46 GMT+1 óra  
Kellene nekem valami trükk ahhoz, hogy egy Quadtree-t hogy tudnék általánosra megcsinálni. Úgy értem, hogy van mondjuk geometriám, pontfényem, meg később még kitudjami. A geometriák viszont layerenként vannak rendezve (hogy lehessen csak egy adott layert rajzolni), de például a fények viszont nem.

Tehát kell nekem egy quadtree layerenként, ami (egyelőre csak) a geometriák rendezéséért felelős, meg kell egy "global" quadtree, ami a nem layerhez tartozó (egyelőre csak point light van) objektumok rendezéséért felelős.

No persze azt meg lehetne csinálni, hogy van egy base class, mondjuk IQuadTreeElement, ami meg tudja mondani a befoglalóját, és tartalmaz egy enumot is, ami megjelöli a típusát. Így egységesen lehetne kezelni az egészet. Amikor pedig lekérdezem a látható IQuadTreeElement-eket, akkor a típus alapján tudok switchelni, és a megfelelő kis bucketbe rakni.

Nyilván ez működőképes, csak kíváncsi vagyok, hogy azért van-e ennél szebb megoldás. Valami közös ős mindenképpen kelleni fog, mert valahol tárolnom kell, hogy egy adott elem az melyik cellába tartozik (hogy transzformálás esetén el tudjam távolítani az adott cellából, ha szükséges).

szerk.:
Nyilván meg lehetne fordítani, és azt mondani, hogy már maga a QuadTree is layerenként tárolja a geometriát, csakhogy ebben az esetben túl sok fölösleges felosztása lenne. Ha például egy layeren csak 1-2 elszórt objektum van, akkor a teljes quadtree-t elég csak néhány alkalommal darabolni. Ha viszont egy quadtree tartozik mindenkihez, akkor a többi layer miatt már kisebb részekre van darabolva, ezzel kvázi növelve a tesztelendő cellák számát.

Ezt a hozzászólást Instalok módosította (2016.05.18 10:54 GMT+1 óra, ---)

   
Tunyu - Tag | 450 hsz       Online status #209555   2016.05.06 20:01 GMT+1 óra  
Nézd meg ezt, talán van benne vmi használható.

   
Instalok - Tag | 607 hsz       Online status #209554   2016.05.06 14:43 GMT+1 óra  
Az értelmesebb játékok kezelik a RightAlt-ot, mint billentyűt, szóval nem, nem felejtem el.

   
Asylum - Törzstag | 5484 hsz       Online status #209552   2016.05.06 12:35 GMT+1 óra  
Nincs ilyen, hogy "right alt", csak egy shortcut a Ctrl Alt-ra, szóval felejtsd el.
C++ fordítóval és macival alszom
http://darthasylum.blog.hu/
   
Instalok - Tag | 607 hsz       Online status #209528   2016.04.29 11:01 GMT+1 óra  
Igen, és ennek állítólag történelmi okai vannak. Valószínűleg valami olyasmi lesz a megoldás, hogy amikor VK_CONTROL érkezik, akkor GetKeyAkármivel megnézem, hogy a right alt (aka AltGr) le van-e nyomva, és ha igen, akkor "elnyelem" az üzenetet.

   
peti634 - Tag | 148 hsz       Online status #209527   2016.04.29 07:59 GMT+1 óra  
Én úgy tudom, nem, mivel nincs AltGr gomb (ahogy én tudom), és ezért muszáj így lennie. Sőt, ha lenyomod a bill-en, a Ctrl, és Alt gombot, akkor ugyan azt kapod mintha az AltGr-t nyomnád. Én legalábbis így tudom.
ha már szép nem vagy, hülye ne légy
http://www.pokolstudio.hu
   
Instalok - Tag | 607 hsz       Online status #209526   2016.04.28 19:00 GMT+1 óra  
Nincs WinAPI topic, szóval ide:
Megvan a keydown/keyup detektálás, csak amikor "Alt Gr"-t, avagy Right Altot, avagy WinAPI-ban VK_RMENU-t nyomok, akkor előtte küld egy VK_LCONTROL-t is, mivel AltGr = Alt+Ctrl.
Ki lehetne ezt valahogy kerülni? Az a baj, hogy először jön a Ctrl, és utána az Alt.

   
Eldor - Tag | 163 hsz       Online status #209477   2016.04.18 19:36 GMT+1 óra  
A következő megoldással megspórolod a static_cast-ot, de nem ugyanazzal a névvel fogsz hivatkozni a típusra és az enumra.

Kód:
namespace EnumName
{
enum
{
    E0 = 0,
    E1,
    E2,
}
}

typedef int EnumName_t;

   
Asylum - Törzstag | 5484 hsz       Online status #209476   2016.04.18 12:48 GMT+1 óra  
A szebb megoldás az, hogy ilyet nem csinálsz... Nem erre való az enum.
C++ fordítóval és macival alszom
http://darthasylum.blog.hu/
   
Instalok - Tag | 607 hsz       Online status #209475   2016.04.18 12:44 GMT+1 óra  
@Asylum:
Igen, én is oda szoktam írni a "= 0"-t, csak most itt lemaradt.

Továbbá azt is tudom, h lehet használni static_cast-ot, de nem ez volt a kérdés. Nem az enum i. elemét akarom elérni, hanem az enum i. eleméhez képest vett k. elemet (ahol az i nem egy szám, hanem az enum egy adott értéke). Ahogy azt lentebb írtam:
Kód:
Enum::Data + k
-->
(int)Enum::Data + k
-->
(Enum)((int)Enum::Data + k);

Csak ez nyilván nem C-style casttal, hanem static_cast-okkal. Engem az érdekelt, hogy van-e ennél szebb megoldás, nem az, hogy ez valid-e, vagy sem. De azért köszi

@Matzi:
Hm, ez egész tetszetős ötlet, egyelőre ott rondálkodik az a pár static cast, de ha még néhányszor kell, akkor tuti írok én is valami hasonlót.

   
Matzi - Szerkesztő | 2526 hsz       Online status #209472   2016.04.18 11:24 GMT+1 óra  
Az enum egy speciális állatfaj, mivel semmi sem garantálja, hogy folytonos a tartomány amit lefednek. Én erre a cégnél, amikor sok enumunk volt mindig 0 és NUM elem kozott, akkor írtam egy iterátor osztályt, ami egyszerre volt int (vagy valami underlying type) meg a num, és azt adta vissza, amlyiket kellett. Pluszban lehetett inkrementálni. A vége valami ilyesmi lett:

Kód:
for (auto elem : Enumerator<EnumType>())
{
  // Implicit cast to both types
  int a = elem;
  EnumType b = elem;
}


Ha kell kuldok kódot, de elég egyszeru.

Az otthoni enginemben meg egy statikus tárba be lehet tolni az elemeket meg a nevuket egyesével. A hatránya, hogy statikus inicializációt igényel, de nem folytonos range-eket is kezel, plusz string nevet, ami hasznos ha ki kell írni fileba.
If your game idea starts with the story it’s not a game idea.
Stories in games are optional.
   
Asylum - Törzstag | 5484 hsz       Online status #209471   2016.04.18 11:23 GMT+1 óra  
Először is:

Kód:
Blah = 0


különben a fordító vad dolgokat csinálhat. Egyékbként meg a szabvány leírja, hogy static_cast használható enumokra.

Kód:
TheEnum nthelem = static_cast<TheEnum >(n);
C++ fordítóval és macival alszom
http://darthasylum.blog.hu/
   
Instalok - Tag | 607 hsz       Online status #209467   2016.04.18 09:22 GMT+1 óra  
Ha van egy enum classom, például:
Kód:
enum class
{
    Blah,
    BlahBlah,
    Data0,
    Data1,
    Data2
}

Meg egy for ciklusom is [0, 3), akkor hogy lehet a legszebben elérni az adott elemet? Mivel nem szeretem a C-style castokat c++ban, így mindig kiírom a static_cast-ot, így viszont elég csúnya lesz:
Kód:
for (uint32 i = 0; i < 3; ++i)
{
    const TheEnum theVal = static_cast<TheEnum>(static_cast<uint32>(TheEnum::Data0) + i);
}

A "standard" enumokkal ugye működik az egyszerű összeadás, de mivel ez erősen típusos, így azt nem engedi meg...
Kód:
const TheEnum theVal = TheEnum::Data0 + i;

   
Asylum - Törzstag | 5484 hsz       Online status #209180   2016.03.12 22:02 GMT+1 óra  
Ha időt akarsz spórolni, akkor használhatod az ICU-t:

http://site.icu-project.org/
C++ fordítóval és macival alszom
http://darthasylum.blog.hu/
   
Instalok - Tag | 607 hsz       Online status #209179   2016.03.12 20:42 GMT+1 óra  
Az UTF-8-ról tudom, hogy változó szélességű, de pl. az UTF-16 már fix. Nemrég pedig ezt olvastam, ahol beszél erről egy picit.

Igazából eleve használhatnék 2 byte-os "karaktereket", igazából egy minimális memóriapazarlás csak a hátránya. No meg ugye a blogon emlegetett byte ordering is, de ha saját magamnak kezelem, akkor úgysincs belőle gond.

Egyébként itt van a videó az általad linkelt pdf-hez.

szerk.:
Most olvasom csak, hogy az UTF-16 is változó hosszúságú. Még jó, hogy az egyetemen hülyeséget tanítanak.

Ezt a hozzászólást Instalok módosította (2016.03.12 21:16 GMT+1 óra, ---)

   
Matzi - Szerkesztő | 2526 hsz       Online status #209177   2016.03.12 19:09 GMT+1 óra  
Ezt olvasd el mindenképp. Pl mert az UTF eleve nem fix szélességu, amit sokan nem tudnak.
Egyébként meg a font renderelés más téma, ott be szokták gyujteni a lokalizációs fájlokból a szimbólumokat és valamilyen formában kirenderelni egy textúrába.
If your game idea starts with the story it’s not a game idea.
Stories in games are optional.
   
Asylum - Törzstag | 5484 hsz       Online status #209174   2016.03.12 10:42 GMT+1 óra  
UTF8

win-en ebből MultiByteToWideChar() és ki tudod rajzolni.
C++ fordítóval és macival alszom
http://darthasylum.blog.hu/
   
Instalok - Tag | 607 hsz       Online status #209173   2016.03.12 07:53 GMT+1 óra  
Csináltam egy alap localization systemet, ami egyelőre semmi extra, csak egy kulcs alapján megkapok egy stringet, amelyet a jelenleg betöltött localization file határoz meg.

A problémám csak annyi, hogy ez jól működik minden olyan nyelvre, amelynek a karakterkészlete belefér 1 byte-ba, mert a betöltött szövegeket std::string-ként tárolom, amely viszont nem lesz jó például a japán nyelvre (kivéve a romanji, katakana, hiragana írásokat), hiszen a kanji sok ezer szimbólumból áll.

A gond például ott kezdődik, hogy kell egy másik karakterábrázolás (2 byte már úgy gondolom elég lenne, 2^16=65536 különböző karakter), valamilyen Unicode dologgal. Érdemes csinálni egy saját "stringet", amely ezeket is tudja tárolni? Ott van a varchar, de arról azt olvastam, h compiler függő, hogy végül mekkora lesz a mérete.

Továbbá felmerül a gond az ingame text rendereléssel, ahol szintén valahogy társítani kell az adott textúrakoordinátákhoz a megfelelő szimbólumokat, de ez már másik topic lesz.

   
Sliden - Tag | 3 hsz       Online status #209128   2016.03.02 12:27 GMT+1 óra  
Sziasztok!
World of Warcraft: Warlords of Draenor szerverhez csinálásához keresek embereket. Jelenleg 5en vagyunk(a wow részlegen), a munkálatokat már elkezdtük, átlag életkor 21+ A csapat teljesen komolyan gondolja amit csinál, amúgy egy "Multigaming" vagyunk, és jó pár játékhoz csinálunk szervereket (Minecraft, GTA5, WoW, ArmA 3 stb...) Saját szervergépekkel, és hozzáértő emberekkel. akit érdekel a dolog az keressen bátran, Aki úgy gondolja hogy van elég ideje és sokat tud foglalkozni a dologgal, annak egy csekély havi szintü fizetést fel tudok ajánlani, nem valami nagy összeg(20-35k ft) de a semminél jobb. Természetesen a szerver beindulása után részesedést jár a bevételből

Amilyen tudású emberekre szükség van:
C++
C#
Visual Studio ismerete
MySQL és Scriptelés
TrinityCore ismerete nem hátrány, de nem is kötelező

Ha érdekel keress meg privát üzenetbe, Skypeon (raptor212) emailen:xsm023@gmail.com vagy TS3 szerverünkön: aviorgaming.com (Brendon néven találtok meg)

Ezt a hozzászólást Sliden módosította (2016.03.03 15:41 GMT+1 óra, ---)

   
Instalok - Tag | 607 hsz       Online status #208966   2016.01.13 22:52 GMT+1 óra  
Igen, tudom, hogy mi a diamond megoldása, viszont inkább annak az elkerülése érdekelt.

Nem igazán értem viszont a feltevésedet. Viszont (ha jól értem), nem szeretem a túlzottan vegyes osztályokat, inkább maradjon csak meg külön-külön. Ha nincs külön vertex- és index buffer, akkor nagyon jó, mert ugyan azt az osztályt lehet példányosítani, és kész. Ráadásul ez az egész így csak annyit mond meg, hogy van egy olyan osztály, ami úgy viselkedik, mint egy vertex buffer. Hogy ez konkrétan hogy van implementálva, az aztán tökre nem érdekes a magas szinten. Ennyi nekem elég is.

   
Asylum - Törzstag | 5484 hsz       Online status #208965   2016.01.13 18:02 GMT+1 óra  
Megint rossz megközelítés. Ne absztrahálj low level dolgokat, mert újabb apikban nincs is vertexbuffer (csak buffer). De említhetném a GL 4-es shader storage buffert is. Vastag réteget csinálj és azt specializáld (GLMesh, DXMesh, stb.).

diamond problemre meg olvasd el az öröklődésről szóló cikkemet (virtuális öröklés a megoldás).
C++ fordítóval és macival alszom
http://darthasylum.blog.hu/
   
Instalok - Tag | 607 hsz       Online status #208963   2016.01.13 12:45 GMT+1 óra  
Milyen patternnel lehetne szépen megoldani az alábbit?

Van egy BufferObject osztály, ami a vertex- és index bufferek közös tulajdonságait, műveleteit tartalmazza. Ebből öröklődik maga a VertexBuffer és IndexBuffer osztály, ami kiegészíti a saját funkcionalitásával.

Ebből a kettőből öröklődik az API-specifikus osztály (pl. OGLVertexBuffer). itt jön a problémám: az OpenGL szintjén a két osztály kb. csak egy enumban tér el, azaz jó lenne, ha közös ősük lenne. Ekkor viszont el is jutottam a "diamond inheritance" problémáig.

Egyetlen megoldásként egyelőre azt találtam ki, hogy van egy OGLBufferObject osztály is, ami az OpenGL szinten közös dolgokat tartalmazza, továbbá ugyan úgy megvan az OGLVertexBuffer és OGLIndexBuffer osztály is, ami implementálja a pure virtual függvényt, ami csak meghívja a megfelelő enummal az OGLBufferObject egy függvényét. Na szóval valami ilyesmi (természetesen ez csak vázlat, de a lényeg benne van)
Kód:
class BufferObject
{
    // .... közös dolgok

    // implementálandó függvény
    virtual void Upload(offset, size) = 0;
};

class VertexBuffer : public BufferObject
{
    // ... kiegészítések
};

class IndexBuffer : public BufferObject
{
    // ... kiegészítések
};

class OGLBufferObject
{
public:
    uint32 GetId() const
    {
        return id;
    }

protected:
    void OGLUpload(target, maxsize, offset, size, data)
    {
        if (!id)
        {
            // ... create buffer (<-- target)
        }
        else
        {
            // ... bind buffer (<-- target)
        }
       
        // ... fill data (<-- target)
    }
   
private:
    uint32 id;
};

class OGLVertexBuffer : public VertexBuffer, public OGLBufferObject
{
    void Upload(offset, size) override
    {
        OGLUpload(GL_ARRAY_BUFFER, GetMaxSize(), offset, size, GetData());
    }
};

class OGLIndexBuffer : public VertexBuffer, public OGLBufferObject
{
    void Upload(offset, size) override
    {
        OGLUpload(GL_ELEMENT_ARRAY_BUFFER, GetMaxSize(), offset, size, GetData());
    }
};

Van-e esetleg erre valami okosabb megoldás, vagy "jóezígy"?

szerk.:
Ja igen, a Vertex- és IndexBuffer osztályoknak a BufferObject osztályból kell öröklődniük, mert használják annak bizonyos függvényét/függvényeit.

   
Instalok - Tag | 607 hsz       Online status #208819   2015.12.19 14:11 GMT+1 óra  
Szóval, ha az ember dynamic libet akar használni, akkor implementáljon saját containereket? Esetleg változott ez a dll-export dolog a 11-es szabvánnyal?

   
Instalok - Tag | 607 hsz       Online status #208814   2015.12.16 22:36 GMT+1 óra  
Nem viszem túlzásba, nagyon sok csúnya dolgot láttam abban a kódban. Például nagyon sok globális változójuk van, nem használt, csúnyán rendszerezett kód, hatalmas (néha több ezer soros) függvények, stb. Viszont miután megfejtek egy adott részt, vannak benne jó ötletek, azokat adaptálom, és a saját számíze szerint megvalósítom, ha megtetszett.

   
Asylum - Törzstag | 5484 hsz       Online status #208813   2015.12.16 21:47 GMT+1 óra  
Azért ne vidd túlzásba ezt az UE4 majmolást...a globális változók nem thread safe-ek, később nagy szopás lehet belőle.
C++ fordítóval és macival alszom
http://darthasylum.blog.hu/
   
Instalok - Tag | 607 hsz       Online status #208812   2015.12.16 18:57 GMT+1 óra  
Na megint jövök a furcsaságaimmal. Böngészve az UE4 forráskódját, megtetszett ez a moduláris felépítés, viszont van néhány dolog, amit statikusan szeretnék linkelni. És hogy LoadModule() esetén ne keresse a dll-t, így valahogy be kell a managernek regisztrálni, hogy ez a modul bizony egy statikusan linkelt modul.

Erre volt benne egy jó ötlet, készítettek a regisztráló osztályt, ami a konstruktorában meghívja a manager megfelelő függvényét. Röviden valami ilyesmi:
Kód:
template <class M>
class Register
{
    Register() { Manager::Get().RegisterStatic(&Register<M>::InitializeModule);

    M* InitializeModule() { return new M(); }
};

Az adott modul implementációjakor pedig egy makró segítségével készítenek ebből egy static objektumot, ami elvileg beregisztrálná. Ez ugye az adott modul egy cpp file-jába kerül.
Kód:
static Register<MyModule> registerForMyModule;

Na most a problémám itt következik. Lebuildeltem static libként, hozzálinkeltem a másikhoz, viszont ez a változó nem inicializálódik.

Gondolom valahol (valószínűleg linkeléskor) eldobta, mert nem hivatkozik rá senki. Az UE4 kódjában (Runtime/Core/Public/Modules/ModuleManager.h) van is a makróban egy erre hivatkozó rész:
Kód:
// [...]
/** Implement an empty function so that if this module is built as a statically linked lib, */ \
/** static initialization for this lib can be forced by referencing this symbol */ \
void EmptyLinkFunctionForStaticInitialization##ModuleName(){} \
// [...]

Viszont azt nem találom meg, hogy erre ki hivatkozik.

Különösebb build-toolok és automatikus kódgenerálás kifejlesztése nélkül van-e lehetőség valahogy inicializálni azt a változót?

szerk.:
Ok, mágikus módon megjavult, egyetlen linker beállítással a futtatható programon:
Kód:
Use Library Dependency Inputs -> true

Viszont észnél kell lenni, meg kell majd nézni (egyszer), hogy g++al milyen eredmény születik.

szerk. 2:
Ja értem! Azért javult meg, mert ezzel az opcióval nem magát a libet, hanem az objecteket linkeli a programhoz?

szerk. 3:
Igen, megtaláltam, itt egy bejegyzés erről.

Ezt a hozzászólást Instalok módosította (2015.12.16 20:24 GMT+1 óra, ---)

   
Instalok - Tag | 607 hsz       Online status #208687   2015.11.25 11:54 GMT+1 óra  
Lentebbi példához kapcsolódóan:

Véleményem szerint ennek mennie kellene:
Kód:
static_assert(std::is_function<decltype(T::GetType)>::value, "Not a COMPONENT_GROUP");

Viszont abban az esetben is írja a hibaüzenetet, ha a T-nek van GetType függvénye. Azonban, ha kicsit megcsavarom a dolgot, és a címével próbálkozok, akkor megjavul:
Kód:
static_assert(std::is_function<typename std::remove_pointer<decltype(&T::GetType)>::type>::value, "Not a COMPONENT_GROUP");

Ezt a hozzászólást Instalok módosította (2015.11.25 12:13 GMT+1 óra, ---)

   
zeller - Törzstag | 487 hsz       Online status #208684   2015.11.24 09:33 GMT+1 óra  
Viszont az rtti-t perf miatt kikapcsolni oltari hulyeseg. A 90-es evekbol visszamaradt rossz szokas. nem ezen fog mulni a 60 fps, leszamitva azt az esetet, ha mocsokszar compilert hasznalsz.

   
Instalok - Tag | 607 hsz       Online status #208683   2015.11.23 17:54 GMT+1 óra  
Egyébként egy ilyen értéket jelenleg is használok megkülönböztetésre, de eddig eszembe nem jutott volna az, hogy virtuális függvényt használjak.

Jelenleg egyébként egy elég hacky megoldást használok. Van egy define-om, ami definiál egy egyszerű static függvényt, ami visszatér egy 32 bites integerrel, magával a függvény címével.
Kód:
#define COMPONENT_GROUP()\
public:\
    inline static Component::Type GetType() { return reinterpret_cast<Component::Type>(&GetType); }

Ahol a Component::Type egy uint32 define (hogy később akár uint64-re is lecserélhető legyen).

Illetve magát a component hozzáadását egy template függvénnyel csinálom, így könnyen el is tudom tárolni az adott példányhoz tartozó típust is, innentől kezdve pedig működhet a virtual függvényes dolog.

Az enummal meg valóban csak annyi a baj, hogy előre tudni kell, hogy milyen gyerekek lesznek pontosan.

Köszi a hozzászólásokat.

   
Matzi - Szerkesztő | 2526 hsz       Online status #208681   2015.11.23 16:17 GMT+1 óra  
Ez lehet hogy egyszerűbb, de nem jól alkalmazható több lépcsős öröklés esetén, illetve a parentnek előre kell tudnia minden gyerekosztályról. Az én változatomban elvileg bármikor utólag is bővíthető, anélkül, hogy hozzá kellene nyúlni a meglévőkhöz.
Persze, ha csak az egyszerűség számít, akkor az enum is elég, ráadásul nincs benne virtuális függvény, ami spórolhat egy vtable-t.
If your game idea starts with the story it’s not a game idea.
Stories in games are optional.
   
Asylum - Törzstag | 5484 hsz       Online status #208680   2015.11.23 14:19 GMT+1 óra  
Egyszerűbb ha:

Kód:
class ParentClass
{
public:
    enum Types { ChildType1, ChildType2 };

    inline Types GetType () const { return mytype; }

protected:
    ParentClass (Types type) { mytype = type; }

private:
    Types mytype;
};


Az idtech4 ezt egyetlen makróval oldja meg ami minden osztály elején ott van (és nincs beleégetve az enum).
C++ fordítóval és macival alszom
http://darthasylum.blog.hu/
   
Frissebbek | Korábbi postok
[1] [2] > 3 < [4] [5] [6] [7] [8] [9] [10] [15] [20] [25] [30] [35] [40] [45] [50] [55] [60] [65] [70] [75] [80] [85] [90] [95] [100] [105] [110] [115] [120] [125] [130] [135] [140] [142]