Как заставить объект двигаться самостоятельно? - PullRequest
2 голосов
/ 02 августа 2020

Для моей симуляции я пытаюсь сделать, чтобы мне нужны формы, чтобы иметь эффект гравитации. Другими словами, когда я нажимаю кнопку, чтобы создать новую фигуру, как я могу заставить ее упасть сама по себе? Любая помощь будет принята с благодарностью.

Примечание: я только пытался заставить кружки работать, поэтому код другой формы уже позади. Мне также нужно завершить sh обнаружение столкновений, поэтому для этого есть несколько случайных вещей.

main.py:

import pygame
import time
from shapes import *
from inv import *

pygame.init()

width, height = (1000, 800)
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Physics Game")
bgc = (223, 255, 252)
screen.fill(bgc)

# Inv Button Variables
iwidth = 100
iheight = 100

# Inventory Classes
icir = InvCir(10, 10, iwidth, iheight)
irect = InvRect(15 + iwidth, 10, iwidth, iheight)
itri = InvTri(20 + (iwidth * 2), 10, iwidth, iheight)

# Object Classes
cir = Circle(40, (97, 160, 255), 500, 300)
rect = Rect(300, 300, 80, 80)

# Shape Lists
cirList = []
rectList = []

def main():
    run = True
    FPS = 60
    clock = pygame.time.Clock()

    def updateScreen():
        icir.draw(screen, (0, 0, 0))
        irect.draw(screen, (0, 0, 0))
        itri.draw(screen, (0, 0, 0))

        pygame.display.update()

    def addList(list, shape):
        list.append(shape)
        print(list)

    while run:
        clock.tick(FPS)

        mpos = pygame.mouse.get_pos()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

            if event.type == pygame.MOUSEBUTTONDOWN:
                if icir.checkClick(mpos):
                    cir.itemDraw(screen)
                    addList(cirList, cir)


            if event.type == pygame.MOUSEBUTTONDOWN:
                if irect.checkClick(mpos):
                    rect.itemDraw(screen)
                    addList(rectList, rect)

        if pygame.mouse.get_pressed()[0]:
                pass

        

        updateScreen()

main()

shape.py:

import pygame
import os
from inv import *

pygame.init()

bgc = (223, 255, 252)
width, height = (1000, 800)
screen = pygame.display.set_mode((width, height))

# Images
CIRCLE = pygame.image.load(os.path.join("assets", "circle.png"))

def collide(obj1, obj2):
    offsetX = obj2.x - obj1.x
    offsetY = obj2.y - obj1.y
    return obj1.mask.overlap(obj2.mask, (offsetX, offsetY)) != None

class Circle:
    def __init__(self, radius, color, x, y):
        self.radius = radius
        self.color = color
        self.x = x
        self.y = y
        self.img = CIRCLE
        self.mask = pygame.mask.from_surface(self.img)

    def itemDraw(self, window):
        window.blit(self.img, (self.x, self.y))

    def move(self, vel):
        self.y += vel

    def wallCol(self, height, width):
        pass

    def objCol(self, obj):
        return collide(self, obj)

class Rect:
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = (255, 163, 76)

    def itemDraw(self, window):
        pygame.draw.rect(window, self.color, (self.x, self.y, self.width, self.height))

inv.py:

import pygame
import os

pygame.init()

CIRCLE = pygame.image.load(os.path.join("assets", "circ_button.png"))
SQUARE = pygame.image.load(os.path.join("assets", "square_button.png"))
TRIANGLE = pygame.image.load(os.path.join("assets", "tri_button.png"))

class Inv:
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height

class InvCir(Inv):
    def __init__(self, x, y, width, height):
        super().__init__(x, y, width, height)

    def draw(self, window, outline = None):
        if outline:
            pygame.draw.rect(window, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)

        window.blit(CIRCLE, (self.x, self.y))

    def checkClick(self, pos):
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True

        return False

class InvRect(Inv):
    def __init__(self, x, y, width, height):
        super().__init__(x, y, width, height)

    def draw(self, window, outline = None):
        if outline:
            pygame.draw.rect(window, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)

        window.blit(SQUARE, (self.x, self.y))
    
    def checkClick(self, pos):
        if pos[0] > self.x and pos[0] < self.x + self.width:
            if pos[1] > self.y and pos[1] < self.y + self.height:
                return True

        return False

class InvTri(Inv):
    def __init__(self, x, y, width, height):
        super().__init__(x, y, width, height)

    def draw(self, window, outline = None):
        if outline:
            pygame.draw.rect(window, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)

        window.blit(TRIANGLE, (self.x, self.y))

    def checkClick(self):
        pass

1 Ответ

2 голосов
/ 02 августа 2020

Уловка прыгающего мяча заключается в добавлении силы тяжести. Гравитация всегда увеличивает скорость Y (вертикальную) к полу.

  • Когда мяч падает , скорость увеличивается
  • Как мяч поднимается , скорость уменьшается

Когда мяч ударяется о землю, скорость меняется на противоположную, и мяч «отскакивает». Когда скорость мяча достигает нуля наверху, гравитация изменяет скорость и притягивает мяч к земле.

Вот простой пример прыгающего мяча:

import pygame as pg
from time import sleep, time

pg.init()

Height = Width = 500  # window dimensions

pg.display.set_caption("Bounce") # window title
win = pg.display.set_mode((Height, Width)) # create window

ball = {'x':Width/2, 'y':100, 'xs':3, 'ys':3 } # ball start position and speed
radius = 20  # ball radius

while True:   # main loop
   for event in pg.event.get(): # required for OS events
      if event.type == pg.QUIT:
         pg.quit()
         
   pg.time.Clock().tick(30)  # 30 FPS
   win.fill((255, 255, 255))  # clear screen
   pg.draw.circle(win, (200, 0, 0), (int(ball['x']), int(ball['y'])), 20) # draw ball

   ball['x'] += ball['xs'] # move ball left \ right
   ball['y'] += ball['ys'] # move ball up \ down
   if ball['y'] >= Height - radius: ball['ys'] = -ball['ys']  # bounce on floor
   else: ball['ys'] += .2   # accelerate toward floor, increase speed down, decrease up
   if ball['x'] <= radius or ball['x'] > Width - radius: ball['xs'] = -ball['xs']  # bounce on wall

   pg.display.update()
...