offline
- Srki94
- Mod u pemziji
- Pridružio: 14 Feb 2008
- Poruke: 12403
|
+ v0.0.3 Napisano: 24 Jul 2014 19:41
0.0.3 Log
1. Privremeni UI
2. Trigger collideri
3. Waypoints
Manje bitne izmene :
- Popravljen loš odsjaj shadera usled lošeg "tilinga" normal mape na moru
To-Do
- Popraviti animaciju mora
- AI ekonomija
- Dorada AI Wander skripte
- Nadogradnje i menadžment konvoja
- ToDo 1 Optimizacija Draw poziva
- Pristup gradovima samo ukoliko je Konvoj blizu
- Collideri za zgrade unutar gradova i propratni UI
1. Dok se pojavi 4.6 (koji bi trebao ovog leta da se pojavi) proći će dosta vremena. Ovo je odlična prilika da naučimo kako da skaliramo UI elemente, napišemo ih kodom od nule i povežemo sa informacijama.
Napisao sam skriptu koja će prikazati jedan GUI prozor kada korisnik klikne na bilo koji grad. Skripta se nalazi u Game Manager objektu kao posebna JS skripta nazvana "GUI_Global".
Zamisao je da kada korisnik klikne na bilo koji grad, u "CityClickInfo" skripti pošaljemo ID broj grada toj skripti i prikažemo jedan prozor sa pozadinom na kome ćemo iscrtati label UI elemente za svaku komponentu. Svaki label element koji iscrtamo će povući informacije iz glavnog dvodimenzionalnog niza "Gradovi" koji drži sve informacije o svakom gradu.
Dakle : Klik na grad > City Click Info šalje parametar funkciji u GUI_Global skripti > GUi_Global skripta iscrtava prozor, label komponente i dodeljuje im vrednosti koje je našla u nizu pod tim parametrom.
Jedan od čestih problema u pisanju UI-a je to što će UI ostati na istom mestu bez obzira na rezoluciju, umesto da se skalira i pomera u zavisnosti od nje. Ja ću rešiti ovaj problem.
Pre svega sam napravio GUI Skin. GUI Skin je u suštini jedna komponenta koja sadrži teksture i stilove za korisnički interfejs. Jednom kada podesim GUI Skin po želji, mogu kasnije jednom linijom da ga dodelim trenutnom kodu za iscrtavanje UI-a i Unity će primeniti sve teksture na kontrole koje pravimo.
Drugi korak je naravno pisanje skripte.
Mogao sam na par načina da prikažem teksturu koju želim, međutim ja sam odlučio da nacrtam jedan prozor i unutar njega sve kontrole koje me interesuju.
Kako bi nacrtali ovaj prozor moramo da obezbedimo par parametara i jednu funkciju koja će biti zadužena za njega, za razliku od običnog pisanja komponenti linijama koda.
Svaki kod zadužen za GUI se piše u funkciji OnGUI ()
No, hajde da analiziramo delove koda :
1. Moram da pristupim skripti koja je zadužena za naš dvodimenzionalni niz.
2. Moram da deklarišem jednu promenljivu za GUI Skin
#pragma strict
var infoUI : CityInformation;
var skin : GUISkin;
var CityID : int ; // Ova promenljiva će nam služiti da prikažemo podatke
Kada skriptu prevučemo na neki gameObject prikazaće se dva nova polja koja trebamo da popunimo skriptom i skinom koji smo prethodno napravili.
Dalje, želim da kontrolišem šta će moja skripta da prikaže kada jer će biti zadužena za svo GUI iscrtavanje i imaće više prozora (Warehouse, Upgrade, Informacije, ...). Napisaću par booleana za tu svrhu :
var b_Info : boolean = false;
var b_Upgrade : boolean = false;
Vrednost im je 0 naravno jer nećemo imati nikakav UI dok korisnik ne klikne na grad.
Sada smo stigli do dela gde ćemo deklarisati promenljive za veličinu elemenata UI-a.
Možemo naravno da upišemo ove cifre kada pravimo komponentu, ali tada nećemo imati nikakvu kontrolu nad njima kasnije ukoliko nam zatreba.
Zato deklarišem ove promenljive:
// Velicine
private var size_lblX : int = 27 ;
private var size_lblY : int = 22 ;
var ekranX : int = Screen.width;
var ekranY : int = Screen.height;
var pos_lblOffset : int ;
// ProcentiTemp
var perc_lblX : float = 1.0;
var perc_lblY : float;
// Velicine prozora
private var prozorX : int = 1000 ;
private var prozorY : int = 700 ;
var prozor : Rect = Rect ( 15, 15, 0, 0);
prozor.width = prozorX;
prozor.height = prozorY;
Size_lblX i Size_lblY služe samo da nacrtaju kvadrat label komponente, ne da ga skaliraju, usled toga imaju statičnu vrednost i ne trebaju nam u editoru...
pos_lblOffset će nam kasnije služiti ukoliko želimo da provučemo kroz petlju iscrtavanje.
perc_lblX i perc_lblY će nam služiti da uvek držimo label na istom mestu kada skaliramo glavni prozor. Objašnjeno će biti u kodu kasnije.
ekranX i ekranY preuzimaju trenutnu rezoluciju ekrana i prema tome ćemo da skaliramo objekte kasnije.
Sada će nam trebati jedna nova funkcija koja će biti zadužena za iscrtavanje komponenti unutar prozora. Ovaj kod će nacrtati Label komponentu čija će lokacija uvek zavisiti od širine i visine našeg prozora.
function InformacijeProzor(windowID : int) {
GUI.Label (Rect(20.66/100*prozor.width, 10.3/100*prozor.height, size_lblX, size_lblY, infoUI.Gradovi[0,0].ToString());
GUI.DragWindow();
}
Vau, ogromna linija koda zar ne ? Vrlo je jednostavno zapravo, format koji sam ja koristio izgleda ovako :
(Rect(x pozicija, y pozicija, širina, visina, tekst)
Rect = [x,y, x,y] tj. Rect = [0,0, 0,0]
Dakle prva dva parametra su lokacije, druga dva veličine.
Umesto da dodelimo piksele kao vrednost, pri čemu bi label bio uvek na toj lokaciji bez obzira na veličinu prozora, mi lokaciju definišemo kao % X i % Y u zavisnosti od veličine ekrana ili u ovom slučaju prozora.
Ovde možemo to videti u akciji, ovaj label koji smo napravili ostaje na istom mestu bez obzira na veličinu glavnog prozora :
Na kraju, u OnGUI() funkciji ćemo iscrtati prozor ovako :
function OnGUI() {
GUI.skin = skin ; // Primenjujemo onaj skin od ranije ! Sve nakon ove linije koda će koristiti taj skin
if (b_Info) {
prozor = GUI.Window (0, prozor, InformacijeProzor, "");
}
}
Prvi parametar je ID prozora, drugi je Rect, treći je naša funkcija i četvrti naziv prozora - koji nama ne treba, stoga je prazan string.
Celo iscrtavanje stoji u uslovu i svaki put kada je b_Info vrednost 1, prozor će se iscrtati.
Kako je to sređeno sada, izmenićemo "CityClickInfo" skriptu koja se nalazi na svakom modelu gradova.
Ova skripta će sada imati vrlo jednostavan zadatak - da drži informaciju o ID-u grada i da je prosledi GUI_Global skripti, kako bi ona obradila isti i prikazala informacije.
#pragma strict
var guiInstance : GUI_Global ;
var CurrentID : int;
function OnMouseDown () {
if (Input.GetMouseButton(0)) {
guiInstance.CityID = CurrentID;
guiInstance.bInfo = true ;
}
}
S druge strane, CityInformation skripta se nalazi na "Game Manager" gameObjectu i drži sve informacije o našem nizu.
Na kraju, da ne bih pisao isti kod još 17 puta, napisao sam for petlju koja je to odradila za mene
perc_lblY = 21.01;
for (var i = 2; i<=19; i++) {
GUI.Label(Rect((16.27/100)*prozor.width, perc_Y_offset+(perc_lblY/100)*prozor.height , size_lblX, size_lblY), infoUI.Gradovi[CityID,i].ToString());
perc_lblY = perc_lblY + perc_Y_offset;
}
~ Edit :
Nekoliko izmena.
Donjim strelicama su prikazani delovi UI-a za koje sam upotrebio tu istu petlju, dok su strelice gore ručno postavljani elementi.
Na kraju ( po treći put ), ostalo je samo skaliranje. Možemo to da uradimo reformiranjem Vector3 promenljive i matrice GUI-a ovako :
scale.x = Screen.width/originalWidth;
scale.y = Screen.height/originalHeight;
scale.z = 1;
var tempMat= GUI.matrix;
GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, scale);
To-Do 1
Veliki je problem trenutno u "draw calls" broju. Što ih je više to više posla ima GPU i to su gore performanse. Broj koji ja trenutno imam na sceni je na skali prihvatljivosti od 0-10 negde oko 30.
Najveći problem dolazi od terena koji ima preko 700 poziva.
Postoji par načina da se ovo reši međutim oni nisu baš tako jednostavni za free verziju.
Jedno od rešenja koje trenutno razmatram je eksportovanje terena a zatim obrađivanje istog u Blenderu. Ovde sam napravio mali test i jasno se vidi poboljšanje :
Prvi screenshot je eksporotvan i obrađen teren u Blenderu sa par tekstura i jednom velikom UV Mapom. Desno je stock teren. Jasno se vidi razlika u pozivima iscrtavanja kao i u FPS-u.
Pokušao sam da iskoristim i par poznatijih skripti za poboljšavanje ovog problema, međutim nisu radile kod mene, tako da ću videti kako ću rešiti problem. U suštini ukoliko mogu da izvučem isti kvalitet tekstura terena najverovatnije ću ga u Blenderu obraditi.
2. Jedna od ideja za poboljšanje prve igre su bile kritične zone u kojima igrače može da opljačka AI i ukrade im resurse. Ova ideja nastavlja svoj život u Raize 3D takođe!
Ideja je da ako igrač ikada prođe kroz šumu, postoji 20% šanse da ga opljačka AI.
Vrlo jednostavna mehanika.
Napravio sam jednu kutiju unutar samog Unityja, zatim sam čekirao "Is trigger" u Box Collider komponenti i odčekirao "Mesh Renderer". Sada imamo jedan zeleni collider bez renderera :
Kako ću imati još par drugih collidera na sceni, dodao sam "Tag" ovom collideru koji će koristiti svaki drugi na sceni. Kasnije ćemo proveriti kada dođe do "sudara" između objekta i collidera da li je taj collider "Wood" ili ne i prema tome ćemo pisati određeni kod. Tag se lako dodaje :
1. Klik na Tag > Add Tag ; 2. Upisati ime taga u prvom slobodnom polju.
Sledeći korak je dodavanje Rigidbody komponente na naš model koji će prolaziti kroz ove collidere. To je Convoy u našem slučaju.
Dodavanje rigidbody komponente je jednostavno - kliknite na "Add component" dugme u Inspektoru i upišite "Rigidbody", zatim potvrdite selekciju.
Vrlo bitna opcija kod Rigidbody komponente je "IsKinematic". Ona je kod mene čekirana a njeno stanje označava vrlo bitno ponašanje - hoće li fizika biti primenjena na objekat ili ne.
Sve što je ostalo sada je da napišemo skriptu koja će proveravati ponašanje.
Za ovaj primer koristim proveru i Debug.Log :
function OnTriggerEnter (Meta : Collider) {
Debug.Log ("Konvoj je usao u collider") ; // Mala provera koja će mi potvrditi da sve radi kako je očekivano.
Debug.Log (Meta.tag); // Ispisaće tag u konzoli collidera
// PROVERA TAGA :
if (Meta.tag == "Wood") {
// Neki kod koji će uraditi nešto ako je igrač ušao u šumu
}
else {
// Neki drugi kod
}
}
Mi smo rekli da želimo da igrača nasumično pljačka AI i da postoji neki procenat, veoma lako možemo da napravimo tu mogućnost upotrebom Random.Range :
Random.Range (0,100);
If (promenljiva >= neki_broj) {
// Neki kod koji će primeniti pljačkanje ili nešto drugo
}
Veoma jednostavno, zar ne ?
Vršio sam neka testiranja fiksnog kretanja takođe no o tome nešto više u youtube verziji ili tek u sledećoj verziji.
YT
GH
Download Raize3D 0.0.3 :
Web
Windows
Linux
Dopuna: 01 Avg 2014 19:44
0.0.4. Log
1. Sistem trgovine
- 1.2 Različiti preseti cena
- 1.3 Sistem gubljenja reputacije
2. Pod sistemi
- Katastrofe
- Bust produkcije
- Godišnja doba
3. GUI Top Layer
To-Do
- Kvestovi
- AI ekonomija
- Dorada AI Wander skripte
- Nadogradnje i menadžment konvoja
- ToDo 1 Optimizacija Draw poziva
- Pristup gradovima samo ukoliko je Konvoj blizu
- Collideri za zgrade unutar gradova i propratni UI
To-Do-2 :
- Elementarne nepogode
-- Dinamično kretanje oblaka i nanošenje štete gradovima
- Ratovi
1. Završen je sistem trgovine.
Trgovina ovako radi :
Igrač ima ograničen novac i ograničeno mesto u konvoju. Kada dođe u grad može da kupuje po 10 resursa. Kako se resursi smanjuju u gradu, u zavisnosti od populacije tog grada, tako se i cene povećavaju. Takođe, kako se resursi smanjuju, tako će se smanjivati i igračeva reputacija u tom gradu, na šta možemo da "nakačimo" neke negativne mogućnosti...
Znamo od ranije da držimo sve podatke o resursima svakog grada u dvodimenzionalnom nizu "Gradovi". Sve resurse jednog konvoja držimo u "Convy" nizu. Sve informacije o igraču držimo u "Player" nizu.
Kako bi ovaj sistem radio, trebaće nam još par promenljivih koje će držati podatke. Cilj je da ovaj kod učinimo što dinamičnijim kako bi kasnije mogli da menjamo bilo koji deo tokom igre.
Deklarišemo nove nizove :
ActualPrices [18,2] - Biće zadužen za držanje svih aktivnih vrednosti cena koje ćemo prikazati igraču
PricePresets [18,3] - Ćemo koristiti da sačuvamo tri različite cene za svaki proizvod.
PopulationPresets[6,3] - Koristimo da definišemo tri vrednosti :
Minimalnu - Onu vrednost gde će cena biti minimalna ukoliko tog resursa ima više od ove vrednosti
Srednju - gde će cena biti srednja ukoliko proizvoda ima između ove i minimalne vrednosti i
Maksimalnu - kada je cena maksimalna i važi ako grad ima manju vrednost resursa od ove vrednosti
Logika iza ovog niza je populacija inače, prvi indeks važi za grad od 100-500 ljudi, drugi indeks za grad od 500-1000 i tako dalje.
var ActualPrices = new int [18,2]; // Array containing buy and sell price for each commodity
var PricePresets = new int [18,3]; // Array that contains different population presets for each commodity
var PopulationPresets = new int [6,3]; // Array that will be used to figure out which preset to show from PricePresets
GameInformation skripta (Preimenovana iz CityInformation jer je sada njena upotreba daleko kompleksnija)
Prvo ćemo definisati različite populacije na ovaj način :
PopulationPresets [0,0] = 150; // 100-500 MIN PRICE
PopulationPresets [0,1] = 100; // 100-500 MID PRICE
PopulationPresets [0,2] = 0; // 100-500 MAX PRICE
PopulationPresets [1,0] = 200; // 500-1000 MIN
PopulationPresets [1,1] = 150; // 500-1000 MID
PopulationPresets [1,2] = 0; // 500-1000 MAX
// ...
Zatim ćemo napisati jednu funkciju koja prihvata jedan parametar i koja će biti zadužena da uporedi vrednosti iz dva niza kako bi unela nove vrednosti u treći niz.
function PriceCalc(ID : int) {
}
Unutar nje prvo moramo da obradimo prvi indeks PopulationPresets niza. To činim pisanjem bloka uslova koji proveravaju da li je populacija grada koji je aktivan veća ili manja od neke vrednosti u tom nizu. U zavisnosti od toga dajem novoj promenljivoj deklarisanoj unutar te funkcije novu vrednost, koju ćemo koristiti kao indeks kasnije.
var Populacija : int ;
//Debug.Log (ID);
if (Gradovi[ID,0] <= 500 ){
Populacija = 0;
}
else if (Gradovi[ID,0] > 500 && Gradovi[ID,0] <= 1000){
Populacija = 1;
}
else if (Gradovi[ID,0] >1000 && Gradovi[ID,0] <= 2000){
Populacija = 2;
}
else if (Gradovi[ID,0] > 2000 && Gradovi[ID,0] <= 3000){
Populacija = 3;
}
else if (Gradovi[ID,0] > 3000 && Gradovi[ID,0] <= 4000){
Populacija = 4;
}
else if (Gradovi[ID,0] > 4000){
Populacija = 5;
}
Sada ću uporediti svaku vrednost niza Gradovi - vrednost resursa, sa sve tri vrednosti drugog indeksa niza PopulationPresets.
Sve to će propratiti uslovi koji će nam lepo sortirati svaku vrednost u novi niz koji ćemo prikazati igraču.
Hajde jedan praktičan primer da pogledamo :
Grad ima 500 stanovnika.
Maksimalno povoljnu cenu igraču prikazujemo ukoliko taj grad ima više od 150 resursa.
Srednju ukoliko ima negde između 100 i 150.
Najskuplju ukoliko ima ispod 100.
Recimo da taj grad ima 150 jabuka.
Ja želim da proverim koliko taj grad ima jabuka i uporedim sa ovom šemom gore.
Ukoliko grad ima više od 150 jabuka, pristupiću nizu sa cenama svakog resursa (Koji je, setimo se, treći niz koji drži 3 cene za svaki proizvod) i uzeću njegovu najjeftiniju vrednost, kako bih je prosledio igraču.
Da je grad imao između 100 i 150 jabuka, uzeo bih srednju cenu, dok da je imao ispod 100 jabuka, igrač bi morao da plati najvišu cenu po jabuci.
Dakle, prvo upoređujem aktuelnu vrednost količine resursa sa onim presetom iznad :
if (Gradovi[ID,i] >= PopulationPresets[Populacija,0]){ // If commodity i in Gradovi array is larger or equal to min price field
U tom slučaju, želim da prosledim nizu "ActualPrices" (Koji, setimo se, drži aktivne cene koje prikazujemo korisniku) najnižu vrednost za taj resurs.
ActualPrices[ceneB,0] = PricePresets[ceneB,0]; //Set buy price of that item in PricePresets array to lowest
ActualPrices[ceneB,1] = PricePresets[ceneB,0]; // Set sell price of that item in PricePresets array to lowest
Ovde takođe možemo da vidimo da imam dva indeksa u ActualPrices nizu za drugi indeks. Broj 1 predstavlja prodajnu cenu, broj 0 kupovnu cenu. One su sada iste, međutim možda kasnije želim da dodam neku novu mogućnost koja će mi smanjiti sve prodajne cene u gradu gde nisam popularan, ili suprotno - poveća.
Zatim pišem drugi deo provere :
else if (Gradovi[ID,i] < PopulationPresets[Populacija,0] && Gradovi[ID,i] >= PopulationPresets[Populacija,1]) {
ActualPrices[ceneB,0] = PricePresets[ceneB,1]; // Set sell price of that item in PricePresets array to mid
ActualPrices[ceneB,1] = PricePresets[ceneB,1]; // Set sell price of that item in PricePresets array to mid
Kao i treći deo provere, koji će raditi isto ovo sem što ćemo napisati drugačiji uslov.
Sve ovo se nalazi u for petlji koja ima dva brojača : ceneB i i.
ceneB je brojač koji počinje od 0. dok je i brojač koji počinje od 2 a završava brojanje na 19.
Ovo je zato što nam je glavni niz Gradovi tako sačinjen da sve vrednosti počinju od trećeg unosa - tj. 2.
Kada se ovaj kod iskompajlira, dobijemo novi niz koji sadrži sve naše cene u zavisnosti od populacije i svakog resursa ponasob.
Hajde da izmenimo GUI_Global skriptu kako bi osvežili sve te vrednosti i prikazali ih igraču.
Unutar naše glavne GUI For petlje menjamo sledeće redove :
GUI.Label(Rect((24.0/100)*prozor.width, perc_Y_offset+(perc_lblY/100)*prozor.height , size_lblX, size_lblY), infoUI.ActualPrices[cnt_Prices,0].ToString()); //Buy Price
GUI.Label(Rect((40.0/100)*prozor.width, perc_Y_offset+(perc_lblY/100)*prozor.height , size_lblX, size_lblY), infoUI.ActualPrices[cnt_Prices,1].ToString()); // Sell price
Sada će ove label komponente vući podatke iz ActualPrices niza.
Zatim vršimo neke logične uslove unutar samih dugmadi za prodaju resursa, kako igrač ne bi mogao da kupi resurs ukoliko nema mesta u konvoju ili dovoljno novca.
if (GUI.Button(Rect((28.2/100)*prozor.width, perc_Y_offset+(perc_btnY/100)*prozor.height , 53, 27), "+10")){ //Buy Dugme
//Debug.Log (infoUI.Gradovi[CityID,i]);
if ((infoUI.Player[0] - infoUI.ActualPrices[cnt_Prices,0]*10 >=0) && (ukupno + 10 <= infoUI.Convoys[0,0]) && (infoUI.Gradovi[CityID,i] - 10 >= 0)){
Dakle druga provera "kaže" ovo :
Ukoliko je rezultat oduzimanja vrednosti cene resursa (puta deset) od vrednosti igračevog zlata veća ili jednaka nuli (Što znači da ako igrač kupi taj resurs neće ostati u minusu) i ukupni broj resursa u konvoju + 10 je manji ili jednak maksimalnom kapacitetu konfoja, i ukoliko će grad, kada oduzmemo 10 od te vrednosti, imati resurse nakon završene prodaje, uradi sledeći kod.
Drugim prostijim rečima :
Zlato igrača : 5000
Cena resursa : 50
Kapacitet konvoja : 250
Kapacitet resursa u gradu : 20
Ako će Zlato igrača - Cena resursa biti više ili jednako 0 i
Ako će Ukupna suma svih resursa u konvoju + 10 biti manja ili jednaka 250 i
Ukoliko će Kapacitet resursa u gradu - 10 biti 0 ili više od deset, tek onda ćemo izvršiti kod.
Sledeće linije su kod koji će se izvršiti ako se svi uslovi ispune :
infoUI.Gradovi[CityID,i] -= 10;
infoUI.Player[0] -= (infoUI.ActualPrices[cnt_Prices,0]*10);
infoUI.Player[i] = infoUI.ActualPrices[cnt_Prices,0];
infoUI.Convoys[0,i] += 10;
infoUI.PriceCalc(CityID);
infoUI.RepFading(CityID,i);
Prvo oduzimam 10 od aktuelne vrednosti resursa.
Zatim oduzimam cenu puta 10 (jer kupujemo 10 resursa) od cene zlata
Zatim ažuriram poslednju kupljenu cenu igrača - poslednja cena po kojoj je neki resurs kupljen je ranije dodata u niz Player.
Na kraju, šaljem ponovo zahtev za osvežavanje cena GameInformation skripti i toj funkciji prosleđujem parametar CityID - koji je parametar koji označava grad.
Poslednja linija koda ima veze sa drugom funkcijom koja je zadužena za spuštanje reputacije.
Kada pokrenete igru, videćete da kada kliknete na grad sve radi savršeno, cene su dinamične i menjaju se u odnosu na resurse i populaciju. Razlikuju se od grada do grada i slično.
1.2 Smanjivanje reputacije
Kako bi se vi osećali da neki gasterbajter sa 250k evra upadne u vaš grad i kupi svu pijaću vodu? Mrzeli bi ga
Isto će se to desiti ukoliko to uradite u Raize igri.
Ovaj kod mi je pravio veliki problem jer sam hteo da spasim mesto, međutim na kraju sam završio tako što sam napisao novu funkciju za njega.
Funkcija se nalazi u novoj "GodMode" skripti i prima dva parametra : CityID i ID. Nova skripta nam treba kako bi odvojili slične funkcije od GameInformation skripte jer će ih verovatno biti mnogo ubuduće.
Ovaj sistem radi tako što će "puniti" jednu promenljivu do 10, svaki put kada igrač kupi resurs koji je pri nestašici u gradu. Jednom kada pređe 10 igrač će dobiti -1 reputaciju u tom gradu.
Postoji razlika trenutno u tome što će igrač dobiti po 5 "kaznenih" poena ukoliko je vrednost baš pri velikoj nestašici dok će inače dobijati po 3 ukoliko je pri srednjoj nestašici.
Hajde da analiziramo kod...
Pre svega moram da povežem naše skripte :
var GodMode : GameInformation ;
GodMode = GetComponent(GameInformation);
Zatim pravim novu funkciju :
function RepFading (CID: int, ID:int){
var normalized : int = ID - 2;
}
Normalized je promenljiva koja će oduzeti 2 od indeksa koji ću proslediti iz GUI skripte. Ovo radim zato što mi je niz Gradovi napravljen na taj način da se resursi nalaze od 2-19 u njemu.
Sada ću napisati uslov. Ukoliko je vrednost aktuelne cene jednaka srednjoj vrednosti iz Preseta kog smo definisali ranije, onda ću dodati 3 kaznenih poena.
if (GodMode.ActualPrices[normalized,0] == GodMode.PricePresets[normalized, 1]) {
GodMode.ReputationModifier[normalized] +=3;
}
Unutar tog upita ću takođe proveriti da li ta nova vrednost prelazi 10 :
if (GodMode.ReputationModifier[normalized] >= 10){
GodMode.ReputationModifier[normalized] -=10;
GodMode.Gradovi[CID,1] -=1;
}
Ukoliko jeste, oduzeću 10, ukoliko ima ostatka on ostaje tu gde jeste a ja samo "resetujem" brojač i dalje oduzimam 1 % reputacije gradu.
Drugi deo koda je isti samo što pokriva kritične vrednosti.
Funkciju pozivamo iz GUI_Global skripta ovako :
infoUI.PriceCalc(CityID);
2. Podsistemi
2.1 Katastrofe
Takođe sam napisao funkciju koja obrađuje sledeću logiku :
Postoji 10% šanse da se desi neka katastrofa u gradu.
Ukoliko će biti katastrofe nasumično biram njen tip.
Postoji tri zamišljenih tipova katastrofa : Požar, cunami i grip.
Vrlo jednostavna funkcija koja koristi Random.Range kao bazu.
2.2 Boost produkcije
Je funkcija koja prima dva parametra - ID grada i tip busta. U zavisnosti od toga će grad imati dodatni bust na građevine koje prave resurse...
2.3 Godišnja doba
Ovu mehaniku kontroliše jedan tajmer koji je podešen na 180 sekundi. Update funkcija oduzima sekundu po sekundu od vrednosti, jednom kada dođe ta vrednost na 0, resetuje se na 180 a godišnje doba se menja, pri čemu daje druge pogodnosti ili nepogodnosti igraču...
3. GUI Top Layer
Pod ovim podrazumevam onaj glavni i prvi sloj koji je vidljiv uvek !
Hteo sam da nateram Unity da mi pomogne tako što ću koristiti integrisane GUi teksture i slično, međutim ispostavilo se da je to više loše nego dobro - jako je teško bilo podesiti veličine i slično...
Na kraju, kako već koristim GUI matricu da skaliram elemente, odlučio sam da ispišem ceo prvi sloj upotrebom skripte.
Nije teško i zapravo je potpuno isto kao i prethodni GUI ...
Prvi sloj GUIa se sastoji od jedne statusne trake koja je na početku ekrana. Ona sadrži "menu" dugme koje otvara novi prozor sa novim mogućnostima. Nekoliko informacija poput trake sa tekstom, datumom, godišjnim dobom i zlatom igrača. Takođe od jednog prozora koji se nalazi sa desne strane i koji je animiran kodom. On sadrži informacije o konvoju i kasnije će nam služiti za prikaz drugih informacija.
Statusna traka je zapravo jedna box komponenta sa teksturom koja počinje od 0,0, ima 25 piksela širine i 1920 piksela dužine.
GUI.Box (Rect(0,0,1920,25), "");
Prethodno smo definisali novi gui skin koji smo napravili zao vu priliku.
Zatim sam iscrtao dugme "Menu" koje kontroliše boolean (koji koristimo kao trigger) :
if (GUI.Button(Rect(0,0, 75,25), "Menu")){
if (b_MenuWindow){
b_MenuWindow = false ;
//Debug.Log ("MenuWindow false");
}
else if (!b_MenuWindow) {
b_MenuWindow = true;
//Debug.Log ("Menu Window true");
}
}
Ostalo je samo da prikažemo ostatak kontrola u zavisnosti od stanja tog booleana :
if (b_MenuWindow){
GUI.Box (Rect(0,25,140,161),"");
GUI.Button (Rect(20,35, 80, 25), "Save");
//...
Takođe je ostalo iscrtavanje label komponenata iznad ove trake, no to je pokriveno još u prošloj verziji tj. kod je potpuno isti ...
Kada je prozor u pitanju, deo koda koji ga iscrtava je isti kao i onaj koji iscrtava Info prozor iz prošle verzije, stim što imamo jedno novo dugme koje moramo da animiramo.
Animiranje se vrši u Update funkciji.
Prvo ću proveriti da li je mover bool aktivan, ukoliko jeste dodavaću našoj X vrednosti prozora neki broj i svo vreme proveravati da li je taj broj veći od maksimalno dozvoljenog broja. Ukoliko jeste, podesiću ga kao maksimalni broj i isključiti bool.
if (mover){
convoys_prozor.x += smoothanim*3;
if (convoys_prozor.x >= 1478){
convoys_prozor.x = 1478;
movel = false;
mover = false;
//anim_time = 0.0;
}
Dakle, pomeramo prozor i svo vreme proveravamo da li je na tačnoj poziciji.
Zašto ponovo podešavamo X poziciju na 1478? Jer može da se desi nešto neočekivano tokom rada pa da ta maksimalna vrednost ne bude 1478 već recimo 1480... što bi pomerilo ceo prozor dva piksela dalje nego što treba.
Drugi deo ovog koda je suprotnost toga pa ćemo oduzimati od X vrednosti kako bi vratili prozor na mesto tj. otvorili ga...
Komponente unutar prozora su iste kao i kod iz prethodne verzije...
Takođe, dugmad poput "Return to world" i label o verziji sam pomerio u GUI_Global skriptu a te dve skripte obrisao pa sada naš GameManager gameObject ima tri skripte : GameInformation, GUI_Global i God_Mode.
Informacije
Preuzimanje : Windows i Linux x86_x64 Uni
Web player
GitHub : https://github.com/Srki94/Raize3D/releases/tag/v0.0.4
YT
|