首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在游戏中设置和显示我的类/子类中的精灵有问题

在游戏中设置和显示我的类/子类中的精灵有问题
EN

Stack Overflow用户
提问于 2020-12-08 00:37:28
回答 1查看 144关注 0票数 3

你好,我对创建游戏/编码相对来说还是比较新的,很抱歉,因为我将要带来的许多问题,以及我的代码的糟糕的组织,我正在尝试让我的类‘有一个函数来让自己融入游戏,而不是使用外部的源。

代码语言:javascript
复制
`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“属性,我不知道这意味着什么,在它吃了足够多的食物链以及组织所有不同的精灵之后,创建一个函数来创建更多的设置类的函数是最好的方法(我知道这不是我的主要问题的一部分,所以如果它得不到答案,那就好了)

这是完整的代码:(对我糟糕的格式所造成的任何痛苦表示歉意。

代码语言:javascript
复制
 #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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-09 09:27:57

您的代码非常混乱,但是不要担心,让我们一步一步地创建一个简单的游戏步骤。试着理解每一步都做些什么。

首先,让我们从游戏的基本框架开始,如下所示:

代码语言:javascript
复制
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

代码语言:javascript
复制
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就知道把动物的图像混在哪里了。

因为到目前为止,这是相当无聊的,让我们在我们的精灵中添加一些行为:

代码语言:javascript
复制
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类子类化,通过覆盖更新函数来改变速度、颜色和行为:

代码语言:javascript
复制
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组中删除,基本上从游戏中删除它。

希望这有助于并给你一个关于如何组织你的游戏游戏的想法。

玩一会儿就行了。为了生存和繁殖,需要吃的动物怎么样?而那些只需要速度较慢的动物的捕食者,如果没有,就吃其他的食肉动物,甚至植物?

代码语言:javascript
复制
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()

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65191469

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档