• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

GorbGorb

Members
  • Content count

    34
  • Joined

  • Last visited

Community Reputation

112 Neutral

About GorbGorb

  • Rank
    Member
  1. If you really have to optimize your solution, I'd suggest this approach: Organizing memory Use fixed size memory blocks of chars as nodes in your rope. This allows you to pool allocate those blocks, minimizing calls to new and malloc. When you run out of allocated blocks, allocate a bigger buffer. Don't simply memcpy your blocks to the new location but push_back each character in your new structure, filling up each block completely, starting at the beginning of the buffer (thus making the doubly linked list cache friendly again, in case you want to traverse it). Finding insert position For inserting text into the string, I assume you need to know where a line starts. I see multiple solutions for this: a) Store the number of newlines a node contains in the node (and keep that number updated). Iterate over nodes to find the right block.[list] [*]easy to implement [*]low memory usage [*]inserting newlines is O(1) [*]finding newlines is O(n) and needs to touch a lot of memory [/list] b) Maintain a dynamic array of pointers to nodes. The pointer at index [i]n [/i]shall point to the node containing the line with index [i]n[/i][list] [*]higher memory usage [*]inserting newlines is O(n) [*]finding newlines is O(1) [/list] c) Combination of a) and b). Use pointers to find approximate location of your line (for example, pointer [i]n [/i]points to line [i]10 * n[/i]).[list] [*]most difficult to implement [*]otherwise, same characteristics as b) [/list]
  2. [quote name='CDProp' timestamp='1347388042' post='4978988'] Just one more thought, real quick... Another place this dynamic_cast issue comes up in a [i]lot[/i] is with publish/subscribe messaging architectures. Often, you have an abstract interface called Message, and then any time you want to send data from one part of your program to another (where nothing knows at compile time who is communicating with whom), then you just subclass Message (e.g., FooMessage, BarMessage). However, the message handler method on the receiving end will get a Message& and it needs to down-cast that to the right message type before it can deal with it. [/quote] You can automate this with templates (not tested, but the concept works): [CODE] class message_dispatcher { private: struct abstract_listener { void* listener; void (*handle)( void* listener , const void* message ); }; template< class MessageType , class ReceivingType > static void handle_func( void* listener , const void* message ) { ReceivingType& typed_listener = *static_cast< ReceivingType* >( listener ); const MessageType& typed_message = *static_cast< const MessageType* >( message ); typed_listener.handle( typed_message ); } std::multimap< type_info , abstract_listener > listeners; public: template< class MessageType , class ReceivingType > void subscribe( ReceivingType& r ) { abstract_listener al{ &r , &handle_func< MessageType , ReceivingType > }; type_info info = typeid( MessageType ); listeners.insert( { inf , al } ); } template< class MessageType > void dispatch( const MessageType& msg ) { type_info info = typeid( MessageType ); auto range = listeners.equal_range( info ); while( range.first != range.second ) { ( *(range.first->handle_func) )( range.first->listener , &msg ); ++range.first; } } }; struct message_a {}; class specific_listener { public: void handle( message_a& m ) { } }; specific_listener listener; message_dispatcher dispatcher; dispatcher.subscribe< message_a >( listener ); dispatcher.dispatch( message_a() ); [/CODE] Notice, however, that you can't use a message hierarchy. If you dispatch a B : A, a handler that has subscribed for A won't get that message. If you need the performance, you can change std::multimap to something like a hash map and replace type_info with your own ids, e.g. [CODE] template< class T > void* t_id() { static char c; return c; } typedef void* msg_id; msg_id id = t_id< message_a >(); //or if you need to communicate between different dlls struct message_a { static const unsigned int id = //some unique value }; [/CODE]
  3. [CODE] template<class First, class Second> class Either { public: template<class T> Either<First, Second>& operator=(Either<T, Empty> either) { first_ = std::move( either.value() ); hasFirst_ = true; return *this; } template<class T> Either<First, Second>& operator=(Either<Empty, T> either) { second_ = std::move( either.value() ); hasFirst_ = false; return *this; } bool hasFirst() const { return hasFirst_; } bool hasSecond() const { return !hasFirst_; } const First& first() const { return first_; } const Second& second() const { return second_; } private: union { First first_; Second second_; }; bool hasFirst_; }; [/CODE] This will eliminate unnecessary copies. Look at boost::variant, it does something similar.
  4. Hi, I'm learning gles 2 android ndk at the moment, but I can't display a texture. I expect my code to render a black texture on the screen, but all I get is some color garbage. This is my rendering routine: [source lang="cpp"] gl_context::create_context( s ); glViewport( 0 , 0 , gl_context::width() , gl_context::height() ); glClearColor( 0.0f , 0.0f , 0.0f , 0.0f ); GLuint shader_program = 0; GLuint position = 0; GLuint texture_coord = 1; GLuint sampler = 0; const char* vertex_shader_source = "attribute vec4 position; \n" "attribute vec2 a_texture_coord; \n" "varying vec2 v_texture_coord; \n" "void main() \n" "{ \n" " gl_Position = position; \n" " v_texture_coord = a_texture_coord; \n" "} \n"; const char* fragment_shader_source = "precision mediump float; \n" "uniform sampler2D sampler; \n" "varying vec2 v_texture_coord; \n" "void main() \n" "{ \n" " gl_FragColor = texture2D( sampler , v_texture_coord );" //" gl_FragColor = vec4( 1.0 , 0.0 , 0.0 , 1.0 );" //uncommenting this results in a red screen, so I guess I have a valid gles 2 context "} \n"; GLuint vertex_shader = glCreateShader( GL_VERTEX_SHADER ); glShaderSource( vertex_shader , 1 , &vertex_shader_source , 0 ); glCompileShader( vertex_shader ); GLuint fragment_shader = glCreateShader( GL_FRAGMENT_SHADER ); glShaderSource( fragment_shader , 1 , &fragment_shader_source , 0 ); glCompileShader( fragment_shader ); shader_program = glCreateProgram(); glAttachShader( shader_program , vertex_shader ); glAttachShader( shader_program , fragment_shader ); glBindAttribLocation( shader_program , position , "position" ); glBindAttribLocation( shader_program , texture_coord , "a_texture_coord" ); glLinkProgram( shader_program ); glUseProgram( shader_program ); sampler = glGetUniformLocation( shader_program , "sampler" ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D , 0 ) ; std::vector< GLubyte > buffer( 64 * 64 * 3 , 0 ); glTexImage2D( GL_TEXTURE_2D , 0 , GL_RGB , 64 , 64 , 0 , GL_RGB , GL_UNSIGNED_BYTE , buffer.data() ); glUniform1i( sampler , 0 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); const GLfloat vertex_positions[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, }; const GLfloat texture_coords[] = { 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, }; glVertexAttribPointer( position , 2 , GL_FLOAT , GL_FALSE , 0 , vertex_positions ); glEnableVertexAttribArray( position ); glVertexAttribPointer( texture_coord , 2 , GL_FLOAT , GL_FALSE , 0 , texture_coords ); glEnableVertexAttribArray( texture_coord ); glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 ); glDisableVertexAttribArray( position ); glDisableVertexAttribArray( texture_coord ); gl_context::swap_buffers();[/source]
  5. [quote name='Antheus' timestamp='1334009746' post='4929688'] I mentioned JavaScript above:[code]var Enemy = function() { this.velocity = [1.0, 2.0, 3.0]; this.mass = 200.0; systems.install(this); }[/code] [/quote] With some template magic and type erasure this can actually be emulated in c++, for example, I use this: [CODE] prototype p = system_manager.new_prototype(); p.add_component( velocitity{ x , y , z } ); p.add_component( mass{ 200 } ); entity a = system_manager.new_entity( p ); entity b = system_manager.new_entity( p ); [/CODE] which doesn't look that much worse. The idea is to have references to base_system s in your system_manager. During its initialization, you create a map< typeinfo , unsigned int >, where the value type is unsigned int. When adding a component to a prototype (usually while loading a level) you lookup that system_index in the map once and store it with the component. To create an entity from a prototype you simply iterate over all components in it and do [CODE] systems[ system_id ].insert( component ); [/CODE] Maybe I'll refactor my implementation a bit and upload it somewhere, it is, as you said, quite some work to implement a generic component system in c++.
  6. boost::shared_ptr has the same thread-safety as a normal pointer. You're not allowed to do [quote] Thread 1:[font=courier new,courier,monospace] a = null;[/font] Thread 2:[font=courier new,courier,monospace] shared_ptr<T> b = a;[/font] [/quote] with normal pointers either.
  7. [quote name='slayemin' timestamp='1330024635' post='4915953'] -Every time you use a 'new' keyword to allocate memory, automatically create a 'delete' keyword to deallocate it and make sure that the delete is reached. [/quote] Don't use new unless you need a custom data structure or for unique_ptr. Use std::make_shared and std::vector instead (you could also create std::make_unique, I'm sure it'll make it into the standard soon). [CODE] A *a = new A; //use a delete a; [/CODE] is very like not exception safe. Better: [CODE] std::unique_ptr< A > a( new A() ); //use a //std::unique_ptr deletes a [/CODE] You don't leak memory if you use modern c++.
  8. Thanks for the answers so far, confirmed me in my thoughts. [quote name='Hodgman' timestamp='1328833523' post='4911495'] [code]int SystemIndex(u32 handle) { return handle>>24; } int InstanceIndex(u32 handle) { return handle & 0xffffff; } [/code] [/quote] Funny, I thought about the exact same thing right after starting this thread =) For now I will go with 1a) and an unsorted vector. I also thought about creating a lookup table from 1b) only once and using it for querying components after construction, reusing the memory for the next entity creation. Another aspect I want to improve in my design is loading and storing entity prototypes. I want to be able to load entities from files, create a prototype and spawn them later. The prototype class is implemented with type erasure, maybe a little bit like boost::any[] (not with slow built-in rtti though). The problems arise when I have to modify new entities slightly, for example setting position and velocity or changing a flag for this specific entity. Currently, I buffer all spawn requests to ensure my component data structures stay valid while iterating, so I can't just change a certain property right after spawning the entity. The solution I've come up is to pass another prototype object to the spawn function which overwrites standard components if set. This sounds rather over-engineered to me. How is that problem typically solved?
  9. Hi, I'm not sure how to implement an entity system, as described in [url="http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/."]http://t-machine.org...opment-part-1/.[/url] Especially construction, communication between components and managing entity lifetime is giving me a hard time. Here are a few alternatives I thought about: 1) Store indexes to components in the entity object a) in an std::map (or a sorted vector). Since map lookup is slow, I have to store additional references in components that need to access other components very often (for example, the physics component needs fast access to the transform component). memory overhead per component: - in map: 1 int component id , 1 int/ptr for access to specific component - in component: optional fast-access references, optional ptr to entity object b) in an array that is large enough to hold an index for each component type in my entity system. Finding a specific component of an entity is just indexing an array, but entities with few components suffer from a heavy memory overhead. In addition, I get cache misses if I access that lookup table very often. memory overhead per component: - in lookup table: 1 int component id , even for nonexistent components - in component: 1 ptr to component entity object 2) Destroy references to components after construction and keep a reference count in the entity object After construction, each component stores references to other components itself. Afterwards, the reference table or map is destroyed. When processing a component, I have to check wether the entity is still valid or deleted. memory overhead per component: - 1 ptr to reference count - references to all possibly needed components, cannot query a component past construction Currently, I tend towards 1a). I like that it's possible to add or remove components from entities during their entire lifetime, and it probably scales better if I want to add many different components. What are your thoughts?
  10. I believe there is no satisfactory solution for your problem. Your base EventListener has to either now about all message types or all specific listener types. This can be automated via variadic templates, but you'll have to recompile when adding a new listener type or message type.
  11. [quote] [CODE] template<typename EVENT_DATA> virtual void onEvent(Event<EVENT_DATA>* event) { ; } [/CODE] [/quote] Which compiler do you use? Function templates cannot be virtual.
  12. I think std::make_shared allocates the reference count in the same memory block as the object.
  13. This is my implementation of your entity class: [code] template< class Type > void destruct_function( void *obj_mem ) { static_cast< Type* >( obj_mem )->~Type(); } class entity { public: ~entity() { for( auto it = components.begin() ; it != components.end() ; ++it ) ( *it->first )( it->second ); } template< class Type > Type *query() { auto it = components.find( &destruct_function< Type > ); if( it != components.end() ) return static_cast< Type* >( it->second ); else return 0; } private: std::map< void (*)( void * ) , void * > components; }; [/code]
  14. I use this solution: [code] inline unsigned int new_id() { static unsigned int previous_id = 0; ++previous_id; return previous_id; } template< class Type > class id_container { public: const static unsigned int value; }; template< class Type > const unsigned int id_container< Type >::value = new_id(); template< class Type > unsigned int type_id() { return id_container< Type >::value; } [/code] Keep in mind though that this won't work across dll boundaries, and you should make the new_id() function thread safe if you want to use type_id in mutliple threads.
  15. I don't want to comment the idea of having an entity object as I don't claim to have found the Holy Grail, but I think it's unclean to use strings to identify components, especially if all component types are known at compile time. Instead, use type erasure: [code] class entity { private: class base_entity_wrapper { public: std::type_info *id; virtual ~base_entity_wrapper() {} }; template< class Type > class entity_wrapper : public base_entity_wrapper { public: entity_wrapper( Type object ) : obj( std::move( object ) ) , id( &typeid( Type ) ) {} Type obj; }; std::vector< base_entity_wrapper* > components; //use a smart pointers instead public: template< class Type > void add_component( Type object ) { components.push_back( new entity_wrapper< Type >( std::move( object ) ) ); //currently not exception safe, use std::unique_ptr } template< class Type > Type *get() { for( auto it = components.begin() ; it != components.end() ; ++it ) { if( *(**it).id == typeid( Type ) ) return static_cast< component_wrapper< Type >* >( *it )->obj; } return 0; } }; //using: e.add_component( CA() ); e.get< CA >(); [/code] You can increase performance drastically by using a handcrafted typeid, but I'm not sure whether posting one is worth the time.