8626
Wow. Very interesting. And dirt cheap! I'm very tempted just to buy a license to play with~!![]()
All the money I make from the gaming industry is from other people's games. Never done any game stuff for myself before.-Renegade (January 20, 2011, 08:43 PM)
I'm thinking about it tooIf I didn't already have a hobby project, I probably would now... but I'll wait until I have time to play with it. But it's very interesting- especially looking at the games made with it. Thanks!
It should be noted that the $99 price point is only temporary, but how long the "sale" lasts and what the price will be afterward are still unknown.@Everyone, the "limited time" language is sort of up to you. We want to see how the community reacts to such a low price. We would like it to stay around for a while since we think that the price ( or some number near it) is really beneficial for our community. We're in this together-Deozaan (January 20, 2011, 08:52 PM)
Thanks for posting this clarification. So now I *really* have to think about it.-wraith808 (January 20, 2011, 08:54 PM)
However you do make a good point about the down-side of putting people under a microscope.-Stoic Joker (January 20, 2011, 07:56 PM)
I've been using my DCDisplay database which is doing 1 image a second (on average, since it has to extract them from archive), and that has been running for 24 hours. I think you should probably decode the images on 1 thread, and do the checksum on a second thread so you would only ever have 1 image being decoded at once.
I found a problem with Texture2D.FromFile (it failed with CYMK format jpg files) so when that fails I use the code belowif (imageCache == null)
{
memory.Seek(0, SeekOrigin.Begin); //Probably safest to do this
using (System.Drawing.Image image = SD.Bitmap.FromStream(memory))
using (MemoryStream bitmapStream = new MemoryStream())
{
image.Save(bitmapStream, System.Drawing.Imaging.ImageFormat.Bmp);
bitmapStream.Seek(0, SeekOrigin.Begin);
imageCache = Texture2D.FromFile(context, bitmapStream);
bitmapStream.Close();
}
}
But for your case you can just use the bitmap stream to calculate the checksum (BMP is a really simple format, and it means all the exif data has been stripped)
Neil Harding-nharding (January 20, 2011, 12:15 PM)
I'm quite sure there are many governments with major abuse.-cmpm (January 20, 2011, 07:19 PM)
Apologies in advance to my American friends Wink
http://www.youtube.c.../watch?v=fJuNgBkloFE
Why the subtitles? I guess they figured that people who watched the video would be just as lost as the people in it.-mrainey (January 20, 2011, 10:34 AM)
it is all pretty confusing...
but it does bother me that the makers obviously set out with an agenda - the maps have the countries all mislabeled - that way you can laugh at the people even if they're just reading the map...
In my experience people from bigger countries, especially better off countries, tend to be very ignorant of the rest of the world, even if it is on their doorstep, and you dont get much bigger than the US of A, but, OTOH, as KatyKaty says: of course we have no way of knowing how many smart people they had to edit out...-tomos (January 20, 2011, 04:19 PM)
"Bitmap bmp = null;"-f0dder (January 20, 2011, 08:18 AM)
If what you're saying about GDI+ is right, I may end up doing it all consecutively in a single thread. I hope not...Well, I've heard of people resorting to running one process per CPU core in order to parallelize GDI/GDI+ operations - it's per-process re-entrant, but not per-thread-in-process.-Renegade-f0dder (January 20, 2011, 08:18 AM)
For why the bitmap is constructed, and not just having memory allocated, I have that 2 posts above. (Catching up here...)Yes, and I commented that you don't need to construct the object, since you have a null-check before disposing it... so just set it to null instead of wasting time on constructing a never-used object-Renegade
As for disposing the MemoryStream, I took a look at in in reflector, and it doesn't look like there's apparent memory leaks if you don't dispose it (but there's some async I/O event cancelling in it's base Stream class) - but since it implements IDisposable, not disposing of it is an error, no matter what the current implementation does.
As for the threading: I'm not sure about the re-entrancy of GDI+, but GDI definitely wasn't re-entrant, and I have a recollection of GDI+ not being, either. This means you should never have more than one thread issuing GDI+ code... when you throw background tasks on a Threadpool, multiple tasks may run in parallel.
Wouldn't be surprised if your issues are because of two threads entering GDI+ at the same time and fucking up some internal state.-f0dder (January 20, 2011, 08:05 AM)
Mind you common sense is telling me to shutup ... But I just gotta ask...
In lines 37 - 43, why is hwi.CompareExactImageData being evaluated (basically) twice?
...
Wouldn't that tend to spike the work load?-Stoic Joker (January 20, 2011, 07:22 AM)
It's unclear code. Unless it is a property with very expensive processing behind it, it will do next to nothing except cost a few more processor cycles. And I somehow expect the CLR to be smart enough to recognise that case.-worstje (January 20, 2011, 07:28 AM)
GetBytesFromBitmap() doesn't dispose of the MemoryStream?
I agree with Worstje you shouldn't allocate the 1x1 bitmap, just set it to null - you already have a null-check in your finally-block before disposing, anyway.
Also, iirc GDI+ is not properly re-entrant, so you'll have to be pretty careful there; dunno if it has to run on the UI thread, though.-f0dder (January 20, 2011, 07:50 AM)
Also, iirc GDI+ is not properly re-entrant, so you'll have to be pretty careful there; dunno if it has to run on the UI thread, though.-f0dder (January 20, 2011, 07:50 AM)
Mind you common sense is telling me to shutup ... But I just gotta ask...
In lines 37 - 43, why is hwi.CompareExactImageData being evaluated (basically) twice?
I'm reading it as:
if(condition = false) do bla
else if(same condition is not false) do bla
Wouldn't that tend to spike the work load?
Also being that there is no trailing else, then if condition is neither true or false (which granted should be impossible) Just ignore it. < I'm guessing that part was cut out for clarity)-Stoic Joker (January 20, 2011, 07:22 AM)
That makes no sense to me, sorry. FromFile() constructs a new bitmap object and returns it for as far I can see. If it weren't ever constructed, then how could you ever use the image you loaded? Unless I am a really big noob at .NET, there is no such thing as a reference to an object that isn't constructed. There's just 'null'.-worstje (January 20, 2011, 05:28 AM)
I can't really test it, but assuming fragmentation is your problem, I think I see the problem you are dealing with. Mind you, I do not usually use GDI+, especially not in .NET, but I assume you have a good reason for using GDI+ as opposed to the System.Drawing classes. Hell, I have no clue how the GDI+ stuff is defined in that context.
Anyhow, on to what I think causes your problem. On line 29, you create a new Bitmap of 1x1 dimensions. The moment you go into the try {} block, you immediately call Bitmap.FromFile() and re-assign the value. In other words: you are creating an object you never use, and the garbage collector only collects that stuff when it feels like it - but at the same time extra objects mean less available continuous blocks. You do not need to create a Bitmap object in order to call FromFile as it is a static function. (See MSDN.) So, the solution ought to be as simple as initializing bmp to null.
I am not sure what all of your GC calls and the likes do. However, GDI+ is not managed, so I doubt tuning/prodding/abusing the GC will do very much for you in this case. But I could be wrong - I'm no .NET expert.-worstje (January 20, 2011, 03:40 AM)
Disposed instance (Ignore...)
5 types have instances that have been disposed but not GCed.
Investigate the types below for more information.
System.Drawing.Bitmap, System.Drawing.Graphics, System.Drawing.Region, DeviceContext, WindowsFont
Instance queued for finalization (Ignore...)
One type has instances that are queued for finalization. This can indicate that a Finalizer method is stuck, which will prevent instances from being finalized and cause memory leaks.
Investigate the type below for more information.
DeviceContext
Pinned instance (Ignore...)
3 types have instances that are pinned in memory.
Investigate the types below for more information.
System.Object, System.Object[], System.String
Instance indirectly rooted by finalizer queue (Ignore...)
2 types have instances that are indirectly rooted by the finalizer queue. This can indicate that a Finalizer method is stuck, which will prevent instances from being finalized and cause memory leaks.
Investigate the types below for more information.
System.Collections.Stack, System.Object[]
Large instance (Ignore...)
2 types have instances that are located in the large object heap.
Investigate the types below for more information.
System.Byte[], System.Object[]
Undisposed instances (unclassified) (Ignore...)
16 types have instances that have been garbage collected without being properly disposed.
Investigate the types below for more information.
SafeTokenHandle, SafeWaitHandle, System.Drawing.Bitmap, System.Drawing.Font, System.IO.BinaryReader, System.IO.MemoryStream, UnmanagedMemoryStream, ResourceReader, RuntimeResourceSet, ExecutionContext, (...)
Yeah, RPG is probably a bad idea. But what about other smaller-scale projects?
Platformer, racing games, Metroidvania (kind of a platformer), Adventure (think Zelda), etc.? (FYI I'm thinking of all of these as 2D games)-Deozaan (January 19, 2011, 10:24 PM)
In what way(s) could people contribute to a tower defense game? Obviously coders could help program, artists could make graphics, and musicians could help with music or maybe sound effects, but in what other ways would someone be able to contribute to a TD game?-Deozaan (January 19, 2011, 09:43 PM)
You can have your buttons, just don't take away my syntax! It's easier for me to keep typing inline rather than have to highlight a phrase and click a button.I don't think that's a true statement. You are more COMFORTABLE typing inline, or you PREFER to type like that. But it's not easier by any means for you, him, or any other person. There's no argument you can make to convince me that it's easier to type a word with brackets or whatever vs. clicking a single button.-wraith808 (January 19, 2011, 04:18 PM)
At the risk of sounding rude, I've heard from programmers that they use all this text editing stuff because it's easier for them. This is not true. you can't say that because the alternative (buttons) doesn't even exist! You can't say one way is easier or better when the other way is not even available! So, in my opinion, the programmers sort of lie to themselves by saying it's better this way, but it's not. What they are really saying is that it's not worth the trouble to create a button, which is true in a lot of ways. It is easier to write code (if you know it) than it is to create a button, which is essentially writing a LOT of code and going through the whole troubleshooting of it, etc. So yes, text-editing is easier compared to writing the code for a button.
But text-editing is definitely NOT easier than clicking a button. Two different things.-superboyac (January 19, 2011, 04:25 PM)