/// <summary> /// Rajzolás /// </summary> /// <param name="obj">Kirajzolandó objektum</param> /// <param name="rect">Pozíció a képernyőn</param> /// <param name="Clickable">Kattintással átrajzolható legyen-e</param> public static void Draw(ref Objects.Obj obj, Rect rect, bool Clickable = false) { int WScale = (int)(rect.width / obj.X); // Szélességet pontosan kitöltő pixelméret int HScale = (int)(rect.height / obj.Y); // Magasságot pontosan kitöltő pixelméret int Scale = Math.Min(WScale, HScale); // Az legyen a végső méret, amelyik kisebb (sehol ne lógjon ki, de legyen maximális méretű, és négyzetekből álljon) int Left = (int)(rect.x + (rect.width - obj.X * Scale) / 2); // Bal oldali behúzás int Top = (int)(rect.y + (rect.height - obj.Y * Scale) / 2); // Felső behúzás bool Clicked = Clickable && Input.GetMouseButtonDown(0); // Módosítandó-e a pixel az egér helyén Vector2 MousePosition = new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y); // Korrigált egérpozíció for (int xPos = 0; xPos < obj.X; ++xPos) // Oszloponként { for (int yPos = 0; yPos < obj.Y; ++yPos) // Soronként { int Pixel = xPos + yPos * obj.X; // Pixel helye a pixeltömbben Rect Position = new Rect(Left + xPos * Scale, Top + yPos * Scale, Scale, Scale); // Pixel helye a képernyőn if (obj.Image[Pixel] % 2 == 1) // Aktív pixel esetén... { GUI.DrawTexture(Position, _Foreground); // ...rajzoljon oda egy előtérszínű négyzetet } if (Clicked && Position.Contains(MousePosition)) // Ha a pixelre kattintott a felhasználó, és engedélyezve van a módosítás { if (obj.Image[Pixel] < 2) // Első OnGUI futás (képkockánként kétszer fut végig) { obj.Image[Pixel] = obj.Image[Pixel] == 0 ? (byte)3 : (byte)2; // A pixel értéke legyen ellentétes, és adjon hozzá kettőt } // E módon tudjuk, ha második OnGUI lefutás jött, és ne invertáljuk újra a pixelt else // Második OnGUI futás { obj.Image[Pixel] -= 2; // Az előbb hozzáadott kettő kivonása, érvényes állapotba állítás } } } } }
/// <summary> /// Induláskor azonnal lefut /// </summary> void Start() { int AfterBackslash = Path.LastIndexOf('\\') + 1; // Fájlnév kezdetének helye a fájl elérési útvonalában SaveAsID = Path.Substring(AfterBackslash, Path.LastIndexOf('.') - AfterBackslash); // Fájlnév, azaz mentési azonosító Image = Objects.LoadObject(Path); // Kép betöltése a megadott helyről OriginalImage = Objects.CopyObject(Image); // Eredeti állapot eltárolása SaveBG = new Texture2D(1, 1); // Új 1x1-es textúra a mentés másként menü hátterének SaveBG.SetPixel(0, 0, new Color(0, 0, 0, .8f)); // Enyhén átlátszó fekete szín beállítása SaveBG.Apply(); // Színezés alkalmazása }
/// <summary> /// GUI-kezelő függvény /// </summary> void OnGUI() { int LevelWidth = 84; // Szint szélessége, minimum 84, hogy ne legyen 0 széles a kép üres pályán int ScreenHeight = Screen.height - 120; // Kép magassága int Block = ScreenHeight / 48; // Blokkméret int EnemyCount = Enemies.Length; // Ellenségek száma for (int i = 0; i < EnemyCount; ++i) // Ellenségeken végighaladva { int BackDistance = Enemies[i].X + Models[Enemies[i].EnemyID].X; // Ellenség jobb széle if (LevelWidth <= BackDistance) // Ha az ellenség távolabb van, mint az eddigi legtávolabbi ismert pont { LevelWidth = BackDistance + 1; // Legyen ott a pálya megjelenítésének vége, és maradjon mellette egy oszlop szabad hely } } ////////////////////// // Szint megjelenítése ////////////////////// // Görgethető nézet kezdete Scrolling = GUI.BeginScrollView(new Rect(300, 0, Screen.width - 300, ScreenHeight + 20), Scrolling, new Rect(0, 0, LevelWidth * Block, ScreenHeight)); Vector2 FixedMouse = new Vector2(Input.mousePosition.x - 300, Screen.height - Input.mousePosition.y) + Scrolling; // Javított egérpozíció for (int i = 0; i < EnemyCount; ++i) // Ellenségeken végighaladva { Objects.Obj Model = Models[Enemies[i].EnemyID]; // Az itteni ellenség megjelenése Rect EnemyBounds = new Rect(Enemies[i].X * Block, Enemies[i].Y * Block, Model.X * Block, Model.Y * Block); // Az itteni ellenség határai if (GUI.Button(new Rect(EnemyBounds.xMax, EnemyBounds.yMin + 25, 20, 20), Directions[Enemies[i].Movement])) // Mozgásirány gomb { Enemies[i].Movement = (Enemies[i].Movement + 1) % 3; // Mozgásirány váltása } if (GUI.Button(new Rect(EnemyBounds.xMax, EnemyBounds.yMin, 20, 20), "X")) // Törlés gomb { int NewEnemyCount = Enemies.Length - 1; // Ellenségek új száma Enemies[i] = Enemies[NewEnemyCount]; // A tömbben rakja az utolsót a jelenlegi helyre... Array.Resize(ref Enemies, NewEnemyCount); // ...majd vágja le a végét --EnemyCount; // Ellenségszám csökkentése, hogy a későbbiekben ne legyen túlhivatkozás } if (Input.GetMouseButtonDown(0) && EnemyBounds.Contains(FixedMouse)) // Ha az ellenségre lett kattintva: { Grabbed = i; // Megfogás LastMousePos = Input.mousePosition; // Utolsó egérpozíció a megfogás helyén MouseMovement = new Vector2(0, 0); // Elmozdulás nullázása } Graphics.Draw(ref Model, EnemyBounds); // Ellenség kirajzolása } /////////////////// // Jobbklikkes menü /////////////////// if (RightClick) // Ha meg van nyitva a jobbklikkes menü { Rect BoxRect = new Rect(RightClickPos, new Vector2(200, 80)); // A menü határai GUI.Box(BoxRect, "New enemy"); // Doboz rajzolása a menünek if (PrevEnemy.CompareTo(TargetEnemy) != 0) // Ha az előző képkocka óta változott a beírt ellenség azonosítója { Exists = File.Exists(EnemyFolder + TargetEnemy.ToString() + ".dat"); // Létezik-e ilyen fájl PrevEnemy = TargetEnemy; // Az előző beírt ellenség legyen a jelenlegi } bool Okay = GUI.enabled = Menu.IsNumeric(TargetEnemy); // Érvényes azonosító van-e megadva, attól függően legyenek engedélyezve a gombok GUI.color = Okay ? Color.white : Color.red; // Ha érvénytelen azonosító van megadva, legyen vörös a beviteli mezeje if (GUI.Button(new Rect(RightClickPos.x + 5, RightClickPos.y + 25, 20, 20), "-")) // Csökkentés gomb { TargetEnemy = (Convert.ToInt32(TargetEnemy) - 1).ToString(); // Azonosító csökkentése } GUI.enabled = true; // Az azonosítóbevitel semmiképp ne legyen letiltva TargetEnemy = GUI.TextField(new Rect(RightClickPos.x + 30, RightClickPos.y + 25, 70, 20), TargetEnemy); // Azonosító beviteli mezeje GUI.enabled = Okay; // Ha érvényes azonosító van megadva, engedélyezze a további gombokat if (GUI.Button(new Rect(RightClickPos.x + 105, RightClickPos.y + 25, 20, 20), "+")) // Növelés gomb { TargetEnemy = (Convert.ToInt32(TargetEnemy) + 1).ToString(); // Azonosító növelése } GUI.color = (GUI.enabled = Exists) ? Color.white : Color.red; // A hozzáadás gomb akkor legyen megnyomható és nem vörös, ha létezik a beírt ellenség if (GUI.Button(new Rect(RightClickPos.x + 130, RightClickPos.y + 25, 65, 20), "Add")) // Hozzáadás gomb { int NewEntry = Enemies.Length; // Új azonosító helye a tömbben int ID = Convert.ToInt32(TargetEnemy); // Az ellenség azonosítója számra konvertálva Array.Resize(ref Enemies, NewEntry + 1); // Új hely létrehozása a tömbben Enemies[NewEntry] = new Enemy() // Az új helyre hozza létre az új ellenséget: { X = (int)RightClickPos.x / Block, // A kattintás szélességi pozícióján Y = (int)RightClickPos.y / Block, // A kattintás magassági pozícióján EnemyID = ID, // A megadott azonosítóval Movement = 0, // Függőleges mozgás nélkül }; LoadModel(ID); // Grafika betöltése az új ellenséghez RightClick = false; // Jobbklikkes menü bezárása } GUI.enabled = true; // A felület legyen engedélyezve a továbbiakban... GUI.color = Color.white; // ...az eredeti színében if (GUI.Button(new Rect(RightClickPos.x + 5, RightClickPos.y + 50, 190, 20), "Cancel") || // A mégse gombra nyomva... (Input.GetMouseButtonDown(0) && !BoxRect.Contains(FixedMouse))) // ...vagy a doboz mellé kattintva... { RightClick = false; // ...záródjon be a hozzáadó. } } else if (Input.GetMouseButtonDown(1)) // Megnyomott jobb egérgomb esetén { RightClick = true; // Jobbklikkes menü megnyitása... RightClickPos = FixedMouse; // ...az egér jelenlegi pozícióján } GUI.EndScrollView(); // Görgethető nézet vége /////////// // Mozgatás /////////// if (Grabbed != -1) // Ha van megfogott ellenség { Vector2 MouseDelta = new Vector2(Input.mousePosition.x - LastMousePos.x, LastMousePos.y - Input.mousePosition.y); // Egérelmozdulás az előző képkockához képest LastMousePos = Input.mousePosition; // Utolsó egérpozíció frissítése MouseMovement += MouseDelta; // Összesített elmozduláshoz adás if (Mathf.Abs(MouseMovement.x) > Block) // Ha elmozdult egy blokknyit szélességben { int Step = Mathf.FloorToInt(MouseMovement.x / Block); // Ennyi blokknyit mozdult odébb Enemies[Grabbed].X += Step; // Odébbmozgatás MouseMovement.x -= Block * Step; // Az összesített elmozdulásból vonódjon le ez a lépés } if (Mathf.Abs(MouseMovement.y) > Block) // Ha elmozdult egy blokknyit magasságban { int Step = Mathf.FloorToInt(MouseMovement.y / Block); // Ennyi blokknyit mozdult odébb Enemies[Grabbed].Y += Step; // Odébbmozgatás MouseMovement.y -= Block * Step; // Az összesített elmozdulásból vonódjon le ez a lépés } if (Input.GetMouseButtonUp(0)) // Ha felengedte a felhasználó az egérgombot... { Grabbed = -1; // ...álljon le a mozgás } } //////////// // Alsó menü //////////// int Left = Screen.width / 2 + 50; // Bal oldali behúzás (a szerkesztőfelület közepe) TextAnchor OldLabelAlign = GUI.skin.label.alignment; // Régi címkeigazítás GUI.skin.label.alignment = TextAnchor.MiddleCenter; // A címkéket írja közép-középre GUI.Label(new Rect(Left, ScreenHeight += 20, 200, 25), "Right click to add enemy."); // Információ közlése a jobb klikkes menü létezéséről GUI.skin.label.alignment = OldLabelAlign; // Címkeigazítás visszaállítása if (GUI.Button(new Rect(Left, ScreenHeight += 25, 200, 25), "Revert")) // Visszaállítás gomb { int OldLength = Original.Length; // Eredeti ellenségek száma Enemies = new Enemy[OldLength]; // Új ellenségtömb, az eredeti méretben Array.Copy(Original, Enemies, OldLength); // Eredeti ellenségek visszamásolása } if (GUI.Button(new Rect(Left, ScreenHeight += 25, 200, 25), "Save")) // Mentés gomb { Save(Path); // Eredetileg megnyitott pálya felülírása } if (GUI.Button(new Rect(Left, ScreenHeight += 25, 200, 25), "Save as")) // Mentés másként gomb { SaveAs = true; // Mentés másként felület megjelenítése } if (SaveAs) // Ha meg van nyitva a mentés másként felület... { SaveAsDialog(); // ...jelenítse meg } }
/// <summary> /// GUI-kezelő függvény /// </summary> void OnGUI() { ////////////////////////// // Pixelenkénti szerkesztő ////////////////////////// // Ugyanazok vannak itt kiszámolva, mint a Graphics.Draw-n belül, hogy a keretet köré lehessen rajzolni int MaxWidth = Screen.width - 300, MaxHeight = Screen.height - 100, WScale = MaxWidth / Image.X, HScale = MaxHeight / Image.Y, Scale = Math.Min(WScale, HScale), Left = 300 + (MaxWidth - Image.X * Scale) / 2, Top = (MaxHeight - Image.Y * Scale) / 2, Width = Image.X * Scale, Height = Image.Y * Scale; Graphics.Draw(ref Image, new Rect(300, 0, MaxWidth, MaxHeight), !SaveAs && !Hardcode); // Szerkesztő megjelenítése GUI.DrawTexture(new Rect(Left, Top, Width, 1), Graphics.Foreground); // Felső keret GUI.DrawTexture(new Rect(Left, Top, 1, Height), Graphics.Foreground); // Bal keret GUI.DrawTexture(new Rect(Left + Width - 1, Top, 1, Height), Graphics.Foreground); // Jobb keret GUI.DrawTexture(new Rect(Left, Top + Height - 1, Width, 1), Graphics.Foreground); // Alsó keret ////////////// // Információk ////////////// Top = Screen.height - 100; // Alsó behúzás GUI.color = Graphics.ForegroundColor; // Előtérszín alkalmazása a GUI-ra StringBuilder Info = new StringBuilder(); // Információ szövegének tárolója Info.Append(SaveAsID).Append(" (").Append(Image.X).Append('x').Append(Image.Y).Append(')'); // Információ összeírása GUI.Label(new Rect(305, Top + 5, 200, 20), Info.ToString()); // Információ megjelenítése ////////////// // Átméretezés ////////////// int OldX = Image.X, OldY = Image.Y; // Régi méretek GUI.Label(new Rect(305, Top + 25, 55, 20), "Width:"); // Szélesség címke Image.X = (int)Graphics.Slider(new Rect(360, Top + 29, 200, 20), Image.X, 1, 84); // Szélesség csúszka GUI.Label(new Rect(305, Top + 45, 55, 20), "Height:"); // Magasság címke Image.Y = (int)Graphics.Slider(new Rect(360, Top + 49, 200, 20), Image.Y, 1, 48); // Magasság csúszka if (Image.X != OldX) // Ha változott a szélesség { int OldPixel = 0; // Adott pixel régi helye int Pixel = 0; // Adott pixel jelenlegi helye int WidthDiff = OldX - Image.X; // Szélességkülönbség byte[] OldImage = new byte[84 * 48]; // Régi pixeltérkép helye Array.Copy(Image.Image, OldImage, 84 * 48); // Másolat létrehozása for (int Row = 0; Row < Image.Y; ++Row) // A jelnlegi méret sorain... { for (int Column = 0; Column < Image.X; ++Column) // ...majd oszlopain (tehát a pixelek sorrendjében) haladva... { Image.Image[Pixel++] = Column >= OldX ? (byte)0 : OldImage[OldPixel]; // ...az odaillő pixel beillesztése, ami a régi szélességen túl biztos nem volt aktív ++OldPixel; // A régi pixeltömb következő elemére ugrás } OldPixel += WidthDiff; // A régi pixeltömbben is a következő sor elejére kerüljön a vizsgálat } int LastPixel = Image.X * Image.Y, OldLastPixel = OldX * Image.Y; // Új, illetve régi utolsó pixel for (Pixel = LastPixel - 1; ++Pixel < OldLastPixel; Image.Image[Pixel] = 0) { ; // Az előző sor pontjai közti részt ürítse ki, ha esetleg újra nőne a szélesség } } if (Image.Y != OldY) // Ha változott a magasság { int LastPixel = Image.X * Image.Y, OldLastPixel = Image.X * OldY; // Új, illetve régi utolsó pixel for (int Pixel = LastPixel - 1; ++Pixel < OldLastPixel; Image.Image[Pixel] = 0) { ; // Az előző sor pontjai közti részt ürítse ki, ha esetleg újra nőne a magasság } } ///////// // Opciók ///////// int WidthJump = (Screen.width - 300) / 2 - 100; // Ugrás mérete az alsó oszlopokkal Left = 300 + WidthJump; // Behúzás középre if (GUI.Button(new Rect(Left, Top + 10, 200, 25), "Clear")) // Ürítés gomb { Array.Clear(Image.Image, 0, Image.X * Image.Y); // Tömb nullázása } if (GUI.Button(new Rect(Left, Top + 40, 200, 25), "Revert")) // Visszaállítás gomb { Image = Objects.CopyObject(OriginalImage); // Eredeti objektum visszaállítása } if (GUI.Button(new Rect(Left, Top + 70, 200, 25), "Crop")) // Levágás gomb { int CropTop = 48, CropLeft = 84, CropRight = 0, CropBottom = 0; // Levágási határok int Pixels = Image.X * Image.Y; // Pixelek száma bool Work = false; // Legyen-e vágás for (int Pixel = 0; Pixel < Pixels; ++Pixel) // Minden pixelt ellenőrizzen { if (Image.Image[Pixel] == 1) // Ha egy pixel aktív { int Row = Pixel / Image.X, Column = Pixel % Image.X; // Sor és oszlop meghatározása if (CropTop > Row) // Ha feljebb van, mint eddig bármi... { CropTop = Row; // ...terjessze ki addig a levágást } if (CropLeft > Column) // Ha balrább van, mint eddig bármi... { CropLeft = Column; // ...terjessze ki addig a levágást } if (CropRight < Column) // Ha jobbrább van, mint eddig bármi... { CropRight = Column; // ...terjessze ki addig a levágást } if (CropBottom < Row) // Ha lejjebb van, mint eddig bármi... { CropBottom = Row; // ...terjessze ki addig a levágást } Work = true; // Legyen vágás } } if (Work) // Ha van aktív pixel { byte[] NewMap = new byte[84 * 48]; // Új pixeltérkép int NewWidth = CropRight - CropLeft + 1, NewHeight = CropBottom - CropTop + 1; // Új szélesség és magasság int NewPixel = 0; // Adott pixel új helye for (int Row = 0; Row < NewHeight; ++Row) // Előbb soronként... { for (int Column = 0; Column < NewWidth; ++Column) // ...majd oszloponként bejárás (ez a bájtsorrend) { NewMap[NewPixel++] = Image.Image[(CropTop + Row) * Image.X + CropLeft + Column]; // Pixelek új helyükre mozgatása } } Image.X = NewWidth; // Szélesség frissítése Image.Y = NewHeight; // Magasság frissítése Image.Image = NewMap; // Pixeltérkép frissítése } } ///////// // Mentés ///////// Left += WidthJump - 5; // Behúzás a jobb szélre if (GUI.Button(new Rect(Left, Top + 10, 200, 25), "Save")) // Mentés gomb { Save(Path); // Eredetileg megnyitott objektum felülírása } if (GUI.Button(new Rect(Left, Top + 40, 200, 25), "Save as")) // Mentés másként gomb { SaveAs = true; // Mentés másként felület megjelenítése } if (GUI.Button(new Rect(Left, Top + 70, 200, 25), "Hardcode")) // Hardcode gomb { int Size = Image.X * Image.Y; // Képméret StringBuilder Out = new StringBuilder("[").Append(Size).Append("] = {"); // Kimenet, tömbformátumban for (int Pixel = 0; Pixel < Size; ++Pixel) // Minden pixelt... { Out.Append(Image.Image[Pixel] == 0 ? '0' : '1').Append(','); // ...adjon hozzá, vesszővel elválasztva } HardcodeOut = Out.Remove(Out.Length - 1, 1).Append('}').ToString(); // Utolsó vessző levágása, tömb lezárása Hardcode = true; // Hardcode felület megjelenítése } GUI.color = Color.white; // GUI színének visszaállítása //////////// // Felületek //////////// if (SaveAs) // Ha meg van nyitva a mentés másként felület... { SaveAsDialog(); // ...jelenítse meg } if (Hardcode) // Ha meg van nyitva a hardcode felület... { HardcodeDialog(); // ...jelenítse meg } }