mirror of
https://github.com/jonthysell/MacLO.git
synced 2024-06-26 08:29:27 +00:00
* Added sound menu which keeps in sync with pressing sound button * Changed navigation behavior between scenes to go straight to next level if it hasn't been beaten, otherwise return to level select so the player can view their progress in the set * More drawing optimizations
245 lines
8.8 KiB
C
245 lines
8.8 KiB
C
// Copyright (c) Jon Thysell <http://jonthysell.com>
|
|
// Licensed under the MIT License.
|
|
|
|
/**
|
|
* @file PlayScene.c
|
|
*
|
|
* This file provides implementations for PlayScene.h.
|
|
*/
|
|
|
|
#include "PlayScene.h"
|
|
|
|
/** Margin around the Playfield area. */
|
|
#define PlayfieldMargin 4
|
|
|
|
/** Padding within the Playfield area. */
|
|
#define PlayfieldPadding 2
|
|
|
|
/** Corner size of the Playfield area. */
|
|
#define PlayfieldCornerSize 12
|
|
|
|
/** Margin around each light. */
|
|
#define LightMargin 6
|
|
|
|
/** Size (width and height) of each light. */
|
|
#define LightSize 50
|
|
|
|
/** Margin around the HUD area. */
|
|
#define HUDMargin PlayfieldMargin
|
|
|
|
/** Scale factor for the level text. */
|
|
#define LevelTextScale 3
|
|
|
|
/** Scale factor for the stars. */
|
|
#define HalfStarScale 2
|
|
|
|
/** Scale factor for the score text. */
|
|
#define ScoreTextScale 1
|
|
|
|
/**
|
|
* Gets the Rect of the light at the given coordinates.
|
|
* @param pGameWindow The GameWindow.
|
|
* @param pRect. The Rect of the light.
|
|
* @param c The column.
|
|
* @param r The row.
|
|
*/
|
|
void PlayScene_SetLightRect(const GameWindow *pGameWindow, Rect *pRect, const int8_t c, const int8_t r);
|
|
|
|
void PlayScene_Init(GameWindow *pGameWindow)
|
|
{
|
|
Rect r;
|
|
|
|
const Rect *pContentRect = &(pGameWindow->Window->portRect);
|
|
|
|
// Setup Playfield
|
|
pGameWindow->PlayScene.PlayfieldRect.top = PlayfieldMargin;
|
|
pGameWindow->PlayScene.PlayfieldRect.bottom = pContentRect->bottom - PlayfieldMargin;
|
|
pGameWindow->PlayScene.PlayfieldRect.left = pGameWindow->PlayScene.PlayfieldRect.top;
|
|
pGameWindow->PlayScene.PlayfieldRect.right = pGameWindow->PlayScene.PlayfieldRect.bottom;
|
|
|
|
// Setup HUD
|
|
pGameWindow->PlayScene.HUDRect.top = HUDMargin;
|
|
pGameWindow->PlayScene.HUDRect.bottom = pContentRect->bottom - HUDMargin;
|
|
pGameWindow->PlayScene.HUDRect.left = pGameWindow->PlayScene.PlayfieldRect.right + HUDMargin;
|
|
pGameWindow->PlayScene.HUDRect.right = pContentRect->right - HUDMargin;
|
|
|
|
// Setup level
|
|
GetScaledPicFrame(pGameWindow->Engine.SetB ? pGameWindow->Bitmaps.BCharPict : pGameWindow->Bitmaps.ACharPict, LevelTextScale, &(pGameWindow->PlayScene.LevelRect));
|
|
Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), 1 + pGameWindow->Engine.Level, LevelTextScale, &r);
|
|
ConcatenateRect(&(pGameWindow->PlayScene.LevelRect), &r, &(pGameWindow->PlayScene.LevelRect));
|
|
|
|
GetBoxRect(&(pGameWindow->PlayScene.HUDRect), Top, &r);
|
|
CenterRect(&r, &(pGameWindow->PlayScene.LevelRect));
|
|
|
|
// Setup half-stars
|
|
Bitmaps_GetHalfStarsRect(&(pGameWindow->Bitmaps), MaxStars, HalfStarScale, &(pGameWindow->PlayScene.HalfStarsRect));
|
|
|
|
GetBoxRect(&(pGameWindow->PlayScene.HUDRect), Center, &r);
|
|
CenterRect(&r, &(pGameWindow->PlayScene.HalfStarsRect));
|
|
|
|
// Setup score
|
|
Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), GameEngine_GetTotalScore(&(pGameWindow->Engine)), ScoreTextScale, &(pGameWindow->PlayScene.ScoreRect));
|
|
GetScaledPicFrame(pGameWindow->Bitmaps.SlashCharPict, ScoreTextScale, &r);
|
|
ConcatenateRect(&(pGameWindow->PlayScene.ScoreRect), &r, &(pGameWindow->PlayScene.ScoreRect));
|
|
Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), PerfectScore, ScoreTextScale, &r);
|
|
ConcatenateRect(&(pGameWindow->PlayScene.ScoreRect), &r, &(pGameWindow->PlayScene.ScoreRect));
|
|
|
|
GetBoxRect(&(pGameWindow->PlayScene.HUDRect), Bottom, &r);
|
|
CenterRect(&r, &(pGameWindow->PlayScene.ScoreRect));
|
|
|
|
// Setup retry button
|
|
GetPictureRect(pGameWindow->Bitmaps.RetryButtonPict, &(pGameWindow->PlayScene.RetryButtonRect));
|
|
|
|
GetBoxRect(&(pGameWindow->PlayScene.HUDRect), BottomLeft, &r);
|
|
CenterRect(&r, &(pGameWindow->PlayScene.RetryButtonRect));
|
|
|
|
// Setup sound button
|
|
Bitmaps_GetSoundRect(&(pGameWindow->Bitmaps), 1, &(pGameWindow->PlayScene.SoundButtonRect));
|
|
GetBoxRect(&(pGameWindow->PlayScene.HUDRect), BottomRight, &r);
|
|
CenterRect(&r, &(pGameWindow->PlayScene.SoundButtonRect));
|
|
}
|
|
|
|
void PlayScene_SetLightRect(const GameWindow *pGameWindow, Rect *pRect, const int8_t c, const int8_t r)
|
|
{
|
|
pRect->top = pGameWindow->PlayScene.PlayfieldRect.top + PlayfieldPadding + LightMargin + (r * (LightMargin + LightSize));
|
|
pRect->bottom = pRect->top + LightSize;
|
|
pRect->left = pGameWindow->PlayScene.PlayfieldRect.left + PlayfieldPadding + LightMargin + (c * (LightMargin + LightSize));
|
|
pRect->right = pRect->left + LightSize;
|
|
}
|
|
|
|
void PlayScene_Draw(const GameWindow *pGameWindow, bool fullRefresh)
|
|
{
|
|
int8_t r, c;
|
|
Rect lightRect;
|
|
|
|
if (fullRefresh)
|
|
{
|
|
// Fill backgrounds
|
|
ForeColor(whiteColor);
|
|
FrameRoundRect(&(pGameWindow->PlayScene.PlayfieldRect), PlayfieldCornerSize, PlayfieldCornerSize);
|
|
ForeColor(blackColor);
|
|
}
|
|
|
|
// Draw Playfield
|
|
|
|
// Draw lights
|
|
for (r = 0; r < PuzzleSize; r++)
|
|
{
|
|
for (c = 0; c < PuzzleSize; c++)
|
|
{
|
|
if (fullRefresh || GameEngine_LightChanged(&(pGameWindow->Engine), c, r))
|
|
{
|
|
PlayScene_SetLightRect(pGameWindow, &lightRect, c, r);
|
|
|
|
if (GameEngine_GetLight(&(pGameWindow->Engine), c, r))
|
|
{
|
|
// Draw ON light
|
|
DrawPicture(pGameWindow->Bitmaps.LightOnPict, &lightRect);
|
|
}
|
|
else
|
|
{
|
|
// Draw OFF light
|
|
DrawPicture(pGameWindow->Bitmaps.LightOffPict, &lightRect);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Draw HUD
|
|
|
|
// Draw level
|
|
if (fullRefresh)
|
|
{
|
|
MoveTo(pGameWindow->PlayScene.LevelRect.left, pGameWindow->PlayScene.LevelRect.top);
|
|
if (pGameWindow->Engine.SetB)
|
|
{
|
|
Bitmaps_DrawBChar(&(pGameWindow->Bitmaps), LevelTextScale);
|
|
}
|
|
else
|
|
{
|
|
Bitmaps_DrawAChar(&(pGameWindow->Bitmaps), LevelTextScale);
|
|
}
|
|
Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), 1 + pGameWindow->Engine.Level, LevelTextScale);
|
|
}
|
|
|
|
// Draw half-stars
|
|
if (fullRefresh || GameEngine_HalfStarsChanged(&(pGameWindow->Engine)))
|
|
{
|
|
MoveTo(pGameWindow->PlayScene.HalfStarsRect.left, pGameWindow->PlayScene.HalfStarsRect.top);
|
|
Bitmaps_DrawHalfStars(&(pGameWindow->Bitmaps), GameEngine_GetHalfStars(&(pGameWindow->Engine)), MaxStars, HalfStarScale);
|
|
}
|
|
|
|
// Draw score
|
|
if (fullRefresh)
|
|
{
|
|
MoveTo(pGameWindow->PlayScene.ScoreRect.left, pGameWindow->PlayScene.ScoreRect.top);
|
|
Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), GameEngine_GetTotalScore(&(pGameWindow->Engine)), ScoreTextScale);
|
|
Bitmaps_DrawSlashChar(&(pGameWindow->Bitmaps), ScoreTextScale);
|
|
Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), PerfectScore, ScoreTextScale);
|
|
}
|
|
|
|
// Draw retry button
|
|
if (fullRefresh)
|
|
{
|
|
DrawPicture(pGameWindow->Bitmaps.RetryButtonPict, &(pGameWindow->PlayScene.RetryButtonRect));
|
|
}
|
|
|
|
// Draw sound button
|
|
MoveTo(pGameWindow->PlayScene.SoundButtonRect.left, pGameWindow->PlayScene.SoundButtonRect.top);
|
|
Bitmaps_DrawSound(&(pGameWindow->Bitmaps), pGameWindow->Sounds.Enabled, 1);
|
|
}
|
|
|
|
void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition)
|
|
{
|
|
int8_t r, c;
|
|
Rect lightRect;
|
|
|
|
if (PtInRect(*pPosition, &(pGameWindow->PlayScene.PlayfieldRect)))
|
|
{
|
|
// Click within Playfield
|
|
for (r = 0; r < PuzzleSize; r++)
|
|
{
|
|
for (c = 0; c < PuzzleSize; c++)
|
|
{
|
|
PlayScene_SetLightRect(pGameWindow, &lightRect, c, r);
|
|
|
|
if (PtInRect(*pPosition, &lightRect))
|
|
{
|
|
// Toggle clicked-on light
|
|
GameEngine_ToggleLights(&(pGameWindow->Engine), c, r);
|
|
GameWindow_Draw(pGameWindow, false);
|
|
Sounds_PlayClickSnd(&(pGameWindow->Sounds));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (GameEngine_IsCompleted(&(pGameWindow->Engine)))
|
|
{
|
|
// Level was completed in the last click
|
|
GameEngine_CompleteLevel(&(pGameWindow->Engine));
|
|
GameWindow_Draw(pGameWindow, false);
|
|
GameSave_SaveData(&(pGameWindow->GameSave), &(pGameWindow->Engine));
|
|
GameWindow_SetScene(pGameWindow, LevelEnd);
|
|
Sounds_PlayDoneSnd(&(pGameWindow->Sounds));
|
|
}
|
|
}
|
|
else if (PtInRect(*pPosition, &(pGameWindow->PlayScene.HUDRect)))
|
|
{
|
|
// Click within HUD
|
|
|
|
if (PtInRect(*pPosition, &(pGameWindow->PlayScene.RetryButtonRect)))
|
|
{
|
|
// Click on retry button, reset level
|
|
GameEngine_ResetLevel(&(pGameWindow->Engine));
|
|
GameWindow_Draw(pGameWindow, false);
|
|
Sounds_PlayRetrySnd(&(pGameWindow->Sounds));
|
|
}
|
|
else if (PtInRect(*pPosition, &(pGameWindow->PlayScene.SoundButtonRect)))
|
|
{
|
|
// Click on sound button
|
|
GameWindow_ToggleSound(pGameWindow);
|
|
}
|
|
}
|
|
}
|