简体   繁体   English

Pygame 用鼠标移动球

[英]Pygame Moving a Ball with The Mouse

I have this assignment where when I click the mouse a ball will be launched and eventually destroy a box.我有这个任务,当我点击鼠标时,一个球将被发射并最终摧毁一个盒子。 I am having trouble moving the ball with the mouse click.我无法通过单击鼠标移动球。 The variables that are defined after the "print initial value line" are required to be those values.在“打印初始值行”之后定义的变量必须是这些值。 I'm not too familiar with pygame and don't know where I should be drawing and if I should remove the ball before I draw a new one.我对 pygame 不太熟悉,不知道我应该在哪里画画,也不知道我是否应该在画一个新球之前把球移开。

import pygame, sys
from Drawable import *
from Ball import *
from Block import *
from Text import *
from pygame.locals import *

pygame.init()
surface = pygame.display.set_mode((500,500))
surface.fill((255,255,255))



class Line(Drawable):
    def __init__(self,x=0, y=0,color=(0,255,0)):
        super().__init__(x, y, color)
        self.position = x , y
        self.visible = False

    def draw(self):
        if self.visible == True:
            pygame.draw.line(surface,(0,0,0),(0,400),(500,400))
    def get_rect(self):
        pass



ground = Line()
ground.visible = True
ground.draw()
ball = Ball()
ball.visible = True
ball.draw(surface)
block = Block()
block.visible = True
block.draw(surface)
text = Text()
text.visible = True
text.draw(surface)

print("Initial Ball Location:", ball.position)

dt = 0.1
g = 6.67
R = 0.7
eta = 0.5

mouespos1 = 0
mousepos2 = 0

xv = 1
yv = 1

def mousedown():
    global mousepos1
    mousepos1 = pygame.mouse.get_pos()


def mouseup():
    global xv
    global yv
    mousepos2 = pygame.mouse.get_pos()
    xv = mousepos2[0] - mousepos1[0]
    print("XV in mouseup:", xv)
    yv = -1 * (mousepos2[1] - mousepos1[1])
    print("YV in mouesup:", yv)

def updateballpos():
    global xv, yv
    print("Ran Update")
    moveX = ball.x + (dt * xv)
    ball.moveX(moveX)
    moveY = ball.y - (dt * yv)
    ball.moveY(moveY)

    print("new x", ball.x)
    print("new y", ball.y)

    if ball.y > 400:
        yv = -R * yv
        xv = eta * xv
    else:
        yv = yv - g * dt
    ball.draw(surface)
    pygame.display.update()







while(True):

    for event in pygame.event.get():

        if (event.type == pygame.QUIT) or \
            (event.type == pygame.KEYDOWN and event.__dict__['key'] == pygame.K_q):
            pygame.quit()
            exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            mousedown()
        if event.type == pygame.MOUSEBUTTONUP:
            mouseup()
        print("xv in while", xv)
        print("yv in while", yv)

    if yv > 0 and xv > 0:
        updateballpos()



    pygame.display.update()

And this is the Ball Class and Drawable Class这是 Ball 类和 Drawable 类

import pygame
import abc
import random

class Drawable(metaclass = abc.ABCMeta):
    def __init__(self,x,y,color):
        self.x = x
        self.y = y
        self.color = color
        self.position = (self.x,self.y)
        self.visible = False

    def getLoc(self):
        return (self.x, self.y)

    def setLoc(self,p):
        self.x = p[0]
        self.y = p[1]

    def getColor(self):
        return self.__color

    def getX(self):
        return self.__x

    def getY(self):
        return self.__y

    @abc.abstractmethod
    def draw(self,surface):
        pass
    @abc.abstractmethod
    def get_rect(self):
        pass





from Drawable import *
import pygame, sys
from pygame.locals import *

class Ball(Drawable):
    def __init__(self, x=20, y=400,color=(0, 0,0)):
        super().__init__(x, y,color)
        self.x = x
        self.y = y
        self.position = (self.x,self.y)
        self.visible = False

    def draw(self,s):
        if self.visible == True:
            pygame.draw.circle(s,(255,0,0),(int(self.x), int(self.y)),8)

    def get_rect(self):
        pass

    def getLoc(self):
        return (self.x, self.y)

    def setLoc(self, x, y):
        self.x = x
        self.y = y

    def moveX(self, inc):
        self.x = self.x + inc

    def moveY(self, inc):
        self.y = self.y + inc

I recommend adding the updateballpos as a method of the Ball , because it only updates the ball attributes.我建议添加updateballpos作为Ball的方法,因为它只更新球的属性。 The xv and yv variables should also be attributes of the balls, then you can give every ball a different velocity. xvyv变量也应该是球的属性,然后你可以给每个球一个不同的速度。

To spawn new balls, you can just create Ball instances and append them to a list, and then use for loops to update and draw the balls in this list.要生成新球,您只需创建Ball实例并将它们附加到列表中,然后使用for循环更新和绘制此列表中的球。 You can clear the screen with the fill method (or blit a background surface) before you draw the balls.在绘制球之前,您可以使用fill方法(或 blit 背景表面)清除屏幕。

For the slingshot effect you could store the rel attribute (relative movement of the mouse in pixels) of the pygame.MOUSEMOTION events, pass it to the balls when you instantiate them and just assign it to the xv , yv attributes.对于弹弓效果,您可以存储pygame.MOUSEMOTION事件的rel属性(鼠标的相对移动,以像素为单位),在实例化它们时将其传递给球,然后将其分配给xvyv属性。

Here's a minimal, complete example:这是一个最小的完整示例:

import sys
import pygame


pygame.init()
screen = pygame.display.set_mode((500,500))


class Ball:

    # Pass the xv, yv as arguments as well.
    def __init__(self, x=20, y=400, xv=0, yv=0, color=(0, 0,0)):
        self.x = x
        self.y = y
        # Give the objects xv and yv attributes.
        self.xv = xv
        self.yv = yv
        self.position = (self.x,self.y)
        self.visible = False

    def draw(self,s):
        if self.visible == True:
            pygame.draw.circle(s,(255,0,0),(int(self.x), int(self.y)),8)

    def get_rect(self):
        pass

    def getLoc(self):
        return (self.x, self.y)

    def setLoc(self, x, y):
        self.x = x
        self.y = y

    def moveX(self, dt):
        self.x += dt * self.xv

    def moveY(self, dt):
        self.y += dt * self.yv

    # Add a method to update the position and other attributes.
    # Call it every frame.
    def update(self, dt):
        self.moveX(dt)
        self.moveY(dt)

        if self.y > 400:
            self.yv = -R * self.yv
            self.xv = eta * self.xv
        else:
            self.yv = self.yv - g * dt

dt = 0.1
g = 6.67
R = 0.7
eta = 0.5

balls = []
clock = pygame.time.Clock()
rel_x = 0
rel_y = 0

while True:
    for event in pygame.event.get():
        if (event.type == pygame.QUIT or
            event.type == pygame.KEYDOWN and event.key == pygame.K_q):
            pygame.quit()
            sys.exit()
        if event.type == pygame.MOUSEBUTTONUP:
            # Create a new ball instance and append it to the list.
            # Pass the rel (the relative mouse movement) as well.
            ball = Ball(xv=rel_x*10, yv=rel_y*10)  # * 10 to make the balls faster.
            ball.visible = True
            balls.append(ball)
        if event.type == pygame.MOUSEMOTION:
            # event.rel is the relative movement of the mouse.
            rel_x = event.rel[0]
            rel_y = event.rel[1]

    # Call the update methods of all balls.
    for ball in balls:
        ball.update(dt)

    # Clear the screen with fill (or blit a background surface).
    screen.fill((255,255,255))
    # Draw the balls.
    for ball in balls:
        ball.draw(screen)

    pygame.display.update()
    dt = clock.tick(30) / 1000

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM