Flappy Bird
Gra polega na sterowaniu małym bohaterem (zazwyczaj ptakiem) i prowadzeniu go przez serię przeszkód (rur/słupów), które pojawiają się na ekranie. Gracz musi klikać (lub używać spacji), aby ptak podskoczył i utrzymał się w powietrzu, unikając zarówno górnej i dolnej części rur, jak i podłogi/sufitu. Celem jest osiągnięcie jak najwyższego wyniku poprzez przelecenie przez jak największą liczbę przeszkód.
Written By Coder Matthew
Last updated 6 months ago
1) Grafiki użyte w Flappy Bird

1.
BackgroundGłówna grafika tła gry.
Stanowi wizualną scenerię, za którą przesuwa się gracz i przeszkody. Jest używana przez skrypt
BackgroundEffectdo stworzenia wrażenia ruchu i głębi.
2.
Bird_01,Bird_02,Bird_03To są klatki animacji (ramki) postaci gracza, czyli ptaka.
Skrypt
Playerwykorzystuje te trzy grafiki, cyklicznie je zmieniając, aby symulować ruch skrzydeł ptaka podczas lotu. Ta zmiana klatek tworzy iluzję animacji.
3.
GameOverTekst lub grafika wyświetlana po przegranej.
Jest to element interfejsu użytkownika (UI). Skrypt
GameManageraktywuje ten obiekt (ustawia go jako widoczny) w momencie wywołania funkcjiGameOver(), informując gracza o końcu rozgrywki.
4.
GetReadyGrafika mówiąca użytkownikowi aby się przygotował do rozgrywki "Get Ready".
Grafika ta jest wyświetlana na początku gry, kiedy gracz czeka na naciśnięcie przycisku "Play" lub wykonanie pierwszego skoku. Sugeruje, że gra jest w stanie Pauzy (
Time.timeScale = 0f).
5.
GroundGrafika przedstawiająca podłoże/ziemię.
Służy jako dolna granica mapy. Kontakt ptaka z tą grafiką wywołuje funkcję
GameOver(). Ta grafika jest również animowana podobnie jak tło, aby symulować ruch.
6.
PipeGrafika przedstawiająca pojedynczy element przeszkody (rury).
Ta grafika jest używana jako Prefab (wzorzec obiektu) przez skrypt
Pipes. W grze są używane dwie instancje tej rury (jedna obrócona) do stworzenia górnej i dolnej części przeszkody, z prześwitem pośrodku.
7.
PlayButtonGrafika przycisku.
Jest to klikalny element interfejsu użytkownika (UI). Jest widoczny na początku gry i po przegranej. Po kliknięciu wywołuje funkcję
GameManager.Play(), rozpoczynając nową rundę.
2) Hierarchia w Unity

1.
Game ManagerReprezentuje fizycznie na scenie jednostkę zarządzającą grą.
Jest to obiekt, do którego przypięty jest skrypt
GameManager. Dzięki temu skryptowi kontroluje on stan gry (Play, Pause, GameOver), punkty oraz komunikację sieciową. Jest to niezbędny element dla działania Singletonu.
2.
Main CameraOdpowiada za perspektywę gracza. To przez nią widzimy świat gry.
Ustawia pole widzenia, proporcje oraz sposób renderowania grafiki. W tej grze jest to statyczna kamera, skupiona na obszarze, w którym porusza się gracz.
4.
CanvasJest to kontener nadrzędny dla wszystkich elementów interfejsu użytkownika (UI).
System UI w Unity wymaga obiektu
Canvas. Upewnia się on, że elementy takie jak tekst i przyciski są wyświetlane prawidłowo na ekranie, niezależnie od rozdzielczości.
5.
Score (wewnątrz Canvas)Element tekstowy, który wyświetla aktualny wynik gracza.
Skrypt
GameManagerodwołuje się do tego obiektu (scoreText) i aktualizuje jego zawartość za każdym razem, gdy gracz pomyślnie minie przeszkodę (w metodzieIncreaseScore()).
6.
GameOver (wewnątrz Canvas)Reprezentuje graficzny element tła sceny.
Do tego obiektu przypięty jest skrypt
BackgroundEffect(lubParallax). Skrypt ten stale modyfikuje teksturę tego obiektu, tworząc iluzję ruchu tła i efekt paralaksy.
7.
GroundReprezentuje podłoże/ziemię w grze.
Jest to obiekt, który służy jako dolna granica dla gracza. Posiada on komponent Collider, a kontakt z nim jest traktowany tak samo jak kolizja z przeszkodą, co prowadzi do wywołania
GameOver(). Jest on również animowany.
8.
PlayerReprezentuje postać sterowaną przez gracza (ptaka).
Jest to obiekt, do którego przypięty jest skrypt
Player. Obiekt ten odpowiada za ruch, animację skrzydeł, stosowanie siły grawitacji oraz skoki, a także fizycznie wykrywa zderzenia z rurami i strefami punktowymi.
9.
SpawnerReprezentuje punkt na scenie, z którego generowane są przeszkody.
Do tego obiektu przypięty jest skrypt
Spawner. Jego pozycja określa, gdzie dokładnie pojawią się nowe rury. Jest on aktywny tylko w trakcie gry i wywołuje cyklicznie tworzenie nowych rur (Pipes).
3) Skrypty użyte w Flappy Bird

1.
GameManager(Menedżer Gry):To centralna jednostka kontrolna całej aplikacji. Jego najważniejszą rolą jest zarządzanie stanem gry (Pauza, Gra, Koniec Gry) i synchronizacja wszystkich kluczowych elementów.
Implementuje wzorzec Singleton, co oznacza, że zapewnia jedną, łatwo dostępną instancję siebie w każdym miejscu kodu (poprzez
GameManager.Instance), umożliwiając innym skryptom, takim jakPlayerczyPipes, komunikację i wywoływanie kluczowych metod (np.GameOver(),IncreaseScore()).Kontroluje mechanikę punktacji, inicjując wynik na zero przy starcie i aktualizując go na interfejsie użytkownika (
scoreText) po pomyślnym przejściu przez przeszkodę.Odpowiada za logikę restartu, czyszcząc scenę z istniejących przeszkód (
Pipes) i resetując stan gracza, gdy wywołana jest funkcjaPlay().Obejmuje komunikację sieciową (
SendScore), która jest uruchamiana po zakończeniu gry, wysyłając wynik gracza na zewnętrzny serwer.
2.
Player(Gracz / Ptak):To skrypt odpowiedzialny za wszelkie interakcje i ruch sterowanej przez gracza postaci.
Zarządza fizyką obiektu: stosuje stałą grawitację (
gravity) w dół i reaguje na wejście użytkownika (spacja/kliknięcie myszą), nadając natychmiastowy impuls w górę (strength), co jest podstawową mechaniką "Flap".Utrzymuje wizualną dynamikę postaci, aktualizując jej rotację (
tilt) w zależności od kierunku i prędkości pionowej, co daje efekt naturalnego opadania lub wznoszenia.Kontroluje animację postaci, cyklicznie przełączając się między kolejnymi sprite'ami zdefiniowanymi w tablicy, aby symulować ruch skrzydeł.
Realizuje kluczową logikę zderzeń (
OnTriggerEnter2D), wykrywając, czy ptak uderzył w przeszkodę (wywołującGameManager.GameOver()) czy przeleciał przez strefę punktową (wywołującGameManager.IncreaseScore()).
3.
Spawner(Generator Rur):Jego wyłącznym zadaniem jest generowanie przeszkód (rur) w regularnych odstępach czasu.
Używa funkcji
InvokeRepeatingw metodzieOnEnable, aby cyklicznie wywoływać metodęSpawn()zgodnie z zadaną częstotliwością (spawnRate).Zarządza losowością wysokości rur, ustawiając nowo utworzony obiekt w losowej pozycji pionowej w ramach zdefiniowanego zakresu (
minHeightdomaxHeight).Przekazuje kluczowy parametr (
verticalGap) do tworzonego skryptuPipes, zapewniając, że wszystkie nowo powstałe przeszkody mają spójną szerokość prześwitu.
4.
Pipes(Rury / Przeszkody):Ten skrypt steruje pojedynczą parą przeszkód po jej wygenerowaniu przez
Spawner.W metodzie
Startoblicza i stosuje pozycjonowanie górnej i dolnej części rury na podstawie przekazanego prześwitu (gap).W metodzie
Updateodpowiada za ciągły, liniowy ruch rury w lewo z ustaloną prędkością.Zawiera logikę oczyszczania pamięci, automatycznie niszcząc obiekt rury, gdy ta przekroczy lewą krawędź ekranu (
leftEdge), co zapobiega gromadzeniu się niepotrzebnych obiektów w pamięci gry.
5.
BackgroundEffect(Efekt Tła / Paralaksa):Jest to skrypt odpowiedzialny za efekty wizualne tła, zwiększając wrażenie prędkości i głębi.
Osiąga to poprzez ciągłe przesuwanie koordynat tekstury (
mainTextureOffset) w poziomie, zamiast przesuwania samego obiektu.Dzięki temu tło wydaje się przesuwać wolniej niż przeszkody (jeśli
animationSpeedjest mniejsza niż prędkość rur), tworząc klasyczny efekt paralaksy bez konieczności tworzenia nowych obiektów tła.
4) Całe skrypty
Tutaj znajdziesz całe skrypty bez owijania w bawełne 😊, każdy blok kodu jest starannie zakomentowany tak żebyś w miarę mógł ogarnąć o co chodzi nawet jak nie znasz unity i C#.
Exampleusing UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
[DefaultExecutionOrder(-1)]
public class GameManager : MonoBehaviour
{
// --- Ustawienie Singletonu i Zmienne Gry ---
// [BLOK KOMENTARZY: Kontrola Instancji i Parametry Gry]
// Ten kod zapewnia, że w grze jest tylko JEDEN Menedżer Gry (Singleton),
// dostępny łatwo z każdego innego skryptu (GameManager.Instance).
// Poniższe zmienne 'SerializeField' to odniesienia do kluczowych obiektów
// na scenie (Gracz, Spawner, Tekst Wyniku, Przyciski UI),
// które ustawia się w edytorze Unity.
public static GameManager Instance { get; private set; }
[SerializeField] private Player player;
[SerializeField] private Spawner spawner;
[SerializeField] private Text scoreText;
[SerializeField] private GameObject playButton;
[SerializeField] private GameObject gameOver;
public int score { get; private set; } = 0;
// --- Inicjalizacja i Czyszczenie ---
// [BLOK KOMENTARZY: Zarządzanie Życiem Obiektu]
// Funkcje Awake i OnDestroy dbają o to, żeby istniała tylko jedna
// instancja Menedżera przez cały czas trwania gry.
// Funkcja Start natychmiast pauzuje grę po jej załadowaniu,
// czekając na akcję gracza (naciśnięcie "Play").
private void Awake()
{
if (Instance != null) {
DestroyImmediate(gameObject);
} else {
Instance = this;
}
}
private void OnDestroy()
{
if (Instance == this) {
Instance = null;
}
}
private void Start()
{
Pause();
}
// --- Kontrola Stanu Gry ---
// [BLOK KOMENTARZY: Sterowanie Czasem i Ruchem]
// Metoda Pause: Zatrzymuje czas (Time.timeScale = 0), zatrzymując ruch i fizykę.
// Wyłącza skrypt sterowania graczem, uniemożliwiając mu ruch.
public void Pause()
{
Time.timeScale = 0f;
player.enabled = false;
}
public void Play()
{
// Metoda Play:
// 1. Resetuje wynik do zera i ukrywa elementy interfejsu "Start/Game Over".
score = 0;
scoreText.text = score.ToString();
playButton.SetActive(false);
gameOver.SetActive(false);
// 2. Wznawia czas (Time.timeScale = 1) i włącza sterowanie graczem.
Time.timeScale = 1f;
player.enabled = true;
// 3. Wyszukuje wszystkie istniejące rury (Pipes) na scenie i je niszczy,
// zapewniając czysty start nowej rundy.
Pipes[] pipes = FindObjectsOfType<Pipes>();
for (int i = 0; i < pipes.Length; i++) {
Destroy(pipes[i].gameObject);
}
}
public void GameOver()
{
// [BLOK KOMENTARZY: Koniec Gry i Zapis Wyniku]
// Po zderzeniu, pokazuje elementy "Koniec Gry" i uruchamia
// procedurę wysłania wyniku do zewnętrznego systemu. Na koniec pauzuje grę.
playButton.SetActive(true);
gameOver.SetActive(true);
StartCoroutine(
SendScore
(
14, // id gry
score // wynik gracza
)
);
Pause();
}
public void IncreaseScore()
{
// [BLOK KOMENTARZY: Punktacja]
// Prosta metoda wywoływana, gdy gracz przeleci przez punktowaną strefę.
// Zwiększa wynik i aktualizuje tekst na ekranie.
score++;
scoreText.text = score.ToString();
}
// --- Komunikacja Sieciowa (Wysyłanie Wyniku) ---
// [BLOK KOMENTARZY: Procedura HTTP]
// Ta funkcja (korutyna) buduje URL i formularz, aby wysłać aktualny wynik
// gracza na zewnętrzny serwer (https://bit.elita.fun). Zawiera prosty
// mechanizm zabezpieczający (hasło generowane na podstawie bieżącej minuty).
public IEnumerator SendScore(int gameId, int score)
{
string url = "https://bit.elita.fun/execs/api/set_score.php?game_id=" + gameId + "&score=" + score;
WWWForm f = new WWWForm();
f.AddField("pass", System.DateTime.Now.ToString("mm") + "E-----K");
using (UnityWebRequest r = UnityWebRequest.Post(url, f))
{
yield return r.SendWebRequest();
Debug.Log(r.result == UnityWebRequest.Result.Success
? r.downloadHandler.text
: "ERR: " + r.error);
}
}
}