我要怎么把这两个球变成很多球?

2024-09-27 04:20:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我最近开始学习python,并在画布上制作了两个球的简单源代码,它们使用2d向量规则移动。我想用python中的list乘以球的数目。这就是原因。你知道吗

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,转换成它们中的许多,而不需要简单地输入每个球。你知道吗


Tags: ifnprandomarraycanvasx1x2randrange
2条回答

Question: How do i change these two balls into many of them?

为每个球或球对创建一个class object
这将导致所有球使用相同的规则。你知道吗

Note: I show only one Ball per class object, not a pair of Balls and without collision detection!

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

Usage:

.create_balls(...循环中创建class BallCanvas,以创建class Ball对象和Canvas create_oval(...对象。
list中累加,根据Ball.vector_rules(...的结果,使用canvas.move(...循环这个list来移动球。你知道吗

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)

Main Application:

使用Tkinter .after(150, ...移动Ball objects
这意味着。所有Ball objects每150ms移动一次

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测试

首先,可以将变量初始化为具有相同长度的随机数组。长度为10的示例:

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

对所有变量执行此操作。在当前循环中,可以循环所有变量。你知道吗

相关问题 更多 >

    热门问题