mirror of https://github.com/jonthysell/MacLO.git
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
|
||||
|
||||
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);
|
||||
engine->Lights = Levels_GetLightsForLevel(engine->Level, setB);
|
||||
engine->Par = Levels_GetParForLevel(engine->Level);
|
||||
engine->Moves = 0;
|
||||
pGameEngine->Level = Levels_BoundLevel(level);
|
||||
pGameEngine->Lights = Levels_GetLightsForLevel(pGameEngine->Level, setB);
|
||||
pGameEngine->Par = Levels_GetParForLevel(pGameEngine->Level);
|
||||
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)
|
||||
{
|
||||
return bitRead(engine->Lights, y * PuzzleSize + x);
|
||||
return bitRead(pGameEngine->Lights, y * PuzzleSize + x);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void GameEngine_ToggleSingleLight(GameEngine *engine, 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)
|
||||
void GameEngine_ToggleLights(GameEngine *pGameEngine, const int8_t x, const int8_t y)
|
||||
{
|
||||
int8_t targetX = max(0, min(x, PuzzleSize - 1));
|
||||
int8_t targetY = max(0, min(y, PuzzleSize - 1));
|
||||
|
||||
GameEngine_ToggleSingleLight(engine, targetX, targetY);
|
||||
GameEngine_ToggleSingleLight(engine, targetX + 1, targetY);
|
||||
GameEngine_ToggleSingleLight(engine, targetX, targetY + 1);
|
||||
GameEngine_ToggleSingleLight(engine, targetX - 1, targetY);
|
||||
GameEngine_ToggleSingleLight(engine, targetX, targetY - 1);
|
||||
GameEngine_ToggleSingleLight(pGameEngine, targetX, targetY);
|
||||
GameEngine_ToggleSingleLight(pGameEngine, targetX + 1, targetY);
|
||||
GameEngine_ToggleSingleLight(pGameEngine, targetX, targetY + 1);
|
||||
GameEngine_ToggleSingleLight(pGameEngine, targetX - 1, targetY);
|
||||
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
|
||||
{
|
||||
int8_t Level;
|
||||
int8_t Level;
|
||||
uint32_t Lights;
|
||||
uint16_t Par;
|
||||
uint16_t Moves;
|
||||
} 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
|
||||
|
|
|
@ -3,27 +3,34 @@
|
|||
|
||||
#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);
|
||||
}
|
||||
|
||||
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);
|
||||
SetPort(gameWindow->Window);
|
||||
CenterWindow(pGameWindow->Window);
|
||||
}
|
||||
|
||||
void GameWindow_Draw(GameWindow *pGameWindow)
|
||||
{
|
||||
SetPort(pGameWindow->Window);
|
||||
|
||||
MoveTo(10, 20);
|
||||
DrawString("\pHello MacLO");
|
||||
}
|
||||
|
||||
|
||||
void GameWindow_Show(GameWindow *pGameWindow)
|
||||
{
|
||||
ShowWindow(pGameWindow->Window);
|
||||
}
|
||||
|
|
|
@ -5,12 +5,16 @@
|
|||
#define GAMEWINDOW_H
|
||||
|
||||
#include "MacCommon.h"
|
||||
#include "GameEngine.h"
|
||||
|
||||
typedef struct GameWindow
|
||||
{
|
||||
WindowPtr Window;
|
||||
WindowPtr Window;
|
||||
GameEngine Engine;
|
||||
} GameWindow;
|
||||
|
||||
void GameWindow_Init(GameWindow *gameWindow);
|
||||
void GameWindow_Init(GameWindow *pGameWindow);
|
||||
void GameWindow_Draw(GameWindow *pGameWindow);
|
||||
void GameWindow_Show(GameWindow *pGameWindow);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,19 +5,13 @@
|
|||
|
||||
void CenterWindow(WindowPtr window)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Boolean IsCompactDisplay()
|
||||
{
|
||||
return screenBits.bounds.right == 512
|
||||
&& screenBits.bounds.bottom == 342;
|
||||
// TODO
|
||||
}
|
||||
|
||||
void ShowError(Str255 message, Boolean isFatal)
|
||||
{
|
||||
ParamText(message, kEmptyString, kEmptyString, kEmptyString);
|
||||
StopAlert(kErrorAlertID, kNilFilterProc);
|
||||
ParamText(message, EmptyString, EmptyString, EmptyString);
|
||||
StopAlert(ErrorAlertResID, NilFilterProc);
|
||||
|
||||
if (isFatal)
|
||||
{
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
#ifndef MACCOMMON_H
|
||||
#define MACCOMMON_H
|
||||
|
||||
#define kBaseResID 128
|
||||
#define kMoveToFront (WindowPtr)-1L
|
||||
#define BaseResID 128
|
||||
#define MoveToFront (WindowPtr)-1L
|
||||
|
||||
#define kEmptyString "\p"
|
||||
#define kNilFilterProc nil
|
||||
#define EmptyString "\p"
|
||||
#define NilFilterProc nil
|
||||
|
||||
#define kErrorAlertID kBaseResID
|
||||
#define ErrorAlertResID BaseResID
|
||||
|
||||
void CenterWindow(WindowPtr window);
|
||||
Boolean IsCompactDisplay();
|
||||
|
|
187
src/MacLO.c
187
src/MacLO.c
|
@ -4,10 +4,33 @@
|
|||
#include "GameWindow.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);
|
||||
InitFonts();
|
||||
InitWindows();
|
||||
|
@ -18,13 +41,169 @@ void MacLO_InitToolBox()
|
|||
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_Draw(&gGameWindow);
|
||||
GameWindow_Show(&gGameWindow);
|
||||
}
|
||||
|
||||
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
|
||||
#define MACLO_H
|
||||
|
||||
void MacLO_InitToolBox();
|
||||
void MacLO_InitWindows();
|
||||
void MacLO_ToolBoxInit();
|
||||
void MacLO_AppInit();
|
||||
void MacLO_MainLoop();
|
||||
|
||||
#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)
|
||||
{
|
||||
MacLO_InitToolBox();
|
||||
MacLO_InitWindows();
|
||||
MacLO_ToolBoxInit();
|
||||
MacLO_AppInit();
|
||||
MacLO_MainLoop();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue