您好,我是开发游戏/编码的新手,所以很抱歉我要带来的众多问题以及我的代码组织得很糟糕,我正在尝试让我的班级具有将自己呈现为函数的功能游戏,而不是使用外部资源
`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))
`
我遇到了问题,因为它说该类没有“屏幕”属性,我也不知道这意味着什么,顺便说一句,创建函数以在之后创建更多的设置类是最好的方法他们已经吃掉了足够多的食物链,并且具有删除它们以及组织所有不同子画面的功能(我知道这不是我的主要问题,因此,如果没有得到答案,那很好)
这是完整的代码:(对于我糟糕的格式化所造成的任何痛苦,我们深表歉意。
#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
该类(或其子类)来绘制和更新精灵。为了画些东西,我在一个组中添加了三个动物,animals
并调用draw
函数,将screen
Surface作为参数传递,这样就Group
知道了在哪里将动物的图像变灰。
到目前为止,由于这很无聊,因此让我们向精灵添加一些行为:
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()
As you can see, we keep all the moving logic in the Animal
class. The only thing that changed in the game loop is that we keep track of the delta time dt
to ensure a constant frame rate (honestly, that's not that important in a small example like this, but again, good practice), and pass it to the groups update
function, which in turn will call the update
function of each sprite it contains.
In the Animal class, we use some simple vector math to move the sprite: we have a speed
and a direction
(which is a vector); and also an additional pos
vector. Changing the position is easy with vectors because we can just do something like pos = pos + direction * speed
, and changing the direction is simple too if we just randomly rotate the direction vector.
If you want to create a 2D game with moving parts I recommend that you learn a litte bit of vector math if you didn't already learn it in school. You don't need to know much more than the fact that you can easily add them up or multiply them etc.
Remember that the sprite is drawn at the coordinate of its rect
, so we need to update the rect's position, too.
Pygame's Rect
class has some handy functions, too. Just look how we check if the sprite would go out of screen. We can simply grab the Rect
of the display surface, move the Sprite's Rect
and check if it's still inside the screen rect. If not, we randomly rotate our direction
vector (well, it's not 100% perfect, but KISS).
So what about other sprites? Let's just subclass our Animal
class, change the speed and color and the behaviour by overwriting the update function:
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()
Sprites can be part of multiple groups, and we use that here to give the Predator
a list of all its victims it can hunt and eat. Again, see how all sprite behaviour is inside the sprite classes. The only thing the main loop does is creating the initial state telling the sprite groups to update and draw all their sprites (and adding new Animals by pressing a key, because why not). Also note how we can use kill
to remove it from all it groups, basically removing it from the game.
Hope that helps and gives you an idea on how to organize your pygame game.
只是玩一点。那些需要吃饭才能生存和繁殖的动物怎么样?捕食者只需要触手可及的较慢动物,如果没有,就吃其他捕食者甚至植物?
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()
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句