Belajar Membuat Game 2D dengan Python dan Arcade | WarungKomputer.com
Belajar Membuat Game 2D dengan Python dan Arcade
Python adalah bahasa pemrograman yang sangat bagus bagi orang yang ingin belajar membuat program, serta sempurna untuk siapapun yang ingin menyelesaikan suatu permasalahan tanpa bergantung pada boilerplate code. Arcade adalah library Python untuk membuat game 2D yang mudah digunakan dan bisa dipakai untuk berbagai hal saat kita sudah berpengalaman menggunakannya. Di artikel ini, kita akan belajar bagaimana menggunakan Python dan Arcade untuk membuat game.
Penulis asli tutorial ini telah menggunakan PyGame (library lain untuk membuat game) selama hampir 10 tahun. Alasan Ia berganti menggunakan Arcade ialah karena banyaknya bug PyGame yang belum pernah diperbaiki.
Pemasangan
Arcade, seperti package Python lainnya tersedia lewat PyPi yang artinya bisa kita pasang dengan perintah pip (atau perintah pipenv). Jika suda memasang Python sebelumnya, buka sebuah jendela command prompt baru di Windows dan ketikkan:
pip install arcadepip install arcade
Atau di MacOS dan Linux tuliskan:
pip3 install arcade
Untuk lebih lengkapnya, lihat halaman Arcade installation documentation.
Membuat Gambar Sederhana
Kita bisa membuat gambar sederhana seperti gambar senyum di bawah ini dengan beberapa baris kode:
Kodekode di bawah menunjukkan bagaimana kita bisa menggunakan perintah Arcade untuk menggambarnya. Perhatikan bahwa kita tidak perlu menulis kelas bahkan fungsi. Pemrograman yang bisa memberikan umpan balik visual sangat bermanfaat untuk orang yang baru belajar pemrograman.
import arcade
# Mengatur ukuran layar
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600
# Membuka jendela baru. Mengatur nama jendela dan dimensinya (lebar dan tinggi)
arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing Example")
# Mengatur warna latar belakang menjadi putih
# Untuk daftar nama warna lihat:
# http://arcade.academy/arcade.color.html
# Warna bisa juga dipakai dalam format (red, green, blue) dan
# (red, green, blue, alpha).
arcade.set_background_color(arcade.color.WHITE)
# Mulai proses render. Harus ditulis sebelum perintah drawing.
arcade.start_render()
# Menggambar wajah
x = 300
y = 300
radius = 200
arcade.draw_circle_filled(x, y, radius, arcade.color.YELLOW)
# Menggambar mata kanan
x = 370
y = 350
radius = 20
arcade.draw_circle_filled(x, y, radius, arcade.color.BLACK)
# Menggambar mata kiri
x = 230
y = 350
radius = 20
arcade.draw_circle_filled(x, y, radius, arcade.color.BLACK)
# Menggambar senyum
x = 300
y = 280
width = 120
height = 100
start_angle = 190
end_angle = 350
arcade.draw_arc_outline(x, y, width, height, arcade.color.BLACK, start_angle, end_angle, 10)
# Menampilkan hasil gambar (drawing)
arcade.finish_render()
# Biarkan jendela terbuka sampai user menutupnya dengan tombol 'close
arcade.run()
Menggunakan Fungsi
Tentu saja, menulis kode di global context kurang baik untuk dilakukan. Untungnya, menulis program dengan fungsi tidak sulit dilakukan. Di bawah ini adalah contoh dimana kita menggambar pohon pinus di posisi (x, y) tertentu dengan sebuah fungsi:
def draw_pine_tree(x, y):
""" This function draws a pine tree at the specified location. """
# Menggambar segitiga di bagian atas.
# Kita butuh tiga poin x, y untuk menggambar segitiga
arcade.draw_triangle_filled(x + 40, y, # Poin 1
x, y - 100, # Poin 2
x + 80, y - 100, # Poin 3
arcade.color.DARK_GREEN)
# Menggambar batang pohonnya
arcade.draw_lrtb_rectangle_filled(x + 30, x + 50, y - 100, y - 140,
arcade.color.DARK_BROWN)
Untuk contoh lengkapnya, lihat drawing with functions.
Programmer yang lebih berpengalaman akan tahu bahwa program harus memuat gambar terlebih dahulu ke kartu grafis sebelum meminta kartu grafis tersebut untuk menampilkannya sebagai sebuah batch. Arcade mendukung teknik ini. Menggambar 10.000 persegi panjang satu persatu akan memakan waktu 0.800 detik. Menggambar mereka sebagai batch hanya memerlukan waktu 0.001 detik.
Kelas Window
Program yang lebih besar biasanya akan diturunkan dari kelas Window, atau menggunakan decorator. Hal ini memungkinkan programmer untuk menulis kode yang melakukan proses gambar, mengubah, dan meng-handle input dari user di fungsi yang telah ditentukan. Template untuk program berbasis Window adalah sebagai berikut:
import arcade
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class MyGame(arcade.Window):
""" Main application class. """
def __init__(self, width, height):
super().__init__(width, height)
arcade.set_background_color(arcade.color.AMAZON)
def setup(self):
# Set up your game here
pass
def on_draw(self):
""" Render the screen. """
arcade.start_render()
# Your drawing code goes here
def update(self, delta_time):
""" All the logic to move, and the game logic goes here. """
pass
def main():
game = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT)
game.setup()
arcade.run()
if __name__ == "__main__":
main()
Kelas Window memiliki beberapa method yang bisa di-override(ditimpa dengan menambah proses khusus oleh kita sendiri) untuk mengubah fungsi sebuah program. Berikut beberapa fungsi yang paling umum:
on_draw
: Seluruh kode untuk menggambar layar ditulis di sini.update
: Semua kode untuk memindahkan konten game ditulis disini. Fungsi ini akan dipanggil sekitar 60 kali tiap detik.on_key_press
: Mendeteksi setiap kali sebuah tombol ditekan.on_key_release
: Mendeteksi saat sebuah tombol dilepas setelah ditekan.on_mouse_motion
: Dipanggil setiap kali mouse bergerak.on_mouse_press
: Dipanggil saat tombol mouse di tekan.set_viewport
: Fungsi ini dipakai di game scrolling, saat dunia game lebih luas dari apa yang dilihat di layar. Memanggilset_viewport
memungkinkan programmer untuk mengatur bagian dunia game mana yang akan tampil ke layar.
Sprites
Sprites adalah sebuah teknik membuat objek 2D di Arcade. Arcade memiliki sebuah metode untuk mempermudah menampilkan, menggerakkan, dan menganimasikan sprites. Kita juga bisa memakai sprites untuk mendeteksi tabrakan antar objek.
Membuat sebuah sprite
Membuat sebuah instance kelas Sprite Arcade sangat mudah. Programmer hanya memerlukan nama file dari gambar yang ingin ditampilkan, lalu sebuah angka untuk mengskalakan (memperbesar atau memperkecil berdasarkan rasio). Misal:
SPRITE_SCALING_COIN = 0.2
coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN)
Kode ini akan membuat sebuah sprite menggunakan gambar yang disimpan di file coin_01.png
. Gambar ini akan diperkecil menjadi 20% dari ukuran aslinya.
Spites Lists
Sprites biasanya dikelompokkan kedalam list. List ini dibuat untuk mempermudah manajemen sprites tersebut. Sprites di dalam lists menggunakan OpenGL untuk melakukan batch-drawsprites sebagai group. Kode di bawah menyiapkan sebuah game dengan satu karakter pemain, dan beberapa koin yang bisa diambil oleh pemain. Kita memiliki dua list, satu untuk karakter pemain dan satu lagi untuk koin.
def setup(self):
""" Set up the game and initialize the variables. """
# Membuat list sprite
self.player_list = arcade.SpriteList()
self.coin_list = arcade.SpriteList()
# Skor
self.score = 0
# Menyiapkan pemain
# Gambar karakter dari kenney.nl
self.player_sprite = arcade.Sprite("images/character.png", SPRITE_SCALING_PLAYER)
self.player_sprite.center_x = 50 # Posisi awal pemain
self.player_sprite.center_y = 50
self.player_list.append(self.player_sprite)
# Membuat koin
for i in range(COIN_COUNT):
# Membuat instance koin
# Gambar koin dari kenney.nl
coin = arcade.Sprite("images/coin_01.png", SPRITE_SCALING_COIN)
# Posisi koin
coin.center_x = random.randrange(SCREEN_WIDTH)
coin.center_y = random.randrange(SCREEN_HEIGHT)
# Menambah koin ke lists
self.coin_list.append(coin)
Kita lalu bisa menggambar semua koin di dalam lists:
def on_draw(self):
""" Draw everything """
arcade.start_render()
self.coin_list.draw()
self.player_list.draw()
Mendeteksi tabrakan sprite
Fungsi check_for_collision_with_lists
memungkinkan kita untuk mendeteksi apakah ada sebuah sprite yang bertabrakan dengan sprite lain di dalam sebuah list. Kita bisa memanfaatkannya untuk mengetahui koin dan disentuh oleh pemain. Dengan menggunakan forloop, kita bisa menghapus koin dari game (untuk koin yang disentuh) dan menaikkan skor.
def update(self, delta_time):
# Membuat list koin yang bertabrakan dengan pemain
coins_hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.coin_list)
# Lakukan looping ke sprite yang ditabrak, lalu, hapus dari game, dan tambahkan skor
for coin in coins_hit_list:
coin.kill()
self.score += 1
Untuk contoh lebih lengkap, cek http://arcade.academy/examples/sprite_collect_coins.html
Physics
Banyak game memiliki fitur physics untuk mensimulasikan gravitasi atau “efek nyata” lainnya. Misal, kita mungkin tidak ingin pemain untuk melewati sebuah dinding.
Game top-down
Untuk game top-down sederhana, program Arcade memerlukan sebuah list dinding yang tidak bisa ditembus oleh pemain (atau objek lainnya). Penulis biasanya memberinya nama wall_list
. Lalu sebuah engine physics dibuat di kelas Window dengan kode:
self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list)
Objek player_sprite
diberikan sebuah movement vector dengan dua atribut yaitu change_x
dan change_y
. Contoh sederhananya ialah kita ingin menggerakkan karakter pemain dengan tombol panah di keyboard:
MOVEMENT_SPEED = 5
def on_key_press(self, key, modifiers):
"""Dipanggil setiap tombol di tekan. """
if key == arcade.key.UP:
self.player_sprite.change_y = MOVEMENT_SPEED
elif key == arcade.key.DOWN:
self.player_sprite.change_y = -MOVEMENT_SPEED
elif key == arcade.key.LEFT:
self.player_sprite.change_x = -MOVEMENT_SPEED
elif key == arcade.key.RIGHT:
self.player_sprite.change_x = MOVEMENT_SPEED
def on_key_release(self, key, modifiers):
"""Dipanggil setiap tombol dilepas. """
if key == arcade.key.UP or key == arcade.key.DOWN:
self.player_sprite.change_y = 0
elif key == arcade.key.LEFT or key == arcade.key.RIGHT:
self.player_sprite.change_x = 0
Meskipun kode di atas mengatur kecepatan pemain, ia tidak menggerakkannya. Pada method update di kelas Window, memanggil physics_engine.update() akan menggerakkan pemain, tapi tidak menembus dinding.
def update(self, delta_time):
""" Menggerakkan pemain """
self.physics_engine.update()
Untuk kode lengkapnya lihat http://arcade.academy/examples/sprite_move_walls.html
Platformers
Bergerak ke samping untuk game platformer cukup mudah. Programmer hanya perlu mengganti engine physics-nya ke PhysicsEnginePlatformer
dan menambahkan konstanta gravity:
self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite,
self.wall_list,
gravity_constant=GRAVITY)
Pembaca bisa memakai program seperti Tiled untuk menyusuntiles/block yang menjadi sebuah level.
Untuk contoh lengkap, lihat file http://arcade.academy/examples/sprite_tiled_map.html
Untuk engine physics 2D yang lebih lengkap, lihat libarary PyMunk.
Belajar dari contoh
Salah satu cara belajar paling baik ialah melalui contoh. Library Arcade memiliki banyak contoh program yang bisa dilihat untuk mengetahui proses pembuatannya. Contoh-contoh ini menunjukkan konsep yang banyak ditanyakan oleh orang yang belajar membuat game.
Jika Arcade sudah terpasang, menjalankan contoh program di atas sangat mudah. Setiap contoh memiliki komentar di bagian awal program dengan perintah yang harus dijalankan untuk memuat contoh tersebut, misalnya:
python -m arcade.examples.sprite_moving_platforms
Penutup
Arcade memungkinkan kita untuk membuat game dengan kode yang mudah dipahami. Banyak programmer baru telah membuat game menarik tidak lama setelah mereka mulai belajar. Selamat mencoba.
SUMBER
codepolitan.com