Найти - Пользователи
Полная версия: Как получить значение свойства объекта другого класса?
Начало » Python для новичков » Как получить значение свойства объекта другого класса?
1
psyh
Сделал по Доусону пример игры “Паника в пиццерии”.
Пытаюсь теперь немного усложнить игру, изменив скорость падения пиццы при достижении score определенного значения. Получается что мне нужно из объекта класса Pizza получить доступ к аттрибуту объекта класса Pan. Но никак не получается, выдает ошибку
NameError: name 'the_pan' is not defined
Пробовал сделать с помощью @property и @setter, чтобы не забирать из класса Pizza атрибут класса Pan, а передавать из класса Pan значение атрибута в класс Pizza. Но ошибка одна и та же.


#!/usr/bin/env python3.4
#Игрок должен падающую пиццу пока она не достигла земли
from livewires import games, color
import random
games.init(screen_width = 640, screen_height = 480, fps = 50)
class Pan(games.Sprite):
	"""Сковорода в которую игрок может ловить падающую пиццу"""
	image = games.load_image("img/pan.bmp")
	def __init__(self):
		"""Инициализирует объект pan и создает объект Text для отображения счета"""
		super(Pan, self).__init__(image = Pan.image,
			x = games.mouse.x,
			bottom = games.screen.height)
		self.score = games.Text(value = 0, 
			size = 25, 
			color = color.black,
			top = 5,
			right = games.screen.width -10)
		games.screen.add(self.score)
	def update(self):
		"""Передвигает объект по горизонтали в точку с абсциссой, как у указателя мыши"""
		self.x = games.mouse.x
		if self.left < 0:
			self.left = 0
		if self.right > games.screen.width:
			self.right = games.screen.width
		self.check_catch()
	def check_catch(self):
		"""Проверяет поймал ли игрок падающую пиццу"""
		for pizza in self.overlapping_sprites:
			self.score.value += 10
			self.score.right = games.screen.width - 10
			pizza.handle_caught()
class Pizza(games.Sprite):
	"""Круги пиццы падающие на землю"""
	image = games.load_image("img/pizza.bmp")
	speed = 1
	def __init__(self, x, y = 90):
		"""Инициализирует объект Pizza"""
		super(Pizza, self).__init__(image = Pizza.image,
			x = x, y = y,
			dy = Pizza.speed)
	def update(self):
		"""Проверяет не коснулась ли нижняя кромка пиццы нижнего кря экрана"""
		if self.bottom > games.screen.height:
			self.end_game()
			self.destroy()
	def handle_caught(self):
		"""Разрушает объект пойманный игроком"""
		self.destroy()
	def end_game(self):
		"""Завершает игру"""
		end_message = games.Message(value = "Game Over",
			size = 90,
			color = color.red,
			x = games.screen.width/2,
			y = games.screen.height/2,
			lifetime = 	5 * games.screen.fps,
			after_death = games.screen.quit())
		games.screen.add(end_message)
class Chef(games.Sprite):
	"""Кулинар который двигаясь влево-вправо разбрасывает пиццу"""
	image = games.load_image("img/chef.bmp")
	def __init__(self, y = 55, speed = 2, odds_change = 200):
		"""Инициализирует объект Chef"""
		super(Chef, self).__init__(image = Chef.image,
			x = games.screen.width/2,
			y = y,
			dx = speed)
		self.odds_change = odds_change
		self.time_til_drop = 0
	def update(self):
		"""Определяет надо ли сменить направление"""
		if self.left < 0 or self.right > games.screen.width:
			self.dx = -self.dx
		elif random.randrange(self.odds_change) == 0:
			self.dx = -self.dx
		self.check_drop()
	def check_drop(self):
		"""Уменьшает интервал ожидания на единицу или сбрасывает очередную пиццу и уменьшает интервал"""
		if self.time_til_drop > 0:
			self.time_til_drop -= 1
		else:
			new_pizza = Pizza(x = self.x)
			games.screen.add(new_pizza)
			#Вне зависимости от скорости падения пиццы, зазор между падающими кругами принимается равным 30% каждого из них по высоте
			self.time_til_drop = int(new_pizza.height * 1.3 / Pizza.speed) + 1
def main():
	"""Собственно игровой процесс"""
	wall_image = games.load_image("img/wall.jpg", transparent = False)
	games.screen.background = wall_image
	the_pan = Pan()
	games.screen.add(the_pan)
	the_chef = Chef()
	games.screen.add(the_chef)
	games.mouse.is_visible = False
	games.screen.event_grab = True
	games.screen.mainloop()
main()

Выходит что объект не существует в тот момент когда я пытаюсь получить значение. Но почему, если он создается в первую очередь?
JOHN_16
psyh
всегда нужно выкладывать ПОЛНЫЙ traceback ошибки
psyh
Извиняюсь, выложил тут работающую версию.
Проблема была в том что the_pan это локальная переменная функции main()
Если выношу содержимое функции main() наружу, то могу доступаться к атрибутам объектов других классов.
Вот доработанная версия:
#!/usr/bin/env python3.4
#Игрок должен падающую пиццу пока она не достигла земли
from livewires import games, color
import random
games.init(screen_width = 640, screen_height = 480, fps = 50)
class Pan(games.Sprite):
	"""Сковорода в которую игрок может ловить падающую пиццу"""
	image = games.load_image("img/pan.bmp")
	def __init__(self):
		"""Инициализирует объект pan и создает объект Text для отображения счета"""
		super(Pan, self).__init__(image = Pan.image,
			x = games.mouse.x,
			bottom = games.screen.height)
		self.score = games.Text(value = 0, 
			size = 25, 
			color = color.black,
			top = 5,
			right = games.screen.width -10)
		games.screen.add(self.score)
	def update(self):
		"""Передвигает объект по горизонтали в точку с абсциссой, как у указателя мыши"""
		self.x = games.mouse.x
		if self.left < 0:
			self.left = 0
		if self.right > games.screen.width:
			self.right = games.screen.width
		self.check_catch()
	def check_catch(self):
		"""Проверяет поймал ли игрок падающую пиццу"""
		for pizza in self.overlapping_sprites:
			self.score.value += 10
			self.score.right = games.screen.width - 10
			pizza.handle_caught()
class Pizza(games.Sprite):
	"""Круги пиццы падающие на землю"""
	image = games.load_image("img/pizza.bmp")
	speed = 1
	def __init__(self, x, y = 90):
		"""Инициализирует объект Pizza"""
		super(Pizza, self).__init__(image = Pizza.image,
			x = x, y = y,
			dy = Pizza.speed)
	def update(self):
		"""Проверяет не коснулась ли нижняя кромка пиццы нижнего кря экрана"""
		if self.bottom > games.screen.height:
			self.end_game()
			self.destroy()
		self.update_level()
	def update_level(self):
		"""Увеличивает сложность игры при наборе определенного количества очков"""
		if the_pan.score.value > 100:
			self.dy = 2
		if the_pan.score.value >200:
			self.dy = 3
	def handle_caught(self):
		"""Разрушает объект пойманный игроком"""
		self.destroy()
	def end_game(self):
		"""Завершает игру"""
		end_message = games.Message(value = "Game Over",
			size = 90,
			color = color.red,
			x = games.screen.width/2,
			y = games.screen.height/2,
			lifetime = 	5 * games.screen.fps,
			after_death = games.screen.quit())
		games.screen.add(end_message)
class Chef(games.Sprite):
	"""Кулинар который двигаясь влево-вправо разбрасывает пиццу"""
	image = games.load_image("img/chef.bmp")
	def __init__(self, y = 55, speed = 2, odds_change = 200):
		"""Инициализирует объект Chef"""
		super(Chef, self).__init__(image = Chef.image,
			x = games.screen.width/2,
			y = y,
			dx = speed)
		self.odds_change = odds_change
		self.time_til_drop = 0
	def update(self):
		"""Определяет надо ли сменить направление"""
		if self.left < 0 or self.right > games.screen.width:
			self.dx = -self.dx
		elif random.randrange(self.odds_change) == 0:
			self.dx = -self.dx
		self.update_level()
		self.check_drop()
	def update_level(self):
		"""Увеличивает сложность игры при наборе определенного количества очков"""
		if the_pan.score.value == 300:
			if self.dx > 0:
				self.dx = 4
			else:
				self.dx = -4
		if the_pan.score.value == 400:
			if self.dx > 0:
				self.dx = 6
			else:
				self.dx = -6
		if the_pan.score.value == 400:
			if self.dx > 0:
				self.dx = 8
			else:
				self.dx = -8
	def check_drop(self):
		"""Уменьшает интервал ожидания на единицу или сбрасывает очередную пиццу и уменьшает интервал"""
		if self.time_til_drop > 0:
			self.time_til_drop -= 1
		else:
			new_pizza = Pizza(x = self.x)
			games.screen.add(new_pizza)
			#Вне зависимости от скорости падения пиццы, зазор между падающими кругами принимается равным 30% каждого из них по высоте
			self.time_til_drop = int(new_pizza.height * 1.3 / Pizza.speed) + 1
"""Собственно игровой процесс"""
wall_image = games.load_image("img/wall.jpg", transparent = False)
games.screen.background = wall_image
the_chef = Chef()
games.screen.add(the_chef)
the_pan = Pan()
games.screen.add(the_pan)
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()

Здесь я вынес содержимое main() в основной код. И добавил методы update_level в классы Pizza и Chef.


А как все же засунуть этот код в функцию, или класс, чтобы иметь доступ к объекту the_pan?
Из метода update_level мне нужно получать доступ к the_pan.score.value, если я помещу этот код в функцию, то the_pan окажется вне области видимости.
"""Собственно игровой процесс"""
wall_image = games.load_image("img/wall.jpg", transparent = False)
games.screen.background = wall_image
the_chef = Chef()
games.screen.add(the_chef)
the_pan = Pan()
games.screen.add(the_pan)
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()
psyh
Объфявил the_pan глобальной переменной. Так работает. Не знаю насколько это правильно, вроде как считается неправильным использовать глобальные переменные.
Radeko
psyh
Объфявил the_pan глобальной переменной. Так работает. Не знаю насколько это правильно, вроде как считается неправильным использовать глобальные переменные.
Дружище, подскажи пожалуйста, может ты делал, я только начал изучать всё это дело, дошёл до этой главы и хочу сделать чтобы при достижении определенного количества очков (как у тебя) увеличивалась скорость падения пиццы. Всю голову переломал, не могу сделать, может есть какие-нибудь мысли?
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB