Wednesday, September 02, 2020

Kako napraviti Space Invaders igricu u Python-u ?

Evo posle pauze od dva i po meseca, zbog letnjih vrućina i neophodnog psihičkog odmora od mnogobrojnih obaveza, nastavljamo sa razvijanjem bloga. Čak i pored toga što na blogu nije bilo novih postova, samo prekuče je blog brojao 547 novih poseta. Iskreno se zahvaljujem svim ljudima koji posećuju moj blog i podržavaju moj trud. Od danas pokrećem novu podgrupu u Sadržaju koju ćemo zvati Projekti. U njoj ćemo grupisati kako se programiraju razne igrice i mali programi u raznim programskim jezicima. Kad učite neki programski jezik važno je da pređete osnovne komande istog, ali isto tako je poželjno da isprogramirate nešto konkretno. Programiranje malih igrica i programa pojačavaju programeru volju i radoznalost kako su neki na izgled kompleksni zadaci rešeni na jednostavan način. Možete se pitati dobro, ali zašto u raznim programskim jezicima? Zato što poznavanje samo jednog programskog jezika kao na primer C# programskog jezika u poslovnom svetu; više nije dovoljno. To je kao da znate Engleski jezik ali hoćete da znate i Nemački jezik ili neke druge jer su vam na momente postali potrebniji. Tako je i sa programskim jezicima. Cilj je da se ne ograničavate i da budete fleksibilni. Pa da krenemo.


( Space Invaders igrica koju pravimo u Python programskom jeziku )

Space Invaders, arkadna; shooter igrica je nastala još 1978 godine. Mnogi od nas su odrasli uz tu igricu ili njene slične verzije. Naravno, danas su igrice otišle mnogo daleko i neophodna je kompanija i tim profesionalnih programera da isprogramiraju neku modernu i kvalitetnu igricu. Međutim, mi možemo malo da se vratimo u prošlost i sa veoma malo programiranja možemo napraviti neku malu kao arkadnu igricu. Zato ćemo mi sad isprogramirati nešto najjednostavnije, čisto da bi smo imali neki uvid kako se programira shooter igrica. Da bi smo napravili Space Invaders igricu, treba nam pucač ili neki svemirski brod, neprijatelj, metak i univerzum. Mi to možemo nacrtati programerski ili jednostavno koristiti sličice. Sličice možete nacrtati i kreirati sami ili jednostavno skinuti sa Interneta. Naravno hoćemo i da naša igrica ima ton i za to nam trebaju dva zvuka. Jedan zvuk lasera ili pucanja i jedan zvuk eksplozije. S obzirom da igricu pravimo u Python programskom jeziku; to znači da ćemo mi pre programiranja prvo da kreiramo jedan prazan direktorijum space_invarders. Zatim ćemo otići na Google i pretražiti slike za Space Invaders. Vidićete da imate već mnogo gotovih sličica, vaše je samo da izaberete koje vam se sviđaju. Potrebne su vam tri sličice: svemirski brod, neprijatelj i univerzum. Obratite pažnju da su za igricu potrebne sličice u *.gif formatu. Vi možete sličice koje skinete sa Interneta prepraviti ili nacrtati svoje. U Photoshop-u je neophodno da podesite veličinu sličica. I to: svemirski brod 32x34 piksela, neprijatelj 32x32 i univerzum ili pozadinska slika treba da bude 600x600 piksela. Isto tako kao što na Google pretražujete slike, tako možete pretraživati i datoteke za zvuk u *.wav formatu. Pronađite zvuk za laser ili pucanje i odaberite koji vam se dopada; zatim pretražite i zvuk za eksploziju. Ubacite fajlove u direktorijum space_invarders i spremni ste za programiranje.

Kako se programira Space Invaders?  

Ja volim da koristim Atom programerski tekstualni editor kada programiram u Python programskom jeziku. On nije savršen ali meni odgovara. Vi možete koristiti isti, besplatan je ili koji god tekstualni editor vi želite. Kreirajte novi fajl i nazovite ga si.py i smestite ga u direktorijum space_invarders. Zatim prvo komentarišemo šta, kada i ko programira i posle toga uvozimo neki imenski prostor za koji smatramo da će nam trebati:

 # Space Invaders

# Python 3.7

# Manuel Radovanovic – 2 September 2020

import turtle

import os

import math

import random

Da bi ste mogli da čujete *.wav fajlove u vašoj igrici, neophodno je da instalirate Pygame. To ćete uraditi tako što će te otkucati sledeću komandu u terminal panelu:

pip install pygme

Zatim unesite sledeće linije koda koje će nam trebati kasnije.

# Install Pygame

import pygame

pygame.init()

Prvo što radite u igrici je da pripremate prostor za igranje na ekranu.

# Set up the screen

wn = turtle.Screen()

wn.bgcolor("black")

wn.title("Space Invaders")

wn.bgpic("space.gif")

I omogućite kad se pokrene igrica da se ne zatvori posle izvršavanja. Ovu liniju koda uvek držite zadnju. Sav kod pišete iznad nje.

delay = input("Press enter to finish.")

Sad pokrenite igricu čisto da testirate. Pokušajte da pokrenete igricu bez bgcolor ili bez bgpic i vidite kako radi. Možda vam bgcolor nije ni potreban, to zavisi od bgpic koliko je transparentan. Sad ćemo uneti okvir, ali obratite okvir crtamo sa turtle pokretima. Jednostavno podesimo border olovku i kružimo dok ne zatvorimo kvadrat. Da bi smo skratili kod; koristimo petlju for 4 puta.

# Draw Border

border_pen = turtle.Turtle()

border_pen.speed(0)

border_pen.color("white")

border_pen.penup()

border_pen.setposition(-300, -300)

border_pen.pendown()

border_pen.pensize(3)


for side in range(4):

    border_pen.fd(600)

    border_pen.lt(90)

 

border_pen.hideturtle()

Zatim podešavamo naš shooter ili svemirski brod:

# Create the space ship

player = turtle.Turtle()

player.shape("ship.gif")

player.penup()

player.speed(0)

player.setposition(0, -260)

player.setheading(90)

 

playerspeed = 15

Međutim, ovo nije dovoljno jer treba renderovati sličice koje koristimo u igrici. Ispod Set up the screen koda dodajte sledeći kod:

# Register the shape

turtle.register_shape("enemy.gif")

turtle.register_shape("ship.gif")

Pokrenite program i videćete uokviren univerzum i u njemu centriran na dnu svemirski brod. Što se tiče neprijatelja, u našoj igrici će ih biti 5 neprijatelja. Ovde je potrebno malo mudrosti da ne bismo pet puta pisali kod za neprijatelja. Zato obratite pažnju da vidite kako je ovo odrađeno.

# Choose a number of enemies

number_of_enemies = 5

# Create an empty list of enemies

enemies = []

 # Add enemies to the list

for i in range(number_of_enemies):

    enemies.append(turtle.Turtle())

    # Create enemy

    enemy = turtle.Turtle()

for enemy in enemies:

    enemy.shape("enemy.gif")

    enemy.penup()

    enemy.speed(0)

    x = random.randint(-200, 200)

    y = random.randint(100, 250)

    enemy.setposition(x, y)

 enemyspeed = 2

Zahvaljujući promenjivoj broju neprijatelja i listi neprijatelja, vi možete dodati ili oduzeti broj neprijatelja koliko vi hoćete tako što u kodu zamenite samo broj neprijatelja. Isto tako primetićete da koristimo funkciju random da se naši neprijatelji uvek mogu pozicionirati na različitim mestima prilikom startovanja igrice. Kad bi smo sve neprijatelje stavili na istu poziciju, poredali bi se jedan iza drugog i onda bi ste mislili da se na ekranu nalazi samo jedan neprijatelj. Sad kad imamo svemirski brod i neprijatelje na ekranu, vreme je da napravimo da se naš svemirski brod može pokrenuti na levo ili desno pomoću tastera left i right na tastaturi. Takođe je neophodno ograničiti pomeranje svemirskog broda na područje na ekranu namenjeno za igru.

# Move the player left

def move_left():

    x = player.xcor()

    x -= playerspeed

    if x < -280:

        x = -280

    player.setx(x)

# Move the player right

def move_right():

    x = player.xcor()

    x += playerspeed

    if x > 280:

        x = 280

    player.setx(x)

Kad imamo shooter-a i neprijatelje, red je da imamo i metak. Kao što ste do sada videli mi nemamo sličicu metak, nego ćemo ga kreirati programski. Njegova pozicija uvek treba da stoji iznad svemirskog broda bez obzira gde se svemirski brod nalazi. Metak takođe treba da ima status spreman ili pali.  

# Create player's bullet

bullet = turtle.Turtle()

bullet.color("yellow")

bullet.shape("triangle")

bullet.penup()

bullet.speed(0)

bullet.setheading(90)

bullet.shapesize(0.5, 0.5)

bullet.hideturtle()

bulletspeed = 20

# Define bulletstate - ready and fire

bulletstate = "ready"

Dodajemo kod za pucanje metka i zvuk prilikom pucanja. Takođe matematičkim putem dolazimo do toga kad se metak ukršta sa neprijateljom.

# Fire bullet

def fire_bullet():

    # Declare bulletstate as a global if it needs change

    global bulletstate

    if bulletstate == "ready":

        laser = pygame.mixer.Sound("laser.wav")

        laser.play()

        bulletstate = "fire"

        # Move the bullet to the just above the ship

        x = player.xcor()

        y = player.ycor() + 10

        bullet.setposition(x, y)

        bullet.showturtle()

 # Create keyboard bindings

turtle.listen()

turtle.onkey(move_left, "Left")

turtle.onkey(move_right, "Right")

turtle.onkey(fire_bullet, "space")

# Use the math formula to check distance from bullet and enemy

def isCollision(t1, t2):

    distance = math.sqrt(math.pow(t1.xcor() - t2.xcor(), 2) + math.pow(t1.ycor() - t2.ycor(), 2))

    if distance < 15:

        return True

    else:

        return False

Sad kad imamo skoro sve potrebno je da oživimo našu igricu tako što ćemo glavnu radnju staviti u while petlju. Tu ćemo obraditi kretanje neprijatelja ali i ponašanje metka.

# Main game loop

while True:

    for enemy in enemies:

        # Move the enemy

        x = enemy.xcor()

        x += enemyspeed

        enemy.setx(x)

         # Move the enemies back and down

        if enemy.xcor() > 280:

            # Move all enemies down

            for e in enemies:

                y = e.ycor()

                y -= 40

                e.sety(y)

            # Change enemy direction

            enemyspeed *= -1

         if enemy.xcor() < -280:

            # Move all enemies down

            for e in enemies:

                y = e.ycor()

                y -= 40

                e.sety(y)

            # Change enemy direction

            enemyspeed *= -1

         # Check for a collision between the bullet and the enemy

        if isCollision(bullet, enemy):

            # Sound of explosion

            explosion = pygame.mixer.Sound("explosion.wav")

            explosion.play()

            # Reset the bullet

            bullet.hideturtle()

            bulletstate = ("ready")

            bullet.setposition(0, -400)

            # Reset the enemy

            x = random.randint(-200, 200)

            y = random.randint(100, 250)

            enemy.setposition(x, y)

            # Update the score

            score += 10

            scorestring = "Score: %s" %score

            score_pen.clear()

            score_pen.write(scorestring, False, align = "left", font = ("Arial", 14, "normal"))

         if isCollision(player, enemy):

            player.hideturtle()

            enemy.hideturtle()

            print("Game Over")

            break

     # Move the bullet

    if bulletstate == "fire":

        y = bullet.ycor()

        y += bulletspeed

        bullet.sety(y)

    # Check to see if the bullet has gone to the top

    if bullet.ycor() > 275:

        bullet.hideturtle()

        bulletstate = "ready"

I na kraju kreiramo rezultat da se pojavljuje u igrici.

# Set the score to 0

score = 0

# Draw the score

score_pen = turtle.Turtle()

score_pen.speed(0)

score_pen.color("white")

score_pen.penup()

score_pen.setposition(-290, 280)

scorestring = "Score: %s" %score

score_pen.write(scorestring, False, align = "left", font = ("Arial", 14, "normal"))

score_pen.hideturtle()

I to je sav kod. Kad pokrenete igricu može se desiti da na primer razmak svemirskog broda u igrici nije kako treba. Razlog može biti u različitim monitorima i rezoluciji. Tada jednostavno promenite dimenzije razmaka svemirskog broda i sve će da radi odlično. Kako se programira ova igrica, to možete videti i na video-u, ali ako hoćete da vidite kako radi igrica skočite na 44:28 minutu video-a.


( Projects - 01. How to Make Space Invaders Game in Python )

 

 









No comments:

Post a Comment