Ho realizzato in Xna un programma fantascientifico che permette la navigazione in un sistema planetario. Gli oggetti sono costruiti tramite moltissime strutture, alcune molto leggere che descrivono un pianeta "in lontananza" (modelli "Far", le cui istanze sono semplici sfere nude), ed altre molto pesanti per i grossi pianeti da sorvolare o da esplorare al suolo (modelli "Near", con milioni di primitive modellati da heightmaps e ricoperti da textures). E' impossibile postare il codice ma il riassunto del Main è qui:
codice://Namespaces using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System; using System.Collections; using System.Windows.Forms; using System.Collections.Generic; namespace Progetto_Albireo { public class My : Microsoft.Xna.Framework.Game { //Generals public static GraphicsDeviceManager Graphicsdevicemanager; ............. public static string StarType = "Progetto_Albireo.Star"; MODELLO STELLA 'FAR' (leggero) public static string TStarType = "Progetto_Albireo.TStar"; MODELLO STELLA 'NEAR' (leggero) //Worlds public static string SphType = "Progetto_Albireo.SphWorld"; MODELLO PIANETA 'FAR' (leggero) public static string SphHType = "Progetto_Albireo.SphHWorld"; MODELLO PIANETA 'NEAR' (molto pesante) ..... ecc. //FUNZIONI DI UTILITY public static float VelocityAt(float G, float M, float d) { return (float)Math.Sqrt(G * M / d); } .......... ecc. //METODO CHE INIZIALIZZA IL SISTEMA public void InitSystem() { Planets.Add("A", new Star(...); Planets.Add("B", new SphWorld(....); ................ ecc. } public My() { //costruiamo un nostro GraphicsDeviceManager //la sua proprietà più importante è il GraphicsDevice Graphicsdevicemanager = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { Spritebatch = new SpriteBatch(GraphicsDevice); ........... ecc. base.Initialize(); } protected override void LoadContent() { Background = Content.Load<Texture2D>("back"); ............. ecc. InitSystem(); } protected override void Update(GameTime gametime) { My.Discovery.Depthlist.Clear(); LISTA DEGLI OGGETTI IN ORDINE DI DISTANZA DALLA CAMERA (astronave) TStar.H1("A"); METODO STATICO CHE TRASFORMA "A" DA 'Sta'r IN 'TStar' SE CI SI AVVICINA TROPPO E LO RIPORTA A 'Star' SE CI SI ALLONTANA; AGGIORNA LA Dephtlist SphHWorld.H1("B", 0f, Vector3.Zero); METODO STATICO CHE TRASFORMA "B" DA 'SphWorld' IN 'SphHWorld' SE CI SI AVVICINA TROPPO E LO RIPORTA A 'SphWorld' SE CI SI ALLONTANA; AGGIORNA LA Dephtlist .......... ecc. } protected override void Draw(GameTime gametime) { GraphicsDevice.Clear(Color.Black); string T; foreach (KeyValuePair<double, string> item in Discovery.Depthlist) { double d = item.Key; string k = item.Value; T = My.Planets[k].GetType().ToString(); if (T == My.StarType) { Star x = (Star)Planets[k]; x.Draw(GraphicsDevice); } else if (T == My.TStarType) { TStar x = (TStar)Planets[k]; x.Draw(GraphicsDevice); } else if (T == My.SphType) { SphWorld x = (SphWorld)Planets[k]; x.Draw(GraphicsDevice); } else if (T == My.SphHType) { SphHWorld x = (SphHWorld)Planets[k]; x.Draw(GraphicsDevice); } else if ........... ecc. } } } }
Il cuore del programma è il metodo statico H1 che opera la trasformazione da "Far" a "Near" e viceversa. Questo è il riassunto:
codice:public static void H1(string k, float FM, Vector3 L) { if (My.Planets[k].GetType().ToString() == My.SphType) { SphWorld x = (SphWorld)My.Planets[k]; Vector3 d = My.Discovery.Position - x.Location; //costruisce la collection di profondità double D = Math.Sqrt((Math.Pow(d.X, 2) + Math.Pow(d.Y, 2) + Math.Pow(d.Z, 2))); My.Discovery.Depthlist.Add(-D, k); ... //Solving if (d.Length() < x.Ehorizon) SphHWorld.Solve(k); 'TRASFORMA x NEL TIPO 'SphHWorld' } else { SphHWorld x = (SphHWorld)My.Planets[k]; Vector3 d = My.Discovery.Position - x.Location; //costruisce la collection di profondità double D = Math.Sqrt((Math.Pow(d.X, 2) + Math.Pow(d.Y, 2) + Math.Pow(d.Z, 2))); My.Discovery.Depthlist.Add(-D, k); ... //Unsolving if (d.Length() > x.Ehorizon) SphHWorld.Unsolve(k);'RIPORTA x IN AL TIPO 'SphWorld' } }
Ecco in dettaglio i due metodi "decisivi" richiamati da H1:
codice:public static void Solve(string k) { ......... My.Planets.Remove(k); My.Planets.Add(k, new SphHWorld(...); } public static void Unsolve(string k) { .......... My.Planets.Remove(k); My.Planets.Add(k, new SphWorld(...); }
Per avere la piena padronanza di questo programma mi manca solo di capire bene cosa succede QUI e QUI, ma soprattutto QUI:
Non capisco un tubo di Garbage Collection. Vorrei capire se l'oggetto k in hastable viene rimosso anche dalla memoria oltre che dall'hash, e se navigando negli spazi aperti lontano dal sistema non ci sono in memoria oggetti "Near" residenti. Un oggetto SphHWorld è veramente ingombrante....codice:public static void Solve(string k) { My.Planets.Remove(k);<<<<<------------------- QUI My.Planets.Add(k, new SphHWorld(...); } public static void Unsolve(string k) { My.Planets.Remove(k);<<<<<-------------------- QUI My.Planets.Add(k, new SphWorld(...); }
Spero di essere stato chiaro. Grazie

Rispondi quotando


in linea di massima nella tua classe non credo ci dovrebbe essere alcunché di static.
