Как я могу изменить эти два шара на многие из них? - PullRequest
0 голосов
/ 05 декабря 2018

Я недавно начал изучать Python, и сделал простой источник из 2 шаров на холсте, которые движутся с 2d векторным правилом.Я хочу умножить количество шаров со списком в Python.вот источник этого.

import time
import random
from tkinter import *
import numpy as np
import math
window = Tk()
canvas = Canvas(window,width=600,height=400)
canvas.pack()


canvas.create_rectangle(50,50,550,350)

R = 15
x1 = random.randrange(50+R,550-R)
y1 = random.randrange(50+R,350-R)
x2 = random.randrange(50+R,550-R)
y2 = random.randrange(50+R,350-R)
vx1 = random.randrange(1 , 10)
vy1 = random.randrange(1 , 10)
vx2 = random.randrange(1 , 10)
vy2 = random.randrange(1 , 10)
ntime = 100000
dt = .1


for iter in range(ntime):

    x1 += vx1*dt
    y1 += vy1*dt
    x2 += vx2*dt
    y2 += vy2*dt
    c1 = canvas.create_oval(x1-R,y1-R,x1+R,y1+R,fill="red")
    c2 = canvas.create_oval(x2-R,y2-R,x2+R,y2+R,fill="blue")
    if (x1 > 550-R):
        vx1 = -vx1
    if (x1 < 50+R ):
        vx1 = -vx1
    if (x2 > 550-R):
        vx2 = -vx2
    if (x2 < 50+R ):
        vx2 = -vx2
    if (y1 > 350-R) or (y1 < 50+R):
        vy1 = -vy1
    if (y2 > 350-R) or (y2 < 50+R):
        vy2 = -vy2
    if (x2-x1)**2 + (y2-y1)**2 <= 4*R*R:

        vector1 = np.array([x1,y1])
        vector2 = np.array([x2,y2])
        vvector1 = np.array([vx1,vy1])
        vvector2 = np.array([vx2,vy2])
        nvector = np.array([x2-x1,y2-y1])
        un = (nvector)/((sum(nvector*nvector))**(1/2))
        tvector = np.array([y1-y2,x2-x1])
        ut = tvector/((sum(nvector*nvector))**(1/2))
        vector1midn = sum(vvector1*un)
        vector2midn = sum(vvector2*un)
        vector1midt = sum(vvector1*ut)
        vector2midt = sum(vvector2*ut)
        vector1after = vector2midn*un + vector1midt*ut
        vector2after = vector1midn*un + vector2midt*ut
        vx1 = vector1after[0]
        vy1 = vector1after[1]
        vx2 = vector2after[0]
        vy2 = vector2after[1]



    txt = canvas.create_text(100,30,text=str(iter),font=('consolas', '20', 
'bold'))


    window.update()
    time.sleep(0.002)



    if iter == ntime-1 : break  

    canvas.delete(c1)
    canvas.delete(c2)
    canvas.delete(txt)


window.mainloop()

Точный вопрос в том, как я могу изменить c1, c2, выше, на многие из них, не просто набирая каждый шарик.

Ответы [ 2 ]

0 голосов
/ 09 декабря 2018

Вопрос : Как мне поменять эти два шара на многие из них?

Создать class object для каждого шара или пары шаров.
В результате все шары используют одни и те же правила.

Примечание : я показываю только один шар на class object, не пара шаров и без обнаружения столкновений !

enter image description here

class Ball:
    R = 15

    def __init__(self, parent=None, color=None):
        self.parent = parent

        # Define shortcuts
        radius = self.R

        # Random bbox Ellipse coordinates of the ball.
        x = random.randrange(50 + radius, 550 - radius)
        y = random.randrange(50 + radius, 350 - radius)
        coord1 = (x - radius, y - radius, x + radius, y + radius)

        # Random direction
        x = random.randrange(1, 10)
        y = random.randrange(1, 10)
        self.direction = (x, y)

        # Save the bbox coordinate of the ball
        self.coord1 = self.bbox(coord1, self.direction)

    def bbox(self, coord1=None, direction=None):
        # Return if NO move
        if coord1 is None:
            return self.coord1

        return (coord1[0] + direction[0],
                coord1[1] + direction[1],
                coord1[2] + direction[0],
                coord1[3] + direction[1]
                )

    def vector_rule(self):
        # Get the estimated new bbox coordinate of the Ball
        coord1 = self.bbox(self.coord1, self.direction)

        # Define shortcuts
        R = self.R
        x1 = coord1[0]
        y1 = coord1[1]
        vx1 = self.direction[0]
        vy1 = self.direction[1]

        # Boundary check
        if (x1 > 530 - R):
            vx1 = -vx1

        if (x1 < 35 + R):
            vx1 = -vx1

        if (y1 > 330 - R) or (y1 < 35 + R):
            vy1 = -vy1

        # Save the new direction - could be the same as before
        self.direction = (vx1, vy1)

        # Save the new bbox coordinate of the Ball
        self.coord1 = self.bbox(self.coord1, self.direction)

        # Return the move offsets
        return self.direction

Использование :

Создание цикла class BallCanvas в .create_balls(... для создания class Ball объектов и Canvas create_oval(... объектов.
Накопление обоих в list, цикл этотlist для перемещения шаров с помощью canvas.move(..., в результате Ball.vector_rules(....

class BallCanvas(tk.Canvas):
    def __init__(self, parent, width, height):
        self.parent = parent
        super().__init__(parent, width=width, height=height)
        self.create_rectangle(50, 50, 550, 350)
        self.grid(row=1)

        self.balls = []
        self.create_balls()

    def create_balls(self):
        for n in range(5):
            for color in ['red', 'blue']:
                ball = Ball()
                self.balls.append((self.create_oval(ball.bbox(), fill=color, tags='ball'), ball))

    def move_balls(self):
        for id, ball in self.balls:
            new_x, new_y = ball.vector_rule()
            self.move(id, new_x, new_y)

Основное применение :

Переместите Ball objects с помощью Tkinter .after(150, ....
Это означает.все Ball objects перемещаются каждые 150 мс.

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry("610x430+650+280")

        self.canvas = BallCanvas(self, width=600, height=400)

        self.count = 200
        self.after(500, self.move)

    def move(self):
        self.count -= 1    
        self.canvas.move_balls()

        if self.count > 0:
            self.after(150, self.move)

if __name__ == "__main__":
    App().mainloop()

Проверено на Python: 3,5

0 голосов
/ 05 декабря 2018

вы можете начать с инициализации переменных как случайных массивов одинаковой длины.Пример с длиной 10:

x = np.random.randint(50+R,550-R, size=10)

Сделайте это для всех переменных.Внутри вашего текущего цикла вы можете просмотреть все переменные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...