Il presente articolo è stato tradotto automaticamente.
Windows Phone SDK 7.1
Creazione di un'applicazione 'Mango'
Andrew Whitechapel
Scaricare il codice di esempio
"Mango" è il nome di codice interno per la versione 7.1 SDK di Windows Phone e, naturalmente, il nome di frutta tropicale davvero deliziosa.È possibile utilizzare manghi in molti modi, ad esempio, nei grafici a torta, insalate e un intervallo di cocktail aromatizzati.Il mango viene detto anche per fornire una serie di vantaggi di salute e dispone di un'interessante cronologia cultura.In questo articolo verrà preso in esame Mangolicious, un'applicazione di Windows Phone SDK 7.1 sui manghi.L'applicazione offre una gamma di soluzioni di mango, cocktail aromatizzati e fatti, ma il vero scopo consiste nell'esplorare alcune delle novità più interessanti in versione 7.1, in particolare:
- Database locale e LINQ to SQL
- Tessere secondarie e il collegamento completo
- Integrazione di Silverlight/XNA
Esperienza utente dell'applicazione è semplice: la pagina principale offre un panorama, con un menu sul primo elemento di panorama, una selezione dinamica della stagione corrente ricette e cocktail aromatizzati sul secondo elemento e alcune semplici "informazioni" sul terzo elemento, come illustrato nella nella figura 1.
Figura 1 Panorama Mangolicious a pagina principale
Il menu e elementi nella sezione evidenzia stagionali fungono da collegamenti per spostarsi tra le altre pagine nell'applicazione.La maggior parte delle pagine sono pagine di Silverlight semplice e una pagina è dedicata a un gioco XNA integrato.Di seguito è riportato un riepilogo delle attività necessarie per creare questa applicazione, dall'inizio alla fine:
- Creare la soluzione di base in Visual Studio.
- Creare in modo indipendente il database per la "ricetta", cocktail e i dati relativi ai fatti.
- Aggiornare l'applicazione di utilizzare il database ed esporlo per l'associazione dati.
- Creare le varie pagine dell'interfaccia utente e associarli ai dati.
- Consente di impostare la funzionalità di tessere secondario per consentire all'utente di aggiungere gli elementi "ricetta" per la pagina iniziale del telefono.
- Incorporare un gioco XNA nell'applicazione.
Creare la soluzione
Per questa applicazione, si utilizzerà il modello Windows Phone Silverlight e XNA applicazione in Visual Studio.Questo genera una soluzione con tre progetti; Dopo la ridenominazione, questi sono riassunte nella figura 2.
Figura 2 progetti in un Windows Phone di Silverlight e soluzione XNA
Progetto | Descrizione |
MangoApp | Contiene l'applicazione di telefono, con un valore predefinito MainPage e un GamePage secondario. |
GameLibrary | Progetto vuoto essenzialmente contenente tutti i riferimenti a destra, ma nessun codice.È fondamentale, include un riferimento contenuto per il progetto di contenuti. |
GameContent | Contenuto progetto vuoto, che conterrà tutti i cespiti giochi (immagini, file audio e così via). |
Creare il Database e la classe DataContext
La versione 7.1 SDK di Windows Phone introduce il supporto per i database locali.In altre parole, un'applicazione può memorizzare dati in un file di database locale (SDF) al telefono.Si consiglia di creare il database nel codice, come parte dell'applicazione stessa o tramite un'applicazione di supporto separato che genera esclusivamente per creare il database.È opportuno creare il database all'interno dell'applicazione in scenari in cui che verrà creato più o tutti i dati solo quando l'applicazione viene eseguita.Per l'applicazione di Mangolicious, dispone di solo dati statici e è possibile popolare il database in anticipo.
A tale scopo, si creeranno un'applicazione di supporto del creatore di database separati, a partire da un semplice modello di applicazione di Windows Phone.Per creare il database nel codice, è necessario che una classe derivata da DataContext, che è definito nella versione personalizzata di telefono dell'assieme System.Data.Linq.Questa classe DataContext stessa può essere utilizzata sia nell'applicazione di supporto che crea il database e l'applicazione principale che utilizza il database.Nell'applicazione helper devo specificare il percorso del database per essere nell'archiviazione isolata, perché questo è l'unica posizione in cui che è possibile scrivere da un'applicazione telefonica.La classe contiene inoltre un insieme di campi di tabella per ogni tabella di database:
public class MangoDataContext : DataContext
{
public MangoDataContext()
: base("Data Source=isostore:/Mangolicious.sdf") { }
public Table<Recipe> Recipes;
public Table<Fact> Facts;
public Table<Cocktail> Cocktails;
}
È disponibile un mapping di 1: 1 tra tabella classi nel codice e le tabelle del database. Le proprietà delle colonne vengono associati alle colonne della tabella nel database e includere le proprietà dello schema di database, ad esempio il tipo di dati e le dimensioni (INT, NVARCHAR e così via), se la colonna può essere null, sia che si tratti di una colonna di chiave e così via. Viene definito tabella classi per tutte le tabelle del database nello stesso modo, nel come mostrato nella nella figura 3.
Figura 3 definizione tabella classi
[Table]
public class Recipe
{
private int id;
[Column(
IsPrimaryKey = true, IsDbGenerated = true,
DbType = "INT NOT NULL Identity", CanBeNull = false,
AutoSync = AutoSync.OnInsert)]
public int ID
{
get { return id; }
set
{
if (id != value)
{
id = value;
}
}
}
private string name;
[Column(DbType = "NVARCHAR(32)")]
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
}
}
}?
...
additional column definitions omitted for brevity
}
Ancora, in applicazione di supporto e l'utilizzo di un approccio Model-View-selezionate (MVVM) standard, ovvero è necessario ora una classe selezionate da interporre tra la visualizzazione (interfaccia utente) e il modello utilizzando la classe DataContext (dati). La selezionate dispone di un campo di DataContext e una serie di insiemi per i dati della tabella (ricette, fatti e cocktail aromatizzati). I dati sono statico, in modo semplice elenco <T> gli insiemi sono sufficienti. Per lo stesso motivo, è necessario solo ottenere le funzioni di accesso di proprietà non setmodificatori (vedere nella figura 4).
Figura 4 definizione delle proprietà di insieme per i dati di tabella il selezionate
public class MainViewModel
{
private MangoDataContext mangoDb;
private List<Recipe> recipes;
public List<Recipe> Recipes
{
get
{
if (recipes == null)
{
recipes = new List<Recipe>();
}
return recipes;
}
}
...
additional table collections omitted for brevity
}
Inoltre espone un metodo pubblico, ovvero che è possibile richiamare dall'interfaccia utente, ovvero creare effettivamente il database e tutti i dati. In questo metodo, creare il database stesso se non già esistenti e quindi crea a sua volta, ogni tabella popolamento di ognuno di essi con dati statici. Ad esempio, per creare la tabella di ricetta, creare più istanze della classe ricetta corrispondenti alle righe della tabella; aggiungere tutte le righe nell'insieme a DataContext; e infine eseguire il commit dei dati nel database. Il modello stesso viene utilizzato per le tabelle dei fatti e dei cocktail aromatizzati (vedere nella figura 5).
Figura 5 creazione del Database
public void CreateDatabase()
{
mangoDb = new MangoDataContext();
if (!mangoDb.DatabaseExists())
{
mangoDb.CreateDatabase();
CreateRecipes();
CreateFacts();
CreateCocktails();
}
}
private void CreateRecipes()
{
Recipes.Add(new Recipe
{
ID = 1,
Name = "key mango pie",
Photo = "Images/Recipes/MangoPie.jpg",
Ingredients = "2 cans sweetened condensed milk, ¾ cup fresh key lime juice, ¼ cup mango purée, 2 eggs, ¾ cup chopped mango.",
Instructions = "Mix graham cracker crumbs, sugar and butter until well distributed.
Press into a 9-inch pie pan.
Bake for 20 minutes.
Make filling by whisking condensed milk, lime juice, mango purée and egg together until blended well.
Stir in fresh mango.
Pour filling into cooled crust and bake for 15 minutes.",
Season = "summer"
});
...
additional Recipe instances omitted for brevity
mangoDb.Recipes.InsertAllOnSubmit<Recipe>(Recipes);
mangoDb.SubmitChanges();
}
In un punto adeguato per l'applicazione di supporto, ad esempio un pulsante fare clic su gestore, è quindi possibile richiamare questo metodo CreateDatabase. Quando si esegue l'helper (sia nell'emulatore o su un dispositivo fisico), verrà creato il file di database nell'archiviazione isolata dell'applicazione. L'attività finale consiste nell'estrarre il file sul desktop in modo che è possibile utilizzare nell'applicazione principale. A tale scopo, si utilizzerà lo strumento di Esplora archivi isolati, uno strumento della riga di comando che viene fornito con il 7.1 SDK di Windows Phone. Ecco il comando per acquisire un'istantanea dell'archiviazione isolata dall'emulatore al desktop:
"C:\Program Files\Microsoft SDKs\Windows Phone\v7.1\Tools\IsolatedStorageExplorerTool\ISETool" ts xd {e0e7e3d7-c24b-498e-b88d-d7c2d4077a3b} C:\Temp\IsoDump
Questo comando si presuppone che lo strumento viene installato in una posizione standard. I parametri sono spiegati in nella figura 6.
Figura 6 isolato Esplora archivi i parametri della riga di comando
Parametro | Descrizione |
Servizi terminal | "Prendere snapshot" (ad esempio, il comando per il download dall'archiviazione isolata per il desktop). |
xD | Abbreviazione di XDE (in altre parole, l'emulatore). |
{e0e7e3d7-c24b-498e-b88d-d7c2d4077a3b} | Il numero di serie per l'applicazione di supporto. Questo è elencato nella finestra di WMAppManifest.xml e si è diverso per ogni applicazione. |
C:\Temp\IsoDump | Qualsiasi percorso valido sul desktop in cui si desidera copiare lo snapshot. |
Avere estratto il file SDF sul desktop, sto completata con l'applicazione di supporto ed può trasformare la mia attenzione per l'applicazione di Mangolicious utilizzerà questo database.
Utilizzare il Database
Nell'applicazione di Mangolicious aggiungere il file SDF al progetto e aggiungere anche la stessa classe DataContext personalizzata alla soluzione, con un paio di modifiche di lieve entità. In Mangolicious, non è necessario scrivere nel database, in modo da utilizzare direttamente dall'applicazione della cartella di installazione. In questo modo la stringa di connessione è leggermente diversa da quello dell'applicazione di supporto. Mangolicious definisce, inoltre, una tabella SeasonalHighlights nel codice. Non vi è alcuna tabella di SeasonalHighlight corrispondente nel database. Invece, questa tabella codice estrarre dati da due tabelle di database sottostanti (ricette e cocktail aromatizzati) e viene utilizzata per popolare l'elemento di panorama evidenzia stagionali. Due di queste modifiche sono le uniche differenze nella classe DataContext tra l'applicazione di supporto di creazione del database e l'applicazione di database che utilizzano Mangolicious:
public class MangoDataContext : DataContext
{
public MangoDataContext()
: base("Data Source=appdata:/Mangolicious.sdf;File Mode=read only;") { }
public Table<Recipe> Recipes;
public Table<Fact> Facts;
public Table<Cocktail> Cocktails;
public Table<SeasonalHighlight> SeasonalHighlights;
}
L'applicazione di Mangolicious deve inoltre una classe selezionate ed è possibile utilizzare la classe selezionate dall'applicazione helper come punto di partenza. È necessario che il campo DataContext e l'insieme dell'elenco <T> proprietà di insieme per le tabelle di dati. Di che, aggiungerà una proprietà di stringa per registrare la corrente stagione, calcolata nel costruttore:
public MainViewModel()
{
season = String.Empty;
int currentMonth = DateTime.Now.Month;
if (currentMonth >= 3 && currentMonth <= 5) season = "spring";
else if (currentMonth >= 6 && currentMonth <= 8) season = "summer";
else if (currentMonth >= 9 && currentMonth <= 11) season = "autumn";
else if (currentMonth == 12 || currentMonth == 1 || currentMonth == 2)
season = "winter";
}
Il metodo critico il selezionate è il metodo LoadData. In questo caso, è possibile inizializzare il database ed eseguire query LINQ per SQL per caricare i dati tramite la proprietà DataContext in insiemi in memoria. Potrei precaricare a questo punto tutte le tre tabelle, ma si desidera ottimizzare le prestazioni di avvio per ritardare il caricamento dei dati, a meno che e fino a quando la pagina corrispondente è effettivamente visitata. I dati solo I deve , carica all'avvio infatti i dati per la tabella SeasonalHighlight, viene visualizzato nella pagina principale. A tale scopo, si dispone di due query per selezionare solo le righe dalle tabelle di ricette e dei cocktail aromatizzati che soddisfano la stagione corrente e aggiungere la riga combinata imposta all'insieme, come illustrato nella nella figura 7.
Figura 7 il caricamento dei dati all'avvio
public void LoadData()
{
mangoDb = new MangoDataContext();
if (!mangoDb.DatabaseExists())
{
mangoDb.CreateDatabase();
}
var seasonalRecipes = from r in mangoDb.Recipes
where r.Season == season
select new { r.ID, r.Name, r.Photo };
var seasonalCocktails = from c in mangoDb.Cocktails
where c.Season == season
select new { c.ID, c.Name, c.Photo };
seasonalHighlights = new List<SeasonalHighlight>();
foreach (var v in seasonalRecipes)
{
seasonalHighlights.Add(new SeasonalHighlight {
ID = v.ID, Name = v.Name, Photo = v.Photo, SourceTable="Recipes" });
}
foreach (var v in seasonalCocktails)
{
seasonalHighlights.Add(new SeasonalHighlight {
ID = v.ID, Name = v.Name, Photo = v.Photo, SourceTable = "Cocktails" });
}
isDataLoaded = true;
}
Posso utilizzare query di LINQ per SQL simili per la creazione di diversi metodi di LoadFacts, LoadRecipes e LoadCocktails che possono essere utilizzati dopo l'avvio per caricare i rispettivi dati su richiesta.
Creare l'interfaccia utente
La pagina principale è costituito da un Panorama con tre PanoramaItems. Il primo elemento è costituito da un controllo ListBox che offre un menu principale per l'applicazione. Quando l'utente seleziona uno degli elementi ListBox, passare alla pagina corrispondente, ovvero in altre parole, la pagina di raccolta per ricette, fatti e cocktail aromatizzati, o la pagina di gioco. Prima di esplorazione, assicurarsi che caricare i dati corrispondenti in insiemi ricette, fatti o cocktail aromatizzati di:
switch (CategoryList.SelectedIndex)
{
case 0:
App.ViewModel.LoadRecipes();
NavigationService.Navigate(
new Uri("/RecipesPage.xaml", UriKind.Relative));
break;
...
additional cases omitted for brevity
}
Quando l'utente seleziona un elemento dall'elenco evidenzia stagionali nell'interfaccia utente, esamina l'elemento selezionato per vedere se si tratta di una "ricetta" o un Cocktail e quindi passare alla pagina di ricette o Cocktail singola, passando l'ID dell'elemento come parte della stringa di query di spostamento, come illustrato nella nella figura 8.
Figura 8 selezionando dall'elenco di luci stagionale
SeasonalHighlight selectedItem =
(SeasonalHighlight)SeasonalList.SelectedItem;
String navigationString = String.Empty;
if (selectedItem.SourceTable == "Recipes")
{
App.ViewModel.LoadRecipes();
navigationString =
String.Format("/RecipePage.xaml?ID={0}", selectedItem.ID);
}
else if (selectedItem.SourceTable == "Cocktails")
{
App.ViewModel.LoadCocktails();
navigationString =
String.Format("/CocktailPage.xaml?ID={0}", selectedItem.ID);
}
NavigationService.Navigate(
new System.Uri(navigationString, UriKind.Relative));
L'utente può spostarsi dal menu nella pagina principale per uno dei tre pagine dell'inserzione. Ciascuno di questi dati di pagine viene associato a uno degli insiemi nelle Visualizza per visualizzare un elenco di elementi: ricette, fatti o cocktail aromatizzati. Ciascuna di queste pagine offre una semplice casella di riepilogo in cui ogni voce dell'elenco contiene un controllo immagine per la foto e un controllo TextBlock per il nome dell'elemento. Ad esempio, nella figura 9 illustra la FactsPage.
Figura 9 fatti divertenti, una delle pagine elenco insiemi
Quando l'utente seleziona un singolo elemento dagli elenchi ricette, fatti o cocktail aromatizzati, passare alla pagina di singola ricette, dei fatti o Cocktail, passando l'ID dell'elemento nella stringa di query di spostamento verso il basso. Nuovamente, queste pagine sono quasi identiche tra i tre tipi, ognuno di essi offre un'immagine e testo riportato di seguito. Si noti che non viene definito uno stile esplicito per la forma di controlli TextBlock con associazione a dati, ma che tutto ciò nonostante utilizzino TextWrapping = ritorno a capo. A tale scopo, la dichiarazione di uno stile di TextBlock il App.xaml.cs:
<Style TargetType="TextBlock" BasedOn="{StaticResource
PhoneTextNormalStyle}">
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
L'effetto di ciò è che qualsiasi TextBlock nella soluzione che non definisce in modo esplicito il proprio stile in modo implicito utilizzerà questo invece. Stile implicito è un'altra nuova funzionalità introdotta nel 7.1 SDK di Windows Phone come parte di Silverlight 4.
Per ciascuna di queste pagine code-behind è semplice. Nell'override OnNavigatedTo I estrarre l'ID del singolo elemento dalla stringa di query, trovare tale elemento dall'associazione di dati e insieme selezionate ad esso. Il codice per il RecipePage è un po' più complesso rispetto alle altre, ovvero il codice aggiuntivo in questa pagina è correlato a HyperlinkButton di posizionato nell'angolo in alto a destra della pagina. Ciò può essere verificato nella figura 10.
Figura 10 A "ricetta" pagina con il pulsante Pin
Tessere secondarie
Quando l'utente sceglie il "pin" HyperlinkButton nella pagina ricetta singola, pin tale elemento come una tessera nella pagina iniziale del telefono. All'atto del blocco accetta l'utente alla pagina di avvio e disattiva l'applicazione. Quando una tessera è bloccata in questo modo, periodicamente, anima capovolgimento tra la parte anteriore e posteriore, come illustrato nella nella figura 11 e nella figura 12.
Figura 11 bloccato tessera di ricetta (anteriore)
Figura 12 bloccato tessera di ricetta (retro)
Successivamente, l'utente può toccare questa tessera bloccata, cui si accede direttamente a tale elemento all'interno dell'applicazione. Quando si raggiunge la pagina, il pulsante "pin" avranno un'immagine "sbloccare". Se egli sblocca la pagina, verrà rimosso dalla pagina iniziale e l'applicazione continua.
Ecco come funziona. Nell'override di OnNavigatedTo per la RecipePage, dopo aver eseguito le operazioni standard per determinare quale ricetta specifico per dati associazione, l'elaborazione di una stringa che è possibile utilizzare in un secondo momento come l'URI per questa pagina:
thisPageUri = String.Format("/RecipePage.xaml?ID={0}", recipeID);
Fare clic sul pulsante di su gestore per il pulsante "pin", innanzitutto verificare per vedere se esiste già una tessera per questa pagina e in caso contrario, creato a questo punto. È possibile creare la tessera con i dati correnti di "ricetta": l'immagine e il nome. Inoltre impostata una singola immagine statica, ovvero e testo statico, ovvero per il retro della tessera. Allo stesso tempo, si ha l'opportunità per aggiornare la visualizzazione del pulsante stesso, utilizzando l'immagine "sbloccare". Se, invece, la tessera già esisteva, quindi I deve essere nel gestore click perché l'utente ha scelto sbloccare la tessera. In questo caso, Elimina la tessera e ridisegnare il pulsante che utilizza l'immagine di "bloccare", come illustrato nella nella figura 13.
Figura 13 pagine di blocco e sblocco
private void PinUnpin_Click(object sender, RoutedEventArgs e)
{
tile = ShellTile.ActiveTiles.FirstOrDefault(
x => x.NavigationUri.ToString().Contains(thisPageUri));
if (tile == null)
{
StandardTileData tileData = new StandardTileData
{
BackgroundImage = new Uri(
thisRecipe.Photo, UriKind.RelativeOrAbsolute),
Title = thisRecipe.Name,
BackTitle = "Lovely Mangoes!",
BackBackgroundImage =
new Uri("Images/BackTile.png", UriKind.Relative)
};
ImageBrush brush = (ImageBrush)PinUnpin.Background;
brush.ImageSource =
new BitmapImage(new Uri("Images/Unpin.png", UriKind.Relative));
PinUnpin.Background = brush;
ShellTile.Create(
new Uri(thisPageUri, UriKind.Relative), tileData);
}
else
{
tile.Delete();
ImageBrush brush = (ImageBrush)PinUnpin.Background;
brush.ImageSource =
new BitmapImage(new Uri("Images/Pin.png", UriKind.Relative));
PinUnpin.Background = brush;
}
}
Si noti che se l'utente maschiatura la tessera bloccata per ottenere la pagina "ricetta" e quindi preme il pulsante Indietro di hardware del telefono, egli uscirà dall'applicazione completamente. Si tratta di una potenziale ambiguità perché l'utente si aspetta normalmente che egli verrà chiuso l'applicazione solo quando si preme nuovamente dalla pagina principale, non da qualsiasi altra pagina. Tuttavia, l'alternativa sarebbe per fornire un qualche tipo di pulsante "home" nella pagina "ricetta" per consentire all'utente di passare il resto dell'applicazione. Purtroppo, anche sarebbe confusione, poiché quando si ottiene la pagina principale e si preme Back, egli sarebbe torna nella pagina ricetta bloccata, invece di uscire dall'applicazione. Per questo motivo, anche se un meccanismo di "home" non è possibile raggiungere, è il comportamento che è opportuno valutare attentamente prima di introdurre.
Incorporare un gioco XNA
È importante ricordare che ho creato originariamente l'applicazione come una soluzione di Silverlight di Windows Phone e applicazione XNA. Questo mi ha dato tre progetti. Ho lavorato con il progetto principale di MangoApp per generare le funzionalità di gioco non. Il progetto GameLibrary funge da "bridge" tra il MangoApp di Silverlight e il GameContent XNA. Esso viene fatto riferimento nel progetto MangoApp e a sua volta fa riferimento al progetto di GameContent. È necessario alcun ulteriore lavoro. Esistono due operazioni principali necessarie per incorporare un gioco nella mia applicazione telefonica:
- Consente di migliorare la classe GamePage nel progetto MangoApp per includere tutta la logica di gioco.
- Consente di migliorare il progetto di GameContent per fornire immagini e suoni per il gioco (nessuna modifica del codice).
Esaminare brevemente i miglioramenti apportati da Visual Studio generati per un progetto che si integra Silverlight e XNA, la prima cosa da notare è che il file app. XAML consente di dichiarare un SharedGraphicsDeviceManager. Ciò consente di gestire la condivisione dello schermo fra i runtime di Silverlight e XNA. Questo oggetto è anche l'unico motivo per la classe AppServiceProvider aggiuntiva nel progetto. Questa classe viene utilizzata per memorizzare nella cache il manager di periferica grafica condivisa in modo che sia disponibile per tutto ciò che è necessario nell'applicazione di Silverlight e XNA. La classe di applicazione dispone di un campo di AppServiceProvider ed espone inoltre alcune proprietà aggiuntive per l'integrazione di XNA: un ContentManager e un GameTimer. Queste vengono tutte inizializzate nel nuovo metodo di InitializeXnaApplication, insieme a un GameTimer, che viene utilizzato per la coda di messaggi XNA il pump.
Il lavoro interessante è come integrare un gioco XNA all'interno di un'applicazione di telefono di Silverlight. La partita stessa è effettivamente meno interessante. In questo modo, per questo esercizio, piuttosto che sprecare la fatica di scrivere un gioco completo partendo da zero, procederò un gioco esistente, in particolare, XNA game esercitazione su AppHub: bit.ly/h0ZM4o.
Nel mio adeguamento, si dispone di un agitatore cocktail, rappresentato dalla classe Player nel codice, che viene generato proiettili a manghi in ingresso (nemici). Quando colpisce un mango, aperta si interrompe e viene trasformata in un mangotini. Ogni hit mango aggiunge 100 per il punteggio. Ogni volta che l'agitatore cocktail collide con un mango, intensità di campo di Windows Media player viene ridotto di 10. Quando l'intensità di campo è pari a zero, la partita termina. L'utente può anche terminare il gioco in qualsiasi momento premendo il pulsante Indietro del telefono, come previsto. Figura 14 viene illustrato il gioco in corso.
Figura 14, il gioco XNA in corso
Non è necessario apportare le modifiche per il GamePage.xaml (quasi vuoto). Piuttosto, tutto il lavoro viene eseguito nel codebehind. Visual Studio genera il codice di partenza per questa classe di GamePage, come descritto nella figura 15.
Figura 15 GamePage Starter codice
Campo/metodo | Scopo | Modifiche necessarie |
ContentManager | Carica e gestisce il ciclo di vita dei contenuti dalla pipeline di contenuto. | Aggiungere il codice per utilizzare questa opzione per caricare i suoni di and di immagini. |
GameTimer | Nel modello XNA game, il gioco consente di eseguire azioni quando l'aggiornamento e vengono generati gli eventi di disegno e questi eventi sono disciplinati da un timer. | Rimane invariato. |
SpriteBatch | Utilizzato per disegnare la texture in XNA. | Aggiungere il codice per utilizzarla nel metodo Draw per disegnare gli oggetti di giochi (Windows Media player, i nemici, proiettili, le esplosioni e così via). |
Costruttore di GamePage | Crea un timer e associa gli eventi di aggiornamento e Draw ai metodi OnUpdate e OnDraw. | Mantenere il codice del timer e inoltre inizializzare gli oggetti di giochi. |
OnNavigatedTo | Imposta grafica condivisione tra Silverlight e XNA e avvia il timer. | Conservare il codice di condivisione e timer e inoltre caricare contenuto nel gioco, tra cui uno stato precedente dall'archivio di isolated. |
OnNavigatedFrom | Arresta il timer e disattiva la condivisione graphics XNA. | Conserva il timer e la condivisione del codice e inoltre memorizza il Punteggio partita e la salute di Windows Media player per l'archiviazione isolata. |
OnUpdate | (Vuoto), gestisce l'evento GameTimer.Update. | Aggiungere il codice per calcolare il gioco oggetto modifiche (posizione di Windows Media player, numero e posizione di nemici, proiettili e le esplosioni). |
OnDraw | (Vuoto), gestisce l'evento GameTimer.Draw. | Aggiungere il codice per disegnare gli oggetti di giochi, gioco punteggio e integrità di Windows Media player. |
Il gioco è un adattamento diretto dell'esercitazione AppHub, che contiene due progetti: il progetto di gioco Sparatutto in e il progetto di contenuti di ShooterContent. Il contenuto contiene le immagini e i file audio. Anche se esso non influenza il codice dell'applicazione, è possibile modificare questi per allinearli con il tema di mango dell'applicazione e che è semplicemente una domanda di sostituzione dei file PNG e WAV. Le modifiche necessarie (codice) sono tutti nel progetto di gioco Sparatutto in. Linee guida per la migrazione dalla classe di gioco a Silverlight/XNA sono su AppHub: bit.ly/iHl3jz.
In primo luogo, è necessario copiare i file di progetto gioco Sparatutto nel progetto MangoApp esistente. Inoltre, copiare i file di contenuto ShooterContent nel mio progetto GameContent esistente. Figura 16 sono riepilogate le classi esistenti nel progetto Sparatutto in gioco.
Classi di gioco Sparatutto in figura 16
Classe | Scopo | Modifiche necessarie |
Animazione | Anima i vari Sprite funziona correttamente: il lettore, oggetti avversario, proiettili e le esplosioni. | Eliminare oragioco. |
Nemico | Uno sprite che rappresenta gli oggetti avversario riprese di user. Questi saranno manghi nel mio adeguamento. | Eliminare oragioco. |
Game1 | La classe di controllo per il gioco. | Unire la classe GamePage. |
ParallaxingBackground | Aggiunge un'animazione di immagini di sfondo cloud per fornire un effetto 3D di parallasse. | Nessuna. |
Windows Media Player | Uno sprite che rappresenta il game carattere dell'utente. Si tratta di un agitatore cocktail nel mio adeguamento. | Eliminare oragioco. |
Programma | Utilizzato solo se il gioco destinato a Windows o Xbox. | Non utilizzate; può essere eliminato. |
Proiettile | Uno sprite che rappresenta i proiettili che Windows Media player viene generato ai nemici. | Nessuna. |
Per incorporare il gioco in un'applicazione telefonica, è necessario apportare le modifiche seguenti alla classe GamePage:
- Copiare tutti i campi dalla classe Game1 per la classe GamePage. Inoltre è possibile copiare l'inizializzazione del campo nel metodo Game1.Initialize per il costruttore di GamePage.
- Copiare il metodo LoadContent e tutti i metodi per aggiungere e aggiornare i nemici, proiettili e le esplosioni. Nessuno di questi richiede modifiche.
- Estrarre tutti gli utilizzi di GraphicsDeviceManager per utilizzare invece una proprietà di GraphicsDevice.
- Estrarre il codice nei metodi Game1.Update e disegnare nel gestore di evento del timer GamePage.OnUpdate e OnDraw.
Un gioco XNA convenzionale crea un nuovo GraphicsDeviceManager, mentre in un'applicazione telefonica sarà già hai un SharedGraphicsDeviceManager che espone una proprietà di GraphicsDevice, e questo è tutto che è realmente necessario. Per semplificare le cose, sarà cache un riferimento per la GraphicsDevice come un campo nella classe GamePage.
In un gioco XNA standard, i metodi di aggiornamento e Draw sono esegue l'override dei metodi virtuali nella classe base Microsoft.Xna.Framework.Game. Tuttavia, in un'applicazione Silverlight/XNA integrata, la classe GamePage non è derivata dalla classe XNA Game devo astrarre il codice di aggiornamento e di disegno e inserire i gestori di eventi OnUpdate e OnDraw invece. Si noti che alcune delle classi di oggetti di gioco (ad esempio animazioni, nemico e Windows Media Player), i metodi Update e Draw e alcuni dei metodi di supporto chiamati dal aggiornamento accettano un parametro di oragioco. Ciò viene definito in Microsoft.Xna.Framework.Game.dll e deve essere considerata un bug se un'applicazione Silverlight contiene qualsiasi riferimento all'assembly. Il parametro oragioco può essere sostituito completamente da due proprietà di Timespan-TotalTime ed ElapsedTime, esposta dall'oggetto GameTimerEventArgs che viene passato ai gestori di eventi OnUpdate e OnDraw timer. A prescindere da oragioco, è possibile porting di codice di disegno invariato.
Il metodo di aggiornamento originale test Game pad a stato e in modo condizionale chiama Game.Exit. Questo non viene utilizzato in un'applicazione Silverlight/XNA integrata, in modo che non devono essere trasferita al nuovo metodo:
//if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
//{
// // this.Exit();
//}
Il nuovo metodo di aggiornamento è ora poco più di un cablaggio preassemblato che chiama altri metodi per aggiornare i vari oggetti di giochi. Aggiornare lo sfondo parallaxing anche quando il gioco è terminata, ma solo aggiornare il lettore, nemici, collisioni, proiettili e le esplosioni se il lettore è ancora in vita. Questi metodi di supporto di calcolare il numero e le posizioni dei vari oggetti di giochi. Avere eliminato l'utilizzo di oragioco, questi possono tutti essere trasferiti oltre invariato, ovvero con una sola eccezione:
private void OnUpdate(object sender, GameTimerEventArgs e)
{
backgroundLayer1.Update();
backgroundLayer2.Update();
if (isPlayerAlive)
{
UpdatePlayer(e.TotalTime, e.ElapsedTime);
UpdateEnemies(e.TotalTime, e.ElapsedTime);
UpdateCollision();
UpdateProjectiles();
UpdateExplosions(e.TotalTime, e.ElapsedTime);
}
}
Il metodo UpdatePlayer è necessario personalizzarne alcune. Nella versione originale del gioco, quando la salute del lettore ridotto a zero, è stato reimpostato su 100, il che significava che il gioco ciclo continuo per sempre. Nel mio adattamento quando salute player scende a zero, impostare un flag su false. Test per questo flag nel metodo OnUpdate e OnDraw. In OnUpdate, il valore del flag determina se utilizzare o meno calcolare ulteriori modifiche agli oggetti; in OnDraw, determina se consente di disegnare gli oggetti o per disegnare una schermata "partita" con il punteggio finale:
private void UpdatePlayer(TimeSpan totalTime, TimeSpan elapsedTime)
{
...unchanged code omitted for brevity.
if (player.Health <= 0)
{
//player.Health = 100;
//score = 0;
gameOverSound.Play();
isPlayerAlive = false;
}
}
Riprodurre
In questo articolo, ho esaminato come sviluppare applicazioni rispetto a molte delle nuove funzionalità di Windows Phone SDK 7.1: database locale, LINQ to SQL, tessere secondarie e collegamento completo e l'integrazione di Silverlight/XNA. La versione 7.1 offre molte più nuove funzionalità e miglioramenti alle funzionalità esistenti. Per ulteriori dettagli, vedere i seguenti collegamenti:
- Novità del SDK di Windows Phone: bit.ly/c2RmNr
- Tessere: bit.ly/oQlu15
- Combinazione di Silverlight e XNA: bit.ly/p4RncQ
- Panoramica di Database locale per Windows Phone: bit.ly/l23UQM
La versione finale dell'applicazione Mangolicious è disponibile nel catalogo servizi Windows Phone a bit.ly/nuJcTA (Nota: software Zune è necessaria per l'accesso). Nell'esempio viene utilizzata la Silverlight per Windows Phone Toolkit (download gratuito, disponibile all'indirizzo bit.ly/qiHnTT).
Andrew Whitechapel è stato uno sviluppatore per più di 20 anni e attualmente lavora come program manager del team di Windows Phone, responsabile di pezzi di base della piattaforma dell'applicazione.
Grazie per i seguenti esperti tecnici per la revisione di questo articolo: Gravelyn di Nick, Brian Hudson e Himadri Sarkar