图片的位置未更新我在PYGAME中想要的方式

时间:2018-10-06 04:13:10

标签: python pygame game-development

我的目标是使大炮以直线路径发射炮弹。我一直在尝试一些算法,但是我无法获得一个流畅的运动,相反,位置会逐块更新,我不确定如何规避此问题。这是我的代码:

 import pygame
from functools import partial

pygame.init()

display_width = 700
display_height = 500
display = pygame.display.set_mode((display_width,display_height))

cannonImg = 'C:/Users/student/Desktop/cannon.png'
skyImg = 'C:/Users/student/Desktop/sky.png'
cannonballImg = 'C:/Users/student/Desktop/cannonball.png'
cannon = pygame.image.load(cannonImg)
sky = pygame.image.load(skyImg)
cannonball = pygame.image.load(cannonballImg)

blue = (0,0,200)
light_blue = (0,0,255)
black = (0,0,0)
red = (200,0,0)
light_red = (255,0,0)

smallfont = pygame.font.SysFont("comicsansms", 25)
medfont = pygame.font.SysFont("Algerian", 50)
largefont = pygame.font.SysFont("Algerian", 85)

altSmall = pygame.font.SysFont("Algerian",20)
altMed = pygame.font.SysFont("Algerian",30)
altLarge = pygame.font.SysFont("Algerian",75)
extrasmall = pygame.font.SysFont("comicsansms",15)

def text_objects(text, color,size = "small"):

    if size == "small":
        textSurface = smallfont.render(text, True, color)
    if size == "medium":
        textSurface = medfont.render(text, True, color)
    if size == "large":
        textSurface = largefont.render(text, True, color)

    if size == "altMed":
        textSurface = altMed.render(text,True,color)

    if size == "altSmall":
        textSurface = altSmall.render(text,True,color)

    if size == "medFont":
        textSurface = medfont.render(text,True,color)

    if size == "smallFont":
        textSurface = smallfont.render(text,True,color)

    if size == "extraSmall":
        textSurface = extrasmall.render(text,True,color)

    return textSurface, textSurface.get_rect()

def message_display(text):
    largeText = pygame.font.Font('freesansbold.ttf',200)
    TextSurf, TextRect = text_objects(text, largeText)
    TextRect.center = ((display_width/2),(display_height/2))
    gameDisplay.blit(TextSurf, TextRect)
    pygame.display.update()
    time.sleep(2)
    game_loop()

class Button():

    text = str()
    x = int()
    y = int()
    width = int()
    height = int()
    inactive_color = None
    active_color = None
    action = str()
    active = bool()

    def __init__(self,text,x,y,width,height,inactive_color,active_color,action,text_color,text_size,active):
        self.text = text
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.inactive_color = inactive_color
        self.active_color = active_color
        self.action = action
        self.text_color = text_color
        self.text_size = text_size
        self.active = active

    def nothing():
        pass

    def handle_event(self,event):

        if self.is_hovered() and event.type == pygame.MOUSEBUTTONDOWN:
            self.action()

    def text_to_button(self,surface):
        textSurf, textRect = text_objects(self.text,self.text_color,self.text_size)
        textRect.center = ((self.x+(self.width/2)), self.y+(self.height/2))
        surface.blit(textSurf, textRect)


    def is_hovered(self):
        cur = pygame.mouse.get_pos()
        return self.x + self.width > cur[0] > self.x and self.y + self.height > cur[1] > self.y

    def drawButton(self, surface):

        if self.active:
            pygame.draw.rect(surface,self.inactive_color,[self.x,self.y,self.width,self.height])

        if self.is_hovered() and self.active:
            pygame.draw.rect(surface, self.active_color,[self.x,self.y,self.width,self.height])

        self.text_to_button(surface)

def nothing():
    pass

class kinematic():

    obj_x = 110
    obj_y = 240
    v = 0
    t = 0

    def __init__(self,v,t):
        self.v = v
        self.t = t

    def addOneV(self):
        self.v += 1

    def addOneXI(self):
        self.xi += 1

    def addOneT(self):
        self.t += 1

    def reset(self):
        self.v = 0
        self.t = 0
        self.obj_x = 125
        self.obj_y = 240

    def calculatePos(self):
        n = 0
        while n < self.t+1:
            self.obj_x = self.t * 10
            self.obj_y = self.v * n
            n += 1

def programLoop():

    object1 = kinematic(0,10)
    reset = Button("Reset",400,25,100,75,red,light_red,object1.reset,black,"smallFont",True)

    programExit = False

    while not programExit:
        addVelocity = Button("Velocity: %i " % object1.v + "m/s",50, 25,150,50,red,light_red,object1.addOneV,black,"extraSmall",True)
        addTime = Button("Time: %i " % object1.t + "s",50, 75,150,50,red,light_red,object1.addOneT,black,"extraSmall",True)
        fireCannon = Button("Fire",display_width/2 - 75,25,125,75,red,light_red,object1.calculatePos,black,"smallFont",True)


        for evt in pygame.event.get():

            fireCannon.handle_event(evt)
            addVelocity.handle_event(evt)
            addTime.handle_event(evt)
            reset.handle_event(evt)
            if evt.type == pygame.QUIT:
                pygame.quit()
                quit()


        display.blit(sky,[0,0])
        display.blit(cannon,[25,300])
        fireCannon.drawButton(display)
        addVelocity.drawButton(display)
        addTime.drawButton(display)
        reset.drawButton(display)
        display.blit(cannonball,[object1.obj_x,object1.obj_y])
        display.blit(cannonball,[object1.obj_x,object1.obj_y])

        pygame.display.update()

programLoop()

谢谢!任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

您需要将对象的速度添加到每一帧中的位置才能移动它。我还将delta time传递给update方法,并将其乘以速度,以使对象每秒移动self.v个像素。

import pygame


pygame.init()

display_width = 700
display_height = 500
display = pygame.display.set_mode((display_width,display_height))

CANNONBALL = pygame.Surface((30, 30))
CANNONBALL.fill((90, 90, 90))

LIGHT_BLUE = (140,220,255)
BLACK = (0,0,0)
RED = (200,0,0)
LIGHT_RED = (255,0,0)

SMALLFONT = pygame.font.SysFont("comicsansms", 25)


def text_objects(text, color, font):  # You can pass the font object.
    textSurface = font.render(text, True, color)
    return textSurface, textSurface.get_rect()


class Button:

    def __init__(self, text, x, y, width, height, inactive_color, active_color,
                 action, text_color, font, active):
        self.text = text
        # Create a rect instead of the separate x, y, w, h attributes.
        self.rect = pygame.Rect(x, y, width, height)
        self.inactive_color = inactive_color
        self.active_color = active_color
        self.action = action
        self.text_color = text_color
        self.font = font  # The font is an attribute now.
        self.active = active

    def handle_event(self, event):
        if self.is_hovered() and event.type == pygame.MOUSEBUTTONDOWN:
            self.action()

    def text_to_button(self, surface):
        textSurf, textRect = text_objects(self.text, self.text_color, self.font)
        textRect.center = self.rect.center
        surface.blit(textSurf, textRect)

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

    def drawButton(self, surface):
        if self.active:
            pygame.draw.rect(surface, self.inactive_color, self.rect)
        if self.is_hovered() and self.active:
            pygame.draw.rect(surface, self.active_color, self.rect)

        self.text_to_button(surface)


class Kinematic:

    def __init__(self, v):
        self.obj_x = 110
        self.obj_y = 240
        self.v = v
        self.started = False

    def reset(self):
        self.started = False
        self.v = 0
        self.obj_x = 125
        self.obj_y = 240

    def start(self):
        self.started = True

    def update(self, dt):
        if self.started:
            # Just add the velocity to the position to
            # move the object.
            # Multiply the velocity by the delta time
            # to move `self.v` pixels per second.
            self.obj_x += self.v * dt


def programLoop():
    clock = pygame.time.Clock()
    object1 = Kinematic(0)

    # Callback functions to modify the object and update the button texts.
    def add_v():
        object1.v += 10
        addVelocity.text = f"Velocity: {object1.v} m/s"

    def reset():
        object1.reset()
        addVelocity.text = f"Velocity: {object1.v} m/s"

    reset = Button(
        "Reset", 400, 25, 100, 75, RED, LIGHT_RED,
        reset, BLACK, SMALLFONT, True)
    addVelocity = Button(
        f"Velocity: {object1.v} m/s", 50, 25, 150, 50,
        RED, LIGHT_RED, add_v, BLACK, SMALLFONT, True)
    fireCannon = Button(
        "Fire", display_width/2 - 75, 25, 125, 75, RED, LIGHT_RED,
        object1.start, BLACK, SMALLFONT, True)
    # You can put all buttons into a list and use for loops to
    # draw them and pass the events.
    buttons = [reset, addVelocity, fireCannon]

    dt = 0
    programExit = False

    while not programExit:
        for evt in pygame.event.get():
            for button in buttons:
                button.handle_event(evt)
            if evt.type == pygame.QUIT:
                return

        # Call the `update` method once per frame.
        object1.update(dt)  # Pass the delta time to the object.

        display.fill(LIGHT_BLUE)
        for button in buttons:
            button.drawButton(display)
        display.blit(CANNONBALL, [object1.obj_x, object1.obj_y])

        pygame.display.update()
        # dt is the time that has passed since the last clock.tick call.
        dt = clock.tick(60) / 1000


programLoop()
pygame.quit()

我还试图改进和简化其他内容。看一下评论。