Post 0x01

Door Tommasso op vrijdag 2 september 2011 15:24 - Reacties (5)
Categorie: -, Views: 3.251

En daar ben ik weer,

Allereerst wil melden dat ik in verband met mijn studie weinig heb kunnen doen aan het project. Dus als je iets groots verwacht, raad ik aan deze post onmiddellijk te verlaten :).

Omdat ik de vorige keer last had snelheidsproblemen, heb ik besloten het project voort te zetten in XNA. Hierdoor moest ik helemaal opnieuw beginnen en dus ben ik verder van huis dan waar ik de vorige keer was. Ik ben totaal niet ervaren met XNA en heb dus een paar problemen waarover deze post voornamelijk zal gaan.

Omdat ik nu geen last meer van snelheidsproblemen, heb ik meteen maar een scroll systeem aangebracht. Dit systeem is gehuisvest in de functie setCameraPos(). Omdat bij mij de gefocude X en Y co÷rdinaten in het midden van het scherm moeten staan en het scherm van linksboven naar rechtsonder wordt gegenereerd, moet deze functie bepalen waar de drawTerrain() functie moet beginnen met tekenen. Dit wordt met de volgende code gedaan:


C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void setCameraPos(float xCoor, float yCoor){
            int xOffset = 0;
            int yOffset = 0 - imageHeight / 2;

            // process the sub tile offsets
            xOffset -= (int) Math.Round(xCoor % 1 * imageWidth / 2, 0);
            yOffset += (int) Math.Round(xCoor % 1 * imageHeight / 2, 0);
            xOffset -= (int) Math.Round(yCoor % 1 * imageWidth / 2, 0);
            yOffset -= (int) Math.Round(yCoor % 1 * imageHeight / 2, 0);

            // now we need to find out where to draw_start
            draw_startScrX = (int) (Math.Round(screenWidth / 2f, 0) + xOffset);
            draw_startScrY = (int) (Math.Round(screenHeight / 2f, 0) + yOffset);

            draw_startMapX = (int) Math.Floor(xCoor);
            draw_startMapY = (int) Math.Floor(yCoor);

            while (draw_startScrX > 0 - imageWidth / 2)
            {
                draw_startScrX -= imageWidth;
                draw_startMapX--;
                draw_startMapY--;
            }
            while(draw_startScrY > 0 - imageHeight / 2)
            {
                draw_startScrY -= imageHeight;
                draw_startMapX++;
                draw_startMapY--;
            }
        }



Het probleem zit waarschijnlijk in het laatste stuk code, hier wordt het middelpunt van het scherm terug gerekend naar de linkerbovenhoek. Eerst wordt de horizontale offset weggewerkt en daarna de verticale. Elke keer als een stap wordt gedaan, moet de huidige mappositie worden aangepast. Dit lijkt allemaal te werken, als ik aangeef dat co÷rdinaat 0x0 het middelpunt is, wordt deze ook in het midden van het scherm getoond. Maar als ik scroll, verspringt het beeld. Hebben jullie enig idee waarom dit zo gebeurt? Verder worden de X en Y co÷rdinaten erg vreemde waardes zoals 3.99999957. Heeft dit te maken met float precision ofzo?

Al dat het mij om het terrein af te beelden op het scherm, moeten deze ook in elkaar kunnen laten overlopen. Hiervoor zijn twee bestanden benodigd: terrain.txt en blendomatic.dat. Om deze bestanden te kunnen gebruiken moet ik deze in het project importeren. Maar als ik deze bestanden heb ge´mporteerd wil het niet meer runnen. Ik krijg de foutmelding: "Error 1 Cannot autodetect which importer to use for "blendomatic.dat". There are no importers which handle this file type. Specify the importeer that handles this file type in your project.". Ik weet niet hoe ik dit moeten oplossen, en als ik het bestand niet importeer maar benader vanuit de code wilt het niet werken: het bestand kan dan niet worden gevonden.
Maar zelfs al zou ik het bestand kunnen openen, moet ik deze ook kunnen uitlezen. In PHP gebruikte ik hiervoor fread(), maar in C# slaag ik er niet in om een soortgelijke functie te vinden (ik vind enkel in functies die het bestand lijn voor lijn uitlezen. Hiermee kan ik blendomatic.dat nooit uitlezen.) Kennen jullie een functie die hiervoor wel geschikt is?


Het project kunnen jullie overigens hier vinden: http://bayfiles.com/file/XsV/US2Q67/AoE01.zip
Let Op: Het lezen van mijn code kan ogen schaden!

Volgende: Post 0x02 09-'11 Post 0x02
Volgende: Post 0x00 08-'11 Post 0x00

Reacties


Door Tweakers user RobIII, vrijdag 2 september 2011 16:11

Verder worden de X en Y co÷rdinaten erg vreemde waardes zoals 3.99999957. Heeft dit te maken met float precision ofzo?
Getallen en talstelsels FAQ
In PHP gebruikte ik hiervoor fread(), maar in C# slaag ik er niet in om een soortgelijke functie te vinden (ik vind enkel in functies die het bestand lijn voor lijn uitlezen. Hiermee kan ik blendomatic.dat nooit uitlezen.) Kennen jullie een functie die hiervoor wel geschikt is?
Alles wat je nodig hebt zit in System.IO

Mag ik vragen waarom je dit in een blogpost aankaart en niet in [PRG]? :)

[Reactie gewijzigd op vrijdag 2 september 2011 16:15]


Door Tweakers user Tommasso, vrijdag 2 september 2011 16:46

Omdat ik al een andere blogpost hierover had gemaakt en ik dus de 'serie' hiermee voortzet :).
(en ik wou effe de source posten)

Maar thx voor de links, ben nogal noob in C# :)

Door Tweakers user RobIII, vrijdag 2 september 2011 16:51

Tommasso schreef op vrijdag 02 september 2011 @ 16:46:

Maar thx voor de links, ben nogal noob in C# :)
Wat betreft je float "probleem"; dat is inherent aan floats (en dus ook het geval bij PHP of eender welke andere taal) en niet C# specifiek ;) (en valt IMHO onder basiskennis programmeren)

[Reactie gewijzigd op vrijdag 2 september 2011 16:52]


Door Tweakers user Voxyn, zaterdag 3 september 2011 00:57

en als ik het bestand niet importeer maar benader vanuit de code wilt het niet werken: het bestand kan dan niet worden gevonden.
Je probeert een map te openen en niet een bestand ;).


code:
1
StreamReader sr = new StreamReader("C:/Program Files (x86)/Age of Empires II/Data/ged_data/terrain");


Zo kan je het proberen:


code:
1
StreamReader sr = new StreamReader(@"C:/Program Files (x86)/Age of Empires II/Data/ged_data/terrain/" + filename);



verder kan je en bestand helemaal van begin tot einde uitlezen met de functie sr.ReadToEnd()

zal dus waarschijnlijk zoiets worden:

code:
1
2
3
4
5
6
7
8
9
10
11
void loadBlendomaticData()
        {
            StreamReader sr = new StreamReader(@"C:/Program Files (x86)/Age of Empires II/Data/ged_data/blendomatic.dat");

            string text = "";

            text = sr.ReadToEnd();
            //close the stream
            sr.Close();

        }




Hoop dat je hier in ieder geval een beginnetje mee hebt, hoor graag een reactie of je iets aan hebt ;).

[Reactie gewijzigd op zaterdag 3 september 2011 00:57]


Door Tweakers user Tommasso, maandag 5 september 2011 10:04

@RobIII
In PHP ben ik het probleem niet tegengekomen. Daar was het altijd keurig 3.1 ed (ik ben denk ik gewoon lui en gewend aan het gemak van PHP :P) Maar ik zal aan mijn code prutsen zodat mijn coor wat netter worden...

@Voxyn
Ik denk dat die map openen wat onafgewerkt gedebug is. Ik had ook het bestand geprobeerd te openen. Ik had alleen die @ niet, dus deed ie het nie :).
Maar ik heb nu blendomatic en terrain succesvol kunnen uitlezen:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
void loadTerrainData(){
            StreamReader sr = new StreamReader(@"C:/Program Files (x86)/Age of Empires II/Data/ged_data/text/terrain.txt");
            // skip first 21 lines
            int i;
            for (i = 0; i < 21; i++)
            {
                sr.ReadLine();
            }
            string name, line;
            int slp, priority, blendmode, sizeX, sizeY;
            string [] segment;

            List<TerrainType> list = new List<TerrainType>();
            // start reading the file
            for(i = 0; sr.Peek() >= 0; i++){
                line = sr.ReadLine(); // ignore line

                line = sr.ReadLine();
                segment = line.Split(new Char [] {' '});
                name = segment[1];
                
                line = sr.ReadLine(); // ignore line

                line = sr.ReadLine();
                segment = line.Split(new Char [] {' '});
                int.TryParse(segment[1], out slp);

                line = sr.ReadLine();
                segment = line.Split(new Char [] {' '});
                int.TryParse(segment[3], out priority);
                int.TryParse(segment[4], out blendmode);

                line = sr.ReadLine(); // ignore line

                line = sr.ReadLine(); // ignore line

                sizeX = 10;
                sizeY = 10;

                list.Add(new TerrainType(name, slp, priority, blendmode, sizeX, sizeY));
            }
            terrainTypes = list.ToArray();
            sr.Close();
        }
        void loadBlendData()
        {
            BinaryReader br = new BinaryReader(File.Open(@"C:/Program Files (x86)/Age of Empires II/Data/blendomatic.dat", FileMode.Open));
            int blendmodes = br.ReadInt32();
            int directions = br.ReadInt32();

            int pixelsPerTile;
            blendMasks = new int [blendmodes][][];

            for (int i = 0; i < blendmodes; i++)
            {
                pixelsPerTile = br.ReadInt32();
                blendMasks[i] = new int[directions][];

                // start reading
                br.ReadBytes(directions); // skip useless data
                br.ReadBytes(pixelsPerTile * 4); // skip useless data

                for (int ii = 0; ii < directions; ii++)
                {
                    blendMasks[i][ii] = new int[pixelsPerTile];
                    for (int iii = 0; iii < pixelsPerTile; iii++)
                    {
                        blendMasks[i][ii][iii] = br.ReadByte();
                    }
                }
            }
        }


Wat een gedoe om een dynamic array werkend te krijgen, of ben ik nou gek?
Bedankt voor de hulp!

Next up is het ontleden van DRS en SLP bestanden, wordt gek van die duizenden images in mijn project :S.

Reageren is niet meer mogelijk