This is a simple little program demonstrating how the phases of the Moon develop depending upon the positions of the Moon and the Sun in the sky. It gives a pleasing graphics display.
Moon Phases.zip (Size: 308.23 KB / Downloads: 13)
Unzip the folder into your QB64 directory (Run Option “Save EXE in source folder” checked).
The view is for an observer in the Northern hemisphere looking South - you Southern-hemispherical people would see things upside-down (but then we're not sure what is preventing you from falling off the Earth, anyway! - cue for Pete to give his "gravity of the situation" pun).
The dark green foreshortened half-circle at the bottom represents the viewer's horizon: the Sun and Moon rise in the East (left-hand side) and sink in the West.
Of course, the sizes of the Sun and Moon are way, way larger than in the actual sky, but it is the phase of the moon that is the only important factor. Apart from the phase, all other factors are quite unrealistic.
The program will start with your current time and date and will then proceed minute-by-minute. The position of the Sun will be correct, but the Moon starts arbitrarily opposite the Sun. The Sun will gradually catch up the Moon, and there will be a total eclipse every complete Moon cycle (27.3 days in this model). You may need to wait for month than a month to witness a total eclipse.
Top right is the time progressing, top left is the date.
The Moon phase is set by PSET & _SETALPHA functions on the program image. Use of _MEM object processing would have been properly optimised but when this program was written I did not know about _MEM processing. The program works fine, anyway.
Moon Phases.zip (Size: 308.23 KB / Downloads: 13)
Unzip the folder into your QB64 directory (Run Option “Save EXE in source folder” checked).
The view is for an observer in the Northern hemisphere looking South - you Southern-hemispherical people would see things upside-down (but then we're not sure what is preventing you from falling off the Earth, anyway! - cue for Pete to give his "gravity of the situation" pun).
The dark green foreshortened half-circle at the bottom represents the viewer's horizon: the Sun and Moon rise in the East (left-hand side) and sink in the West.
Of course, the sizes of the Sun and Moon are way, way larger than in the actual sky, but it is the phase of the moon that is the only important factor. Apart from the phase, all other factors are quite unrealistic.
The program will start with your current time and date and will then proceed minute-by-minute. The position of the Sun will be correct, but the Moon starts arbitrarily opposite the Sun. The Sun will gradually catch up the Moon, and there will be a total eclipse every complete Moon cycle (27.3 days in this model). You may need to wait for month than a month to witness a total eclipse.
Top right is the time progressing, top left is the date.
The Moon phase is set by PSET & _SETALPHA functions on the program image. Use of _MEM object processing would have been properly optimised but when this program was written I did not know about _MEM processing. The program works fine, anyway.
Code: (Select All)
'Moon Phases by Magdha 2025-11-24 ex Qwerkey
'Moon shadow (phase) set by PSET and _SETALPHA
CONST Radius% = 98, HalfScreenX% = 550, HalfScreenY% = 300
CONST G! = 0.75, H! = 0.7, Twelve% = 720, MinsStep%% = 2, Delta! = 0.15, Eclipse! = 0.004
_TITLE "Moon Phases - Esc to Quit"
$EXEICON:'.\moon.ico'
Moon1& = _LOADIMAGE("moon1.png", 32)
TempImg& = _NEWIMAGE(2 * Radius% + 1, 2 * Radius% + 1, 32)
_DEST TempImg&
_PUTIMAGE (0, 0)-(2 * Radius%, 2 * Radius%), Moon1&
Moon& = MakeHardware&(TempImg&)
_FREEIMAGE Moon1&
TempImg& = _NEWIMAGE(2 * Radius% + 1, 2 * Radius% + 1, 32)
_DEST TempImg&
CIRCLE (Radius%, Radius%), Radius%, _RGB32(255, 255, 0)
PAINT (Radius%, Radius%), _RGB32(255, 255, 0)
Sun& = MakeHardware&(TempImg&)
TempImg& = _NEWIMAGE(2 * HalfScreenX% + 1, 2 * HalfScreenX% + 1, 32)
_DEST TempImg&
CIRCLE (HalfScreenX%, HalfScreenX%), HalfScreenX%, _RGB32(0, 50, 0)
PAINT (HalfScreenX%, HalfScreenX%), _RGB32(0, 50, 0)
Ground& = MakeHardware&(TempImg&)
DIM Months$(12, 1), Days%(1)
DATA Jan,31,Feb,28,Mar,31,Apr,30,May,31,Jun,30,Jul,31,Aug,31,Sep,30,Oct,31,Nov,30,Dec,31
FOR N% = 1 TO 12
FOR M% = 0 TO 1
READ Months$(N%, M%)
NEXT M%
NEXT N%
Days%(0) = VAL(LEFT$(DATE$, 2))
Days%(1) = VAL(MID$(DATE$, 4, 2))
IF Days%(0) = 2 AND Days%(1) = 29 THEN Days%(1) = 28
NoMins% = INT(TIMER) \ 60
Beta1! = (Twelve% - NoMins%) * _PI / Twelve%
Beta2! = Beta1! - _PI
SCREEN _NEWIMAGE(2 * HalfScreenX% + 1, 2 * HalfScreenY% + 1, 32)
_SCREENMOVE 50, 20
_DEST 0
_DISPLAYORDER _SOFTWARE , _HARDWARE
WHILE INKEY$ = ""
_LIMIT 60
Theta! = Beta1! - Beta2! - 3 * _PI / 2
IF Theta! < -3 * _PI / 2 THEN
Theta! = Theta! + 2 * _PI
ELSEIF Theta! > _PI / 2 THEN
Theta! = Theta! - 2 * _PI
END IF
IF Beta1! > -_PI / 2 AND Beta1! < _PI / 2 THEN
IF (Theta! < -3 * _PI / 2 + Eclipse! AND Theta! > -3 * _PI / 2) OR (Theta! < _PI / 2 AND Theta! > _PI / 2 - Eclipse!) THEN
COLOR _RGB32(255, 255, 255), _RGB32(0, 0, 10)
ELSE
COLOR _RGB32(255, 255, 255), _RGB32(0, 0, 250 * (COS(Beta1!)) ^ 0.3)
END IF
CLS
END IF
IF Beta1! > -_PI / 2 - Delta! AND Beta1! < _PI / 2 + Delta! THEN
X1% = CINT(HalfScreenX% * SIN(-Beta1!))
Y1% = CINT(2 * HalfScreenY% * G! * COS(-Beta1!))
_PUTIMAGE (HalfScreenX% + X1% - Radius%, 2 * HalfScreenY% + 1 - Y1% - Radius%), Sun&
END IF
IF Beta2! > -_PI / 2 - Delta! AND Beta2! < _PI / 2 + Delta! THEN
TempImg& = _NEWIMAGE(2 * Radius% + 1, 2 * Radius% + 1, 32)
_DEST TempImg&
IF Theta! >= -_PI / 2 THEN
FOR N% = 0 TO 500
Phi! = N% * _PI / 500
PSET (CINT(Radius% * SIN(Phi!) * SIN(-_PI / 2)) + Radius%, CINT(Radius% * COS(Phi!)) + Radius%), _RGB32(40, 40, 20)
NEXT N%
FOR N% = 0 TO 500
Phi! = N% * _PI / 500
PSET (CINT(Radius% * SIN(Phi!) * SIN(Theta!)) + Radius%, CINT(Radius% * COS(Phi!)) + Radius%), _RGB32(40, 40, 20)
NEXT N%
IF CINT(Radius% * SIN(_PI / 2) * SIN(Theta!)) > -(Radius% - 1) THEN PAINT (1, Radius%), _RGB32(40, 40, 20)
_SETALPHA 230, _RGB32(40, 40, 20)
ELSE
FOR N% = 0 TO 500
Phi! = N% * _PI / 500
PSET (CINT(Radius% * SIN(Phi!) * SIN(_PI / 2)) + Radius%, CINT(Radius% * COS(Phi!)) + Radius%), _RGB32(40, 40, 20)
NEXT N%
Theta2! = Theta! + _PI
FOR N% = 0 TO 500
Phi! = N% * _PI / 500
PSET (CINT(Radius% * SIN(Phi!) * SIN(Theta2!)) + Radius%, CINT(Radius% * COS(Phi!)) + Radius%), _RGB32(40, 40, 20)
NEXT N%
IF CINT(Radius% * SIN(_PI / 2) * SIN(Theta2!)) < (Radius% - 1) THEN PAINT (2 * Radius% - 1, Radius%), _RGB32(40, 40, 20)
_SETALPHA 230, _RGB32(40, 40, 20)
END IF
Shadow& = MakeHardware&(TempImg&)
_DEST 0
X2% = CINT(HalfScreenX% * SIN(-Beta2!))
Y2% = CINT(2 * HalfScreenY% * G! * COS(-Beta2!))
_PUTIMAGE (HalfScreenX% + X2% - Radius%, 2 * HalfScreenY% + 1 - Y2% - Radius%), Moon&
_PUTIMAGE (HalfScreenX% + X2% - Radius%, 2 * HalfScreenY% + 1 - Y2% - Radius%), Shadow&
_FREEIMAGE Shadow&
END IF
_PUTIMAGE (0, (2 * HalfScreenY% + 1) * H!)-(2 * HalfScreenX% + 1, 2 * HalfScreenY% + 1), Ground&, , (0, 0)-(2 * HalfScreenX% + 1, HalfScreenX%)
LOCATE 1, 1
IF NoMins% \ 60 <= 9 THEN
PRINT " 0" + RIGHT$(STR$(NoMins% \ 60), 1) + " "; NoMins% MOD 60;
ELSE
PRINT NoMins% \ 60; NoMins% MOD 60;
END IF
LOCATE 1, 130: PRINT Months$(Days%(0), 0) + " "; Days%(1);
_DISPLAY
NoMins% = NoMins% + MinsStep%%
IF NoMins% >= 1440 THEN
NoMins% = NoMins% - 1440
Days%(1) = Days%(1) + 1
IF Days%(1) > VAL(Months$(Days%(0), 1)) THEN
Days%(1) = 1
Days%(0) = Days%(0) + 1
IF Days%(0) > 12 THEN Days%(0) = 1
END IF
END IF
Beta1! = (Twelve% - NoMins%) * _PI / Twelve% ' Sun
IF Beta1! < -_PI THEN Beta1! = Beta1! + 2 * _PI
Beta2! = Beta2! - (MinsStep%% * _PI / Twelve%) + (2 * 0.0001593) 'Moon 27.39days
IF Beta2! < -_PI THEN Beta2! = Beta2! + 2 * _PI
WEND
SYSTEM
FUNCTION MakeHardware& (Img&)
MakeHardware& = _COPYIMAGE(Img&, 33)
_FREEIMAGE Img&
END FUNCTION

