Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Orzo posted:

Can you give an example of this? Maybe I'm not understanding your system correctly, but why would an entity need knowledge about it's controller? I would think you'd design an API around the commands an entity can receive regardless of where they're coming from.
I had thought about doing something like that as part of my big ramble. But the impression I had gotten was if an entity "supports" a subsystem, then it implements some interface for it. I am supposing that things like control and AI could technically just implement the same interface. If that's the case I'm trying to figure out what decides when and where how to turn on/off different subsystems sending stuff through the interface.

I think an good example of this is something like an action RPG where playable characters cross a trigger point that starts a small dramatization. At that point the computer is moving stuff around for the player and the controllers shouldn't be moving the characters anymore. Then when that's done they can take back control. Alternately, I was thinking if there is 1 person and 2 characters, maybe they'd want to switch between them. That would mean switching between manual control and an AI for both of them.

Adbot
ADBOT LOVES YOU

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Gerblyn posted:

I made a post about a possible solution for this a few pages back:

http://forums.somethingawful.com/showthread.php?threadid=2692947&pagenumber=84&perpage=40#post390228673

Where characters are controlled by sending them messages. The character's themselves don't need to know where the messages are coming from, allowing a higher level system like a cutscene manager or a player controller decide what gets to route which messages to which characters.
Basically a command pattern? I'll end up giving something like this a go. It was one of the things on the table anyways. It's been two days since I really had my face glued to the code so I've had enough time to step back and not freak out about anything so much.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I've got more conceptual problems with component-based design, based on an accumulation of factors. My issue now is with information sharing for an AI subsystem. I want the AI to take care of an entity for me to have it approach the player and start attacking it. The big question in a design situation for me is how the AI should figure out who the players are and where the players are. Some approaches that aren't incompatible:

1. Just tell the AI sub system up front into hard-coded slots. This is what I'm doing right now while I figure out what the hell I'm doing. I can smash away on a lot of stuff and refactor it later. So I'm not entirely stuck or anything.
2. Some sort of "faction" system with entities so that entities of incompatible factions naturally try to duke it out. But then my entities would have to have some awareness of this. I guess that could be a required interface method when registering with AI.
3. Maintaining a list of all entities and scanning against that. Something like faction information would have to be a part of that so that each entity knows how to respond. Generally the search system on that scares me. It also sounds a lot like putting too much on entities, to the point of tempting to subclass them.

Anyways I have something at hand right now while I settle on something but I wanted again to vet my problems with people more experienced with this whole setup.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Internet Janitor posted:

Then have some of your entities implement it. When you're figuring out what belongs to a given team, use your equivalent of instanceof to identify 'factional' entities.
Actually maybe I'll latch on to that for a moment, and maybe it's a question for the C++ thread. They make a huge fuss over casting in C++. There is a way to determine the types of stuff dynamically, but it requires an extra compilation option and "performance will go down." I haven't seen it quantified so I wondered the type name stuff in C++ really is a burden. It has hampered my thinking when trying to resolve some of this stuff.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I reread a lot of stuff about component based designs and realized I really wasn't getting it right at all. I'm still doing a bunch of stuff with interfaces and I think that's probably staving off the inevitable. Already I get into the uglies with switching between human and AI control. It's embarrassing to me because I've been doing a lot more design kind of stuff in my day job, yet I couldn't wrap my head around the general idea of it all. I suppose the big problem is in assuming there's a lot of OOP involved in it at all. From what I can tell, a lot of component-based development could probably be done with C structs.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Something for the game engine types: How do you pass information back and forth across game objects? In all the stuff I gobbled up on component-based design lately, I saw there isn't really a consensus there. It's kind of interesting really to see what some people come up with. I've seen three things pretty often so far:

1. Subsystems and things that care about particular objects poll over them each frame and update game state. This appears initially repulsive to me but I imagine it works fine for smaller games, and since it's so simple I imagine it works fine for rapidly making little games.
2. Using event callbacks in some kind of way. I've naturally stumbled into this kind of came in my own thing. It means having to register to receive callbacks for anything that can send them. It's similar enough to GUI stuff that I'm used to it.
3. Some kind of message bus where message packets are transmitted and received by those that might care. I have the least detail on this and I'm the most interested in understanding it for general software design's sake; it might be something I might use in non-game stuff.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Shalinor posted:

...
For the message registration itself, you typically want a base message class and then a child class per message type, whether hand-constructed or built out from message defs in a neato precompiler step, with each handler being trusted in some way to upcast properly.
...
From a development point of view, have you found it particularly superior to doing event callbacks? I saw mention of targeting things, or targeting things in a range. I imagine the same could be done with callbacks.

The most evil setup I saw was basically from, to, some type identifer, and a void*. More generally I see people using strings to describe their messages. I have some aversion to using strings like that because of people screwing up the spelling on something. You'd likely only catch it at runtime.

quote:

EDIT: And you will probably need a concept of messages sent to the interfaces themselves vs messages sent to other objects, but depending, that distinction may not need to be enforced particularly hard in code. You may also want to consider object messages being handleable by more than one component type, in which case you end up with a separate messaging interface that routes messages to all components on an object, instead of only specific components that registered. You can do this with messages "owned" by specific interfaces, so long as you use a callback system and no assumptions are made about what components are registering for handling.
Something I haven't figured out yet is how compatible Python and C++ can be with each other when it comes to this kind of thing. I'm probably going to end up doodling most of my code in Python, with the big iron stuff in C++. However, it could be C++ or Python at either side of the transaction, and what I can do that would probably determine the details anyways.

PDP-11 posted:

coupled with a list of active messages held in some widely visible GameManager style object. On each timer tick the GameManager goes down the list, subtracts the frametime from each Message's DelayTime field and calls Execute on Messages where the DelayTime is less than or equal to zero. Any object references are packed into the concrete implementations of Message at instantiation.
This is pretty neat. It looks like you have your timer built into your messaging system.

I think my big problem is some design paralysis from writing in C++. There's nothing really stopping me from trying anything out in particular, other than the fact that the little C++ monkey on my back yells that it's inefficient. But I'd gleefully try it in most any JIT or interpreted language.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

HiriseSoftware posted:

http://cmpmedia.vo.llnwd.net/o1/vault/gdccanada09/slides/marcinchadyGDCCanada.ppt - Gives an overview on the system used in the game "Prototype" by one of the developers.
So would you say then that a component exposes no methods, just something to handle messages to/from it? I think that's what is going on in the slides. I'm letting that kind of set into my head, because it's kind of like history repeating in the whole component-based design stuff. I couldn't really grok having an entity object that is just stuffed with things to make it into whatever it needs to be. It basically throws away the whole inheritance side of OOP. Using messages basically throws away the idea of methods too for all the game logic stuff.

I think I do owe it to myself to understand Qt's signaling system because it's coming up more often.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

HiriseSoftware posted:

Pretty much, yeah. Like 1337JiveTurkey says, you don't have all entities with the same game logic "blowUp" method whether they blow up or not. An entity component knows to respond to a certain message, so when you attach that component to an entity, you can send the MESSAGE_BLOWUP message without having to worry about if in fact that entity DOES "blow up".
Since you guys seem to have used it a lot, generally how clean or messy does it tend to get in the component itself versus having methods and callbacks?

I'm also falling for premature optimization here. I think I've seen a few variations of this posted online. I guess the gist of it is that you send a message to whoever manages the components for the entity (the entity itself or some entity manager) and that just passes it to each component. The component decides what to do with it. Do components tend to get spurious messages?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Physical posted:

I emailed notch one time asking if I could help port to xbox. I was serious about it and have the chops to get it done, but of course he probably read that and laughed at how much of a schmuck he perceived me as being.

I was curious about the technical challenges in that. Isn't Minecraft in Java? Is there even a JVM for xbox?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Physical posted:

What are VBOs/VBAs?
Vertex Buffer Objects and Vertex Buffer Arrays. Take all you vertices and arrange them sequentially in memory. To turn them into a VBO/VBA, you have the mark them off to OpenGL, which a lot of people call "compiling." It's not really compiling in the sense of programming or anything; I speculate it's a leftover from display lists. Anyways, once compiled, it'll try to ram it down into the video card's memory--assume it has the memory for it. Now you can work with the vertices much closer to the video card's hardware itself, without having to beam all the same vertices over and over across the bus. You'll improve your performance right there. The downside is you put a bunch of traffic cones around the vertices when you compile it. You can't just casually go in and muck with a vertex anymore. But so long as you can manipulate them using stuff resident to the video card like viewing matrix transformations or vertex shaders, then you're fine.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
So far in my own dabbling around with game engines I've found a few things that have come out to be global constructs. One is all the subsystems, which I originally wrapped into a singleton, and then the entity manager. I ended up actually taking out the subsystem singleton because part of the interface I wrote had components get a handle to it at a specific time, so that way I know that only at that point would a component get to muck around with the subsystems.

Anyways it's true that it's easy enough to refactor. The code is basically already written, but just has to get moved around.

For the problem at hand, I wonder why the messaging system is not a part of the entity manager. If messaging happens across entities, then at the 40,000 foot level, it would make sense to me the entity manager would take care of these interactions.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
More questions about my favorite topic in this thread: component-based design. I now have entities and components and they're working together for the most part. I foresee some dependency problems though. I have one component that represents position and some other components are interested in position within the entity. I define the position first, so I get lucky here, and I also try to make sure any components relying on information from other ones will not fall apart if the information is not there yet. I wondered at a more general design level if there's something better I could be doing.

The one thought I had was each component would get a message when there were live. At that moment they then should be able to get all the information they needed. I can think of hypothetical situations with things like circular dependencies where this still might not work.

At this point I think it's not really worth the effort to worry about though. Where I think problems might show up is when I get entities loading from templates. There I don't think I can always guarantee a safe order anymore.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
More component-based design stuff, but I think this is more in the fun realm than anything else. I was curious for some examples of how people are splitting up things into components.

For a basic human-controlled character right now I have something like:

Health: for managing health. It services requests for taking damange or getting healed, and emit a death dignal if the player is considered dead.
AnimationState: for mapping movements to frames of some kind. This stores whether to player is walking, running, slumping backwards, and whatnot.
Position: for position, but this is an interface implemented by a PhysicsPosition which knows to interact with the physics engine for the most up-to-date. There's a stub one for dealing with positions not in the physics engine.
Facing: which pretty much just stores where the entity is facing
Velocity: like facing, but for movement, and this is tied to the physics engine.
Faction: Which side they're on, who are their friends and enemies.
HumanControl: Translating controller messages into movement and facings. This emits signals that a lot of other components listen to. For example, Velocity would takes signals for movement and try to make good on them.
AnimatedMesh: To be added, since AnimationState manages the mesh too much right now.
Physical: Physics information like mass. This interacts directly with the physics subsystem, but takes a lot of stuff from other components.

I intend to add something like a GhostPhysics for bounding boxes and such for thinks like melee and ranged attacks, but I haven't scribbled them out yet.

Is this looking like the right idea?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

poemdexter posted:

With your components you have actions right? Should probably discuss both. My setup is similar to yours but my game is a roguelike so no need for much physics.
I didn't do actions--I think. I guess we should make sure I understand the nomenclature here. By "actions," I am assume code that is applied to an entity that does whatever with the components. I think with everything I have in place I could, but it didn't really cross my mind as a thing to do. Instead, I'm doing stuff with signals and requests. When components are added to an entity, it registers signals it cares about, and requests it can accommodate. So eventually another component may request a signal, and the servicing component gets notified with the request ID, and it sends back a message containing the relevant data.

HumanControl works particularly with signals, with the idea that I could swap out for an AIControl component that would control the entity using the exact same signals, and all the components listening for them would be none the wiser.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

poemdexter posted:

HumanControl: This is something I might look into later. Right now I let XNA's keyboard stuff worry about moving and just tells the player entity to do an action for the position component. Of course my only keys at the moment are up,down,left, right so this might get changed later.
AI: Mobs have a component for the A* pathfinding. the action is "MoveTowards". It takes an argument of the target position (in case i want mobs to pick up gold and not just steam towards player). The action will actually do the pathfinding and the tell the position component to move.

I thought I would update the thread--and particularly you for expressing some interest--in what came up while I was getting HumanControl working. It gets a little hairy when it comes to activities that could get cancelled.

Say that you are doin something with real-time rendering with a 3d animated mesh, although it isn't entirely necessary. Once an attack animation is triggered, you probably don't want to let the player just let go of the attack button, and move around, aborting that animation. Similarly, you wouldn't want an enemy to always be able to abort an attack sequence. So once the attack animation starts, a lot of animation is suspended.

In my case, the state of animation is in one component, but human control is the one trying to request things happen up front. So there's some interplay there. What I have right now is that HumanControl will send a request out to anything that will tell it if the entity isn't accepting movement at the moment. If it's accepting movement, it will update the position component, which here has a relation to physics. That figures out the physical possibilities of movement. Once that component says it's okay, it sends out yet another signal that everything is in fact moving, and the mesh better get animated like it is.

It's kind of ugly. Another thing I thought I'd try is have the animation component send a signal when it wasn't moving, and then other components could unregister for certain signals until another comes along saying all is well again.

----

I picked up some of the Game Programming Gems books and saw some neat stuff. I've been doing C for... almost 20 years (holy poo poo!) and never really respected macros too much, but there was some good stuff about how to use them effectively. I haven't really interacted with expert C or C++ developers too much so it was enlightening to see why they decide to do this or that. Amongst some of the stuff was A*. I haven't worked on the AI side with pathfinding at all, so I have been worried about this. I'm kind of wondering how this has worked out for anybody else on here. In my case, I'm not working with systematic tiles so it sounds like I should probably define waypoints in my levels to guide AI.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I wonder about your finalize system since I pondered something similar for dependency resolution. Can you think of any situations where you might want to dynamically add or remove components? I imagine that would give you some grief if you're baking the entities. Maybe it won't come up for you, so you're fine and good.

Edit: An example I had where I could imagine myself adding or removing components was with having more than one playable character between which I might switch. So there I'd switch out an AI component for a human control, or vice versa.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Unormal posted:

One thing I wish I had added was a way to prioritize message handling between components. It'd be nice to be able to tell a component to handle an event before a different component, without having to add nests "BeforeX", "BeforeBeforeX", "AfterX", "AfterAfterX" (etc) messages/delegates.

This somehow makes me feel better. I did post earlier but my problems turning control messages into actionable activities. This was because the player may want to walk to the right, but they're in the middle of an attack animation. I kind of did the same thing of implying precedence in the event IDs. Since I now have two data points of this, I might put more thought into how that could be done better.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Does anybody here have a recommendation of existing examples or a middleware project that implements A* in C++? To be honest I'm lazy and would rather work from pre-existing code than craft something from scratch, especially since it seems to be common enough now. I see a lot of stuff online and might just start banging away, but I'd love to hear from anybody that has tried any stuff already.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I think I'm using a different communication structure than you, which probably will just make things more confusing. But I'll try anyways. I'm using a message bus for my entities, where components register messages that they're planning to send, and there are subscribers to them as well. Other entities can subscribe to the messages. A big one would a GUI entity for a health bar signing up for health change events in another entity. I guess that's along the lines of the kind of thing you needed.

I don't think in my own stuff I have a good solution for having multiples of the same component in my design. It will not accept the second one. By chance, if the copies of the component really are doing distinct things, then perhaps you have two different components after all.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
The kind of bugs specific to game programming I think have to be the coolest and funniest bugs of any kind of programming. I was testing out my attack box applying damage to enemies last night, when I'd find both the enemy and the player dying. I found out that the player's bounding sphere was touching the box too, so it was getting hit by itself too. So the player was killing itself with the attack.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
More component-based stuff: I'm trying to figure out how I want to handle entity death. At this point I have a Health component that emits a signal when health reaches the minimum health. Something that uses that right now is the component for animation capability. It will go through the death animations and freeze it on the dead body animation. However I haven't made anything else use it yet, notable components that control the entity in some way like AI or Homing. So with Homing I now have a body on the ground following the player around.

It was at that point I decided maybe not having every single component listen for this signal was wise. The best solution I can think of is for something external to listen for the death signal, and transform the entity into a dying entity, and then perhaps a dead entity. It will remove the components that are involved directly in making it do alive stuff, but keep around everything else so if it gets revived, it can get right back to what it was doing. It seems like the best way to handle it as I can think of, but am I missing the benefits of not transforming the entity? Or am I going to get into a mess changing the entities out?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I was wondering now how common it was for games written in static languages on Windows to actually target 64-bit now? I'm asking this after wrestling with a lot of middleware stuff that were still 32-bit by default.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Heh maybe I should stop trying to get all these 64-bit dependencies set up then. It's a shame--I was just about done. :(

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I have to ask some general questions about how you generally multithread up a game engine without generating all kinds of horrors because I think I've finally opened that Pandora's Box. I was dealing with the same scenario causing crashing in all variety of parts of my (crappy) game engine tonight. To me that smells of a race condition. Finally, I saw in a progression of test messages in at least one of the signatures that I was in the middle of the Irrlicht scene manager draw call when I freed one of my entities, which had some drawing information attached to it.

I am trying to follow the subsystem model, and I have most of the subsystems in their own threads. I have already done some thread safety within each subsystem so that calls to affect that subsystem don't cause it to blow itself up. However, the interplay of things is where things start to get a little crazy.

Generally I'm seeing the problem with an attack bounding box getting deleted. Previously, an entity with a component describing animation state has told the engine to create another entity to represent the bounding box. The bounding box is an entity with a contact trigger that applies damage to entities that are not the originator or the same faction. At the first frame that makes sense to do the attack damage, the animation state requests a new entity from the engine and has it made into the bounding box entity. The animation subsystem makes sure Irrlicht knows the mesh wants to play frames x-y. At the end of frame Y, that is the frame where it no longer makes sense for the object to be able to apply damage, so the animation state has the bounding box entity removed.

The problem goes something like this:

1. Irrlicht draws a frame.
2. The animation subsystem callback from Irrlicht is told that the part of the attack animation for some entity has finished; the part that involves keeping the bounding box active. Recall the animation subsystem is in its own thread and it triggered the callback to the animation state. This thread is separate from the main engine thread.
3. The animation component--which has the reference to the bounding box--tells the engine to start cleaning up the bounding box entity.
4. Meanwhile, the main engine thread that takes care of Irrlicht and friends has moved back to the top of the loop and is starting to tell the scene manager to draw.
5. The bounding box entity is getting cleaned up. All of its components are getting freed, including the Bullet physics stuff for the ghost object. I am using a wrapper that's Irrlicht-friendly, and that wrapper is currently displaying debug stuff through Irrlicht. That's important.
6. I believe meanwhile that in the scene manager, it's trying to draw the bounding box debug stuff for the ghost object that was getting freed, and it shits itself.

The best I can think of doing is having all the subsystem threads turn on a bool when they finished their loop, and have the main engine thread wait for this. I can't remember what it's called in Boost but I recall it has a really efficient way of doing this. I think that would take care of this particular problem. However, I expect other new and exciting problems to happen if I start trying to muck with the entities and components externally in the Python wrappers I've exposed. I think I actually first saw the problem there, even if I'm building without involving it right now. In that case, I got blown away at the same part of the engine loop when I was constructing entities and filling it with components related to drawing stuff.

Looking at the bigger picture, I can perhaps see more sinister problems afoot that make me think trying to be a big boy with multiple threads was completely stupid. I kind of did this more to better appreciate the real problems one can run into--not so much to actually make a game. But boy do I appreciate the problem now. However, even if I had made the whole mess single-threaded, I expect I'd still get into poo poo with an external scripting interpreter trying to manipulate things. So how do I generally protect this? I can't imagine that in real engines they're putting tons of locks around everything.

Edit: I suppose I just need to hear myself think through this a bit. I gave it about 10 minutes of pondering and pretty much realized I need to have a good separation of game logic from the critical section of the engine. I am thinking I may also need to have locks on the entities themselves. I expect a deadlock on that someday. :(

Still, I think even if I had something really simple, I could knock it on its rear end if I tried to attach some kind of scripting language to it. So I wonder if there are any good articles on trying to prevent scripting from trampling on the engine. Imagine giving a command in a script and it happens to come in at the engine's critical section. I got myself some reading on multithreaded game engines in general, but I'll take anything on that specifically since I think I may have started with something very naive.

Rocko Bonaparte fucked around with this message at 10:53 on Dec 11, 2011

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

OneEightHundred posted:

Basically, think how it would work if you tried doing everything with one thread, and see if individual parts of it could either be run as parallel operations (i.e. a task with a large number of objects with almost no interdependency), or sent to a work thread because other things you also need to do don't interfere with it, i.e. you can spin sound work off to a threadable job if you can do rendering work at the same time. poo poo with high resource contention usually doesn't thread well anyway.

After a night's sleep I've had a chance to settle down here. It looks like a big part of the engine--Irrlicht for rendering and Bullet for physics--can't run in parallel right now. I'm using a wrapper that exposes the Irrlicht object types to Bullet. I guess if there was some isolation then this could be done, but right now Bullet could move an Irrlicht object midway through drawing it and gently caress everything up royally. I don't think I want to go there (yet).

I'm mostly preoccupied with how to get a scripting console to be able to do rapid operations--ie not sit on a lock for a resource that would keep me from doing more than one script command per frame. Reading some stuff, do people approach this kind of like a GUI framework, where events are piled up into a queue?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

DancingMachine posted:

Is this your first time doing asynchronous programming? You're kind of jumping in to the deep end of the pool it sounds like. Retrofitting pre-existing single-threaded code to take advantage of multiple threads is the hardest kind of async programming. It is very fraught with peril and to do it successfully you need to really deeply understand the pre-existing code inside and out, plus be fairly confident in general async concepts.

Hubis and OneEightHundred give good advice. But at a higher level, if this is your first time dabbling in threads, I would try writing something from the ground up that is parallelized. That's much easier to do, but still difficult enough that you will learn a lot.
I'd say this is the first time I've messed around with real concurrency. Previously I just had to deal with situations where some small fries stuff had to run simultaneously, without much information sharing. I'm confident I can generally write thread-safe code. I will admit though at an architectural level, I am not experienced enough to be aware where I should be drawing the lines if I were trying to do it right.

I'm more keen on keeping that Irrlicht/Bullet critical path together than to try to get them running in parallel right now. To be honest, it's just because I'm currently not that interested in trying to do it. I want to see instead that I can start interacting with the engine with some scripting so I can try to get something vaguely resembling a game to run along. Later on, if it all really pisses me off, I can start to split up that critical path. I see a good bit of literature on that, which is reassuring that I'll be able to find good advice. The replies here have also been interesting.

What I'm really hitting right now is that a component can trample on the critical path quite easily. The entity addition/removal stuff is kind of secondary to that because it's the components the entities contain that causes the problems. After sitting on it today, it occurred to me this is the kind of reason why GUI draw threads are single-threaded. So what I guess I need is basically an event queue. The queue can be processed at any time outside of the critical section. I've seen some mutterings of action/event/command queues in some writeups, so I assume this is a pretty standard approach.

I wouldn't want to instead have a lock on the critical path because this could mean my ability to run scripted commands could be limited to my frame rate. Say, a scripted command comes in that causes some component to try to do something, but it finds its waiting on the critical path to finish, so it waits on it. In the worst case, the command completes and the next one starts just in time to hit the critical path again.

Perhaps the most illuminating thing so far I've had in doing all this is has to be the amount of architecture and engineering I do see in game engine design. Walking in, I got the impression a lot of stuff was slopped together, or that at best there were a ton of ugly compromises. But I do see a lot of structure now.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

DancingMachine posted:

Is this your first time doing asynchronous programming?

I was thinking about this a little bit more and I don't think I really got what you were implying. This, as something distinct from concurrency and multithreading, is the first time I've done this from the systems end. Certainly I've used asynchronous systems before when working with stuff like GUIs, but I would have to admit this would be the first time I've stood on the other side of the fence and seen what it looks like.

From that perspective, do you have any good recommendations for reading up on it that treat it distinct from the standard gamut of concurrency stuff?

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
Well I started to dig into the synchronization stuff by just slapping a lock around the part of the main loop that tells Irrlicht and Bullet to do stuff. Actually, I went completely chronic and put the lock around the whole inside of the loop body. I did this to see how it would respond to a different problem I am seeing--this is just because the mere act of throwing the locks around what I think was the part giving me the grief made the access violation go away. Gotta love it.

Anyways, I am trying to create an entity through Python using wrappers to the C++ code. A new entity gets fetched, and then it starts tagging on components, of which one is representing an animated mesh. This component wants to tell Irrlicht to load a new mesh. Since I was seeing an access violation here, I had it working against the same look as the main loop. Oddly enough, I still get an access violation all the way down in the ATI driver. It looks like Irrlicht's own code was able to load everything up okay to a point. I think the pants making GBS threads happens when Irrlicht starts to transmit the texture down to the card.

I'm wondering if there's some bizarre thread/resource ownership that happens with 3d stuff like you get with GUIs on Windows. I've at least seen this in C# before with Windows Forms stuff that you have to interact with GUI components on the thread they were created, so all this hilarity ensues. I'm kind of wondering if there's something inherent in having code triggered by the Python interpreter thread that would cause this to completely fail.

I'm thinking not, but it's quicker to ask this then to start really messing around with stuff to try to uncover why this could be happening. I'm actually thinking this isn't a race condition or something, so I'd have to write something up that still loads the mesh through Python w/o all the other baggage.

Edit: The initial impression I get is that it's just completely unsafe for the thread that is invoking the Python commands to muck with Irrlicht. I have been doing an experiment where I have the code being wrapped in Python trigger a temporary block in the engine thread to construct the stuff I want. This seems to generate the objects without crashing. So I guess I need to change my code so I don't pass around the Irrlicht and Bullet stuff directly, but rather have the thread that creates them take requests to manipulate them. You know, like you would do properly with abstracting subsystems or something.

Rocko Bonaparte fucked around with this message at 17:57 on Dec 13, 2011

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I can see that generally as a good architectural methodology. There is a lot of stuff out there. The one place where I don't really see anything is how to incorporate scripting into a multithreaded engine. Actually, I don't see much about the technical implications of incorporating scripting generally.

Imagine I have some thousand lines of scripting code for some basic but complete game, and there's an engine doing its own thing. There's plenty of code there that, if left to its own devices, would probably affect objects that the engine is actively using, causing all hell to break loose. I see two main ways around it. One is to spin on the contested resources, and the other is to just enqueue the scripting command to get processed whenever; I guess that would be like running jobs.

With the spin, I imagine a case where if my frame rate was basically 60 FPS that due to the contention, I could only get 60 commands through. Is this paranoia?

With the enqueuing, I imagine temporality becomes a huge bitch. At some point in the script I have to be sure what was put in previously is actually active.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Nalin posted:

Yes. Irrlicht is not thread safe. At all. Do not touch anything related to Irrlicht while in another thread; you are just asking for trouble. If you want to multi-thread stuff, develop a type of job system. The Irrlicht thread can then ask if the job is done, and, if it is, grab and parse the data. You will want to keep everything away from the Irrlicht thread and anything that it touches. Do as much of the work as you can and let Irrlicht do the rest.
This is good to know because I've been spending a lot of time now throwing Irrlicht in its own little pen and making everything outside interact with it through a slit in the door. However, I'm just for starters trying to avoid an contention by having Irrlicht's render call sitting inside a lock that all the helpers also get before trying to stir the pot. I don't think this helped me earlier, so I'll have to do something with jobs too.

Coming to a C++ programming thread near you: A question about how I could do that with Boost and template voodoo without having to write a bunch of stupid classes.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

Unormal posted:

Heh, little tidbit for C# component-composition-based engine. I'm learning Unity3d and it taught me that:

public T GetComponent<T>() where T : IPart

is a heck of a lot cleaner in practice than

public IPart GetComponent( string Name )

I've been running my rear end into the ground doing the messy way, basically because I want to be able to smash away at a lot of the game coding in Python itself. So I can't rely on static types at all. Otherwise templates--or at least generics as done here--makes a lot more sense.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

duck monster posted:

One thing I always wondered, is why of all errors, divide by zero error got the prestige of having its very own interupt (interupt zero, in fact)
My speculation was that since Intel started out with microprocessors for calculating machines, it probably stuck in reuse going into x86. You could imagine them moving on from one project to the next that they'd want to make sure it can do its predecessor's stuff, so from the beginning of x86 they were probably dragging in 4004 stuff into it.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

OneEightHundred posted:

I wouldn't have dreamed that Epic would have released a free version of UE, but I'm not actually that shocked by the lack of good low-end C++ options. That much has pretty much been the territory of open source engines, which have been awful starting with Crystal Space (1997) and continuing through today because the developers are all more interested in making stuff that's fun to develop (i.e. renderer features) than useful (i.e. tools, cohesive integration, scripting, networking).

I give credit there for Irrlicht for at least admitting that and making a rendering engine, versus an entire game engine. But in the bigger picture, I've been mashing away on my own game engine to tie into that for awhile now, and only now can I say I have something with a good entity-component-subsystem model that I could be comfortable using. Plus, currently it only ever crashes when I tell it to exit! I really only went this route because I wanted to get more cozy with C++ generally, but boy do I pay for it.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

OneEightHundred posted:

Well, I don't give them credit for it, that's exactly what I'm critical of. Irrlicht can get off the hook a bit for having a bunch of plug-ins to make it a more thorough game engine, but the problem in the first place is that there is way too much focus on making renderers and not a thoroughly-integrated game engine. Making mods for existing games, including engine mods, is staggeringly easier because a lot of the difficult integration and content creation problems have been solved, but making renderers is attractive because it lets you get flashy screenshots without doing the hard, unglamorous work needed to make a full game tick.
Compromise for partial credit then? They openly at least said they were making a rendering engine versus claiming to make a full-on game engine, but flubbing everything else by the shiny.

quote:

The worst part is that the so-called "rendering engines" inevitably start creeping in features like resource management, collision detection, UIs, sometimes even entity/component systems. At that point, it's not a rendering engine; it's a lovely half-finished game engine.
Okay, I stand corrected.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
That article on Super Metroid's world design does show some general themes and rules that should be considered in procedural generation. I think what Orzo is lamenting is when world generation fails to show good game design.

I suppose we could look at Nethack, which takes a lot of time to understand all the crazy crap that goes on. Or even Dwarf Fortress, which pretty much just throws you right into it. That feeling of freedom is great, although you could make a game easier to learn, and more popular, by designing in invisible hands for guidance. The hands would have to be pretty well invisible though; not some ham-fisted rails to work against, but something where a new player can stumble and bumble but still end up learning how the game generally works in most of its facets right away. If you're personal choice is to have advanced players skip all that, then the generator should give them that option.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I'm thinking maybe look at Ogre Battle for some inspiration, since I think it's doing a similar thing with multiples attacking multiples.

I'm also thinking about the amount of smacking around that's happening with just one peasant and one goblin. If they just take turns smacking each other, it looks to me like the normal formula would be who hits first wins. So they'd take turns taking away 2 HP each time, going around 5 times before the fatal blow. If that exchange is common then that would be tedious.

Something perhaps to consider is having more personality to the different individual units. I recall how in the original Warcraft, the humans and orcs were practical identical, except a small difference in their projectile attack and their magic attack. In those cases it's mostly a logistics game, and not a tactical one. If it's not tactical, you might as well just take the combined math of everything and declare a winner without the interactive combat.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I don't understand why one would regard composition as being less OOP. There are sure going to be a ton of objects running around by the end of things, and they communicate with each other across prescribed boundaries. Arguably it's more like OOP than the traditional tree of inherited stuff. It's more in line with the Gang of Four's idea of design, and follows the convention that inheritance is a kind of polymorphism, and polymorphism is actually the king.

From awhile back I was sometimes asking here in the thread about this stuff. My medium for practicing this stuff was writing my own game at a much lower level. That is, I wanted to play with lower-level stuff than necessarily write the game. I'm trying to learn new skills. Since that time I've learned a lot more about composition and see where I should apply it in my day job. Beyond that I've learned a lot about asynchronous programming by going overboard with it in my little engine project.

So it still holds true that if you want to write a game, don't write a game engine. If you want to write a game engine, then write a game engine. But perhaps consider writing a game first.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I'm trying to draw a think line between two points in OpenGL. I'm figuring--for now--to use a cube mesh of 1 unit length on all sides and just muck with the position, rotation and scaling. Doing position and scaling is simple enough in its own right, but rotation is messing me up.

My first impression was this was a job for atan2, doing something in the spirits of:

X axis rotation = atan2(y, z)
Y axis rotation = atan2(z, x)
X axis rotation = atan2(x, y)

But I see I'm doing some multi-axis rotation for things like, say, connecting (0, 0, 0) and (5, 5, 0). How should I approach this?

Adbot
ADBOT LOVES YOU

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

HiriseSoftware posted:

You can't use glLineWidth()?

Edit: You should be able to use glRotatef() to rotate by an arbitrary axis and not just x, y, or z. I'm assuming in your case you want to rotate this elongated cube along the axis defined by the line you're trying to draw, so just normalize the vector between e.g. (0, 0, 0) and (5, 5, 0) and use that vector as the axis you pass to glRotatef().

I'm using Irrlicht here and am trying to ignore the OpenGL-specific API, even if I think I can pull that out and use it under the hood. I was assuming setting the rotation vector to that value would be the same as glRotatef, but maybe not. That vector normalized is (0.7071, 0.7071, 0.0000), which would move me along multiple axes. I did try it regardless and it's spun all wrong.

Paniolo posted:

Depending on exactly what it is you're trying to do, you'll need to first transform the two endpoints into screen space (line thickness is a screen space concept, after all.) From there, it's pretty simple to calculate the four vertices needed to represent a line of thickness r - find the vector perpendicular to the line and its inverse, and add each to the start and end point of the line.

As your results will also be in screen space it's easiest to do this in the vertex or geometry shader so you can pass the results directly to the pixel shader.
I'm assuming here the result is something that would be a uniform line drawn across the screen as if I had run a pen across it. That's pretty nifty but not what I necessarily wanted. I was planning to use the line basically for aiming stuff.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply