Obiekty graficzne na przykładzie prostej gry. Część 1

Ten materiał rozpoczyna krótki kurs związany z funkcjami obsługi plików graficznych przy użyciu języka C# i kompilatora Visual Studio na przykładzie prostej gry. Na tą chwilę gra nie określonego scenariusz. Kod aplikacji będzie wykorzystywał standardową bibliotekę System.Drawing. Biblioteka ta zawiera podstawowe klasy i metody związane z obsługą grafiki.

W tej części przygotujemy naszą klasę o nazwie bitmapy. Przeznaczeniem tej klasy będzie:

Na tą chwilę tyle wystarczy.

Tworzymy plik zasobów graficznych

Na przykład przy użyciu dowolnego programu graficznego (tu został wykorzystany GIMP) tworzymy naszą grafikę. Grafikę zorganizujemy z szeregu klatek o wymiarach 48x48 pikseli przechowywanych w jednym pliku graficznym zapisanym z kanałem przezroczystości w formacie PNG.

zasoby graficzne gry Visual studio C#

Utworzoną grafikę w programie GIMP eksportujemy do pliku, który koniecznie umieszczamy w folderze przechowywanym w katalogu bin\Debug\g oraz bin\Release\g

zasoby graficzne gry lokalizacja pliku Visual studio C#

Tworzymy klasę obsługującą zasoby graficzne

Dodanie klasy obsługującej nasze zasoby graficzne wykonamy wybierając Menu/ Projekt/ Dodaj klasę lub wykonując kolejne kliknięcia zgodnie z poniższą ilustracją

klasa zasoby graficzne gry Visual studio C#

W oknie dialogowym Dodaj nowy element postępujemy jak poniżej. Uwaga: Przypisana nazwa tworzonego pliku klasy jest również nazwa tej klasy. W omawianym kodzie programu jest to nazwa pliku: bitmapy.cs

Dodaj nowy element Visual studio C#

Dodajemy bibliotekę System.Drawing i tworzymy zmienną publiczną do przechowywania wczytanej grafiki: public Bitmap zasobyBmp; Dodajemy również zalążek kodu destruktora. Zwróć uwagę, że destruktor inicjuje się przez wpisanie znaku ~ (tylda) poprzedzającego nazwę tworzonej klasy. Patrz poniższy kod.

bitmapy.cs:


using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace czolg_1
{
    internal class bitmapy
    {
        public Bitmap zasobyBmp;
        //destruktor
        ~bitmapy()
        {

        }
    }
}

Destruktor jest wymagany w naszym projekcie, ponieważ nie chcemy zaśmiecać pamięci systemu pozostawiając w niej wczytane zasoby graficzne.

Test ładowania grafiki

Mamy przygotowaną grafikę oraz zalążek klasy, przy pomocy której możemy będziemy wczytywać wskazany ścieżką plik graficzny. Do testy przygotujemy główną formatkę aplikacji. W jej obszarze osadzimy kontrolkę typu Panel oraz jedne klawisz- Button

Test ładowania grafiki Visual studio C#

Obszar kontrolki typu Panel będzie służyć jako ekran tworzonej gierki 2D

Dodajemy kod do tworzonej klasy

Na tą chwilę przewidujemy, że nasza klasa powinna obsłużyć wczytanie pliku graficznego. Co jest bardzo proste. Odbywa się instrukcją

Wskazówka:


public void WczytajBmp(string plik)
{
	//funkcja wczytuje bitmapę z pliku graficznego
	zasobyBmp = new Bitmap(plik);
}

Gdzie argument plik typu string jest ścieżką do lokalizacji przechowywanego pliku z grafiką naszej gry.

W tworzonej klasie implementujemy konstruktora klasy, zmienne parametrów wymiaru klatki, kod funkcji testowej rysującej fragment wyciętej grafiki na wskazanym ekranie.

Uzupełnij plik tworzonej klasy poniższym kodem

bitmapy.cs:


using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace czolg_1
{
    internal class bitmapy
    {
        public Bitmap zasobyBmp;
        private int w, h;//szerkość klatki

        public int W {//zwroc,ustaw szerokość klatki 
                       get { return w; } 
                       set { w = value;}
                     }
        public int H
        {   //zwroc,ustaw wysokość klatki
            get { return h; }
            set { h = value; }
        }

        //konstruktor
        public bitmapy(int _w,int _h)
        {
            this.w = _w;
            this.h = _h;
        }

        public void WczytajBmp(string plik)
        {
            //funkcja wczytuje bitmapę z pliku graficznego
            zasobyBmp = new Bitmap(plik);
        }
        public void testPokazBmp(Graphics g, int x, int y, int w, int h)
        {
            //funkcja testowa, pokazuje pierwszą klatkę ze współrzędnych (0,0,0+w,0+h)
            g.DrawImage(zasobyBmp, new Rectangle(x,y,w,h), new Rectangle(0, 0, w, h), GraphicsUnit.Pixel);
        }
        //destruktor
        ~bitmapy()
        {
            //zwolnij pamięc zajmowaną przez zasoby graficzne 
            zasobyBmp.Dispose();
        }
    }
}

Skompiluj program i sprawdź czy nie zawiera błędów

Przygotowujemy główne okno aplikacji do pierwszego testu graficznego

Okno główne powinno zawierać

Uzupełnij kod pliku głównej formatki jak poniżej

Form1.cs:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace czolg_1
{
    public partial class Form1 : Form
    {
        bitmapy bmp;
        public Form1()
        {
            InitializeComponent();
            bmp=new bitmapy(48,48);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //wczytaj bitmape na sztwyno z pliku
            //zakładamy, że plik grafiki istnieje
            //więc nie musimy sprawdzać czy istnieje
            bmp.WczytajBmp("./g/czolg.png");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //test sprawdzajacy czy prawidłowo załadowano grafikę 
            Graphics g = Graphics.FromHwnd(panel1.Handle);
            //wklej wyciętą klatkę grafiki we współrzędnych x=100, y=100
            bmp.testPokazBmp(g, 100, 100, 48, 48);
            g.Dispose();    
        }
 
    }
}

Skompiluj program i sprawdź efekt działania. Prawidłowo wykonane czynności przedstawia poniższa ilustracja

Test ładowania grafiki okno głowne gry 2d Visual studio C#

Test odczytu wybranej klatki

Modyfikujemy główne okno aplikacji do postaci jak poniżej. Wybrana klatkę będziemy mogli podać poprzez jej indeks ewentualnie licznikiem kliknięć zwiększającym wspomniany indeks.

okno głowne gry 2d Visual studio C#

W omawianym pomyśle po wczytaniu pliku zasobu graficznego szatkujemy go na kolejne klatki o wymiarach 48 x 48 pikseli. Otrzymane kafelki zasobów graficznych 2D będziemy przechowywać w liście bazującej na typie Bitmap. W kodzie to

private List<Bitmap> bitmaps = new List<Bitmap>();

Tworzona klasę wzbogacamy o kod

bitmapy.cs:


using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace czolg_1
{
    internal class bitmapy
    {
        public Bitmap zasobyBmp;
        //lista klatek wycinanych bitmapek
        private List<Bitmap> bitmaps = new List<Bitmap>();
        private int w, h;//szerkość klatki

        public int W {//zwroc,ustaw szerokość klatki 
                       get { return w; } 
                       set { w = value;}
                     }
        public int H
        {   //zwroc,ustaw wysokość klatki
            get { return h; }
            set { h = value; }
        }

        //konstruktor
        public bitmapy(int _w,int _h)
        {
            this.w = _w;
            this.h = _h;
        }

        public void WczytajBmp(string plik)
        {
            //funkcja wczytuje bitmapę z pliku graficznego
            zasobyBmp = new Bitmap(plik);
            //wczytany plik zasobów potnij na klatki o wymiarach W x H
            //w programie przyjałem 48 x 48 pikseli
            int ileKolumn = zasobyBmp.Width / W;
            int ileWierszy= zasobyBmp.Height / H;
            for (int i = 0; i < ileWierszy; i++)
             for (int j = 0; j < ileKolumn; j++)
                {
                    bitmaps.Add(new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb));
                    Graphics g = Graphics.FromImage(bitmaps[bitmaps.Count-1]);
                    g.DrawImage(zasobyBmp, new Rectangle(0, 0, w, h), 
                                           new Rectangle(j*w, i*h, w, h),
                                           GraphicsUnit.Pixel);
                    g.Dispose();
                }
        }
        public void testPokazBmp(Graphics g, int x, int y, int w, int h)
        {
            //funkcja testowa, pokazuje pierwszą klatkę ze współrzednych (0,0,0+w,0+h)
            g.DrawImage(zasobyBmp, new Rectangle(x,y,w,h), new Rectangle(0, 0, w, h), GraphicsUnit.Pixel);
        }
        public void pokazKlatke(Graphics g, int idKlatka, int x, int y)
        {
            //funkcja testowa, pokazuje dowolną klatkę 
            g.DrawImage(bitmaps[idKlatka], new Rectangle(x, y, w, h), new Rectangle(0, 0, w, h), GraphicsUnit.Pixel);
        }
        //destruktor
        ~bitmapy()
        {
            //zwolnij pamięc zajmowaną przez zasoby graficzne 
            zasobyBmp.Dispose();
            foreach (Bitmap b in bitmaps) { b.Dispose(); }
        }
    }
}

Modyfikujemy główne okno aplikacji

W oknie głównym dodaj wywołanie funkcji wyświetlającej wybrana klatkę

Form1.cs:


private void button2_Click(object sender, EventArgs e)
{
	int idKlatka=int.Parse(textBox1.Text);
	Graphics g = Graphics.FromHwnd(panel1.Handle);
	bmp.pokazKlatke(g, idKlatka, 0, 0);
	g.Dispose();
}

Skompiluj program i sprawdź efekt wyświetlania dowolnej wyciętej klatki

wycinanie klatek gry 2d Visual studio C#

W tej części to na tyle. Poniżej pełny kod klasy bitmapy

bitmapy.cs:


using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace czolg_1
{
    internal class bitmapy
    {
        public Bitmap zasobyBmp;
        //lista klatek wycinanych bitmapek
        private List<Bitmap> bitmaps = new List<Bitmap>();
        private int w, h;//szerkość klatki

        public int W {//zwroc,ustaw szerokość klatki 
                       get { return w; } 
                       set { w = value;}
                     }
        public int H
        {   //zwroc,ustaw wysokość klatki
            get { return h; }
            set { h = value; }
        }

        //konstruktor
        public bitmapy(int _w,int _h)
        {
            this.w = _w;
            this.h = _h;
        }

        public void WczytajBmp(string plik)
        {
            //funkcja wczytuje bitmapę z pliku graficznego
            zasobyBmp = new Bitmap(plik);
            //wczytany plik zasobów potnij na klatki o wymiarach W x H
            //w programie przyjałem 48 x 48 pikseli
            int ileKolumn = zasobyBmp.Width / W;
            int ileWierszy= zasobyBmp.Height / H;

            for (int i = 0; i < ileWierszy; i++)
             for (int j = 0; j < ileKolumn; j++)
                {
                    bitmaps.Add(new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb));
                    Graphics g = Graphics.FromImage(bitmaps[bitmaps.Count-1]);
                    g.DrawImage(zasobyBmp, new Rectangle(0, 0, w, h), 
                                           new Rectangle(j*w, i*h, w, h),
                                           GraphicsUnit.Pixel);
                    g.Dispose();
                }
        }
        public void testPokazBmp(Graphics g, int x, int y, int w, int h)
        {
            //funkcja testowa, pokazuje pierwszą klatkę ze współrzednych (0,0,0+w,0+h)
            g.DrawImage(zasobyBmp, new Rectangle(x,y,w,h), new Rectangle(0, 0, w, h), GraphicsUnit.Pixel);
        }
        public void pokazKlatke(Graphics g, int idKlatka, int x, int y)
        {
            //funkcja testowa, pokazuje dowolną klatkę 
            g.DrawImage(bitmaps[idKlatka], new Rectangle(x, y, w, h), new Rectangle(0, 0, w, h), GraphicsUnit.Pixel);
        }
        //destruktor
        ~bitmapy()
        {
            //zwolnij pamięc zajmowaną przez zasoby graficzne 
            zasobyBmp.Dispose();
            foreach (Bitmap b in bitmaps) { b.Dispose(); }
        }
    }
}

Pełny kod głównego okna tworzonej formatki

Form1.cs:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace czolg_1
{
    public partial class Form1 : Form
    {
        bitmapy bmp;
        public Form1()
        {
            InitializeComponent();
            bmp=new bitmapy(48,48);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //wczytaj bitmape na sztwyno z pliku
            //zakładamy, że plik grafiki istnieje
            //więc nie musimy sprawdzać czy istnieje
            bmp.WczytajBmp("./g/czolg.png");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //test sprawdzajacy czy prawidłowo załadowano grafikę 
            Graphics g = Graphics.FromHwnd(panel1.Handle);
            bmp.testPokazBmp(g, 100, 100, 48, 48);
            g.Dispose();    
        }

        private void button2_Click(object sender, EventArgs e)
        {
            int idKlatka=int.Parse(textBox1.Text);
            Graphics g = Graphics.FromHwnd(panel1.Handle);
            bmp.pokazKlatke(g, idKlatka, 0, 0);
            g.Dispose();
        }
    }
}
Układ okresowy- kod qr
Układ okresowy

Układ okresowy pierwiastków- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Alkomat- wirtualny test kod qr
Alkomat- wirtualny test

Alkomat- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Taklarz- olinowanie stałe kod qr
Olinowanie stałe- kalkulator średnic

Olinowanie stałe- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
przepis na gogfry

Przepis na gofry

zobacz
przepis na bitą śmietanę

Przepis na bitą śmietanę

zobacz