Post 0x00

Door Tommasso op dinsdag 23 augustus 2011 15:41 - Reacties (16)
Categorie: -, Views: 5.274

hallo allemaal, in de zomervakantie heb ik, om de verveling tegen te gaan, besloten om een nieuw projectje te starten en het leek mij 'grappig'/'interessant' om deze met jullie te delen.
Na het maken van vele websites begon dat nogal te vervelen en besloot ik om iets anders te gaan doen. Ik wilde iets wat met computerspellen te doen had gaan doen, en omdat ik vroeger het computerspel Age of Empires II erg veel heb gespeeld, besloot ik om deze na te maken.
Natuurlijk ben ik niet instaat om zoon gigantisch karwei in mijn eentje te doen en dus besloot ik om enkel het grafische gedeelte te klonen. Maar ook dit is nog steeds een enorm karwei en dus besloot ik om (voorlopig) enkel het terrein na te maken.

Hier leg ik uit hoe ik dit heb gedaan. Als je dit saai vindt en enkel het resultaat wil zien, scippen naar onderen!

Allereerst moest ik er achter komen waar en hoe de afbeeldingen voor het terrein zijn opgeslagen. Na een korte analyse van de Age of Empires II bestanden, zag ik al snel dat alle gegevens in de /Data map staan. in deze map staan vijf .drs bestanden, respectievelijk:
graphics.drs hier zitten waarschijnlijk alle afbeeldingen voor de units in opgeslagen
interfac.drs hier zitten waarschijnlijk alle afdelingen voor de interface opgeslagen
sounds.drs hier zitten waarschijnlijk alle geluidsbestanden opgeslagen
terrain.drs en hier was ik naar op zoek, alle afbeeldingen voor het terrein
gamedata.drs ik weet niet precies wat hier inzit, waarschijnlijk data voor het spel zoals mappen van de scenario's van het campain.

vervolgens moest ik nog de afdeling uit de .drs bestanden halen. Gelukkig hoefde ik dit niet zelf uit te vogelen, iemand anders was zo vriendelijk om hiervoor een programma te schrijven.
http://img200.imageshack.us/img200/2875/csg4e53722eefac8.png
Zoals te zien bestaat elk terrein-type uit 100 (behalve farms) kleinere afdelingen (welke tiles worden genoemd). Deze tiles moeten in een speciale volgorde worden gelegd zodat het terrein er vloeiend uitziet. Iedereen die Age of Empires II gespeeld heeft met de mappen ruitvormig zijn in plaats van vierkant. Dit kan je ook aan de tiles zelf zien en dus moeten de tiles in een ruit van 10x10 worden gelegd.
Eerst dacht ik dat de map bovenaan begon en de rijen als een forward-slash lagen.
(geen afbeelding meer)
Daarna dacht ik dat de map bovenaan begon en de rijen als een backward-slash lagen:
http://img845.imageshack.us/img845/6500/terrain02.png
Driemaal is scheepsrecht zegt men vaak, en in dit geval klopte dit ook. Het bleek dat de map links begon en de rijen als een forward-slash lagen:
http://img38.imageshack.us/img38/9159/terrain03.png
(die nummers zijn voor debug; blauw voor scherm grid pos, groen voor map pos)
Nu ik wist hoe ik terrein moest aanleggen, kwam de volgende stap: de terrein-typen in elkaar laten overlopen. Eerst dacht ik dat er zogenaamde overloop-tiles zouden zijn. Helaas kon ik deze niet vinden en realiseerde ik dat er extreem veel van deze overloop-tiles zouden moeten zijn om alle verschillende terreinen in alle verschillende richtingen te kunnen laten overlopen (namelijk iets van 31^2 * 100 * 31 * 16 = 47665600, 31 ^2 omdat elk terrein kan overlopen in een ander, 100 omdat er 100 tiles per terrain zijn, 31 omdat er 31 richtingen zijn en 16 omdat er 16 stretch mogelijkheden zijn (bergen)). Age of Empires II moet dus ergens een stuk code staan waarmee terrein-typen in elkaar overlopen. Om erachter te komen hoe deze precies werkte, ging ik experimenteren.
Eerst moest ik alle mogelijke richtingen achterhalen. En na een lang puzzelen kwam ik uit op 31 verschillende richtingen:
http://img851.imageshack.us/img851/5673/test01.png
Hierna wilde ik alle overgangsvormen achterhalen. Ook dit duurde erg lang, dit komt voornamelijk omdat verschillende terreinen die mogelijk wel dezelfde overgangsvormen gebruiken er alsnog heel erg anders uitzien en je dus last hebt van false postives. Uiteindelijk kwam ik uit op vier verschillende overgangsvormen (snow en road zijn bijvoorbeeld het zelfde):
http://img832.imageshack.us/img832/4725/test02i.png
Verder moest ik weten waarom het ene terrein-type overvloeit in het het andere terwijl soms het andere terrein-type overvloeit op deze. Ik redeneerde dat elk terrein een soort 'prioriteit' heeft en als de ander een lagere heeft wordt hij overspoeld.
Als laatste moest ik nog achterhalen wanneer welke overgangsvorm wordt gebruikt. Ik wist alleen niet hoe ik hier achter moest komen. Ik kon de gegevens in geen enkele .drs bestand vinden en dus moest het in een ander bestand zitten. Na de .drs bestanden is het empires2_x1.dat bestand het grootste. Helaas is dit bestand een grote warboel. Na lang zoeken op Google kwam ik bij een programma genaamd genied.exe welke dit bestand kon uitpakken. En ja wel, er zat een tekstbestand tussen de bestanden welke terrain.txt heette.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
terrain_0_unknown01: 0 1
terrain_0_name1: Grass
terrain_0_name2: g_grs
terrain_0_slp: 15001
terrain_0_unknown02: 0 256 100 0
terrain_0_colours: 55 236 54 0
terrain_0_unknown03: -256 255 0 0 0 0 0 0 0 0 0 0 0 100 1 0 1 1 100 1 1 101 1 1 102 1 1 103 1 1 104 1 1 105 1 1 106 1 1 107 1 1 108 1 1 109 1 1 110 1 1 111 1 1 112 1 1 113 1 1 114 1 1 115 0 0 116 0 0 116 -1 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
terrain_1_unknown01: 0 1
terrain_1_name1: Water
terrain_1_name2: g_wtr
terrain_1_slp: 15002
terrain_1_unknown02: 0 257 140 3
terrain_1_colours: 19 19 19 0
terrain_1_unknown03: -256 255 0 0 0 0 0 0 0 0 0 0 0 100 1 0 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 0 0 100 -1 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0


Helaas zit er dus erg veel onbekende data tussen, maar met wat denkwerk is er veel data uit te filteren:
unknown01 lijkt elke keer het zelfde te zijn en is dus niet zinnig.
unknown03 is een bulk aan data welke voor mij niet te begrijpen valt. Maar omdat ik opzoek ben naar de prioriteit van het terrein en de overgangsvorm lijkt het niet de juiste data voor.
Dan hebben we enkel nog unknown02 over, welke uit 4 int's lijkt te bestaan. Int 1 is altijd 0 en dus niet zinnig; Int 2 schommelt tussen de 254 en de 257 en lijkt mij ook niet echt zinnig.
Int 3 heeft veel waarden welke rond de 100 schommelen. Verder is int 3 bij gras (terrein 0) 100 en elke keer als een terrein een grotere waarde heeft is deze ook in Age of Empires II dominant. Ik vond dat dit waarschijnlijk de prioriteit int is.
Nu ben ik nog op zoek naar de overgangsvorm en heb nog 1 int over (int 4). Deze schommelt tussen 0 en 7. Dit komt niet overeen met de vier overgangsvormen die ik heb gevonden. Dit blijft voor mij dus nog niet helemaal zeker, maar ik ga er van uit dat int 4 toch de int is voor de overgangsvormen.

Maar om terrein in elkaar over te laten lopen moest ik ook nog een mask hebben. Immers moet het terrein met een bepaald patroon overlopen. Eerst dacht ik dat unknown03 dit verzorgde, maar omdat hier waarden van -256 tot 255 in voorkomen en een dat dus betekend dat de alpha-channel 9 bits breed moet zijn leek mij dit onwaarschijnlijk. De masks moesten dus nog in een ander bestand zitten.
Dus nam ik een kijkje in de /Data map en zag daar blendomatic.dat staan. Omdat overvloeien in het Engels vaak "blenden" wordt genoemd nam ik aan dat hier de masks inzaten. Maar ook dit bestand is een wirwar van data en dus moest ik weer Google raadplegen en kwam ik deze afbeelding tegen:
http://img546.imageshack.us/img546/1602/blendomatica.png
De afbeelding bevatte de masks, maar er was een probleem: Er waren volgens de afbeelding 9 masks terwijl er volgens terrain.txt er slechts 8 zijn. Maar er klopte nog meer niet: Ice had overgangsvorm 7 (6) en volgens de afbeelding moest deze 6 zijn. Maar ookal staat er in terrain.txt bij ice een 6 moest dit overgangsvorm 7 betekenen omdat bij grass 0 staat en deze anders geen overgangsvorm heeft. Ook lijkt het dat er dubbelen zijn. Deze problemen negeerde ik en door de ice masks te vergelijken met de ice overgangen waarmee ik had gepuzzeld kon ik achterhalen welke mask bij welke richting gebruikt werd:
http://img838.imageshack.us/img838/9411/test011.png

En na lang testen leek het allemaal te kloppen, behalve bij ice: Elke keer als een dominant terrein een onderdanig terrein tegen komt, wordt deze door het dominante terrein overspoeld. Eerst wordt het onderdanige terrein getekend en daarna wordt het dominante terrein met zijn eigen overgangsvorm getekend. Maar dit geldt niet bij ice, daarbij wordt altijd de eigen overgangsmethode gebruikt. En na lang testen wanneer de omringende tiles invloed hebben op welke richtig moest worden gebruikt is dit mijn uiteindelijke resultaat:
http://img684.imageshack.us/img684/7831/terrain04.png
No blend:
http://img38.imageshack.us/img38/351/terrain05.png
Origineel:
http://img546.imageshack.us/img546/2057/test03.png

Maar een paar zaken kloppen nog niet:
- Overgangsvorm in terrain.txt komt niet overeen met de afbeelding
- De overgangen in Age of Empires II komen niet 100% overeen met die ik produceer. Dit komt waarschijnlijk omdat de afbeelding niet klopt: Het grijs heeft RGB waarde 128, 128, 128, en het zwarte is natuurlijk 0, 0, 0. Dit betekend dat er een range is van 129 wat neer komt op 8 bits. Echter is het heel raar om 8 bits te nemen en vervolgens niet hoger te komen dan 128. Ik denk dat de afbeelding niet helemaal klopt en er slechts een range van 128 moet zijn wat wel gewoon 7 bits zijn.

- Ik heb nog een paar bugs in de code zitten, bijvoorbeeld in de berekening waarbij wordt berekend welke tile links boven in het scherm zit als er bekend is welke tile in het midden van het scherm zit.

Maar het grootste probleem is de snelheid: Het laatste voorbeeld duurde maarliefst 10 sec om te genereren. Nu heb ik natuurlijk niet de meest efficiente code van de wereld, maar 10 sec is simpelweg gestoord. Ik denk dat de PHP functies die ik gebruik niet adequaat zijn qua snelheid en ik op een realtime grafische engine moet gaan draaien. Nu kan dat natuurlijk niet in PHP en moet ik een applicatie schrijven. En al weet ik wel wat van C++ (kan text-only programma's schrijven en met visual C++ lukt het ook nog wel om knoppies te doen werken), is het boven mijn pet om met DirectX of OpenGL te werken. Heeft iemand wat tips hoe ik dit moet gaan doen?

Als er vraag is naar de sourcel, zal ik hem online zetten (pastebin ofzo?). Maar het is een bende, be prepared!
En als je er helemaal niks van snapt omdat ik te snel ga wil ik wel toelichting geven, maar als je er niks meer van snapt omdat ik te lelijk Nederlands heb, nou pech voor jou! :P

Volgende: Post 0x01 09-'11 Post 0x01

Reacties


Door Tweakers user Mar2zz, dinsdag 23 augustus 2011 18:50

lol wat een leuke puzzel. Ga er maar aanstaan.... Succes, hoop dat het je lukt.

Door Tweakers user Voxyn, dinsdag 23 augustus 2011 18:51

Volgens mij kan je heel simpel mbv XNA DirectX gebruiken is dit een optie?

Door Tweakers user DexterDee, dinsdag 23 augustus 2011 19:21

Ah, de klassieke isometrische tile-based engine. Altijd leuk om mee te beginnen als je games wil leren maken. Mijn complimenten voor deze eerste versie! Het is je gelukt om tot dusver het formaat en de rendering uit te pluizen en dat stukje oplossingsgericht denken is van groot belang als je dit een paar stappen verder wil zetten.

Allereerst, er zullen genoeg mensen zijn die je gaan vertellen dat dit niet in PHP moet. Deze mensen hebben uiteraard gelijk als je dit product voor een gameontwikkelaar aan het maken bent die daar z'n geld mee moet verdienen. Voor de hobbysfeer brengt het echter wel een hoop nieuwe uitdagingen met zich mee die met een beetje creativiteit goed op te lossen zijn.

Om in het PHP straatje te blijven zal ik hieronder een scenario schetsen waarbij je PHP kan blijven gebruiken en toch een paar stappen extra kunt zetten.

Het grootste probleem met het gebruik van PHP zit 'm mijns inziens niet in de rendersnelheid, want deze is met wat out-of-the-box denken wel effectief "op te lossen", maar eerder in het feit dat PHP niet gemaakt is om iets anders dan tekst te outputten (al dan niet interactief). Natuurlijk bestaan er wel initiatieven om GUI applicaties te maken in PHP, maar deze zijn niet geschikt om een game in te renderen.

PHP is voor low-level functies geen snelheidsmonster zoals je al weet. Vooral de pixelbewerkingen doen je de das om. Waar een gecompiled C++ programma moeiteloos met weinig CPU opcodes door een array van pixels loopt, heeft PHP last van de enorme overhead die nodig is om de taal goed te laten werken. Voor elke pixelbewerking worden in PHP talloze zaken gecheckt (opzoeken van de array key in de interne hash, moet ik de waarde typecasten?, etc..). Wil je snelheid in PHP, dan is het zaak om zoveel mogelijk high-level functies en extensies te gebruiken. Op het gebied van graphics zijn er een paar extensies als GD en ImageMagick. Deze zijn echter voornamelijk gemaakt voor manipulatie van images en niet zozeer om in een game engine te gebruiken.

Om het GUI probleem op te lossen kun je mijns inziens het beste zo dicht mogelijk bij de sterke punten van PHP blijven. Een mogelijkheid is om de webbrowser in te zetten als GUI. Hierin is grafisch veel mogelijk en de laatste jaren is er qua grafische snelheid het een en ander gebeurd (denk aan WebgGL, Canvas, HTML5) waardoor je met een beetje creativiteit hele mooie dingen kunt doen.

Het probleem van het trage renderen is een ander verhaal. Aangezien je isometric tiles gebruikt, kun je deze "pre-renderen" en opslaan als PNG bestanden. Je gebruikt nu bij het renderen de kleine tiles, zeg maar de kleinste eenheid in je terrein. Als je 5x5 van die tiles in een ruitvorm bijelkaar neemt en rendert tot een kant en klare grotere tile, dan kun je die kant en klare tile zonder pixelbewerkingen gebruiken. Het enige wat je dient te weten is de X en Y positie van de tile in je terrein.

Door de kant en klare tiles als het ware te "cachen" als kant en klaar PNG plaatje en klaar te zetten voor de webbrowser, kun je deze in een webapplicatie gebruiken. Nu is het alleen nog zaak om alles slim aan elkaar te knopen. De PHP code kent de layout van de tiles en HTML + JavaScript zorgt ervoor dat de tiles correct in de browser worden gerendered. Dit concept is niet nieuw, een goed voorbeeld is bijvoorbeeld Google Maps. Door slim gebruik te maken van uitwisseling tussen de backend en de frontend (AJAX JSON calls, COMET, etc,,,) zorg je ervoor dat de gebruiker ťťn interactieve applicatie voor z'n neus heeft.

Als het terrein vervolgens goed gerendered wordt, kun je eventueel met sprites gaan werken die je op het terrein rendert. Dat kunnen huisjes zijn of mannetjes die rondlopen. De enige beperking hierin is je eigen fantasie. In HTML5 kun je zelfs met audio en toetsenbord input werken om zo een wat "completere" spelervaring te creŽren.

Als het basisconcept eenmaal staat kun je met talloze variaties aan de slag. Je kunt bijvoorbeeld de terrein tiles pre-renderen op verschillende groottes, zodat de gebruiker het terrein kan zoomen. Als de gebruiker het speelveld wil roteren kun je ook van elke tile 4 aangezichten renderen.

De "maar" met bovenstaand scenario is wel dat slechts een gedeelte van je code in PHP geschreven kan worden. De interactieve elementen zullen toch echt in JavaScript gemaakt moeten worden. Ik denk echter dat het behoorlijk haalbaar is om iets moois in elkaar te zetten. Het zal nooit zo soepel en snel zijn als een native DirectX of OpenGL applicatie, maar het sluit denk ik wel veel meer aan bij je ervaring als webontwikkelaar.

Veel succes verder!

Door Tweakers user Ram0n, dinsdag 23 augustus 2011 19:40

Heel leuk om te lezen! Typisch van die dingetjes die ik ook leuk vind om uit te zoeken :) Ga je er nog mee verder? Zou het overigens leuk vinden om de source te zien hoor :) Pastebin is daar inderdaad goed geschikt voor, mocht je het willen laten zien.

Verder is het zoals hierboven beschreven zeker interessant om eens te kijken naar het inzetten van een browser; allerlei zaken als transparantie e.d. worden een stuk eenvoudiger (png) en je kan het eventueel ook nog interactief maken.

Door Tweakers user TeXiCiTy, dinsdag 23 augustus 2011 19:47

Als je toch de wondere wereld van OpenGL in durft te duiken kan ik Swiftless zijn blog zeker aanraden. Met minimale C/C++ ervaring heb ik zo stap voor stap aardig wat gigantische heightmaps op mijn scherm weten te toveren bij verbazingwekkend nette frama-rates.

Ik ben nu weer begonnen bij het begin omdat ik merkte dat mijn programmeerkunsten op een wel heel gammele fundering gebouwd waren (en omdat mijn projectsmap op een Vertex 2 stond zonder backup :X ), maar ik had al een aardig opzetje voor een terrain generator voor hexagonale tiles zoals in Civilization 5.

Het reverse engineeren lijkt je in ieder geval goed af te gaan! Dit lijkt me in ieder geval ook een leuk opstapje voor de beginnende hobby-ist programmeur.

Door Tweakers user CopperCAT, dinsdag 23 augustus 2011 20:27

Ik zou eens kijken naar wat SDL te bieden heeft. Portable, hw accelerated en optimaal voor low level gfx operaties :)
Oh en SDL heeft OpenGL bindings.

[Reactie gewijzigd op dinsdag 23 augustus 2011 20:29]


Door Tweakers user Sgreehder, dinsdag 23 augustus 2011 20:47

Hmm, iets met wiel en uitvinden. Maar je moet even weten waar je zoal op zoeken moet. Ik noem bijvoorbeeld:

http://ondra.zizka.cz/str...-isometric-libraries.texy

En op Wikipedia, wat algemener:

http://en.wikipedia.org/wiki/Isometric_projection

Door Tweakers user 4ourty2, dinsdag 23 augustus 2011 20:51

Programmeer ervaring had ik eigenlijk helemaal niet maar met sfml heb ik al mooie dingen gemaakt. Het is eigenlijk een soort sdl maar ik vind persoonlijk de leercurve van sdl iets stijler.

[Reactie gewijzigd op dinsdag 23 augustus 2011 20:51]


Door Tweakers user Tommasso, dinsdag 23 augustus 2011 21:20

@voxyn
Ik ga er meteen naar kijken!

@DexterDee
Thanks!

Het werken met PHP is idd nogal onhandig... Ik heb nu namelijk zo gemaakt dat nadat de output af is deze wordt opgeslagen in een bestand en deze daarna door de browser weer wordt ingeladen. Die 10 sec is dus enkel de PHP render-time, Firefox heeft nog ong 1 sec nodig om alles in te laden (vooral als ik hem op 1080 instel..., dan is die image ongeveer 2MB).

Het uitlezen en schrijven van pixels lijken idd het probleem te zijn. Tussen no-blend en blend zit een factor van 100 qua render-time. Met ImageMagick ed heb ik nog niet veel gewerkt. Dit project begon ook als uitdaging om meer met afbeeldingen te kunnen spelen :).

Ik had idd om de snelheidsproblemen in te demmen al een versie gemaakt waarbij de browser het renderen deed (dit was wel in <img style="position: absolute;"> stijl), maar dit was nog slomer. Met canvas heb ik nog niet veel gewerkt en ben ik ook nu mee aan het experimenteren. Ik heb wel iets wat enigzins vergelijkbaar is gevonden: http://www.canvasdemos.com/2010/12/13/bencity/. Maar dit project is op mijn computer erg sloom (scrollen duurt ~.5 seconden) en daar wordt (zo ver ik weet) nog niet eens geblend. Ik concludeerde eigenlijk dat canvas ook niet voldeed.

De tiles zijn als .GIF opgeslagen en worden enkel op de output image weggeschreven (tenzij blending nodig is). Ik heb al een cache met daarin al eerder gebruikte tiles in gebruik.
Het maken van 5x5 vlakken is een erg goed idee! Was is zelf niet op gekomen :). Al lijkt het mij wel dat je wel wat "logic overhead" gaat krijgen (elke keer moet je dus checken of de 24 andere tiles ook van dat type zijn, of de daar omringende tiles geen dominant terrein hebben en of er geen berg is. Al denk ik dat dit allemaal wel meevalt (is meer werk, bah :P).

Het genereren van terrein op het scherm moet wel haalbaar zijn in JS ed, maar stel dat we het hele scherm willen vullen met villagers welke lopen. Per tile kunnen er 5 villagers staan ofzo (schatting) en er kunnen 1920 / 96 * 2 * 1080 / 48 = 900 tiles in een scherm (en als je met bergen werkt kunnen het er nog meer zijn). Dus kunnen er 4500 villagers op een scherm passen. Maar als je bijv archers hebt schieten deze ook nog arrows en dus kan je zeggen dat er ~9000 items op een scherm staan. Ik denk eerlijk gezegd simpelweg dat zoiets niet haalbaar is met JS. Zelfs om dit in een native applicatie te kunnen laten draainen wordt denk ik al lastig...

Ik heb nog een paar dingen bedacht welke de CPU nog meer gaan belasten:
Zo schat ik in dat op een map van 256x256 het mogelijk is dat er rond de 80000 objecten kunnen zijn (hele map kan bomen zijn: 256 * 256 = 65536, er kunnen 8 players met 200 units rondlopen = 1600 welke meerdere kogels kunnen schieten (castle, chi yo) dus 1600 * 2, er kunnen gebouwen zijn (mss wel 1000 per player) dus 8000 en je hebt nog vogels ed). Er moeten dus constant 80000 objecten worden nagelopen op elke game-turn, ik denk dat hier aardig wat CPU power in gaat zitten.
Verder zijn de afbeeldingen allemaal in een .slp formaat opgeslagen. Dit is een formaat waar per bestand meerdere frame's worden opgeslagen (villager, walking is bijv 1 slp) Je kan de afbeeldingen niet zomaar als .GIF gaan opslaan omdat er player-colours zijn en als een unit achter een boom staat er een soort "glow" komt. Ik ben bezig met het uitfutsellen van dit formaat...

Ik denk zelf dat de browser een dood eind is (helaas, moet ik met DirectX/OpenGL werken, geen zin in)

btw, ik ben niet een webontwikkelaar, slechts een hobby-ist :). Die websites waren voor het vak Informatica.

@Ram0n
Ja, ik wil er wel mee verder gaan. Maar moet eerst echt die preformance issues oplossen. Daarna moet ik blendomatic.dat zelf helemaal doornemen (daar ben ik al aardig ver mee :))
Source zal ik zosnel mogelijk online zetten. Kan trouwens niet op pastebin, moet een zip worden (meerdere files, de tiles enz), was daar een goede plek voor? (normaal gooi ik dat op een willekeurige site van mij (freehost...), maar dat doe ik nu liever niet)

@ andere suggesties
Ik zal er allemaal naar kijken, maar neem wss de makkelijkste :P (Dat wordt denk ik DirectX, OpenGL vind ik lastiger te begrijpen zover ik er Łberhaupt iets van snap :).

@Sgreehder
Ja, wss vind ik het wiel opnieuw uit, maar ging mij vooral om het leren omgaan met afbeeldingen (dat was het oorspronkelijke doel)

Door Tweakers user Punkie, woensdag 24 augustus 2011 10:54

64K bomen? Ik denk dat je met 10 bomen toekomt. 10 unieke bomen. Dat je elk van die bomen 1000 keer op het terrein zet maakt voor de gamelogic niets uit. Het kopieren van de boomafbeelding in de schermbuffer zou snel genoeg moeten zijn. Das slechts 1 keer lezen en vervolgens 1000 adressen berekenen en 1000 stukjes geheugen kopieren. Tenslotte is een string ook maar een herhaling van dezelfde karakters en om de afbeeldingen van de letters te printen heb je ook niet veel tijd nodig.
Zelfde geld voor de mannetjes. 30 animaties en 10 kleuren maakt 300 "objecten".

Petje af voor wat je tot nu toe al verwezenlijkt hebt.
BTW ipv opengl te gebruiken kan je een rendering engine gebruiken van een hoger abstractieniveau waardoor je met wat standaard C++ kennis weg kunt komen. eg http://www.ogre3d.org/

Door Tweakers user DexterDee, woensdag 24 augustus 2011 10:57

Je rekent nu voor jezelf het worst-case scenario door en dat is waar je de fout ingaat. Met de maximale getallen zoals jij ze schetst zal Age of Empires het zelf ook moeilijk hebben. Sowieso is de kans erg klein dat het je gaat lukken om in je eentje de volledige featureset te implementeren van een AoE, in welke programmeertaal dan ook. Als dat al lukt ben je er jaren en jaren mee bezig.

Je hoeft geen 80.000 objecten te renderen, alleen alle objecten in je viewport. Dat scheelt sowieso al een hele hoop. Dit is zelfs uitermate essentieel voor bijvoorbeeld de performance in 3D spellen (frustom culling). Door klein te beginnen (niet te groot terrein, niet teveel objecten) kun je de performance redelijk op peil houden. Browsers van tegenwoordig zijn steeds meer krachtpatsers op grafisch gebied. Hier een paar voorbeelden:
http://webglsamples.googlecode.com/hg/aquarium/aquarium.html
http://data-arts.appspot.com/globe-search
http://people.mozilla.org/~jmuizelaar/fishie/fishie-gl.html
In het laatste voorbeeld kan ik met mijn laptop met 10.000 vissen op het scherm nog een framerate van 24/sec halen. Dat is al veel meer dan je ooit nodig zult hebben in de viewport van een spelletje als deze.

Als je je verwachtingspatroon en "scope" van je hobbyprojectje wat bijstelt, dan is de browser echt wel haalbare kaart.

Door Tweakers user l1dert, woensdag 24 augustus 2011 11:10

OpenGL is echt niet nodig hiervoor dit is een gewone 2D game. Het kan natuurlijk wel, maar het is ook prima mogelijk om dit op andere manieren te doen. Het eerder genoemde XNA Framework is relatief simpel om te gebruiken.

Maar ik denk dat het goed mogelijke is om dit in de browser te doen. Je kan proberen om het als javascript/html 5 app te bouwen. Waarschijnlijk moet je dan heel veel gaan optimaliseren. Een andere mogelijkheid is om een flash / silverlight te gebruiken.

Door Tweakers user Tommasso, woensdag 24 augustus 2011 13:52

Ik heb blendomatic.dat zelf ontleend met de onderstaande instructies (eerste succesvolle HEX-job, :P):

code:
1
2
3
4
5
6
7
8
9
10
11
12
uint32: nr of blending modes (9)
uint32: nr of tiles(31)
for (i=0;i<nr of blendingmodes)
{
  uint32: tilesize(2353, that`s 48*49 pixels);
  31bytes: tileflags(they are all 1);
  4*blocksize bytes which are 32 interleaved tiles representing 1 bit alpha masks, don't know how this is used for
  for (j=0;j<nr of tiles)
  {
    blocksize bytes: the actual tile pixels; starting from the top .. rendered in the isometric tile format
  }
}



Helaas komen ook bij mij pixels voor die de waarde 128 hebben. Dus ook ik heb te maken met een range van 129 (of ben ik gek en is een bereik van 0 tot met 128 slechts zeven bits lang?). Ik zie bij de overgang van grass naar desert duidelijk dat er te veel desert aanwezig is. Omdat grass hier het dominante terrein is, betekent dit dat de transparantie te hoog is. Immers wordt eerst desert getekend waar vervolgens het grass overheen getekend wordt. Omdat in PHP een hogere waarde betekent dat iets meer transparant is, is dus mijn alpha-waarde te hoog.

De functie waarmee het blendomatic.dat bestand heb ontleed:

PHP:
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
<?php
$fp = fopen("blendomatic.dat", "rb");

$blendmodes = fread($fp, 4);
$blendmodes = end(unpack("i", $blendmodes));
$directions = fread($fp, 4);
$directions = end(unpack("i", $directions));

for($i = 0; $i < $blendmodes; $i++){
    $pixelsPerTile = fread($fp, 4);
    $pixelsPerTile = end(unpack("i", $pixelsPerTile));
    fread($fp, 31); // skip data
    fread($fp, 9412); // skip 1-bit data
    for($ii = 0; $ii < $directions; $ii++){
        for($iii = 0; $iii < $pixelsPerTile; $iii++){
            $tmp = unpack("C", fread($fp, 1));
            $data[$i][$ii][$iii] = $tmp[1];
        }
    }
}
//print_r($data);
echo(ftell($fp));
for($i = 0; $i < $blendmodes; $i++){
    for($ii = 0; $ii < $directions; $ii++){
        $imageWidth = 1;
        $iii = 0;
        $half = FALSE;
        $output = imagecreatetruecolor(97, 49);
        for($row = 0; $row < 96; $row++){
            $xOffset = 48 - (int) floor($imageWidth / 2);
            for($col = $xOffset; $col < $xOffset + $imageWidth; $col++){
                imagesetpixel($output, $col, $row, imagecolorallocatealpha( $output, 128 - $data[$i][$ii][$iii], 128 - $data[$i][$ii][$iii], 128 - $data[$i][$ii][$iii], 0));
                $iii++;
            }
            if($imageWidth == 97) $half = TRUE;
            if($half == FALSE) $imageWidth += 4;
            else  $imageWidth -= 4;
        }
        imagepng($output, 'blendomatic_' . $i . '_' . $ii . '.png');
        imagedestroy($output);
    }
}
?>


En mijn blend functies:

PHP:
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
<?php
function imagealphamask($picture, $mask ) {
    // Get sizes and set up new picture
    $xSize = $GLOBALS['CFG']['imageWidth'];
    $ySize = $GLOBALS['CFG']['imageHeight'];
    $newPicture = imagecreatetruecolor( $xSize, $ySize );
    imagesavealpha( $newPicture, true );
    imagefill( $newPicture, 0, 0, imagecolorallocatealpha( $newPicture, 0, 0, 0, 127 ) );
   
    // Perform pixel-based alpha map application
    for( $x = 0; $x < $xSize; $x++ ) {
        for( $y = 0; $y < $ySize; $y++ ) {
            $alpha = imagecolorsforindex( $mask, imagecolorat( $mask, $x, $y ) );
            $alpha = 127 - round($alpha['red'] / 128 * 127); // Q&D fix!
            $color = imagecolorsforindex( $picture, imagecolorat( $picture, $x, $y ) );
            imagesetpixel( $newPicture, $x, $y, imagecolorallocatealpha( $newPicture, $color[ 'red' ], $color[ 'green' ], $color[ 'blue' ], $alpha ) );
        }
    }
   
    // Copy back to original picture
    imagedestroy( $picture );
    return $newPicture;
}
function getMask($bm, $index){
    return ImageCreateFromPNG('blendomatic_' . $bm . '_' . $index . '.png');
}
function blend($tileFrame, $mask){
    global $terrainTypes, $map, $CFG;
    global $mapCol, $mapRow;
    global $renderX, $renderY;
    global $result;
    global $terrain;
    global $tileFrameIndex, $filenamePostfix;
    
//  imagepng($mask, '' . (microtime(TRUE) - $time) . 'mask.png');
    $tmp = imagealphamask(ImageCreateFromGIF('G' . $terrainTypes[$terrain]['slp'] . leading_zeros($tileFrameIndex, 2) . $filenamePostfix), $mask);
//  imagepng($tmp, '' . (microtime(TRUE) - $time) . 'tmp.png');
    imagecopy($result, $tmp, $renderX, $renderY - $map['elevation'][$mapRow][$mapCol] * $CFG['imageHeight'] / 2, 0, 0, $CFG['imageWidth'], $CFG['imageHeight']);
}
?>


als iemand ergens een bug ziet, laat mij weten!

@DexterDee
Dat is inderdaad een worst-case scenario, en ik realiseer me dat ook Age of Emprires II zelf hier moeite mee zal hebben. Maar een situatie waar rond de 1000 units met elkaar vechten heb ik al vaak meegemaakt en moet ook gewoon kunnen. Alleen betwijfel ik of dit in een browser gaat lukken.
Met die 80.000 units had ik het niet over het tekenen ervan maar over het bijhouden ervan (de simulatie, schade opnemen, sterven maar ook bijvoorbeeld het verwijderen van de unit als deze opnieuw wordt verkend en in de tussentijd is verdwenen.). Er is een verschil tussen het enkel tekenen van objecten op het scherm en het werkelijk bijhouden van een simulatie/spel. Volgens mij kan je ervan uitgaan dat ongeveer 20 a 30% van de processor moet worden benut hier aan. Ik zal kijken of ik morgen tijd heb om met canvassen te gaan werken.
Overigens is die fishie bij mij niet sneller dan 5FPS. Ik denk dat mijn Firefox nogal verrot is :).

@l1dert
ik denk dat je gelijk hebt. Dat zijn zaken waar ik totaal geen verstand van heb.

Overigens als iemand anders behoefte heeft om aan dit project mee te helpen/werken zeg ik: elke hulp is welkom.

o ja, ook bij mij zijn er negen overgangsvormen uit de blendomatic.dat gekomen en zit ice blending op een verkeerde plek (zit hier nog een conversie tabel tussen ofzo?)

[Reactie gewijzigd op woensdag 24 augustus 2011 13:56]


Door Tweakers user SKiLLa, woensdag 24 augustus 2011 16:43

Had AoE 2 niet een unit-limiet van 200 per player ofzo ? En vergis je niet in HTML 5 hoor; de rendering is lightning fast, maar het is wel belangrijk dat je code ervoor geoptimaliseerd is en je de juiste technieken/methodieken/algo's gebruikt.

[Reactie gewijzigd op woensdag 24 augustus 2011 16:43]


Door Tweakers user Hipska, woensdag 24 augustus 2011 23:29

Ik heb mij ook eens bezig gehouden met html5/css3 en in JS dus een pathfinding algoritme uitgewerkt waarna het karakter dmv css3 animation naar de bestemming gaat.

http://dl.dropbox.com/u/1...ntend/documents/test.html

Edit: volgens mij enkel in webkit browsers, het is al een hele tijd geleden en moet het nog eens cross-browser maken.

[Reactie gewijzigd op woensdag 24 augustus 2011 23:30]



Reageren is niet meer mogelijk