• Advertisement


  • Content count

  • Joined

  • Last visited

Community Reputation

12159 Excellent


About Nypyren

  • Rank

Personal Information

  • Interests
  1. Overriding HandleHits seems like a reasonable thing for a derived class to do. You might want to make a separate virtual method to replace the "if" part of HandleHits which actually destroys the brick, and keep the rest in HandleHits without overriding it. You can create those other brick types the same way as your current Brick: either put them on a prefab/scene, or use AddComponent<DerivedBrickType>(). You can change some (or all) of your private members to protected to allow derived classes to use the same variables and methods.
  2. Clockwise angle between two Vector3

    I think you'd need to make a reference vector that is perpendicular to your navmesh edges, right (a "surface normal")? You could cross product two of your edges on the current cell. If you know they are always in a specific order, that means the cross product of edge[0] and edge[1] should be fairly consistent between cells. If your navmesh is always flat (or nearly flat), the normals of all of your navmesh cells should be close to the same direction ("up"). It may be simpler to just always use "up" in this case to bypass having to compute the cross product of the cell's edges each time you need it. Alternatively if the navmesh never changes, you could at the very least precompute the normal vector of each cell when it is created.
  3. Clockwise angle between two Vector3

    If you use the length of the cross product divided by the product of the lengths of the input vectors, that length represents the sin(angle between them). So you can say: angle = asin(cross(a, b).Length / a.Length / b.Length); BUT this will only ever return a value between 0 and pi because vector lengths can ever be negative. The problem that alvaro is pointing out is that when the angle between your vectors would pass pi, the cross product becomes zero and then starts going in the opposite direction from the direction it was facing earlier. If you do not have an additional reference vector, there is no way to distinguish this flip, and all angles you attempt to measure will be between 0 and pi. If you do have a reference vector 'n', you can use it to figure out whether the cross product has flipped or not by using dot(cross, n) and checking whether the result is positive or negative. If you use this information to negate the angle you get from the above equation you can get a decent enough result. You will run into problems if your cross product is not parallel to the reference vector, and you will have a useless result if it's perpendicular since the dot product will be zero. What would a reference vector be? If you have a game where ground vehicles are driving around a world where Y is up, you might use the up vector (0,1,0) as your reference vector and the forward vectors of vehicles or vectors-towards-waypoints as the inputs to the cross product. This might let you determine which way a vehicle should steer in certain situations. For other types of games, it depends on what your intended use is. For some games, you shouldn't use angles at all.
  4. I'm not very familiar with maximum flow. What I would do to verify an algorithm is come up with a few test cases that you know how to compute by hand, and then make sure your code produces the same results. You could use unit testing for that.
  5. I haven't implemented one of these myself yet, but I see cycles shown in the examples on the https://en.wikipedia.org/wiki/Edmonds–Karp_algorithm page (a specific implementation of the method you mentioned). I'm not quite sure how to interpret your printout as a graph, though.
  6. Sometimes I will add an indentation parameter to recursive methods when I want to print things in them. For example: int function(int number, int indentation) { if (number < 1)return(1); cout << std::string(indentation, ' ') << "is here. " << number << endl; cout << std::string(indentation, ' ') << "am here 1 : " << number <<endl; function(number-1, indentation+1); cout << std::string(indentation, ' ') << "am here 2 : " << number <<endl; function(number-1, indentation+1); }
  7. If you somehow find out how to reproduce it 100% of the time, you could use a data breakpoint on the stack address of the pointer that's becoming null to discover what code is causing it. It might be some stack corruption caused by one of those other methods. Another thing to check is: Maybe the debugger is showing you the last line of code that you have source code for, but maybe the crash actually happens deep inside the DLL. Make sure you look at the very top of the call stack even if you don't have source code for it. You should at least be able to read through the disassembly and speculate about what might be happening.
  8. Blind guess: That line of code is in a member function, and 'this' is null. x,y,rot,etc could all be member variables for all I know, which would cause the access violation.
  9. Problem serializing small ammount of data

    Ah, sorry. I didn't realize this was in the beginner's section. I actually have to deal with code like this at work, with (ostensibly) professionals who should know better, and this post just struck a nerve. Let me clarify my points for beginners: Using the + or += operators in C# creates a brand new string EVERY time you add something. This has to copy all of the characters from both of the input strings to the new string. If you do this in a loop once per character, the amount of memory read/written increases exponentially. This can drastically slow down even for a few thousand characters in the final string. A StringBuilder is optimized to allow appending lots of things because it uses separate arrays when it needs to expand, minimizing the number of character copying it needs to make. Casting from an int to a char treats the integer as a character code. For example, if your integer is 32, you get a space character. If it's 65, you get an 'A'. In the code posted above there's no way I could see that being intended. Things that I would use if I had to use text files: Write the file out using StreamWriter. This lets you do it without building the whole string in memory at once. Based on the format example you gave in the first post, I would read each line in from a file using StreamReader.ReadLine. Similar to StreamWriter, you don't need to load the entire file into memory as a single string. You can read one line at a time, split it up, then use int.TryParse and float.TryParse on each section. I typically use binary files instead. Even though some people like text because it's human-readable, binary is more compact and simpler to read and write with code. If you get familiar with hexeditors, you can examine files even if they're binary. This will come in handy since there will be some point where you'll need to use someone else's binary format. With binary, use BinaryReader and BinaryWriter. These have functions to read/write C#'s primary data types directly (ints, floats, bytes, chars, strings, etc). Strings written by a BinaryWriter have an additional length prefix (in binary) and are therefore NOT readable using a StreamReader. When you use BinaryReader/Writer, your reading code typically looks nearly identical to your writing code: If you had 'Write(int) Write(byte)' you'd have ReadInt32() then ReadByte(). If you need to write lists or arrays, typically you want to write out the length of the list/array first, then foreach through the list and write each element. When you read, you read the length, create the list/array of that size, then write something like: for (int i=0; i<length; ++i) { list.Add(binaryReader.Read____(); }
  10. It would probably be simpler to use a 2D array and have each element of that array store a brick or null. Then when you want to see if a cell is OK to place a brick in, check to see if at least one neighboring cell has a brick in it. You only have to check four elements of the array rather than the entire list of existing bricks. You could also keep a set of locations that you know are good places to place bricks, and update that set when you add/remove bricks. This would let you also randomly pick from that set fairly in one step, instead of having to randomly retry different locations if you can't place a brick at your first attempted location.
  11. Problem serializing small ammount of data

    I think I speak for everyone here when I say: "What the F*** are you even doing?" Never use += with strings like that. Just don't. You're performing N^2 work for no reason and that's why it's horrifically slow. Use a StringBuilder. I really doubt casting an int to a char is doing what you think it's doing. Do you know how to use a debugger? It should be obvious that something's wrong while you step through that. Seriously, why are you using strings? Do you LIKE your code being slow and broken?
  12. Path finding for most simple path?

    You want to visit all points? That sounds like the Travelling Salesman Problem. See also: https://en.wikipedia.org/wiki/Hamiltonian_path I forget what the algorithm is called, but I implemented a Hamiltonian path solver for complete graphs by starting with a minimum spanning tree and iteratively removing edges from vertices that have 3+ edges and then connecting the two isolated parts via the ends. This eventually makes a hamiltonian path, which is not necessarily optimal but may look decent.
  13. You could possibly use a Dictionary<object, SizeMode> instead of your array. Use the menu item or whatever other kind of object as the dictionary key. Otherwise the code could look pretty much like what you're doing with the array. You'll just have to fill out the dictionary somehow before you click things. Maybe in your form constructor or whatever.
  14. Yeah. In this case 'time' can be whatever measure of time is most appropriate for your game. It could be number of frames (integer), simulation time in seconds (float), etc.
  15. currentTime >= nextAllowedAttackTime
  • Advertisement