_
This commit is contained in:
124
TuGUI/Objects/Multiscene.py
Normal file
124
TuGUI/Objects/Multiscene.py
Normal file
@@ -0,0 +1,124 @@
|
||||
import copy
|
||||
import math
|
||||
import pygame
|
||||
from numpy import array as a
|
||||
from TuGUI.Objects.Scene import Scene
|
||||
|
||||
|
||||
class Multiscene(Scene):
|
||||
|
||||
object_type = "multiscene"
|
||||
|
||||
def __init__(self, width: float, height: float, scene_size: a):
|
||||
super().__init__(width, height, scene_size)
|
||||
|
||||
self.subscenes = []
|
||||
self.subscenes_prepared = False
|
||||
|
||||
def prepare_subscenes(self):
|
||||
|
||||
for subscene in self.subscenes:
|
||||
subscene.multiscene = self
|
||||
subscene.subscene_size = subscene.screen_size
|
||||
subscene.resize_screen(self.to_ints((self.matrix @ subscene.subscene_size).tolist()), True)
|
||||
|
||||
self.s = pygame.display.set_mode(self.screen_size)
|
||||
|
||||
self.subscenes_prepared = True
|
||||
|
||||
def light_update(self):
|
||||
for subscene in self.subscenes:
|
||||
subscene.light_update()
|
||||
|
||||
for object_ in self.l_objects:
|
||||
object_.update()
|
||||
object_.blit(True)
|
||||
|
||||
pygame.display.update()
|
||||
|
||||
def update(self):
|
||||
if self.subscenes_prepared is False:
|
||||
self.prepare_subscenes()
|
||||
|
||||
self.s_.fill(self.bg)
|
||||
|
||||
for object_ in self.l_objects:
|
||||
object_.update()
|
||||
|
||||
for object_ in self.r_objects:
|
||||
object_.blit()
|
||||
|
||||
rs = pygame.transform.scale(self.s_, self.screen_size)
|
||||
self.s.blit(rs, [0, 0])
|
||||
|
||||
for scene in self.subscenes:
|
||||
scene.blit()
|
||||
|
||||
for object_ in self.nr_objects:
|
||||
object_.blit()
|
||||
|
||||
for object_ in self.d_objects:
|
||||
object_.progress()
|
||||
|
||||
for object_ in self.c_objects:
|
||||
object_.input(self.mouse_pos, self.clicked)
|
||||
|
||||
pygame.display.update()
|
||||
|
||||
def resize_screen(self, new_screen_size, subscene=False):
|
||||
if self.subscenes_prepared is False:
|
||||
self.prepare_subscenes()
|
||||
|
||||
self.screen_size = a(new_screen_size)
|
||||
self.matrix = a([
|
||||
[new_screen_size[0] / self.width, 0],
|
||||
[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_ = math.sqrt(self.pd)
|
||||
|
||||
if subscene is False:
|
||||
self.s = pygame.display.set_mode(new_screen_size)
|
||||
else:
|
||||
self.s = pygame.Surface(new_screen_size)
|
||||
|
||||
self.resize_subscenes()
|
||||
|
||||
def update_mouse_events(self, mouse_pos, clicked):
|
||||
mouse_pos = a(mouse_pos)
|
||||
self.mouse_pos = self.inverse_matrix @ mouse_pos
|
||||
self.clicked = clicked
|
||||
|
||||
for subscene in self.subscenes:
|
||||
subscene.mouse_pos = (subscene.inverse_matrix @ (mouse_pos - (self.matrix @ subscene.position)))
|
||||
subscene.clicked = clicked
|
||||
|
||||
def progress(self):
|
||||
self.progress_subscenes()
|
||||
|
||||
def resize_subscenes(self):
|
||||
for subscene in self.subscenes:
|
||||
subscene.resize_screen(self.to_ints((self.matrix @ subscene.subscene_size).tolist()), True)
|
||||
|
||||
def progress_subscenes(self):
|
||||
for subscene in self.subscenes:
|
||||
subscene.progress()
|
||||
|
||||
def get_i_objects(self):
|
||||
i_objects = [[copy.copy(self.i_objects), self.mouse_pos]]
|
||||
|
||||
for subscene in self.subscenes:
|
||||
i_objects += subscene.get_i_objects()
|
||||
|
||||
return i_objects
|
||||
|
||||
@staticmethod
|
||||
def to_ints(iterable):
|
||||
for i in range(len(iterable)):
|
||||
iterable[i] = int(iterable[i])
|
||||
|
||||
return iterable
|
109
TuGUI/Objects/Scene.py
Normal file
109
TuGUI/Objects/Scene.py
Normal file
@@ -0,0 +1,109 @@
|
||||
import pygame.transform
|
||||
from TuGUI.Objects.Screen import Screen
|
||||
from numpy import array as a
|
||||
import numpy as np
|
||||
|
||||
|
||||
class Scene(Screen):
|
||||
|
||||
object_type = "scene"
|
||||
|
||||
def __init__(self, width: float, height: float, scene_size: a, bg=(60, 60, 60)):
|
||||
super().__init__(width, height, scene_size)
|
||||
|
||||
self.bg = bg
|
||||
self.r_objects = [] # resizable Objects
|
||||
self.nr_objects = [] # non-rescalable Objects
|
||||
|
||||
self.d_objects = [] # dynamic Objects
|
||||
self.c_objects = [] # controllable Objects
|
||||
self.i_objects = [] # interactive Objects
|
||||
self.l_objects = [] # light Objects
|
||||
|
||||
self.position = a([0, 0])
|
||||
self.multiscene = None
|
||||
|
||||
self.mouse_pos = a([0, 0])
|
||||
self.clicked = False
|
||||
|
||||
def light_update(self):
|
||||
for object_ in self.l_objects:
|
||||
object_.update()
|
||||
object_.blit(True)
|
||||
|
||||
pygame.display.update()
|
||||
|
||||
def update(self):
|
||||
self.s_.fill(self.bg)
|
||||
|
||||
for object_ in self.l_objects:
|
||||
object_.update()
|
||||
|
||||
for object_ in self.r_objects:
|
||||
object_.blit()
|
||||
|
||||
rs = pygame.transform.scale(self.s_, self.screen_size)
|
||||
self.s.blit(rs, [0, 0])
|
||||
|
||||
for object_ in self.nr_objects:
|
||||
object_.blit()
|
||||
|
||||
for object_ in self.d_objects:
|
||||
object_.progress()
|
||||
|
||||
for object_ in self.c_objects:
|
||||
object_.input(self.mouse_pos, self.clicked)
|
||||
|
||||
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):
|
||||
self.update()
|
||||
self.multiscene.s.blit(self.s, self.multiscene.matrix @ self.position)
|
||||
|
||||
def progress(self):
|
||||
pass
|
||||
|
||||
def get_i_objects(self):
|
||||
return [[self.i_objects, self.mouse_pos]]
|
||||
|
||||
def get_info_for_light_objects(self, position):
|
||||
s = self
|
||||
positions = [position]
|
||||
matrices = [self.matrix]
|
||||
|
||||
while s.multiscene is not None:
|
||||
positions.append(s.position)
|
||||
s = s.multiscene
|
||||
matrices.append(s.matrix)
|
||||
|
||||
transformed_position = a([0., 0.])
|
||||
for p, m in zip(positions, matrices):
|
||||
transformed_position += a(m @ p)
|
||||
|
||||
return s.s, transformed_position
|
||||
|
||||
def sort_objects(self, *args):
|
||||
for object_ in args:
|
||||
for object_tag in object_.object_type.split("_"):
|
||||
if object_tag == "r":
|
||||
self.r_objects.append(object_)
|
||||
elif object_tag == "nr":
|
||||
self.nr_objects.append(object_)
|
||||
elif object_tag == "d":
|
||||
self.d_objects.append(object_)
|
||||
elif object_tag == "c":
|
||||
self.c_objects.append(object_)
|
||||
elif object_tag == "i":
|
||||
self.i_objects.append(object_)
|
||||
elif object_tag == "l":
|
||||
self.l_objects.append(object_)
|
||||
elif object_tag in ["scene", "multiscene"]:
|
||||
if self.object_type == "multiscene":
|
||||
self.subscenes.append(object_)
|
||||
else:
|
||||
raise ValueError("Scene/Multiscene object encountered in scene.sort_objects()\n"
|
||||
"Please use Multiscene for this purpose.")
|
56
TuGUI/Objects/Screen.py
Normal file
56
TuGUI/Objects/Screen.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from numpy import array as a
|
||||
import math
|
||||
import pygame
|
||||
|
||||
|
||||
class Screen:
|
||||
def __init__(self, width: float, height: float, screen_size: a):
|
||||
pygame.init()
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.size = a([float(width), float(height)])
|
||||
self.screen_size = a(screen_size)
|
||||
self.matrix = a([
|
||||
[screen_size[0] / width, 0],
|
||||
[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_ = math.sqrt(self.pd)
|
||||
|
||||
self.s_ = pygame.Surface([width, height])
|
||||
self.s = pygame.display.set_mode(screen_size)
|
||||
|
||||
self.center = a([width, height]) / 2
|
||||
|
||||
def resize_screen(self, new_screen_size, subscene=False):
|
||||
self.screen_size = a(new_screen_size)
|
||||
self.matrix = a([
|
||||
[new_screen_size[0] / self.width, 0],
|
||||
[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_ = math.sqrt(self.pd)
|
||||
|
||||
if subscene is False:
|
||||
self.s = pygame.display.set_mode(new_screen_size)
|
||||
else:
|
||||
self.s = pygame.Surface(new_screen_size)
|
||||
|
||||
def save(self, path, size=None):
|
||||
if size is None:
|
||||
pygame.image.save(self.s, path)
|
||||
else:
|
||||
surface = pygame.Surface(size)
|
||||
|
||||
surface.blit(self.s, [0, 0])
|
||||
|
||||
pygame.image.save(surface, path)
|
17
TuGUI/Objects/nr_objects/Circle.py
Normal file
17
TuGUI/Objects/nr_objects/Circle.py
Normal file
@@ -0,0 +1,17 @@
|
||||
import pygame.draw
|
||||
|
||||
|
||||
class Circle:
|
||||
|
||||
object_type = "nr"
|
||||
|
||||
def __init__(self, center, radius, color, scene):
|
||||
self.center = center
|
||||
self.radius = radius
|
||||
self.color = color
|
||||
self.scene = scene
|
||||
|
||||
def blit(self):
|
||||
pygame.draw.circle(self.scene.s, self.color,
|
||||
self.scene.matrix @ self.center,
|
||||
self.radius * self.scene.pd_)
|
22
TuGUI/Objects/nr_objects/Ellipse.py
Normal file
22
TuGUI/Objects/nr_objects/Ellipse.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import pygame
|
||||
|
||||
|
||||
class Ellipse:
|
||||
|
||||
object_type = "nr"
|
||||
|
||||
def __init__(self, center, a, b, color, scene):
|
||||
self.center = center
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.color = color
|
||||
self.scene = scene
|
||||
|
||||
def blit(self):
|
||||
a_ = self.a * self.scene.pd_
|
||||
b_ = self.b * self.scene.pd_
|
||||
center_ = self.scene.matrix @ self.center
|
||||
center_ = [center_[0] - a_, center_[1] - b_]
|
||||
|
||||
pygame.draw.ellipse(self.scene.s, self.color,
|
||||
pygame.Rect(center_, [a_ * 2, b_ * 2]))
|
52
TuGUI/Objects/nr_objects/EquilateralTriangle.py
Normal file
52
TuGUI/Objects/nr_objects/EquilateralTriangle.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from numpy import array as a
|
||||
import pygame
|
||||
import math
|
||||
|
||||
|
||||
class EquilateralTriangle:
|
||||
|
||||
object_type = "nr"
|
||||
|
||||
def __init__(self, position, side_length, rotation, color, scene, width=0):
|
||||
self.position = position
|
||||
self.side_length = side_length
|
||||
self.rotation = rotation
|
||||
self.color = color
|
||||
self.scene = scene
|
||||
self.width = width
|
||||
self.rotation_point = complex(math.cos(rotation), math.sin(rotation))
|
||||
|
||||
self.pd_ = self.scene.pd_
|
||||
|
||||
self.points = a([
|
||||
complex(0, self.side_length),
|
||||
complex(self.side_length, self.side_length),
|
||||
complex(self.side_length * 0.5,
|
||||
self.side_length - math.sqrt(self.side_length ** 2 - (self.side_length * 0.5) ** 2))
|
||||
])
|
||||
self.points -= complex(self.side_length * 0.5, self.side_length * 0.5)
|
||||
self.points *= self.rotation_point * self.pd_
|
||||
self.points += complex(self.side_length * 0.5, self.side_length * 0.5)
|
||||
rescaled_position = self.scene.matrix @ self.position
|
||||
self.points += complex(rescaled_position[0], rescaled_position[1])
|
||||
self.points = [[point.real, point.imag] for point in self.points]
|
||||
|
||||
def blit(self):
|
||||
if self.pd_ != self.scene.pd_:
|
||||
self.pd_ = self.scene.pd_
|
||||
|
||||
self.points = a([
|
||||
complex(0, self.side_length),
|
||||
complex(self.side_length, self.side_length),
|
||||
complex(self.side_length * 0.5,
|
||||
self.side_length - math.sqrt(self.side_length ** 2 - (self.side_length * 0.5) ** 2))
|
||||
])
|
||||
self.points -= complex(self.side_length * 0.5, self.side_length * 0.5)
|
||||
self.points *= self.rotation_point * self.pd_
|
||||
self.points += complex(self.side_length * 0.5, self.side_length * 0.5)
|
||||
rescaled_position = self.scene.matrix @ self.position
|
||||
self.points += complex(rescaled_position[0], rescaled_position[1])
|
||||
self.points = [[point.real, point.imag] for point in self.points]
|
||||
|
||||
pygame.draw.polygon(self.scene.s, self.color, self.points, self.width)
|
||||
|
52
TuGUI/Objects/nr_objects/Image.py
Normal file
52
TuGUI/Objects/nr_objects/Image.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from numpy import array as a
|
||||
import numpy as np
|
||||
import pygame
|
||||
import copy
|
||||
|
||||
|
||||
class Image:
|
||||
|
||||
object_type = "nr"
|
||||
|
||||
def __init__(self, center, scalar, path, scene):
|
||||
self.center = center
|
||||
self.scalar = scalar
|
||||
self.path = path
|
||||
self.scene = scene
|
||||
self.pd_ = self.scene.pd_
|
||||
|
||||
self.image = pygame.image.load(self.path).convert()
|
||||
self.image = pygame.transform.scale(self.image,
|
||||
self.to_ints((a(self.image.get_size()) * self.scalar).tolist()))
|
||||
|
||||
self.size = a(self.image.get_size(), dtype=np.float64)
|
||||
self.sides_ratio = self.size[0] / self.size[1]
|
||||
|
||||
self.rescaled_size = copy.copy(self.size)
|
||||
if self.scene.matrix[1, 1] - self.scene.matrix[0, 0] / self.sides_ratio >= 0:
|
||||
self.rescaled_size *= self.scene.matrix[0, 0]
|
||||
else:
|
||||
self.rescaled_size *= self.scene.matrix[1, 1]
|
||||
|
||||
self.rescaled_image = pygame.transform.scale(self.image, self.to_ints((self.size * self.pd_).tolist()))
|
||||
|
||||
def blit(self):
|
||||
|
||||
if self.pd_ != self.scene.pd_:
|
||||
self.pd_ = self.scene.pd_
|
||||
self.rescaled_size = copy.copy(self.size)
|
||||
if self.scene.matrix[1, 1] - self.scene.matrix[0, 0] / self.sides_ratio >= 0:
|
||||
self.rescaled_size *= self.scene.matrix[0, 0]
|
||||
else:
|
||||
self.rescaled_size *= self.scene.matrix[1, 1]
|
||||
|
||||
self.rescaled_image = pygame.transform.scale(self.image, self.to_ints((self.size * self.pd_).tolist()))
|
||||
|
||||
self.scene.s.blit(self.rescaled_image, self.scene.matrix @ self.center)
|
||||
|
||||
@staticmethod
|
||||
def to_ints(iterable):
|
||||
for i in range(len(iterable)):
|
||||
iterable[i] = int(iterable[i])
|
||||
|
||||
return iterable
|
17
TuGUI/Objects/nr_objects/Line.py
Normal file
17
TuGUI/Objects/nr_objects/Line.py
Normal file
@@ -0,0 +1,17 @@
|
||||
import pygame.draw
|
||||
|
||||
|
||||
class Line:
|
||||
|
||||
object_type = "nr"
|
||||
|
||||
def __init__(self, a, b, width, color, scene):
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.width = width
|
||||
self.color = color
|
||||
self.scene = scene
|
||||
|
||||
def blit(self):
|
||||
pygame.draw.line(self.scene.s, self.color, self.scene.matrix @ self.a, self.scene.matrix @ self.b,
|
||||
max(1, int(self.width * self.scene.pd)))
|
35
TuGUI/Objects/nr_objects/Text.py
Normal file
35
TuGUI/Objects/nr_objects/Text.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import pygame
|
||||
|
||||
|
||||
class Text:
|
||||
|
||||
object_type = "nr"
|
||||
|
||||
def __init__(self, position, text, font_size, color, scene, font_name="calibri", bold=True):
|
||||
self.position = position
|
||||
self.text = text
|
||||
self.font_size = font_size
|
||||
self.font_name = font_name
|
||||
self.bold = bold
|
||||
self.color = color
|
||||
self.scene = scene
|
||||
self.scalar = self.scene.matrix[0, 0]
|
||||
|
||||
self.font = pygame.font.SysFont(self.font_name, max(1, int(self.font_size * self.scalar)), self.bold)
|
||||
self.rendered_text = self.font.render(self.text, False, self.color)
|
||||
|
||||
self.blit_position = self.scene.matrix @ self.position
|
||||
self.blit_position[0] -= self.rendered_text.get_width() / 2
|
||||
self.blit_position[1] -= self.rendered_text.get_height() / 2
|
||||
|
||||
def blit(self):
|
||||
if self.scalar != self.scene.matrix[0, 0]:
|
||||
self.scalar = self.scene.matrix[0, 0]
|
||||
self.font = pygame.font.SysFont(self.font_name, max(1, int(self.font_size * self.scalar)), self.bold)
|
||||
self.rendered_text = self.font.render(self.text, False, self.color)
|
||||
|
||||
self.blit_position = self.scene.matrix @ self.position
|
||||
self.blit_position[0] -= self.rendered_text.get_width() / 2
|
||||
self.blit_position[1] -= self.rendered_text.get_height() / 2
|
||||
|
||||
self.scene.s.blit(self.rendered_text, self.blit_position)
|
@@ -0,0 +1,39 @@
|
||||
import math
|
||||
import pygame
|
||||
|
||||
|
||||
class RopeInteractiveDot:
|
||||
|
||||
object_type = "nr_c"
|
||||
|
||||
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 * self.scene.pd_)
|
||||
|
||||
def input(self, mouse_pos, clicked):
|
||||
self.position = mouse_pos
|
||||
|
||||
if clicked:
|
||||
for object_batch in self.scene.get_i_objects():
|
||||
rmp = object_batch[1] # relative mouse position
|
||||
for object_ in object_batch[0]:
|
||||
if object_.__class__.__name__ == "Rope":
|
||||
for node in object_.nodes:
|
||||
if node.locked is False:
|
||||
if math.sqrt(sum((node.position - rmp) ** 2)) < self.forcefield_range:
|
||||
force_vector = node.position - rmp
|
||||
full_force_vector = (force_vector / math.sqrt(sum(force_vector ** 2))) \
|
||||
* self.forcefield_range
|
||||
force_vector = full_force_vector - force_vector
|
||||
force_vector /= self.forcefield_range / self.force
|
||||
|
||||
node.position += force_vector
|
||||
|
||||
|
105
TuGUI/Objects/nr_objects/dynamic_objects/Rope.py
Normal file
105
TuGUI/Objects/nr_objects/dynamic_objects/Rope.py
Normal file
@@ -0,0 +1,105 @@
|
||||
from numpy import array
|
||||
import pygame
|
||||
import math
|
||||
|
||||
|
||||
class Rope:
|
||||
|
||||
object_type = "nr_d_i"
|
||||
|
||||
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=2, start_angle=1,
|
||||
balance_amount=10, 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.balance_amount = balance_amount
|
||||
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(self.balance_amount):
|
||||
for connection in self.connections:
|
||||
connection.balance()
|
||||
|
||||
def blit(self):
|
||||
if self.pd_ != self.scene.pd_:
|
||||
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,
|
||||
max(1, int(self.rescaled_rope_width)))
|
||||
|
||||
for node in self.nodes:
|
||||
pygame.draw.circle(self.scene.s, self.node_color, self.scene.matrix @ node.position,
|
||||
max(1, self.rescaled_nodes_r))
|
||||
|
||||
@staticmethod
|
||||
def to_ints(iterable):
|
||||
for i in range(len(iterable)):
|
||||
iterable[i] = int(iterable[i])
|
||||
|
||||
return iterable
|
@@ -0,0 +1,82 @@
|
||||
import math
|
||||
import random
|
||||
import numpy as np
|
||||
from numpy import array
|
||||
from pygame.draw import circle
|
||||
|
||||
|
||||
class LuminousCircleEffect:
|
||||
|
||||
object_type = "nr_l"
|
||||
|
||||
def __init__(self, position, r, color, scene, circles_n=20, point_speed=0.02, movement_stability=5):
|
||||
self.position = position
|
||||
self.r = r
|
||||
self.color = color
|
||||
self.scene = scene
|
||||
self.circles_n = circles_n
|
||||
self.point_speed = point_speed
|
||||
self.point_speed_inverse = 1 / self.point_speed
|
||||
self.movement_stability = movement_stability
|
||||
|
||||
self.point_position = array([0., 0.])
|
||||
self.point_velocity = array([0., 0.])
|
||||
|
||||
def update(self):
|
||||
self.point_position += self.point_velocity
|
||||
|
||||
a = math.sqrt(sum(self.point_position ** 2))
|
||||
|
||||
if a > 1:
|
||||
self.point_position /= a
|
||||
a = 1
|
||||
|
||||
b = 1 - a
|
||||
c = (0.5 * a) + b
|
||||
d = math.sqrt((c ** 2) - ((a * 0.5) ** 2))
|
||||
|
||||
if a == 0:
|
||||
rotation_point = complex(1, 0)
|
||||
else:
|
||||
normalized_point_position = self.point_position / a
|
||||
rotation_point = complex(*normalized_point_position)
|
||||
|
||||
delta = random.uniform(0, math.tau)
|
||||
m = max(random.uniform(0, 1), random.uniform(0, 1))
|
||||
|
||||
point_position = complex(math.cos(delta) * m * c, math.sin(delta) * m * d) * rotation_point
|
||||
point_position = array([point_position.real, point_position.imag])
|
||||
|
||||
self.point_velocity *= self.movement_stability * self.point_speed_inverse
|
||||
self.point_velocity += point_position - self.point_position
|
||||
self.point_velocity /= math.sqrt(sum(self.point_velocity ** 2))
|
||||
self.point_velocity *= self.point_speed
|
||||
|
||||
def blit(self, light_blit=False):
|
||||
if light_blit:
|
||||
s, transformed_position = self.scene.get_info_for_light_objects(self.position)
|
||||
|
||||
rescaled_r = self.r * self.scene.pd_
|
||||
|
||||
x = np.linspace(0, self.point_position[0], self.circles_n) * rescaled_r
|
||||
y = np.linspace(0, self.point_position[1], self.circles_n) * rescaled_r
|
||||
r = np.linspace(rescaled_r, 0, self.circles_n)
|
||||
|
||||
c = [np.linspace(value, 255, self.circles_n) for value in self.color]
|
||||
|
||||
for i in range(self.circles_n - 1):
|
||||
circle(s, (c[0][i], c[1][i], c[2][i]),
|
||||
transformed_position + array([x[i], y[i]]), r[i])
|
||||
else:
|
||||
rescaled_r = self.r * self.scene.pd_
|
||||
transformed_position = self.scene.matrix @ self.position
|
||||
|
||||
x = np.linspace(0, self.point_position[0], self.circles_n) * rescaled_r
|
||||
y = np.linspace(0, self.point_position[1], self.circles_n) * rescaled_r
|
||||
r = np.linspace(rescaled_r, 0, self.circles_n)
|
||||
|
||||
c = [np.linspace(value, 255, self.circles_n) for value in self.color]
|
||||
|
||||
for i in range(self.circles_n - 1):
|
||||
circle(self.scene.s, (c[0][i], c[1][i], c[2][i]),
|
||||
transformed_position + array([x[i], y[i]]), r[i])
|
16
TuGUI/Objects/r_objects/Rect.py
Normal file
16
TuGUI/Objects/r_objects/Rect.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import pygame.draw
|
||||
|
||||
|
||||
class Rect:
|
||||
|
||||
object_type = "r"
|
||||
|
||||
def __init__(self, pos, size, color, scene):
|
||||
self.pos = pos
|
||||
self.size = size
|
||||
self.color = color
|
||||
self.rect = pygame.Rect(self.pos, self.size)
|
||||
self.scene = scene
|
||||
|
||||
def blit(self):
|
||||
pygame.draw.rect(self.scene.s_, self.color, self.rect)
|
38
TuGUI/Sample_Scenes/BasicMultiscene.py
Normal file
38
TuGUI/Sample_Scenes/BasicMultiscene.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from TuGUI.Objects.Multiscene import Multiscene
|
||||
from TuGUI.Sample_Scenes.BasicScene import BasicScene
|
||||
from numpy import array as a
|
||||
|
||||
from TuGUI.Objects.nr_objects.Line import Line
|
||||
|
||||
|
||||
class BasicMultiscene(Multiscene):
|
||||
def __init__(self, scene_size):
|
||||
|
||||
self.s__size = [600, 400]
|
||||
|
||||
super().__init__(self.s__size[0], self.s__size[1], scene_size)
|
||||
|
||||
s0 = BasicScene([200, 400])
|
||||
|
||||
s1 = BasicScene([400, 400])
|
||||
s1.position = a([200, 0])
|
||||
|
||||
l0 = Line(a([200, 0]), a([200, 400]), 10, (255, 100, 100), self)
|
||||
|
||||
self.sort_objects(s0, s1, l0)
|
||||
|
||||
self.i = 0
|
||||
|
||||
def progress(self):
|
||||
if self.i == 1:
|
||||
self.subscenes[0].subscene_size[0] += 1
|
||||
self.subscenes[1].subscene_size[0] -= 1
|
||||
self.subscenes[1].position[0] += 1
|
||||
|
||||
self.nr_objects[0].a[0] += 1
|
||||
self.nr_objects[0].b[0] += 1
|
||||
|
||||
self.resize_subscenes()
|
||||
self.i = 0
|
||||
else:
|
||||
self.i += 1
|
34
TuGUI/Sample_Scenes/BasicScene.py
Normal file
34
TuGUI/Sample_Scenes/BasicScene.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from TuGUI.Objects.Scene import Scene
|
||||
from numpy import array as a
|
||||
|
||||
from TuGUI.Objects.nr_objects.Ellipse import Ellipse
|
||||
from TuGUI.Objects.nr_objects.Circle import Circle
|
||||
from TuGUI.Objects.nr_objects.EquilateralTriangle import EquilateralTriangle
|
||||
from TuGUI.Objects.nr_objects.Image import Image
|
||||
from TuGUI.Objects.nr_objects.Line import Line
|
||||
from TuGUI.Objects.nr_objects.Text import Text
|
||||
from TuGUI.Objects.r_objects.Rect import Rect
|
||||
|
||||
|
||||
class BasicScene(Scene):
|
||||
def __init__(self, scene_size: a, bg=(60, 60, 60)):
|
||||
|
||||
self.s__size = [600, 400]
|
||||
|
||||
super().__init__(self.s__size[0], self.s__size[1], scene_size, bg)
|
||||
|
||||
r0 = Rect(a([0, 0]), a([200, 200]), (160, 160, 160), self)
|
||||
|
||||
l0 = Line(a([100, 300]), a([500, 100]), 3, (255, 100, 100), self)
|
||||
|
||||
c0 = Circle(a([400, 200]), 40, (100, 100, 255), self)
|
||||
|
||||
e0 = Ellipse(a([150, 360]), 60, 20, (100, 255, 100), self)
|
||||
|
||||
t0 = Text(a([100, 50]), "hello world!", 26, (200, 200, 200), self)
|
||||
|
||||
i0 = Image(a([200, 0]), 0.8, "sample_image.png", self)
|
||||
|
||||
triangle0 = EquilateralTriangle(a([500, 300]), 30, 1, (250, 250, 150), self)
|
||||
|
||||
self.sort_objects(r0, l0, c0, e0, t0, i0, triangle0)
|
43
TuGUI/Sample_Scenes/LuminousCircleEffectMultiscene.py
Normal file
43
TuGUI/Sample_Scenes/LuminousCircleEffectMultiscene.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from TuGUI.Objects.Multiscene import Multiscene
|
||||
from TuGUI.Objects.nr_objects.light_objects.LuminousCircleEffect import LuminousCircleEffect
|
||||
from TuGUI.Sample_Scenes.LuminousCircleEffectScene import LuminousCircleEffectScene
|
||||
from numpy import array as a
|
||||
|
||||
from TuGUI.Objects.nr_objects.Line import Line
|
||||
|
||||
|
||||
class LuminousCircleEffectMultiscene(Multiscene):
|
||||
def __init__(self, scene_size):
|
||||
|
||||
self.s__size = [600, 400]
|
||||
|
||||
super().__init__(self.s__size[0], self.s__size[1], scene_size)
|
||||
|
||||
s0 = LuminousCircleEffectScene([200, 400])
|
||||
|
||||
s1 = LuminousCircleEffectScene([400, 400])
|
||||
s1.position = a([200, 0])
|
||||
|
||||
l0 = Line(a([200, 0]), a([200, 400]), 10, (255, 100, 100), self)
|
||||
|
||||
lce0 = LuminousCircleEffect(a([200, 320]), 60, (255, 100, 100), self)
|
||||
|
||||
self.sort_objects(s0, s1, l0, lce0)
|
||||
|
||||
self.i = 0
|
||||
|
||||
def progress(self):
|
||||
if self.i == 1:
|
||||
self.subscenes[0].subscene_size[0] += 1
|
||||
self.subscenes[1].subscene_size[0] -= 1
|
||||
self.subscenes[1].position[0] += 1
|
||||
|
||||
self.nr_objects[0].a[0] += 1
|
||||
self.nr_objects[0].b[0] += 1
|
||||
|
||||
self.l_objects[0].position[0] += 1
|
||||
|
||||
self.resize_subscenes()
|
||||
self.i = 0
|
||||
else:
|
||||
self.i += 1
|
16
TuGUI/Sample_Scenes/LuminousCircleEffectScene.py
Normal file
16
TuGUI/Sample_Scenes/LuminousCircleEffectScene.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from TuGUI.Objects.Scene import Scene
|
||||
from numpy import array as a
|
||||
|
||||
from TuGUI.Objects.nr_objects.light_objects.LuminousCircleEffect import LuminousCircleEffect
|
||||
|
||||
|
||||
class LuminousCircleEffectScene(Scene):
|
||||
def __init__(self, screen_size, bg=(60, 60, 60)):
|
||||
|
||||
s__size = [600, 400]
|
||||
|
||||
super().__init__(*s__size, screen_size, bg)
|
||||
|
||||
lce0 = LuminousCircleEffect(a([300, 200]), 100, (80, 120, 80), self, circles_n=60)
|
||||
|
||||
self.sort_objects(lce0)
|
41
TuGUI/Sample_Scenes/MultisceneInMultiscene.py
Normal file
41
TuGUI/Sample_Scenes/MultisceneInMultiscene.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from TuGUI.Objects.Multiscene import Multiscene
|
||||
from TuGUI.Sample_Scenes.BasicMultiscene import BasicMultiscene
|
||||
from numpy import array as a
|
||||
|
||||
from TuGUI.Objects.nr_objects.Line import Line
|
||||
|
||||
|
||||
class MultisceneInMultiscene(Multiscene):
|
||||
def __init__(self, scene_size):
|
||||
self.s__size = [600, 800]
|
||||
|
||||
super().__init__(self.s__size[0], self.s__size[1], scene_size)
|
||||
|
||||
ms0 = BasicMultiscene([600, 400])
|
||||
|
||||
ms1 = BasicMultiscene([600, 400])
|
||||
ms1.position = a([0, 400])
|
||||
|
||||
l0 = Line(a([0, 400]), a([600, 400]), 12, (100, 100, 255), self)
|
||||
|
||||
self.sort_objects(ms0, ms1, l0)
|
||||
|
||||
self.i = 0
|
||||
|
||||
def progress(self):
|
||||
self.progress_subscenes()
|
||||
|
||||
if self.i == 1:
|
||||
self.subscenes[0].subscene_size[1] += 1
|
||||
self.subscenes[1].subscene_size[1] -= 1
|
||||
self.subscenes[1].position[1] += 1
|
||||
|
||||
self.nr_objects[0].a[1] += 1
|
||||
self.nr_objects[0].b[1] += 1
|
||||
|
||||
self.resize_subscenes()
|
||||
self.i = 0
|
||||
else:
|
||||
self.i += 1
|
||||
|
||||
|
38
TuGUI/Sample_Scenes/RopeMultiscene.py
Normal file
38
TuGUI/Sample_Scenes/RopeMultiscene.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from numpy import array as a
|
||||
|
||||
from TuGUI.Objects.Multiscene import Multiscene
|
||||
from TuGUI.Objects.nr_objects.Line import Line
|
||||
from TuGUI.Sample_Scenes.RopeScene import RopeScene
|
||||
|
||||
|
||||
class RopeMultiscene(Multiscene):
|
||||
def __init__(self, scene_size):
|
||||
|
||||
self.s__size = [800, 400]
|
||||
|
||||
super().__init__(self.s__size[0], self.s__size[1], scene_size)
|
||||
|
||||
s0 = RopeScene([200, 400])
|
||||
|
||||
s1 = RopeScene([600, 400])
|
||||
s1.position = a([200, 0])
|
||||
|
||||
l0 = Line(a([200, 0]), a([200, 400]), 10, (255, 100, 100), self)
|
||||
|
||||
self.sort_objects(s0, s1, l0)
|
||||
|
||||
self.i = 0
|
||||
|
||||
def progress(self):
|
||||
if self.i == 1:
|
||||
self.subscenes[0].subscene_size[0] += 2
|
||||
self.subscenes[1].subscene_size[0] -= 2
|
||||
self.subscenes[1].position[0] += 2
|
||||
|
||||
self.nr_objects[0].a[0] += 2
|
||||
self.nr_objects[0].b[0] += 2
|
||||
|
||||
self.resize_subscenes()
|
||||
self.i = 0
|
||||
else:
|
||||
self.i += 1
|
22
TuGUI/Sample_Scenes/RopeScene.py
Normal file
22
TuGUI/Sample_Scenes/RopeScene.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from TuGUI.Objects.Scene import Scene
|
||||
from numpy import array as a
|
||||
import pygame
|
||||
|
||||
from TuGUI.Objects.nr_objects.dynamic_objects.Rope import Rope
|
||||
from TuGUI.Objects.nr_objects.controllable_objects.RopeInteractiveDot import RopeInteractiveDot
|
||||
|
||||
|
||||
class RopeScene(Scene):
|
||||
def __init__(self, scene_size, bg=(60, 60, 60)):
|
||||
|
||||
self.s__size = [600, 400]
|
||||
|
||||
super().__init__(self.s__size[0], self.s__size[1], scene_size, bg)
|
||||
|
||||
r0 = Rope(a([300, 50]), 200, 20, 2, 2, self)
|
||||
|
||||
rd0 = RopeInteractiveDot(a([0, 0]), 10, (100, 255, 100), 20, 100, self)
|
||||
|
||||
self.sort_objects(r0, rd0)
|
||||
|
||||
pygame.mouse.set_visible(False)
|
16
TuGUI/light_update_sample.py
Normal file
16
TuGUI/light_update_sample.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from numpy import array as a
|
||||
import time
|
||||
|
||||
from TuGUI.Sample_Scenes.LuminousCircleEffectMultiscene import LuminousCircleEffectMultiscene
|
||||
|
||||
screen_size = a([1000, 800])
|
||||
scene = LuminousCircleEffectMultiscene(screen_size)
|
||||
|
||||
|
||||
scene.update()
|
||||
for i in range(400):
|
||||
|
||||
scene.light_update()
|
||||
|
||||
time.sleep(0.05)
|
||||
|
28
TuGUI/main.py
Normal file
28
TuGUI/main.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import pygame.mouse
|
||||
|
||||
from numpy import array as a
|
||||
import time
|
||||
|
||||
from TuGUI.Sample_Scenes.BasicScene import BasicScene
|
||||
|
||||
screen_size = a([200, 500])
|
||||
scene = BasicScene(screen_size)
|
||||
|
||||
mouse_pos = [0, 0]
|
||||
clicked = False
|
||||
|
||||
for i in range(400):
|
||||
scene.resize_screen(screen_size)
|
||||
scene.update()
|
||||
scene.update_mouse_events(pygame.mouse.get_pos(), pygame.mouse.get_pressed(3)[0])
|
||||
scene.progress()
|
||||
|
||||
if i < 150:
|
||||
screen_size[0] += 3
|
||||
elif i < 250:
|
||||
screen_size[1] += 2
|
||||
else:
|
||||
pass
|
||||
screen_size -= 4
|
||||
|
||||
time.sleep(0.1)
|
BIN
TuGUI/sample_image.png
Normal file
BIN
TuGUI/sample_image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
TuGUI/test.png~
Normal file
BIN
TuGUI/test.png~
Normal file
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
Reference in New Issue
Block a user