Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

124 Neutral

About Kaetemi

  • Rank

Personal Information

  • Interests

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. What's non-intuitive.. When comparison operators are interpreted from this `(5 < b < 10)` into `((5 < b) < 10)`, which I would argue is useless (comparing a boolean with 10), rather than doing a chained expansion into the more useful `(5 < b && b < 10)`. EDIT: Just found this recent proposal: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0893r0.html I can agree with that. How about, assuming a strongly typed typedef mechanism is available, and if I'd typedef `char*` as `cstring`. As the pointer is now "hidden" from the programmer, would it be more acceptable to overload `==` on that `cstring` type?
  2. If you have a structure that has a pointer to another structure, or a pointer to a pointer, or some other indirection... automatically generated equality could become some weird blend of equality and indirect identity. Let's say I have two lists containing lists containing lists. Am I looking for The two lists actually being one list? (Identity) Two lists that contain the same collection of lists? Two lists that both contain lists that contain the same lists? Two lists that both contain lists that each contain lists with the same values? (Deep equality) Equality and identity in itself already seem to be a non-binary property... So we have the following situation in C/C++ (and a similar situation in Java): char *a; // "hello world"; char *b; // "hello world"; int x; // 42 int y; // 42 a == b; // false x == y; // true Which is... coldly logical... but not intuitive. However... assuming all hell breaks loose, and suddenly operators on pointers could be overloaded to allow for a more intuitive experience, we're no longer able to do the identity comparison there. Which would mean either explicit unoverloadable identity comparison operators, or a mechanism to get the original operator of a type, would be required in such case. Another coldly logical but non-intuitive syntax oddity in many programming languages, and one that's extremely common in game development: if (5 < x && x < 10) { } if (5 < x < 10) { } The second form is what everyone has already learned during primary school, but cold hard logic makes it expand to something that's absolutely useless, hence we're stuck with needing the first verbose syntax. There doesn't actually seem to be any technical reason why comparison operators couldn't be logically chained by a compiler though... (Just looked it up, and it seems Python actually implements comparison chaining, which is neat )
  3. So in my imaginary programming language, I'd need three operators to be precise. Equivalence, equality, and identity?
  4. I thought that was the whole point of C/C++. According to the documentation the <=> operator has 4 different possible standard return types, with each 3 or 4 different possible values, of which two can be == 0. I guess they're aiming at a different level of confusion.
  5. Would introducing a === operator for this make sense in the context of C++?
  6. In game development, code is indeed generally about transforming one chunk of data into another chunk of data, yeah. The use of OO does not bring that much to the table for that purpose. I think a lot of the OO push comes from the enterprise sector. From that POV, programming is largely concerned with storing and retrieving records of data, where real world associations do make sense. One of the things I find odd with OO implementations in current languages, is that while the following functions are pretty much equivalent from a technical point of view (aside from calling convention), they are treated as two completely different things. foo(bar); bar->foo(); However, at which point should a function be a method in a class, and when should it not? Does it actually even make sense to specifically declare class methods? I'd find it more convenient and style-flexible if these ways of calling a function were just syntactic sugar for the same function. It would also add some sanity to the weird hack that is called "extension methods", essentially make it obsolete. You could even go as far as making "properties" just syntactic sugar for a function call. A getter is a function that returns something, a setter is just a function that takes some parameters (and yes, why not have properties that take and return tuple values). As an example, an `int` property named `foo`. Make all three ways of using it valid, and you can code in whatever style you like. // This is not C // function int foo(int* this); a = x.foo(); // Method call a = x.foo; // Property getter a = foo(&x); // Function call // function foo(int* this, int value); x.foo(a); // Method call x.foo = a; // Property setter foo(&x, a); // Function call
  7. You just need 1 water bitmap for each tile with a gradient following the flow direction as alpha channel. Render with alpha test on the alpha channel, and animate the alpha test value depending on how much water you want in the pipe section. Add some particle effects for decoration.
  8. Unless you live in an overpopulated city with poor internet, an overabundance of wifi interference from neighbours, and are using a mobile hotspot as internet connection. Yes, you can have a beefy 50mbps internet connection today with 350ms ping and 1-5% packet loss. Also if you're using WiFi over an AP that's slightly too far from the internet router. LAN connections will go through the router regardless if they're on the same AP, and there will be packet loss (a lot of it). Okay. Player A sends position (5, 10) at 100050ms. Player A sends position (5, 20) at 100100ms. Then. Player B receives the first position. It sets the time of player A to 99950ms (so we keep an animation clock for each remote player), 100ms earlier (buffering delay), and positions him at (5, 10). Player B has a next frame 50ms later, it moves the animation time of player A forward to 100000ms, position stays the same. Player B receives the second position. Player B has a next frame 50ms later, it moves the animation time of player A forward to 100050ms, position stays the same, since it's now at the first position. Player B has a next frame 25ms later, it moves the animation time of player A forward to 100075ms. This time is inbetween the two received positions, so the position is interpolated to (5, 15). And so on. The key here is, start with replicating exactly the positions and timing from the remote player, as if they're an animation timeline, with some initial delay to allow for buffering. Only once you get that working, think about extrapolating and advanced smoothing. Quick and dirty interpolation pseudocode: double timestamp0, timestamp1; vector2 pos0, pos1; double timestampNow; double diffTotal = timestamp1 - timestamp0; // time between timestamps if (diffTotal <= 0) return pos1; // sanity double diffNow = timestmap1 - timestampNow; // should be between 0 and diffTotal if interpolating double factor1 = diffNow / diffTotal; // between 0 and 1 double factor0 = 1.0 - factor1; // between 0 and 1 return (pos0 * factor0) + (pos1 * factor1); // result vector Review the following maths: Trigonometry (area, sin, cos, tan, the rest is not important). Right angled triangles are practically the same math as vector math, so you can skip ahead to vector math from there as well (vector math is 'easier'). Vector math (adding vectors, multiplying vectors with a factor, the length of a vector (sqrt(x²+y²), it's easy.), dot product.) Matrix math (matrix * vector, matrix * matrix.) This is useful for rotations and stuff. Interpolation (linear interpolation, bezier interpolation.) Extrapolation Approximation And always remember: sin, cos, tan and sqrt are evil.
  9. Not sure about the C# GC, but for comparison, the Dart GC is optimized specifically for working with many short-lived objects (they also dropped the 'new' keyword). It has a multi-tiered (generational) GC approach, using a round-robin stack for all new objects. Only objects that outlive their welcome in that stack get allocated into heap memory. Unfortunately Dart doesn't have proper integer and floating point primitives (it has a JS-like number type), so it's not really an entirely appropriate language for game development. Fully agree that a language should empower the programmer with choice, rather than enforce default behaviour. There's a `stackalloc` operator at least for some cases in C#...
  10. For example, say client A sends the position. It should also send it's current time alongside it's current position (so, the time that the packet was sent, and the position at that time.) Client B will receive a position and a timestamp. When it receives the second position it knows the exact time it took client A to move from the first to the second position, so in case the packets did not arrive cleanly, it can replay the movement at the original speed. Extrapolating is "the same" as interpolating, but beyond the known positions. When extrapolating, you need to do additional smoothing, so start with only interpolating. As an initial test, just for interpolation with delay, let the first timestamp you receive be your reference time. Subtract 100ms, which serves as a "delay" time difference. Let the resulting timestamp tick forward according to the local time. This will be your "replay" time. Simply keep the latest positions received from the other client in a list. Interpolate linearly between the positions that are before and after your current "replay" time. This will give you a very basic delayed interpolation.
  11. At the very least, your packet will have to include the timestamp that the position was originally recorded at, so you can interpolate the timing between positions appropriately (the difference between the timestamp of each position message is what matters here). The timing difference between sequential packets between sending and receiving is one cause of jitter. Timestamped packets give you the real position curve. Use basic interpolation to match the position timing. Then look into extrapolation, slowing, and speeding for expected packets that are delayed or lost. Decide on an acceptable delay to use as target. Calculated connection ping time can be used for extrapolated realtime position. You can trade-off between delayed position and extrapolation jitter. Smoothly slow down and speed up the position simulation speed to match your target delay time. Extrapolate or interpolate the position based on the real position curve.
  12. Simple question. What practically annoys you on a regular basis in the programming languages your are using? For example; lack of builtin vector and matrix types, undecipherable template syntax, inconsistently utilized exception handling, irrational type names for primitives, ...
  • Advertisement

Important Information

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

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

Sign me up!