C# MVC userControls osv.

Tags:    c#

Som sagt i: http://www.udvikleren.dk/DotNet/Thread.aspx/13/28250/ ville jeg komme tilbage, og spørge noget mere om hvordan det er smart at strukturer sit program i c#(i virkeligheden nok .NET generalt)

Nu er jeg her så, og denne gang er jeg stødt ind i et enligt problem. Som sagt i den første tråd, har jeg tænkt mig at lave en 2D level editor (link til, og beskrivelse af, en i den originale tråd).

Så vis man skal holde det helt simpelt skal man bruge:

-Et område der kan vise de tiles man har lagt ud, og kan lægge nye, ved at trykke der hvor man vil have lagt en. (kalder den "Editoren" fremover)
-En måde, at bestemme hvilken tile, der skal ligges i Editoren.(kalder den "TileVælgeren" fremover)
-En muglighed for at gemme hvilke tiles, og hvordan de er lagt, til en tekst fil, der kan læses af spillet.

Her er hvad jeg har tænkt indtil vidre:

De første to punkter, Editoren og TileVælgeren, skal vises grafisk på skærmen, så derfor vil jeg lave en user control til hver. Da jeg har læst om MVC, og det ser ud som om det er den måde der oftest bliver anvendt, vil jeg også lave en model klasse til hver control. (jeg kan ikke se hvad jeg skal bruge en control klasse til, men vis den er svaret på alle mine problemer, så bare sig hvordan jeg skal bruge den :D)

Editor modellen skal så have disse værdier (og funktioner):
int[,] map //til at holde hvilken værdi der skal puttes, hvor i det grid som Editoren består af
int currentTile //til at afgøre hvilken tile der skal placeres, når jeg trykker et sted i Editoren
//noget event noget til at underrette viewet når modellen bliver opdateret
saveToTxt() // er ikke sikker på om den skal være her.
setTile(int x, int y)
{
xPos = x/tileWidth //tileWidth er bredden på et felt i "tabellen"
yPos = y/tileHeight //du kan nok gætte hvad tileHeight er :P

map[xPos,yPos] = currentTile;
}

EditorViewet(selve controllen) skal se ud således:
EditorModel model = new EditorModel();

enlig skal det bare være et panel der fylder hele controllen. når man trykker et sted, skal den kalde model.setTile(int x, int y) med musse positionen som argument. i paint metoden, skal den med et loop i et loop iterere gennem model.map, og tegne hver tile i det tal som loopet er nået til*tileWidth eller tileHeight. Bliver nok nødt til at skrive selve koden(er lidt svært at forklare), men jeg ved ikke lige hvordan man tegner et billede til skærmen, så jeg antager bare at funktion drawPicture(x, y) tegner et billede til skærmen i koordinaterne x,y.
Fold kodeboks ind/udKode 


Jeg har ikke tænkt så meget i tileVælgeren endnu, men her er det helt basic:
Model:
int currentTile //hvilken tile der er valgt
string(eller en form for billede) tileSheet //enten selve billedet der skal bruges som tile sheet, eller path'en til det

view:
Skal kunne vælge hvilken til der skal være currentTile.


Så er det på plads. MVC arkitekturen ser god ud når viewet kun skal være view for mig, men hvad når viewet også skal kunne bruges af andre objekter? eksempelvis skal editoren kunne trække currentTile ud af TileVælgeren(eller vælgeren skal kunne give editoren dens currentTile værdi), og for at kunne gøre det bliver det nødt til at have en referance til TileVælgeren.

Det er her jeg er gået lidt i stå. Jeg kan ikke rigtig finde ud af hvordan man kæder flere MVC dele sammen i et program.

Skal jeg lave noget om i det jeg har tænkt indtil vidre?
Skal jeg droppe MVC?
Har jeg misforstået MVC?
Er der noget andet?



3 svar postet i denne tråd vises herunder
1 indlæg har modtaget i alt 4 karma
Sorter efter stemmer Sorter efter dato
Der er et par ting jeg vil anbefale dig, både arkitekturmæssigt og helt generelt.

For det første synes jeg grundlæggende det er forkert at følge en model, bare for at følge modellen. Hvis du har en bedre måde (velunderbygget) så er det den der fungerer for dig - tag og brug den så.

Måske er det vigtigere for dig at få lavet noget det kan visers, så du kan se problemerne i virkeligheden end blot rent teoretisk. Måske skulle du starte med at lave noget der kan tegne dit kort (til at starte med sorte og hvilde tiles) på en kontrol. Så har du fundet ud af hvordan det gøre, og du kan strege det fra listen over "problemer der skal løses / ukendte faktorer"

Nu til arkitekturen. Det der er vigtigst for dig når du skal bygge denne arkitektur er naturligvis at den fungerer, men ligeså meget at du forstår den. Du skal forstå de begreber du modellerer og du skal forstå den "mini-verden" du modellerer. Hvis det er for vildt for dig at bruge MVC, så drop det og lav det som du synes det skal laves - det er ikke den endelige version du laver nu, det er nok mere en prototype du kan bygge videre på senere. Det er en vigtig ting at indse at man ikke kan lave tingene 100% rigtigt i første forsøg, hvis man satser på at gøre dette kommer man aldrig ud af analyse fasen. Rent psykologisk er der også noget godt i at få lavet noget, og føle et fremskridt i stedet for at du 2 måneder i træk sidder og kigger på din kode, for så at opdage at du ikke kan tegne det...få noget lavet du kan se, så din psyke har det godt :-)

Der er generelt to veje til det du vil. "Bottom-up" og "Top Down", og du skal beslutte hvilken type udvikler du er, personligt er jeg en "Middle Out" jeg starter et sted i midten og arbejder mig ud af indtil jeg har implementeret hele vertikaler (hele vejen fra din GUI til din .map fil, (hvorfor bruger du ikke .xml, eller serialiserer dine objekter til enten xml eller binært format???). Hvis du gør det i "små tynde kolonner" så får du lavet lidt GUI, lidt logik og lidt filarbejde, det er nemt at ændre når du støder på nogle problemer senere hen, da du har en begyndende skabelon til at gøre tingene med.

Med hensyn til din faktiske implementering, så kan jeg forstå du vil lave en form for isometrisk/2D spilleflade - god ide! Nu kommer vi tilbage til det med at forstå din "mini-verden". Dvs, du har et map, som er sammensat af flere tiles (lad være med at tænke filer eller GUI nu, nu modellerer vi bare den logiske sammensætning af objekterne, representationen kan altid laves). Prøv at byg hvert lag (på papir) uden at tænke over hvordan det skal gemmes eller hvordan det skal vises, men koncentrer dig om at lave det enkelte lag "korrekt" - det er det bedste i længden. Det vil sige at et map har en liste af tiles (og måske et navn og en størrelse). Hver tileklasse har et billede, en placering, og måske en liste af de tiles der er omkring den. (senere kan vi nedarve den til en græs tile, en sten tile, en bjerg tile, en væg tile osv). En map klasse har også en funktion der hedder Tegn() (eller Render() hvis du er mere til engelsk) som tager et "Graphics" objekt med ind. Denne metodes ansvar er at tegne selve mappet på den Graphics den får ind - i princippet skal den ingenting gøre, andet end at løbe sine tiles igennem, udregne deres position (for at placere den rigtigt) og bede hver enkelt tile om at tegne sig selv - hvilket også betyder at hver enkelt Tile skal have en Tegn(Graphics g) metode der tager et Graphics object med ind (når du tegner skal du også vige hver tile den x og y position den har (som jeg beskrev tidligere). Nu har vi de mest basale klasser i en meget simpel udgave, nu kan du "hardcode" din første prototype. Blot lav et map, tilføj nogle tiles og bed den om at tegne sig. Når dette er på plads er du nok mere klaar til at gå videre, du ved også hvad næste skridt vil være.

Håber det giver mening

/Brian



Mange tak. Det er nok rigtigt at jeg skal lave min map klasse mere så den opfylder kravne til et 'map' end den opfylder kravne til MVC.

Det er også ret smart at man kan sende et grapichs object, og få den til at tegne på det, så man kan holde den mere adskilt fra selve viewet.

Har også tænkt på at lave mine maps (som er .txt filer) om til XML, da jeg har prøvet at lave noget der kan parse filerne i mit spil, og min kode fungere ret dårligt.



Med hensyn til filformat, så stil dig selv følgende spørgsmål: "Er det relevant for mit spil hvilket filformat der gemmes til?" - Hvis svaret er "Nej" (og det håber jeg lidt det er) så gem det i det format der er nemmest. Igen husk på at det at gemme behøver ikke at være samme struktur som det du har i dit objekt lag. Ligesom din GUI ikke behøver at være det samme som dit objektlag. Du kan overveje at kigge nærmere på "serialisering", prøg at google det og leg lidt med et - jeg tror her til at starte med at det ville være det bedste for dig. Så er du hurtigt i gang.

P.S. Serialisering er .NET's måde at gemme objekter i en filstruktur på. Du kan i princippet gemme hele dit map, i een linies kode, så er du fri for at gøre det selv. Ellers se evt min tidligere artikel om en objectfactory



t