Added offscreen rendering via WindowBuffer to remove drawing flicker

This commit is contained in:
Jon Thysell 2021-11-21 16:29:38 -08:00
parent 85e3d0f003
commit 95dba45a0e
9 changed files with 87 additions and 8 deletions

View File

@ -27,8 +27,12 @@ void GameWindow_Init(GameWindow *pGameWindow)
// Load snd resources
Sounds_Init(&(pGameWindow->Sounds));
// Set port for first draw
// Initialize window buffer
WindowBuffer_Init(&(pGameWindow->WindowBuffer), pGameWindow->Window);
// Setup graphics before first draw
SetPort(pGameWindow->Window);
FillRect(&(pGameWindow->Window->portRect), WindowPattern);
GameWindow_SetScene(pGameWindow, Title);
}
@ -38,9 +42,10 @@ void GameWindow_Draw(const GameWindow *pGameWindow, bool fullRefresh)
GrafPtr oldPort;
const Rect *pContentRect = &(pGameWindow->Window->portRect);
// Save the current port
GetPort(&oldPort);
SetPort(pGameWindow->Window);
WindowBuffer_StartDraw(&(pGameWindow->WindowBuffer));
if (fullRefresh)
{
@ -64,6 +69,8 @@ void GameWindow_Draw(const GameWindow *pGameWindow, bool fullRefresh)
break;
}
WindowBuffer_EndDraw(&(pGameWindow->WindowBuffer));
SetPort(oldPort);
}

View File

@ -5,6 +5,7 @@
#define GAMEWINDOW_H
#include "MacCommon.h"
#include "WindowBuffer.h"
#include "GameEngine.h"
#include "Bitmaps.h"
#include "Sounds.h"
@ -15,6 +16,7 @@
typedef struct sGameWindow
{
WindowPtr Window;
WindowBuffer WindowBuffer;
GameEngine Engine;
Bitmaps Bitmaps;
Sounds Sounds;

View File

@ -85,13 +85,12 @@ void LevelEndScene_Click(GameWindow *pGameWindow, const Point *pPosition)
{
if (PtInRect(*pPosition, &(pGameWindow->LevelEndScene.RetryButtonRect)))
{
Sounds_PlayRetrySnd(&(pGameWindow->Sounds));
GameEngine_ResetLevel(&(pGameWindow->Engine));
GameWindow_SetScene(pGameWindow, Play);
Sounds_PlayRetrySnd(&(pGameWindow->Sounds));
}
else if (PtInRect(*pPosition, &(pGameWindow->LevelEndScene.NextButtonRect)))
{
Sounds_PlayClickSnd(&(pGameWindow->Sounds));
GameEngine_NextLevel(&(pGameWindow->Engine));
if (GameEngine_IsGameOver(&(pGameWindow->Engine)))

Binary file not shown.

Binary file not shown.

View File

@ -161,9 +161,9 @@ void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition)
if (PtInRect(*pPosition, &lightRect))
{
Sounds_PlayClickSnd(&(pGameWindow->Sounds));
GameEngine_ToggleLights(&(pGameWindow->Engine), c, r);
GameWindow_Draw(pGameWindow, false);
Sounds_PlayClickSnd(&(pGameWindow->Sounds));
break;
}
}
@ -183,9 +183,9 @@ void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition)
if (PtInRect(*pPosition, &(pGameWindow->PlayScene.RetryButtonRect)))
{
Sounds_PlayRetrySnd(&(pGameWindow->Sounds));
GameEngine_ResetLevel(&(pGameWindow->Engine));
GameWindow_Draw(pGameWindow, false);
Sounds_PlayRetrySnd(&(pGameWindow->Sounds));
}
else if (PtInRect(*pPosition, &(pGameWindow->PlayScene.SoundButtonRect)))
{

View File

@ -54,13 +54,11 @@ void TitleScene_Click(GameWindow *pGameWindow, const Point *pPosition)
{
if (PtInRect(*pPosition, &(pGameWindow->TitleScene.SetARect)))
{
Sounds_PlayClickSnd(&(pGameWindow->Sounds));
GameEngine_NewGame(&(pGameWindow->Engine), false);
GameWindow_SetScene(pGameWindow, Play);
}
else if (PtInRect(*pPosition, &(pGameWindow->TitleScene.SetBRect)))
{
Sounds_PlayClickSnd(&(pGameWindow->Sounds));
GameEngine_NewGame(&(pGameWindow->Engine), true);
GameWindow_SetScene(pGameWindow, Play);
}

56
src/WindowBuffer.c Normal file
View File

@ -0,0 +1,56 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// Licensed under the MIT License.
#include "WindowBuffer.h"
#include "MacCommon.h"
void WindowBuffer_Init(WindowBuffer *pWindowBuffer, const WindowPtr window)
{
int16_t width, height;
BitMap newBits;
pWindowBuffer->Window = window;
// Create a BitMap as the backing for the buffer,
// since System 6 doesn't have fancy GWorlds
width = window->portRect.right - window->portRect.left;
height = window->portRect.bottom - window->portRect.top;
SetRect(&newBits.bounds, 0, 0, width, height);
newBits.rowBytes = ((width + 31)/32) * 4;
newBits.baseAddr = NewPtr(height * newBits.rowBytes);
// Clear the bitmap
CopyBits(&newBits,
&newBits,
&newBits.bounds,
&newBits.bounds,
srcXor,
nil);
// Create the buffer and get it ready
pWindowBuffer->Buffer = (GrafPtr)NewPtr(sizeof(GrafPort));
OpenPort(pWindowBuffer->Buffer);
SetPort(pWindowBuffer->Buffer);
pWindowBuffer->Buffer->portRect = newBits.bounds;
RectRgn(pWindowBuffer->Buffer->visRgn, &newBits.bounds);
SetPortBits(&newBits);
}
void WindowBuffer_StartDraw(const WindowBuffer *pWindowBuffer)
{
// Set the buffer as the port for future QuickDraw commands
SetPort(pWindowBuffer->Buffer);
}
void WindowBuffer_EndDraw(const WindowBuffer *pWindowBuffer)
{
SetPort(pWindowBuffer->Window);
// Copy the buffer to the window
CopyBits(&(pWindowBuffer->Buffer->portBits),
&(pWindowBuffer->Window->portBits),
&(pWindowBuffer->Buffer->portRect),
&(pWindowBuffer->Window->portRect),
srcCopy, nil);
}

17
src/WindowBuffer.h Normal file
View File

@ -0,0 +1,17 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// Licensed under the MIT License.
#ifndef WINDOWBUFFER_H
#define WINDOWBUFFER_H
typedef struct sWindowBuffer
{
WindowPtr Window;
GrafPtr Buffer;
} WindowBuffer;
void WindowBuffer_Init(WindowBuffer *pWindowBuffer, const WindowPtr window);
void WindowBuffer_StartDraw(const WindowBuffer *pWindowBuffer);
void WindowBuffer_EndDraw(const WindowBuffer *pWindowBuffer);
#endif