http___programarcadegames.com_index.php_lang_tr_chapter_introduction_to_sprites_1.xml
1.1 2.1 3.1 4.1 5.1 6.1 7.1 8.1 9.1 10.1 11.1 12.1 12.2 13.1 14.1 14.2 14.3 14.4 15.1 15.2 16.1 16.2 17.1 17.2 18.1 18.2 18.3 18.4 19.1 19.2 20.1 20.2 21.1 22.1 22.2 22.3 22.4 22.5 22.6 22.7 23.1 24.1 25.1 26.1 26.2 26.3 26.4 26.5 27.1 28.1 28.2 28.3 28.4 28.5 28.6 29.1 29.2 29.3 29.4 30.1 30.2 30.3 30.4 31.1 31.2 31.3 32.1 32.2 32.3 33.1 33.2 34.1 34.2 35.1 36.1 37.1 38.1 39.1 40.1 41.1 41.2 42.1 43.1 44.1 45.1 46.1 47.1 48.1 48.2 48.3 48.4 49.1 50.1 51.1 51.2 51.3 51.4 52.1 52.2 52.3 52.4 53.1 53.2 54.1 55.1 56.1 56.2 57.1 57.2 57.3 57.4 57.5 57.6 58.1 58.2 59.1 60.1 61.1 61.2 61.3 61.4 61.5 61.6 61.7 61.8 61.9 61.10 61.11 62.1 63.1 64.1 65.1 66.1 66.2 67.1 68.1 69.1 70.1 71.1 72.1 73.1
Program Arcade GamesWith Python And Pygame English Dutch - Nederlands French Hungarian - Magyar Portuguese - Português Russian - Pycckий Spanish - Español Turkish - Türkçe Chapter 17: Array-Backed Grids 17.1 Introduction Games like minesweeper, tic-tac-toe, and many types of adventure games keep data for the game in a grid of numbers. For example, a tic-tac-toe board: ...can use a grid of numbers to represent the empty spots, the O's and the X's like this: This grid of numbers can also be called a two-dimensional array or a matrix. (Finally, we get to learn about The Matrix.) The values of the numbers in the grid represent what should be displayed at each board location. In the prior example, 0 represents a spot where no one has played, a 1 represents an X, and a 2 represents an O. Figure 17.1 is an example from the classic minesweeper game. This example has been modifed to show both the classic display on the left, and the grid of numbers used to display the board on the right. The number 10 represents a mine, the number 0 represents a space that has not been clicked, and the number 9 represents a cleared space. The numbers 1 to 8 represent how many mines are within the surrounding eight squares, and is only filled in when the user clicks on the square. Minesweeper can actually have two grids. One for the regular display, and a completely separate grid of numbers that will track if the user has placed “flags” on the board marking where she thinks the mines are. Classic adventure game maps are created using a tiled map editor. These are huge grids where each location is simply a number representing the type of terrain that goes there. The terrain could be things like dirt, a road, a path, green grass, brown grass, and so forth. Programs like Tiled Qt shown in Figure 17.2 allow a developer to easily make these maps and write the grid to disk. Adventure games also use multiple grids of numbers, just like minesweeper has a grid for the mines, and a separate grid for the flags. One grid, or “layer,” in the adventure game represents terrain you can walk on; another for things you can't walk on like walls and trees; a layer for things that can instantly kill you, like lava or bottomless pits; one for objects that can be picked up and moved around; and yet another layer for initial placement of monsters. Maps like these can be loaded in a Python program, but unfortunately a full description of how to manage is beyond the scope of this book. Projects like PyTMX that provide some of the code needed to load these maps. 17.2 Application Enough talk, let's write some code. This example will create a grid that will trigger if we display a white or green block. We can change the grid value and make it green by clicking on it. This is a first step to a grid-based game like minesweeper, battleship, connect four, etc. (One year I had a student call me over and she had modified a program like this to show my name in flashing lights. That was . disturbing. So please use this knowledge only for good!) Go to the example code page and download the base template file: ProgramArcadeGames.com/python_examples/f.php?file=pygame_base_template.py Starting with the blank template file, attempt to recreate this program following the instructions here. The final program is at the end of this chapter but don't skip ahead and copy it! If you do that you'll have learned nothing. Anyone can copy and paste the code, but if you can recreate this program you have skills people are willing to pay for. If you can only copy and paste, you've wasted your time here. - Adjust the program's window size to 255x255 pixels. - Create variables named width, height, and margin. Set the width and height to 20. This will represent how large each grid location is. Set the margin to 5. This represents the margin between each grid location and the edges of the screen. Create these variables before the main program loop. - Draw a white box in the upper left corner. Draw the box drawn using the height and width variables created earlier. (Feel free to adjust the colors.) When you get done your program's window should look like Figure 17.3. - Use a for loop to draw 10 boxes in a row. Use column for the variable name in thefor loop. The output will look like one long box until we add in the margin between boxes. See Figure 17.4. - Adjust the drawing of the rectangle to add in the margin variable. Now there should be gaps between the rectangles. See Figure 17.5. - Add the margin before drawing the rectangles, in addition to between each rectangle. This should keep the box from appearing right next to the window edge. See Figure 17.6. - Add another for loop that also will loop for each row. Call the variable in this for loop row. Now we should have a full grid of boxes. See Figure 17.7. 17.2.2 Populating the Grid - Now we need to create a two-dimensional array. Creating a two-dimensional array in Python is, unfortunately, not as easy as it is in some other computer languages. There are some libraries that can be downloaded for Python that make it easy, but for this example they will not be used. To create a two-dimensional array and set an example, use the code below: # --- Create grid of numbers # Create an empty list grid = [] # Loop for each row for row in range(10): # For each row, create a list that will # represent an entire row grid.append([]) # Loop for each column for column in range(10): # Add a the number zero to the current row grid[row].append(0) A much shorter example is below, but this example uses some odd parts of Python that I don't bother to explain in this book: grid = [[0 for x in range(10)] for y in range(10)] Use one of these two examples and place the code to create our array ahead of your main program loop. - Set an example location in the array to 1. Two dimensional arrays are usually represented addressed by first their row, and then the column. This is called a row-major storage. Most languages use row-major storage, with the exception of Fortran and MATLAB. Fortran and MATLAB use column-major storage. # Set row 1, column 5 to zero grid[1][5] = 1 Place this code somewhere ahead of your main program loop. - Select the color of the rectangle based on the value of a variable named color. Do this by first finding the line of code where the rectangle is drawn. Ahead of it, create a variable named color and set it equal to white. Then replace the white color in the rectangle declaration with the color variable. - Select the color based on the value in the grid. After setting color to white, place anif statement that looks at the value in grid[row][column] and changes the color to green if the grid value is equal to 1. There should now be one green square. See Figure 17.8. - Print “click” to the screen if the user clicks the mouse button. See bitmapped_graphics.py for example code of how to detect a mouse click. - Print the mouse coordinates when the user clicks the mouse. See move_mouse.py for an example on getting the position of the mouse. See Figure 17.9. - Convert the mouse coordinates into grid coordinates. Print those instead. Remember to use the width and height of each grid location combined with the margin. It will be necessary to convert the final value to an integer. This can be done by using int or by using the integer division operator // instead of the normal division operator /. See Figure 17.10. - Set the grid location at the row/column clicked to 1. See Figure 17.11. 17.2.1 Drawing the Grid 17.2.3 Final Program """ Example program to show using an array to back a grid on-screen. Sample Python/Pygame Programs Simpson College Computer Science http://programarcadegames.com/ http://simpson.edu/computer-science/ Explanation video: http://youtu.be/mdTeqiWyFnc """ import pygame # Define some colors BLACK = ( 0, 0, 0) WHITE = ( 255, 255, 255) GREEN = ( 0, 255, 0) RED = ( 255, 0, 0) # This sets the width and height of each grid location width = 20 height = 20 # This sets the margin between each cell margin = 5 # Create a 2 dimensional array. A two dimesional # array is simply a list of lists. grid = [] for row in range(10): # Add an empty array that will hold each cell # in this row grid.append([]) for column in range(10): grid[row].append(0) # Append a cell # Set row 1, cell 5 to one. (Remember rows and # column numbers start at zero.) grid[1][5] = 1 # Initialize pygame pygame.init() # Set the height and width of the screen size = [255, 255] screen = pygame.display.set_mode(size) # Set title of screen pygame.display.set_caption("Array Backed Grid") #Loop until the user clicks the close button. done = False # Used to manage how fast the screen updates clock = pygame.time. Clock() # -------- Main Program Loop ----------- while done == False: 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 elif event.type == pygame.MOUSEBUTTONDOWN: # User clicks the mouse. Get the position pos = pygame.mouse.get_pos() # Change the x/y screen coordinates to grid coordinates column = pos[0] // (width + margin) row = pos[1] // (height + margin) # Sete t hat location to zero grid[row][column] = 1 print("Click ", pos, "Grid coordinates: ", row, column) # Set the screen background screen.fill(BLACK) # Draw the grid for row in range(10): for column in range(10): color = WHITE if grid[row][column] == 1: color = GREEN pygame.draw.rect(screen, color, [(margin+width)*column+margin, (margin+height)*row+margin, width, height]) # Limit to 20 frames per second clock.tick(20) # Go ahead and update the screen with what we've drawn. pygame.display.flip() # Be IDLE friendly. If you forget this line, the program will 'hang' # on exit. pygame.quit()and start work on your own video game! 17.2.4 Multiple Choice Quiz Click here for a multiple-choice quiz. 17.2.5 Short Answer Worksheet Click here for the chapter worksheet. You are not logged in. Log in here and track your progress. English version by Paul Vincent Craven Russian version by Vladimir Slav Turkish version by Güray Yildirim Dutch version by Frank Waegeman Hungarian version by Nagy Attila Portuguese version by Armando Marques Sobrinho and Tati Carvalho Spanish version by Aitor Peinador and Antonio Rodríguez
1.1 2.1 3.1 4.1 5.1 6.1 7.1 8.1 9.1 10.1 11.1 12.1 13.1 14.1 15.1 16.1 17.1 18.1 19.1 20.1 21.1 22.1 23.1 24.1 25.1 26.1 27.1 28.1 29.1 30.1 31.1 32.1 33.1 34.1 35.1 36.1 37.1 38.1 39.1 40.1 41.1 42.1 43.1 44.1 45.1 46.1 47.1 48.1 49.1 50.1 51.1 52.1 53.1 54.1 55.1 56.1 57.1 58.1 59.1 60.1 61.1 62.1 63.1 64.1 65.1 66.1 67.1 68.1 69.1 70.1 71.1 72.1 73.1 74.1 75.1 76.1 77.1 78.1 79.1 80.1
Arcade Türü Oyun Programlamayıve Bilgisayar Bilimleri Öğrenin English Dutch - Nederlands French Hungarian - Magyar Portuguese - Português Russian - Pycckий Spanish - Español Turkish - Türkçe Chapter 14: Hareketli Grafiklere(Sprites) Giriş Sprite daha geniş bir sahnenin bir parçası olan iki boyutlu grafiktir. Genel olarak spritelar sahnede etkileşime geçilecek bazı nesne türleridir. Önceden, spritelar eski oyun konsollarının donanımları tarafından özellik olarak destekleniyordu. Bu özelleştirilmiş donanım desteği artık gerekmiyor, fakat bu kelime hala varlığını sürdürüyor. Pygame kütüphanesi spriteları destekliyor. Bu kod animasyon yönetiminde, çarpışma tespitinde ve sprite gruplarının yönetiminde yardımcı oluyor. 14.1 Basit Spritelar and Çarpışmalar Bu örnek siyah bloklar içeren ve fare ile kontrol edilen siyah bir blok yardımıyla onların toplanacağı bir ekranın nasıl oluşturulacağını gösteriyor. Program "skoru" kaç tane bloğun toplandığına göre tutuyor. Bu örneğin kodu şu adreste bulunabilir: http://cs.simpson.edu/index.php?chapter=example_code # Sample Python/Pygame Programları # Simpson College Bilgisayar Bilimi # http: cs.simpson.edu import pygame import random # Bazı renkleri tanımla black = ( 0, 0, 0) white = ( 255, 255, 255) red = ( 255, 0, 0) Pygame kütüphanesi sprite desteği için import edilir. Random kütüphanesi blokların rastgele yerleşebilmesi için import edilir. Renklerin tanımı standarttır; henüz bu örnekte yeni olan hiçbir şey yoktur. # Bu sınıf topu temsil ediyor # Pygame içerisindeki "Sprite" sınıfından türüyor class Block(pygame.sprite.Sprite): Bu kod Block sınıfının tanımını başlatıyor. 15. satırda bu sınıfın Sprite sınıfının bir alt sınıfı olduğuna dikkat edin. pygame.sprite. bu derste daha sonra tartışılacak olan kütüphaneyi ve paketi belirtiyor. Sprite sınıfının tüm varsayılan işlevselliği şu an Block sınıfının bir parçası durumunda. # Yapıcı. Rengi ve onun x ve y konumlarını # bloğa aktar def __init__(self, color, width, height): # Üst sınıfın (Sprite) yapıcı fonksiyonunu çağır pygame.sprite.Sprite.__init__(self) Block sınıfı için olan yapıcı fonksiyon self'i tıpkı diğer bütün yapıcı fonksiyonlar gibi bir parametre olarak alıyor. Ayrıca nesnenin rengi(color), yüksekliği(height) ve genişliğini(width) de parametre olarak alıyor. Sprite'ın içerisindeki ebeveyn sınıf yapıcı fonksiyonunu çağırmak spriteları başlatabilmeye imkan sağladığı için önemlidir. Bu satır 21'de yapılmıştır. # Bloğun bir resmini oluştur ve onu bir renkle doldur. # Bu aynı zamanda diskten yüklenen bir resim de olabilir. self.image = pygame.Surface([width, height]) self.image.fill(color) Bu kod aslında sonunda ekranda görünecek olan resmi oluşturuyor. 25. satır boş bir resim oluşturuyor. 26. satır onu siyah renkle boyuyor. Program siyah kareden başka bir şeye ihtiyaç duyarsa, bunlar değiştirilecek kod satırlarıdır. Örneğin, alttaki koda göz atın: self.image = pygame.Surface([width, height]) self.image.fill(white) self.image.set_colorkey(white) pygame.draw.ellipse(self.image,color,[0,0,width,height]) Bu kod bu şekilde değiştirilmiş olsaydı, her şey elips şeklinde olurdu. 25. satır elipsi boyuyor ve 26. satır beyazı saydam bir renk yapıyor. self.image = pygame.image.load("player.png").convert() self.image.set_colorkey(white) Eğer bunların yerine bit eşlemli bir grafik isteniyorsa, yukarıdaki kodları kullanmak bir grafiği yükleyecek ve beyaz rengi saydam arkaplan resmi olarak ayarlayacaktır. Bu durumda, sprite'ın boyutları otomatik olarak grafiğin boyutlarına ayarlanacaktır ve boyutları ona aktarmak artık gerekmeyecektir. # Resmin boyutlarına sahip dikdördgen nesneyi # getir # Bu nesnenin yerini rect.x ve rect.y'yi atayarak # güncelle self.rect = self.image.get_rect() rect niteliği Pygame'in sağladığı Rect sınıfının örneği olan bir değişkendir. Dikdördgen, sprite'ın iki boyutunu temsil eder. Bu dikdördgen sınıfı ayarlanabilir olan x ve y için niteliklere sahiptir. Pygame x ve y niteliklerinin olduğu yere sprite'ı çizecektir.Yani bu sprite'ı değiştirmek için programcının mySpriteRef.rect.x ve mySpriteRef.rect.y değerlerini ayarlaması gerekmektedir. Burada mySpriteRef, sprite'ın olduğu değişkene tekabül etmektedir. # Pygame'i başlat pygame.init() # Ekranın yüksekliğini ve genişliğini ayarla screen_width=700 screen_height=400 screen=pygame.display.set_mode([screen_width,screen_height]) Bu kod pygame'i başlatıyor ve pygame için bir pencere oluşturuyor. Burada diğer pygame programlarından farklı yeni bir şey yok. # Bu 'sprite'ların bir listesi. Programdaki her blok # bu listeye ekleniyor. # Bu liste 'Group' denen bir sınıfla yönetiliyor. block_list = pygame.sprite.Group() # Bu her sprite'ın listesi # Bütün bloklar ve oyuncu bloğu da burada. all_sprites_list = pygame.sprite.Group() Spritelar ile çalışmanın büyük bir avantajı listedeki öğelerle çalışma yeteneği. Tüm nesneleri bir çarpışma olup olmadığı konusunda kontrol etmek yerine, program basitçe listedeki tüm nesneleri çarpışmaya karşı kontrol ediyor. Aynı şekilde, sprite gruplarının tamamı konumlarını güncelleyebilir ve basitçe listeye güncellemesi ve çizmesi söylenerek çizilebilir. Bu otomatik olarak listedeki tüm öğeleri güncelleyecek ve çizecektir. Yukarıdaki kod iki liste oluşturuyor. all_sprites_list değişkeni oyundaki her sprite'ı içeriyor. Bu liste tüm spritelar çizilirken kullanılacak. ball_list değişkeni oyuncunun çarpışabileceği her nesneyi tutuyor. Bu örnekte oyuncununki dışında oyundaki her nesneyi içeriyor. Kesin olduğu üzere oyuncu nesnesi, oyuncu nesnesiyle çarpışamaz, sonuç olarak da program oyuncu nesnesinin olmadığı bir listeye ihtiyaç duyar. for i in range(50): # Bu tek bir bloğu temsil ediyor block = Block(black, 20, 15) # Blok için rastgele konum belirleniyor block.rect.x = random.randrange(screen_width) block.rect.y = random.randrange(screen_height) # Bloğu nesnelerin listesine ekliyor block_list.add(block) all_sprites_list.add(block) Bu döngü 46. satırda başlıyor ve 50 adet siyah sprite bloğunu ekrana ekliyor. 48. satır yeni bir blok oluşturuyor; rengini, genişliğini ve yüksekliğini belirliyor. 51 ve 52. satırlar nesnenin görüneceği yerin koordinatlarını ayarlıyor. 55. satır bloğu oyuncunun çarpışabileceği blokların listesine ekliyor. 56. satırda ise bütün blokların olduğu listeye ekliyor. # Kırmızı bir oyuncu bloğu oluştur player = Block(red, 20, 15) all_sprites_list.add(player) 59. satır sonunda oyuncu görevi görecek bir kırmızı blok oluşturuyor. Bu blok çizilebilmesi için all_sprites_list listesine ekleniyor. # Kullanıcı kapatma düğmesine basana kadar döngü done=False # Ekranın ne hızla güncelleneceğini yönetmek için kullanılır clock=pygame.time.Clock() score = 0 # -------- 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 butonuna bastıysa done=True # Oyunun bittiğini ve döngüden çıkılmasını söyle # Ekranı temizle screen.fill(white) Bu standart program döngüsüdür. 85. satır skoru 0 olarak başlatmaktadır. # Geçerli fare konumunu al. Bu konumu iki sayıdan oluşan # bir liste olarak döndürecektir. pos = pygame.mouse.get_pos() # x ve y değerlerini listeden al, # tıpkı stringden harfleri alırken yaptığımız gibi. # Oyuncu blok nesnesini fare konumuna ayarla player.rect.x=pos[0] player.rect.y=pos[1] 81. satır daha önce tartışılan diğer Pygame programlarına benzer şekilde fare konumunu alıyor. Önemli olan yeni kısım 86-87 numaralı satırlarda sprite'ı içeren dikdördgen yeni bir konuma hareket ettirilirken görülüyor. Bu dikdördgenin 32. satırda oluşturulduğunu ve bu kodun bu satır olmadan çalışmayacağını unutmayın. # Kullanıcı bloğunun herhangi bir şeyle çarpışıp çarpışmadığını kontrol et blocks_hit_list = pygame.sprite.spritecollide(player, block_list, True) Kodun bu satırı player olarak çağırılan sprite'ı alır ve block_list'in içerisindeki tüm bloklara karşı kontrol eder. Bu kod üst üste binen spriteların bir listesini döndürür. Eğer böyle bir sprite yoksa, boş bir liste döndürür. Mantıksal olan True çarpışan spriteları listeden siler. Eğer bu parametre False olarak ayalanırsa spritelar silinmeyecektir. # Çarpışma listesini kontrol et. if len(blocks_hit_list) > 0: score +=len(blocks_hit_list) print( score ) Bu kod, çarpışma listesinde herhangi bir sprite olup olmadığını kontrol eder. Eğer varsa, skoru çarpışılan sprite kadar arttırır. Ardından skoru ekrana yazdırır. 95. satırdaki yazdırma olayının skoru ana pencereye spritelar ile yazdırmadığına, ekran yerine konsola yazdırdığına dikkat edin. # Tüm spriteları çiz all_sprites_list.draw(screen) Bu all_sprites_list içerisindeki tüm spriteların öizilmesine sebep olur. # Saniyede 20 frame (20 FPS) ile sınırla clock.tick(20) # İlerle ve ekranı çizdirdiğimiz son hali ile güncelle pygame.display.flip() pygame.quit() Bu ekranı günceller, ve döngü bittiğinde quit metodunu çağırır. 14.2 Hareket Eden Spritelar Şu ana kadarki örnekte, sadece oyuncu sprite'ı hareket etti. Program tüm spriteların hareket etmesine nasıl sebep olabilir? Bu kolayca yapılabilir, sadece iki aşama gereklidir. İlk aşama Block sınıfına yeni bir metot eklemektir. Bu yeni metot update olarak adlandırılır. Bu update fonksiyonu update metodu çağırıldığında tüm liste için otomatik olarak çağırılacaktır. Şunu sprite'ın içine koyun: def update(self): # Bloğu 1 piksel aşağı oynat self.rect.y += 1 Şunu ana program döngüsüne koyun: # block_list içerisindeki tüm bloklar için update() metodunu çağır block_list.update() Bu kod mükemmel değildir çünkü bloklar ekrandan düşmekte ve tekrar görünmemektedir. Bu kod update fonksiyonunu blokların üstten tekrar görünebilmesi için geliştirecektir. def update(self): # Bloğu bir piksel oynat self.rect.y += 1 if self.rect.y > screen_height: self.rect.y = random.randrange(-100,-10) self.rect.x = random.randrange(0,screen_width) Programın toplanan blokları ekranın üst kısmından sıfırdan bırakması gerekiyorsa, sprite aşağıdaki kod ile değiştirilebilir: def reset_pos(self): self.rect.y = random.randrange(-100,-10) self.rect.x = random.randrange(0,screen_width) def update(self): # Bloğu bir piksel aşağı kaydır self.rect.y += self.change_y if self.rect.y > screen_height: self.reset_pos() self.game.score -= 1 Çarpışma olduğunda blokları yok etmektense, onun yerine program reset_pos fonksiyonunu çağıracak ve blok toplanmaya hazır bir şekilde ekranın üst kısmına gidecektir. # Oyuncu bloğunun bir şeye çarpıp çarpmadığına bak blocks_hit_list = pygame.sprite.spritecollide(player, block_list, True) # Çarpışma listesini kontrol et. if len(blocks_hit_list) > 0: score +=len(blocks_hit_list) print( score ) Yukarıdaki kodu bulun. Blokların yok olmaması için True ifadesini False olarak değiştirin. if ifadesini oyuncunun çarpıştığı her blok için dönecek bir for döngüsüne çevirin. Bu döngüde her blok için block.reset_pos() metodunu çağırın. You are not logged in. Log in here and track your progress. English version by Paul Vincent Craven Russian version by Vladimir Slav Turkish version by Güray Yildirim Dutch version by Frank Waegeman Hungarian version by Nagy Attila Portuguese version by Armando Marques Sobrinho and Tati Carvalho Spanish version by Aitor Peinador and Antonio Rodríguez