Retrogamecoding and Basicprogramming Forum

Retrogamecoding(.org) => Examples => Topic started by: Cybermonkey on 01. January 2016, 18:33:54

Title: Analog (with integrated digital) clock
Post by: Cybermonkey on 01. January 2016, 18:33:54
This was already posted on the old forum but since that is gone ... I just added a digital display to the analog clock.
Feel free to port this to your preferred language.
Code: [Select]
-- analog clock
-- converted to PulsarLua by Cybermonkey
require "scancodes"

win = openwindow ("Analog Clock",-1,-1,350,350)
setactivewindow (win)
setframetimer (60)
page = 0
xcenter = windowwidth()/2
ycenter = windowheight()/2

backcolor  (0,90,82,255)
textsize (2)
texttype (2)

repeat
cls()
key = getkey()

color (0,0,0,255)

fillcircle (xcenter, ycenter, 150)

color  (50,255,50,255)

for i=1, 11 do
if (i~=3) and (i~=6) and (i~=9) then
fillcircle (round(math.cos((i * 30) * math.pi / 180 - math.pi / 2) * 140 + xcenter), round(math.sin((i * 30) * math.pi / 180 - math.pi / 2) * 140 + ycenter), 3)
end
end

color  (255,0,0,255)

drawtext ("9",xcenter - 145, ycenter - 5)
drawtext ("3",xcenter + 135, ycenter - 5)
drawtext ("12",xcenter - 15, ycenter - 145)
drawtext ("6",xcenter - 5, ycenter + 130)

color (0,255,0,255)
drawtext (time(),xcenter-60 , ycenter -70)

second = os.date ("%S")
minute = os.date ("%M")
hour = os.date ("%H")
xsecond = round(math.cos(second * math.pi / 30 - math.pi / 2) * 120 + xcenter)
ysecond = round(math.sin(second * math.pi / 30 - math.pi / 2) * 120 + ycenter)
xminute = round(math.cos(minute * math.pi / 30 - math.pi / 2) * 100 + xcenter)
yminute = round(math.sin(minute * math.pi / 30 - math.pi / 2) * 100 + ycenter)
xhour = round(math.cos((hour * 30 + minute / 2) * math.pi / 180 - math.pi / 2) * 80 + xcenter)
yhour = round(math.sin((hour * 30 + minute / 2) * math.pi / 180 - math.pi / 2) * 80 + ycenter)

color (0,255,0,255)
line (xcenter, ycenter, xsecond, ysecond)
color (0,0,255,255)
line (xcenter, ycenter - 1, xminute, yminute)
line (xcenter - 1, ycenter, xminute, yminute)
color (255,0,0,255)
line (xcenter, ycenter - 1, xhour, yhour)
line (xcenter - 1, ycenter, xhour, yhour)

sync()
until key == SCANCODE_ESCAPE
closewindow (win)
closeapplication()
Title: Re: Analog (with integrated digital) clock
Post by: ZXDunny on 09. January 2016, 17:40:47
I remember messing around with this one back on the old forum!

Here's my updated version, in SpecBAS natch:

Code: [Select]
10 REM Analog Clock with sweep-second-hand
20 PALETTE 8,0,90,82: SCREEN LOCK: DEGREES: OPTION "base",0
30 xc=SCRw/2,yc=SCRh/2: GO SUB 190
40 REM Draw the clock face
50 CLS : CIRCLE INK 0;xc,yc,150 FILL
60 FOR f=0 TO 59: CIRCLE INK 3;xc+COS(6*f)*136,yc+SIN(6*f)*136,1.5 FILL: NEXT f
70 FOR f=0 TO 11: x=xc+COS(30*f)*136,y=yc+SIN(30*f)*136: IF f MOD 3 THEN s$=STR$((f+3) MOD 12): PRINT PAPER 0;INK 4;MOVE x-4*LEN s$,y-4;INK 4;s$ ELSE s$=STR$ IIF(f=9,12,(f+3) MOD 12): PRINT PAPER 0;MOVE x-(8*LEN s$),y-8;SCALE 2,2;INK 10;s$
80 NEXT f
90 REM Calculate the angles of the hands
100 t=TIME,s=6*SECONDS t+MILLISECONDS t*.006,m=6*MINUTES t+(6*(s/360)),h=30*HOUR t+(30*(m/360)),s-=90,m-=90,h-=90
110 a$=TIME$(TIME,"hh:mm:ss"): GO SUB 250
120 REM Draw the hands
130 POLYGON INK 10;xc+COS(m-90)*3,yc+SIN(m-90)*3 TO xc+COS(m)*100,yc+SIN(m)*100 TO xc+COS(m+90)*3,yc+SIN(m+90)*3 FILL
140 POLYGON INK 9;xc+COS(h-90)*2,yc+SIN(h-90)*2 TO xc+COS(h)*80,yc+SIN(h)*80 TO xc+COS(h+90)*2,yc+SIN(h+90)*2 FILL
150 POLYGON INK 12;xc+COS(s-90)*1.5,yc+SIN(s-90)*1.5 TO xc+COS(s)*120,yc+SIN(s)*120 TO xc+COS(s+90)*1.5,yc+SIN(s+90)*1.5 FILL
160 CIRCLE INK 11;xc,yc,8 FILL : CIRCLE INK 0;xc,yc,4 FILL
170 IF INKEY$="" THEN WAIT SCREEN : GO TO 50
180 REM Set up LED segments
190 sw=1,svh=6,shw=4
200 vd$="sx,sy TO sx+sw,sy+sw TO sx+sw,sy+svh+sw TO sx,sy+sw+svh+sw TO sx-sw,sy+svh+sw TO sx-sw,sy+sw",hd$="sx,sy TO sx+sw,sy-sw TO sx+sw+shw,sy-sw TO sx+sw+shw+sw,sy TO sx+sw+shw,sy+sw TO sx+sw,sy+sw"
210 DIM digit$="123456","34","23567","23457","1347","12457","124567","234","1234567","123457" BASE 0: DIM coord$="sw,sw+1","sw+1,sw","sw*3+shw+2,sw+1","sw*3+shw+2,sw*3+svh+3","sw+1,sw*5+svh*2+4","sw,sw*3+svh+3","sw+1,sw*3+svh+2" BASE 1
220 DIM led$(10) BASE 0: FOR f=0 TO 9: b$="": FOR g=1 TO LEN digit$(f): b=VAL digit$(f)(g): b$=b$+REPLACE$("sx=x+"+coord$(b),",",",sy=y+")+":POLYGON "+IIF$(b IN [2,7,5],hd$,vd$)+" FILL:": NEXT g: led$(f)=TOKEN$ b$: NEXT f
230 RETURN
240 REM Draw LED segment string
250 INK 1: x=xc-48,y=yc+64: FOR i=1 TO LEN a$: IF a$(i) IN ["0" TO "9"] THEN EXECUTE led$(VAL a$(i)): x+=shw+sw+sw+6 ELSE IF (s+90) MOD 6<3 THEN RECTANGLE 3+x+sw+shw/2,2+y+sw+svh/2,2,2 FILL: RECTANGLE 3+x+sw+shw/2,2+y+sw+svh*2,2,2 FILL: x+=shw+sw*2+6 ELSE x+=shw+sw*2+6
260 NEXT i: RETURN

(http://s8.postimg.org/q0nr8kjtx/clock.png)

And here's (attached) a small executable-ish... Run the batch file after unpacking :)

D.
Title: Re: Analog (with integrated digital) clock
Post by: Cybermonkey on 13. February 2016, 19:57:44
Now this is also possible with AllegroBASIC v0.6 (I implemented a TIME function - downloads are coming soon).
Code: [Select]
' analog clock
' converted from Pascal to Lua to AllegroBASIC
' by Cybermonkey 2/2016

KEY_ESC          = 59
screen (352,352,"Analog Clock")
setfps (60) ' That's enough ...
PI = 3.141
xcenter = screenwidth/2
ycenter = screenheight/2
paper (0,90,82)
textsize (2)

do
cls
ink (0,0,0)
fillcircle (xcenter, ycenter, 150)
ink (50,255,50)
fillcircle (175,175,3)
for i=1 to 11
  if (i<>3) and (i<>6) and (i<>9) then
    fillcircle (round(cos((i * 30) * PI / 180 - PI / 2) * 140 + xcenter), round(sin((i * 30) * PI / 180 - PI / 2) * 140 + ycenter), 3)
 endif
next

ink (255,0,0)

drawtext (xcenter - 145, ycenter - 5,"9")
drawtext (xcenter + 135, ycenter - 5,"3")
drawtext (xcenter - 15, ycenter - 145,"12")
drawtext (xcenter - 5, ycenter + 130,"6")

ink (0,255,0)

second = val (right (time,2))
hour = val (left (time,2))
minute = val (mid (time,3,2))

xsecond = round(cos(second * PI / 30 - PI / 2) * 120 + xcenter)
ysecond = round(sin(second * PI / 30 - PI / 2) * 120 + ycenter)
xminute = round(cos(minute * PI / 30 - PI / 2) * 100 + xcenter)
yminute = round(sin(minute * PI / 30 - PI / 2) * 100 + ycenter)
xhour = round(cos((hour * 30 + minute / 2) * PI / 180 - PI / 2) * 80 + xcenter)
yhour = round(sin((hour * 30 + minute / 2) * PI / 180 - PI / 2) * 80 + ycenter)

ink (0,255,0)
line (xcenter, ycenter, xsecond, ysecond)
ink (0,0,255)
line (xcenter, ycenter - 1, xminute, yminute)
line (xcenter - 1, ycenter, xminute, yminute)
ink (255,0,0)
line (xcenter, ycenter - 1, xhour, yhour)
line (xcenter - 1, ycenter, xhour, yhour)
ink(255,255,255):textsize (1)
drawtext (xcenter - 30, ycenter + 160,TIME)
textsize (2)
sync
until (keystate (KEY_ESC) = true) or (windowclosed=true)
Title: Re: Analog (with integrated digital) clock
Post by: B+ on 13. September 2016, 03:50:02
Just tested KSINK library in Naalaa with some time functions.

Code: [Select]
' clock.txt [B+=MGA] 2016-09-12
' test using this ksink library and dll

import "ksink.lib"
'needs ksink.dll too in same folder

constant:
XMAX = 400
YMAX = 400
XC = 200
YC = 200
HR# = 4.0
HL1# = 175.0
HL2# = 10.0
HhandR# = 15.0
MhandR# = 8.0
ShandR# = 5.0
HhandL# = 105.0
MhandL# = 150.0
ShandL# = 160.0
visible:

hidden:

set window 100, 40, XMAX, YMAX
set redraw false
Pstart = xy2P(XC, YC)
do
set colori 0
cls
'digital time
set colori 0xffffff
set caret 5, 5
h$ = str(GetHour() + 0)
if len(h$) = 1 then h$ = "0" + h$
m$ = str(GetMinute() + 0) 
if len(m$) = 1 then m$ = "0" + m$
s$ = str(GetSecond() + 0)
if len(s$) = 1 then s$ = "0" + s$
wln h$, ":", m$, ":", s$

'allow esc
set caret 360, 380
wln "esc"

'analog time
'draw hour markers
for i = 0 to 11
'this draws an invisble arm out to hour markers
aHR# = float(i * 30) - 90.0
set colori 0
Pnext = quad(Pstart, 1.0, aHR#, HL1# - 10.0, 1.0)
'use Pnext to locate hour marker starts
set colori 0xffffff
Pnext = quad(Pnext, HR#, aHR#, HL2#, HR#)
next

'draw the clock hands
'account for partial hour and minute passed with fractions
minFrac# = float(GetMinute() % 60) / 60.0
secFrac# = float(GetSecond() % 60) / 60.0

'arm angles 0 degrees is due east, so minus 90 is north = 0 for our clock
aHour# = (float(GetHour() % 12) + minFrac#)  / 12.0  * 360.0 - 90.0
aMin# =  (minFrac# + secFrac# / 60.0) * 360.0 - 90.0
aSec# =  secFrac# * 360.0 - 90.0

'draw arms with slightly different shades of gray
set colori 0xf0f0f0
Pnext = quad(Pstart, HhandR#, aHour#, HhandL#, HhandR# - 6.0)
set colori 0xa0a0a0
Pnext = quad(Pstart, MhandR#, aMin#, MhandL#, MhandR# - 3.5)
set colori 0x707070
Pnext = quad(Pstart, ShandR#, aSec#, ShandL#, ShandR# - 3.0)

'draw a center pin
set colori 0
_fcirc XC, YC, 2

redraw
wait 1
until keydown(27, true)


function quad(pStart, r1#, ang#, lng#, r2#)
'solid fill circles at both ends, use polygon 4 points to fill middle area
'draws from pStart at radius r1 down angle ang for length of leg
'with r2 being the radius at end point
'returns the x, y end point in P form for further pendage drawing

'constants XMAX, YMAX
'needs fcirc(x, y, r)
'needs xy2P(x, y)

'extract x, y start line of circles
  fx# = float(pStart % (XMAX + 1))
fy# = float(pStart) / float(XMAX)
x1# = fx# + r1# * cos(ang# + 90.0)
y1# = fy# + r1# * sin(ang# + 90.0)
x2# = fx# + r1# * cos(ang# - 90.0)
y2# = fy# + r1# * sin(ang# - 90.0)

  xe# = fx# + lng# * cos(ang#)
  ye# = fy# + lng# * sin(ang#)
x3# = xe# + r2# * cos(ang# + 90.0)
y3# = ye# + r2# * sin(ang# + 90.0)
x4# = xe# + r2# * cos(ang# - 90.0)
y4# = ye# + r2# * sin(ang# - 90.0)

_fcirc int(fx#), int(fy#), int(r1#)
  _fcirc int(xe#), int(ye#), int(r2#)
'draw quad fill
draw poly[int(x1#), int(y1#), int(x2#), int(y2#), int(x4#), int(y4#), int(x3#), int(y3#)], true
return xy2P(int(xe#), int(ye#))
endfunc

procedure fcirc(x, y, r)
rsq = r * r
for a = 0 to r
b = int(sqr(float(rsq - a * a)))
x1 = x + a; x2 = x - a; y1 = y - b; y2 = y + b
draw line x1, y1, x1, y2
draw line x2, y1, x2, y2
next
endproc

function xy2P(x, y)
'note uses constants XMAX screen width
return y * (XMAX + 1) + x
endfunc


Title: Re: Analog (with integrated digital) clock
Post by: Mike Lobanovsky on 13. September 2016, 17:48:47
Just wait for the seconds hand to point to 12. :)

Code: [Select]
#Option Strict

#DllImports OpenGL32

#Define GL_LINES &H0001
#Define GL_QUADS &H0007
#Define GL_MODELVIEW &H1700
#Define GL_PROJECTION &H1701

#Include <Include\Windows.inc>
#Include ".\COGLApp1.inc"

Type SYSTEMTIME Align 2
  wYear As Integer * 16
  wMonth As Integer * 16
  wDayOfWeek As Integer * 16
  wDay As Integer * 16
  wHour As Integer * 16
  wMinute As Integer * 16
  wSecond As Integer * 16
  wMilliseconds As Integer * 16
End Type

Dim width, height, Viewer

Sub Main()
  Viewer = New COGLApp1("-=:: OpenGL Boom O'Clock ::=-", _
  AddressOf Renderer, AddressOf Messenger, NULL, 600)
 
  glLineWidth(!5)
 
  With Viewer
    .DataRate(2): .Bias(-2.6)
    Center(.hWnd()): Show(.hWnd)
    .Start(): Delete Viewer
  End With
End Sub

Function Messenger(ByVal %hwnd, ByVal %msg, ByVal %wparam, ByVal %lparam) As Integer
  If msg = WM_KEYDOWN Then
    If wparam = VK_ESCAPE Then
      Viewer.Quit()
    End If
    Return 0
  ElseIf msg = WM_SIZE Then
    width = LoWord(lparam)
    height = HiWord(lparam)
    Reshape()
    Return 0
  ElseIf msg = WM_MOUSEMOVE OrElse msg = WM_MOUSEWHEEL Then
    Return 0 // suppress default processing ...
  Else
    Return -1 // ... or allow it
  End If
End Function

Sub Renderer()
  Static st As SYSTEMTIME
  Static secs, red, boom
  Static lastminute = Time(2)
 
  GetLocalTime(@st)
 
  With st
    Dim oldsecs = secs
   
    If .wMinute <> lastminute Then
      lastminute = .wMinute
      red = 20: boom = 4
    End If
   
    secs = .wSecond + .wMilliseconds / 1000
    red = red * Exp(Max(secs - oldsecs, 0) * -5)
    boom = boom * Exp(Max * -.6)
   
    glClearColor(!red, 0, 0, 0)
    DrawClock(secs, .wMinute, .wHour, boom)
  End With
End Sub

Sub DrawClock(s, m, h, b)
  Dim bang = Sin(s * 25) * b
 
  DrawDial(bang * .005)
  glColor3d(.7, .7, .7)
  DrawHand(h * 30 + m * .5 + bang, .6)
  glColor3d(.8, .8, .8)
  DrawHand(m * 6 + bang, .75)
  glColor3d(1., 1., 1.)
  DrawHand(s * 6, .9)
End Sub

Sub DrawDial(shift)
  Dim tick
 
  For Dim i = 0 To 59
    glPushMatrix()
    glRotated(!!(-i * 6), .0, .0, 1.)
    tick = i Mod 5 = 0
    glBegin(GL_LINES)
    glVertex2d(shift, shift + .95 - tick * .1)(shift, shift + 1)
    glEnd()
    glPopMatrix()
  Next
End Sub

Sub DrawHand(r, s)
  glPushMatrix()
 
  glScaled(s, s, s)
  glRotated(-r, .0, .0, 1.)
 
  glBegin(GL_QUADS)
  glVertex2d(.0, -.1)(.1, .0)(.0, 1.)(-.1, .0)
  glEnd()
 
  glPopMatrix()
End Sub

Sub Reshape()
  glViewport(0, 0, width, height)
  glMatrixMode(GL_PROJECTION)
  glLoadIdentity()
  gluPerspective(45., width / height, .1, 1000.)
  glMatrixMode(GL_MODELVIEW)
End Sub

Sub gluPerspective(ByVal !!fovy, ByVal !!xy, !!z0, !!z1)
  fovy = Tan(fovy * PI / 360) * z0: xy = xy * fovy
  glFrustum(-xy, xy, -fovy, fovy, z0, z1)
End Sub
Title: Re: Analog (with integrated digital) clock
Post by: B+ on 13. September 2016, 23:37:53
 ;D Is that an alarming clock!

Nice wobble effect!   :)