Jump to content
Xtreme .Net Talk

snarfblam

Leaders
  • Posts

    2156
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by snarfblam

  1. Back onto topic... How is this game meant to be run. There are games like minesweeper where it is important to utilize as little CPU power as necessary, and there are games like Unreal Tournament where the need to share CPU power with other applications is minimal. If your game is more along the lines of the latter, I highly recommend using a solution along the lines of PD's "heartbeat". A great heartbeat is the monitor refresh rate, where you examine the amount of time that passes between each refresh and perform logic accordingly (for each timed event, you examine how much time has passed and determine if the "deadline" has passed yet, and if so, perform said event). If you want the advantages of multi-threading, you can always dispatch tasks to worker threads.
  2. The code sample at http://www.xtremedotnettalk.com/showthread.php?t=85719 must have been written before formatting was implemented for CS tags. Formatting tags are visible within the C# code. And here: http://www.xtremedotnettalk.com/showthread.php?t=86021. And maybe more of dynamic_sysop's code samples.
  3. The Problem Using reflection, you can manipulate almost any aspect of any object in a completely dynamic manner. However, when implementing a .Net based automation or scripting software it becomes painfully obvious that event handlers can not be attached dynamically unless a function with the appropriate signature already exists, which is hardly dynamic at all. There are two solutions to this problem. Solution: Delegate Contravariance Delegate contravariance is the creation of a delegate where the target method has at least one argument whose type derives from the corresponding argument's type on the delegate type declaration. For example, examine the following C# code: void DelegateExample(object o1, object o2) { MessageBox.Show(o1.ToString() + ", " + o2.ToString()); } void CreateContravariantDelegate() { // EventHandler is defined as: void EventHandler(object sender, e EventArgs) this.Click += new EventHandler(this.DelegateExample); // Although the signatures are not identical, we can still create // the delegate because the fact that each argument in // EventHandler is the same type or a derivative type of // the corresponding argument in DelegateExample, the // invocation is guaranteed to succeed. // In this case, the "sender" parameter is the same type, // and the "e" (event args) parameter is a derived type // (System.EventArgs inherits System.Object). } This allows you to create a method where all parameter types are object, and then use this method to handle any event where the parameters are all pass-by-value and reference-type. C# version 2 supports this feature. Older versions and other .Net languages can achieve the same effect through reflection. The problem is that this solution requires a pre-defined handler for each given number of arguments, can not handle value-type parameters, and does not account for the possibility of pass-by-reference parameters (out and ref parameters in C#, ByRef parameters in VB). This solution can use a single pre-defined method to dynamically handle events from the vast majority if not all .Net Framework objects, but can only handle a very limited number of non-event delegates and non-standard events. Solution: Reflection Emit A more flexible solution to the problem would be to use Reflection.Emit to dynamically generate "lightweight" methods that can handle a given type of delegate. A lightweight dynamic method is a method created at runtime using Reflection.Emit. This type of method does not need to be tied to an assembly or type (although instance methods can still be invoked on lightweight methods not owned by any type), which means significantly less resources are used for dynamically generated code, hence the name. Subscriber: The attached code sample defines a class named Subscriber. Subscriber "subscribes to" (handles) events and delegates, generating handlers as needed (not taking contravariance into account), re-routing subscribed events to a universal event handler to which it passes the arguments in the form of an object array. The universal event handler raises an event each time it handles a subscribed event so that outside classes can receive these events, regardless of the event's signature. The following is an explanation of the basic components of the Subscriber class. CreateHandler Method: This is the heart of the operation. This helper function uses Reflection.Emit to create a dynamic method that loads all the arguments into an array of objects and passes this array onto the universal event handler (a manner of "thunking" if you like to think of it that way). This function accounts for out and ref parameters and works with either value-type or reference-type parameters. The limitations are that it, as implemented, does not allow out and ref parameters to be assigned to, and does not support events and delegates with return types. Universal Event Handler: This function, which is invoked by all of the dynamic event handlers, raises the EventRaised event to broadcast subscribed events. It can also be overridden in a derived class to handle subscribed events. EventRaised Event: This single event is raised every time any subscribed event is raised, for fully dynamic event handling. Subscribe Method: This method has four overloads. Two subscribe to events and two subscribe to delegates. All overloads examine the delegate type, create a handler if one doesn't already exist, and either attaches the handler to an event or returns a multicast delegate with the universal event handler added to the invocation list. Usage To use the Subscriber class, first create an instance of it. To subscribe to events, pass the event source (the object that will raise the event you want to handle) and either the name of the event or an EventInfo that represents the event. To subscribe to a delegate, pass either an existing delegate or a System.Type that represents a delegate. A delegate will be returned with the universal event handler appended to the invocation list, so that the delegate will behave exactly as before with the exception that it will also broadcast its invocation through the Subscriber object. To handle events, either handle the EventRaised event, or inherit the Subscriber class and override the OnEvent method, which is the universal event handler. Events can also be simulated by explicitly invoking OnEvent. Possible Improvements Dynamic methods could assign values back to parameters from the array after invoking the universal handler in order to support ref and out parameters. Support for return-values. Reduce the number of dynamic methods created by using a delegate contravariance mechanism with a small number of pre-defined handlers and using System.Object for all reference-type parameters in dynamic methods. This would require a re-write of the handler caching mechanism. Provide a mechanism to persist dynamic methods to a DLL so that they don't need to be created every time an application is run. Subscriber.zip
  4. Go to Tools/Options->Projects And Solutions/Build and Run. F5 is not "Compile and Run," but rather "Start Debugging." It will only re-compile if you have it set to.
  5. From what I see, employers on the whole have lost sight of the needs (and wants) of their employees. It is all about good numbers. Every level of management gets pushed on, in one way or another, to produce good numbers. Today. Tomorrow is another day. No one understands the concept of investing in your employees. Companies tend to forget that a happy employee is a productive employee, and that a good job is something that good workers compete for. People who like their jobs tend to do them well and people who don't, don't. I don�t program for work, but I am lucky enough to work for an old fashioned company that still seems to care more about the employees than the stocks.
  6. Okay, let me make this clear. No offense, but no one seems to be reading the whole thread. Using dynamic assemblies means that I need to create new assemblies at run-time. Since I will need to create and access handlers immediately as I need them I will need to finalize each and every dynamic delegate I create, in its own assembly, hence an assembly for each type of event. This is what I want to avoid. You can't go back and amend a dynamic assembly once the process is finished, and I will need to finish the process for every delegate type because it needs to be created and used as soon as it is defined (I have no way of knowing ahead of time which types of delegates I will need). MrPaul came up with an ingenious bit of code that can use pre-defined delegates and handlers to handle 95% of the events I will run into, but 95% isn't enough. I think that a hybrid solution would be my best bet. Predefine the very common event handlers. For the rest, create dynamic assemblies. But, on application close, create a single new dynamic assembly where I can consolidate all dynamically created event handlers, and save this to a DLL. Next time I load the app I will have a single assembly that contains any previously-created handlers. Correction:
  7. I'm sorry. I haven't used VB8. You must be using "magic forms" (I thing the actual name of the feature is "default instances"), i.e. VB6-style forms. VB optionally allows you to access a form by it's class name instead of explicitly instantiating it and setting it to a variable. When you close or dispose a form, VB injects its own behavior for the form instead of using normal .Net behavior, including the spawning of new forms when an old instance is no longer usable (disposed, for example). Hence, when you code with your magic forms in VB you will experience different behavior than I do with normal OOP forms in C# (don't start an OOP argument, I'm just referring to different referencing tecniques).
  8. Diesel, we can always count on you to spread cheer and optimism. First of all, there are already a small handful of game-programming books for .Net, both VB and C#. And as far as I know, most of them are still selling for $50 each. Even the horrible ones with code listings in the book that don't work. I really can't imagine that it would be hard to top the handful of mediocre .Net game programming books out there. Secondly, the site is probably outdated and not the highest priority in his life. If he were to write a book, he probably would, as I would, go to great lengths to make sure that everything was conceptually and logically sound, and have other programmers participate in the editing process. Thirdly, so? If countless books have been written on a given technique, then that goes to prove that there is room for more than one, and most likely, one more. Fourthly, I think that the other three quarters of the book are in his brain and any programming projects he has contributed to over the years. If it isn't enough for you, don't buy the book. Isn't capitalism great? Fifthly, he is ThePentiumGuy. You have to start somewhere. His book might not be a New York Times Bestseller, but if it is good and people find it useful then word of mouth will do some wonders, and who knows, it could turn into a series. Can't know if you don't try (I know you think you know, but you aren't doing the thinking for the rest of us). Sixthly, check out micro printing. Anyone can get a book published. Anyone. So even if it flops and doesn't make him a cent or get him anywhere in the world, he can still keep it on his bookshelf and tell people he meets that he wrote a book. Oh, and keep on smiling, Diesel.
  9. Well, like I said, I would prefer not to create an assembly for each type of event (both of the links do this), but I don't think it can be helped. Mr Paul, each line of code is clearly commented but it is hard to make out the logic of the code as a whole. By the looks of things, though, I would say that when using your method, the event handlers must already be defined for each given number of arguments. Also, I think there would be a problem with your code when pass-by-reference arguments are involved. And value types are a must. Basically, I want to be able to handle just about anything that a user might try to link to dynamically. That means anything goes. Not just sender/eventargs events, but any kind of signature. Your code looks handy and dynamic, but it doesn't quite fit the bill.
  10. Perhaps you should research some .Net optimization techniques. Then you can go back and look at your code and try to find bottlenecks, sort out redundant and unnecessary code, and re-examine the logic to see just how logical it is. Draw some program flow diagrams and see if things can be organized better, and so on. Re-examining your program's architecture might also help you identify bugs and bottlenecks.
  11. The MSDN interface online is poopy. It is slow and klunky. Even if you just view one page. It doesn't work with the mouse wheel in FireFox and the text renders incorrectly: some times text overlaps or doesn't scroll with everything else. The index on the left is useless. Not to mention, it doesn't remember my language filter settings. Besides all that, this is how I use MSDN: When I need more info on a specific class, function, or keyword I will use MSDN. I am not lacking in hard drive space, and the locally installed MSDN documentation is easy and fast, except for the search. If I need to search I go to the object browser or google, depending on what I'm looking for. The fact is that I don't find myself googling for .Net documentation very often though. To each, his own. If you like MSDN online, that's fine, but it doesn't fulfill my personal programming needs.
  12. A VC++ 6 book will teach you C++ just as well as any other C++ book. It will also probably teach you MFC and ATL. This is what it will leave out: -special keywords and constructs for .Net (properties, garbage collection, etc.). These are mainly useful when converting other .Net code to C++ or when your compiled code will be used in another .Net language. -The .Net Framework, which is a very large, useful, easy programming library, but it is not a must. Anything that can be done with the .Net framework can be done without (whether by MFC, Windows API, code posted on the web, whatever). Or to sum it up:
  13. The thing you need to realize is that the menus in .Net 2005 are actually a different class (MenuStrip, MenuStripItem versus MainMenu and MenuItem). There are some pretty nice owner-drawn menu classes out there that mimic the OfficeXp style, and some that are very customizable. I've written my own after looking through a tutorial on the subject. I can post it if you like. (It is actually a single, self-contained code file.) You can also search google for Xp-style menu controls.
  14. The easiest way to find the cause of a stack overflow is to look at a stack trace, whether in the IDE or a logged exception (if you manage to log a stack overflow exception).
  15. Almost any aspect of any object can be handled dynamically through reflection. Functions can be called dynamically because we can pass parameters in an array. We can access properties and fields and instantiate classes. We can discover base classes and interfaces. But is there a way to dynamically handle events? To receive parameters as an array from an event in the same way that we would pass them to a function using reflection, or anything to that effect? I'd like to avoid is compiling and creating assembies during runtime. It seems as though it could get pretty bulky if I need to handle a very large range of event types. I will need to create them as I need them, which means that if I have 50 event types I would need to emit 50 dynamic assemblies. I suppose I could optimize by creating and saving an assembly that contains all encountered event types when the app closes (basically caching them all in a single DLL) so that next time I will have far fewer assemblies, but it still seems to be a bit much.
  16. Denaes, I think the real benefit to the online/wiki book is the benefit to others rather than oneself. And I think that the best way to decide is to just think about it in terms of your priorities. I don't think that you are necessarily restricted to one solution or the other, although it would be quite a project to manage both at the same time and maintain them as completely separate works. If your biggest concern is your financial situation or the state of your resume, by all means go with the book. I've looked at your website, and I have no doubt that you can do it, and there will always be more chances to contribute to the programming community. On the other hand, if your ideals are a high priority, make the online book. I think that a programming tutorial wiki of some sort would be a very good way for users of all different skill levels to interact and cooperate.
  17. If it is true that the .Net Random class is not very "random," it hardly matters in the context of picking a random song. The only time this might ever be an issue is in some sort of scientific or mathematical application.
  18. I think your best bet might be managed DirectX. It takes a little effort to learn, but it's not that hard and it is a very useful thing to know.
  19. Components and controls should be disposed automatically when the form is disposed. If you don't call Form.Dispose explicitly the form's finalizer should do it for you (but, of course, that is a fallback).
  20. Application.Exit (like End in VB6) is considered bad practice. The correct way to end an application is to get to the end of your Main, which, like wraith said, is done by closing your main form, which returns control to your Main. According to MSDN, Application.Exit does not actually abruptly force the program to terminate. It tells all message loops to terminate and after they finish processing messages all the windows are closed. This naturally causes Application.Run to return control to your Main, allowing the program to terminate. All finalizers should be closed, and fall-back finalizers should still call the appropriate Dispose methods for you. In version 2.0 of the framework, you can actually stop the application from closing by handling the Form.Closing event and setting e.Cancel to true. This is probably a bad idea, though, since the order that forms are closed is most likely undefined, which means you never know which forms will be left open and which ones won't.
  21. Does it slow down other processes and threads? If you use another application while the CPU usage jumps up what happens?
  22. Exceptions rock my world.
  23. I don't know didly about databases, but I've never seen || mean anything except "or".
×
×
  • Create New...