I'm designing a component-based system and everything works well, but a critical feature is missing and that is to be able to obtain a type of component from within a class of type Object, whereof this class can be added/removed components. In the Object class there exists a vector of components thus:
vector<Component*> pComponents;
And in the Component class, a Component has to have a name. So, a component such as Drawable would be called like so:
pPlayer->addComponent(new Drawable("Drawable"));
And that's all that's required for the player to be drawable. Now this is the problem: when it comes to adding loads of components that rely on other components, is there a settlement in how components communicate with one another?
Currently, in my Game class (which is not of type Object, although I might have it derive from Object albeit not sure if that's a good design decision) I have this code in the update function:
void Game::update()
{
pPlayer->update(0);
pSpriteLoader->getSprite()->move(pPlayer->getVelocity());
}
I'm using SFML2 solely because it's easy to use for the 2D graphics. The player update function calls the components' respective update functions. And the sprite loader is also a component and it is in charge of handling the loading of sprites through textures/images that can be read from file or memory. If I were to omit this line of code then the sprite would not be able to appear moving on the screen. As you can see, it's odd that pPlayer has a getVelocity() function and it's because I haven't moved all the physics stuff into its own component. What is dreading is that once I have moved the physics stuff out of the Player class into a Physical component class, how can I get these components to communicate with each other without having to resort to the lines of code ascribed above?
My solution is to create a component manager which registers each component and any component that requires another component will have to consult with this component manager without having to do so directly. Would this be a viable solution, and how can I proceed with the logic of such a component manager then?
Well, I suppose you would start by designing a messaging system.
It appears that you want to heavily decouple code and create components as much as possible. This is fine, I suppose, but the answer to having dependencies without coupling is probably something among the lines of message passing.
Say you need an Achievement system. This is a perfect example of a system that needs to stick its hand into as many nooks and crannies as possible in order to allow for the greatest flexibility in designing achievements. But how would you be able to stick your hand into, say, the Physics, AI, and Input system all at the same time and not write spaghetti code? The answer would be to put listeners on event queues and then run them by certain criteria based on the contents of the messages.
So for each component, you might want to inherit a common message sending/receiving component, possibly with generics, in order to send data messages. For example, say you shoot a laser in a FPS game. The laser will most likely make a sound, and the laser will most likely need an animation. You will probably want to send a message to the sound system to play a certain sound, and then send a message to the physics system or such to simulate the effects of the laser.
If you're interested, I have a really, really crude library for modeling a event system based on queues, listeners, and generic messages here: https://github.com/VermillionAzure/Flexiglass You might get some insight from fellow newbie code.
I really suggest taking a look at Boost.Signals2 or Boost.Asio as well. Knowledge of signals/networking can often help when designing communication systems, even if the system is just between game components.
I've recently been working on an entity-component system in SFML and came across the same problem.
Instead of creating some sort of messaging system that allows components to communicate with each other I ended up adding 'System' objects to the mix instead. This is another popular method that is often used when implementing component systems and it's the most flexible one that I've used so far.
Entities are nothing more than collections of components
Components are POD structs and have no methods (e.g. a PositionComponent would have nothing more than X and Y values)
Systems update any entities that have the required components
For example, my 'MovementSystem' iterates through each of my entities and checks if they have a VelocityComponent and an InputComponent. If it does, it changes the velocity of the current entity according to the current key being pressed.
This removes the issue with components communicating with each other because now all you need to do is access/modify the data stored in the current entity's components.
There are a few different ways that you can work out whether or not the current entity has the required components - I'm using bitmasks. If you decide to do the same, I highly suggest you take a look at this post for a more thorough explanation of the method: https://gamedev.stackexchange.com/questions/31473/role-of-systems-in-entity-systems-architecture
Related
My end goal is to make a VRidge lightweight clone to understand the OpenVR API, but I'm struggling to understand how to get my code to display something. As a starting point, instead of my phone, I want to create a window as the HMD (SFML, SDL, you name it...) and having SteamVR rendering the VR view in it.
I understand that an object implementing IServerTrackedDeviceProvider is the handler of my driver's devices, ITrackedDeviceServerDriver is the interface of the device itself, and I suspect that my "HMD" device will have to implement IVRDisplayComponent.
Aside from setting some properties and having callbacks to activate and deactivate my device, I have no clue where to get an actual frame to display on the screen. What am I missing ?
You are almost right.
A class inheriting vr::IServerTrackedDeviceProvider(I'll call it the device parent later on) is responsible for registering and maintaining the lifetime of your devices(creating them, registering them, etc.)
Classes inheriting vr::ITrackedDeviceServerDriver after they have been registered by a device parent are considered a tracked device, device type is set by the device parent on register, also in case of the HMD device GetComponent() method needs to return display components if requested, for other devices it can just return NULL
GetComponent() receives a c string with a component name and version, for example "IVRDisplayComponent_002" stored in vr::IVRDisplayComponent_Version, and if the device has a component with a matching name version pair you need to return a pointer to it, if no match is found return NULL
Also about components, in the driver example that Valve provides its done in a very lazy and bad way, DO NOT INHERIT COMPONENTS TO YOUR DEVICE CLASSES
Segment your components into separate objects that you initialize in your device and return them in GetComponent() accordingly
Now, the only thing left for your devices to be properly identified and used by SteamVR is registering them, but there is a catch, you need to specify the device type when you register it by passing one of the values from vr::ETrackedDeviceClass enum(these should be pretty self explanatory when you look at the enum)
This is not all there is to openvr driver of course, for it all to work and for SteamVR to even acknowledge your driver's existence you need to implement an HmdDriverFactory() function, its similarly to GetComponent() except you compare the input c string to a provider name version pair and in case of a device parent its vr::IServerTrackedDeviceProvider_Version, if you get a match return a pointer to the instance of your device parent or any other provider you implemented
A few notes:
HMD needs at least one display component
HMD device is very sensitive to how you submit poses to it(dont ask why, it just is)
Be prepared for the lack of documentation, the best docs that you're gonna get are code comments in openvr_driver.h, ValveSoftware/openvr issue tracker and other people working with openvr drivers (even though there are only few...)
This is not the best explanation of how openvr drivers work, so you're always welcomed to ask for more details in the comments
What is the relationship between SDL_Joystick and SDL_GameController? These are the only things I know of right now:
SDL_GameController and related functions are all part of a new API introduced in SDL2.
SDL_GameController and related functions are built on top of the existing SDL_Joystick API.
(Working Draft) You can obtain an instance of SDL_Joystick by calling on the function SDL_GameControllerGetJoystick() and passing in an instance of SDL_GameController.
(Working Draft) You can obtain an instance of SDL_GameController first by calling on SDL_JoystickInstanceID() and passing in an instance of SDL_Joystick, then pass in the SDL_JoystickID to SDL_GameControllerFromInstanceID.
Even though SDL_Joystick and SDL_GameController are both interchangeable, it seems like SDL_GameController is here to replace and slowly succeed the SDL_Joystick.
Reason is, when polling for SDL_Event, the SDL_Event instance contains both the SDL_Event::jbutton and SDL_Event::cbutton structs, representing the SDL_Joystick buttons and SDL_GameController buttons, respectively. I guess I can use either one, or both, button events for the player controls.
I could be wrong here.
I would like to ask:
What are the differences between SDL_Joystick and SDL_GameController?
Is SDL_Joystick now referring to this controller?
And the same for SDL_GameController?
What are the advantages/disadvantages of using SDL_Joystick over SDL_GameController (and vice versa)?
First of all, SDL game controllers are the extension of SDL joystics (for the scope of this answer when I say "controller" or "joystick" I mean SDL's implementation, not hardware device category in general). As wiki says,
This category contains functions for handling game controllers and for
mapping joysticks to game controller semantics. This is built on top
of the existing joystick API.
If you are running your game from Steam, the game controller mapping
is automatically provided for your game.
Internally SDL uses joystic events and processes them to produce game controller events according to controller mapping. Hence one may say that joystic is lower level thing while game controller is a generalisation upon joysticks to produce more predictable/compatible (but more constrained) for games that wants gamepad-like input devices.
With game controller, you can program input for just one xbox-like controller thing, and SDL will make user's controller compatible with that (sometimes with the user's help - there are way too many different controllers, we can't possibly expect SDL to have configurations for all of them). Of course if controller is very different (or not controller at all - e.g. fly simpulation sticks, wheels, etc.), that would be problemmatic.
Basically game controller provides xbox-like buttons and axes for user side, freeing application developer from the need to support controller remapping - as remapping is done in SDL itself. For some popular controllers SDL already have builtin mappings, and for others user-defined mapping can be loaded via environment variable.
There is also a configuration tool that simplifies remapping for end user, including exporting resulting configuration to said environment variable. Steam also have builtin configuration tool, which configuration it (supposedly - I've never used that) exports to SDL - essentially making users themselves responsible for configuring their controllers.
I need to do some basic networking for a Pygame project.
Basically, it's a 2D single player or cooperative game. The networking only needs to support two players, with one as a host.
The only information that needs to be sent is the positions of players, creeps and bullets.
I've been reading around and Twisted keeps coming up, but I haven't done networking before, and I'm not sure if that might be an overkill.
So, is it possible for a relative newbie to implement networking in Pygame?
This was asked recently on Reddit, so I'll more or less just copy my answer over from there. I apologize for not being able to provide more links, I have <10 rep so I can only post two at a time.
Twisted might work, but I don't have a whole lot of experience with it. I'd recommend going with sockets, as that's what Twisted uses in the background anyway. Beej's guide (google it) is pretty much the Holy Bible of sockets if you want to learn how they work (in C++, but the concepts extend everywhere). Python does abstract some of the complexity away, but it's still a good idea to know what's going on in the background.
For Python specific sockets, you can go ahead and just use the howto (user745294 posted a link above). Here's a nice article titled "What every programmer needs to know about Game Networking". It goes into the different types of major networking styles (client-server, p2p, udp v. tcp, etc.) and the history behind what some major games used for their networking.
Below is a link to a demo I did on making a networked "game" in Python 2.6/Pygame. It's not actually a game, but each client you create connects to the server and controls a character. You can move your character with the arrow keys and the character will move on all connected clients. I tried commenting the source code with some indication of what I'm sending back and forth, but you may need a little knowledge about sockets to understand it.
The source code is provided in the codepad links in the comment below this post. You will need to provide two images in the same directory as the scripts:
bg.png is the background sprite. It should be an image 400px wide and 300px tall (this can be changed in the GameClient class if needed)
sprite.png is the player character. It should be smaller than the background so that you can see it moving around.
You can use Twisted for networking with Pygame. The "game" project on Launchpad has some examples of how one might integrate the main loops together; basically, use twisted.internet.task.LoopingCall to draw Pygame frames and handle input, while letting the Twisted reactor of your choice run normally.
Since you are already using Pygame, I think this light networking library made for Pygame will do what you need and teach you, but not overwhelm you.
"Mastermind Networking Lib" via pygame.org
There is Pyro (Python remote objects) as another solution for networking in Python.
http://irmen.home.xs4all.nl/pyro/
Using raw sockets is low-level and full of danger. As said before, Twisted is complex and takes to time get up and running. To save yourself some headaches I'd try something like zerorpc.
You need the following solutions:
discovering other player(s) on the (local) network, you don't want player to enter some IP address
handle network errors
serialize messages containing your data (positions, player name, etc.)
handle threading as networking is asynchronous I/O
Above should still be called 'basic', you should really use some fancy networking library with idiomatic API.
Essentially you need to expose the network service (in its own thread) that will push messages to Python's Queue, and then access this same queue from your Pygame code, and if there is a message then you update whatever structures you use to store player's position and draw it on screen.
You shouldn't send stuff like bullet positions over the network as they can be easily (and faster) calculated locally. You just send an event like bullet_shot over the network with a source position and velocity vector.
I need to do some basic networking for a Pygame project.
Basically, it's a 2D single player or cooperative game. The networking only needs to support two players, with one as a host.
The only information that needs to be sent is the positions of players, creeps and bullets.
I've been reading around and Twisted keeps coming up, but I haven't done networking before, and I'm not sure if that might be an overkill.
So, is it possible for a relative newbie to implement networking in Pygame?
This was asked recently on Reddit, so I'll more or less just copy my answer over from there. I apologize for not being able to provide more links, I have <10 rep so I can only post two at a time.
Twisted might work, but I don't have a whole lot of experience with it. I'd recommend going with sockets, as that's what Twisted uses in the background anyway. Beej's guide (google it) is pretty much the Holy Bible of sockets if you want to learn how they work (in C++, but the concepts extend everywhere). Python does abstract some of the complexity away, but it's still a good idea to know what's going on in the background.
For Python specific sockets, you can go ahead and just use the howto (user745294 posted a link above). Here's a nice article titled "What every programmer needs to know about Game Networking". It goes into the different types of major networking styles (client-server, p2p, udp v. tcp, etc.) and the history behind what some major games used for their networking.
Below is a link to a demo I did on making a networked "game" in Python 2.6/Pygame. It's not actually a game, but each client you create connects to the server and controls a character. You can move your character with the arrow keys and the character will move on all connected clients. I tried commenting the source code with some indication of what I'm sending back and forth, but you may need a little knowledge about sockets to understand it.
The source code is provided in the codepad links in the comment below this post. You will need to provide two images in the same directory as the scripts:
bg.png is the background sprite. It should be an image 400px wide and 300px tall (this can be changed in the GameClient class if needed)
sprite.png is the player character. It should be smaller than the background so that you can see it moving around.
You can use Twisted for networking with Pygame. The "game" project on Launchpad has some examples of how one might integrate the main loops together; basically, use twisted.internet.task.LoopingCall to draw Pygame frames and handle input, while letting the Twisted reactor of your choice run normally.
Since you are already using Pygame, I think this light networking library made for Pygame will do what you need and teach you, but not overwhelm you.
"Mastermind Networking Lib" via pygame.org
There is Pyro (Python remote objects) as another solution for networking in Python.
http://irmen.home.xs4all.nl/pyro/
Using raw sockets is low-level and full of danger. As said before, Twisted is complex and takes to time get up and running. To save yourself some headaches I'd try something like zerorpc.
You need the following solutions:
discovering other player(s) on the (local) network, you don't want player to enter some IP address
handle network errors
serialize messages containing your data (positions, player name, etc.)
handle threading as networking is asynchronous I/O
Above should still be called 'basic', you should really use some fancy networking library with idiomatic API.
Essentially you need to expose the network service (in its own thread) that will push messages to Python's Queue, and then access this same queue from your Pygame code, and if there is a message then you update whatever structures you use to store player's position and draw it on screen.
You shouldn't send stuff like bullet positions over the network as they can be easily (and faster) calculated locally. You just send an event like bullet_shot over the network with a source position and velocity vector.
I'm trying to code up an interface to a basic ECG device. I need the form to setup the device, send the 'record' message and save the ECG data that comes back into a file (as well as report a bit on the screen). The hardware device gets sent commands, and returns data via a serial interface.
My question is about the most appropriate class structures to set up.
Option 1:
MainWindow instantiates a
Hardware Device Object that reads the ECG info realtime, creates an 'ECG File class object' and handles it all internally to the Device object.
When recording is finished, MainWindow deletes the Device object and we're done.
Option 2:
MainWindow instantiates the
Hardware Device Object that receives a whole lot of data, maintains that data as a publically accessible data structure (member) then
MainWindow would then refer to that Device Object data structure, instantiate the ECG File class object itself and write it out to a file.
Ideally I'd like to write the data out in different formats (eg. classes that specify the format?)
Sorry if the question's not that clear, I guess I'm asking whether it's appropriate for a hardware device object to also manage all its own data, or pass it back for the main window to then process itself.
I've had a go at option 1, but it's getting ugly and I'm not sure whether I've mis-designed the thing from the start.
Any/all views appreciated!
Pete
Not knowing too much about the Domain, I have designed several systems that uses devices. I have also seem some design for devices. There are many ways to design this kind of stuff, but i like to write wrappers for all devices and use an open, close, read, and write interface.
So essentially, an abstract class is created called Device. Specific devices can be designed to extend this base class. Then a builder class is created to create and initialize the specific class. From this basic class a system can be built to handle it's out input and output. I tend to design to interfaces and keep classes as simple as possible.