This commit is contained in:
Benjamín 2021-09-02 22:25:45 +02:00
parent 319b85c552
commit 4b97fda8f2
8 changed files with 200 additions and 6 deletions

@ -18,7 +18,7 @@ class App:
hands_ai_process.start() hands_ai_process.start()
while True: while True:
self.scene.redraw() self.scene.update()
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == QUIT: if event.type == QUIT:

@ -20,7 +20,7 @@ class Multiscene(Scene):
self.subscenes_prepared = True self.subscenes_prepared = True
def redraw(self): def update(self):
if self.subscenes_prepared is False: if self.subscenes_prepared is False:
self.prepare_subscenes() self.prepare_subscenes()
@ -38,6 +38,14 @@ class Multiscene(Scene):
for object_ in self.nr_objects: for object_ in self.nr_objects:
object_.blit() object_.blit()
for object_ in self.nrd_objects:
object_.blit()
object_.progress()
for object_ in self.nrc_objects:
object_.blit()
object_.input(self.mouse_pos, self.clicked)
pygame.display.update() pygame.display.update()
def resize_screen(self, new_screen_size, subscene=False): def resize_screen(self, new_screen_size, subscene=False):
@ -49,6 +57,10 @@ class Multiscene(Scene):
[new_screen_size[0] / self.width, 0], [new_screen_size[0] / self.width, 0],
[0, new_screen_size[1] / self.height] [0, new_screen_size[1] / self.height]
]) ])
self.inverse_matrix = a([
[1 / self.matrix[0, 0], 0],
[0, 1 / self.matrix[1, 1]]
])
self.pd = abs(self.matrix[0, 0] * self.matrix[1, 1]) # positive determinant self.pd = abs(self.matrix[0, 0] * self.matrix[1, 1]) # positive determinant
self.pd_ = math.sqrt(self.pd) self.pd_ = math.sqrt(self.pd)

@ -11,10 +11,16 @@ class Scene(Screen):
self.r_objects = [] # resizable Objects self.r_objects = [] # resizable Objects
self.nr_objects = [] # non-rescalable Objects self.nr_objects = [] # non-rescalable Objects
self.nrd_objects = [] # non-rescalable dynamic Objects
self.nrc_objects = [] # non-rescalable controllable Objects
self.position = a([0, 0]) self.position = a([0, 0])
self.multiscene = None self.multiscene = None
def redraw(self): self.mouse_pos = a([0, 0])
self.clicked = False
def update(self):
self.s_.fill(self.bg) self.s_.fill(self.bg)
for object_ in self.r_objects: for object_ in self.r_objects:
@ -26,10 +32,22 @@ class Scene(Screen):
for object_ in self.nr_objects: for object_ in self.nr_objects:
object_.blit() object_.blit()
for object_ in self.nrd_objects:
object_.blit()
object_.progress()
for object_ in self.nrc_objects:
object_.blit()
object_.input(self.mouse_pos, self.clicked)
pygame.display.update() pygame.display.update()
def update_mouse_events(self, mouse_pos, clicked):
self.mouse_pos = self.inverse_matrix @ a(mouse_pos)
self.clicked = clicked
def blit(self): def blit(self):
self.redraw() self.update()
self.multiscene.s.blit(self.s, self.multiscene.matrix @ self.position) self.multiscene.s.blit(self.s, self.multiscene.matrix @ self.position)
def progress(self): def progress(self):

@ -15,6 +15,10 @@ class Screen:
[screen_size[0] / width, 0], [screen_size[0] / width, 0],
[0, screen_size[1] / height] [0, screen_size[1] / height]
]) ])
self.inverse_matrix = a([
[1 / self.matrix[0, 0], 0],
[0, 1 / self.matrix[1, 1]]
])
self.pd = abs(self.matrix[0, 0] * self.matrix[1, 1]) # positive determinant self.pd = abs(self.matrix[0, 0] * self.matrix[1, 1]) # positive determinant
self.pd_ = math.sqrt(self.pd) self.pd_ = math.sqrt(self.pd)
@ -29,6 +33,10 @@ class Screen:
[new_screen_size[0] / self.width, 0], [new_screen_size[0] / self.width, 0],
[0, new_screen_size[1] / self.height] [0, new_screen_size[1] / self.height]
]) ])
self.inverse_matrix = a([
[1 / self.matrix[0, 0], 0],
[0, 1 / self.matrix[1, 1]]
])
self.pd = abs(self.matrix[0, 0] * self.matrix[1, 1]) # positive determinant self.pd = abs(self.matrix[0, 0] * self.matrix[1, 1]) # positive determinant
self.pd_ = math.sqrt(self.pd) self.pd_ = math.sqrt(self.pd)

@ -0,0 +1,31 @@
import math
import pygame
class RopeInteractiveDot:
def __init__(self, position, r, color, force, forcefield_range, scene):
self.position = position
self.r = r
self.color = color
self.force = force
self.forcefield_range = forcefield_range
self.scene = scene
def blit(self):
pygame.draw.circle(self.scene.s, self.color, self.scene.matrix @ self.position, self.r)
def input(self, mouse_pos, clicked):
self.position = mouse_pos
if clicked:
for object_ in self.scene.nrd_objects:
if object_.__class__.__name__ == "Rope":
for node in object_.nodes:
if math.sqrt(sum((node.position - self.position) ** 2)) < self.forcefield_range:
force_vector = node.position - self.position
force_vector /= math.sqrt(sum(force_vector ** 2))
force_vector *= self.force
node.position += force_vector

@ -0,0 +1,99 @@
from numpy import array
import pygame
import math
class Rope:
class Node:
def __init__(self, position):
self.position = position
self.previous_position = position
self.locked = False
def progress(self, gravity):
if self.locked is False:
position_before_update = self.position
self.position += self.position - self.previous_position
self.position[1] += gravity
self.previous_position = position_before_update
class Connection:
def __init__(self, a, b, length):
self.a = a
self.b = b
self.length = length
def balance(self):
center = (self.a.position + self.b.position) * 0.5
connection_vector = (self.b.position - self.a.position)
connection_vector /= math.sqrt(sum(connection_vector ** 2))
connection_vector *= self.length * 0.5
if self.b.locked is False:
self.b.position = center + connection_vector
if self.a.locked is False:
self.a.position = center - connection_vector
def __init__(self, position, length, nodes_n, nodes_r, rope_width, scene, gravity=1, start_angle=1,
node_color=(255, 100, 100), rope_color=(255, 160, 160)):
self.position = position
self.length = length
self.nodes_n = nodes_n
self.nodes_r = nodes_r
self.rope_width = rope_width
self.gravity = gravity
self.start_angle = start_angle
self.scene = scene
self.node_color = node_color
self.rope_color = rope_color
self.pd_ = self.scene.pd_
self.initial_direction = array([math.cos(self.start_angle), math.sin(self.start_angle)])
self.rope_segment_length = self.length / (self.nodes_n - 1)
self.rescaled_rope_segment_length = self.rope_segment_length * self.pd_
self.rescaled_nodes_r = self.nodes_r * self.pd_
self.rescaled_rope_width = self.rope_width * self.scene.pd_
self.nodes = [self.Node(self.position +
self.initial_direction * i * self.rescaled_rope_segment_length)
for i in range(self.nodes_n)]
self.nodes[0].locked = True
self.connections = [self.Connection(self.nodes[i], self.nodes[i + 1], self.rescaled_rope_segment_length)
for i in range(len(self.nodes) - 1)]
def progress(self):
for node in self.nodes:
node.progress(self.gravity)
for _ in range(6):
for connection in self.connections:
connection.balance()
def blit(self):
if self.pd_ != self.scene.pd_:
self.rescaled_rope_segment_length = self.rope_segment_length * self.pd_
self.rescaled_nodes_r = self.nodes_r * self.pd_
self.rescaled_rope_width = self.rope_width * self.pd_
for connection in self.connections:
connection.length = self.rescaled_rope_segment_length
for i in range(len(self.nodes) - 1):
pygame.draw.line(self.scene.s, self.rope_color,
self.scene.matrix @ self.nodes[i].position,
self.scene.matrix @ self.nodes[i + 1].position,
int(self.rescaled_rope_width))
for node in self.nodes:
pygame.draw.circle(self.scene.s, self.node_color, self.scene.matrix @ node.position, self.rescaled_nodes_r)
@staticmethod
def to_ints(iterable):
for i in range(len(iterable)):
iterable[i] = int(iterable[i])
return iterable

19
UI/Scenes/RopeScene.py Normal file

@ -0,0 +1,19 @@
from Objects.Scene import Scene
from numpy import array as a
from UI.Objects.nr_objects.dynamic_objects.Rope import Rope
from UI.Objects.nr_objects.controllable_objects.RopeInteractiveDot import RopeInteractiveDot
class RopeScene(Scene):
def __init__(self, scene_size, bg=(60, 60, 60)):
s__size = [600, 400]
super().__init__(s__size[0], s__size[1], scene_size, bg)
r0 = Rope(a([300, 50]), 400, 20, 2, 2, self, gravity=5)
self.nrd_objects.append(r0)
rd0 = RopeInteractiveDot(a([100, 100]), 20, (100, 255, 100), 5, 100, self)
self.nrc_objects.append(rd0)

@ -1,17 +1,24 @@
import pygame.mouse
from Scenes.BasicScene import BasicScene from Scenes.BasicScene import BasicScene
from Scenes.BasicMultiscene import BasicMultiscene from Scenes.BasicMultiscene import BasicMultiscene
from Scenes.MultisceneInMultiscene import MultisceneInMultiscene from Scenes.MultisceneInMultiscene import MultisceneInMultiscene
from Scenes.RopeScene import RopeScene
from numpy import array as a from numpy import array as a
import time import time
screen_size = a([200, 500]) screen_size = a([200, 500])
scene = MultisceneInMultiscene(screen_size) scene = RopeScene(screen_size)
mouse_pos = [0, 0]
clicked = False
for i in range(400): for i in range(400):
scene.resize_screen(screen_size) scene.resize_screen(screen_size)
scene.redraw() scene.update()
scene.update_mouse_events(pygame.mouse.get_pos(), pygame.mouse.get_pressed(3)[0])
scene.progress() scene.progress()
# scene.save(f"Render/{i}.png", [800, 800]) # scene.save(f"Render/{i}.png", [800, 800])