mirror of
https://github.com/jonthysell/MacLO.git
synced 2024-06-01 20:41:28 +00:00
Proper event loop, menus, and more
* Added a proper event loop * Added minimal menu bars * Added about menu * GameWindow initializes a GameEngine (even if you can't play it yet) * Updated variable naming conventions
This commit is contained in:
parent
6184d31e6a
commit
2ce4236ea7
|
@ -12,53 +12,55 @@ const uint8_t MinHalfStars = 1;
|
||||||
|
|
||||||
const uint16_t PerfectScore = 300; // LevelCount * MaxHalfStars
|
const uint16_t PerfectScore = 300; // LevelCount * MaxHalfStars
|
||||||
|
|
||||||
void GameEngine_LoadLevel(GameEngine *engine, const int8_t level, const bool setB)
|
void GameEngine_ToggleSingleLight(GameEngine *pGameEngine, const int8_t x, const int8_t y);
|
||||||
|
|
||||||
|
void GameEngine_LoadLevel(GameEngine *pGameEngine, const int8_t level, const bool setB)
|
||||||
{
|
{
|
||||||
engine->Level = Levels_BoundLevel(level);
|
pGameEngine->Level = Levels_BoundLevel(level);
|
||||||
engine->Lights = Levels_GetLightsForLevel(engine->Level, setB);
|
pGameEngine->Lights = Levels_GetLightsForLevel(pGameEngine->Level, setB);
|
||||||
engine->Par = Levels_GetParForLevel(engine->Level);
|
pGameEngine->Par = Levels_GetParForLevel(pGameEngine->Level);
|
||||||
engine->Moves = 0;
|
pGameEngine->Moves = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameEngine_GetLight(const GameEngine *engine, const int8_t x, const int8_t y)
|
bool GameEngine_GetLight(const GameEngine *pGameEngine, const int8_t x, const int8_t y)
|
||||||
{
|
{
|
||||||
if (x >= 0 && x < PuzzleSize && y >= 0 && y < PuzzleSize)
|
if (x >= 0 && x < PuzzleSize && y >= 0 && y < PuzzleSize)
|
||||||
{
|
{
|
||||||
return bitRead(engine->Lights, y * PuzzleSize + x);
|
return bitRead(pGameEngine->Lights, y * PuzzleSize + x);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameEngine_IsCompleted(const GameEngine *engine)
|
bool GameEngine_IsCompleted(const GameEngine *pGameEngine)
|
||||||
{
|
{
|
||||||
return engine->Lights == 0;
|
return pGameEngine->Lights == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t GameEngine_GetHalfStars(const GameEngine *engine)
|
uint8_t GameEngine_GetHalfStars(const GameEngine *pGameEngine)
|
||||||
{
|
{
|
||||||
uint8_t halfStarsLost = engine->Moves <= engine->Par ? 0 : max(0, (1 + engine->Moves - engine->Par) / 2);
|
uint8_t halfStarsLost = pGameEngine->Moves <= pGameEngine->Par ? 0 : max(0, (1 + pGameEngine->Moves - pGameEngine->Par) / 2);
|
||||||
return max(MinHalfStars, MaxHalfStars - halfStarsLost);
|
return max(MinHalfStars, MaxHalfStars - halfStarsLost);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameEngine_ToggleSingleLight(GameEngine *engine, const int8_t x, const int8_t y)
|
void GameEngine_ToggleLights(GameEngine *pGameEngine, const int8_t x, const int8_t y)
|
||||||
{
|
|
||||||
if (x >= 0 && x < PuzzleSize && y >= 0 && y < PuzzleSize)
|
|
||||||
{
|
|
||||||
bitToggle(engine->Lights, y * PuzzleSize + x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameEngine_ToggleLights(GameEngine *engine, const int8_t x, const int8_t y)
|
|
||||||
{
|
{
|
||||||
int8_t targetX = max(0, min(x, PuzzleSize - 1));
|
int8_t targetX = max(0, min(x, PuzzleSize - 1));
|
||||||
int8_t targetY = max(0, min(y, PuzzleSize - 1));
|
int8_t targetY = max(0, min(y, PuzzleSize - 1));
|
||||||
|
|
||||||
GameEngine_ToggleSingleLight(engine, targetX, targetY);
|
GameEngine_ToggleSingleLight(pGameEngine, targetX, targetY);
|
||||||
GameEngine_ToggleSingleLight(engine, targetX + 1, targetY);
|
GameEngine_ToggleSingleLight(pGameEngine, targetX + 1, targetY);
|
||||||
GameEngine_ToggleSingleLight(engine, targetX, targetY + 1);
|
GameEngine_ToggleSingleLight(pGameEngine, targetX, targetY + 1);
|
||||||
GameEngine_ToggleSingleLight(engine, targetX - 1, targetY);
|
GameEngine_ToggleSingleLight(pGameEngine, targetX - 1, targetY);
|
||||||
GameEngine_ToggleSingleLight(engine, targetX, targetY - 1);
|
GameEngine_ToggleSingleLight(pGameEngine, targetX, targetY - 1);
|
||||||
|
|
||||||
engine->Moves++;
|
pGameEngine->Moves++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameEngine_ToggleSingleLight(GameEngine *pGameEngine, const int8_t x, const int8_t y)
|
||||||
|
{
|
||||||
|
if (x >= 0 && x < PuzzleSize && y >= 0 && y < PuzzleSize)
|
||||||
|
{
|
||||||
|
bitToggle(pGameEngine->Lights, y * PuzzleSize + x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,20 +16,20 @@ extern const uint16_t PerfectScore;
|
||||||
|
|
||||||
typedef struct GameEngine
|
typedef struct GameEngine
|
||||||
{
|
{
|
||||||
int8_t Level;
|
int8_t Level;
|
||||||
uint32_t Lights;
|
uint32_t Lights;
|
||||||
uint16_t Par;
|
uint16_t Par;
|
||||||
uint16_t Moves;
|
uint16_t Moves;
|
||||||
} GameEngine;
|
} GameEngine;
|
||||||
|
|
||||||
void GameEngine_LoadLevel(GameEngine *engine, const int8_t level, const bool setB);
|
void GameEngine_LoadLevel(GameEngine *pGameEngine, const int8_t level, const bool setB);
|
||||||
|
|
||||||
bool GameEngine_GetLight(const GameEngine *engine, const int8_t x, const int8_t y);
|
bool GameEngine_GetLight(const GameEngine *pGameEngine, const int8_t x, const int8_t y);
|
||||||
|
|
||||||
bool GameEngine_IsCompleted(const GameEngine *engine);
|
bool GameEngine_IsCompleted(const GameEngine *pGameEngine);
|
||||||
|
|
||||||
uint8_t GameEngine_GetHalfStars(const GameEngine *engine);
|
uint8_t GameEngine_GetHalfStars(const GameEngine *pGameEngine);
|
||||||
|
|
||||||
void GameEngine_ToggleLights(GameEngine *engine, const int8_t x, const int8_t y);
|
void GameEngine_ToggleLights(GameEngine *pGameEngine, const int8_t x, const int8_t y);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,27 +3,34 @@
|
||||||
|
|
||||||
#include "GameWindow.h"
|
#include "GameWindow.h"
|
||||||
|
|
||||||
void GameWindow_Init(GameWindow *gameWindow)
|
void GameWindow_Init(GameWindow *pGameWindow)
|
||||||
{
|
{
|
||||||
if (gameWindow->Window != nil)
|
if (pGameWindow->Window != nil)
|
||||||
{
|
{
|
||||||
ShowError("\pGameWindow already initialized!", false);
|
ShowError("\pGameWindow already initialized!", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
gameWindow->Window = GetNewWindow(kBaseResID, nil, kMoveToFront);
|
pGameWindow->Window = GetNewWindow(BaseResID, nil, MoveToFront);
|
||||||
|
|
||||||
if (gameWindow->Window == nil)
|
if (pGameWindow->Window == nil)
|
||||||
{
|
{
|
||||||
ShowError("\pGameWindow resource WIND kBaseResID missing!", true);
|
ShowError("\pGameWindow resource WIND BaseResID missing!", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
CenterWindow(gameWindow->Window);
|
GameEngine_LoadLevel(&(pGameWindow->Engine), 0, false);
|
||||||
|
|
||||||
ShowWindow(gameWindow->Window);
|
CenterWindow(pGameWindow->Window);
|
||||||
SetPort(gameWindow->Window);
|
}
|
||||||
|
|
||||||
|
void GameWindow_Draw(GameWindow *pGameWindow)
|
||||||
|
{
|
||||||
|
SetPort(pGameWindow->Window);
|
||||||
|
|
||||||
MoveTo(10, 20);
|
MoveTo(10, 20);
|
||||||
DrawString("\pHello MacLO");
|
DrawString("\pHello MacLO");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameWindow_Show(GameWindow *pGameWindow)
|
||||||
|
{
|
||||||
|
ShowWindow(pGameWindow->Window);
|
||||||
|
}
|
||||||
|
|
|
@ -5,12 +5,16 @@
|
||||||
#define GAMEWINDOW_H
|
#define GAMEWINDOW_H
|
||||||
|
|
||||||
#include "MacCommon.h"
|
#include "MacCommon.h"
|
||||||
|
#include "GameEngine.h"
|
||||||
|
|
||||||
typedef struct GameWindow
|
typedef struct GameWindow
|
||||||
{
|
{
|
||||||
WindowPtr Window;
|
WindowPtr Window;
|
||||||
|
GameEngine Engine;
|
||||||
} GameWindow;
|
} GameWindow;
|
||||||
|
|
||||||
void GameWindow_Init(GameWindow *gameWindow);
|
void GameWindow_Init(GameWindow *pGameWindow);
|
||||||
|
void GameWindow_Draw(GameWindow *pGameWindow);
|
||||||
|
void GameWindow_Show(GameWindow *pGameWindow);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,19 +5,13 @@
|
||||||
|
|
||||||
void CenterWindow(WindowPtr window)
|
void CenterWindow(WindowPtr window)
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
}
|
|
||||||
|
|
||||||
Boolean IsCompactDisplay()
|
|
||||||
{
|
|
||||||
return screenBits.bounds.right == 512
|
|
||||||
&& screenBits.bounds.bottom == 342;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowError(Str255 message, Boolean isFatal)
|
void ShowError(Str255 message, Boolean isFatal)
|
||||||
{
|
{
|
||||||
ParamText(message, kEmptyString, kEmptyString, kEmptyString);
|
ParamText(message, EmptyString, EmptyString, EmptyString);
|
||||||
StopAlert(kErrorAlertID, kNilFilterProc);
|
StopAlert(ErrorAlertResID, NilFilterProc);
|
||||||
|
|
||||||
if (isFatal)
|
if (isFatal)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
#ifndef MACCOMMON_H
|
#ifndef MACCOMMON_H
|
||||||
#define MACCOMMON_H
|
#define MACCOMMON_H
|
||||||
|
|
||||||
#define kBaseResID 128
|
#define BaseResID 128
|
||||||
#define kMoveToFront (WindowPtr)-1L
|
#define MoveToFront (WindowPtr)-1L
|
||||||
|
|
||||||
#define kEmptyString "\p"
|
#define EmptyString "\p"
|
||||||
#define kNilFilterProc nil
|
#define NilFilterProc nil
|
||||||
|
|
||||||
#define kErrorAlertID kBaseResID
|
#define ErrorAlertResID BaseResID
|
||||||
|
|
||||||
void CenterWindow(WindowPtr window);
|
void CenterWindow(WindowPtr window);
|
||||||
Boolean IsCompactDisplay();
|
Boolean IsCompactDisplay();
|
||||||
|
|
187
src/MacLO.c
187
src/MacLO.c
|
@ -4,10 +4,33 @@
|
||||||
#include "GameWindow.h"
|
#include "GameWindow.h"
|
||||||
#include "MacLO.h"
|
#include "MacLO.h"
|
||||||
|
|
||||||
GameWindow gGameWindow;
|
#define AppleMenuResID BaseResID
|
||||||
|
#define AboutMenuItemID 1
|
||||||
|
|
||||||
void MacLO_InitToolBox()
|
#define GameMenuResID BaseResID+1
|
||||||
|
#define QuitMenuItemID 1
|
||||||
|
|
||||||
|
#define AboutDialogResID BaseResID
|
||||||
|
#define AboutDialogOKID 1
|
||||||
|
|
||||||
|
GameWindow gGameWindow;
|
||||||
|
Boolean gExitApp;
|
||||||
|
|
||||||
|
void MacLO_HandleUpdate(const EventRecord *pEvent);
|
||||||
|
void MacLO_HandleMouseDown(const EventRecord *pEvent);
|
||||||
|
|
||||||
|
void MacLO_HandleMenuChoice(const long menuChoice);
|
||||||
|
void MacLO_HandleAppleMenuChoice(const short item);
|
||||||
|
|
||||||
|
void MacLO_ShowAboutDialog();
|
||||||
|
void MacLO_LaunchAppleMenuItem(const short item);
|
||||||
|
|
||||||
|
void MacLO_HandleGameMenuChoice(const short item);
|
||||||
|
|
||||||
|
void MacLO_ToolBoxInit()
|
||||||
{
|
{
|
||||||
|
MaxApplZone();
|
||||||
|
|
||||||
InitGraf(&thePort);
|
InitGraf(&thePort);
|
||||||
InitFonts();
|
InitFonts();
|
||||||
InitWindows();
|
InitWindows();
|
||||||
|
@ -18,13 +41,169 @@ void MacLO_InitToolBox()
|
||||||
InitCursor();
|
InitCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacLO_InitWindows()
|
void MacLO_AppInit()
|
||||||
{
|
{
|
||||||
|
Handle menuBar;
|
||||||
|
MenuHandle appleMenu;
|
||||||
|
|
||||||
|
// Add the menu bar
|
||||||
|
menuBar = GetNewMBar(BaseResID);
|
||||||
|
SetMenuBar(menuBar);
|
||||||
|
|
||||||
|
// Populate the apple menu
|
||||||
|
appleMenu = GetMHandle(AppleMenuResID);
|
||||||
|
AddResMenu(appleMenu, 'DRVR');
|
||||||
|
|
||||||
|
DrawMenuBar();
|
||||||
|
|
||||||
|
// Setup the game window
|
||||||
GameWindow_Init(&gGameWindow);
|
GameWindow_Init(&gGameWindow);
|
||||||
|
GameWindow_Draw(&gGameWindow);
|
||||||
|
GameWindow_Show(&gGameWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacLO_MainLoop()
|
void MacLO_MainLoop()
|
||||||
{
|
{
|
||||||
while (!Button()) { }
|
EventRecord event;
|
||||||
|
char cmdChar;
|
||||||
|
|
||||||
|
while (!gExitApp)
|
||||||
|
{
|
||||||
|
if (WaitNextEvent(everyEvent, &event, LONG_MAX, nil))
|
||||||
|
{
|
||||||
|
switch (event.what)
|
||||||
|
{
|
||||||
|
case updateEvt:
|
||||||
|
MacLO_HandleUpdate(&event);
|
||||||
|
break;
|
||||||
|
case mouseDown:
|
||||||
|
MacLO_HandleMouseDown(&event);
|
||||||
|
break;
|
||||||
|
case keyDown:
|
||||||
|
case autoKey:
|
||||||
|
// Translate command key combos to menu items
|
||||||
|
cmdChar = event.message & charCodeMask;
|
||||||
|
if ((event.modifiers & cmdKey) != 0)
|
||||||
|
{
|
||||||
|
MacLO_HandleMenuChoice(MenuKey(cmdChar));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacLO_HandleUpdate(const EventRecord *pEvent)
|
||||||
|
{
|
||||||
|
WindowPtr window;
|
||||||
|
|
||||||
|
window = (WindowPtr)pEvent->message;
|
||||||
|
|
||||||
|
BeginUpdate(window);
|
||||||
|
|
||||||
|
if (window == gGameWindow.Window)
|
||||||
|
{
|
||||||
|
GameWindow_Draw(&gGameWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
EndUpdate(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacLO_HandleMouseDown(const EventRecord *pEvent)
|
||||||
|
{
|
||||||
|
WindowPtr window;
|
||||||
|
long windowPart;
|
||||||
|
long menuChoice;
|
||||||
|
|
||||||
|
windowPart = FindWindow(pEvent->where, &window);
|
||||||
|
|
||||||
|
switch (windowPart)
|
||||||
|
{
|
||||||
|
case inMenuBar:
|
||||||
|
menuChoice = MenuSelect(pEvent->where);
|
||||||
|
MacLO_HandleMenuChoice(menuChoice);
|
||||||
|
case inSysWindow:
|
||||||
|
SystemClick(pEvent, window);
|
||||||
|
break;
|
||||||
|
case inDrag:
|
||||||
|
DragWindow(window, pEvent->where, &((*GetGrayRgn())->rgnBBox));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacLO_HandleMenuChoice(const long menuChoice)
|
||||||
|
{
|
||||||
|
short menu;
|
||||||
|
short item;
|
||||||
|
|
||||||
|
if (menuChoice != 0)
|
||||||
|
{
|
||||||
|
menu = HiWord(menuChoice);
|
||||||
|
item = LoWord(menuChoice);
|
||||||
|
|
||||||
|
switch (menu)
|
||||||
|
{
|
||||||
|
case AppleMenuResID:
|
||||||
|
MacLO_HandleAppleMenuChoice(item);
|
||||||
|
break;
|
||||||
|
case GameMenuResID:
|
||||||
|
MacLO_HandleGameMenuChoice(item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
HiliteMenu(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacLO_HandleAppleMenuChoice(const short item)
|
||||||
|
{
|
||||||
|
MenuHandle appleMenu;
|
||||||
|
Str255 accName;
|
||||||
|
short accNumber;
|
||||||
|
|
||||||
|
switch (item)
|
||||||
|
{
|
||||||
|
case AboutMenuItemID:
|
||||||
|
MacLO_ShowAboutDialog();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MacLO_LaunchAppleMenuItem(item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacLO_ShowAboutDialog()
|
||||||
|
{
|
||||||
|
DialogPtr dialog;
|
||||||
|
int itemHit;
|
||||||
|
|
||||||
|
dialog = GetNewDialog(AboutDialogResID, nil, MoveToFront);
|
||||||
|
|
||||||
|
SetPort(dialog);
|
||||||
|
ShowWindow(dialog);
|
||||||
|
|
||||||
|
ModalDialog(nil, &itemHit);
|
||||||
|
|
||||||
|
DisposDialog(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacLO_LaunchAppleMenuItem(const short item)
|
||||||
|
{
|
||||||
|
MenuHandle appleMenu;
|
||||||
|
Str255 accName;
|
||||||
|
|
||||||
|
appleMenu = GetMHandle(AppleMenuResID);
|
||||||
|
GetItem(appleMenu, item, accName);
|
||||||
|
OpenDeskAcc(accName);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacLO_HandleGameMenuChoice(const short item)
|
||||||
|
{
|
||||||
|
switch (item)
|
||||||
|
{
|
||||||
|
case QuitMenuItemID:
|
||||||
|
gExitApp = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#ifndef MACLO_H
|
#ifndef MACLO_H
|
||||||
#define MACLO_H
|
#define MACLO_H
|
||||||
|
|
||||||
void MacLO_InitToolBox();
|
void MacLO_ToolBoxInit();
|
||||||
void MacLO_InitWindows();
|
void MacLO_AppInit();
|
||||||
void MacLO_MainLoop();
|
void MacLO_MainLoop();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
BIN
src/MacLO.pi.bin
BIN
src/MacLO.pi.bin
Binary file not shown.
Binary file not shown.
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
MacLO_InitToolBox();
|
MacLO_ToolBoxInit();
|
||||||
MacLO_InitWindows();
|
MacLO_AppInit();
|
||||||
MacLO_MainLoop();
|
MacLO_MainLoop();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user