你好,我对创建游戏/编码相对来说还是比较新的,很抱歉,因为我将要带来的许多问题,以及我的代码的糟糕的组织,我正在尝试让我的类‘有一个函数来让自己融入游戏,而不是使用外部的源。
`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))
`我遇到了一些问题,因为它说这个类没有"screen“属性,我不知道这意味着什么,在它吃了足够多的食物链以及组织所有不同的精灵之后,创建一个函数来创建更多的设置类的函数是最好的方法(我知道这不是我的主要问题的一部分,所以如果它得不到答案,那就好了)
这是完整的代码:(对我糟糕的格式所造成的任何痛苦表示歉意。
#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发布于 2020-12-09 09:27:57
您的代码非常混乱,但是不要担心,让我们一步一步地创建一个简单的游戏步骤。试着理解每一步都做些什么。
首先,让我们从游戏的基本框架开始,如下所示:
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类,类需要一个image属性(即Surface )和一个rect属性(即Rect ),该属性包含Surface的位置和大小。如果您创建了这样一个Sprite,您可以使用Group类(或它的子类)来绘制和更新您的精灵。为了画一些东西,我在一个组animals中添加了三个动物,并调用了draw函数,将screen曲面作为一个参数传递给Group,这样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()如您所见,我们将所有移动逻辑保留在Animal类中。游戏循环中唯一改变的事情是,我们跟踪增量时间dt,以确保一个恒定的帧速率(老实说,在这样的小例子中,这并不重要,但同样,良好的实践),并将它传递给组update函数,后者将调用它所包含的每个sprite的update函数。
在动物类中,我们使用一些简单的向量数学来移动雪碧:我们有一个speed和一个direction (它是一个向量);还有一个附加的pos向量。用矢量改变位置很容易,因为我们可以做一些像pos = pos + direction * speed这样的事情,如果我们只是随机地旋转方向向量,改变方向也很简单。
如果你想创建一个带有移动部件的2D游戏,我建议你学习一点矢量数学,如果你还没有在学校学过的话。你不需要知道更多的事实,你可以很容易地把它们加起来或乘以它们,等等。
请记住,精灵是在它的rect坐标上绘制的,所以我们也需要更新rect的位置。
Pygame的Rect类也有一些方便的函数。看看我们是如何检查雪碧是否会脱离屏幕。我们可以简单地抓取显示表面的Rect,移动雪碧的Rect并检查它是否还在屏幕正向内。如果不是,我们随机旋转我们的direction矢量(嗯,它不是100%完美,而是接吻)。

那其他精灵呢?让我们将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()

精灵可以是多个群体的一部分,我们在这里用它给Predator一个它可以猎杀和吃的所有受害者的名单。再一次,看看雪碧类中的所有精灵行为。主循环所做的唯一一件事就是创建初始状态,告诉雪碧组更新并绘制它们的所有精灵(并按下一个键添加新的动物,因为为什么不这样做)。还请注意如何使用kill将其从所有it组中删除,基本上从游戏中删除它。
希望这有助于并给你一个关于如何组织你的游戏游戏的想法。
玩一会儿就行了。为了生存和繁殖,需要吃的动物怎么样?而那些只需要速度较慢的动物的捕食者,如果没有,就吃其他的食肉动物,甚至植物?
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()

https://stackoverflow.com/questions/65191469
复制相似问题