Deprecated: The behavior of unparenthesized expressions containing both '.' and '+'/'-' will change in PHP 8: '+'/'-' will take a higher precedence in /home/iano/public_html/tpforums-vb5/forum/includes/class_core.php on line 5842

PHP Warning: Use of undefined constant MYSQL_NUM - assumed 'MYSQL_NUM' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_ASSOC - assumed 'MYSQL_ASSOC' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_BOTH - assumed 'MYSQL_BOTH' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 588

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 612

PHP Warning: Use of undefined constant misc - assumed 'misc' (this will throw an Error in a future version of PHP) in ..../global.php(29) : eval()'d code(6) : eval()'d code on line 1

PHP Warning: Use of undefined constant index - assumed 'index' (this will throw an Error in a future version of PHP) in ..../global.php(29) : eval()'d code(6) : eval()'d code on line 1

PHP Warning: Use of undefined constant misc - assumed 'misc' (this will throw an Error in a future version of PHP) in ..../includes/class_bootstrap.php(1422) : eval()'d code(4) : eval()'d code on line 1

PHP Warning: Use of undefined constant index - assumed 'index' (this will throw an Error in a future version of PHP) in ..../includes/class_bootstrap.php(1422) : eval()'d code(4) : eval()'d code on line 1

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 85

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 85

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6
A plea for information - Page 2
Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 26

Thread: A plea for information

  1. #11
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Quote Originally Posted by Sketchy View Post
    First with that particular implementation you should ideally pass the Graphics object as a method argument, that way you only have to instantiate it once outside your drawing code which greatly reduces the native interop overhead taking place within the FromHwnd method. But despite this using FillRectangle definitely isn't a fast method of doing this but is pretty much the only option with the Graphics class, but there are alternatives.

    The easiest one would be to create a Bitmap object, which includes Get/SetPixel methods, with the same dimensions as your picture box and set it to the box's Image property which it internally draws as the background within its OnPaint method before calling any attached OnPaint event handlers. When you want to draw a pixel just call Bitmap.SetPixel, more advanced drawing routines can be done by creating a Graphics object from the bitmap as well. When done drawing call PictureBox.Refresh/Invalidate to make it undergo a repaint, and like said the image will be automatically drawn.

    Code:
    // Only need to create once after your picture box has been created
    Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
    Graphics bmpGraphics = Graphics.FromImage(bmp);
    
    pictureBox.Image = bmp;
    
    
    // Drawing routine, don't bother creating a Graphics object for the picture box since it's not needed
    bmpGraphics.Clear(Color.Black);
    
    bmp.SetPixel(256, 256, Color.White);
    bmpGraphics.DrawLine(Pens.Red, 32, 32, 64, 64);
    
    pictureBox.Refresh();
    
    
    // Best to explicitly dispose of these (and any other unmanaged resources like brushes/pens too) when no longer needed.
    // If you forget they won't be disposed until the GC kicks in and calls their finalizers, really shouldn't rely on this though.
    bmpGraphics.Dispose();
    bmp.Dispose();
    You can achieve even better performance by using Bitmap.LockBits for your pixel manipulation, this returns a pointer to the pixel data buffer which you can access directly using an unsafe pointer or using the System.Runtime.InteropServices.Marshal class (unsafe pointer being fastest obviously). One drawback is that you cannot use the Bitmap within any of the Graphics methods whilst locked, you will need to unlock first. In my tests even the worst-case scenario of setting only a single pixel between the lock/unlock surprisingly achieves better performance than using Bitmap.SetPixel, and the performance gains will only continue to rise as you increase the number of pixels you are manipulating within the locked block. If you are interested in LockBits I suggest taking a look at Jo3's sprite file structure thread which copies the pixel data into a local array with Marshal.Copy (cut his entire read time down to 3.5~ seconds from 35~ seconds with SetPixel, only slightly slower than using an unsafe pointer), and you could look at my example attached here which includes doing it with an unsafe pointer or with the Marshal.Read/Write* classes (slowest method of the 3, still much faster than SetPixel though). I would suggest creating your own bitmap class that creates an internal Bitmap and Graphics object and expose only what is necessary, similar to what I had done in my program.
    Out of interest, would you advise drawing maps on init to a bitmap file, and storing that file on the HDD, then refreshing it each time the software boots? Or would this cause too many issues with unexplored map? I think it might be a useful idea personally, since it would save constantly reading map files and could potentially reduce my overall CPU usage by 50% (at the minute the map reading alone is using quite a large amount of CPU...)

    I'll give this a shot now, and will let you know the results of it. Thanks again <3

    Edit: Can't seem to find PixelFormat - should I be importing a new class for this?

    Edit 2: First google result was correct, fixed. My bad.

    Edit 3: Holy fuck that's quick. It was taking 3-4 seconds to draw the thing using DrawPixel (my old method), but using bmp.SetPixel is quicker than I can describe, it just happens instantly. Awesome shit dude, thanks!
    Last edited by XtrmJash; 02-09-2013 at 01:59 PM.

  2. #12
    A few tips to help optimize

    1. Background color

    Play around with a background color. Before drawing, iterate over the map file and determine the "majority color," then when your create your bitmap, make that the pre-drawn background color. In your setPixel() loop, work as normal but ignore the majority color. To make this as fast as possible, you can make an array of WORD (int16) that has 256 elements. When doing your initial pass, just do colorCounts[color]++ for each tile. When you have a map that is a majority black or green, for instance, this will works amazingly. For maps that have many colors in somewhat even distribution, this wont be as fast but can;t be much slower (if at all) then your current method.

    2. Chunking

    This may or may not be faster, I'm just speculating. This requires you to have a graphics object instantiated on your image to draw on it. When looping through colors in the setPixel() loop, keep track of the last color and only draw once either your y coordinate changes or the color changes. This will make many of your drawing calls look like drawRectangle(1, occurrences, x, starty, color), where 1 is width (always 1), occurrences is the number of repeats (height), x is the x coordinate, starty is the y coordinate where the repeat started at, and, of course, color is the color.

  3. #13
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Quote Originally Posted by DarkstaR View Post
    A few tips to help optimize

    1. Background color

    Play around with a background color. Before drawing, iterate over the map file and determine the "majority color," then when your create your bitmap, make that the pre-drawn background color. In your setPixel() loop, work as normal but ignore the majority color. To make this as fast as possible, you can make an array of WORD (int16) that has 256 elements. When doing your initial pass, just do colorCounts[color]++ for each tile. When you have a map that is a majority black or green, for instance, this will works amazingly. For maps that have many colors in somewhat even distribution, this wont be as fast but can;t be much slower (if at all) then your current method.

    2. Chunking

    This may or may not be faster, I'm just speculating. This requires you to have a graphics object instantiated on your image to draw on it. When looping through colors in the setPixel() loop, keep track of the last color and only draw once either your y coordinate changes or the color changes. This will make many of your drawing calls look like drawRectangle(1, occurrences, x, starty, color), where 1 is width (always 1), occurrences is the number of repeats (height), x is the x coordinate, starty is the y coordinate where the repeat started at, and, of course, color is the color.
    I can see both of these being optimal for the performance side of things, I'll work on the background colour now as a matter of fact, it seems it could actually take a huge amount of resources away from this relatively useless rendering.

    I'm yet to link the map information to the current player position, but I will be working on that next. So far I've managed to read and display map info using WPF and WinForms, so I'm pretty happy this weekend! I'm gonna work now on obtaining the correct map file for my current location, then I'll build an array of 9 "useful" map files, which will be the ones around me, so I can work out paths at least 256 sqm away... I think this limit is feasible using a well written search algorithm, though I might advise people not to go above 100 or so squares, since it would be pretty insane to do so :P

    Next step: Work out how to do the background colour (might be able to just blanket, but might have to use drawpixels or some plural of drawpixel... not sure yet, got some research to do!)

    Edit: Now I've managed to blanket the background and ignore anything which I don't then need to draw due to the background changes. Marvelous! Time to get to work on reading the next chunk of bytes, and drawing another image to show walk speeds, then I guess I'll have to create some struct for map tiles, generate an array of said struct, and begin the long process of sorting the data as I need it for my search algorithm... Which I'll also have to squeeze in there at some point.
    Last edited by XtrmJash; 02-09-2013 at 08:23 PM.

  4. #14
    Senior Member
    Join Date
    Jan 2012
    Posts
    417
    Quote Originally Posted by ManInTheCave View Post
    ... so I can work out paths at least 256 sqm away... I think this limit is feasible using a well written search algorithm, though I might advise people not to go above 100 or so squares, since it would be pretty insane to do so :P
    ...
    there is a hidden idea inside A* that if you find it, your algorithm for 2D-tile based games will run near O(#path * #neighborhood) operation when you are able to find a path, of course. For games like Tibia, each tile has #neighborhood <= 8.

    The worst case is near O(#grid)
    Last edited by Blequi; 02-09-2013 at 09:15 PM.

  5. #15
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Quote Originally Posted by Blequi View Post
    there is a hidden idea inside A* that if you find it, your algorithm for 2D-tile based games will run near O(#path * #neighborhood) operation when you are able to find a path, of course. For games like Tibia, each tile has #neighborhood <= 8.

    The worst case is near O(#grid)
    LOL <= 8

    but seriously dude, that just flew straight over me. Fancy simplifying or expanding on it?

  6. #16
    Senior Member
    Join Date
    Jan 2012
    Posts
    417
    it's an estimate I've made, not so accurate because I didn't take into account O(ln n) inserting in the priority queue. But I can assure you, if you attempt to the VISIBLE problem, your pathfinder will beat 99% in speed other pathfinders.

    it's only a implementation detail that nobody pay attention to the problem. And you can SEE the problem, that's incredible.

  7. #17
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Quote Originally Posted by Blequi View Post
    it's an estimate I've made, not so accurate because I didn't take into account O(ln n) inserting in the priority queue. But I can assure you, if you attempt to the VISIBLE problem, your pathfinder will beat 99% in speed other pathfinders.

    it's only a implementation detail that nobody pay attention to the problem. And you can SEE the problem, that's incredible.
    Are you talking about chopping the map up into chunks, then looking if the chunks are connected? I seriously don't understand a word you're saying at the minute mate, I've not started writing the algorithm yet, and have never written one before, so I'm pretty newb to it. I'll be doing my best though, just bare with me if I ask silly questions! lol

  8. #18
    Senior Member
    Join Date
    Jan 2012
    Posts
    417
    my bad, I though you had a working A*.

    But when you get your A* working, draw your results in a forms. Personally, I save a "Pathfind State" containing all info about the search (grid, open set, closed set, path, turns it got, time spent, ...). This way I know exactly what is going on.

  9. #19
    Quote Originally Posted by ManInTheCave View Post
    Are you talking about chopping the map up into chunks, then looking if the chunks are connected? I seriously don't understand a word you're saying at the minute mate, I've not started writing the algorithm yet, and have never written one before, so I'm pretty newb to it. I'll be doing my best though, just bare with me if I ask silly questions! lol
    He's talking about the estimated time to run. What he is using is called Big O Notation, which shows asymptotic complexity of the algorithm given its inputs.

  10. #20
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Quote Originally Posted by DarkstaR View Post
    He's talking about the estimated time to run. What he is using is called Big O Notation, which shows asymptotic complexity of the algorithm given its inputs.
    Bookmarked that, will take a look once I have a better understanding. At the minute I'm getting some strange behavior, for some reason my current position doesn't line up with the minimap file... I think I've mistyped something somewhere so I'm stepping through every single piece of code to find it lol

    I'll elaborate a little in case someone gets some time to offer a brain:

    In Lizard City cast I read address using my Walker tab, and it gave an address which was on the Map Data list (This is good!) It did the same in Farmine depot, and the tile speed matched, though I can't be sure on the tile colour I'm pretty sure that did too.

    In Yalahar I'm getting a value from memory of 32791, 31244, 7. The map file, however, is returning from 32256 to 32511, 32768 to 33023, and of course 7...

    This is just strange, why does one appear to work and the other not, hmmm... I'd think it could be some multiplication... The map file I'm reading is 12812207 (32768 to 33024, 31232 to 31488, 7). So yeah, it must be my calculations going wrong somewhere... I'll take a look. I love this cardboard engineer idea, it's fucking immense.

    Found the issue. I was reading a map file based on a textbox in one place, and reading one based on current location (getting the map file for my position in game) for the other... That was annoying as hell.

    Thanks again.

    Now feels like I've crashed into the wall that is A* search algorithm. I've spent 2 hours~ reviewing code from CodeProject (There is an example there in C#), and I just can't get my head around it! Oh well, time to get to sleep. Will keep trying at this for a few weeks I guess, and see how I get on. How hard can it be?
    Last edited by XtrmJash; 02-10-2013 at 01:31 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •