# JClock VIII

Interpreting the hour hand on a clock as a two-dimensional object on a plane, the hand’s tip can be seen as a complex number.
This clock converts the hour hand’s position into a complex number, sets the number’s length to the current minutes and displays it in the form $a + b \cdot i$.
The angle $\phi$ is determined by the hours passed ( $\frac{2 \cdot \pi \cdot \text{hour}}{12} = \frac{\pi \cdot \text{hour}}{6}$) but has to be slightly modified because a complex number starts at the horizontal axis and turns anti-clockwise whilst an hour hand starts at the vertical axis and turns — as the name implies — clockwise.
Thus $\phi = (2 \cdot \pi - \frac{\pi \cdot \text{hour}}{6}) + \frac{\pi}{2} = (\frac{15 - \text{hour}}{6}) \cdot \pi$.
The complex number’s length is simply determined by the minutes passed. Because the length must not be equal to $0$, I simply add 1. $|z| = k = \text{minute} + 1$.
Lastly, to convert a complex number in the form $k \cdot e^{\phi \cdot i}$ into the form $a + b \cdot i$, I use the formula $k \cdot (\cos{\phi} + \sin{\phi} \cdot i) = a + b \cdot i$. # Python 2.7.7 Code
# Pygame 1.9.1 (for Python 2.7.7)
# Jonathan Frech 29th of July, 2016

# Python 2.7.7 Code
# Pygame 1.9.1 (for Python 2.7.7)
# Jonathan Frech 29th of July, 2016

# importing needed modules
import pygame, sys, time, math, os, datetime
pygame.font.init()

""" CLASSES """
# screen class
class Screen():
def __init__(self, size = None):
if not size:
self.size = [G.Width, G.Height]
else:
self.size = size

self.surface = pygame.Surface(self.size)

def swap(self):
pass

def render(self, surface):
pass

def tick(self):
pass

def handle(self, event):
pass

# main screen
class mainScreen(Screen):
def __init__(self):
Screen.__init__(self)

self.font = pygame.font.Font(pygame.font.match_font("Courier"), 50)

def render(self, surface):
self.surface.fill([10, 10, 10])

now = datetime.datetime.now()
hour = now.hour % 12
minute = now.minute

phi = ((15 - hour) / 6.) * math.pi
k = minute + 1

a = round( math.cos(phi) * k, 3)
b = round( math.sin(phi) * k, 3)

#s = str(k) + " * e**(" + str(phi) + "*i)"
s = str(a) + [" + ", " - "][b<0] + str(abs(b)) + "i"
print s

txt = self.font.render(s, True, [255, 255, 255])
rct = txt.get_rect()
pos = [(G.Width-rct.right)/2, (G.Height-rct.bottom)/2]
self.surface.blit(txt, pos)

surface.blit(self.surface, [0, 0])

""" GAME """
# game class
class Game():
def __init__(self):
# screen (class)
self.screenname = "main"

# screen (window)
self.Width, self.Height = 600, 300
self.Size = [self.Width, self.Height]
self.Screen = pygame.display.set_mode(self.Size)

# running variables
self.ticks = 0
self.running = True

# functions
pygame.display.set_caption("JClock VIII")

# further initialization
def init(self):
self.screens = {
"main": mainScreen()
}

# get the screen based on name
def screen(self):
if self.screenname in self.screens:
return self.screens[self.screenname]
else:
return Screen()

def swapscreen(self, name = ""):
self.screenname = name
self.screen().swap()

# tick function
def tick(self):
# handle events
for event in pygame.event.get():

# quit when window is closed
if event.type == pygame.QUIT:
self.quit()

# handle key presses
if event.type == pygame.KEYDOWN:
# F12 quits
if event.key == pygame.K_F12:
self.quit()

# F1 screenshots
if event.key == pygame.K_F1:
self.screenshot()

# handle screen
self.screen().handle(event)

# tick screen
self.screen().tick()

# render function
def render(self):
# fill
self.Screen.fill([0, 0, 0])

#render screen
self.screen().render(self.Screen)

# flip
pygame.display.flip()

# quits
def quit(self):
self.running = False

# takes a screenshot
def screenshot(self):
# define path
path = os.getcwd() + "/out/"

# try to save
try:
# create path
if not os.path.isdir(path):
os.mkdir(path)

# define name
now = datetime.datetime.now()
name = "img" + str(len(os.listdir(path))) + " (" + str(now.hour) + "h " + str(now.minute) + "m).png"

# save image
pygame.image.save(self.Screen, path + name)

# save failed somehow
except:
pass

# run function (uses tick() and render())
def run(self):
ticksPerSecond = 60
lastTime = time.time() * 1000000000
nsPerTick =  1000000000.0 / float(ticksPerSecond)

ticks = 0
frames = 0

lastTimer = time.time() * 1000
delta = 0.0

while self.running:
now = time.time() * 1000000000
delta += float(now - lastTime) / float(nsPerTick)
lastTime = now
shouldRender = False

while delta >= 1:
ticks += 1
self.ticks += 1
self.tick()
delta -= 1
shouldRender = True

if shouldRender:
frames += 1
self.render()

if time.time() * 1000 - lastTimer >= 1000:
lastTimer += 1000

frames = 0
ticks = 0

# start game
G = Game()
G.init()
G.run()

This site uses Akismet to reduce spam. Learn how your comment data is processed.