doom oyununun fizik mekaniği ray casting

entry4 galeri6
    1.
  1. ai chatbotlarla 1 dk da üretebilirsiniz, yeter ki terminolojiye azbuçuk hakim olun! uzak noktanın daha koyu,
    yakın noktaların daha açık tonda görünmesi fikri şahsıma ait, derinlik detayını arttırır diye düşündüm:
    https://streamable.com/kitni4
    https://galeri.uludagsozluk.com/r/2421580/+
    0 ...
  2. 2.
  3. 3.
  4. programı ulu dan cpp uzantılı herhangi boş bir dosyaya kopyala yapıştır yapıp, derledikten sonra çalıştırabilirsiniz, sfml ve c++ ın kütüphane, fonksiyon, metot isimleri çok anlaşılır zaten. return döndür. define tanımla, include içine al, input output stream girdi çıktı akış kütüphanesi, sin cos terimleri bildiğiniz lise trigonometrisi, event olay, key pressed tuşa basıldıysa, draw çizdir, clear sil, update güncelle v.s. v.s.

    bu arada derleme komutunuz:
    g++ labirent.cpp -o labirent -lsfml-graphics -lsfml-window -lsfml-system -lGL -lGLU

    ve kaynak kodu:
    #include <SFML/Graphics.hpp>
    #include <cmath>
    #include <iostream>

    #define ekran_genisligi 320
    #define ekran_yuksekligi 200
    #define harita_genisligi 10
    #define harita_yuksekligi 9
    #define blok_boyutu 64

    // Harita tanımı: '#' duvar, boşluk serbest alan, 'P' oyuncu başlangıcı, 'E' çıkış
    char harita[harita_yuksekligi][harita_genisligi + 1] = {
    "##########",
    "#P #",
    "# # ### #",
    "# # #",
    "### # ## #",
    "# # #",
    "# ### ####",
    "# e#",
    "##########"
    };

    // Çıkış konumu
    struct cikis {
    float x, y;
    } cikis = {8.5f, 7.5f}; // Çıkışın merkezi (haritadaki 'e' konumu)

    // Oyuncu yapısı: Konum ve bakış açısı
    struct oyuncu {
    float x, y; // Oyuncunun haritadaki x ve y koordinatları
    float aci; // Oyuncunun bakış açısı (radyan cinsinden)
    } oyuncu = {1.5f, 1.5f, 0.0f}; // Başlangıç: (1.5, 1.5) konumunda, 0 derece açı

    // Renk yapısı: RGB bileşenleri
    struct renk {
    unsigned char kirmizi, yesil, mavi; // Renk değerleri (0-255)
    };
    // Zemin, tavan ve duvarlar için renk tanımları
    renk zemin_rengi = {50, 50, 50}; // Gri zemin
    renk tavan_rengi = {100, 100, 100}; // Açık gri tavan
    renk acik_sari = {255, 255, 150}; // Yakın mesafe duvar rengi
    renk sari = {255, 255, 0}; // Orta mesafe duvar rengi
    renk kirmizi = {255, 0, 0}; // Çıkışa yakın duvar rengi

    // Oyuncunun çıkışa olan mesafesini hesaplayan fonksiyon
    float cikis_mesafesi_hesapla() {
    float dx = oyuncu.x - cikis.x;
    float dy = oyuncu.y - cikis.y;
    return sqrt(dx * dx + dy * dy); // Öklid mesafesi
    }

    // Mesafeye göre renk geçişi hesaplayan fonksiyon (çıkış mesafesine bağlı)
    renk mesafeye_gore_renk_hesapla(float duvara_mesafe) {
    renk sonuc; // Dönecek renk değeri
    float cikis_mesafesi = cikis_mesafesi_hesapla(); // Oyuncunun çıkışa mesafesi
    float maksimum_cikis_mesafesi = 10.0f; // Çıkış etkisinin maksimum mesafesi
    float normalize_cikis_mesafesi = cikis_mesafesi / maksimum_cikis_mesafesi; // 0-1 aralığına ölçekle
    if (normalize_cikis_mesafesi > 1.0f) normalize_cikis_mesafesi = 1.0f; // 1'i aşarsa sınırla

    float maksimum_mesafe = 20.0f; // Görüşün maksimum mesafesi
    float normalize_duvar_mesafesi = duvara_mesafe / maksimum_mesafe; // Duvar mesafesini ölçekle
    if (normalize_duvar_mesafesi > 1.0f) normalize_duvar_mesafesi = 1.0f;

    // Çıkışa yakınlık ve duvar mesafesine göre renk geçişi
    if (normalize_cikis_mesafesi < 0.5f) { // Çıkışa yakın: Sarı -> Kırmızı geçişi
    float t = normalize_cikis_mesafesi * 2.0f; // 0-1 aralığına ölçekle
    sonuc.kirmizi = sari.kirmizi + (kirmizi.kirmizi - sari.kirmizi) * (1.0f - t);
    sonuc.yesil = sari.yesil + (kirmizi.yesil - sari.yesil) * (1.0f - t);
    sonuc.mavi = sari.mavi + (kirmizi.mavi - sari.mavi) * (1.0f - t);
    } else { // Çıkıştan uzak: Açık sarı -> Sarı geçişi
    float t = normalize_duvar_mesafesi; // Duvar mesafesine bağlı geçiş
    sonuc.kirmizi = acik_sari.kirmizi + (sari.kirmizi - acik_sari.kirmizi) * t;
    sonuc.yesil = acik_sari.yesil + (sari.yesil - acik_sari.yesil) * t;
    sonuc.mavi = acik_sari.mavi + (sari.mavi - acik_sari.mavi) * t;
    }
    return sonuc; // Hesaplanan rengi döndür
    }

    // Kendi raycasting motorumuz: Işınları gönderip görüntüyü oluşturur
    void isinlari_gonder(sf::Uint8* pikseller) {
    float gorus_alani = M_PI / 3; // Görüş alanı: 60 derece (radyan)

    // Ekranın her sütunu için bir ışın gönder
    for (int x = 0; x < ekran_genisligi; x++) {
    // Bu sütun için ışın açısını hesapla: Oyuncu açısı ± görüş alanının yarısı
    float isin_acisi = oyuncu.aci - (gorus_alani / 2) + (x * gorus_alani) / ekran_genisligi;
    float duvara_mesafe = 0; // Işının duvara olan mesafesi
    bool duvara_carpti = false; // Duvara çarpıp çarpmadığını kontrol et
    float goz_x = cos(isin_acisi); // Işının x yönü (kosinüs)
    float goz_y = sin(isin_acisi); // Işının y yönü (sinüs)

    // Duvara çarpana veya maksimum mesafeye ulaşana kadar ışını ilerlet
    while (!duvara_carpti && duvara_mesafe < 20) {
    duvara_mesafe += 0.05f; // Küçük adımlarla ilerle (hassasiyet için)
    int test_x = (int)(oyuncu.x + goz_x * duvara_mesafe); // Test edilecek x koordinatı
    int test_y = (int)(oyuncu.y + goz_y * duvara_mesafe); // Test edilecek y koordinatı

    // Harita sınırlarını kontrol et
    if (test_x < 0 || test_x >= harita_genisligi || test_y < 0 || test_y >= harita_yuksekligi) {
    duvara_carpti = true; // Sınırlara çarpılırsa duvar kabul et
    duvara_mesafe = 20; // Maksimum mesafeye sabitle
    }
    // Haritada duvara çarpıp çarpmadığını kontrol et
    else if (harita[test_y][test_x] == '#') {
    duvara_carpti = true; // Duvarsa çarpma tespit edildi
    }
    }

    // Duvar yüksekliğini hesapla (perspektif için açıyı düzelt)
    int duvar_yuksekligi = (int)(ekran_yuksekligi / (duvara_mesafe * cos(isin_acisi - oyuncu.aci)));
    if (duvar_yuksekligi > ekran_yuksekligi) duvar_yuksekligi = ekran_yuksekligi; // Ekranı aşmasın

    // Tavan ve zemin sınırlarını belirle
    int tavan = (ekran_yuksekligi / 2) - (duvar_yuksekligi / 2); // Tavanın üst sınırı
    int zemin = tavan + duvar_yuksekligi; // Zemin başlangıcı

    // Mesafeye bağlı duvar rengini hesapla
    renk duvar_rengi = mesafeye_gore_renk_hesapla(duvara_mesafe);

    // Sütunun her pikselini doldur
    for (int y = 0; y < ekran_yuksekligi; y++) {
    int piksel_indeksi = (y * ekran_genisligi + x) * 4; // Pikselin bellekteki konumu (RGBA)
    if (y < tavan) { // Tavan alanı
    pikseller[piksel_indeksi] = tavan_rengi.kirmizi; // Kırmızı bileşen
    pikseller[piksel_indeksi + 1] = tavan_rengi.yesil; // Yeşil bileşen
    pikseller[piksel_indeksi + 2] = tavan_rengi.mavi; // Mavi bileşen
    pikseller[piksel_indeksi + 3] = 255; // Opaklık (alpha)
    }
    else if (y >= tavan && y < zemin) { // Duvar alanı
    pikseller[piksel_indeksi] = duvar_rengi.kirmizi; // Kırmızı bileşen
    pikseller[piksel_indeksi + 1] = duvar_rengi.yesil; // Yeşil bileşen
    pikseller[piksel_indeksi + 2] = duvar_rengi.mavi; // Mavi bileşen
    pikseller[piksel_indeksi + 3] = 255; // Opaklık (alpha)
    }
    else { // Zemin alanı
    pikseller[piksel_indeksi] = zemin_rengi.kirmizi; // Kırmızı bileşen
    pikseller[piksel_indeksi + 1] = zemin_rengi.yesil; // Yeşil bileşen
    pikseller[piksel_indeksi + 2] = zemin_rengi.mavi; // Mavi bileşen
    pikseller[piksel_indeksi + 3] = 255; // Opaklık (alpha)
    }
    }
    }
    }

    // Ana program
    int main() {
    // Oyun penceresini oluştur
    sf::RenderWindow pencere(sf::VideoMode(ekran_genisligi, ekran_yuksekligi), "90'lar raycasting labirenti");
    pencere.setFramerateLimit(30); // Kare hızını 30 FPS ile sınırla

    // Piksel verilerini tutacak dizi
    sf::Uint8* pikseller = new sf::Uint8[ekran_genisligi * ekran_yuksekligi * 4];
    sf::Texture doku; // Ekran görüntüsünü tutacak doku
    doku.create(ekran_genisligi, ekran_yuksekligi); // Dokuyu ekran boyutunda oluştur
    sf::Sprite goruntu(doku); // Dokuyu ekrana çizecek sprite

    // Oyun döngüsü
    while (pencere.isOpen()) {
    sf::Event olay; // Olayları işlemek için yapı
    while (pencere.pollEvent(olay)) {
    if (olay.type == sf::Event::Closed) pencere.close(); // Pencere kapatılırsa çık
    }

    float hareket_hizi = 0.1f; // Oyuncunun hareket hızı
    float donus_hizi = 0.05f; // Oyuncunun dönüş hızı

    // ileri hareket
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
    float yeni_x = oyuncu.x + cos(oyuncu.aci) * hareket_hizi; // Yeni x konumu
    float yeni_y = oyuncu.y + sin(oyuncu.aci) * hareket_hizi; // Yeni y konumu
    if (harita(int)yeni_y](int)yeni_x] != '#') { // Çarpışma yoksa hareket et
    oyuncu.x = yeni_x;
    oyuncu.y = yeni_y;
    }
    }
    // Geri hareket
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
    float yeni_x = oyuncu.x - cos(oyuncu.aci) * hareket_hizi; // Yeni x konumu
    float yeni_y = oyuncu.y - sin(oyuncu.aci) * hareket_hizi; // Yeni y konumu
    if (harita(int)yeni_y](int)yeni_x] != '#') { // Çarpışma yoksa hareket et
    oyuncu.x = yeni_x;
    oyuncu.y = yeni_y;
    }
    }
    // Sola dönüş
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
    oyuncu.aci -= donus_hizi; // Açıyı saat yönünün tersine çevir
    }
    // Sağa dönüş
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
    oyuncu.aci += donus_hizi; // Açıyı saat yönüne çevir
    }

    // Piksel dizisini sıfırla (temizle)
    for (int i = 0; i < ekran_genisligi * ekran_yuksekligi * 4; i++) {
    pikseller[i] = 0;
    }

    // Raycasting ile görüntüyü oluştur
    isinlari_gonder(pikseller);

    // Dokuyu güncelle ve ekrana çiz
    doku.update(pikseller);
    pencere.clear(); // Ekranı temizle
    pencere.draw(goruntu); // Sprite'ı çiz
    pencere.display(); // Ekranı göster
    }

    // Belleği temizle
    delete[] pikseller;
    return 0;
    }
    0 ...
  5. 4.
© 2025 uludağ sözlük