This commit is contained in:
2021-09-13 20:21:11 +02:00
parent 1e3e7939b0
commit 5b86a84488
26 changed files with 34 additions and 40 deletions

View 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_)

View 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]))

View 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)

View 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

View 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)))

View 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)

View File

@@ -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

View 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

View File

@@ -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])