המפתח והדלת
חלק מהיחידה פרויקטים במסלול ה-Pygame של Coddy. שיעור 23 מתוך 31.
הדלת בקיר הימני נעולה. האביר אוסף את המפתח כשהוא עובר מעליו, ובעזרת המפתח הדלת נפתחת כשהוא נוגע בה.
דלת נעולה היא עוד דבר שחוסם את האביר. מתודה של Room מחזירה את רשימת ה־Rect שחוסמים אותו:
def blocks(self):
if self.door_open:
return self.walls
return self.walls + [self.door]יש כאן עניין קטן בנגיעה בדלת: move דוחף את האביר החוצה ממנה בכל פריים, כך שה־Rect שלו אף פעם לא חופף לדלת. knight.rect.inflate(8, 8) הוא עותק של ה־Rect שלו, שגדל ב־4 פיקסלים מכל צד, והעותק הזה כן חופף לדלת שהוא צמוד אליה.
if room.has_key and knight.rect.inflate(8, 8).colliderect(room.door):
room.door_open = Trueמעבר לדלת הפתוחה נמצאת שפת החלון, לכן השאר את האביר בתוך החלון בעזרת clamp_ip. בשיעור מאוחר יותר, הפתח יוביל לחדר הבא. הצג את המפתח למעלה כשהוא נושא אותו.
אתגר
בינוני- בתוך
Room, הגדירו אתself.has_key = Falseואתself.door_open = False. תוKמגדיר אתself.key = cell_rect(col, row); תוDמגדיר אתself.doorכ־Rect בגודל 48 על 48 של האריח שלו. - הוסיפו את המתודה
blocksשלמעלה והזיזו את האביר באמצעותknight.move(dx, dy, room.blocks()). - אחרי התנועה:
knight.rect.clamp_ip(screen.get_rect()); אם אין לו מפתח והוא נוגע ב־room.key, הגדירו אתroom.has_key = True; ואז פתחו את הדלת כמתואר למעלה. - ציירו את הדלת באמצעות
screen.blit(door_img, room.door)כל עוד היא סגורה, את המפתח באמצעותdraw(key_img, room.key)עד שהוא נאסף, ואתkey_imgבמיקום(136, 6)כאשרroom.has_keyהוא true.
נסו בעצמכם
import pygame
TILE = 48
MAP = [
"##############",
"#............#",
"#.P......K...#",
"#............#",
"#....##......D",
"#....##......#",
"##.#######.###",
"#............#",
"#...S....H...#",
"##############",
]
pygame.init()
screen = pygame.display.set_mode((672, 480))
pygame.display.set_caption("Rune Keep")
clock = pygame.time.Clock()
font = pygame.font.Font("assets/fonts/pixel.ttf", 32)
def load(name):
return pygame.image.load("assets/images/" + name).convert_alpha()
floor_img = load("floor.png")
wall_img = load("wall.png")
knight_img = load("knight.png")
door_img = load("dungeon_door.png")
key_img = load("key.png")
slime_img = load("slime.png")
spider_img = load("spider.png")
heart_img = load("heart.png")
empty_img = load("heart_empty.png")
sword_img = load("sword.png")
potion_img = load("potion_red.png")
def draw(image, rect):
screen.blit(image, image.get_rect(center=rect.center))
def cell_rect(col, row):
rect = pygame.Rect(0, 0, 32, 32)
rect.center = (col * TILE + 24, row * TILE + 24)
return rect
class Room:
def __init__(self, lines):
self.walls = []
self.start = (72, 72)
for row, line in enumerate(lines):
for col, char in enumerate(line):
if char == "#":
self.walls.append(pygame.Rect(col * TILE, row * TILE, TILE, TILE))
elif char == "P":
self.start = cell_rect(col, row).center
class Knight(pygame.sprite.Sprite):
def __init__(self, center):
super().__init__()
self.image = knight_img
self.rect = pygame.Rect(0, 0, 32, 32)
self.rect.center = center
def move(self, dx, dy, blocks):
self.rect.x += dx
for block in blocks:
if self.rect.colliderect(block):
if dx > 0:
self.rect.right = block.left
elif dx < 0:
self.rect.left = block.right
self.rect.y += dy
for block in blocks:
if self.rect.colliderect(block):
if dy > 0:
self.rect.bottom = block.top
elif dy < 0:
self.rect.top = block.bottom
room = Room(MAP)
knight = Knight(room.start)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
dx = 0
dy = 0
if keys[pygame.K_LEFT]:
dx = -3
if keys[pygame.K_RIGHT]:
dx = 3
if keys[pygame.K_UP]:
dy = -3
if keys[pygame.K_DOWN]:
dy = 3
knight.move(dx, dy, room.walls)
for row in range(10):
for col in range(14):
screen.blit(floor_img, (col * TILE, row * TILE))
for wall in room.walls:
screen.blit(wall_img, wall)
draw(knight.image, knight.rect)
pygame.display.flip()
clock.tick(60)
pygame.quit()
כל השיעורים ביחידה פרויקטים
תרגלו בעצמכם: Pygame אונליין