问题描述
我在与方法中的类变量进行交互时遇到问题.我想更改对象在pygame中的位置.这必须在方法中完成,因为我使用threading
,它需要将其目标作为方法.如何在enemy_list
中定位特定的enemy
?
I am having an issue with interacting with a classes variables from within a method. I want to change the position of an object in pygame. This has to be done in a method as i use threading
which needs its targets to be methods.How can i target a specific enemy
in enemy_list
?
我尝试将整个Enemy
类放入EnemyMove
方法中,但仍会输出:
I have tried putting the whole Enemy
class into the EnemyMove
Method and it still outputs:
AttributeError: type object 'Enemy' has no attribute 'X'
代码在这里:
import pygame
import threading
from random import randint
from time import sleep
pygame.init()
window = pygame.display.set_mode((900, 900))
bg = pygame.image.load("Background.png").convert()
class Enemy:
def __init__(self):
self.W = 50
self.H = 50
self.X = 420
self.Y = 850
def Gameplay():
global enemy_list
speed=2
while True:
window.blit(bg, [0, 0])
for enemy in enemy_list:
pygame.draw.rect(window, (255, 50, 49), (enemy.X, enemy.Y, enemy.W, enemy.H))
pygame.display.update()
def EnemySpawn():
global enemy_list
while True: # make enemies forever
print("Spawned an enemy")
enemy_list.append(Enemy()) # make an instance of our class
sleep(randint(1, 5))
def EnemyMove():
print(Enemy.X) #ISSUE OCURS HERE
enemy_list = [] # to maintain records of all enemies made
enemyMovement_thread = threading.Thread(target=EnemyMove)
enemyMovement_thread.start()
game_thread = threading.Thread(target=Gameplay)
game_thread.start()
enemy_spawner_thread = threading.Thread(target=EnemySpawn)
enemy_spawner_thread.start()
我做错了什么?为什么它不能在Gameplay
中工作,而不能在EnemyMove
中工作?
What am I doing wrong? Why does it work in Gameplay
but not in EnemyMove
?
推荐答案
您不能简单地调用Enemy.X
,因为Enemy
是一个类定义.在另一行中,您有for enemy in enemy_list
,它调用Enemy
的所有 instances (实例是不同的,这里的它们是enemy
,带有小写字母).要跟随玩家,您首先需要代码中的玩家!我还建议您不要对游戏的每个功能都使用新的线程.您可以投入逻辑,将敌人移动到已经具有自己线程的普通游戏循环中.
You can't simply call Enemy.X
because Enemy
is a class definition. In the other line you have for enemy in enemy_list
which calls upon all the instances of Enemy
(instances are different and here they are enemy
with a lowercase). To follow a player you would first need a player in your code! I would also recommend you don't use a new thread for each functionality of your game. You can throw in your logic to move enemies into your normal game loop which already has its own thread.
import pygame
import threading
from random import randint
from time import sleep
pygame.init()
window = pygame.display.set_mode((900, 900))
bg = pygame.image.load("Background.png").convert()
class Enemy:
def __init__(self):
self.W = 50
self.H = 50
self.X = 420
self.Y = 850
self.speed = 1
class Player: # make a new class so players can have better stats
def __init__(self):
self.W = 50
self.H = 50
self.X = 300
self.Y = 300
self.speed = 10
def Gameplay():
global enemy_list
global player
while True:
window.blit(bg, [0, 0])
pygame.draw.rect(window, (255, 255, 255), (player.X, player.Y, player.W, player.H))
for enemy in enemy_list:
if enemy.X > player.X:
enemy.X = enemy.X - enemy.speed
else:
enemy.X = enemy.X + enemy.speed
if enemy.Y > player.Y:
enemy.Y = enemy.Y - enemy.speed
else:
enemy.Y = enemy.Y + enemy.speed
pygame.draw.rect(window, (255, 50, 49), (enemy.X, enemy.Y, enemy.W, enemy.H))
pygame.display.update()
def EnemySpawn():
global enemy_list
while True: # make enemies forever
print("Spawned an enemy")
enemy_list.append(Enemy()) # make an instance of our class
sleep(randint(1, 5))
if __name__ == "__main__":
player = Player() # notice the difference in capitalization!
enemy_list = [] # to maintain records of all enemies made
game_thread = threading.Thread(target=Gameplay)
game_thread.start()
enemy_spawner_thread = threading.Thread(target=EnemySpawn)
enemy_spawner_thread.start()
正如@furas指出的那样,尽管仅使用具有子功能来检查所有这些内容的mainloop
可能会更好!我怀疑您接下来要做的是实现一个键盘侦听器以允许您的player
移动.
As @furas notes though you may be better off with just a mainloop
that has sub-functions to check all these things! I suspect the next thing you would want to do is implement a keyboard listener to allow your player
to move.
还请注意,这时我们有两个看上去非常相似的类.我们可能将从这两个类都继承的基类(例如Human
)中受益.这样,我们可以用单行代码将特征添加到两个类中.如果需要,子类仍然可以覆盖提供的值:
Also note that at this point we have two classes that look very similar. We will probably benefit from having a base class (let's say Human
) that both these classes inherit from. In this way we can add a trait to both classes with a single line of code. The child classes can still overwrite the values supplied though if needed:
import pygame
import threading
from random import randint
from time import sleep
pygame.init()
window = pygame.display.set_mode((900, 900))
bg = pygame.image.load("Video & Image Processing/Image Processing/InputImage.jpg").convert()
class Human:
def __init__(self):
self.W = 50
self.H = 50
self.X = 420
self.Y = 850
self.speed = 1
class Enemy(Human): # inherit Human
def __init__(self):
Human.__init__(self) # get all traits a Human has
class Player(Human): # inherit Human
def __init__(self):
Human.__init__(self) # get all traits a Human has
self.X = 300 # overwrite specific traits
self.Y = 300
def Gameplay():
global enemy_list
global player
while True:
window.blit(bg, [0, 0])
pygame.draw.rect(window, (255, 255, 255), (player.X, player.Y, player.W, player.H))
for enemy in enemy_list:
if enemy.X > player.X:
enemy.X = enemy.X - enemy.speed
else:
enemy.X = enemy.X + enemy.speed
if enemy.Y > player.Y:
enemy.Y = enemy.Y - enemy.speed
else:
enemy.Y = enemy.Y + enemy.speed
pygame.draw.rect(window, (255, 50, 49), (enemy.X, enemy.Y, enemy.W, enemy.H))
pygame.display.update()
def EnemySpawn():
global enemy_list
while True: # make enemies forever
print("Spawned an enemy")
enemy_list.append(Enemy()) # make an instance of our class
sleep(randint(1, 5))
if __name__ == "__main__":
player = Player() # notice the difference in capitalization!
enemy_list = [] # to maintain records of all enemies made
game_thread = threading.Thread(target=Gameplay)
game_thread.start()
enemy_spawner_thread = threading.Thread(target=EnemySpawn)
enemy_spawner_thread.start()
这篇关于Python-如何以不同的方法与类进行交互的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!