Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

371 Neutral

About buggypixels

  • Rank
  1. It is interesting to see that most frameworks will force you to use a pattern that you should clearly avoid. We all have learned that having something like GameObjects and call an update method in every object is bad due to cache misses and so on. This is the gap that actually ECS tries to eliminate. So in general it is bad practice to do it like Cocos2d. On the other hand how would you do it when you are such a framework designer? This is the only currently somehow accepted solution. Since there still is no common vision how a ECS should be designed and there are many different solutions out there it is safe to fall back to such an approach. But still it is bad design.
  2. The basic idea of supporting events in a game engine is nice. Actually it is a simple way of decoupling different systems. Somehow it seems that providing a gobal event manager is a common approach.  I strongly disagree here and here is a perfect explanation why: http://bitsquid.blogspot.de/2009/12/events.html I really like the idea and in my games all that is left of my previous event system is just an event stream buffer. Now a subsystem can write to its own event buffer stream and a higher level system may ask for the stream and process it. IMHO it makes everything so much easier and predictable.
  3. I have recently reworked by event system completely and it now looks totally different. First of all I did the same design flaw that you can find in many solutions. There is something like void fireEvent(EventData* evn) { foreach ( Listener l : listeners ) { onEvent(evn); } } First using a raw pointer here is awfull. But the major problem is that every event will be processed immediately when they are fired. This leads to unpredictable circumstances in your code. You actually never know WHEN an event will be fired and therefore you cannot know the states of your objects. So what I did was to buffer the events and then at a certain point in my engine (right after the big update loop) I process ALL events and send them to the listeners. Also in my opinion using a base class for an event is awfull. An event contains only data. You are just sending plain data around. So I removed this completely and just using structs. This makes the code much leaner and cleaner. The entire solution now looks completely different. I got the idea after reading this: http://bitsquid.blogspot.com/2011/02/managing-decoupling-part-2-polling.html It took me quite a while to finally get it and then it just hit me how awfully right the author is. Actually I now have a buffer where I store the events like: [header1][event data][header2][event data2] The header is a simple struct: struct Header { uint32 index; uint32 id; size_t size; }; The ID is the actual ID of the event and the size is the size of the event data struct. The index is the actual index in my buffer. The entire buffer is sent to any listener and the listener can grab any data he likes from the buffer like: size_t get(void* p, size_t size,uint32 index); Example: Here is the event data when the ship is hit by a projectile: struct ShipHit { Vec2 pos; int damage; int rocketType; } Now I fire the event: ShipHit sh; sh.pos = Vec2(100,100); sh.rocketType = 1; sh.damage = 100; evnetManager->fireEvent(100,&sh,sizeof(sh); In the listener I do something like: // check if we have a ship hit event in the buffer if ( buffer.containsID(100) ) { // yes so grab the data ShipHit sh; buffer.get(100,&sh,sizeof(sh)); } I hope I could actually shed some light on my approach. It is actually not easy and I am not sure I could get the point across. Just ask if you have any questions.
  4. You might take a look here: http://gamesfromwithin.com/managing-data-relationships. Since your example is about resource management this might fit perfectly. Overall using strings and std::map is not the best solution here. If you still need to support strings (better to say to support name lookups) you can easily extend the system described above to include a name/handler mapping.
  5. buggypixels

    DX9: Generic VertexBuffer using template

    You are right. Right now I only need 16-bit indices in my engine. But it should be straight forward to use the index type as second template type. My next step is to support subsets within the vertex buffer. Basically the same as you have when using the IDXMesh object. So I can activate or deactivate certain subsets and do not take care of rendering any particular subset individually. Someone might argue that I could use the said IDXMesh. But hey, I am doing it for the fun of it. As you can see that actual part of setting textures/shaders/materials are not part of the vertex buffer since the engine during the render stages takes care of this already. So probably this is not as generic as it could be. I just wanted to share the idea of using a template here.
  6. buggypixels

    DX9: Generic VertexBuffer using template

    I have posted the code along with some short explanations at my webset buggypixels.com Hope you find it interesting.
  7. buggypixels

    DX9: Generic VertexBuffer using template

    The solution was quite easy. Instead of using vector I am not using an array. It is also much easier to copy the data to memory. Now I have a nice vertex and index buffer that can use any kind of vertex data. If anyone is interested I can post the code.
  8. Hi everyone, I am trying to build a generic vertexbuffer. Generic means that I could use any kind of Vertex along a VertexDeclaration. So far I have a working version which is posted below. The problem is the way how I copy the data to the vertex buffer. First I get a warning from the compiler. Here is the snippet: template<class T> void DynamicVertexBuffer<T>::update() { int total = m_Vertices.size(); if ( total > 0 ) { T* pVertices; HR(vertexBuffer->Lock( 0, 0, ( void** )&pVertices, 0 )); for ( size_t i = 0; i < total; ++i ) { m_Vertices->set(pVertices); pVertices++; } HR(vertexBuffer->Unlock()); } m_numVertices = total; } Basically I want the vertex buffer to have a list/vector of vertices and the update method will copy the vertices to the buffer. The warning is about this line: T* pVertices; Also I do not like the way how I currently handle the building of the pointer: m_Vertices->set(pVertices); But that was the only solution I could come up with that is working. When you search around the internet you can find a huge list of examples but they all take a slightly different approach. For example Chad Vernon uses a method like this in his generic vertex buffer: BOOL SetData( UINT numVertices, void *pVertices, DWORD flags = D3DLOCK_DISCARD ); So in his code the vertex buffer is not storing the data (which I would prefer). Also he uses arrays and memcopy to build the actual vertex buffer. I would still prefer the vector/list approach. Now here are my questions: I am on the wrong trackCan somebody give me a hint about the compiler warningDoes someone has a better ideaShould I drop my stuff and simply take the same approach as all the others Any feedback would be great. Here is the entire code: #pragma once #include "..\dxstdafx.h" #include "IndexBuffer.h" #include <vector> namespace ds { template <class T> class DynamicVertexBuffer { typedef std::vector<T*> Vertices; public: DynamicVertexBuffer(D3DPRIMITIVETYPE primitiveType,IDirect3DVertexDeclaration9* vertexDeclaration,const int& vertexSize,const int& maxVertices); ~DynamicVertexBuffer(); void addVertex(T* v); void clear(); void update(); void preRendering(); void render(int numPrimitives); void postRendering(); private: Vertices m_Vertices; int m_MaxVertices; IDirect3DVertexDeclaration9* m_VertexDeclaration; LPDIRECT3DVERTEXBUFFER9 vertexBuffer; IndexBuffer* indexBuffer; UINT m_numVertices; int m_vertexSize; D3DPRIMITIVETYPE m_primitiveType; }; template<class T> DynamicVertexBuffer<T>::DynamicVertexBuffer(D3DPRIMITIVETYPE primitiveType,IDirect3DVertexDeclaration9* vertexDeclaration,const int& vertexSize,const int& maxVertices) : m_VertexDeclaration(vertexDeclaration) , m_vertexSize(vertexSize) , m_primitiveType(primitiveType) , m_MaxVertices(maxVertices) { IDirect3DDevice9 * pDevice = gEngine->getDevice(); D3DPOOL pool = D3DPOOL_DEFAULT; DWORD usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC; LOG(logINFO) << "creating new dynamic vertext buffer - size: " << m_MaxVertices; HR(pDevice->CreateVertexBuffer( m_MaxVertices * vertexSize,usage,0 ,pool, &vertexBuffer, NULL )); indexBuffer = 0; } template<class T> DynamicVertexBuffer<T>::~DynamicVertexBuffer() { if( vertexBuffer ) { vertexBuffer->Release(); vertexBuffer = NULL; } } template<class T> void DynamicVertexBuffer<T>::addVertex(T* v) { m_Vertices.push_back(v); } template<class T> void DynamicVertexBuffer<T>::clear() { for ( size_t i = 0 ; i < m_Vertices.size(); ++i ) { delete m_Vertices; } m_Vertices.clear(); } template<class T> void DynamicVertexBuffer<T>::update() { int total = m_Vertices.size(); if ( total > 0 ) { T* pVertices; HR(vertexBuffer->Lock( 0, 0, ( void** )&pVertices, 0 )); for ( size_t i = 0; i < total; ++i ) { m_Vertices->set(pVertices); pVertices++; } HR(vertexBuffer->Unlock()); } m_numVertices = total; } template<class T> void DynamicVertexBuffer<T>::preRendering() { if ( m_numVertices > 0 ) { IDirect3DDevice9 * pDevice = gEngine->getDevice(); update(); if ( indexBuffer != 0 ) { indexBuffer->init(); } pDevice->SetStreamSource( 0, vertexBuffer, 0, m_vertexSize ); pDevice->SetVertexDeclaration(m_VertexDeclaration); } } template<class T> void DynamicVertexBuffer<T>::render(int numPrimitives) { if ( m_numVertices > 0 ) { IDirect3DDevice9 * pDevice = gEngine->getDevice(); if ( indexBuffer ) { HR(pDevice->SetIndices( indexBuffer->getIndexBuffer() )); HR(pDevice->DrawIndexedPrimitive( m_primitiveType, 0, 0, m_numVertices, 0, numPrimitives )); gEngine->getDrawCounter()->addIndices(indexBuffer->getSize()); gEngine->getDrawCounter()->addPrimitives(m_numVertices); } else { HR(pDevice->DrawPrimitive(m_primitiveType,0,numPrimitives)); gEngine->getDrawCounter()->addPrimitives(m_numVertices); } } } template<class T> void DynamicVertexBuffer<T>::postRendering() { } };
  9. buggypixels

    [DX9 C++] Picking triangles

    This is working fine now. But there is one little problem left. Actually the user can rotate the big cube around the y-axis. Once the big cube has been rotated the picking fails. It just picks up the small cubes at their original location. Do I have to rotate the picking ray as well? Or do I have to start the calculation of the picking ray with a different origin? I am a bit lost here.
  10. buggypixels

    [DX9 C++] Picking triangles

    I was thinking along the line. But it is always better to get some support. Tonight I will try out your suggestion.
  11. Hi there, I have a probably slightly simple problem. Basically I have about 400 cubes. These cubes are all in one vertex buffer along with the indices in an index buffer. These 400 cubes are building one big cube. The user can actually rotate the big cube. That is working smoothly. But now I want to select any of these cubes with my mouse. So far I have understood that I need to calcuate a ray tracing from the mouse position in screenspace. Of course convert this ray into world space. This is not a problem. But how do I check which of my cubes was selected? I know the position of the cube. So I can also calculate each index in the vertex and index buffer to get the 24 vertices and 36 indices I have for each cube. Of course I could use the indices to get the vertices belonging to one triangle. But how to continue?
  12. buggypixels

    do you guys use Hungarian notation?

    There actually was a time when hungarian notation made sense. It was way back in ancient times of C. The basic idea is that you can look at the name of the variable and see what kind of type it is. Since in C you have to define the variable at the beginning. But as the variable might be used a few pages futher down you still would be able to see that iCounter is supposed to be an int variable. This is now all obsolete since you have nice IDEs. You can hoover over the varible and will get a nice popup showing the details. Also in C++ you can define the variable where you actually need it. I am developing software for 25 years now and this is definitely something that has died the deserved death.
  13. buggypixels

    DirectX Breakout game problem

    When the ball hits the wall you should: - change velocity - move the ball directly into the new direction ball.x += ball.velx * dt; ball.y += ball.vely * dt; if (ball.x &lt; 0 || ball.x &gt; SCREENW - ball.width) { ball.velx *= -1; ball.x += ball.velx * dt; } if (ball.y &lt; 0) { ball.vely *= -1; ball.y += ball.vely * dt; }
  14. buggypixels

    #include trouble

    Header files can be troublesome. I have found a nice resource which explained the best practice but lost the URL. So let me try to explain it. The best way is always to use forward declaration where possible and only use include when necessary. Let us look at an example: class MyClass : public BaseClass { public: Entity* getEntity(); }; Here you need to include BaseClass. The compiler and preprocessor needs to know the size and so on of your BaseClass. But for the Entity just use forward declaration. It is only a pointer so a forward declaration is perfectly fine. Include the actual header file in your cpp file. So the example looks like #include "BaseClass.h" class Entity; class MyClass : public BaseClass { public: Entity* getEntity(); }; This works nice and can help you especially when you have these cyclic dependencies. This is how I learned it and it works fine for me. If I am wrong hopefully someone will explain it.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!