Help with loading external resources PLEASE!!!!!!!

Jul 30, 2010 at 3:23 PM

I'm hoping that someone please responds to this post. I've been developing with Silversprite for over 6 months now, and i really need some answers. It seems NO ONE reponds on this forum and there really are no answers anywhere else on the net.........mostly because Silversprite's functions are only half-working.

How can you load images or audio from a dll, assembly, or another project.....to use in your silversprite project?

Reason for this is my XAP is too big, and I'd like to load resources from outside my project.

I have tried every single available method: Creating an assembly, assembly.Load, WebClient, HttpRequest, Texture2D.FromFile.........

But it seems EVERY TIME i use one of these methods, it can never find my filepath or some type of error pops up.

 

If someone has a solution that WORKS in silversprite, PLEASE let me know!!! I would even consider paying for you help! How does a quick $50 sound??

Developer
Jul 30, 2010 at 10:27 PM

Hi

I actually see all the posts in the discussion on this project, I just don't know the answer to all of them or have the time to look into, sadly.

I understand your problem, but is this problem SilverSprite related? I mean, loading in assets from "the out side", isn't that more of a Silverlight question? Have you tried look over at the Silverlight forum for an answer to this? Have you tried doing a very simple Silverlight project where you try it out first, before including it in your game project?

Don't get me wrong here, I mean all these questions in the best way. :)

Jul 31, 2010 at 7:51 AM

Yes I have searched the MSDN, the silverlight forums, gamedev.net, and all over here. What I mostly meant is that Texture2D.FromFile would be the biggest help here, but most all of those variations aren't implemented. And WebClient, you have to be connected to a server before it will actually work........but then I can't debug my errors.

I have a solution with a website project and my silversprite project - the web project is referencing my silveright app, and has the XAP in the Clientbin folder. I placed an image in my clientbin folder. FROM MY SILVERLIGHT app, in the MainPage.xaml, I try to create an image or bitmap image:

BitmapImage bitmapImage = new BitmapImage(new Uri("BlueClouds.jpg", UriKind.Relative));

From everything I've read on the net, this SHOULD work if your image is in the ClientBin folder on the same level as your XAP. It does execute, and the ImageFailed event is never fired, but if you look at the URI source, it every part of the image threw an exception of "'System.InvalidOperationException."

If I try to create an Image using this bitmap image as a source, it says "Object reference not set to an instance of an object."

So I'm truly wondering if this is a silverlight or silversprite issue?

Aug 4, 2010 at 10:14 AM
Edited Aug 4, 2010 at 10:16 AM

I wanted to post my solution for this problem, in case anyone else needed help.

In my particular situation, I've created a huge game with many sounds, images, and xml files. In total all my content came to about 80 MB, with all my content inside the XAP file. Yeah, ouch....it took perhaps 1-2 minutes to actually load on my website before you could start playing. Of course if you want to make browser games with silverlight, this loading time would prevent most people from even trying the game.

The solution: place all of your textures, images, xml files, content whatever into a "Silverlight Library Application." Then you can reference your content from the library .dll, not your XAP.  This brought the size of my XAP down to 8MB - still big, but much better loading time for a game :)

Here is the example I found online after weeks of searching: http://www.silverlightexamples.net/post/Load-Bitmap-Image-From-Resource-in-a-Single-Line-of-Code.aspx

It did exactly what I was looking for.

So, now that all my images and sounds were in the library, I can load them into my silverlight project using this code:

 System.Windows.Media.Imaging.BitmapImage myBitmap = ResourceHelper.GetBitmap("ImageFiles/MyImage.png", "SilverlightClassLibrary1");
                Texture2D myTexture = new Texture2D(myBitmap, GraphicDevice.GraphicsDevice, new Vector2(100, 100), "MyImage.png");

 And there you have it. The "ResourceHelper" in my example above is a special class, included in the link I provided.

Hope this helps someone!


Developer
Aug 4, 2010 at 12:23 PM

Great to hear you found a solution and thanks for posting it in here :)

Aug 4, 2010 at 8:44 PM

OKAY another edit:  Even though the above method DOES put all your images/sound/content into a different project, and compiles it into a .dll, there is still a problem. Inside my silverlight app, you must "Add Reference" to this .dll to actually use it. And well............this .dll ALSO gets included into your XAP file, making your XAP exactly the same size as it was before......in my case huge.

Well poo.

So here is another extended, crazy solution THAT IS CONFIRMED TO WORK. I used the sample code at this website: http://www.silverlightshow.net/items/Silverlight-Dynamically-Loading-an-Assembly.aspx

Now in my visual web solution file, I have a website project, I have my silverlight project, a library project for my assets, and now a NEW library project as an "Interface". Think of it as a middle-man between my assets and my silverlight app.

So in this new library project, I place one new file where I create an "interface" class, just like the "Interfaces" project mentioned in the link a couple lines above. Here is my code:

 public interface ITexture
    {
        BitmapImage GetBitmap(string _filePath);
    }
Wow isn't that amazing. NOW I go back to my asset library project. Here I place my "ResourceHelper" file (as mentioned in the previous post) and 
create a new file that will inherit my new interface:
 
public class MyTexture: ITexture
    {
        public MyTexture():base()
        {
        }

        public BitmapImage GetBitmap(string _filePath)
        {
            BitmapImage tempBitmap = ResourceHelper.GetBitmap(_filePath, "AssetLibrary");
            return tempBitmap;
        }
    }
In this example, the filepath is relative to the asset library project (meaning, your images must be placed in this project to be accessed). Please look toward my previous 
for information on the ResourceHelper.
Remember you need to "Add a Reference" to your "Interface" library project. That's the only way you'll get access to "ITexture" 
(or whatever you decide to call it)
So now, we need to open the assembly (.dll of the AssetProject) inside your SILVERLIGHT PROJECT to actually use it.
First, "Add a reference" to your interface project.
Secondly, go to the "Page.xaml.cs" file. Here is some code:
public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Page_Loaded);
        }

        private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            WebClient client = new WebClient();
            client.OpenReadCompleted += OnAssemblyOpened;
            client.OpenReadAsync(new Uri("AssetLibrary.dll", UriKind.Relative));
        }

        void OnAssemblyOpened(object sender, OpenReadCompletedEventArgs e)
        {
            AssemblyPart assemblyPart = new AssemblyPart();
            System.Reflection.Assembly assembly = assemblyPart.Load(e.Result);
            // The string I'm passing in here has this format: namespace.className 
            // (namespace of your asset library project, name of your class that implements the interface)
            ITexture tempTexture = assembly.CreateInstance("AssetLibrary.MyTexture") as ITexture;

            BitmapImage thisBitmap = tempTexture.GetBitmap("Textures/MyAwesomeImage.png");

        }
    }
Woot, now you can load images WITHOUT having to include them in your XAP file. BUT PLEASE NOTE!!!!
YOU MUST MANUALLY COPY your "AssetProject.dll" (whatever you name your asset project file) and PASTE IT IN THE CLIENTBIN FOLDER
OF YOUR WEBSITE PROJECT. Your XAP file and this asset .dll must both be in the clientbin folder of your website project to actually work.
I tried to create this method a couple times and it took me days to get it right. So I hope this code can help someone too!