Jump to content
  • Advertisement

Verg

Member
  • Content count

    755
  • Joined

  • Last visited

Community Reputation

450 Neutral

About Verg

  • Rank
    Advanced Member
  1. Verg

    Lightning Bolts

    Very nice job there. I'm in awe. Well... of course, it just so happens that our game is calling for lightning <parenthesis> wink </parenthesis> ... and I happened upon your nice article. I understood it well, and have been able to implement it about 90 percent satisfactorily (as much as possible in XNA). Unfortunately (yes) I'm running into a strange blending problem with XNA... even with alpha blending turned on (explicitly) RenderStates, yadda yadda... and this is how the lightning bolts are looking: Of course, I think you explained how to take care of this by moving vertex strips over the normals or something... and this is where I lost consciousness :D Or at least the eyes started to glaze over. If you have a moment, might you care to explain to someone with a pea brain how to do this? Thanks! Chad
  2. Verg

    Juggling

    How many of you are juggling right now? Not tossing balls around, but juggling school and work. Oy, this stuff is tough. Gevalt, even. Next rhetorical question: how stupid is it to take 19 credit hours with a full-time job? On the plus side, I'm a full CS major now; going through CS3500 (software practice). It's funny to see all the poor java-lings struggling with C++ [smile]
  3. Verg

    2nd Year of University

    Hey... Welcome young sir to the land of the journals. Please keep your seatback and traytable in the upright and locked position until we have reached our cruising altitude of 35,0000 feet, and the captain has turned off the fasten seatbelt sign. C
  4. Verg

    Under the Radar

    All right... you want TDD? You got TDD. I've written a semi "tutorial"... (more of an "example") of a TDD session. Parts I & II of my new TDD Example are now online. Sample code, galore! Please tell me if you find any errors, or parts that don't make sense to you. There will be at least two more parts to the example, when I can work them in between work and school. Thanks a million! Soon I'll finish a RANT about new school games begun on a different developer's journal, as well... Chad
  5. Verg

    Why Do People Hate Graphics?

    You must be from the new school [smile] What you say rings true; however, I'm old school as they get. I feel like when the "3D barrier" for video games broke, and broke hard (sometime in the early 90s) games for quite some time were really shitty. That, coupled with the new idea (for arcade machines) that you could just add more quarters to finish a game, or (for consoles) that you could put in cheat codes... made games less of a challenge and more a way to pass the time. Consequently, arcade machines died out ... because you couldn't conquer one on a single quarter any more. There was no more "air of mastery" of feeling of accomplishment, cuz any shlub with $50 bucks in his pocket could just shrug his way through the game without any skill. I think these factors, combined with the overwhelming rush of game makers to embrace 3D technology left a whole culture of video-game players out of the loop... but enticed a different kind of "player" to join up. Sports sims and simulation-based games kind of rocketed from there... and your skill-based side scrollers went tits up. I lost all desire to play or write video games when 3D started taking everything over, because the emphasis on graphics was so heavy. In my day (says Grampa) you could play a game called "Qix" at the arcade, and it was just a bunch of raster lines with about four colors... and you'd dump quarter after quarter into the machine because it was fun. There was a challenge to it. You could actually gain a mastery level over these sorts of games that didn't require just another roll of quarters, or another cheat code. The initials you typed in after winning the game on a single quarter meant something... they were there for all the wannabes to see. I guess this is sort of a mini-rant... will probably pick it up in my own journal at some future time. But I do see what you're saying; there's no reason why people should just hate on graphics. Chad
  6. Verg

    A Simple Test

    Fails on firefox 1.0.7
  7. Verg

    Can't even google it

    You sir win an internet. Use it wisely.
  8. Verg

    Part of the Pain (part I)

    Fuzzy no-dice Well as promised, I recorded my last TDD session on tape. Unfortunately NOT as promised... it is undeliverable as is... er... the words were too fuzzy (analog VCR tape... shoulda known). I was hopin to have a nice y00t00b link or something today... oh well [smile] If I weren't getting ready to go back to The U of U CS School, I'd have this done already. What I will do is watch the tapes and put everything down on paper ... and then HERE... for you instead. In written form. Some Big, Fat Policies We're done with the "Tile Loading" iteration, and ready for some integration testing now. Just to give you a TASTE of the pain that is "policy-based" design... here is the exact rough-up of the typedefs we'll have to use to get our newly TDD'ed objects off the ground: typedef MS::dx::ddraw::Tile tile_t; typedef bawd::graphics::_TileSet tileset_t; typedef MS::dx::ddraw::TileImplCreator tile_impl_creator_t; typedef MS::win32::graphics::bitmap::GetSourceBits get_source_bits_t; typedef MS::win32::graphics::bitmap::ParseHeader parse_header_t; typedef MS::dx::ddraw::bitmap::ConvertHeaderToScreen convert_header_t; typedef MS::win32::graphics::utility::ConvertPixelToX1R5G5B5 convert_pixel_16_t; typedef bawd::graphics::utility::colors::Bit24Alpha bit_24_alpha_t; typedef bawd::graphics::utility::colors::OpaqueAlpha opaque_alpha_t; typedef MS::win32::graphics::bitmap::GetPalette get_palette_t; typedef MS::win32::system::api::callers::LoadLibrary_ load_library_t; // not tested typedef MS::win32::system::api::callers::FreeLibrary_ free_library_t; // not tested typedef MS::win32::system::api::callers::memcpy_ memcpy_t; // not tested typedef MS::win32::system::api::callers::FindResource_ find_resource_t; // not tested typedef MS::win32::system::api::callers::LoadResource_ load_resource_t; // not tested typedef MS::win32::system::api::callers::LockResource_ lock_resource_t; // not tested typedef MS::win32::system::api::callers::DeleteObject_ delete_object_t; // not tested typedef MS::win32::system::policies::_OpenDLL open_dll_t; typedef MS::win32::system::policies::_CloseDLL close_dll_t; typedef MS::dx::ddraw::_DataBlit data_blit_t; typedef MS::win32::graphics::bitmap::_CreateEmptyBitmap create_bitmap_t; typedef MS::win32::system::memory::_GetAvailableMemory get_available_memory_t; typedef MS::win32::graphics::utility::_ConvertPixelToA8R8G8B8 convert_pixel_24_t; typedef MS::win32::graphics::utility::_ConvertPixelToA8R8G8B8 convert_pixel_32_t; typedef bawd::graphics::bitmap::_BitmapBuilder bitmap_builder_t; typedef MS::win32::system::_ResourceOpener resource_opener_t; typedef bawd::graphics::bitmap::_Parse bitmap_parser_t; typedef bawd::graphics::bitmap::_ExtractData data_extractor_t; typedef MS::win32::graphics::bitmap::transform::_Flip bitmap_flip_t; typedef bawd::graphics::bitmap::_PixelConverter pixel_converter_t; typedef bawd::graphics::bitmap::transform::_BitdepthToScreen bitdepth_to_screen_t; typedef bawd::graphics::bitmap::_ConvertLoadedBitmap convert_loaded_bitmap_t; typedef MS::win32::system::resource::_GetBitmapResource get_bitmap_resource_t; typedef MS::dx::ddraw::_TileExtractor tile_extractor_t; typedef bawd::graphics::_TileLoader tile_loader_t; Yikes! Validated After a Battle Isn't it extremely weird that sometimes... that you can battle mightily for something... expecting the worst... and, after all you can do... you are proven right in the end? It was like that today when trying to "instantiate" the main monstrosity shown above (the "tile_loader_t" type). Loki en la cabeza I've been using Andrei Alexandrescu's "Loki Library" for some time now. Even found a bug that they ended up fixing once. Well... today... it seemed like Loki's "ClassLevelLockable" wasn't about to let me get away with instantiating a "tile_loader_t" without bitching and popping up one of them ugly dialog boxes (ASSERT) After tracing through... and noticing that I had had plenty of success using very similar code for Loki in the past... I felt like the problem had to be inside Loki. Divide and Divide So yeah... divide and conquer... got down to the smallest pieces I could (policy classes) and found that the assert was happening when instantiating a Loki::Functor template that used "Loki::ClassLevelLockable" as a policy. But it didn't make sense. Then one of my dumb mistakes made me realize that I wasn't really testing it right. I was actually putting test code at the end of a source file as if it were global data...... I actually tried using an "if()" statement outside of a function block... and the compiler complained. That woke me up to what Loki was actually doing. Maybe the assert inside Loki would happen if and only if you used a Functor in the global namespace. Proof positiveSo I mocked up a trivial example that tested that theory... which can be found here... and tried it out. Yep. Vindicated. The assert happened only in the global namespace outside of a function definition... in "global" variables. So I happily went back and fixed my test code so that it ran inside of a small, trivial test... and was able to get a "tile_loader_t" instantiated (woo hoo!) without any asserts. Pudding The real treat was in realizing that none of my code had to change one IOTA. I did spend a helluva lot of time tracking down Loki's dumb bug, which I submitted to them... but my TDD'ed code kicked ass all the way. On to integration!... (psst... this means I've now found TWO bugs in LOKI all by myself. I must be hella awesome [wink]) C
  9. Class reunion was fantastic. I may marry that one chick... Well, the spies have it. You'll see in the responses to the last Verg-o-nomics entry that I'd screwed up the implementation of the spies, and that's what's caused all the pain. Stubbing your foot on the inheritance tree It stands to reason that you should use 100% configurable spies/stubs so that they return 100% predictable results for the indirect inputs to your SUT ... you can even set the stubs to fail on purpose and exercise a different facet of your SUT. If, on the other hand, you're just lazy (like I was) and directly subclass the real components or "DOCs" to create your spy/stub classes, you may have to roll real test data, or your tests may crash! Tests have been much smoother so far... though I've been mostly refactoring to remove key components from classes who were delegating to too many delegatees... and consolidating them by overall responsibility into larger delegatees. You can take a peek at the actual refactoring on the Death Star whiteboard... it's the PixelConverter template being extracted from the PixelDepthToScreen template... which will be renamed 'BitdepthToScreen'. Calm waters Overall, TDD has been a calming influence and steadying force throughout... because refactoring is painless, and I know right away if I've broken something when the tests squeal. It shouldn't be too long before this is done. An experiment I'm going to experiment with putting up a step-by-step TDD session (warts and all) soon... as soon as I can figure out how to record the session (S-Video out to VCR?) and then translate it. Who knew "Tile Loading" would be the major component, in contrast to "Tile Rendering", or even "Tile Map Scrolling"? Piece, Chad
  10. Verg

    Does your brain hurt too?

    Quote:Original post by gutzofter It is good that you are working your way through the testing paradigm. Is there some way to get a copy of your source code? I'm interested in testing graphic renderers. I would like to see some code to see if TDDing one makes it easier to unit test the code that utilizes the renderer. Hey Joe... Sorry I didn't get back to you right away (class reunion over the weekend)... I can't release the code to you (not mine [smile]) but I've been thinking about showing an example (step by step) of what I'm doing, including the building of spies/stubs (which example is sorely lacking on the web or in print, IMO). I'll have to figure out how to capture a session (VCR?) and then I'll translate that to print and put it here for you. Thanks again. Chad
  11. Verg

    Does your brain hurt too?

    Quote:Original post by gutzofter Hey Verg, Sometimes when TDDing and I run into this type of problem. I stop and remember to ask, what am I doing? What is the intention of the SUT, not what is the implementation. How come you need a class that acts like a facade for your aggregates. Maybe something else is screaming to get out? Did you just say to your self I need to have this class? Hey thanks for the insight, gutzofter... its quite helpful. The intention of the "software", in this case, was to take a raw bitmap and convert it into a "useable" bitmap... meaning 1) flip it 2) convert it to the current screen res. There are several sub-responsibilities... and those mapped to separate classes. But the "glue" code, in this case, is what delegates these responsibilities... the "BitmapTransform" class, if you will. Quote:This is what they say is is BUFD writ small. I'm not saying that your shouldn't do this, but it can trap you into making a least effective design decision. Something the Continuous Integration Crowd talks about, is that you always turn in your code at the end of the day only after your tests pass. If you can't do that. Just delete the code and start over the next day. Wow... guess that works :) Quote:For me, if it's not the end of the day I will delete the code and go someplace else for a bit. Maybe look to refactor my code base. Spend 15-30 minutes refactoring, then go back to writing the code again. Hope this helps! Surely it does. However, I think my problem can be traced directly back to not using stubs/spies correctly. Instead of fully controlling the outputs and inputs of the stubs, like I should have, the stubs were subclassed from the real components, (meaning the SUT would call actual components instead of spies through virtual functions) ...making my unit tests more into integration tests... because I had to come up with real data to feed in! I had to fake some bitmaps at 16-bits, for instance, and then come up with real "result" bitmaps at 32-bit, for instance. THAT's what took so long. I retraced my steps a bit these last couple days... and created FULL spies that are fully configurable to 1) record all their inputs and, based on the inputs 2) return a value that I've set up for the input. (std::map takes care of the mapping). This (of course) means I can feed the spies complete nonsense data... (which is much easier)... because all that really matters is what the SUT does with those indirect inputs/outputs. The work seems to be much easier when it's more configurable like that. There are still some tricky bits... like how to "sense" through mock APIs... ("memcpy", for instance)... to figure out if the bitmap was actually "flipped"... but I figured out a way to handle that. ... More in a later entry... and thanks for your input! Uprate for you. Chad
  12. Verg

    Does your brain hurt too?

    Sometimes things just get ugly. I'm TDDing a larger (delegating) class, and it got fugly. Fugly Fixtures First of all... I tried to set up too complicated a fixture, I think, and it took way too long. The reason why? I think the cause of the problem was I was trying to use "pseudo-real" data to drive the tests. But it doesn't seem to work when talking about "delegator" types, because the inputs and outputs for delegators should actually be simpler...... I *think*. I believe what ended up happening was the creation of Integration tests instead of unit tests, because in the end the data I was feeding in was meant to elicit proper outputs from delegatees instead of just the SUT (the delegator). Who's driving this bus? I'm confused, though, as to what to think. TDD is supposed to drive the development of your "system under test". In this case, I'm talking about a delegating class that either aggregates, or has as policies previously TDD'ed classes/components. What does this mean about using "specific examples" to drive development, in this case? In other words... what type of "specific example" would be needed to TDD a delegator type? Do I need to just fall back and test that the "depended-on components" are called, through stubs/spies/mocks? ? ? ? I realize the end result *should be* an algorithm in code form, which utilizes the delegatee classes. There's just a disconnect in my brain somewhere about what type of "specific example" would drive this development. Sigh. And I leave for Philadelphia tonight at 10PM.
  13. Verg

    Never... never log out

    This stuff is starting to sink into the old coconut... Beware the inputs... of March It seems pretty common when doing TDD that you forget some of the inputs for the CUT (class-under-test) that you are working on. I learned this lesson: Dependency injection works. Think about it. If your class needs some data to operate, where is it going to get the data? Either it is born with it, you give it to it through other means, or it finds it itself. Now if the class is an atomic structure; that is, it has few external dependencies (if any), it can't usually find the data for itself... unless you've gone and been ugly and used global data or a singleton. So dependency injection is the way to go. H8 teh settors Now if you're like me, you haet setters. Haet 'em. The philosophy behind hating setters is "if you need to set the data, it should have been there in the first place". But considering the scenario I just described... what's wrong with a setter? Class objects should have a single responsibility, yet no class is an island. Classes in isolation don't do very much. So the thought process was this: If instances of this CUT are created on the fly, use constructor injection If this CUT is going to persist through the life of the application, and has no external dependencies, use dependency injection through the public interface If this CUT depends on other aggregated or otherwise depended on components (DOCs), it's possible for the CUT to call one of them for its data (dependency lookup) I don't hate setters so much now [smile] Just do what it tells you to do Moving along and refactoring the resultant code proved much easier... some instance variables cleared up and disappeared, and the public interface for the CUT and some of its collaborators simplified greatly. This is the code speaking to you. If you trust it, the design of your overall framework will be happier for it. Tests multiplying like little rabbit buggers Another interesting observation is that I'm always coming up with "new things to test" in the middle of testing. An idea occurs... "Oh! What if that function gets called twice in succession? Shouldn't I test that?"... and then it is written down. When this used to happen before TDD... panic would set in, because it seemed like a destabilizing force was trying to rock the ship. Now I just recognize it as a force of emergent design... where the requirements are not fully known, nor is the architecture at test time. You have to go on discovering things... possibly way into the future... but the existing network of tests, and your greatly decoupled code make it trivial to just write one more test at any time. Look me up I glossed over it earlier in this... but let me tell you that "Dependency Lookup" was a watershed discovery yesterday. Obviously when doing TDD, you have to try to write tests in such a way that you come up with the expected behavior when you're done. I got stumped on a single test on a class that would convert a Bitmap Header into a header that matched the current screen resolution. I knew an impending hardware call was coming... because how else would you discover the current screen resolution? So how was I going to "test this in" so that the code could get the required bitdepth? Step back and let the data handle it First of all.. I decided to write a specific case... TEST ( _HeaderConverter_Retrieves32AsScreenBitdepth ) ... and then it just sort of fell into place when I realized that the object that KNEW what the screen depth was... in this case... was the stub for DirectDraw. Exclamation points. SO all I had to do was stuff the data into the stubbed DirectDraw object, and then there would be tension between the test and the hardware. Initial Test: failed. Expected 32, but was 0; change TEST code so that the stubbed direct draw object held "32" in its DDPIXELFORMAT member change production code to call IDirectDraw::GetDisplayFormat() A hard-coded "32" wouldn't have worked in this case to make the test pass, because I was using a "test-specific subclass", which is a subclass of the class you are testing... which makes it trivial to peek at the class variables and such. I could have written about 30 different tests passing bitdepths from 0 to a million in there, but in one way or another, the class would have had to make a call to the hardware which is what we wanted. Key understandings: Go from Specific To General So the key understandings I've pulled from the last few days' experience are: To write tests: Outline a bunch of specific cases and what you expect the results to beThen write a test for each You'll find that you go from a specific result (like returning "32" or something) to a much more general approach... shaped by the inputs you either send to the CUT, or by the inputs it gets from somewhere else. As an overall "mindset" when starting a TDD session... I'm trying to think this thought: "What resource do we have that could provide the inputs we are looking for? If we have it, could we mock/fake it?" *** Hah... what a ramble. A lot of words that say basically two things. Hopefully this "newb to TDD" road is useful for other clueless ones in the end. Chad
  14. Verg

    boost::random

    Cheer up. At least you're not a dirty hippie [smile]
  15. Verg

    It gets easier, it does

    Hey, there's nothing wrong with spaghetti [smile] Those dirty hippies, though... :-/
  • 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!