Arcade Türü Oyun Programlamayı ve Bilgisayar Bilimleri Öğrenin

Arcade Türü Oyun Programlamayı
ve Bilgisayar Bilimleri Öğrenin

Chapter 8: Animasyona Giriş

8.1 Sıçrayan Dikdördgen

Video: Sıçrayan Dikdördgen

Animasyonla çalışmaya başlamak için, boş bir ekran açan temel pygame programıyla başlamalıyız. pygame_base_template.py dosyasının kaynağı şurada bulunabilir:
pygame_base_template.py

Siyah arkaplanlı bir ekranın etrafında beyaz bir dikdörtgeni sıçratan bir program oluşturacağız. Kendi renklerinizi seçmekte özgürsünüz, fakat arkaplan rengini dikdördgenin renginden farklı yaptığınıza emin olmak isteyeceksiniz! Sonuç olarak, bir temel şablon alıp ekran arkaplan rengini beyazdan siyaha çevirerek başlayacağız. Bu kod 46. satır civarında olmalı.

screen.fill(black)

Şimdi oynatacak bir nesne alalım. Basit bir dikdördgen yetecektir. Bu kod ekran temizleme kodunun altında ve onu çeviren (flip) kodtan önce olmalıdır.

pygame.draw.rect(screen,white,[50,50,50,50])

Bu kod döngü her döndüğünde tam olarak (50,50) noktasında bir dikdördgen çizecektir. Bu sayı değişene kadar, kare hareket etmeyecektir.

Değişen bir değer elde etmenin yolu bir değişken kullanmaktır. Alttaki kod bunun ilk aşamasını oluşturur:

rect_x = 50
pygame.draw.rect(screen,white,[rect_x,50,50,50])

Dikdördgeni sağa kaydırmak içni, x her frame'de (çerçevede) bir değer artırılır. Bu kod yapmaya oldukça yakın olmasına rağmen bunu tamamen yapamaz:

rect_x = 50
pygame.draw.rect(screen,white,[rect_x,50,50,50])
rect_x += 1

Yukarıdaki kodta bulunan sorun rect_x'in döngünün her seferinde 50 değerine sıfırlanmasıdır. Bu sorunu çözmek için, rect_x'in başlangıç değeri olan 50'yi döngünün dışına ve üstüne yazmak gerekir. Kodun bu versiyonu sağa doğru başarıyla kayacaktır.

# Dikdördgenin başlangıç pozisyonu
rect_x = 50

# -------- Ana Program Döngüsü -----------
while done==False:
	for event in pygame.event.get(): # Kullanıcı bir şey yaptı
		if event.type == pygame.QUIT: # Kullanıcı kapat'a bastıysa
			done=True # Döngüden çıkabilmemiz için işaretle

	# Ekran arkaplanını ayarla
	screen.fill(black)

	pygame.draw.rect(screen,white,[rect_x,50,50,50])
	rect_x += 1

Kutuyu daha hızlı hareket ettirmek için rect_x'in değeri şu şekilde artırılabilir:

rect_x += 5

x ve y pozisyonlarının ikisinin de artırılması karenin aşağı ve sağa hareket etmesine sebep olur:

# Dikdördgenin başlangıç pozisyonu
rect_x = 50
rect_y = 50

# -------- Ana Program Döngüsü -----------
while done==False:
	for event in pygame.event.get():
		if event.type == pygame.QUIT: 
			done=True

	# Ekran arkaplanını ayarla
	screen.fill(black)
	
	# Dikdördgeni çiz
	pygame.draw.rect(screen,white,[rect_x,rect_y,50,50])

	# Dikdördgenin taşınma miktarı
	rect_x += 5
	rect_y += 5

Kutuların hareketinde yön ve hız bir vektörün içerisinde saklanabilir. Bu, hareket eden nesnenin yönü ve hızı değiştiğinde işimizi kolaylaştırır. Sonraki kod parçası x ve y'de (5, 5)'lik değişme için değişkenleri kullanmayı gösteriyor.

# Dikdördgenin hızı ve yönü
rect_change_x = 5
rect_change_y = 5

# -------- Ana Program Döngüsü -----------
while done==False:
	for event in pygame.event.get(): # Kullanıcı bir şey yaptı
		if event.type == pygame.QUIT: # Kullanıcı kapat'a bastıysa
			done=True # Döngüden çıkabilmemiz için işaretle

	# Arkaplanı ayarla
	screen.fill(black)

	# Dikdördgeni çiz
	pygame.draw.rect(screen,white,[rect_x,rect_y,50,50])

	# Dikdördgeni yeni konumuna taşı
	rect_x += rect_change_x
	rect_y += rect_change_y

Kod ekranın kenarına çarptığında gitmeye devam edecektir. Hiçbir şey dikdördgenin ekranın kenarından çarptığında sekmesini sağlamaz. Topun sağa hareket etmesi için yönü değiştirme amacıyla, rect_change_y'un top ekranın kenarına gittiğinde 5'ten -5'e değişmesi gereklidir. rect_y'nin değeri ekranın yüksekliğinden büyük olduğunda top alttadır. Alttaki kod yönü kontrol edip tersine çevirebilir:

# Gerektiğinde topu sektirmek
if rect_y > 450:
	rect_change_y = rect_change_y * -1

Why check rect_y against 450? If the screen is 500 pixels high, then checking against 500 would be a logical first guess. But the rectangle is drawn starting from the upper left of the rectangle. So the rectangle would slide completely off-screen before bouncing. Taking into account that the rectangle is 50 pixels high:
$500-50=450$.

The code below will bounce the rectangle off all four sides of a 700x400 window:

# Bounce the ball if needed
if rect_y > 450 or rect_y < 0:
	rect_change_y = rect_change_y * -1
if rect_x > 650 or rect_x < 0:
	rect_change_x = rect_change_x * -1

Daha karışık şekilleri oynatmak için birkaç çizim komutu kullanılabilir. Alttaki kod beyaz dikdördgenin içine kırmızı bir dikdöndgen oluşturuyor. Kırmızı dikdördgen beyaz dikdördgenin sol üst köşesinden x ve y yönlerinde kenarlardan 10 piksel uzaklıktadır. Kırmızı dikdördgenin beyaz tarafından 10 pikselle sarılması sonucu o, iki boyutta da 20 piksel daha geniştir.

# Beyazın içine kırmızı bir dikdördgen çiz.
pygame.draw.rect(screen,red,[rect_x+10,rect_y+10,30,30])

8.2 Kar Animasyonu

8.2.1 Kod açıklaması

Video: Kar Animasyonu

Bu bölümle çalışmaya başlamak için,, boş bir ekran açan temel pygame programıyla başlamalıyız. pygame_base_template.py dosyasının kaynağı şurada bulunabilir:
pygame_base_template.py

Rastgele sayıları kullanarak yıldızları, karı veya yağmuru oluşturmak mümkündür. Başlamayı denemenin en basit yolu rastgele x,y pozisyonlarında for döngüsünü kullanarak çemberler çizmektir. Ana while döngüsünün içerisinde alttaki kodu deneyin.

for i in range(50):
    x=random.randrange(0,400)
    y=random.randrange(0,400)
	pygame.draw.circle(screen,white,[x,y],2)

Bu programı çalıştırmak bir sorun gösterecektir. Döngü her döndüğünde, biz yeni rastgele konumlarda yıldızlar çiziyoruz. Program yıldızları saniyede 20 kez yeni konumlara çiziyor!

Yıldızları aynı konumda tutmak için, nerede olduklarının bir listesini tutmak gereklidir. Program bunu yapabilmek için bir Python listesi kullanabilir. Bu ana döngü öncesinde yapılmalıdır, aksi takdirde program saniyenin her 1/20'sinde 50 yeni yıldız ekleyecektir.

for i in range(50):
    x=random.randrange(0,400)
    y=random.randrange(0,400)
    star_list.append([x,y])

Yıldızların konumları eklendiğinde, onlara normal bir liste gibi erişilebilir. Alttaki kod ilk konumdan x ve y koordinatlarını yazdıracaktır:

print( star_list[0] )

Bu kod ilk konumun y değerini yazdıracaktır çünkü koordinat bir listedir ve y değeri ikinci konumdadır:

print( star_list[0][1] )

Ana while döngüsünün içerisinde, program yıldız listesinde (star_list) olan her öğeyi çizmek için for döngüsü kullanabilir. len(star_list) fonksiyonunun yıldız listesindeki eleman sayısını verdiğini unutmayın.

# Listedeki her yıldızı işleme al
for i in range(len(star_list)):
	# Yıldızı çiz
	pygame.draw.circle(screen,white,star_list[i],2)

Program, kar yağışı gibi, dizideki her nesneyi aşağı hareket ettirecekse alttaki satırın üstte oluşturulan for döngüsüne eklenmesi y koordinatının artmasına sebep olur.

	# Yıldızı bir piksel aşağı kaydır
	star_list[i][1]+=1

Bu, karı aşağı hareket ettirir fakat tek bir kere olur ve ekranda yeni hiçbir şey gerçekleşmez. Alttaki kodu eklersek, bigisayar ekranın üst kısmında rastgele bir yerden kar yağdırmaya başlayacaktır:

	# Yıldız ekranın altına hareket ettiyse
	if star_list[i][1] > 400:
		# Onu ekranın üst kısmında sıfırla
		y=random.randrange(-50,-10)
		star_list[i][1]=y
		# Ona yeni bir x pozisyonu ver
		x=random.randrange(0,400)
		star_list[i][0]=x

8.2.2 Tümünün Listesi

"""
 Animating multiple objects using a list.
 Sample Python/Pygame Programs
 Simpson College Computer Science
 http://programarcadegames.com/
 http://simpson.edu/computer-science/

 Explanation video: http://youtu.be/Gkhz3FuhGoI
"""

# Import a library of functions called 'pygame'
import pygame
import random

# Initialize the game engine
pygame.init()

BLACK = [0, 0, 0]
WHITE = [255, 255, 255]

# Set the height and width of the screen
SIZE = [400, 400]

screen = pygame.display.set_mode(SIZE)
pygame.display.set_caption("Snow Animation")

# Create an empty array
snow_list = []

# Loop 50 times and add a snow flake in a random x,y position
for i in range(50):
    x = random.randrange(0, 400)
    y = random.randrange(0, 400)
    snow_list.append([x, y])

clock = pygame.time.Clock()

# Loop until the user clicks the close button.
done = False
while not done:

    for event in pygame.event.get():   # User did something
        if event.type == pygame.QUIT:  # If user clicked close
            done = True   # Flag that we are done so we exit this loop

    # Set the screen background
    screen.fill(BLACK)

    # Process each snow flake in the list
    for i in range(len(snow_list)):

        # Draw the snow flake
        pygame.draw.circle(screen, WHITE, snow_list[i], 2)

        # Move the snow flake down one pixel
        snow_list[i][1] += 1

        # If the snow flake has moved off the bottom of the screen
        if snow_list[i][1] > 400:
            # Reset it just above the top
            y = random.randrange(-50, -10)
            snow_list[i][1] = y
            # Give it a new x position
            x = random.randrange(0, 400)
            snow_list[i][0] = x

    # Go ahead and update the screen with what we've drawn.
    pygame.display.flip()
    clock.tick(20)

# Be IDLE friendly. If you forget this line, the program will 'hang'
# on exit.
pygame.quit()

8.3 3D Animasyon

Video: Blender Oyun Motoru Demosu

Oyun fizik kurallarını 2 boyutlu ortamdan 3 boyutlu ortama genişletmek gözüktüğü kadar zor değildir. Bu, bu sınıfın kapsamı dışında olduğu halde, bunun nasıl yapıldığını görmeye uğraşmaya değer.

Blender adı verilen ve programcıların 3D oyun oluşturmalarına imkan sağlayan "oyun motoruna" sahip ücretsiz bir 3 boyutlu program mevcuttur. Oyundaki 3 boyutlu nesneler onların oyundaki hareketlerini kontrol etmek için onlarla ilişkilendirilmiş Python kodu içerebilir.

fig.blender01
Figure 8.1: Örnek Blender Dosyası

Şekil 8.1'e bakın. İçerisinde birkaç nesne olan yeşil bir tepsi gösteriyor. Mavi nesne diğer nesnelere çarpması için onların etrafında hareket etmesini sağlayacak bir Python komut dosyasıyla kontrol ediliyor. Altta gösterilen komut dosyası 2 boyutlu programlarda olan birçok özelliğin aynısına sahip. Bir ana döngü var, x ve y lokasyonlarının listesi var ve vektörü kontrol eden değişkenler var.

Ana program döngüsü Blender tarafından kontrol ediliyor. Listelemede gösterilen Python kodu her seferinde program döngüsü tarafından otomatik olarak çağırılıyor. Bu Python kodunun neden bir ana döngü göstermediğini açıklıyor. Ama ne olursa olsun bir döngü var.

Mavi nesne x,y,z formatında tutulan bir konuma sahiptir. blueobject.position değişkeni kullanılarak değiştirilebilir ve ona erişilebilir. Dizi konumu olan [0] x'in, [1] y'nin ve [2] z'nin konumunu tutar.

change_x ve change_y değişkenlerini bu değiştiricide 2 boyutlu örneklerde kullanmak yerine, bu Blender örneği blueObject["x_change"] ve blueObject["y_change"] kullanıyor.

if yapıları mavi nesnenin ekranın kenarlarına ulaşıp ulaşmadığını ve böylece yönünün tersine çevrilip çevrilmeyeceğini kontrol etmekte kullanılıyor. 2 boyutlu oyunlarda olanın aksine, nesnelerin yerleri ondalıklı sayı türünde (floating point number type) olabilir. Bir öğeyi 5 ve 6 arasında bir yere konumlandırmak için, konumunu 5.5 olarak atamak mümkündür.

Bunun oyun koluyla (Ç.N nam-ı diğer joystick) etkileşime izin verecek şekilde genişletilmesi oldukça kolaydır ve bu kitapta daha sonra anlatılacaktır.

import bge

# Mavi nesneye bir referans alalım
cont = bge.logic.getCurrentController()
blueObject = cont.owner

# Mavi nesnenin x ve y koordinatlarını ekrana bastıralım
print (blueObject.position[0],blueObject.position[1] )

# x ve y koordinatlarını x_change ve y_change'e göre 
# değiştir. x_change ve y_change mavi nesneyle ilişkili 
# oyun özellikleridir.
blueObject.position[0]+=blueObject["x_change"]
blueObject.position[1]+=blueObject["y_change"]

# Nesnenin köşeye gidip gitmediğini kontrol et.
# Eğer gittiyse yönü tersine çevir. Bunu 4 köşe için de yap.
if blueObject.position[0] > 6 and blueObject["x_change"] > 0:
    blueObject["x_change"] *= -1

if blueObject.position[0] < -6 and blueObject["x_change"] < 0:
    blueObject["x_change"] *= -1

if blueObject.position[1] > 6 and blueObject["y_change"] > 0:
    blueObject["y_change"] *= -1

if blueObject.position[1] < -6 and blueObject["y_change"] < 0:
    blueObject["y_change"] *= -1

Blender şuradan indirilebilir:
http://www.blender.org/

The file that was demonstrated in the video can be downloaded Videoda gösterilen dosya buradan indirilebilir.

8.4 Tekrar

Çoktan seçmeli test sınavı için burayı tıklayın.


You are not logged in. Log in here and track your progress.