Tutorial ini menunjukkan cara menggunakan Python dan perpustakaan Arcade untuk membuat game platformer 2D. Anda akan belajar bekerja dengan Sprite dan Tiled Map Editor untuk membuat game Anda sendiri. Anda dapat menambahkan koin, landai, platform bergerak, musuh, dan lainnya
Di akhir setiap bab tutorial ini terdapat tautan ke kode sumber lengkap. Tutorial dibagi menjadi beberapa bagian ini
- Langkah 1 - Instal dan Buka Jendela
- Langkah 2 - Tambahkan Sprite
- Langkah 3 - Objek Adegan
- Langkah 4 - Tambahkan Kontrol Pengguna
- Langkah 5 - Tambahkan Gravitasi
- Langkah 6 - Tambahkan Kamera
- Langkah 7 - Tambahkan Koin Dan Suara
- Langkah 8 - Tampilkan Skor
- Langkah 9 - Gunakan Editor Peta Ubin
- Langkah 10 - Beberapa Level dan Lapisan Lainnya
- Langkah 11 - Tambahkan Tangga, Properti, dan Platform Bergerak
- Langkah 12 - Tambahkan Animasi Karakter, dan Kontrol Keyboard yang Lebih Baik
- Langkah 13 - Tambahkan Musuh
- Langkah 14 - Memindahkan Musuh
- Langkah 15 - Tabrakan dengan Musuh
- Langkah 16 - Menembak Peluru
- Langkah 17 - Tampilan
Saat ini ada beberapa contoh lagi yang berkembang di luar tutorial. Anda dapat melihat kode sumber untuk contoh tersebut serta setiap bab dalam tutorial di Arcade Github di https. //github. com/pythonarcade/arcade/tree/development/arcade/examples/platform_tutorial
Tutorial ini juga diperluas menjadi game berfitur lengkap yang dikembangkan oleh komunitas Arcade. Anda dapat melihat proyek itu di Github di https. //github. com/pythonarcade/community-platformer
Dalam tutorial sebelumnya kami memperkenalkan pengembangan game grafis dengan PyGame, membahas cara mengembangkan game 2D dengan sprite animasi dan interaksi pengguna. Dalam tutorial ini, kita akan melangkah lebih jauh dan membuat platformer 2D, di mana Anda dapat membuat alien berjalan dan melompati ruangan yang penuh dengan kotak. Tutorial PyGame sebelumnya bukanlah prasyarat untuk mencoba yang ini
Kami akan fokus pada animasi dan gerakan dasar untuk menciptakan basis yang kokoh dari mana Anda dapat terus membangun seluruh permainan platform, lengkap dengan musuh, power-up, dan berbagai level
Mulai
Buat repl baru dan pilih "PyGame" dari tarik-turun bahasa
Anda akan melihat "Python3 with PyGame" ditampilkan di konsol default dan panel terpisah di Replit IDE tempat Anda dapat melihat dan berinteraksi dengan game yang akan Anda buat
Sebelum kita mulai menulis kode, kita membutuhkan beberapa sprite, yang telah kita sediakan di sini. Ekstrak file ZIP ini dan tambahkan file di dalamnya ke repl Anda menggunakan fungsi def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
0. Anda dapat memilih beberapa file untuk diunggah sekaligus. Panel file repl Anda sekarang akan terlihat seperti ini
Dalam tutorial ini, kita akan membangun file def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
1 secara bertahap, menambahkan kode di berbagai bagian file seiring berjalannya waktu. Setiap cuplikan kode akan berisi beberapa kode yang ada untuk memberi Anda gambaran di mana penambahan baru harus ditempatkan di file. Baris def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
_2 akan digunakan untuk mewakili kode yang ada yang telah ditinggalkan untuk singkatnya
Menyiapkan perancah
Kami akan mulai dengan kode berikut di def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
1, yang menggambar layar hitam
import pygame
WIDTH = 400
HEIGHT = 300
BACKGROUND = (0, 0, 0)
def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
if __name__ == "__main__":
main()
_
Di bagian atas file, kami mengimpor def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
4. Setelah itu, kami mengatur lebar dan tinggi layar dalam piksel, dan warna latar belakang. Nilai terakhir ini adalah RGB tuple, dan akan membuat background kita menjadi hitam. Untuk menggunakan latar putih sebagai gantinya, kami akan menulis def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
5
Kemudian, dalam metode def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
_6, kami memulai PyGame, membuat layar dan jam, dan memulai putaran permainan, yaitu kode ini
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_
Putaran permainan adalah tempat segala sesuatu terjadi. Karena game kita berjalan dalam waktu nyata, kode kita harus terus-menerus mengumpulkan penekanan tombol dan gerakan mouse pengguna, dan terus-menerus menggambar ulang layar sebagai respons terhadap penekanan tombol dan gerakan mouse tersebut, dan peristiwa lain dalam game. Kami mencapai ini dengan while loop yang tak terbatas. PyGame menggunakan baris def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
7 terakhir dalam loop ini untuk menyesuaikan frekuensi gambar game sejalan dengan berapa lama waktu yang dibutuhkan setiap iterasi loop, agar game tetap berjalan lancar
Sekarang mari menggambar sesuatu di layar hitam ini. Game kita akan memiliki dua sprite. alien, yang akan menjadi pemain, dan sebuah kotak. Untuk menghindari duplikasi kode, mari buat kelas induk def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
8 sebelum kita membuat salah satunya. Kelas ini akan mewarisi dari kelas def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
_9, yang memberi kita metode berguna untuk deteksi tabrakan – ini akan menjadi penting nantinya
class Sprite(pygame.sprite.Sprite):
def __init__(self, image, startx, starty):
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = [startx, starty]
def update(self):
pass
def draw(self, screen):
screen.blit(self.image, self.rect)
def main():
Karena class ini akan menjadi induk untuk semua objek lain dalam game kita, kita membuatnya cukup sederhana. Ini memiliki tiga metode
- player = Player(100, 200)
boxes = pygame.sprite.Group()
0, yang akan membuat sprite dengan gambar tertentu dan persegi panjang PyGame berdasarkan gambar tersebut. Persegi panjang ini awalnya akan ditempatkan pada posisi yang ditentukan oleh player = Player(100, 200)
boxes = pygame.sprite.Group()
1 dan player = Player(100, 200)
boxes = pygame.sprite.Group()
2. Persegi panjang sprite adalah apa yang akan digunakan PyGame untuk gerakan sprite dan deteksi tabrakan - player = Player(100, 200)
boxes = pygame.sprite.Group()
3, yang akan kita gunakan di kelas anak untuk menangani peristiwa, seperti penekanan tombol, gravitasi, dan tabrakan - player = Player(100, 200)
boxes = pygame.sprite.Group()
4, yang kita gunakan untuk menggambar sprite. Kami melakukan ini dengan memasukkannya ke layar
Sekarang kita dapat membuat objek player = Player(100, 200)
boxes = pygame.sprite.Group()
_5 dan player = Player(100, 200)
boxes = pygame.sprite.Group()
6 sebagai kelas anak dari def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
8
class Sprite(pygame.sprite.Sprite):
# ...
class Player(Sprite):
def __init__(self, startx, starty):
super().__init__("p1_front.png", startx, starty)
class Box(Sprite):
def __init__(self, startx, starty):
super().__init__("boxAlt.png", startx, starty)
def main():
Kami akan menambahkan lebih banyak kode ke pemain nanti, tetapi pertama-tama mari menggambar sprite ini di layar
Menggambar sprite
Mari kembali ke fungsi def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
_6 kita dan buat sprite kita. Kami akan mulai dengan pemain
def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
Maka kita perlu meletakkan kotak di bawah kaki pemain. Karena kami akan menempatkan banyak sprite, kami akan membuat PyGame untuk memasukkannya
player = Player(100, 200)
boxes = pygame.sprite.Group()
Sprite kotak kami memiliki lebar 70 piksel, dan kami perlu menjangkau lebar layar 400 piksel. Kita bisa melakukan ini dalam player = Player(100, 200)
boxes = pygame.sprite.Group()
_9 loop menggunakan Python
player = Player(100, 200)
boxes = pygame.sprite.Group()
for bx in range(0,400,70):
boxes.add(Box(bx,300))
Sekarang kita perlu kembali ke loop game dan menambahkan beberapa kode untuk mewujudkannya. Pertama, kita akan membuat PyGame menempatkan acara baru di antrean acara, lalu kita akan memanggil fungsi player = Player(100, 200)
boxes = pygame.sprite.Group()
3 pemain. Fungsi ini akan menangani peristiwa yang dihasilkan oleh player = Player(100, 200)
boxes = pygame.sprite.Group()
for bx in range(0,400,70):
boxes.add(Box(bx,300))
2
while True:
pygame.event.pump()
player.update()
# ...
Untuk permainan yang lebih kompleks, kami ingin mengulang beberapa sprite dan memanggil metode player = Player(100, 200)
boxes = pygame.sprite.Group()
3 masing-masing, tetapi untuk saat ini hanya melakukan ini dengan pemain sudah cukup. Kotak kami tidak akan memiliki perilaku dinamis, jadi tidak perlu memanggil metode player = Player(100, 200)
boxes = pygame.sprite.Group()
3 mereka
Berbeda dengan player = Player(100, 200)
boxes = pygame.sprite.Group()
_3, kita membutuhkan semua sprite kita untuk menggambar dirinya sendiri. Setelah menggambar latar belakang, kami akan menambahkan panggilan ke metode menggambar pemain. Untuk menggambar kotak, kita dapat menghubungi PyGame di grup player = Player(100, 200)
boxes = pygame.sprite.Group()
for bx in range(0,400,70):
boxes.add(Box(bx,300))
7 kita
while True:
pygame.event.pump()
player.update()
# Draw loop
screen.fill(BACKGROUND)
player.draw(screen)
boxes.draw(screen)
pygame.display.flip()
clock.tick(60)
Putaran permainan kami sekarang disiapkan untuk memperbarui dan menggambar setiap sprite dalam permainan di setiap siklus putaran permainan. Jika Anda menjalankan permainan sekarang, Anda akan melihat pemain dan garis kotak di layar
Selanjutnya, kita akan menambahkan beberapa interaksi pengguna
Membuat Pemain Berjalan
Mari kembali ke objek player = Player(100, 200)
boxes = pygame.sprite.Group()
_5 dan membuatnya mobile. Kami akan memindahkan pemain menggunakan player = Player(100, 200)
boxes = pygame.sprite.Group()
for bx in range(0,400,70):
boxes.add(Box(bx,300))
_9, yang memindahkan persegi panjang tertentu dengan vektor tertentu. Ini akan dibungkus dengan metode while True:
pygame.event.pump()
player.update()
# ...
_0, untuk menyederhanakan kode kita. Buat metode ini sekarang
class Player(Sprite):
# ...
def move(self, x, y):
self.rect.move_ip([x,y])
Sekarang kita memiliki cara untuk memindahkan pemain, saatnya menambahkan metode player = Player(100, 200)
boxes = pygame.sprite.Group()
3 sehingga gerakan ini dapat dipicu oleh penekanan tombol. Tambahkan metode player = Player(100, 200)
boxes = pygame.sprite.Group()
_3 kosong sekarang
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_0
PyGame menyediakan beberapa cara berbeda untuk memeriksa status keyboard. Secara default, antrian kejadiannya mengumpulkan while True:
pygame.event.pump()
player.update()
# ...
3 dan while True:
pygame.event.pump()
player.update()
# ...
4 kejadian saat tombol tertentu ditekan dan dilepaskan. Menggunakan peristiwa while True:
pygame.event.pump()
player.update()
# ...
_3 untuk menggerakkan pemain tampaknya merupakan hal yang logis untuk dilakukan, tetapi karena peristiwa tersebut hanya dipicu dalam loop pembaruan yang sama saat tombol ditekan pertama kali, ini akan memaksa kita untuk mengetuk tombol panah dengan cepat untuk terus bergerak dalam
Kami membutuhkan cara untuk memindahkan pemain setiap kali tombol panah ditekan, tidak hanya setelah ditekan. Jadi alih-alih mengandalkan acara, kami akan menanyakan status saat ini dari semua tombol keyboard dengan while True:
pygame.event.pump()
player.update()
# ...
6
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_1
Metode ini mengembalikan tupel 0 dan 1 yang menunjukkan status penekanan setiap tombol pada keyboard. Dengan demikian, kami dapat mendeteksi apakah tombol panah kiri atau kanan saat ini ditekan dengan mengindeks tuple dengan konstanta keyboard PyGame, seperti itu
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_2
Jalankan permainan. Anda sekarang dapat menggerakkan pemain ke kiri dan ke kanan, meskipun sangat lambat. Mari kita percepat dan kurangi ketergantungan kode kita pada angka ajaib pada saat yang sama dengan memberi pemain variabel while True:
pygame.event.pump()
player.update()
# ...
7
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_3
Saat ini pemain meluncur dari satu sisi ke sisi lain, tetapi kami telah mengupload gambar untuk animasi siklus berjalan, jadi mari terapkan itu sekarang. Pertama, kami akan menambahkan beberapa kode pemuatan gambar ke metode player = Player(100, 200)
boxes = pygame.sprite.Group()
0 pemain kami
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_4
Dalam kode ini, pertama-tama kita menetapkan gambar alien awal kita sebagai while True:
pygame.event.pump()
player.update()
# ...
9. Ini akan memungkinkan kita menggunakannya untuk pemain saat dia berdiri diam. Kami kemudian memuat gambar berjalan kami ke dalam daftar yang disebut while True:
pygame.event.pump()
player.update()
# Draw loop
screen.fill(BACKGROUND)
player.draw(screen)
boxes.draw(screen)
pygame.display.flip()
clock.tick(60)
0, menggunakan Python untuk mendapatkan format nama file yang benar ( while True:
pygame.event.pump()
player.update()
# Draw loop
screen.fill(BACKGROUND)
player.draw(screen)
boxes.draw(screen)
pygame.display.flip()
clock.tick(60)
1 -> while True:
pygame.event.pump()
player.update()
# Draw loop
screen.fill(BACKGROUND)
player.draw(screen)
boxes.draw(screen)
pygame.display.flip()
clock.tick(60)
2). Kami kemudian membuat while True:
pygame.event.pump()
player.update()
# Draw loop
screen.fill(BACKGROUND)
player.draw(screen)
boxes.draw(screen)
pygame.display.flip()
clock.tick(60)
3, yang akan merekam bingkai mana dari siklus berjalan yang dimainkan pemain, dan while True:
pygame.event.pump()
player.update()
# Draw loop
screen.fill(BACKGROUND)
player.draw(screen)
boxes.draw(screen)
pygame.display.flip()
clock.tick(60)
4 yang akan membantu kami membalikkan gambar berjalan yang menghadap ke kanan saat pemain berjalan ke kiri
Sekarang mari kita terapkan animasi yang sebenarnya. Buat metode baru bernama while True:
pygame.event.pump()
player.update()
# Draw loop
screen.fill(BACKGROUND)
player.draw(screen)
boxes.draw(screen)
pygame.display.flip()
clock.tick(60)
5
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_5
Di sini kami menyetel gambar pemain saat ini ke bingkai siklus berjalan yang sedang kami jalani. Jika pemain menghadap ke kiri, kita gunakan while True:
pygame.event.pump()
player.update()
# Draw loop
screen.fill(BACKGROUND)
player.draw(screen)
boxes.draw(screen)
pygame.display.flip()
clock.tick(60)
6 untuk membalik sprite secara horizontal (dua argumen terakhir masing-masing untuk flip horizontal dan vertikal). Kemudian kami menganimasikan pemain dengan menambah while True:
pygame.event.pump()
player.update()
# Draw loop
screen.fill(BACKGROUND)
player.draw(screen)
boxes.draw(screen)
pygame.display.flip()
clock.tick(60)
7, kecuali animasi berada dalam bingkai kedua dari belakang, dalam hal ini kami kembali ke awal animasi
Mari tambahkan ini ke metode player = Player(100, 200)
boxes = pygame.sprite.Group()
_3 kita sekarang
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_6
Jika kita bergerak ke kiri atau kanan, kita mengatur while True:
pygame.event.pump()
player.update()
# Draw loop
screen.fill(BACKGROUND)
player.draw(screen)
boxes.draw(screen)
pygame.display.flip()
clock.tick(60)
4 dengan tepat dan memanggil class Player(Sprite):
# ...
def move(self, x, y):
self.rect.move_ip([x,y])
0. Jika tidak, kami menyetel gambar pemain ke class Player(Sprite):
# ...
def move(self, x, y):
self.rect.move_ip([x,y])
1
Jalankan game sekarang untuk melihat gerakan siklus berjalan pemain. Setelah itu, saatnya membuatnya melompat
Membuat Pemain Melompat
Agar pemain kita bisa melompat, kita perlu menerapkan empat hal
- Gerakan ke atas dipicu oleh tombol panah atas
- Gravitasi, untuk membawa pemain kembali turun setelah mencapai puncak lompatannya
- Deteksi tabrakan, sehingga pemain tidak jatuh ke tanah
- Sebuah animasi melompat
Memicu lompatan
Untuk sekadar membuat pemain naik, kita bisa menambahkan class Player(Sprite):
# ...
def move(self, x, y):
self.rect.move_ip([x,y])
2 lagi, seperti itu
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_7
Jika Anda mencoba permainan sekarang, Anda akan melihat beberapa masalah dengan pendekatan ini. Selain kekurangan gravitasi, kita hanya bisa melompat lurus ke atas, dan harus melepaskan tombol panah kiri dan kanan sebelum melakukannya. Sebagian besar gameplay di platformer bergantung pada kemampuan pemain untuk melompat ke kiri atau kanan, jadi ini tidak akan berhasil. Untuk memperbaikinya, kami akan mengubah class Player(Sprite):
# ...
def move(self, x, y):
self.rect.move_ip([x,y])
2 terakhir kami menjadi pernyataan class Player(Sprite):
# ...
def move(self, x, y):
self.rect.move_ip([x,y])
4 yang terpisah
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_8
Kita juga mungkin ingin bisa melompat dengan kecepatan yang berbeda dengan kecepatan berjalan kita, jadi mari kita definisikan variabel lain dan gunakan itu
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_9
Itu lebih baik, tapi sekarang kita benar-benar membutuhkan gravitasi
Menambahkan gravitasi
Hingga saat ini, kami hanya memiliki satu operasi yang memanipulasi kecepatan horizontal atau vertikal kami per putaran pembaruan. Dengan penambahan gravitasi, ini akan berubah, jadi kita perlu merestrukturisasi kode kita untuk menghitung pergerakan horizontal dan vertikal bersih kita sebelum memanggil while True:
pygame.event.pump()
player.update()
# ...
0. Mari ubah fungsi player = Player(100, 200)
boxes = pygame.sprite.Group()
3 seperti itu
class Sprite(pygame.sprite.Sprite):
def __init__(self, image, startx, starty):
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = [startx, starty]
def update(self):
pass
def draw(self, screen):
screen.blit(self.image, self.rect)
def main():
0
Kami telah menambahkan dua variabel, class Player(Sprite):
# ...
def move(self, x, y):
self.rect.move_ip([x,y])
_7 dan class Player(Sprite):
# ...
def move(self, x, y):
self.rect.move_ip([x,y])
8, untuk mewakili kecepatan horizontal dan kecepatan vertikal kami. Alih-alih memanggil while True:
pygame.event.pump()
player.update()
# ...
_0 ketika setiap tombol ditekan, kami bekerja dengan variabel-variabel ini di seluruh metode player = Player(100, 200)
boxes = pygame.sprite.Group()
3 dan kemudian meneruskan nilai akhirnya menjadi satu panggilan while True:
pygame.event.pump()
player.update()
# ...
0 di akhir
Tapi tunggu. Masuk akal jika kecepatan horizontal disetel ke 0 pada awal setiap loop pembaruan, karena langsung dikontrol oleh penekanan tombol pemain. Saat panah kiri ditahan, pemain bergerak ke kiri dengan kecepatan 4 piksel per putaran; . Kecepatan vertikal akan kurang dapat dikendalikan – sambil menekan panah atas akan memulai lompatan, melepaskannya tidak akan menghentikan pemain di udara. Oleh karena itu, kecepatan vertikal harus bertahan di antara loop
Kita dapat melakukannya dengan memindahkan definisi class Player(Sprite):
# ...
def move(self, x, y):
self.rect.move_ip([x,y])
8 ke dalam player = Player(100, 200)
boxes = pygame.sprite.Group()
0 dan menjadikannya sebagai variabel instan
class Sprite(pygame.sprite.Sprite):
def __init__(self, image, startx, starty):
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = [startx, starty]
def update(self):
pass
def draw(self, screen):
screen.blit(self.image, self.rect)
def main():
1
Sekarang kita bisa menerapkan gravitasi. Kami akan melakukan ini dengan menambahkan konstanta kecil ke kecepatan vertikal pemain (class Player(Sprite):
# ...
def move(self, x, y):
self.rect.move_ip([x,y])
8) hingga mencapai kecepatan terminal
class Sprite(pygame.sprite.Sprite):
def __init__(self, image, startx, starty):
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = [startx, starty]
def update(self):
pass
def draw(self, screen):
screen.blit(self.image, self.rect)
def main():
2
Mulai permainan sekarang, dan pemain akan jatuh lurus ke bawah, menembus tanah dan keluar dari layar. Gravitasi berfungsi, tapi kami butuh tempat untuk mendaratkan pemain
Menambahkan deteksi tabrakan
Deteksi tabrakan adalah elemen kunci dari sebagian besar game grafis. Di PyGame, sebagian besar pendeteksian tabrakan melibatkan pemeriksaan apakah persegi panjang berpotongan satu sama lain. Untungnya, PyGame menyediakan sejumlah built-in yang berguna untuk melakukan hal ini, jadi kita tidak perlu memikirkan terlalu banyak tentang cara kerja tabrakan internal.
Mari tambahkan beberapa deteksi tabrakan sekarang, di dekat bagian atas metode player = Player(100, 200)
boxes = pygame.sprite.Group()
3 kita. Kami akan membuat variabel yang disebut while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_06 dan mengaturnya ke hasil while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
07
class Sprite(pygame.sprite.Sprite):
def __init__(self, image, startx, starty):
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = [startx, starty]
def update(self):
pass
def draw(self, screen):
screen.blit(self.image, self.rect)
def main():
3
Metode PyGame ini membutuhkan dua argumen. satu sprite dan sekelompok sprite. Ini mengembalikan apakah sprite diberikan sebagai argumen pertama, i. e. pemain, bertabrakan dengan salah satu sprite dalam grup yang diberikan sebagai argumen kedua, i. e. kotak-kotak. Jadi kita akan tahu bahwa pemain berada di kotak saat kembali while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
08
Kita dapat meneruskan grup player = Player(100, 200)
boxes = pygame.sprite.Group()
for bx in range(0,400,70):
boxes.add(Box(bx,300))
_7 ke dalam metode player = Player(100, 200)
boxes = pygame.sprite.Group()
3 pemain dengan membuat beberapa perubahan kode
class Sprite(pygame.sprite.Sprite):
def __init__(self, image, startx, starty):
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = [startx, starty]
def update(self):
pass
def draw(self, screen):
screen.blit(self.image, self.rect)
def main():
4
Sekarang kita dapat mengetahui apakah pemain berada di tanah, kita dapat mencegah melompat di udara dengan menambahkan kondisi pada kode lompat kita
class Sprite(pygame.sprite.Sprite):
def __init__(self, image, startx, starty):
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = [startx, starty]
def update(self):
pass
def draw(self, screen):
screen.blit(self.image, self.rect)
def main():
5
Untuk menghentikan pemain agar tidak jatuh ke tanah, kami akan menambahkan kode berikut ke implementasi gravitasi kami
class Sprite(pygame.sprite.Sprite):
def __init__(self, image, startx, starty):
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = [startx, starty]
def update(self):
pass
def draw(self, screen):
screen.blit(self.image, self.rect)
def main():
6
Menambahkan animasi melompat
Terakhir, kami akan menggunakan gambar alien terakhir kami ( while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
11) untuk memberi pemain kami animasi melompat. Pertama buat while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_12 di player = Player(100, 200)
boxes = pygame.sprite.Group()
0
class Sprite(pygame.sprite.Sprite):
def __init__(self, image, startx, starty):
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = [startx, starty]
def update(self):
pass
def draw(self, screen):
screen.blit(self.image, self.rect)
def main():
7
Kemudian buat metode player = Player(100, 200)
boxes = pygame.sprite.Group()
5 berikut
class Sprite(pygame.sprite.Sprite):
def __init__(self, image, startx, starty):
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = [startx, starty]
def update(self):
pass
def draw(self, screen):
screen.blit(self.image, self.rect)
def main():
8
Animasi lompat kami hanya memiliki satu bingkai, jadi kodenya jauh lebih sederhana daripada yang kami gunakan untuk animasi berjalan kami. Untuk memicu metode ini saat pemain berada di udara, ubah implementasi gravitasi seperti itu
class Sprite(pygame.sprite.Sprite):
def __init__(self, image, startx, starty):
super().__init__()
self.image = pygame.image.load(image)
self.rect = self.image.get_rect()
self.rect.center = [startx, starty]
def update(self):
pass
def draw(self, screen):
screen.blit(self.image, self.rect)
def main():
_9
Jalankan game, dan Anda harus bisa berlari dan melompat. Berhati-hatilah agar tidak jatuh dari tepi
Menyempurnakan Game
Pada titik ini, kami memiliki permainan kami bekerja pada tingkat dasar, tetapi itu bisa menggunakan beberapa perbaikan. Pertama, lompatannya cukup tidak responsif terhadap masukan pengguna. menekan panah atas untuk waktu yang lama menghasilkan lompatan ukuran yang sama. Kedua, deteksi tabrakan kami hanya akan mencegah pemain jatuh dari lantai, tidak berjalan menembus dinding atau melompati langit-langit
Kami akan mengulangi kode kami untuk memperbaiki kedua kekurangan ini
Membuat variabel lompatan
Alangkah baiknya jika pemain dapat mengontrol ketinggian lompatan mereka dengan menahan tombol lompat untuk jangka waktu yang berbeda. Ini cukup sederhana untuk diterapkan – kita hanya perlu cara untuk mengurangi kecepatan lompatan jika pemain melepaskan tombol lompat saat pemain masih bergerak ke atas. Tambahkan kode berikut ke metode player = Player(100, 200)
boxes = pygame.sprite.Group()
0 pemain
class Sprite(pygame.sprite.Sprite):
# ...
class Player(Sprite):
def __init__(self, startx, starty):
super().__init__("p1_front.png", startx, starty)
class Box(Sprite):
def __init__(self, startx, starty):
super().__init__("boxAlt.png", startx, starty)
def main():
0
Di sini kami telah menambahkan variabel instan while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_16 yang akan melacak status keyboard di loop pembaruan sebelumnya, dan variabel while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
17, yang akan menjadi lompatan terkecil yang akan kami izinkan untuk dilakukan pemain, hanya dengan mengetuk tombol lompat
Sekarang mari tambahkan variabel melompat ke metode player = Player(100, 200)
boxes = pygame.sprite.Group()
3, antara kode yang menangani tombol panah atas dan kode yang menangani gravitasi
class Sprite(pygame.sprite.Sprite):
# ...
class Player(Sprite):
def __init__(self, startx, starty):
super().__init__("p1_front.png", startx, starty)
class Box(Sprite):
def __init__(self, startx, starty):
super().__init__("boxAlt.png", startx, starty)
def main():
1
Pernyataan class Player(Sprite):
# ...
def move(self, x, y):
self.rect.move_ip([x,y])
_4 yang baru saja kita tambahkan akan dievaluasi menjadi while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
08 jika tombol panah atas ditekan pada loop sebelumnya tetapi tidak lagi ditekan, i. e. itu telah dirilis. Saat itu terjadi, kami menghentikan lompatan pemain dengan mengurangi kecepatannya menjadi while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
17. Kami kemudian mengatur while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_22 ke status keyboard saat ini sebagai persiapan untuk loop berikutnya
Coba permainan sekarang, dan Anda akan melihat ketinggian lompatan yang berbeda saat menekan tombol panah ke atas dengan ringan dibandingkan saat Anda menahannya. Bermain-main dengan nilai while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_17 dan lihat apa bedanya
Menyempurnakan deteksi tabrakan
Seperti disebutkan di atas, satu-satunya deteksi tabrakan yang kami terapkan berlaku untuk tanah di bawah kaki pemain, sehingga dia dapat berjalan menembus dinding dan melompat menembus langit-langit. Lihat ini sendiri dengan menambahkan beberapa kotak di atas dan di samping pemain dalam metode def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
player = Player(100, 200)
6
class Sprite(pygame.sprite.Sprite):
# ...
class Player(Sprite):
def __init__(self, startx, starty):
super().__init__("p1_front.png", startx, starty)
class Box(Sprite):
def __init__(self, startx, starty):
super().__init__("boxAlt.png", startx, starty)
def main():
2
Masalah lain yang mungkin telah Anda perhatikan adalah bahwa pemain tenggelam ke dalam tanah setelah beberapa lompatan – ini diakibatkan oleh ketidaktepatan pendeteksian tabrakan kami
Kami akan memperbaiki masalah ini dengan membuat perubahan halus pada cara kami menangani tabrakan dengan kotak. Daripada memutuskan bahwa kita berada di tanah saat sprite pemain bertabrakan dengan kotak, kita akan memeriksa apakah pemain berada 1 piksel di atas tabrakan dengan kotak. Kami kemudian akan menerapkan prinsip yang sama untuk kiri, kanan dan atas, menghentikan pemain tepat sebelum tabrakan
Pertama, mari beri pemain metode while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
25 untuk melakukan pemeriksaan ini
class Sprite(pygame.sprite.Sprite):
# ...
class Player(Sprite):
def __init__(self, startx, starty):
super().__init__("p1_front.png", startx, starty)
class Box(Sprite):
def __init__(self, startx, starty):
super().__init__("boxAlt.png", startx, starty)
def main():
3
Di sini, kami memindahkan pemain dengan jumlah tertentu, memeriksa tabrakan, lalu memindahkan pemain kembali. Gerakan bolak-balik ini terjadi sebelum pemain ditarik ke layar, sehingga pengguna tidak akan melihat apapun
Mari ubah centang while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
06 kita untuk menggunakan metode ini
class Sprite(pygame.sprite.Sprite):
# ...
class Player(Sprite):
def __init__(self, startx, starty):
super().__init__("p1_front.png", startx, starty)
class Box(Sprite):
def __init__(self, startx, starty):
super().__init__("boxAlt.png", startx, starty)
def main():
4
Jalankan game sekarang, dan Anda mungkin dapat melihat sedikit perbedaan dalam cara pemain berdiri di tanah dari sebelumnya
Ini belum menyelesaikan masalah tabrakan horizontal dan ke atas kita. Untuk itu, kita harus menerapkan metode while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
25 baru kita langsung ke metode while True:
pygame.event.pump()
player.update()
# ...
0 pemain. Hal pertama yang perlu kita lakukan adalah menyiapkan parameter while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
29 dan while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
30 untuk pemrosesan tambahan
class Sprite(pygame.sprite.Sprite):
# ...
class Player(Sprite):
def __init__(self, startx, starty):
super().__init__("p1_front.png", startx, starty)
class Box(Sprite):
def __init__(self, startx, starty):
super().__init__("boxAlt.png", startx, starty)
def main():
5
Kemudian kita akan memeriksa tabrakan, jadi kita harus mulai meneruskan player = Player(100, 200)
boxes = pygame.sprite.Group()
for bx in range(0,400,70):
boxes.add(Box(bx,300))
7 ke while True:
pygame.event.pump()
player.update()
# ...
0. Kami akan melakukan ini untuk while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_29 dan while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
30 secara terpisah, dimulai dengan while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
30. Kami akan memeriksa tabrakan setelah memindahkan while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
36 piksel secara vertikal, mengurangi while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
36 hingga kami tidak lagi bertabrakan dengan kotak
class Sprite(pygame.sprite.Sprite):
# ...
class Player(Sprite):
def __init__(self, startx, starty):
super().__init__("p1_front.png", startx, starty)
class Box(Sprite):
def __init__(self, startx, starty):
super().__init__("boxAlt.png", startx, starty)
def main():
6
Tapi tunggu. Kode ini hanya akan berfungsi sebagaimana mestinya jika kita bergerak ke bawah dan while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
36 positif. Jika while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_36 negatif, ini hanya akan membawa kita lebih jauh ke dalam tabrakan, bukan menjauhinya. Untuk memperbaikinya, kita harus mengimpor while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
40 di bagian atas file kita, sehingga kita dapat menggunakan while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
41
class Sprite(pygame.sprite.Sprite):
# ...
class Player(Sprite):
def __init__(self, startx, starty):
super().__init__("p1_front.png", startx, starty)
class Box(Sprite):
def __init__(self, startx, starty):
super().__init__("boxAlt.png", startx, starty)
def main():
7
while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_41 mengambil bilangan bulat dan mengembalikan 1 jika positif, -1 jika negatif, dan 0 jika 0. Inilah fungsi yang kami butuhkan
class Sprite(pygame.sprite.Sprite):
# ...
class Player(Sprite):
def __init__(self, startx, starty):
super().__init__("p1_front.png", startx, starty)
class Box(Sprite):
def __init__(self, startx, starty):
super().__init__("boxAlt.png", startx, starty)
def main():
8
Sekarang lakukan hal yang sama untuk while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
_43. Karena kita sudah mengetahui while True:
screen.fill(BACKGROUND)
pygame.display.flip()
clock.tick(60)
36 yang sesuai untuk pergerakan kita, kita akan memasukkannya ke dalam pemeriksaan tabrakan
class Sprite(pygame.sprite.Sprite):
# ...
class Player(Sprite):
def __init__(self, startx, starty):
super().__init__("p1_front.png", startx, starty)
class Box(Sprite):
def __init__(self, startx, starty):
super().__init__("boxAlt.png", startx, starty)
def main():
_9
Jalankan permainan. Pemain sekarang harus berhenti ketika dia menabrak dinding atau melompat ke langit-langit
Kemana Selanjutnya?
Jika Anda ingin terus mengerjakan game ini, Anda dapat menemukan sejumlah besar aset seni yang cocok di sini. Coba terapkan beberapa fitur ini