111 lines
3.7 KiB
Python

from objects import *
from useful import *
from threading import Thread
import pygame
def main():
try:
print("Initializing...")
data.multithreading = settings.useMultithreading
data.running = True
pygame.init()
pygame.display.set_mode(settings.resolution)
data.display = pygame.display.get_surface()
data.pixelScale = int(pow(2, settings.maxPixelScale - 1))
if settings.useMultithreading: beginMultithreading()
print("Ready")
minPixelScale = int(pow(2, settings.minPixelScale - 1))
while data.running and data.pixelScale >= minPixelScale:
render()
if not data.multithreading: pygame.display.update()
getInputs()
data.pixelScale /= 2
data.multithreading = False
pygame.display.update()
while data.running:
getInputs()
finally:
print("Closing...")
if settings.useMultithreading: endMultithreading()
pygame.quit()
# begins any threads required for multithreading
def beginMultithreading():
print("Beginning multithreading")
data.monitor = Thread(target=m_Monitor)
data.monitor.start()
# kills all threads other than the main thread
def endMultithreading():
print("Ending multithreading")
data.multithreading = False
data.monitor.join()
# a monitor to constantly update the screen.
# only used in multithreading.
def m_Monitor():
while data.multithreading:
pygame.display.update()
# gets pygame inputs
def getInputs():
for event in pygame.event.get():
if event.type == pygame.QUIT:
data.running = False
return
# renders a screen of fractal
def render():
for y in range(int(settings.resolution[1] / data.pixelScale)):
if data.multithreading:
pygame.draw.rect(data.display, (0, 0, 0), (0, y * data.pixelScale, settings.resolution[0], data.pixelScale))
pygame.draw.rect(data.display, (255, 255, 255), (0, (y + 1) * data.pixelScale, settings.resolution[0], data.pixelScale))
for x in range(int(settings.resolution[0] / data.pixelScale)):
unit = pixelsToUnits(x * data.pixelScale, y * data.pixelScale)
pygame.draw.rect(data.display, getColor(unit[0], unit[1]), (x * data.pixelScale, y * data.pixelScale, data.pixelScale, data.pixelScale))
getInputs()
# converts a given display pixel into the proper world coordinates.
# this is where the zoom and offset are factored in.
def pixelsToUnits(x, y):
fX = x / settings.resolution[0]
fY = y / settings.resolution[1]
fX = fX * 2 - 1
fY = fY * 2 - 1
fX *= settings.scale
fY *= settings.scale
fX += settings.offset[0]
fY += settings.offset[1]
return (fX, fY)
# gets a color for a given coordinate.
# this function is just a handler for fractalContains()
def getColor(x, y):
insideColor = (0, 0, 0)
outsideColor = (0, 0, 255)
val = fractalContains(x, y)
if val == -1: return insideColor
percent = val / settings.fractalIterations
percent = sqrt(percent).real
return(outsideColor[0] * percent, outsideColor[1] * percent, outsideColor[2] * percent)
# returns -1 if the point x + yi is contained in the fractal, otherwise
# it returns how many iterations it took to be determined outside.
# this is also where you can modify the recursive function
def fractalContains(x, y):
c = complex(x, y)
x = c
for i in range(settings.fractalIterations):
x = x * x + c
if x.__abs__() >= 2: return i
return -1
if __name__ == "__main__": main()