Another python demo, (enter to toggle between editor and demos, T to switch between demos), added code to delete modules from python VM so they get reloaded properly on code changes.

This commit is contained in:
Bobby Lucero 2024-10-12 19:34:16 -04:00
parent 611b6def6a
commit 29e3ba208e
6 changed files with 175 additions and 1393 deletions

View File

@ -15,8 +15,8 @@ class Blobs(Scene):
def draw(self):
clear(0)
for i in range(128):
for j in range(128):
for i in range(width):
for j in range(height):
c = cos(i / 10) + (sin(j / 10) + 2)
#c2 = cos(i / 5) + sin(j / 5)
pixel(i, j, 2 * c + self.t)

View File

@ -3,7 +3,7 @@ from particles import Particles
from triangles import Triangles
from squares import Squares
from blobs import Blobs
from mechanical import Mechanical
from threeD import ThreeD
# Palette class (inherits from scene)
class Palette(Scene):
@ -29,11 +29,9 @@ class RGBTest(Scene):
self.title = "RGB To Palette"
scenes = [Particles(), Triangles(), Palette(), Squares(), Blobs()]
scenes = [ ThreeD(), Particles(), Squares(), Triangles(), Palette(), Blobs()]
current_scene = 0
KEY_T = 84
switch = False
@ -53,3 +51,6 @@ def update():
if(not scenes[current_scene].paused):
scenes[current_scene].update()
scenes[current_scene].draw()
text("T to change scene", 255, 1,31)

File diff suppressed because it is too large Load Diff

159
python/threeD.py Normal file
View File

@ -0,0 +1,159 @@
from scene import Scene
from triangles import draw_line
import math
# Palette class (inherits from scene)
class ThreeD(Scene):
def __init__(self):
super().__init__()
self.title = "Squares"
self.t = 0
self.x = 0.01
self.y = 0
self.z = 0
self.a = 10
self.b = 28
self.c = 8.0/3.0
self.scale = 5
self.focal_length = 800
self.screen_width = width * 4
self.screen_height = height * 4
self.lines = []
self.points = []
self.gradient = [4, 8, 6, 15, 18, 19, 26, 25, 24, 23, 16, 23, 22, 7, 5]
def update(self):
self.t += 0.00002
if(len(self.points) > 1200):
return
dx = (self.a * (self.y - self.x)) * self.t
dy = (self.x * (self.b - self.z) - self.y) * self.t
dz = (self.x * self.y - self.c * self.z) * self.t
self.x += dx
self.y += dy
self.z += dz
self.points.append((self.x, self.y, self.z))
def line3D(self, x1, y1, z1, x2, y2, z2, c):
self.lines.append(((x1, y1, z1), (x2, y2, z2), c))
def draw(self):
self.lines.clear()
clear(0)
for i in range(len(self.points)):
size = len(self.points)
if(i < size - 1):
x, y, z = self.points[i]
x2, y2, z2 = self.points[i + 1]
x *= self.scale
y *= self.scale
z *= self.scale
x2 *= self.scale
y2 *= self.scale
z2 *= self.scale
self.line3D(x, y, z, x2, y2, z2, self.gradient[int(i / 5) % len(self.gradient)])
self.render_scene(self.focal_length, self.screen_width, self.screen_height, 0, self.t*500, self.t * 200, 0, 0, 300)
def rotate_point(self, x, y, z, angle_x, angle_y, angle_z):
"""Rotates a point around the X, Y, and Z axes."""
# Rotation around the X axis
cos_x, sin_x = math.cos(angle_x), math.sin(angle_x)
y, z = y * cos_x - z * sin_x, y * sin_x + z * cos_x
# Rotation around the Y axis
cos_y, sin_y = math.cos(angle_y), math.sin(angle_y)
x, z = x * cos_y + z * sin_y, -x * sin_y + z * cos_y
# Rotation around the Z axis
cos_z, sin_z = math.cos(angle_z), math.sin(angle_z)
x, y = x * cos_z - y * sin_z, x * sin_z + y * cos_z
return x, y, z
def project_point(self, x, y, z, focal_length, screen_width, screen_height, angle_x, angle_y, angle_z, translate_x, translate_y, translate_z):
x, y, z = self.rotate_point(x, y, z, angle_x, angle_y, angle_z)
# Apply translation
x += translate_x
y += translate_y
z += translate_z
"""Projects a 3D point onto a 2D screen using perspective projection."""
if z == 0:
z = 0.001 # Avoid division by zero
# Perspective projection formula
screen_x = (x * focal_length) / z
screen_y = (y * focal_length) / z
# Translate to screen coordinates (centered)
screen_x += screen_width / 2
screen_y += screen_height / 2
return screen_x, screen_y
def z_sort_lines(self, lines):
"""Sorts lines based on their average Z values for depth ordering."""
return sorted(lines, key=lambda line: (line[0][2] + line[1][2]) / 2, reverse=True)
def draw_3d_line(self, x1, y1, z1, x2, y2, z2, focal_length, screen_width, screen_height, color, angle_x, angle_y, angle_z, translate_x, translate_y, translate_z):
"""Draws a 3D line projected onto a 2D screen."""
# Project the endpoints
screen_x1, screen_y1 = self.project_point(x1, y1, z1, focal_length, screen_width, screen_height, angle_x, angle_y, angle_z, translate_x, translate_y, translate_z)
screen_x2, screen_y2 = self.project_point(x2, y2, z2, focal_length, screen_width, screen_height, angle_x, angle_y, angle_z, translate_x, translate_y, translate_z)
# Use the renderer to draw the line on the screen
draw_line(int(screen_x1) / 4, int(screen_y1) / 4, int(screen_x2) / 4, int(screen_y2) / 4, color)
def render_scene(self, focal_length, screen_width, screen_height, angle_x, angle_y, angle_z, translate_x, translate_y, translate_z):
"""Renders the 3D lines in the scene with perspective projection and Z-sorting."""
# Sort the lines by Z value (depth)
sorted_lines = self.z_sort_lines(self.lines)
i = 0
# Draw each line
for line in sorted_lines:
(x1, y1, z1), (x2, y2, z2), c = line
self.draw_3d_line(x1, y1, z1, x2, y2, z2, focal_length, screen_width, screen_height, c, angle_x, angle_y, angle_z, translate_x, translate_y, translate_z)
i += 1
# Example usage
# renderer is an object that has a draw_line(x1, y1, x2, y2) function
liines = [
((-50, -50, -50), (50, -50, -50)),
((50, -50, -50), (50, 50, -50)),
((50, 50, -50), (-50, 50, -50)),
((-50, 50, -50), (-50, -50, -50)),
((-50, -50, 50), (50, -50, 50)),
((50, -50, 50), (50, 50, 50)),
((50, 50, 50), (-50, 50, 50)),
((-50, 50, 50), (-50, -50, 50)),
((-50, -50, -50), (-50, -50, 50)),
((50, -50, -50), (50, -50, 50)),
((50, 50, -50), (50, 50, 50)),
((-50, 50, -50), (-50, 50, 50)),
]
# Assuming you have a renderer object

View File

@ -14,7 +14,7 @@
EditorState::EditorState(pkpy::VM *vm, Graphics *graphics) : m_vm(vm), m_graphics(graphics){
m_pythonTokenizer = new PythonTokenizer();
std::string randomSource = Pycron::loadFileToString("../python/particles.py");
std::string randomSource = Pycron::loadFileToString("../python/threeD.py");
//randomSource = Pycron::loadFileToString("../src/States/Editor/EditorState.cpp");
m_editorFrame = m_graphics->loadImage("../resources/EditorFrame.png");

View File

@ -11,6 +11,7 @@
GameState::GameState(pkpy::VM* vm, Graphics* graphics) :m_vm(vm), m_graphics(graphics){
m_updateFunction = nullptr;
m_previousError = "";
}
void GameState::Draw() {
@ -28,10 +29,15 @@ void GameState::Draw() {
void GameState::OnEnter() {
m_graphics->Clear(0);
PreProcessScripts();
}
void GameState::OnExit() {
for(const auto& pair : m_vm->_lazy_modules){
m_vm->_modules.del(pair.first);
}
m_vm->_lazy_modules.clear();
m_updateFunction = m_vm->None;
}
@ -80,6 +86,8 @@ std::unordered_map<std::string, std::string> GameState::readPythonFiles(const st
}
void GameState::loadPythonModules(std::unordered_map<std::string, std::string> &fileContents) {
m_vm->_lazy_modules.clear();
for(const auto& pair : fileContents){
try{
if(pair.first != MAIN_FILE){