Pygame角色脸鼠标

时间:2018-05-04 03:18:36

标签: pygame

我正在创建一个基本的2D头顶视图游戏,我正在努力制作角色" face"我移动它时的鼠标。

到目前为止,这是我的代码:

    import pygame
from pygame.locals import * 
import sys
import math
import pygame.gfxdraw
import random

pygame.init()

black=(0,0,0)
white=(255,255,255)
forest=(34,139,34)
red=(255,0,0)
blue=(0,0,255)
green=(0,255,0)
light_green=(0,120,0)
dark_green=(0,90,0)
skin=(255,224,189)
yellow=(255,255,0)

wood_image=pygame.image.load('./assets/images/wood.png')
stone_image=pygame.image.load('./assets/images/stone.png')
player_image=pygame.image.load('./assets/images/player.png')

tick=0

def terminate():
    pygame.quit()
    sys.exit()

def drawTextcenter(text,font,screen,x,y,color):
    textobj=font.render(text,True,color)
    textrect=textobj.get_rect(center=(x,y))
    screen.blit(textobj,textrect)

def drawText(text, font, surface, x, y,color):
    textobj=font.render(text, 1, color)
    textrect=textobj.get_rect()
    textrect.topleft=(x, y)
    surface.blit(textobj, textrect)

class Button(object):
    global screen_width,screen_height,screen
    def __init__(self,x,y,width,height,text_color,background_color,text):
        self.rect=pygame.Rect(x,y,width,height)
        self.x=x
        self.y=y
        self.width=width
        self.height=height
        self.text=text
        self.text_color=text_color
        self.background_color=background_color
        self.angle=0

    def check(self):
        return self.rect.collidepoint(pygame.mouse.get_pos())

    def draw(self):
        pygame.draw.rect(screen, self.background_color,(self.rect),0)
        drawTextcenter(self.text,font,screen,self.x+self.width/2,self.y+self.height/2,self.text_color)  
        pygame.draw.rect(screen,self.text_color,self.rect,3) 

class Bar(object):
    def __init__(self,x,y,length,color):
        self.rect=pygame.Rect(x,y,length,17.5)
        self.image=pygame.draw.rect(screen,white,(self.rect),)
        self.x=x
        self.y=y
        self.width=100
        self.height=17.5
        self.color=color
        self.multiplier=length/100

    def draw(self,num): 
        rect=pygame.Rect(self.x,self.y,num*self.multiplier,self.height)
        pygame.draw.rect(screen,self.color,self.rect,3)
        pygame.draw.rect(screen,self.color,rect,0)

class Player(pygame.sprite.Sprite):
    def __init__(self,x,y):
        super(Player,self).__init__()
        self.image=player_image
        self.original_image=self.image
        self.rect=self.image.get_rect(center=(x,y))
        self.change_x=0
        self.change_y=0
        self.speed=7.5
        self.inventory={'wood':0}

    def changespeed(self,x,y):
        self.change_x+=x
        self.change_y+=y

    def update(self,rect):
        self.rotate(camera)
        self.rect.x += self.change_x
        self.rect.y += self.change_y
        rect = camera.apply(self)
        screen.blit(self.image, rect)

    def check(self):
        global tick
        if pygame.mouse.get_pressed()[0]: 
            for tree in resources:
                tree_rect=tree.rect                                
                if self.rect.colliderect(tree_rect) and tick>=9:
                    self.inventory['wood']+=1
                    tick=0

    def rotate(self,camera):
        mouse_x, mouse_y = pygame.mouse.get_pos()
        mouse_x -= camera.state.x
        mouse_y -= camera.state.y
        rel_x, rel_y = mouse_x - self.rect.centerx, mouse_y -self.rect.centery
        angle = -math.degrees(math.atan2(rel_y, rel_x))
        self.image = pygame.transform.rotate(self.original_image, angle)
        self.rect = self.image.get_rect(center=self.rect.center)

class Tree(pygame.sprite.Sprite):
    def __init__(self,x,y):
        super(Tree,self).__init__()
        self.rect=pygame.Rect(x,y,100,100)
        self.rect.x=x
        self.rect.y=y

    def update(self,rect):
        pygame.gfxdraw.filled_circle(screen,rect.x,rect.y,80,light_green)
        pygame.gfxdraw.aacircle(screen,rect.x,rect.y,80,light_green)

class Rock(pygame.sprite.Sprite):
    def __init__(self):
        pass

class Camera(object):
    def __init__(self,camera_func,width,height):
        self.camera_func=camera_func
        self.state=pygame.Rect(0,0,width,height)

    def apply(self,target):
        return target.rect.move(self.state.topleft)

    def update(self,target):
        self.state=self.camera_func(self.state,target.rect)

def complex_camera(camera, target_rect):
    l, t = target_rect.center
    _,_,w,h = camera
    l,t,_,_ = -l+screen_width/2, -t+screen_height/2, w, h

    l = min(0, l)                           
    l = max(-(camera.width-screen_width), l)
    t = max(-(camera.height-screen_height), t)
    t = min(0, t)                           

    return pygame.Rect(l, t, w, h)

clock=pygame.time.Clock()
font=pygame.font.SysFont(None,40)

screen_width=1440
screen_height=800
screen=pygame.display.set_mode([screen_width,screen_height])
pygame.display.set_caption('Survival')

total_level_width=screen_width*5
total_level_height=screen_height*5
camera = Camera(complex_camera, total_level_width, total_level_height)

player=Player(random.randint(100,7900),random.randint(100,5900))
friendlies=pygame.sprite.Group()
friendlies.add(player)

player_health_bar=Bar(125,15,200,green)
player_health=100
player_food_bar=Bar(437.5,15,200,red)
player_food=100
player_thirst_bar=Bar(750,15,200,blue)
player_thirst=100
player_energy_bar=Bar(1100,15,200,yellow)
player_energy=100

resources=pygame.sprite.Group()

wood=False
inventory={}

for i in range(1000):
    tree=Tree(random.randint(100,7900),random.randint(100,5900))
    resources.add(tree)

done1=False
while not done1:
    screen.fill(black)
    font=pygame.font.SysFont(None, 90)
    text_width,text_height=font.size('Survival')
    drawText('Survival', font, screen, (screen_width/2-text_width/2), (screen_height / 2-375),white)
    font=pygame.font.SysFont(None, 40)
    start_button=Button(screen_width/2-125,650,250,50,white,black,'Start')
    start_button.draw()
    back_button=Button(screen_width/2-125,725,250,50,white,black,'Back')
    back_button.draw()
    pygame.display.flip()
    done2=False
    while not done2:
        for event in pygame.event.get():
            if event.type==QUIT:
                terminate()
            elif event.type==pygame.MOUSEBUTTONDOWN:
                if start_button.check()==True: 
                    done3=False
                    pause_back=False
                    while not done3:             
                        tick+=1
                        for event in pygame.event.get():
                            if event.type==pygame.QUIT:
                                terminate()
                            elif event.type==pygame.KEYDOWN:
                                if event.key==pygame.K_a:
                                    player.changespeed(-(player.speed), 0)
                                elif event.key==pygame.K_d:
                                    player.changespeed(player.speed, 0)
                                elif event.key==pygame.K_w:
                                    player.changespeed(0, -(player.speed))
                                elif event.key==pygame.K_s:
                                    player.changespeed(0, player.speed)
                                elif event.key==pygame.K_p:
                                    font=pygame.font.SysFont(None, 90)
                                    text_width,text_height=font.size('Paused')
                                    drawText('Paused', font, screen, (screen_width / 2-(text_width/2)), (screen_height / 2-375),white)
                                    resume_button=Button(screen_width/2-125,650,250,50,white,black,'Resume')
                                    resume_button.draw()
                                    back_button.draw()
                                    pygame.display.flip()
                                    back=False
                                    while not back:
                                        for event in pygame.event.get():
                                            if event.type==QUIT:
                                                terminate()
                                            elif event.type==pygame.MOUSEBUTTONDOWN:
                                                if resume_button.check()==True:
                                                    back=True
                                                elif back_button.check()==True:
                                                    done3=True
                                                    done2=True
                                                    pause_back=True
                                                    back=True

                            elif event.type == pygame.KEYUP:
                                if event.key == pygame.K_a:
                                    player.changespeed(player.speed, 0)
                                elif event.key == pygame.K_d:
                                    player.changespeed(-(player.speed), 0)
                                elif event.key == pygame.K_w:
                                    player.changespeed(0, player.speed)
                                elif event.key == pygame.K_s:
                                    player.changespeed(0, -(player.speed))   

                        camera.update(player)

                        if player.rect.x<0:
                            player.rect.x=0
                        if player.rect.right>total_level_width:
                            player.rect.right=total_level_width
                        if player.rect.y<0:
                            player.rect.y=0
                        if player.rect.bottom>total_level_height:
                            player.rect.bottom=total_level_height

                        screen.fill(dark_green)

                        player.update(camera)

                        for resource in resources:
                            resource.update(camera.apply(resource))

                        player_health_bar.draw(player_health)
                        player_food_bar.draw(player_food)
                        player_thirst_bar.draw(player_thirst)
                        #player_endergy_bar.draw(player_energy)
                        font=pygame.font.SysFont(None, 40)
                        drawText('Health:',font,screen,20,10,green)
                        drawText('Food:',font,screen,350,10,red)
                        drawText('Thirst:',font,screen,650,10,blue)
                        #drawText('Energy:', font, screen, 975, 10, yellow)
                        pygame.draw.rect(screen,forest,(50,675,100,100))
                        pygame.draw.rect(screen,forest,(175,675,100,100))
                        pygame.draw.rect(screen,forest,(300,675,100,100))

                        #player.check()

                        for item in player.inventory:
                            if item=='wood' and player.inventory['wood']>0:
                                wood=True

                        if wood:
                            screen.blit(wood_image,(62.5,687.5))
                            drawTextcenter(str(player.inventory['wood']),font,screen,100,735,black)

                        pygame.display.flip()

                        clock.tick(100)

                        if pause_back==True:
                                break
                    if pause_back==True:
                        break
                    screen.fill(black)
                    font=pygame.font.SysFont(None, 90)
                    text_width,text_height=font.size("Game Over")
                    drawText('Game Over', font, screen, (screen_width/2-text_width/2), (screen_height / 2-200),white)
                    font=pygame.font.SysFont(None, 40)
                    retry_button=Button(screen_width/2-125,650,250,50,white,black,'Retry')
                    retry_button.draw()
                    back_button.draw()
                    pygame.display.flip()
                    back=False 
                    while not back:
                        for event in pygame.event.get():
                                if event.type==QUIT:
                                    terminate()
                                elif event.type==pygame.MOUSEBUTTONDOWN:
                                    if retry_button.check()==True:
                                        back=True
                                    if back_button.check()==True:
                                        back=True
                                        done2=True
                                        done3=True        
                elif back_button.check()==True: 
                    done2=True
                    done1=True

为此,我按照answer进行了操作。它应该计算出鼠标和播放器之间的向量,并且每一步都将角色转向鼠标,但是对于我来说,当鼠标移动时,精灵会转动,并且变为不可见。

完整代码:

{{1}}

Player.png:

1 个答案:

答案 0 :(得分:1)

我没有检查完整的程序,因为它的代码太多,但我可以在Player类中看到错误。您在(self.rect.x,self.rect.y)方法中将rotate(左上角)坐标指定给新rect的中心,但您必须指定前一个rect的center坐标。< / p>

self.rect = self.image.get_rect(center=(self.rect.x,self.rect.y))

将上面的行更改为:

self.rect = self.image.get_rect(center=self.rect.center)

这是一个最小的,完整的例子:

import math
import pygame as pg


class Player(pg.sprite.Sprite):
    def __init__(self, pos):
        super(Player,self).__init__()
        x, y = pos
        self.image = pg.Surface((50, 30), pg.SRCALPHA)
        pg.draw.polygon(
            self.image,
            pg.Color('dodgerblue1'),
            ((1, 1), (49, 15), (1, 29)))
        self.original_image = self.image
        self.rect=self.image.get_rect(center=(x,y))
        self.change_x=0
        self.change_y=0
        self.speed=7.5
        self.inventory={'wood':0}

    def changespeed(self,x,y):
        self.change_x+=x
        self.change_y+=y

    def update(self):
        self.rotate()
        self.rect.x+=self.change_x
        self.rect.y+=self.change_y

    def rotate(self):
        mouse_x, mouse_y = pg.mouse.get_pos()
        rel_x, rel_y = mouse_x - self.rect.x, mouse_y -self.rect.y
        angle = (180 / math.pi) * -math.atan2(rel_y, rel_x)
        self.image = pg.transform.rotate(self.original_image, angle)
        # rect.x and .y are the topleft coords, but you need the to
        # pass the center coordinates of the previous rect to the new one.
        self.rect = self.image.get_rect(center=self.rect.center)


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    all_sprites = pg.sprite.Group()
    player = Player((300, 200))
    all_sprites.add(player)

    done = False
    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_d:
                    player.change_x = 4
                elif event.key == pg.K_a:
                    player.change_x = -4
            elif event.type == pg.KEYUP:
                if event.key == pg.K_d:
                    player.change_x = 0
                elif event.key == pg.K_a:
                    player.change_x = 0

        all_sprites.update()
        screen.fill((30, 30, 30))
        all_sprites.draw(screen)

        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

问题是由相机引起的。您还必须将相机偏移应用于鼠标位置。

这是一个简单的解决方案。首先,将相机而不是矩形传递给player.update方法。

player.update(camera)

也将它传递给rotate方法。

def update(self, camera):
    self.rotate(camera)
    self.rect.x += self.change_x
    self.rect.y += self.change_y
    rect = camera.apply(self)
    screen.blit(self.image, rect)

在旋转方法中,您必须从鼠标位置减去相机位置以获得世界坐标。

def rotate(self, camera):
    mouse_x, mouse_y = pygame.mouse.get_pos()
    # Subtract the camera offset from the mouse position.
    mouse_x -= camera.state.x
    mouse_y -= camera.state.y
    # Use the center coordinates of the rect.
    rel_x, rel_y = mouse_x - self.rect.centerx, mouse_y -self.rect.centery
    angle = -math.degrees(math.atan2(rel_y, rel_x))
    self.image = pygame.transform.rotate(self.original_image, angle)
    # Set the new center to the previous center coords.
    self.rect = self.image.get_rect(center=self.rect.center)

我还必须修改complex_camera函数,因为它应该与中心坐标一起使用。

def complex_camera(camera, target_rect):
    # The camera works with the center instead of
    # the topleft coordinates now.
    l, t = target_rect.center
    _,_,w,h = camera
    l,t,_,_ = -l+screen_width/2, -t+screen_height/2, w, h

    l = min(0, l)                           
    l = max(-(camera.width-screen_width), l)
    t = max(-(camera.height-screen_height), t)
    t = min(0, t)                           

    return pygame.Rect(l, t, w, h)