pendulum68k/main.c

1 line
4.3 KiB
C

#include <math.h>
#include "common.h"
#include "pendulum.h"
#include "pendMenu.h"
#include "pendDialog.h"
#define SET_RECT(R,t,l,b,r) \
do { (R).top = (t); (R).left = (l); (R).bottom = (b); (R).right = (r); } while(0)
#define THETA (M_PI / 3)
#define D_THETA (0)
#define MU 0.1
#define LEN 2
#define GRAV 9.8
extern Boolean running = true;
extern Boolean resetting = true;
extern Boolean paused = false;
extern Boolean forceRedraw = false;
extern struct dialog_prefs_t pendPrefs = {
THETA, D_THETA, MU, LEN, GRAV
};
Rect WINDOW_RECT = {50, 50, 250, 250};
char WINDOW_NAME[] = "\pPendulum";
WindowPtr pendWindow;
struct pendulum_t thePend;
static Rect dragRect; /* const */
static void InitMacintosh(void);
static void ExitError(void);
static long HandleEvent(int eventMask);
static void HandleMouseDown(EventRecord *theEvent);
static void WaitTicks(unsigned qty);
static void WindowCreate(void);
static void WindowDrawContent(WindowPtr theWin, double angle, Boolean force);
static int iround(double n) {
double ipart, fpart;
int sign;
fpart = modf(n, &ipart);
sign = (n >= 0 ? 1 : -1);
if(fabs(fpart) >= 0.5) return (int)(ipart) + sign;
return (int) ipart;
}
void InitMacintosh(void) {
MaxApplZone();
InitGraf(&thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(0L);
FlushEvents(everyEvent, 0);
InitCursor();
}
void ExitError(void) {
SysBeep(1);
ExitToShell();
}
void WaitTicks(unsigned qty) {
static long lastTick = 0;
if(qty == 0) return;
while(--qty) {
while(lastTick == Ticks) {
HandleEvent(updateMask);
HandleEvent(everyEvent);
}
}
lastTick = Ticks;
}
long HandleEvent(int eventMask) {
int res;
EventRecord theEvent;
HiliteMenu(0);
SystemTask(); /* Handle desk accessories */
if (!GetNextEvent(eventMask, &theEvent)) return;
switch (theEvent.what) {
case mouseDown:
HandleMouseDown(&theEvent);
break;
case keyDown:
if(theEvent.modifiers & cmdKey) {
MenuEvent(MenuKey(theEvent.message & 0xFF));
}
/* FALLTHROUGH */
case autoKey:
break;
case activateEvt:
if(theEvent.modifiers & activeFlag) {
MenuEditMode(false);
paused = 0;
} else {
MenuEditMode(true);
paused = 1;
}
break;
case updateEvt:
WindowDrawContent((WindowPtr) theEvent.message,
thePend.theta, paused || forceRedraw);
forceRedraw = false;
break;
}
}
void HandleMouseDown(EventRecord *theEvent) {
WindowPtr theWindow;
int windowCode = FindWindow(theEvent->where, &theWindow);
switch (windowCode) {
case inSysWindow:
SystemClick (theEvent, theWindow);
break;
case inDrag:
DragWindow(theWindow, theEvent->where, &dragRect);
break;
case inMenuBar:
MenuEvent(MenuSelect(theEvent->where));
break;
case inContent:
if(theWindow != FrontWindow()) {
SelectWindow(theWindow);
}
break;
case inGoAway:
if(TrackGoAway(theWindow, theEvent->where)) {
HideWindow(theWindow);
running = false;
}
break;
}
}
void WindowCreate(void) {
pendWindow = NewWindow(0L, &WINDOW_RECT, WINDOW_NAME,
true, noGrowDocProc, (WindowPtr) -1L, true, 0);
if(!pendWindow) ExitError();
}
void WindowDrawContent(WindowPtr theWin, double angle, Boolean force) {
static Point lastPoint = {0, 0};
Rect BallRect = {0, 0, 25, 25};
Point lineEnd;
lineEnd.h = 100 + iround(75.0 * sin(angle));
lineEnd.v = 100 + iround(75.0 * cos(angle));
if(!force &&
lastPoint.h == lineEnd.h && lastPoint.v == lineEnd.v) {
return;
}
/*HideCursor();*/
BeginUpdate(theWin);
EraseRect(&theWin->portRect);
MoveTo(100, 100);
LineTo(lineEnd.h, lineEnd.v);
OffsetRect(&BallRect, lineEnd.h - 12, lineEnd.v - 12);
PaintRoundRect(&BallRect, 25, 25);
EndUpdate(theWin);
/*ShowCursor();*/
lastPoint.h = lineEnd.h;
lastPoint.v = lineEnd.v;
}
int main(void) {
InitMacintosh();
WindowCreate();
MenuCreate();
SetPort(pendWindow);
SET_RECT(dragRect, 4, 24, screenBits.bounds.right-4,
screenBits.bounds.bottom-4);
thePend.timestep = 1.0/20.0;
while(running) {
if(resetting) {
thePend.theta = pendPrefs.theta;
thePend.d_theta = pendPrefs.d_theta;
thePend.mu = pendPrefs.mu;
thePend.gl = pendPrefs.grav / pendPrefs.len;
resetting = false;
}
if(!paused) {
InvalRect(&pendWindow->portRect);
WaitTicks(4);
pendulum_iter(&thePend);
} else {
HandleEvent(everyEvent);
}
}
}