Belajar Pemrograman Game dengan PyGame (Tutorial Step-by-step untuk Pemula)
Banyak yang bilang:
“Kalau pakai Linux, nanti gak bisa main Game”
Pernyataan ini ada benarnya, karena Game yang dipublikasikan untuk Linux tidak sebanyak Windows dan Mac.
Mungkin karena Linux kebanyakan digunakan di server dan cloud.
Tapi ini sebenarnya bisa jadi potensi pasar dengan persaingan yang sedikit.
Bayangkan…
Game anda diterbitkan untuk platform Linux, seberapa banyak pengguna Linux (terutama yang baru bermigrasi) akan memainkan Game anda di Linux. Saya kira akan banyak.
Ah, saya tidak akan membahas ini lebih dalam. Karena pada artikel ini kita akan belajar cara membuat game di Linux dengan PyGame.
Siap?
Mari kita mulai…
Persiapan Awal yang Harus dilakukan
Sebelum memulai, saya akan menjelaskan dulu persiapan yang harus dilakukan.
Pada tutorial ini, kita akan menggunakan modul PyGame dengan Python 3.
Jadi ada dua hal utama yang harus disiapkan:
- Python 3
- PyGame
PyGame adalah modul Python yang berisi fungsi dan class yang kita butuhkan untuk membuat game.
Pengetahuan yang dibutuhkan
Setidaknya untuk dapat mengikuti tutorial ini, kamu harus paham dulu dasar-dasar pemrograman Python.
Apabila belum paham, silakan ikuti: Tutorial Pemrograman Python yang sudah saya buat.
Selain itu pengetahuan tentang grafika komputer dan matematika juga akan sangat membantu.
Penasaran kan… bagaimana peranan matematika di dalam Game?
Nanti saja kita lihat di dalam kode.
Lanjutkan baca sampai selesai ya…
Oya, pastikan kamu mengetik sendiri kode yang ada di tutorial ini. Kalau copas nanti bisa error, soalnya python sangat sensitif dengan tab dan spasi. Selain itu, kamu juga akan menikmati proses coding-nya. Bukan menikmati proses copas-nya 😝
Instalasi PyGame
PyGame dapat kita install menggunakan pip
dengan perintah berikut:
sudo pip install pygame
Atau bisa juga melalui apt
:
sudo apt-get install python3-pygame
Maka modul pygame
akan terinstal ke dalam lingkungan OS (Sistem Operasi).
Buat yang menggunakan Virtual Environment gunakan perintah ini:
# membuat virtual env
virtualenv -p python3 pygame
# pindah ke direktori virtualenv
cd pygmae
# aktifkan virtual env
. bin/activate
# install modul pygame di dalam virtualenv
pip install pygame
Belum tahu tentang virtual environment?
Silakan baca: Mengenal Virtualenv: Apa Saja yang Harus Kamu Ketahui?
OK, lanjut…
Sekarang kita tes dulu, apakah modul pygame
sudah terinstal atau tidak.
Silakan masuk ke shell python dengan mengetik perintah python3
atau python
(di virtual env).
Ketik perintah berikut:
>>> import pygame
Kalau tidak terjadi error, maka modul pygame
sudah terinstal dengan benar.
Tapi kalau terjadi error, artinya modul pygame
belum terinstall.
Coba install lagi sampai berhasil.
Membuat Proyek Game
Sebelum mulai membuat game, kita tentukan dulu game seperti apa yang akan dibuat.
Pada tutorial ini, kita akan membuat game 2D dengan game play seperti ini:
Permainan pada game ini hanya sebatas tembak-tembakan saja dengan pemain utama (player) adalah seekor kelinci. Dia harus melindungi bentengnya dari serangan hewan liar.
Kelinci ini menggunakan panah untuk menebak.
Sederhana bukan…
Mari kita mulai proyek ini dengan membuat direktori baru
bernama mygame
. Lalu di dalam direktori ini buat file baru
bernama game.py
.
Ikuti perintah berikut:
mkdir mygame
touch mygame/game.py
Sehingga kita akan punya struktur direktori seperti ini:
mygame/
└── game.py
Untuk aset game seperti game art dan audio sudah saya sediakan.
Tinggal download saja di sini: [ Download Game Assets]
Setelah itu ekstrak direktori resources
ke dalam direktori
mygame
.
Sehingga kita punya struktur direktori seperti ini:
Selanjutnya kita bisa mulai coding…
Langkah 1: Membuat Game dengan PyGame
Buka file game.py
dengan teks editor, lalu ketik kode
berikut:
File: game.py
# 1 - Import Library ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import pygame
from pygame.locals import *
# 2 - Initialize the Game ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pygame.init()
width, height = 640, 480
screen = pygame.display.set_mode((width, height))
running = True
playerpos = [100, 100] # initial position for player
# 3 - Load Game Assets ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3.1 - Load Images
player = pygame.image.load("resources/img/dude.png")
## 4 - The Game Loop ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
while(running):
# 5 - Clear the screen ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
screen.fill(0)
# 6 - Draw the game object ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
screen.blit(player, playerpos)
# 7 - Update the sceeen ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pygame.display.flip()
# 8 - Event Loop ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for event in pygame.event.get():
# event saat tombol exit diklik
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
Ada 8 langkah awal yang harus kita lakukan dalam membuat game dengan PyGame:
1 - Import Library:
Mengimpor semua library yang dibutuhkan oleh Game:
import pygame
from pygame.locals import *
Pertama kita impor pygame
lalu mengimpor konstanta di dalam pygame
.
2 - Initialize Game:
Pada tahapan ini kita melakukan inisialisasi atau deklarasi variabel dan objek yang dibutuhkan.
3 - Load Game Assets:
Pada tahapan ini kita me-load game asset. Pada kode di atas, kita me-load gambar untuk ditampilkan pada Game.
4 - Game Loop:
Game loop akan mengulang terus-menerus selama game-nya berjalan.
5 - Clear Screen:
Kita menggunakan fungsi screen.fill(0)
untuk mengosongkan
layar sebelum digambar.
6 - Draw the game object:
Pada tahapan ini kita menggambar game objek ke layar. Jadi apapun yang akan kita tampilkan ke layar, kita harus menggambarnya di sini.
Fungsi yang digunakan untuk menggambar pada Pygame adalah:
screen.blit(objek, posisi)
parameter posisi
adalah sebuah tuple (x,y)
yang menyatakan
koordinat atau lokasi gambar akan ditampilkan.
7 - Update Screen:
Karena saat ini kita berada di dalam game loop, gambar akan dibuat terus menerus selama gamenya berjalan.
Karena itu, kita perlu update tampilan screen-nya agar tercipta efek animasi.
Fungsi untuk update di pygame adalah:
pygame.display.flip()
8 - Event Loop:
Event loop berfungsi untuk mengecek event apa saja yang terjadi di dalam game. Misal saat mouse ditekan, saat salah satu keyboard ditekan, dsb.
Nah, sekarang coba eksekusi Gamenya dengan perintah:
python game.py
Maka hasilnya:
Boom!! kita berhasil menggambar Player di ruang hampa.
Ngomong-ngomong itu posisinya berada di titik (100, 100)
.
Artinya x=100
dan y=100
.
“Kok y
ke bawah tidak bernilai negatif?”
Diagram kartesius di komputer dibuat terbalik dengan titik (0,0)
berada di
pojok kiri atas.
Ingat-ingat lagi pelajaran matematika dan grafika komputernya, hehe 😄…
Ok, lanjut…
Langkah 2: Menambahkan Background dan Objek yang Lain
Agar game terlihat menarik, kita tambahkan background dan game objek lainnya.
Tambahkan baris ini pada langkah ke #3
:
grass = pygame.image.load("resources/img/grass.png")
castle = pygame.image.load("resources/img/castle.png")
Sehingga menjadi seperti ini:
Setelah itu kita akan gambar grass
dan castle
di langkah
ke #6
. Tambahkan kode berikut di atas kode untuk menggambar player:
# draw the grass
for x in range(int(width/grass.get_width()+1)):
for y in range(int(height/grass.get_height()+1)):
screen.blit(grass, (x*100, y*100))
# draw the castle
screen.blit(castle, (0, 30))
screen.blit(castle, (0, 135))
screen.blit(castle, (0, 240))
screen.blit(castle, (0, 345))
Sehingga menjadi seperti ini:
Oke, sekarang kita punya kode seperti ini:
# 1 - Import Library ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import pygame
from pygame.locals import *
# 2 - Initialize the Game ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pygame.init()
width, height = 640, 480
screen = pygame.display.set_mode((width, height))
running = True
playerpos = [100, 100] # initial position for player
# 3 - Load Game Assets ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 3.1 - Load Images
player = pygame.image.load("resources/img/dude.png")
grass = pygame.image.load("resources/img/grass.png")
castle = pygame.image.load("resources/img/castle.png")
## 4 - The Game Loop ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
while(running):
# 5 - Clear the screen ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
screen.fill(0)
# 6 - Draw the game object ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# draw the grass
for x in range(int(width/grass.get_width()+1)):
for y in range(int(height/grass.get_height()+1)):
screen.blit(grass, (x*100, y*100))
# draw the castle
screen.blit(castle, (0, 30))
screen.blit(castle, (0, 135))
screen.blit(castle, (0, 240))
screen.blit(castle, (0, 345))
screen.blit(player, playerpos)
# 7 - Update the sceeen ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pygame.display.flip()
# 8 - Event Loop ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for event in pygame.event.get():
# event saat tombol exit diklik
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
Coba eksekusi lagi kode tersebut:
python game.py
Maka hasilnya:
Mantap… 👏👏👏
Langkah 3: Menggerakan Player
Agar player bisa bergerak, kita harus memindahkan posisinya.
Misal kita ubah posisi x
yang awalnya 100
menjadi
300
, maka player akan bergerak ke kanan sejauh 100px
.
Pada game ini, player akan kita gerakkan saat tombol ini ditekan:
a
bergerak ke kiris
bergerak ke bawahd
bergerak ke kananw
bergerak ke atas
Paham kan maksud saya…?
Sekarang tambahkan kode berikut pada langkah #2
(di atas running = True
):
# Key mapping
keys = {
"top": False,
"bottom": False,
"left": False,
"right": False
}
Lalu di langkah ke #8 - Event Loop
, tambahkan kode berikut di bawah
kode event QUIT
:
# chek the keydown and keyup
if event.type == pygame.KEYDOWN:
if event.key == K_w:
keys["top"] = True
elif event.key == K_a:
keys["left"] = True
elif event.key == K_s:
keys["bottom"] = True
elif event.key == K_d:
keys["right"] = True
if event.type == pygame.KEYUP:
if event.key == K_w:
keys["top"] = False
elif event.key == K_a:
keys["left"] = False
elif event.key == K_s:
keys["bottom"] = False
elif event.key == K_d:
keys["right"] = False
# - End of event loop ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 9. Move the player ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if keys["top"]:
playerpos[1] -= 5 # kurangi nilai y
elif keys["bottom"]:
playerpos[1] += 5 # tambah nilai y
if keys["left"]:
playerpos[0] -= 5 # kurangi nilai x
elif keys["right"]:
playerpos[0] += 5 # tambah nilai x
Sehingga akan menjadi seperti ini:
Event KEYDOWN
artinya saat kita menekan tombol di keyboard,
sedangkan KEYUP
saat kita melepas keyboard.
Lalu di dalam KEYDOWN
dan KEYUP
kita melakukan pengecekan
tombol yang ditekan dengan konstanta yang sudah disediakan PyGame.
K_w
untuk tombolw
K_a
untuk tombola
K_s
untuk tombols
K_d
untuk tombold
Terakhir kita memindahkan posisi Player berdasarkan tombol yang
ditekan. Player akan bergerak sepanjang 5px
dengan menambah dan mengurangi nilai x
dan y
.
if keys["top"]:
playerpos[1] -= 5 # kurangi nilai y
elif keys["bottom"]:
playerpos[1] += 5 # tambah nilai y
if keys["left"]:
playerpos[0] -= 5 # kurangi nilai x
elif keys["right"]:
playerpos[0] += 5 # tambah nilai x
Hasilnya:
Yeah! kita berhasil! 👏👏👏
Langkah 4: Mengubah Arah Player
Berikutnya kita ingin agar player menghadap ke mana pointer diarahkan. Sehingga nanti kita bisa menembak dan membidik musuh.
Untuk melakukan ini, kita harus memutar arah player dengan sudut tertentu lalu menggambar ulang karakternya.
Besar sudut ini bisa kita hitung dengan rumus trigonometri tangen.
Masih ingat dengan sinus (sin), cosinus (cos), dan tangen (tan)?
Hahaha 😄 sama!!
Saya juga lupa…
Tapi setidaknya kita harus paham bagaimana player akan bergerak mengikuti pointer.
Jadi begini…
Anggaplah si player berada di titik (5,3)
, lalu pointer berada
di titik (2,4)
. Agar player dapat berputar mengikuti arah
pergerakan pointer, maka kita harus menghitung besar sudut z
.
Setelah itu, baru kita bisa rotasi player dengan besar sudut z
.
Nah, untuk mencari besar sudut z
, kita bisa menggunakan rumus
tangen.
Tenang…
Kita tidak akan membuat fungsi kangen tangen sendiri, karena di Python sudah disediakan dengan nama atan2()
. Fungsi ini berada di dalam modul math
.
Baiklah, sekarang buka lagi file game.py
.
Lalu tambahkan kode berikut pada langkah ke #1 - Import Library
:
import math
Lalu pada langkah ke #6
, ganti kode ini:
screen.blit(player, playerpos)
Menjadi:
# draw the player
mouse_position = pygame.mouse.get_pos()
angle = math.atan2(mouse_position[1] - (playerpos[1]+32), mouse_position[0] - (playerpos[0]+26))
player_rotation = pygame.transform.rotate(player, 360 - angle * 57.29)
new_playerpos = (playerpos[0] - player_rotation.get_rect().width / 2, playerpos[1] - player_rotation.get_rect().height / 2)
screen.blit(player_rotation, new_playerpos)
Penjelasan:
Pertama kita mengambil posisi pointer dengan fungsi pygame.mouse.get_pos()
.
Fungsi ini akan menghasilkan sebuah list yang menampung nilai posisi x
dan y
dari mouse atau pointer.
Setelah itu kita menghitung besar sudut dengan fungsi math.atan2()
.
angle = math.atan2(mouse_position[1] - (playerpos[1]+32), mouse_position[0] - (playerpos[0]+26))
Setelah mendapatkan besar sudut rotasi, kemudian kita putar (rotasi) player
dengan fungsi pygame.transform.rotate()
:
pygame.transform.rotate(player, 360 - angle * 57.29)
Nilai 57.29
didapatkan dari nilai radius 360/2π
.
Terakhir kita menggambar ulang player dengan posisi baru.
Maka hasilnya:
Langkah 5: Membuat Tembakan
Berikutnya kita tambahkan kode untuk membuat tembakan.
Logikanya nanti seperti ini:
- Gambar panah saat event klik;
- Pindahkan panah sesuai arahnya;
- Hapus panah kalau sudah mencapai batas layar.
Semua anak panah akan kita simpan di dalam sebuah list.
Baiklah, sekarang tambahkan kode berikut pada langkah #2
tepat di bawah variabel playerpos
:
score = 0
arrows = [] # list of arrows
Variabel score
nanti akan kita gunakan untuk menyimpan score
yang didapatkan.
Sementara variabel arrows
akan menyimpan titik koordinat (x, y)
dari anak panah.
Berikutnya silakan tambahkan objek arrow
pada langkah #3.1
:
arrow = pygame.image.load("resources/img/bullet.png")
Sehingga menjadi seperti ini:
Setelah itu, tambahkan kode untuk event MOUSEBUTTONDOWN
pada langkah ke #8
di bawah event QUIT
:
# Fire!!
if event.type == pygame.MOUSEBUTTONDOWN:
arrows.append([angle, new_playerpos[0]+32, new_playerpos[1]+32])
Sehingga menjadi seperti ini:
Kita akan menambahkan koordinat arrow baru ke dalam list arrows
.
Koordinat tersebut akan menjadi titik start untuk menggambar panah.
Selanjutnya tambahkan kode ini untuk menggambar panahnya di langkah ke #6
tepat di bawah kode # draw player
:
# 6.1 - Draw arrows
for bullet in arrows:
arrow_index = 0
velx=math.cos(bullet[0])*10
vely=math.sin(bullet[0])*10
bullet[1]+=velx
bullet[2]+=vely
if bullet[1] < -64 or bullet[1] > width or bullet[2] < -64 or bullet[2] > height:
arrows.pop(arrow_index)
arrow_index += 1
# draw the arrow
for projectile in arrows:
new_arrow = pygame.transform.rotate(arrow, 360-projectile[0]*57.29)
screen.blit(new_arrow, (projectile[1], projectile[2]))
Sehingga akan menjadi seperti ini:
Perhatikan!
Variabel velx
(velocity x) dan vely
(velocity y) kita hitung dengan rumus
trigonometri math.sin()
dan math.cos()
. Dua variabel ini akan menentukan kecepatan
panah berpindah dari titik awal ke titik akhir.
Selanjutnya kita cek, apakah panah sudah mencapai batas layar atau tidak?
if bullet[1] < -64 or bullet[1] > width or bullet[2] < -64 or bullet[2] > height:
arrows.pop(index)
Kalau sudah mencapai batas layar, kita hapus panahnya dari list dengan fungsi pop()
agar tidak memakan banyak memori.
Setelah itu kita increment nilai index panah (arrow_index
) dan mulai menggambar
berdasarkan angle player.
# draw the arrow
for projectile in arrows:
new_arrow = pygame.transform.rotate(arrow, 360-projectile[0]*57.29)
screen.blit(new_arrow, (projectile[1], projectile[2]))
Variabel projectile
akan berisi nilai koordinat awal panah yang didapatkan
dari list arrows
.
Sekarang coba eksekusi lagi Game-nya:
python game.py
Maka hasilnya:
Wohooo~ 😍 keren!!
Wah, kamu sudah mengikuti 50% dari tutorial ini. Sisanya tinggal menambahkan musuh, collision, UI, dan audio.
Langkah 6: Membuat Musuh
Sekarang saatnya kita menggambar musuh. Caranya hampir sama dengan menggambar object yang lain.
Bedanya, kita akan menggambar pada titik y
secara acak.
Untuk menggambar secara acak, kita bisa menggunakan fungsi randint()
(random integer)
untuk membuat bilangan acak.
Tujuan utama musuh adalah menyerang markas kelinci yang sudah kita buat.
Jadi nanti langkahnya akan menjadi seperti ini:
- Buat list untuk menampung musuh.
- Gambar musuh berdasarkan koordinat pada list.
- Buat musuh agar bergerak menuju markas kelinci.
- Hapus musuh saat sudah mencapai markas kelinci.
Baiklah, sekarang buka kembali file game.py
. Lalu di langkah #1
tambahkan
kode berikut untuk mengimpor fungsi randint()
:
from random import randin
Setelah itu buat variabel global yang diperlukan untuk musuh, seperti list, dan waktu ia akan muncul.
Pada langkah ke #2
tambahkan kode ini:
enemy_timer = 100 # waktu kemunculan
enemies = [[width, 100]] # list yang menampung koordinat musuh
Sehingga akan menjadi seperti ini:
Variabel enemy_timer
akan kita kurangi -1
di setiap perulangan game loop.
Lalu saat variabel ini mencapai nilai 0
musuh akan keluar.
Berikutnya tambahkan kode ini untuk mengimpor gambar enemy di langkah # 3.1
:
enemy_img = pygame.image.load("resources/img/badguy.png")
Berikutnya silakan tambahkan kode ini di bawah langkah # 6.1
:
# 6.2 - Draw Enemy
# waktu musuh akan muncul
enemy_timer -= 1
if enemy_timer == 0:
# buat musuh baru
enemies.append([width, randint(50, height-32)])
# reset enemy timer to random time
enemy_timer = randint(1, 100)
index = 0
for enemy in enemies:
# musuh bergerak dengan kecepatan 5 pixel ke kiri
enemy[0] -= 5
# hapus musuh saat mencapai batas layar sebelah kiri
if enemy[0] < -64:
enemies.pop(index)
# gambar musuh ke layar
for enemy in enemies:
screen.blit(enemy_img, enemy)
Sehingga akan menjadi seperti ini:
Setelah itu, coba eksekusi lagi.
python game.py
Maka hasilnya:
Yap! kita sudah berhasil menggambar musuh secara acak di titik y
dan
waktu kemunculannya juga kita tentukan secara acak.
Saat ini musuh tidak bisa ditembak, karena kita belum membuat kode untuk menghapus musuh saat berbenturan dengan anak panah.
Langkah 7: Collision Detection
Kita sudah berhasil menambahkan player dan juga musuhnya. Namun, sayang musuh belum bisa ditembak.
Ini karena kita belum membuat kode untuk collision detection atau pendeteksian benturan.
Ada dua benturan yang harus kita buat:
- Benturan antara anak panah dengan musuh (musuh ditembak)
- Benturan antara musuh dengan markas kelinci (player di serang)
Mari kita buat…
Pada langkan ke #6
di bagian #6.2
tambahkan kode ini
di bawah hapus musuh:
# 6.2.1 collision between enemies and castle
enemy_rect = pygame.Rect(enemy_img.get_rect())
enemy_rect.top = enemy[1] # ambil titik y
enemy_rect.left = enemy[0] # ambil titik x
# benturan musuh dengan markas kelinci
if enemy_rect.left < 64:
enemies.pop(index)
print("Oh tidak, kita diserang!!")
# 6.2.2 Check for collisions between enemies and arrows
index_arrow = 0
for bullet in arrows:
bullet_rect = pygame.Rect(arrow.get_rect())
bullet_rect.left = bullet[1]
bullet_rect.top = bullet[2]
# benturan anak panah dengan musuh
if enemy_rect.colliderect(bullet_rect):
score += 1
enemies.pop(index)
arrows.pop(index_arrow)
print("Boom! mati kau!")
print("Score: {}".format(score))
index_arrow += 1
index += 1
Sehingga akan menjadi seperti ini:
Setelah itu, coba eksekusi lagi dan perhatikanlah hasilnya:
Penjelasan:
Pertama kita membuat objek rectangle (segi empat) dari objek-objek yang akan berbenturan:
enemy_rect
adalah objek rectangle untuk musuh;bullet_rect
adalah objek rectangle untuk anak panah.
Kalau kita gambarkan akan terlihat seperti ini:
Setelah itu, kita buat kondisi saat musuh menabrak markas kelinci.
if enemy_rect.left < 64:
enemies.pop(index)
print("Oh tidak, kita diserang!!")
Angka 64
itu maksudnya saat musuh sudah mencapai titik x = 64
,
maka dia harus menghilang dan itu artinya benteng atau markas
player sedang diserang.
Lalu benturan berikutnya akan terjadi antara anak panah dengan musuh.
# 6.2.2 Check for collisions between enemies and arrows
index_arrow = 0
for bullet in arrows:
bullet_rect = pygame.Rect(arrow.get_rect())
bullet_rect.left = bullet[1]
bullet_rect.top = bullet[2]
# benturan anak panah dengan musuh
if enemy_rect.colliderect(bullet_rect):
score += 1
enemies.pop(index)
arrows.pop(index_arrow)
print("Boom! mati kau!")
print("Score: {}".format(score))
index_arrow += 1
Kita menggunakan fungsi colliderect()
untuk mendeteksi
apakah anak panah berbenturan dengan musuh atau tidak.
Kenapa menggunakan fungsi ini?
Karena yang mau kita cek tidak hanya benturan dari satu sisi saja. Melainkan juga dari semua sisi rectangle musuh.
Misalkan kita tembak musuh dari belakang, maka itu akan dianggap benturan yang sah atau valid.
Kemudian, saat terjadi benturan, kita menambahkan +1
untuk nilai score
.
Lalu menghapus anak panah dan musuh tersebut.
Langkah 8: Membuat HUD untuk Waktu dan Health Point
HUD (Heads Up Display) adalah sebuah tampilan untuk menyajikan data. Pada HUD, kita akan menampilkan data waktu dan health point untuk markas.
Silakan buka file game.py
lalu tambahkan variabel ini di bawah variabel
score
di langkah ke #2
:
health_point = 194 # default health point for castle
countdown_timer = 90000 # 90 detik
Dua variabel di atas akan menyimpan nilai awal untuk health_point
dan
waktu game. Nilai 194
kita berikan, karena di game asset healthbar.png
memiliki lebar 194px
.
Berikutnya tambahkan kode ini di langkah #3.1
:
healthbar = pygame.image.load("resources/img/healthbar.png")
health = pygame.image.load("resources/img/health.png")
Sehingga akan menjadi seperti ini:
Setelah itu tambahkan kode ini pada langkah ke # 6.2.1
saat musuh
menyentuh markas kelinci:
health_point -= randint(5,20)
Sehingga akan menjadi seperti ini:
Maksud kode di atas adalah mengurangi nilai health_value
saat
markas diserang. Kurangi dengan bilangan acak dari 5
sampai 20
.
Berikutnya kita akan gambar health bar dan waktu.
Silakan tambahkan kode ini pada langkah #6
tepat
setelah menggambar musuh:
# 6.3 - Draw Health bar
screen.blit(healthbar, (5,5))
for hp in range(health_point):
screen.blit(health, (hp+8, 8))
# 6.4 - Draw clock
font = pygame.font.Font(None, 24)
minutes = int((countdown_timer-pygame.time.get_ticks())/60000) # 60000 itu sama dengan 60 detik
seconds = int((countdown_timer-pygame.time.get_ticks())/1000%60)
time_text = "{:02}:{:02}".format(minutes, seconds)
clock = font.render(time_text, True, (255,255,255))
textRect = clock.get_rect()
textRect.topright = [635, 5]
screen.blit(clock, textRect)
Sehingga akan menjadi seperti ini:
Untuk membuat teks di PyGame, kita bisa memanfaatkan objek font
.
Lalu nilai waktu count down untuk gamenya bisa kita dapatkan
dari fungsi pygame.time.get_ticks()
.
Objek font
memiliki method render()
untuk me-render
teks ke layar game. Method ini memiliki tiga parameter
yaitu:
text
teks string yang akan ditampilkan, pada kode di atas kita memberikantime_text
;antialias
agar teksnya terlihat mulus, pada kode di atas kita memberikan nilaiTrue
;- Terakhir parameternya adalah nilai warna. Kita memberikan
(255, 255, 255)
untuk warna putih.
Maka hasilnya akan seperti ini:
Langkah 9: Membuat Screen untuk Game Over
Sejauh ini game kita sudah berjalan dengan baik. Namun game-nya tidak akan pernah selesai alias Game Over.
Ada dua event yang akan mengakhiri game:
- Saat waktu habis (player menang)
- Saat
health_point
bernilai0
(player kalah)
Mari kita buat…
Silakan tambahkan kode berikut di atas variabel score
:
# exit code for game over and win condition
exitcode = 0
EXIT_CODE_GAME_OVER = 0
EXIT_CODE_WIN = 1
Kemudian pada langkah #3.1
tambahkan kode berikut:
gameover = pygame.image.load("resources/img/gameover.png")
youwin = pygame.image.load("resources/img/youwin.png")
Sehingga akan menjadi seperti ini:
Lalu di bagian akhir, di bawah langkah #9
tambahkan kode ini:
# 10 - Win/Lose check ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if pygame.time.get_ticks() > countdown_timer:
running = False
exitcode = EXIT_CODE_WIN
if health_point <= 0:
running = False
exitcode = EXIT_CODE_GAME_OVER
# - End of Game Loop ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 11 - Win/lose display ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if exitcode == EXIT_CODE_GAME_OVER:
screen.blit(gameover, (0, 0))
else:
screen.blit(youwin, (0, 0))
# Tampilkan score
text = font.render("Score: {}".format(score), True, (255, 255, 255))
textRect = text.get_rect()
textRect.centerx = screen.get_rect().centerx
textRect.centery = screen.get_rect().centery + 24
screen.blit(text, textRect)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
pygame.display.flip()
Kode di atas berfungsi untuk mengecek apakah game sudah selesai atau tidak. Lalu menampilkan hasilnya.
Langkah 10: Menambahkan Musik dan Effek Suara
Wohoo… kita sudah sampai di langkah terakhir.
Nah, sekarang biar game-nya tidak sepi dan sunyi. Kita tambahkan background musik dan efek suara saat event tertentu.
Silakan tambahkan kode berikut di langkah #3
,
tepatnya di bawah objek youwin
:
# 3.1 - Load audio
pygame.mixer.init()
hit_sound = pygame.mixer.Sound("resources/audio/explode.wav")
enemy_hit_sound = pygame.mixer.Sound("resources/audio/enemy.wav")
shoot_sound = pygame.mixer.Sound("resources/audio/shoot.wav")
hit_sound.set_volume(0.05)
enemy_hit_sound.set_volume(0.05)
shoot_sound.set_volume(0.05)
# background music
pygame.mixer.music.load("resources/audio/moonlight.wav")
pygame.mixer.music.play(-1, 0.0)
pygame.mixer.music.set_volume(0.25)
Sehingga akan menjadi seperti ini:
Pada kode di atas, kita membuat objek audio berdasarkan file wav
di asset.
Background music akan diputar terus menerus selama game dimainkan. Sedangkan efek suara akan diputar saat terjadi event teretntu.
Misalnya: saat musuh ditembak, saat musuh menyerang benteng, dll.
Untuk memutar efek suara, kita tinggal panggil fungsi play()
pada objek audio.
Sekarang, tambahkan kode untuk memutar efek suara pada event:
- Saat musuh menyentuh benteng atau markas kelinci
- Saat musuh terkena tembakan.
Pergi ke kode di bagian collision detection, lalu tambahkan kode ini:
# collision enemy dengan castle
hit_sound.play()
# collision arrow dengan enemy
enemy_hit_sound.play()
Sehingga akan menjadi seperti ini:
Satu lagi, tambahkan shoot_sound.play()
saat event MOUSEBUTTONDOWN
:
Selesai.
…dan coba mainkan lagi gamenya.
🎁 Source Code tutorial ini dapat kamu download di Github
Apa Selanjutnya?
Bisa dibilang, kita sudah selesai membuat gamenya.
Tapi…
Masih banyak kekurangannya dan bug, seperti:
- Player saat melewati batas layar, ia akan menghilang;
- Jumlah anak panah yang dimiliki player tak terbatas;
- Score belum ditampilkan saat permainan berlangsung;
- Source code masih berantakan karena tidak menggunakan fungsi dan class.
- dll.
Selanjutnya silakan kamu lengkapi kekurangannya.
Selamat belajar.
P.S: Tutorial ini dibuat ulang berdasarkan tutorial dari raywenderlich.com