gpt4 book ai didi

python - 在 pygame 的类/子类中设置和显示 Sprite 时遇到问题

转载 作者:行者123 更新时间:2023-12-04 15:11:05 24 4
gpt4 key购买 nike

您好,我对创建游戏/编码相对较新,因此对于我将要带来的大量问题以及我的代码的糟糕组织,我很抱歉,我正在尝试让我的类(class)拥有一个功能来呈现自己游戏而不是使用外部资源

`class Animal(pygame.sprite.Sprite):
def __init__(Self,):
super().__init__()
Self.Image=pygame.image.load('Blank.png').convert_alpha()
Self.rect=Self.image.get_rect()
Self.x=x
Self.y=y
Self.Screen= screen
#Self.Width=Width
#Self.Height=Height
#Self.Energy=0



def BoundryX(entityX):
if entityX<=0:
entityX=0
elif entityX>=600:
entityX=600

def BoundryY(entityY):
if entityY<=0:
entityY=0
elif entityY>=800:
entityY=800

class Predator(Animal):
def __init__(Self):
#super().__init__()
Self.Img=pygame.image.load('Icon.png')
Self.PredatorX=0
Self.PredatorY=0
Self.Screen= screen


def Render(Self,Img,X,Y):
Self.screen.blit(Img,(X,Y))
`
我遇到了问题,因为它说该类没有属性“屏幕”,我不知道这意味着什么,顺便说一下,创建函数以在之后创建更多集合类的最佳方法是什么他们已经吃够了他们的食物链以及删除它们以及组织所有不同 Sprite 的功能(我知道这不是我的主要问题的一部分,所以如果没有得到答案也没关系)
这是完整的代码:(对于我糟糕的格式造成的任何痛苦,我深表歉意
 #imports
import math
import random
import pygame,sys
import random
import pdb
from pygame.locals import *


timmer=1




class Animal(pygame.sprite.Sprite):
def __init__(Self,):
super().__init__()
Self.Image=pygame.image.load('Blank.png').convert_alpha()
Self.rect=Self.image.get_rect()
Self.x=x
Self.y=y
Self.Screen= screen
#Self.Width=Width
#Self.Height=Height
#Self.Energy=0



def BoundryX(entityX):
if entityX<=0:
entityX=0
elif entityX>=600:
entityX=600

def BoundryY(entityY):
if entityY<=0:
entityY=0
elif entityY>=800:
entityY=800






class Predator(Animal):
def __init__(Self):
#super().__init__()
Self.Img=pygame.image.load('Icon.png')
Self.PredatorX=0
Self.PredatorY=0
Self.Screen= screen


def Render(Self,Img,X,Y):
Self.screen.blit(Img,(X,Y))






class prey(pygame.sprite.Sprite):
def __init__():

Self.preyImg=pygame.image.load('Prey.png')
Self.preyX=300
Self.preyY=700
Self.PreyX_change=0

def Render(Self):
Self.screen.blit(preyImg,(preyX,preyY))

def delete(Self):
i.delete()




CarrotImg=pygame.image.load('carrot.png')
CarrotX=100
CarrotY=300
foodamount=7


def food():
#CarrotX=random.randint(10,950)
#CarrotY=random.randint(10,750)
screen.blit(CarrotImg,(CarrotX,CarrotY))



#setup pygame
pygame.init()

#caption and Icons
pygame.display.set_caption("Game Of Life")

#predator icon

predatorImg=pygame.image.load('Icon.png')
predatorX=900
predatorY=100
predatorX_change=0


#Prey Icon
preyImg=pygame.image.load('Prey.png')
preyX=300
preyY=700
PreyX_change=0



#def delete():
#prey.delete()

preyImg=pygame.image.load('Prey.png')
preyX=300
preyY=700
PreyX_change=0

#def Prey():
#screen.blit(preyImg,(preyX,preyY))
class setup():
def __init__():
x=1

def Predator1(Self):
screen.blit(predatorImg,(predatorX,predatorY))

#Finding closest prey
def FindClosestItem(AgressorX,DefenderX,AgressorY,DefenderY):
dist = math.sqrt((AgressorX-DefenderX)**2 + (AgressorY-DefenderY)**2)#finds distance in pixels


#create pop out for game
screen=pygame.display.set_mode((1000,800))





def Tracking(AgressorX,DefenderX,AgressorY,DefenderY):
global XMovement#make variables global so it actually works
global YMovement

if AgressorX > DefenderX:#finds whether its position then moves left/righ,up/down depending on its location
XMovement=-0.25

elif AgressorX< DefenderX:
XMovement=0.25

else:
XMovement=0


if AgressorY > DefenderY:
YMovement=-0.25

elif AgressorY < DefenderY:
YMovement=0.25

else:
YMovement=0


def EatPrey(predatorX,PreyX,predatorY,preyY):
dist = math.sqrt((predatorX-preyX)**2 + (predatorY-preyY)**2)
if dist < 20:
return True
else:
return False


#setup test

predator=Predator()


#Sprite groups
all_sprites_Wolves=pygame.sprite.Group()


all_sprites_Rabbits=pygame.sprite.Group()


all_sprites_Carrots=pygame.sprite.Group()



#game loop
running=True
while running:

#Back ground colour
screen.fill((0,128,0))

for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False






predator.Render(pygame.image.load('Icon.png'),600,700)
#Prey.Render()

ClosestPrey=FindClosestItem(predatorX,preyX,predatorY,preyY)


food()

Track(predatorX,preyX,predatorY,preyY)
predatorX+=XMovement
predatorY+=YMovement
#predatorX=BoundryX(predatorX)
#predatorY=BoundryY(predatorY)


Track(preyX,CarrotX,preyY,CarrotY)
preyX+=XMovement
preyY+=YMovement
#preyX=BoundryX(preyX)
#preyY=BoundryY(preyY)


#Eat=EatPrey(preyX,preyY,predatorX,predatorY)

#if Eat==True:
#delete()
#T=1

#Boundry(prey)
if preyX<=0:
preyX=0
elif preyX>=950:
preyX=950
if preyY<=0:
preyY=0
elif preyY>=750:
preyY=750
#preyY-=1

#Boundry(predator)
if predatorX<=0:
predatorX=0
elif predatorX>=950:
predatorX=950
elif predatorY<=0:
predatorY=0
elif predatorY>=750:
predatorY=750
pygame.display.update()

timmer=timmer+1



最佳答案

你的代码很乱,但别担心,让我们一步一步地创建一个简单的 pygame 游戏。尝试了解每个步骤的作用。
首先,让我们从游戏的基本骨架开始,如下所示:

import pygame

def main():
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
screen.fill('grey')
pygame.display.flip()
clock.tick(60)

if __name__ == '__main__':
main()
在这里,我们有一个简单的 main函数和一个简单的游戏循环,它只听 QUIT事件,将所有内容设为灰色并将帧率限制为 60。您不必拥有 main函数和 __name__检查但这样做是一种很好的做法,因为它允许您在不运行游戏的情况下导入文件。此外,我有助于不污染全局命名空间。
好的,让我们创建一些 Sprites :
import pygame
from random import randint, choice

class Animal(pygame.sprite.Sprite):

colors = ['lightblue', 'blue', 'darkblue', 'dodgerblue']

def __init__(self, pos=None, color=None):
super().__init__()
self.image = pygame.Surface((32, 32))
self.image.fill(color if color else choice(Animal.colors))
self.rect = self.image.get_rect(center = pos if pos else (randint(100, 540), randint(100, 380)))

def main():
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()

animals = pygame.sprite.Group()
animals.add(Animal())
animals.add(Animal())
animals.add(Animal())

while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
screen.fill('grey')
animals.draw(screen)
pygame.display.flip()
clock.tick(60)

if __name__ == '__main__':
main()
使用 Sprite pygame 中的类,该类需要一个 image属性,这是一个 Surface , 和 rect属性,这是一个 Rect 并包含 Surface 的位置和大小.如果您创建一个 Sprite像这样,您可以使用 Group 类(或其子类)来绘制和更新您的 Sprite 。为了画点东西,我在一个组中添加了三个动物 animals并调用 draw函数,通过 screen表面作为参数所以 Group知道在哪里 blit 动物的图像。
enter image description here
由于到目前为止这很无聊,让我们为我们的 Sprite 添加一些行为:
import pygame
from random import randint, choice

class Animal(pygame.sprite.Sprite):

colors = ['lightblue', 'blue', 'darkblue', 'dodgerblue']

def __init__(self, pos=None, color=None):
super().__init__()
self.image = pygame.Surface((32, 32))
self.image.fill(color if color else choice(Animal.colors))
self.rect = self.image.get_rect(center = pos if pos else (randint(100, 540), randint(100, 380)))
self.pos = pygame.Vector2(*self.rect.center)
self.speed = 3
self.direction = pygame.Vector2(1, 0).rotate(randint(0, 360))

def update(self, dt):
v = self.direction * self.speed
while not pygame.display.get_surface().get_rect().contains(self.rect.move(v)):
self.direction = pygame.Vector2(1, 0).rotate(randint(0, 360))
v = self.direction * self.speed
self.pos += v
self.rect.center = self.pos

def main():
screen = pygame.display.set_mode((640, 480))
clock, dt = pygame.time.Clock(), 0

animals = pygame.sprite.Group()
animals.add(Animal())
animals.add(Animal())
animals.add(Animal())

while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return

animals.update(dt/1000)

screen.fill('grey')
animals.draw(screen)
pygame.display.flip()
dt = clock.tick(60)

if __name__ == '__main__':
main()
如您所见,我们将所有移动逻辑保留在 Animal 中。类(class)。游戏循环中唯一改变的是我们跟踪增量时间 dt确保恒定的帧速率(老实说,这在像这样的小例子中并不那么重要,但同样是一种很好的做法),并将其传递给组 update函数,它将调用 update它包含的每个 Sprite 的功能。
在 Animal 类中,我们使用一些简单的向量数学来移动 Sprite :我们有一个 speed和一个 direction (这是一个向量);还有一个 pos向量。使用向量改变位置很容易,因为我们可以做类似 pos = pos + direction * speed 的事情。 ,如果我们只是随机旋转方向向量,改变方向也很简单。
如果你想创建一个带有移动部件的 2D 游戏,我建议你学习一点矢量数学,如果你在学校还没有学过的话。除了可以轻松地将它们相加或相乘等这一事实之外,您不需要知道更多。
请记住, Sprite 是在其 rect 的坐标处绘制的。 ,所以我们也需要更新矩形的位置。
Pygame的 Rect class 也有一些方便的功能。看看我们如何检查 Sprite 是否会离开屏幕。我们可以简单地获取 Rect的显示表面,移动 Sprite 的 Rect并检查它是否仍在屏幕矩形内。如果没有,我们随机旋转我们的 direction向量(好吧,它不是 100% 完美,而是 KISS)。
enter image description here
那么其他 Sprite 呢?让我们子类化我们的 Animal类,通过覆盖更新函数来改变速度和颜色以及行为:
import pygame
import pygame.freetype
from random import randint, choice
from math import hypot

class Animal(pygame.sprite.Sprite):

colors = ['lightblue', 'blue', 'darkblue', 'dodgerblue']

def __init__(self, pos=None, color=None, *grps):
super().__init__(*grps)
self.image = pygame.Surface((32, 32))
self.color = color if color else choice(Animal.colors)
self.image.fill(self.color)
self.rect = self.image.get_rect(center = pos if pos else (randint(100, 540), randint(100, 380)))
self.pos = pygame.Vector2(*self.rect.center)
self.speed = 3
self.direction = pygame.Vector2(1, 0).rotate(randint(0, 360))

def update(self, dt):
v = self.direction * self.speed
while not pygame.display.get_surface().get_rect().contains(self.rect.move(v)):
self.direction = pygame.Vector2(1, 0).rotate(randint(0, 360))
v = self.direction * self.speed
self.pos += v
self.rect.center = self.pos


class Preditor(Animal):

def __init__(self, animals, pos=None, color=None, *grps):
super().__init__(pos, color or 'red', *grps)
self.speed = 4
self.target = None
self.animals = animals
self.eaten = 0
self.font = pygame.freetype.SysFont(None, 16)
self.font.render_to(self.image, (10, 10), str(self.eaten), 'white')

def get_nearest_animal(self):
target = None
distance = None
for animal in self.animals:
pygame.draw.line(pygame.display.get_surface(), 'darkgrey', self.pos, animal.pos)
if not target:
target = animal
distance = hypot(animal.pos.x - self.pos.x, animal.pos.y - self.pos.y)
else:
new_distance = hypot(animal.pos.x - self.pos.x, animal.pos.y - self.pos.y)
if new_distance < distance:
target = animal
distance = new_distance
if target:
pygame.draw.line(pygame.display.get_surface(), 'green', self.pos, target.pos)
return target

def update(self, dt):
self.target = self.get_nearest_animal()
if self.target:
self.direction = (self.target.pos - self.pos).normalize()
else:
self.direction = pygame.Vector2(0, 0)

self.pos += self.direction * self.speed
self.rect.center = self.pos

if self.target and self.rect.colliderect(self.target.rect):
self.target.kill()
self.image.fill(self.color)
self.eaten += 1
self.font.render_to(self.image, (10, 10), str(self.eaten), 'white')

def main():
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock, dt = pygame.time.Clock(), 0

animals = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
for _ in range(5):
Animal(None, None, animals, all_sprites)
Preditor(animals, None, None, all_sprites)

while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
if e.type == pygame.KEYDOWN:
Animal(None, None, animals, all_sprites)

screen.fill('grey')
all_sprites.update(dt/1000)
all_sprites.draw(screen)
pygame.display.flip()
dt = clock.tick(60)

if __name__ == '__main__':
main()
enter image description here
Sprite 可以是多个组的一部分,我们在这里使用它来给出 Predator它可以猎杀和吃掉的所有受害者的 list 。再次,看看所有的 Sprite 行为是如何在 Sprite 类中的。主循环所做的唯一一件事就是创建初始状态,告诉 Sprite 组更新和绘制它们的所有 Sprite (并通过按键添加新的动物,因为为什么不呢)。还要注意我们如何使用 kill将其从所有 it 组中删除,基本上将其从游戏中删除。
希望对您有所帮助并让您了解如何组织您的 pygame 游戏。
稍微玩一下就行了。需要进食以维持生命和繁殖的动物怎么样?而捕食者只需要触手可及的速度较慢的动物,如果没有,吃其他捕食者甚至植物?
import pygame
import pygame.freetype
from random import randint, choice
from math import hypot
from dataclasses import dataclass

class Plant(pygame.sprite.Sprite):

colors = ['green', 'lightgreen', 'darkgreen']

def __init__(self, pos=None, color=None, *grps):
self._layer = -10
super().__init__(*grps)
self.image = pygame.Surface((24, 24))
self.color = color if color else choice(Plant.colors)
self.image.fill(self.color)
self.rect = self.image.get_rect(center = pos if pos else (randint(10, 630), randint(10, 470)))
self.pos = pygame.Vector2(*self.rect.center)

class Animal(pygame.sprite.Sprite):

font = None
colors = ['lightblue', 'blue', 'darkblue', 'dodgerblue']

def __init__(self, system, pos=None, color=None, *grps):
super().__init__(*grps)
self.image = pygame.Surface((24, 24))
self.color = color if color else choice(Animal.colors)
self.image.fill(self.color)
self.rect = self.image.get_rect(center = pos if pos else (randint(100, 540), randint(100, 380)))
self.pos = pygame.Vector2(*self.rect.center)
self.speed = randint(20, 50) / 10
self.direction = pygame.Vector2(1, 0).rotate(randint(0, 360))
self.reproduce = randint(1, 5)
self.sleep = 0
self.eaten = 0
self.energy = 10
self.system = system
if not self.font:
Animal.font = pygame.freetype.SysFont(None, 16)

def base_update(self, dt):
self.energy -= dt * (self.speed / 2)
if self.energy <= 0:
self.kill()
return False

if self.sleep >= 0:
self.sleep -= dt
return False

self.reproduce -= dt
if self.reproduce <= 0 and self.energy >= 4:
self.reproduce = randint(1, 7)
self.__class__(self.system, self.pos, None, *self.groups())
self.sleep = 0.5
self.energy -= 1.5

return True

def update_image(self):
self.image.fill(self.color)
self.image.set_alpha(122 if self.sleep > 0 else 255)

pygame.draw.rect(self.image, 'green', (0, 0, self.rect.width * self.energy/10, 3))
self.font.render_to(self.image, (7, 7), str(self.eaten), 'white')

def get_nearest_target(self, targets, max_distance=250):
target = None
distance = None
for possible_target in targets:
if possible_target == self or hasattr(possible_target, 'speed') and possible_target.speed > self.speed:
continue

new_distance = hypot(possible_target.pos.x - self.pos.x, possible_target.pos.y - self.pos.y)
pygame.draw.line(pygame.display.get_surface(), 'darkgrey' if new_distance > max_distance else 'white', self.pos, possible_target.pos)
if new_distance <= max_distance:
if not target or new_distance < distance:
target = possible_target
distance = new_distance
if target:
pygame.draw.line(pygame.display.get_surface(), 'green', self.pos, target.pos)
return target

def update(self, dt):
if not self.base_update(dt) or len(self.groups()) == 0:
return

v = self.direction * self.speed
while not pygame.display.get_surface().get_rect().contains(self.rect.move(v)):
self.direction = pygame.Vector2(1, 0).rotate(randint(0, 360))
v = self.direction * self.speed

for plant in self.system.plants:
if plant.rect.colliderect(self.rect) and self.energy < 8:
plant.kill()
self.eaten += 1
self.energy = 10
continue

self.pos += v
self.rect.center = self.pos
self.update_image()

class Preditor(Animal):

def __init__(self, system, pos=None, color=None, *grps):
super().__init__(system, pos, color or 'red', *grps)
self.speed = randint(20, 40) / 10
self.target = None
self.update_image()

def update(self, dt):
if not self.base_update(dt) or len(self.groups()) == 0:
return

self.target = self.get_nearest_target(self.system.animals)
if not self.target:
self.target = self.get_nearest_target(self.system.preditors)
if not self.target:
self.target = self.get_nearest_target(self.system.plants)

if self.target:
self.direction = (self.target.pos - self.pos).normalize()
else:
self.direction = pygame.Vector2(0, 0)

self.pos += self.direction * self.speed
self.rect.center = self.pos

if self.target and self.rect.colliderect(self.target.rect):
self.target.kill()
self.eaten += 1
self.sleep = 0.5
self.energy += 3
if self.energy > 10:
self.energy = 10

self.update_image()

@dataclass
class System:
plants: object
animals: object
preditors: object

def main():
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock, dt = pygame.time.Clock(), 0

GROW = pygame.USEREVENT + 1
pygame.time.set_timer(GROW, 1000)


animals = pygame.sprite.Group()
plants = pygame.sprite.Group()
preditors = pygame.sprite.Group()
all_sprites = pygame.sprite.LayeredUpdates()

system = System(plants, animals, preditors)

for _ in range(4):
Animal(system, None, None, animals, all_sprites)

for _ in range(5):
Plant(None, None, plants, all_sprites)

Preditor(system, None, None, preditors, all_sprites)

while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
if e.type == pygame.KEYDOWN:
Animal(system, None, None, animals, all_sprites)
if e.type == GROW:
for _ in range(5):
Plant(None, None, plants, all_sprites)

screen.fill('grey')
all_sprites.update(dt/1000)
all_sprites.draw(screen)
pygame.display.flip()
dt = clock.tick(30)

if __name__ == '__main__':
main()
enter image description here

关于python - 在 pygame 的类/子类中设置和显示 Sprite 时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65191469/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com