Jump to content
  • Advertisement

DrDeath3191

Member
  • Content count

    25
  • Joined

  • Last visited

Community Reputation

113 Neutral

About DrDeath3191

  • Rank
    Member

Personal Information

  • Industry Role
    Programmer
  • Interests
    Art
    Programming
  1. So, it turns out I'm a bit of an imbecile. I was just telling you how chrono can use nanoseconds. I was using microseconds in the game. It appears to work now. Further testing will be required, no doubt. I'm just going to be in the idiot corner, hating myself.
  2. The chrono library's high_resolution_clock can get to nanosecond precision, so I'm not entirely convinced there's a problem there. As for the rest of your post; I must admit I'm having a little trouble understanding. It seems like way too much to accomplish something that should be so simple. However, from what I think I understand, you believe my server falls behind and continues to lose time in a downward spiral, right? However, that's not really what's happening: a frame arrives late, yes. But then it appears to correctly receive frames again for a few frames, then drops one again later, ad infinitum. In fact, after the initial failure, it fails again every 4 frames. A very distressing pattern. My interpolation buffer delays this for a bit, but that's all its done. Perhaps some sleep will help me piece it together.
  3. I figured as much. But I have no idea what else to do. Everything I try, the server eventually falls behind. I improved the condition somewhat in my actual game by fixing my interpolation buffer implementation. I render 5 frames behind the server, and yet the client catches up after 20 frames or so. Changing the number of frames behind does not stop the server from catching up, but it does delay it somewhat. All of this is still local to my machine. It is quite infuriating, as I'm sure anybody making a real time multiplayer game has solved the issue I'm having, but I'm floundering. Do other games have a non-zero timeout? That certainly would make things easier. If not, what the heck am I doing wrong here?
  4. I did, but it seemed a bit large, so I thought it would look better in spoiler tags. I will remember this in the future. Upon testing this, you appear to be one hundred percent correct. I was under the impression that the latency of sending network messages to myself would be so negligible that the client would always have something to read, but apparently it is enough to cause this issue. So in terms of timeout, how much would you recommend?
  5. I have begun adding online functionality to my game. I use ENet to handle my networking. I intend to have the server and client run at a fixed timestep, with the server ahead in time sending world state information, and the client sending input commands. This seems to be working for the most part. However, it appears to be really jittery. The reason is that apparently every 2 or 3 frames the client tries to read from the server and gets nothing. The server somehow manages to get slightly behind for a bit despite having the same timestep as the client and starting first. I tried adding artificial delays to the client, but eventually the server would fall slightly behind. Naturally, I assumed that perhaps my simulation code was taking too long, but having created a minimal client and server and it happened again. I've been bashing my head against this for a while and I'm out of ideas. Perhaps someone more experienced can help me out here? Here's the code for the server loop: void oneSecondServerThread() { ENetAddress address; ENetHost* server = nullptr; ENetEvent event; ENetPacket *packet = nullptr; std::vector<ENetPeer*> connectedPeers; address.host = ENET_HOST_ANY; address.port = 8080; server = enet_host_create(&address, 32, 2, 0, 0); //wait for the client to connect while (connectedPeers.empty()) { while (enet_host_service(server, &event, 0) > 0) { if (event.type == ENET_EVENT_TYPE_CONNECT) { connectedPeers.push_back(event.peer); } } } bool running = true; //for testing purposes, the timestep is one frame per second std::chrono::high_resolution_clock::time_point currentTime = std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::time_point previousTime = std::chrono::high_resolution_clock::now(); std::chrono::nanoseconds timestep(1000000000); std::chrono::nanoseconds accumulator(0); uint8_t packetNumber = 0; while (running) { previousTime = currentTime; currentTime = std::chrono::high_resolution_clock::now(); std::chrono::nanoseconds delta = std::chrono::duration_cast<std::chrono::nanoseconds>(currentTime - previousTime); accumulator += delta; while (accumulator.count() > timestep.count()) { accumulator -= timestep; //check for events while (enet_host_service(server, &event, 0) > 0) { switch (event.type) { case ENET_EVENT_TYPE_CONNECT: connectedPeers.push_back(event.peer); break; case ENET_EVENT_TYPE_DISCONNECT: running = false; break; case ENET_EVENT_TYPE_RECEIVE: uint8_t receivedNumber; memcpy(&receivedNumber, event.packet->data, 1); printf("Client packet %u received\n", packetNumber); enet_packet_destroy(event.packet); } } //create a packet consisting of a single byte packet = enet_packet_create(&packetNumber, 1, ENET_PACKET_FLAG_UNSEQUENCED); for (ENetPeer* peer : connectedPeers) { enet_peer_send(peer, 0, packet); } printf("Server packet %u sent\n", packetNumber); packetNumber++; } } enet_host_flush(server); enet_host_destroy(server); } And the client: void oneSecondClientThread() { ENetAddress address; ENetHost* client = nullptr; ENetEvent event; ENetPeer *peer = nullptr; ENetPacket *packet = nullptr; client = enet_host_create(nullptr, 1, 2, 0, 0); enet_address_set_host(&address, "localhost"); address.port = 8080; printf("Attempting to connect ...\n"); peer = enet_host_connect(client, &address, 2, 0); bool connected = false; while (!connected) { while (enet_host_service(client, &event, 0) > 0) { if (event.type == ENET_EVENT_TYPE_CONNECT) { printf("Connection successful!\n"); connected = true; } } } bool running = true; //like with the server above, the timestep is 1 frame per second std::chrono::high_resolution_clock::time_point currentTime = std::chrono::high_resolution_clock::now(); std::chrono::nanoseconds timestep(1000000000); std::chrono::nanoseconds accumulator(0); uint8_t packetNumber = 0; while (running) { std::chrono::high_resolution_clock::time_point previousTime = currentTime; currentTime = std::chrono::high_resolution_clock::now(); std::chrono::nanoseconds delta = std::chrono::duration_cast<std::chrono::nanoseconds>(currentTime - previousTime); accumulator += delta; while (accumulator.count() > timestep.count()) { int receivedCount = 0; accumulator -= timestep; while (enet_host_service(client, &event, 0) > 0) { switch (event.type) { case ENET_EVENT_TYPE_DISCONNECT: running = false; break; case ENET_EVENT_TYPE_RECEIVE: receivedCount++; uint8_t receivedNumber; memcpy(&receivedNumber, event.packet->data, 1); printf("Server packet %u received\n", packetNumber); enet_packet_destroy(event.packet); } } //The server is sending frames once per second constantly //if we didn't receive a packet, that means that the server fell behind if (receivedCount == 0) { printf("Server dropped a frame!\n"); } //create a packet consisting of a single byte packet = enet_packet_create(&packetNumber, 1, ENET_PACKET_FLAG_UNSEQUENCED); enet_peer_send(peer, 0, packet); printf("Client packet %u sent\n", packetNumber); packetNumber++; } } enet_peer_reset(peer); enet_host_destroy(client); } The server method is called in its own thread, while the client works on the main thread. I'm sure I'm missing something obvious, but for the life of me I don't know what.
  6. DrDeath3191

    Continuous Collision Detection of Scaling AABBs

    Yes, but you hit the horizontal line second, so why even test the vertical? Even in the case where you cross both axes and miss, you only need to test the last one to determine the intersection never happened.
  7. DrDeath3191

    Continuous Collision Detection of Scaling AABBs

    You are correct, it seems I missed that. Apologies to Dirk. So the idea is that I calculate the minimum distance vector between the colliders shapes, and find when in the timestep a vertex moves more than that amount projected on that vector, am I understanding that correctly? This seems simple enough for me to get my head around. But why would you bother checking anything other than the maximum TOI? Doesn't the fact that one axis has a higher TOI imply that the lower ones couldn't possibly be correct? Placing an order as we speak.
  8. DrDeath3191

    Continuous Collision Detection of Scaling AABBs

    I've been off the net for the past few days, which is why its taken me a while to post again. I understand the paper a bit more, and it seems compelling. However, I wonder if perhaps just doing a binary search would be better in the case of AABBs. I would do something akin to the paper; I could start with two variables, t0 = 0, t1 = 1. Take the midpoint of t0 and t1, and calculate the state of the AABBs of interest at that point. Then, create an encompassing AABB which covers the t0 and midpoint rectangles of each collider. If they collide set t1 to the midpoint, otherwise set t0 to the midpoint. Repeat until the bracket is sufficiently small, and return t0. It seems to me that just doing a bunch of AABB collision checks would be faster than having to recalculate the closest features multiple times. Am I wrong? Of course, there is always the option of just having slower moving projectiles. I've been spinning in my analysis paralysis for a while, as you can probably tell.
  9. DrDeath3191

    Continuous Collision Detection of Scaling AABBs

    So I've thought about it some more, and I struck up upon an idea. Maybe good, maybe bad, not sure. The problem I had with my second plan was that I would have to perform 16 checks, one for each vertex on each box (the box is in 3D, sorry I didn't mention that). However, I think I really only need to check 2; the closest vertices on each box. So if I perform an interpolation of the nearest two vertices' paths in the frame, I can find a time where the line segments would intersect. The only case that I can currently think of that would break this is rotation, because the nearest points might not be the first ones that generate a collision. But I am specifically using AABBs, so there is no rotation to consider. Does that sound reasonable?
  10. DrDeath3191

    Continuous Collision Detection of Scaling AABBs

    Well, that sucks. However, I still hold onto at least a slight thread of hope, because I think you misunderstood what I meant when I mentioned rotation earlier. If I was using the rotated AABB as a bounding box, I would have agreed immediately that I'm pretty much screwed. However, what I was talking about was building a new AABB based on the rotation; meaning that for all intents and purposes no rotation takes place at all for the collision check. Like I said, I'm not trying to make the world's most accurate physics simulation; I can be a little generous. So hopefully that leaves me marginally less screwed. If that hope is misplaced, I may have to reconsider the fast moving projectiles for now, at least until I feel more comfortable with collision detection logic. Thanks for all your help.
  11. DrDeath3191

    Continuous Collision Detection of Scaling AABBs

    Yes, I figured that much out at least. The issue is, how do I get the time of intersection in this case? Please pardon me if I am not quite understanding, but do you believe this algorithm would not handle non-uniform scaling well? Because recalculating an AABB after rotation could very easily result in non-uniform scaling. I may have to read that paper a few times more to make sure I understand it, but it seems like overkill for what I need. I'm not well versed in this stuff, so I may be completely wrong, but I would imagine that the AABB case would have been a little simpler. Perhaps some false hope on my part?
  12. Hello, I have been doing some research on continuous collision solutions, because I intend to have fast-moving bullets. However, the AABBs of these bullets may change in scale, either by scaling directly or rotation of the underlying object. From what I've seen in my searches, continuous collision solutions such as Minkowski Difference and Separating Axis Theorem take the scale of the shape to be constant (if I am wrong about that, please let me know). So I'm at a bit of a loss as to what the correct solution is. I do have a couple of thoughts, but I'm not a fan of them; The easiest solution would be to create another AABB that encompasses the previous frame's and the current frame's AABB. This would not be the most accurate (though I don't really need it to be I suppose), but the bigger issue is how to determine the time of intersection, which I need to sort the collisions. My next thought is to create line segments for each vertex in both AABBs from their positions in the previous frame to the current frame, then check these line segments for intersections. This would make getting the time of intersection simple (I think), but it strikes me as monstrously inefficient. The other thought I had was creating a swept shape of the AABBs, and then using the Separating Axis Theorem to find collisions with the swept shapes. This is accurate, and highly used from what I understand, but I don't know how I would get the time of intersection, seeing as the scale of the AABB could easily change between frames. I don't plan on making a super-complex physics simulation; I don't need the minimum translation vector, the contact normal, or any of that. I just need to see that there was a collision, and when in the time-step it happened. If I am overthinking any of this, I sure would like to know. I've been wracking my brain on this for the last few days, and been feeling like a complete moron. Thanks in advance for any help!
  13.   Agreed. I'm not going to pretend I understand why it worked (especially since I am now intending on using another solution), but after all that crap happened I was happy just to have things up and running again.
  14.   This solution also works, and is probably the better one. Thanks for your help!     It sounds like you're testing in debug mode, and modern versions of Visual C++ perform a lot of debug checks on vector accesses.     I actually did test it in release mode. Same results. But perhaps other things have changed I am unaware of. I was working on a pretty old version.
  • Advertisement
×

Important Information

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

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!