• Content count

  • Joined

  • Last visited

Community Reputation

178 Neutral

About mike3

  • Rank
  1.   Thanks -- a nice "KISS" method for doing this. I had tried something similar, I believe, but did not use the flag grid, which seems better.
  2. Hi.   I am wondering about this. I was not satisfied with my previous system for doing this, which seemed kind of ugly or limited, and I was wondering what would be the most efficient and elegant solution.   What I have is a cell-based, turn-based game with a discrete game world, that is, it's a raster of tiles, not a space with (approximately) continuous (floating point) coordinates, with each object in one time. And I was wondering how you deal with collisions. In particular, each object can move but it can, obviously, only move from tile to tile, never be in between two tiles.   This means that when we get collisions, we have a number of cases to consider, and I'd preferably like something better than a casewise approach. Moving one cell at a time, we could have, e.g. that two objects move at each other, their coordinates would change by 1 cell each in opposing directions, causing them to swap places if they were right next to each other. They'd go through each other, so that should be a collision. Another way a collision can occur is that two objects try to rush each other for the same cell. A situation that might look like it would be a collision, but isn't, is two objects moving in the same direction, in the same line, one just behind the other. If you look at only the one in behind, one could think it will collide with the one ahead unless you also look to see which way that is moving, which adds more complicated, tricky programming to make it work on a computer. Things are further complicated by that some objects may move different velocities, crossing multiple squares in a turn (like a shot arrow).   Almost all the collision-handling stuff I've seen deals with continuous space and (approximate) continuous time, e.g. checking overlap, etc. and so does not seem obvious how to apply to a discrete space and maybe also discrete time.   One way I thought to handle it would be to just use a continuous simulation space which is "rounded" to discrete, but then we get a computationally-intensive simulation, as it seems that given the discrete character of the world space, we should be able to simplify/optimize things considerably.   What do you do?  
  3. Overlap means yes, windows/widgets overlapping on top of each other. Not necessarily draggable -- just on top of each other, e.g. a menu and then you open up a sub-menu which floats above.
  4. Hi.   I am wondering about this. I am curious as to how you efficiently program a "widget" GUI system, that is, a part of a program that draws interface windows with buttons and scrollbars and that type of stuff (widgets) on them.   I have done this a couple times before but I was not really satisfied with my previous attempts and am now curious about how you really make it efficient and clean. In particular, what I have is this: I represent the windows and widgets by a tree structure, which is "natural" because it has a natural hierarchical structure, in which the root node represents the whole screen, and then below that we have nodes for the windows, then each window node has nodes for the widgets, then each widget node has nodes for the components of the widget (It could go further, in theory, but this is as far as I go). The order in which the widgets/windows overlap (from front to back) is determined by the ordering of them as siblings on the tree -- the nodes keep pointers to the next sibling in a linked list.   The trouble is that I am trying to figure out how to make the render/drawing as quick and efficient as possible -- in particular, we may know that only certain widgets or components need to be redrawn, so we shouldn't need to explore every node of the tree, but we also have to deal with resolving overlap: we shouldn't redraw something with a higher position on the order if it doesn't actually overlap anything, but we also may not want to keep exploring the whole structure to check for overlaps every time we do a redraw. How can we efficiently do this whole process, including the overlap resolution, the latter ideally without having to check every sibling?   This has to have an already-existing solution since window-based GUIs are so ubiquitous. I am just not sure where to find a good description of it. What would that be?
  5. Event Handling within an ECS

    @Servant of the Lord: Thanks a lot. I think I grasp now how this works. It certainly seems more flexible than trying to shoehorn everything into the "update" routine, probably is more amenable to optimization as well. You don't have to worry so much about trying to fit the system effect to a strict sequencing regiment, either.
  6.   Because it provides one solution to your problem. You can allocate a single block of memory and messages and write themselves into the buffer, etc...   First, I'd make sure you really need a messaging system anyway. Ideally you could replace them with method calls, and that would make the dependencies more clear.   If you really do need some sort of message-like design though (for instance, to be able to queue up messages and process them later), then ask yourself if dynamic allocation will really be a problem (I assume you're worried about performance of dynamic allocation).     Yes, I suppose that you could just use method calls, e.g. inherit from some kind of interface class which is kept suitably loose that implementation details don't leak, but then you can't defer processing until later, which was the purpose of the messaging system.
  7.   Why would we serialize messages? This is about internal communication within the program.
  8. Hi. I am wondering about this. Is there a good way to do event messages between two large-scale loose-coupled parts of a game program without having to dynamically allocate and deallocate the messages? Messages may need to be queued, and there can be different types of messages, which suggests an inheritance hierarchy and that's where the dynamic memory stuff comes from, at least when using C++ as I'd be in this case. Thanks.
  9. Event Handling within an ECS

      This is a shocker. I am curious: could you run through a few very simple explicit examples of like what kinds of methods would be on a couple of types of system objects built this way in a game? As I'm very used to thinking of the "update" thing. Also, what calls these methods? (With update its obvious: it's just called in the main game loop, but with this, some more diverse code must be doing the calling because the methods are more specific in scope.)
  10. Hi.   I was building a game program that uses an "Entity-Component-System" type architecture and was wondering how you would go about implementing doors. In the program as it stands, there are the following requirements:   1. Components should be generic enough that you can form new entity types without a type of component for every type of entity (as that essentially defeats the purpose of the ECS architecture, which is to allow you to make all kinds of things with composition),   2. Components should contain only data, no code.   3. Systems contain all the code for the logic.   4. There is a messaging pipeline where the systems can send messages to each other.   Given this, I am wondering how you would go about implementing doors? It seems that doors require a state and changing that state changes the graphic displayed for the door. Right now, I have a GraphicComponent which stores a key to a graphical asset, and a PositionComponent to store the entity's position. There's also a PhysicsComponent which stores the physical properties of the entity. But if I add a StateComponent to store the door's state, then, when you change states, that has to update the GraphicComponent somehow, and also the PhysicsComponent to make the door passable -- this is a tile-based game, not one taking place in a continuous space. However, because of requirement 1, genericity, we cannot have anything too specific to the door in the StateComponent, but we must specify how to update the other components. But how do we do that without violating requirement 2 -- absence of code in the components? I have a "Finite State Machine" (FSM) object in my program, which would seem to be what I'd want to use, however it's meant to be general (I use it in the user interface to handle various user interface states, such as main menu, playing the game, etc.) so when you make one you specify code, not just data. It would seem it would violate requirement 2 to stick that in the StateComponent.   What is a good way to do this? Should I just use the FSM and see if I can get away with it?   And it gets worse: what happens if you want to have the door be jammed by something else sitting on the door's tile when it's open? Then there needs to be something to sense the object is present. How can you do this without a dedicated system for doors which would violate condition 1?
  11. Why would it crash on "whatever" if none of the old code uses it? You literally could have an object with two members, one being a pointer set to gibberish and one being a pointer set to a valid object and as long as you never tried to -use- the gibberish pointer it wouldn't actually do anything undefined.     The way I interpreted the example, the crash occurs when Foo's constructor is invoked with the FooContext having an uninitialized whatever member, and the crash occurs when Foo's constructor is invoked and chokes.
  12. I suppose I wasn't understanding the example very well. If "whatever" is a member added to the struct later then what would it being set to null matter for old code? Unless the "old code" tried to utilize it then it would essentially be the same as the transparent addition of adding a new variable to a class your code was using, but not utilizing that particular variable. I'm assuming the point you're getting at is, someone adds the new "whatever" variable to an object, and your code attempts to use the "whatever" object, but your coworker managing the usage of the struct that passes it to you hasn't implemented setting that whatever to something yet. In that case of course you would have to check validity of the object before you use it. If I'm getting this wrong please do re-explain it to me.    The example appears to be: We have a class "Foo" which takes a "FooContext" to specify how to set it up. Initially, this "FooContext" contains only one parameter, "bla". Bits of code are created that have to make Foos from a FooContext, and naturally, they only set bla. But then down the road as our project progresses, someone decides now to add a new feature to Foo, which now requires a new parameter, "whatever", in the FooContext. And in how I imagine this scenario, which may or may not be how kunos imagined it, I imagine "whatever" to be a strictly "extensional" feature, i.e. it does not alter the original behavior of Foo, but extends it to add capability, that is, that the old way of using Foo should still work and not break. (The reason for this requirement is because without it, we might be forced to change the code anyway, but I'm trying to isolate the addition of the data field itself as the problem) But the programmer adding the new "whatever" parameter forgets a place where FooContexts are used and so doesn't add the proper initialization to the extensional feature whatever. The constructor for Foo now gets gibberish in the whatever field and crashes or behaves in some unpredictable ("undefined") way. It's not that the old code (here, meaning the code that makes the FooContext and the Foo) attempts to use "whatever", it's that the old code doesn't use "whatever", and because it was not updated to take "whatever" into account (meaning, it doesn't even set it to null, it doesn't do anything with it, period), causes Foo's constructor to gag.   So do you add the check for "whatever" not being set in to the old code, in which case it would probably be easier simply to just properly initialize whatever, or do you add the check in Foo, and regardless of the check placement, do you need to add a constructor to FooContext that ensures a stable "uninitialized" or "null" value that can be checked for? Because if you have to add the check and/or set-to-null in the old Foo-using code, then if you forget to add it there, you have a crash or other failure. To me, it seems the only way to make it robust against such omission is to put a constructor in FooContext that pre-initializes whatever to null.
  13. The ideal thing to do would be to treat the context as a volatile object and check for null on .bla before attempting to use it.     Do you mean a check on "whatever"? Since "whatever" was supposed to be the problem variable, as it was supposed to represent a "new feature" that had been added, and all preexisting code (i.e. before the feature addition) only knew of bla. The code already initializes bla. (Though I suppose maybe a check on bla would be good too, as someone could fail to init that, too) But where would this check go? If "in the code initializing the FooContext", then that means the programmer has to add it to each such piece of code, which creates a lot of duplicated checks, and more importantly, if you're doing that why aren't you just adding a proper initialization of whatever? And furthermore, the programmer adding such checks is then aware of the existence of the rest of the code, whereas kunos' scenario was that someone adds a new feature ("whatever" in this case) but isn't aware of/forgets to add the corresponding initialization to every place the FooContext is initialized. So if they are to add the checks to wherever the FooContext is initialized, then they know about those places, and so they should be adding proper initialization too, I'd think. But his scenario is that they are not so aware. It seems he wants it "robust against feature addition" or something like that. If the check goes in the constructor, then what about the concern about constructors being bloated with checks?
  14.   So how do you suggest to avoid crashing when someone "fails to pass something" as you suggest should be avoided? And in the example given, that something was to be passed to a constructor.
  15.   So what would be the correct approach in the example case, with the struct where a new member may be added? Where would the error be "reported" to, and in what way? More importantly, how would we know "whatever" was uninitialized, when its value as uninitialized may be undefined?   E.g.   FooContext fooContext; fooContext.bla = <smth>; // old code that didn't know about the new "whatever" feature   // member whatever could have an undefined value, so how does this check that and "report" it, fail gracefully, etc.? Foo *foo(new Foo(fooContext));   As like he says, it seems you need a constructor of some kind in fooContext to prevent this. Even if not one to force the programmer to pass a parameter, then at least a default one to initialize the variables so their values are all defined (perhaps so as to indicate special uninitialized states that Foo can then check for).