Added Jooleem sources (I've changed them too much from the original, have to publish them to conform with LGPL)

This commit is contained in:
pelya
2010-07-26 15:25:35 +03:00
parent b95831357b
commit d5b27e5441
78 changed files with 11591 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
LibSdlVersion=1.2
AppName="Jooleem"
AppFullName=net.sourceforge.jooleem
ScreenOrientation=h
AppDataDownloadUrl="http://sites.google.com/site/xpelyax/Home/jooleem_0.1.4_data.zip?attredirects=0&d=1|http://sitesproxy.goapk.com/site/xpelyax/Home/jooleem_0.1.4_data.zip"
SdlVideoResize=y
NeedDepthBuffer=n
MultiABI=n
AppVersionCode=01403
AppVersionName="0.1.4.03"
CompiledLibraries="sdl_mixer sdl_image sdl_ttf"
AppCflags='-finline-functions -O2'
ReadmeText='^You may press "Home" now - the data will be downloaded in background'

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@@ -0,0 +1,72 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource1.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource1.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON "Jooleem.ico"
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -0,0 +1,21 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Jooleem", "Jooleem.vcproj", "{BF0C4EBF-38B1-47E4-A576-1CF34F82C283}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{BF0C4EBF-38B1-47E4-A576-1CF34F82C283}.Debug.ActiveCfg = Debug|Win32
{BF0C4EBF-38B1-47E4-A576-1CF34F82C283}.Debug.Build.0 = Debug|Win32
{BF0C4EBF-38B1-47E4-A576-1CF34F82C283}.Release.ActiveCfg = Release|Win32
{BF0C4EBF-38B1-47E4-A576-1CF34F82C283}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,351 @@
<?xml version="1.0" encoding="windows-1255"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="Jooleem"
ProjectGUID="{BF0C4EBF-38B1-47E4-A576-1CF34F82C283}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="FALSE">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="sdl.lib sdlmain.lib SDL_image.lib SDL_mixer.lib SDL_ttf.lib"
OutputFile="$(OutDir)/Jooleem.exe"
LinkIncremental="2"
IgnoreDefaultLibraryNames="msvcrt.lib"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/Jooleem.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="TRUE">
<Tool
Name="VCCLCompilerTool"
Optimization="3"
FavorSizeOrSpeed="1"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
StructMemberAlignment="0"
EnableEnhancedInstructionSet="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="sdl.lib sdlmain.lib SDL_image.lib SDL_mixer.lib SDL_ttf.lib"
OutputFile="$(OutDir)/Jooleem.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
<File
RelativePath=".\Jooleem.ico">
</File>
<File
RelativePath=".\Jooleem.rc">
</File>
</Filter>
<Filter
Name="UI"
Filter="">
<File
RelativePath=".\src\Ui\aboutwindow.cpp">
</File>
<File
RelativePath=".\src\Ui\aboutwindow.h">
</File>
<File
RelativePath=".\src\Ui\gameoverwindow.cpp">
</File>
<File
RelativePath=".\src\Ui\gameoverwindow.h">
</File>
<File
RelativePath=".\src\Ui\highscoreswindow.cpp">
</File>
<File
RelativePath=".\src\Ui\highscoreswindow.h">
</File>
<File
RelativePath=".\src\Ui\mainwindow.cpp">
</File>
<File
RelativePath=".\src\Ui\mainwindow.h">
</File>
<File
RelativePath=".\src\Ui\quitwindow.cpp">
</File>
<File
RelativePath=".\src\Ui\quitwindow.h">
</File>
<File
RelativePath=".\src\Ui\uibutton.cpp">
</File>
<File
RelativePath=".\src\Ui\uibutton.h">
</File>
<File
RelativePath=".\src\Ui\uicontrol.cpp">
</File>
<File
RelativePath=".\src\Ui\uicontrol.h">
</File>
<File
RelativePath=".\src\Ui\uilabel.cpp">
</File>
<File
RelativePath=".\src\Ui\uilabel.h">
</File>
<File
RelativePath=".\src\Ui\uiprogress.cpp">
</File>
<File
RelativePath=".\src\Ui\uiprogress.h">
</File>
<File
RelativePath=".\src\Ui\uitextbox.cpp">
</File>
<File
RelativePath=".\src\Ui\uitextbox.h">
</File>
<File
RelativePath=".\src\Ui\uiwindow.cpp">
</File>
<File
RelativePath=".\src\Ui\uiwindow.h">
</File>
</Filter>
<Filter
Name="common"
Filter="">
<File
RelativePath=".\src\common\common.h">
</File>
<File
RelativePath=".\src\common\effectmanager.cpp">
</File>
<File
RelativePath=".\src\common\effectmanager.h">
</File>
<File
RelativePath=".\src\common\events.h">
</File>
<File
RelativePath=".\src\common\filenames.h">
</File>
<File
RelativePath=".\src\common\font.cpp">
</File>
<File
RelativePath=".\src\common\font.h">
</File>
<File
RelativePath=".\src\common\fontmanager.cpp">
</File>
<File
RelativePath=".\src\common\fontmanager.h">
</File>
<File
RelativePath=".\src\common\musicmanager.cpp">
</File>
<File
RelativePath=".\src\common\musicmanager.h">
</File>
<File
RelativePath=".\src\common\soundmanager.cpp">
</File>
<File
RelativePath=".\src\common\soundmanager.h">
</File>
<File
RelativePath=".\src\common\surfacemanager.cpp">
</File>
<File
RelativePath=".\src\common\surfacemanager.h">
</File>
<File
RelativePath=".\src\common\texteffect.cpp">
</File>
<File
RelativePath=".\src\common\texteffect.h">
</File>
<File
RelativePath=".\src\common\trap.h">
</File>
</Filter>
<Filter
Name="engine"
Filter="">
<File
RelativePath=".\src\engine\aboutstate.cpp">
</File>
<File
RelativePath=".\src\engine\aboutstate.h">
</File>
<File
RelativePath=".\src\engine\engine.cpp">
</File>
<File
RelativePath=".\src\engine\engine.h">
</File>
<File
RelativePath=".\src\engine\enginestate.h">
</File>
<File
RelativePath=".\src\engine\gameonstate.cpp">
</File>
<File
RelativePath=".\src\engine\gameonstate.h">
</File>
<File
RelativePath=".\src\engine\gameoverstate.cpp">
</File>
<File
RelativePath=".\src\engine\gameoverstate.h">
</File>
<File
RelativePath=".\src\engine\highscoresstate.cpp">
</File>
<File
RelativePath=".\src\engine\highscoresstate.h">
</File>
<File
RelativePath=".\src\engine\introstate.cpp">
</File>
<File
RelativePath=".\src\engine\introstate.h">
</File>
<File
RelativePath=".\src\engine\pausedstate.cpp">
</File>
<File
RelativePath=".\src\engine\pausedstate.h">
</File>
<File
RelativePath=".\src\engine\quitstate.cpp">
</File>
<File
RelativePath=".\src\engine\quitstate.h">
</File>
</Filter>
<Filter
Name="game"
Filter="">
<File
RelativePath=".\src\game\board.cpp">
</File>
<File
RelativePath=".\src\game\board.h">
</File>
<File
RelativePath=".\src\game\game.cpp">
</File>
<File
RelativePath=".\src\game\game.h">
</File>
<File
RelativePath=".\src\game\highscores.cpp">
</File>
<File
RelativePath=".\src\game\highscores.h">
</File>
<File
RelativePath=".\src\game\selection.cpp">
</File>
<File
RelativePath=".\src\game\selection.h">
</File>
</Filter>
<File
RelativePath=".\src\main.cpp">
</File>
<File
RelativePath=".\src\resource.h">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,170 @@
Jooleem changelog
=================
Changes relevant to developers are marked with *
Changes relevant to users are marked with **
0.1.0 (Beta 1) [2005-08-08]
** First public release
0.1.1
[2005-08-08]
* Added PushUserEvent() to event.h
** Clicking a selected marble deselects it
** Executable installer
** Added link to website in the about window
** Fixed button behavior when clicking and dragging
-----
0.1.2
[2005-08-27]
** All new original sound effects by Dale North
** All new music track by Ryan Reilly
** When completing a rectangle, the points earned are shown
** Improved sound and music support
** Improved resource loading
** Minor fixes so the game compiles on OS X (GCC 4.0)
** Browser can now be launched on OS X
** Exceptions are shown in an OS specific message dialog
[2005-08-09]
* Fixed Level messages during game
[2005-08-10]
* Add redraw to label's text change, button's align etc
* Add to events.h - MakeUserEvent(&event, EVENT_CODE)
[2005-08-11]
** Minor fixes so it compiles on OS X (GCC 4.0)
[2005-08-12]
** Browser can now be launched on OS X
[2005-08-13]
** Exceptions are shown in an OS specific message dialog, and not in stderr
* Switched from strstream (deprecated) to sstream in trap.h
[2005-08-14]
* Added support for data fields to PushUserEvent
* Revised about window's layout
[2005-08-15]
* Renamed events: EVENT_SCORE -> EVENT_RECT_COMPLETE, EVENT_GAMEOVER -> EVENT_GAME_OVER, EVENT_LEVELOVER -> EVENT_NEW_LEVEL, EVENT_HISCORES -> EVENT_HIGH_SCORES
* Added CoordToPixels(), PixelsToCoord() and CoordToSDLRect() to Board
* On rectangle completion, the rectangle's screen location is pushed as data for EVENT_RECT_COMPLETE
** When completing a rectangle, the points earned are shown
* Added TextEffect and EffectManager classes
** Fixed: Two or more sounds can now play simultaneously
[2005-08-19]
* Added HandleUserEvents() to IntroState, GameOnState, gets called from HandleEvents
* Renamed: ChunkManager -> SoundManager
* Added events: EVENT_SELECTION_ADD, EVENT_SELECTION_CANCEL, EVENT_SELECTION_INVALID
[2005-08-20]
** The game can now handle music
* Added MusicManager class
* Added events: EVENT_TRACK_OVER
* Added folder: data/music
* Renamed folder: data/tiles -> data/marbles
* Added music loading and playing to various classes
* Removed Mix_Chunk member from all game classes (not UI), replaced with SoundManager::PlaySound()
[2005-08-24]
** All new original sound effects by Dale North
* Added Engine::LoadSounds()
[2005-08-26]
** Improved resource loading
* Replaced Engine::LoadSounds() with Engine::LoadResources()
* Moved all resource loading to Engine::LoadResources()
* Add Engine::InitStates()
* Added common/filenames.h - contains all resource file names
* Fixed Trap macro
* Removed AddResources() from all windows
* Changed all reference to "tiles" to "marbles"
* Added SetVolume() to music and sound manager
[2005-08-27]
** All new music track by Ryan Reilly
---
0.1.3
[2005-08-27]
* Fixed - music now loops properly in game mode
---
0.1.4
[2005-09-25]
New features:
* New Music track by Ryan Reily
* 4 new sound effects by Dale North
* When time is low, the time bar begins to flash and an alarm is sounded
* Pressing F12 takes a screenshot
* Upgraded to SDL 1.2.9
Fixes:
* When right clicking, the marble deselect sound is only played if any marbles are actually selected
* Fixed sound corruption issue that appeared on some systems (thanks to Malte Thiesen)
[2005-08-28]
** Upgraded to SDL 1.2.9
* Moved Blit from Font to SurfaceManager
* SoundManager assigns a channel to each new sound, and keeps track of it
* Added SoundManager::StopSound()
* Added events: EVENT_TIME_LOW, EVENT_TIME_OK
** Fixed: When right clicking, the marble deselect sound is only played if marbles are selected
[2005-08-30]
* Fixed TextEffect::Update so transparency will not underflow and make the effects opaque again
* Minor compile-pleasing warning-stomping
[2005-08-31]
* Minor fixes so it compiles on linux (case sensitivy, files end with a newline). Thanks to Jani Huhtanen.
[2005-09-01]
* Removed FULLSCREEN flag
* Changed post-increment to pre-increment for all loops (i++ to ++i)
* Moved all board related consts from common.h to board.h
* Converted sound effect files from WAV to Ogg
[2005-09-02]
** Fixed: The computer can keep playing indefinitely in the intro demo (thanks to mein@stare.nl)
[2005-09-03]
* Added UIProgressBar class
* Added SoundManager::StopAll()
** When time is low, the time bar begins to flash and an alert is sounded
* When restarting via the Game Over window, the music is restarted as well
* Changed audio buffer size to 2048, this may fix audio corruption
* Added DEFAULT_VOLUME to SoundManager and MusicManager
* Added Engine::GetMute()
[2005-09-04]
* Added visibility array to Board (bool m_isVisible[][])
[2005-09-05]
* Added new music track (track_01.ogg)
[2005-09-08]
* Added ScreenShot() to common.h
** Pressing F12 takes a screenshot
* Added EffectManager::AddGameOverEffect()
[2005-09-10]
* Added __FILE__ and __LINE__ to TRAP
[2005-10-10]
* Added game over effect to GameOverState::Enter
* Removed font objects from EffectManager, they are now loaded into the font manager
* Fixed in Engine::InitSDL(): Allocated audio channels to required number of effects
* Added Board::DropRectLogic, Board::ChangeVisibility, Board::RenderDroppingRect
* Added marble dropping effect to Board, currently diabled. define MARBLE_DROP to try it out
[2005-10-11]
* UIButton no longer contains a Mix_chunk, and uses the sound manager to play the click sound
* Added SoundManager::SetVolume(string, float) - set a sample's volume

View File

@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@@ -0,0 +1,3 @@
SRCS=$(shell find . -type f -name "*.cpp")
jooleem: $(SRCS) makefile
g++ -o $@ `sdl-config --cflags` $(SRCS) `sdl-config --libs` -lSDL_mixer -lSDL_ttf -lSDL_image

View File

@@ -0,0 +1,78 @@
Jooleem 0.1.3+
=============
http://jooleem.sourceforge.net/
== Introduction ==
Jooleem is a simple yet extremely addictive puzzle game. There is only one
rule: click on four marbles of the same color that form a rectangle. Time is
constantly running out, but you can earn time (and points) by forming
rectangles. The larger the rectangle, the more time and points are won.
Jooleem is free and open source software.
== Controls ==
Left click - Selects a marble. Selecting an already selected marble deselects it.
Right click - Deselects the currently selected marbles.
P - Pauses the game.
H - Hint.
F12 - Takes a screenshot. The file can be found in the "data/screenshot" folder.
Esc - Quits the game.
== Tips ==
* When stuck, click the hint button. But beware - you will pay a time penalty.
* Fill up the time bar to advance to the next level. The higher the level, the
more points you get per marble.
* The higher the level, the tougher the game. You earn less and less time per
marble as the game progresses.
== License ==
Jooleem is free and open source software. The code is released under the GNU
General Public License. The full license can be found in GPL.txt in the game's
folder.
All of the game's assets (music, sound effects, images) are original and
released under a Creative Commons deed. The relevant deed can by found at http://creativecommons.org/licenses/by-nc/2.5/.
== Development ==
Jooleem is developed using C++ and SDL, with cross platform compatibility in
mind. Currently, Windows and Linux versions of the game are available for
download. Mac OS X and RISC OS ports are planned.
You can follow the development process, submit bug reports and make feature
requests on the game's project page - http://sourceforge.net/projects/jooleem/.
== Credits ==
Project lead, code & graphics: Chai Braudo (braudo@users.sourceforge.net)
Music: Ryan Reilly (http://www.allacrost.org/)
Sound design: Dale North (http://www.dalenorth.com/northmedia)
Linux port: Jani Huhtanen
Beta testing: Iddo Braudo, Uri Grupel, Shany Tcshernichov and Ma'ayan Zigdon
The game was inspired by Nick Kouvaris' ZNAX
(http://www.freestuff.gr/lightforce/znax.php)
== Changelog ==
0.1.3
[2005-08-27]
* Fixed - music now loops properly in game mode
0.1.2
[2005-08-27]
* All new original sound effects by Dale North
* All new music track by Ryan Reilly
* When completing a rectangle, the points earned are shown
* Improved sound and music support
* Improved resource loading
* Minor fixes so the game compiles on OS X (GCC 4.0)
* Browser can now be launched on OS X
* Exceptions are shown in an OS specific message dialog
0.1.1 [2005-08-08]
* Clicking a selected marble deselects it
* Executable installer
* Added link to website in the about window
* Fixed button behavior when clicking and dragging
0.1.0 [2005-08-07]
* First public release
[2005-08-27]

View File

@@ -0,0 +1,15 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Jooleem.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 204
#define _APS_NEXT_COMMAND_VALUE 32768
#define _APS_NEXT_CONTROL_VALUE 201
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../UI/aboutwindow.h"
#include "../common/trap.h"
#include "../common/events.h"
#include "../common/common.h"
#include "../common/surfacemanager.h"
#include "../common/fontmanager.h"
#include "../common/soundmanager.h"
#include "../UI/uibutton.h"
#include "../UI/uilabel.h"
#include "../UI/uitextbox.h"
AboutWindow::AboutWindow(SDL_Surface *background):
UIWindow(background)
{
InitControls();
}
AboutWindow::~AboutWindow()
{
}
// Initializes the window's controls, and adds them to the
// control collection
void AboutWindow::InitControls()
{
SurfaceManager *surfaceMgr = SurfaceManager::GetInstance();
FontManager *fontMgr = FontManager::GetInstance();
SoundManager *sndMgr = SoundManager::GetInstance();
{
/////// Buttons ///////
SDL_Color buttonTextColor = {0, 0, 0, 0};
// Link:
// This is an unusual button. To simulate the graphical beahvior of a HTML link
// as viewed in a web broweser, the text is rendered several times (normal, hover,
// click) and these surfaces are passed to the button *as surfaces*. The button
// itself has no text.
SDL_Color linkNormalColor = {66, 128, 221, 0};
SDL_Color linkHoverColor = {75, 147, 255, 0};
SDL_Color linkClickColor = {131, 194, 255, 0};
Font *linkFont = fontMgr->GetFont("LinkFont");
linkFont->SetStyle(Font::STYLE_UNDERLINE); // Make the font underline
SDL_Surface *linkNormalSurface = surfaceMgr->AddSurface("LinkNormal",
linkFont->RenderPlain(Font::ALN_LEFT, linkNormalColor, APP_URL));
SDL_Surface *linkHoverSurface = surfaceMgr->AddSurface("LinkHover",
linkFont->RenderPlain(Font::ALN_LEFT, linkHoverColor, APP_URL));
SDL_Surface *linkClickSurface = surfaceMgr->AddSurface("LinkClick",
linkFont->RenderPlain(Font::ALN_LEFT, linkClickColor, APP_URL));
UIButton *linkButton = new UIButton();
linkButton->Set(0, 0, "ButtonClick",
linkNormalSurface, linkNormalSurface, linkHoverSurface, linkClickSurface,
linkNormalSurface, NULL);
linkButton->AddState(EVENT_WEBSITE, fontMgr->GetFont("MediumButtonFont"), " ", buttonTextColor);
linkButton->Align(UIControl::HALN_CENTER, UIControl::VALN_BOTTOM, 320, 241);
linkButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_LINK, linkButton);
// Close:
UIButton *closeButton = new UIButton();
closeButton->Set(0, 0, "ButtonClick",
surfaceMgr->GetSurface("MediumButtonNormal"), surfaceMgr->GetSurface("MediumButtonDisabled"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonClicked"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonMask"));
closeButton->AddState(EVENT_CLOSE, fontMgr->GetFont("MediumButtonFont"), "Close", buttonTextColor);
closeButton->Align(UIControl::HALN_CENTER, UIControl::VALN_BOTTOM, 320, 355);
closeButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_CLOSE, closeButton);
/////// Labels ///////
SDL_Color titleColor = {64, 64, 64, 0};
SDL_Color labelTextColor = {0, 0, 0, 0};
// Title:
UILabel *titleLabel = new UILabel();
titleLabel->Set(0, 0, NULL, fontMgr->GetFont("WindowTitleFont"), titleColor);
titleLabel->SetText(UIControl::HALN_LEFT, "About");
titleLabel->Align(UIControl::HALN_CENTER, UIControl::VALN_TOP, 320, 125);
AddControl(LBL_TITLE, titleLabel);
// Logo:
UILabel *logoLabel = new UILabel();
logoLabel->Set(0, 0, surfaceMgr->GetSurface("Logo"), NULL, labelTextColor);
logoLabel->Align(UIControl::HALN_CENTER, UIControl::VALN_TOP, 320, 153);
AddControl(LBL_LOGO, logoLabel);
// Application name and version:
UILabel *appVersionLabel = new UILabel();
appVersionLabel->Set(0, 0, NULL, fontMgr->GetFont("AppVersionFont"), labelTextColor);
appVersionLabel->SetText(UIControl::HALN_LEFT, "%s %s", APP_NAME.c_str(), APP_VERSION.c_str());
appVersionLabel->Align(UIControl::HALN_CENTER, UIControl::VALN_BOTTOM, 320, 219);
AddControl(LBL_APP, appVersionLabel);
// Credits:
UILabel *creditsLabel = new UILabel();
creditsLabel->Set(0, 0, NULL, fontMgr->GetFont("CreditsFont"), labelTextColor);
creditsLabel->SetText( UIControl::HALN_CENTER,
"Developed by Chai Braudo\n"
"Music by Ryan Reilly\n"
"Sound design by Dale North");
creditsLabel->Align(UIControl::HALN_CENTER, UIControl::VALN_BOTTOM, 320, 289);
AddControl(LBL_CREDITS, creditsLabel);
// License:
UILabel *licenseLabel = new UILabel();
licenseLabel->Set(0, 0, NULL, fontMgr->GetFont("LicenseFont"), labelTextColor);
licenseLabel->SetText( UIControl::HALN_LEFT,
"This program is free, open source software\n"
"released under the GNU General Public License.");
licenseLabel->Align(UIControl::HALN_CENTER, UIControl::VALN_BOTTOM, 320, 318);
AddControl(LBL_LICENSE, licenseLabel);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ABOUTWINDOW_H_
#define _ABOUTWINDOW_H_
// The about window.
#include "../UI/uiwindow.h"
#include "SDL.h"
class AboutWindow: public UIWindow
{
public:
enum Controls {
// Buttons:
BTN_LINK, // Website link
BTN_CLOSE, // Close
// Labels:
LBL_TITLE, // Window title
LBL_LOGO, // Logo
LBL_APP, // Application name and version
LBL_CREDITS, // Game credits
LBL_LICENSE, // License info
};
// Constructor / destructor:
AboutWindow(SDL_Surface *background);
~AboutWindow();
private:
void InitControls(); // Initializes the window's controls, and adds them to the control collection
};
#endif

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../UI/gameoverwindow.h"
#include "../common/trap.h"
#include "../common/events.h"
#include "../common/surfacemanager.h"
#include "../common/fontmanager.h"
#include "../common/soundmanager.h"
#include "../UI/uibutton.h"
#include "../UI/uilabel.h"
#include "../UI/uitextbox.h"
#include "../game/highscores.h"
GameOverWindow::GameOverWindow(SDL_Surface *background):
UIWindow(background)
{
InitControls();
}
GameOverWindow::~GameOverWindow()
{
}
// Initializes the window's controls, and adds them to the
// control collection
void GameOverWindow::InitControls()
{
SurfaceManager *surfaceMgr = SurfaceManager::GetInstance();
FontManager *fontMgr = FontManager::GetInstance();
SoundManager *sndMgr = SoundManager::GetInstance();
{
/////// Buttons ///////
SDL_Color buttonTextColor = {0, 0, 0, 0};
// OK:
UIButton *okButton = new UIButton();
okButton->Set(0, 0, "ButtonClick",
surfaceMgr->GetSurface("MediumButtonNormal"), surfaceMgr->GetSurface("MediumButtonDisabled"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonClicked"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonMask"));
okButton->AddState(EVENT_CLOSE, fontMgr->GetFont("MediumButtonFont"), "OK", buttonTextColor);
okButton->Align(UIControl::HALN_CENTER, UIControl::VALN_BOTTOM, 320, 373);
okButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_OK, okButton);
// Quit:
UIButton *quitButton = new UIButton();
quitButton->Set(0, 0, "ButtonClick",
surfaceMgr->GetSurface("MediumButtonNormal"), surfaceMgr->GetSurface("MediumButtonDisabled"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonClicked"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonMask"));
SDL_Event event;
event.type = SDL_QUIT;
quitButton->AddState(event, fontMgr->GetFont("MediumButtonFont"), "Quit", buttonTextColor);
quitButton->Align(UIControl::HALN_RIGHT, UIControl::VALN_BOTTOM, 435, 373);
quitButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_QUIT, quitButton);
// Restart:
UIButton *restartButton = new UIButton();
restartButton->Set(0, 0, "ButtonClick",
surfaceMgr->GetSurface("MediumButtonNormal"), surfaceMgr->GetSurface("MediumButtonDisabled"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonClicked"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonMask"));
restartButton->AddState(EVENT_RESTART, fontMgr->GetFont("MediumButtonFont"), "Restart", buttonTextColor);
restartButton->Align(UIControl::HALN_LEFT, UIControl::VALN_BOTTOM, 205, 373);
restartButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_RESTART, restartButton);
/////// Labels ///////
SDL_Color titleColor = {64, 64, 64, 0};
SDL_Color labelTextColor = {0, 0, 0, 0};
// Title:
UILabel *titleLabel = new UILabel();
titleLabel->Set(0, 0, NULL, fontMgr->GetFont("WindowTitleFont"), titleColor);
titleLabel->SetText(UIControl::HALN_LEFT, "Game Over");
titleLabel->Align(UIControl::HALN_CENTER, UIControl::VALN_TOP, 320, 108);
AddControl(LBL_TITLE, titleLabel);
// Congratulations message:
UILabel *congratsLabel = new UILabel();
congratsLabel->Set(0, 0, NULL, fontMgr->GetFont("GameOverCongratsFont"), labelTextColor);
congratsLabel->SetText(UIControl::HALN_LEFT,
"Congratulations, you got a\n"
"high score!\n"
"Please enter your name.");
congratsLabel->Align(UIControl::HALN_LEFT, UIControl::VALN_TOP, 204, 133);
AddControl(LBL_CONGRATS, congratsLabel);
// Final score:
UILabel *scoreLabel = new UILabel();
scoreLabel->Set(0, 0, NULL, fontMgr->GetFont("GameOverScoreFont"), labelTextColor);
AddControl(LBL_SCORE, scoreLabel);
// Statistics description:
UILabel *statsDescLabel = new UILabel();
statsDescLabel->Set(0, 0, NULL, fontMgr->GetFont("GameOverStatsFont"), labelTextColor);
statsDescLabel->SetText(UIControl::HALN_LEFT,
"Level reached:\n"
"Total game time:\n"
"Marbles cleared:\n"
"Rectangles cleared:\n"
"Avg. rectangle size:\n"
"Best move:\n"
"Perfect moves:");
statsDescLabel->Align(UIControl::HALN_LEFT, UIControl::VALN_BOTTOM,
203, 337);
AddControl(LBL_STATS_DESC, statsDescLabel);
// Statistics values:
UILabel *statsValLabel = new UILabel();
statsValLabel->Set(0, 0, NULL, fontMgr->GetFont("GameOverStatsFont"), labelTextColor);
AddControl(LBL_STATS_VAL, statsValLabel);
// Text box:
UITextBox *textBox = new UITextBox();
textBox->Set(205, 188,
16, 6,
surfaceMgr->GetSurface("TextBoxBackground"),
surfaceMgr->GetSurface("TextBoxCursor"),
fontMgr->GetFont("TextBoxFont"),
titleColor);
AddControl(TXT_NAME, textBox);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _GAMEOVERWINDOW_H_
#define _GAMEOVERWINDOW_H_
// This window is displayed when the game is over.
// It shows the final score and various game statitics.
#include "../UI/uiwindow.h"
#include "SDL.h"
class GameOverWindow: public UIWindow
{
public:
enum Controls {
// Buttons:
BTN_OK, // OK
BTN_QUIT, // Quit
BTN_RESTART, // Restart
// Labels:
LBL_TITLE, // Window title
LBL_CONGRATS, // Congratulations message
LBL_SCORE, // Final score
LBL_STATS_DESC, // Statistics description
LBL_STATS_VAL, // Statistics values
// Text box:
TXT_NAME, // Enter the player's name
};
// Constructor / destructor:
GameOverWindow(SDL_Surface *background);
~GameOverWindow();
private:
void InitControls(); // Initializes the window's controls, and adds them to the control collection
};
#endif

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../UI/highscoreswindow.h"
#include "../common/trap.h"
#include "../common/events.h"
#include "../common/surfacemanager.h"
#include "../common/fontmanager.h"
#include "../common/soundmanager.h"
#include "../UI/uibutton.h"
#include "../UI/uilabel.h"
#include "../game/highscores.h"
HighScoresWindow::HighScoresWindow(SDL_Surface *background):
UIWindow(background)
{
InitControls();
}
HighScoresWindow::~HighScoresWindow()
{
}
// Initializes the window's controls, and adds them to the
// control collection
void HighScoresWindow::InitControls()
{
SurfaceManager *surfaceMgr = SurfaceManager::GetInstance();
FontManager *fontMgr = FontManager::GetInstance();
SoundManager *sndMgr = SoundManager::GetInstance();
{
/////// Buttons ///////
SDL_Color buttonTextColor = {0, 0, 0, 0};
// Close:
UIButton *closeButton = new UIButton();
closeButton->Set(0, 0, "ButtonClick",
surfaceMgr->GetSurface("MediumButtonNormal"), surfaceMgr->GetSurface("MediumButtonDisabled"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonClicked"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonMask"));
closeButton->AddState(EVENT_CLOSE, fontMgr->GetFont("MediumButtonFont"), "Close", buttonTextColor);
closeButton->Align(UIControl::HALN_CENTER, UIControl::VALN_BOTTOM, 320, 375);
closeButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_CLOSE, closeButton);
// Restart:
UIButton *restartButton = new UIButton();
restartButton->Set(0, 0, "ButtonClick",
surfaceMgr->GetSurface("MediumButtonNormal"), surfaceMgr->GetSurface("MediumButtonDisabled"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonClicked"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonMask"));
restartButton->AddState(EVENT_RESTART, fontMgr->GetFont("MediumButtonFont"), "Restart", buttonTextColor);
restartButton->Align(UIControl::HALN_LEFT, UIControl::VALN_BOTTOM,
m_x + 29, m_y + m_h - 34);
restartButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_RESTART, restartButton);
// Quit:
UIButton *quitButton = new UIButton();
quitButton->Set(0, 0, "ButtonClick",
surfaceMgr->GetSurface("MediumButtonNormal"), surfaceMgr->GetSurface("MediumButtonDisabled"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonClicked"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonMask"));
SDL_Event event;
event.type = SDL_QUIT;
quitButton->AddState(event, fontMgr->GetFont("MediumButtonFont"), "Quit", buttonTextColor);
quitButton->Align(UIControl::HALN_RIGHT, UIControl::VALN_BOTTOM,
m_x + m_w - 40 + 13, m_y + m_h - 34);
quitButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_QUIT, quitButton);
/////// Vectors ///////
SDL_Color tableTextColor = {0, 0, 0, 0};
vector<UIControl *> indexVec; // Index
vector<UIControl *> namesVec; // Names
vector<UIControl *> scoresVec; // Scores
for (Uint16 i = 0 ; i < NUM_OF_HIGH_SCORES ; ++i)
{
// Index:
UILabel *index = new UILabel();
index->Set(0, 0, NULL, fontMgr->GetFont("HighScoresFont"), tableTextColor);
index->SetText(UIControl::HALN_LEFT, "%d", i + 1);
index->Align(UIControl::HALN_LEFT, UIControl::VALN_TOP, 207, 136 + 20 * i);
indexVec.push_back(index);
// Names:
UILabel *name = new UILabel();
name->Set(0, 0, NULL, fontMgr->GetFont("HighScoresFont"), tableTextColor);
name->SetText(UIControl::HALN_LEFT, "-");
name->Align(UIControl::HALN_LEFT, UIControl::VALN_TOP, 233, 136 + 20 * i);
namesVec.push_back(name);
// Scores:
UILabel *score = new UILabel();
score->Set(0, 0, NULL, fontMgr->GetFont("HighScoresFont"), tableTextColor);
score->SetText(UIControl::HALN_LEFT, "-");
score->Align(UIControl::HALN_RIGHT, UIControl::VALN_TOP, 435, 136 + 20 * i);
scoresVec.push_back(score);
}
AddControlVector(VEC_INDEX, indexVec);
AddControlVector(VEC_NAMES, namesVec);
AddControlVector(VEC_SCORES, scoresVec);
/////// Labels ///////
SDL_Color titleColor = {64, 64, 64, 0};
// Title:
UILabel *titleLabel = new UILabel();
titleLabel->Set(0, 0, NULL, fontMgr->GetFont("WindowTitleFont"), titleColor);
titleLabel->SetText(UIControl::HALN_LEFT, "High Scores");
titleLabel->Align(UIControl::HALN_CENTER, UIControl::VALN_TOP, 320, 106);
AddControl(LBL_TITLE, titleLabel);
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HIGHSCORESWINDOW_H_
#define _HIGHSCORESWINDOW_H_
// The high scores window.
#include "../UI/uiwindow.h"
#include "SDL.h"
class HighScoresWindow: public UIWindow
{
public:
enum Controls {
// Buttons:
BTN_CLOSE, // Close
BTN_RESTART, // Restart
BTN_QUIT, // Quit
// Vectors (the names and scores are a vector of labels):
VEC_INDEX, // Scores index (1st place, 2nd...)
VEC_NAMES, // Player names
VEC_SCORES, // Scores
// Labels:
LBL_TITLE, // Window title
};
// Constructor / destructor:
HighScoresWindow(SDL_Surface *background);
~HighScoresWindow();
private:
void InitControls(); // Initializes the window's controls, and adds them to the control collection
};
#endif

View File

@@ -0,0 +1,172 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../UI/mainwindow.h"
#include "../common/trap.h"
#include "../common/events.h"
#include "../common/surfacemanager.h"
#include "../common/fontmanager.h"
#include "../common/soundmanager.h"
#include "../UI/uibutton.h"
#include "../UI/uilabel.h"
#include "../UI/uiprogress.h"
MainWindow::MainWindow(SDL_Surface *background):
UIWindow(background)
{
InitControls();
}
MainWindow::~MainWindow()
{
}
// Initializes the window's controls, and adds them to the
// control collection
void MainWindow::InitControls()
{
SurfaceManager *surfaceMgr = SurfaceManager::GetInstance();
FontManager *fontMgr = FontManager::GetInstance();
SoundManager *sndMgr = SoundManager::GetInstance();
{
/////// Buttons ///////
SDL_Color buttonTextColor = {0, 0, 0, 0};
SDL_Event event;
// Start / restart:
UIButton *startButton = new UIButton();
startButton->Set(20, 344, "ButtonClick",
surfaceMgr->GetSurface("LargeButtonNormal"), surfaceMgr->GetSurface("LargeButtonDisabled"),
surfaceMgr->GetSurface("LargeButtonHover"), surfaceMgr->GetSurface("LargeButtonClicked"),
surfaceMgr->GetSurface("LargeButtonHover"), surfaceMgr->GetSurface("LargeButtonMask"));
startButton->AddState(EVENT_START, fontMgr->GetFont("LargeButtonFont"), "Start", buttonTextColor);
startButton->AddState(EVENT_RESTART, fontMgr->GetFont("LargeButtonFont"), "Restart", buttonTextColor);
startButton->SetState(EVENT_START);
startButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_START, startButton);
// Pause / resume:
UIButton *pauseButton = new UIButton();
pauseButton->Set(20, 276, "ButtonClick",
surfaceMgr->GetSurface("LargeButtonNormal"), surfaceMgr->GetSurface("LargeButtonDisabled"),
surfaceMgr->GetSurface("LargeButtonHover"), surfaceMgr->GetSurface("LargeButtonClicked"),
surfaceMgr->GetSurface("LargeButtonHover"), surfaceMgr->GetSurface("LargeButtonMask"));
pauseButton->AddState(EVENT_PAUSE, fontMgr->GetFont("LargeButtonFont"), "Pause", buttonTextColor);
pauseButton->AddState(EVENT_RESUME, fontMgr->GetFont("LargeButtonFont"), "Resume", buttonTextColor);
pauseButton->SetState(EVENT_PAUSE);
pauseButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_PAUSE, pauseButton);
// Quit:
UIButton *quitButton = new UIButton();
quitButton->Set(20, 412, "ButtonClick",
surfaceMgr->GetSurface("LargeButtonNormal"), surfaceMgr->GetSurface("LargeButtonDisabled"),
surfaceMgr->GetSurface("LargeButtonHover"), surfaceMgr->GetSurface("LargeButtonClicked"),
surfaceMgr->GetSurface("LargeButtonHover"), surfaceMgr->GetSurface("LargeButtonMask"));
event.type = SDL_QUIT;
quitButton->AddState(event, fontMgr->GetFont("LargeButtonFont"), "Quit", buttonTextColor);
quitButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_QUIT, quitButton);
// Hint:
UIButton *hintButton = new UIButton();
hintButton->Set(20, 208, "ButtonClick",
surfaceMgr->GetSurface("LargeButtonNormal"), surfaceMgr->GetSurface("LargeButtonDisabled"),
surfaceMgr->GetSurface("LargeButtonHover"), surfaceMgr->GetSurface("LargeButtonClicked"),
surfaceMgr->GetSurface("LargeButtonHover"), surfaceMgr->GetSurface("LargeButtonMask"));
hintButton->AddState(EVENT_HINT, fontMgr->GetFont("LargeButtonFont"), "Hint", buttonTextColor);
hintButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_HINT, hintButton);
// Mute / unmute:
UIButton *muteButton = new UIButton();
muteButton->Set(20, 140, "ButtonClick",
surfaceMgr->GetSurface("SmallButtonNormal"), surfaceMgr->GetSurface("SmallButtonDisabled"),
surfaceMgr->GetSurface("SmallButtonHover"), surfaceMgr->GetSurface("SmallButtonClicked"),
surfaceMgr->GetSurface("SmallButtonHover"), surfaceMgr->GetSurface("SmallButtonMask"));
muteButton->AddState(EVENT_MUTE, surfaceMgr->GetSurface("MuteButton"),
fontMgr->GetFont("TooltipFont"), "Mute");
muteButton->AddState(EVENT_UNMUTE, surfaceMgr->GetSurface("UnmuteButton"),
fontMgr->GetFont("TooltipFont"), "Unmute");
muteButton->SetState(EVENT_MUTE);
muteButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_MUTE, muteButton);
// About:
UIButton *aboutButton = new UIButton();
aboutButton->Set(120, 140, "ButtonClick",
surfaceMgr->GetSurface("SmallButtonNormal"), surfaceMgr->GetSurface("SmallButtonDisabled"),
surfaceMgr->GetSurface("SmallButtonHover"), surfaceMgr->GetSurface("SmallButtonClicked"),
surfaceMgr->GetSurface("SmallButtonHover"), surfaceMgr->GetSurface("SmallButtonMask"));
aboutButton->AddState(EVENT_ABOUT, surfaceMgr->GetSurface("AboutButton"),
fontMgr->GetFont("TooltipFont"), "About");
aboutButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_ABOUT, aboutButton);
// High scores:
UIButton *hiscoreButton = new UIButton();
hiscoreButton->Set(70, 140, "ButtonClick",
surfaceMgr->GetSurface("SmallButtonNormal"), surfaceMgr->GetSurface("SmallButtonDisabled"),
surfaceMgr->GetSurface("SmallButtonHover"), surfaceMgr->GetSurface("SmallButtonClicked"),
surfaceMgr->GetSurface("SmallButtonHover"), surfaceMgr->GetSurface("SmallButtonMask"));
hiscoreButton->AddState(EVENT_HIGH_SCORES, surfaceMgr->GetSurface("HighScoresButton"),
fontMgr->GetFont("TooltipFont"), "High Scores");
hiscoreButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_HISCORES, hiscoreButton);
/////// Labels ///////
SDL_Color scoreTextColor = {64, 64, 64, 0};
// Score:
UILabel *scoreLabel = new UILabel();
scoreLabel->Set(20, 70, surfaceMgr->GetSurface("ScoreLabel"), fontMgr->GetFont("ScoreFont"),
scoreTextColor);
AddControl(LBL_SCORE, scoreLabel);
// Level:
UILabel *levelLabel = new UILabel();
levelLabel->Set(20, 55, NULL, fontMgr->GetFont("LevelFont"),
scoreTextColor);
AddControl(LBL_LEVEL, levelLabel);
/*
// Time bar:
UILabel *timeBarLabel = new UILabel();
timeBarLabel->Set(192, 454, surfaceMgr->GetSurface("TimeBar"), NULL, scoreTextColor);
AddControl(LBL_TIMEBAR, timeBarLabel);
*/
/////// Progress bar ///////
UIProgressBar *timeBar = new UIProgressBar();
timeBar->Set(192, 454, NULL, surfaceMgr->GetSurface("TimeBar"), surfaceMgr->GetSurface("TimeBarFlash"),
surfaceMgr->GetSurface("TimeBarPaused"));
AddControl(PRG_TIMEBAR, timeBar);
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _MAINWINDOW_H_
#define _MAINWINDOW_H_
// The main window.
#include "../UI/uiwindow.h"
#include "SDL.h"
class MainWindow: public UIWindow
{
public:
enum Controls {
// Buttons:
BTN_START, // Start / restart
BTN_PAUSE, // Pause / resume
BTN_QUIT, // Quit
BTN_HINT, // Hint
BTN_MUTE, // Mute
BTN_ABOUT, // About
BTN_HISCORES, // High scores
// Labels:
LBL_SCORE, // Game score
LBL_LEVEL, // Game level
//LBL_TIMEBAR, // The time bar
// Windows:
WND_ABOUT, // About window
WND_HISCORES, // High scores window
// Progress bar:
PRG_TIMEBAR, // Time bar
};
// Constructor / destructor:
MainWindow(SDL_Surface *background);
~MainWindow();
private:
void InitControls(); // Initializes the window's controls, and adds them to the control collection
};
#endif

View File

@@ -0,0 +1,103 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../UI/quitwindow.h"
#include "../common/trap.h"
#include "../common/events.h"
#include "../common/surfacemanager.h"
#include "../common/fontmanager.h"
#include "../common/soundmanager.h"
#include "../UI/uibutton.h"
#include "../UI/uilabel.h"
QuitWindow::QuitWindow(SDL_Surface *background):
UIWindow(background)
{
InitControls();
}
QuitWindow::~QuitWindow()
{
}
// Initializes the window's controls, and adds them to the
// control collection
void QuitWindow::InitControls()
{
SurfaceManager *surfaceMgr = SurfaceManager::GetInstance();
FontManager *fontMgr = FontManager::GetInstance();
SoundManager *sndMgr = SoundManager::GetInstance();
{
/////// Buttons ///////
SDL_Color buttonTextColor = {0, 0, 0, 0};
// Close:
UIButton *quitButton = new UIButton();
quitButton->Set(0, 0, "ButtonClick",
surfaceMgr->GetSurface("MediumButtonNormal"), surfaceMgr->GetSurface("MediumButtonDisabled"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonClicked"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonMask"));
SDL_Event event;
event.type = SDL_QUIT;
quitButton->AddState(event, fontMgr->GetFont("MediumButtonFont"), "Quit", buttonTextColor);
quitButton->Align(UIControl::HALN_LEFT, UIControl::VALN_BOTTOM, 328, 290);
quitButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_QUIT, quitButton);
// Play:
UIButton *playButton = new UIButton();
playButton->Set(0, 0, "ButtonClick",
surfaceMgr->GetSurface("MediumButtonNormal"), surfaceMgr->GetSurface("MediumButtonDisabled"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonClicked"),
surfaceMgr->GetSurface("MediumButtonHover"), surfaceMgr->GetSurface("MediumButtonMask"));
playButton->AddState(EVENT_CLOSE, fontMgr->GetFont("MediumButtonFont"), "Play", buttonTextColor);
playButton->Align(UIControl::HALN_RIGHT, UIControl::VALN_BOTTOM, 312, 290);
playButton->SetMode(UIButton::MODE_NORMAL);
AddControl(BTN_PLAY, playButton);
/////// Labels ///////
SDL_Color titleColor = {64, 64, 64, 0};
SDL_Color labelTextColor = {0, 0, 0, 0};
// Title:
UILabel *titleLabel = new UILabel();
titleLabel->Set(0, 0, NULL, fontMgr->GetFont("WindowTitleFont"), titleColor);
titleLabel->SetText(UIControl::HALN_LEFT, "Quit");
titleLabel->Align(UIControl::HALN_CENTER, UIControl::VALN_TOP, 320, 191);
AddControl(LBL_TITLE, titleLabel);
// Dialog text:
UILabel *textLabel = new UILabel();
textLabel->Set(0, 0, NULL, fontMgr->GetFont("DialogTextFont"), labelTextColor);
textLabel->SetText( UIControl::HALN_LEFT,
"Are you sure you want to\n"
"quit Jooleem?");
textLabel->Align(UIControl::HALN_CENTER, UIControl::VALN_BOTTOM, 320, 252);
AddControl(LBL_TEXT, textLabel);
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _QUITWINDOW_H_
#define _QUITWINDOW_H_
// The quit dialog window.
#include "../UI/uiwindow.h"
#include "SDL.h"
class QuitWindow: public UIWindow
{
public:
enum Controls {
// Buttons:
BTN_QUIT, // Close
BTN_PLAY, // Play
// Labels:
LBL_TITLE, // Window title
LBL_TEXT, // Dialog text
};
// Constructor / destructor:
QuitWindow(SDL_Surface *background);
~QuitWindow();
private:
void InitControls(); // Initializes the window's controls, and adds them to the control collection
};
#endif

View File

@@ -0,0 +1,559 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../UI/uibutton.h"
#include "../common/trap.h"
#include "../common/events.h"
#include "../common/soundmanager.h"
#include "SDL_image.h"
#include <iostream>
using namespace std;
// Constructor - initialize the data members:
UIButton::UIButton()
{
m_maskW = m_maskH = 0;
m_clickSoundID = "";
for (int i = 0 ; i < MODE_MAX ; ++i)
m_surfaces[i] = NULL;
m_currentMode = MODE_DISABLED;
m_enabled = true;
m_visible = true;
m_mask = NULL;
m_showTooltip = false;
m_isFlashing = false;
// Populate the tooltip callback timer parameter struct:
m_tooltipParam.currentMode = &m_currentMode;
m_tooltipParam.showTooltip = &m_showTooltip;
}
// Destructor - Free the tooltip surfaces memory for all the states:
UIButton::~UIButton()
{
SDL_RemoveTimer(m_timerID);
map<int, State>::iterator itr;
for (itr = m_states.begin() ; itr != m_states.end() ; itr++)
{
if ((itr->second).toolTipSurface != NULL)
SDL_FreeSurface((itr->second).toolTipSurface);
}
delete []m_mask;
}
// Set the button's location, click sounds, surfaces and mask:
void UIButton::Set(Uint16 x, Uint16 y, string clickSoundID, SDL_Surface* normal,
SDL_Surface* disabled, SDL_Surface* hover, SDL_Surface* clicked,
SDL_Surface* flash, SDL_Surface* mask)
{
SetLocation(x, y);
m_clickSoundID = clickSoundID;
m_surfaces[MODE_NORMAL] = normal;
m_surfaces[MODE_DISABLED] = disabled;
m_surfaces[MODE_HOVER] = hover;
m_surfaces[MODE_CLICKED] = clicked;
m_surfaces[MODE_FLASH] = flash;
if (mask != NULL)
{
m_w = (Sint16) mask->w;
m_h = (Sint16) mask->h;
}
else
{
m_w = (Sint16) normal->w;
m_h = (Sint16) normal->h;
}
MakeMask(mask);
}
// Handle a mouse down event:
bool UIButton::MouseDown(Uint16 x, Uint16 y)
{
if (m_states.size() == 0 || m_visible == false || m_currentMode == MODE_DISABLED ||
m_currentMode == MODE_CLICKED)
return false;
if (IsInButton(x, y))
{
m_currentMode = MODE_CLICKED;
return true;
}
else
return false;
}
// Handle a mouse down event:
bool UIButton::MouseUp(Uint16 x, Uint16 y)
{
if (m_states.size() == 0 || m_visible == false || m_currentMode == MODE_DISABLED
|| m_currentMode != MODE_CLICKED)
return false;
if (IsInButton(x, y))
return Click();
else
{
m_currentMode = MODE_NORMAL;
return true;
}
}
// Are the coordinates inside the button (use mask)?
bool UIButton::IsInButton(Uint16 x, Uint16 y)
{
Sint32 X = x - m_x;
Sint32 Y = y - m_y;
// If no mask is defined, do a simple boundry check:
if (m_mask == NULL)
return (X > 0 && Y > 0 && X <= m_surfaces[m_currentMode]->w && Y <= m_surfaces[m_currentMode]->h);
// Otherwise, check the mask:
if (X < 0 || Y < 0 || X >= m_maskW || Y >= m_maskH)
return false;
return ((m_mask[Y * m_maskW + X] == 0)? false : true);
}
// Are the coordinates inside the button?
bool UIButton::IsInRect(Uint16 x, Uint16 y)
{
return (m_x <= x && m_x + m_w >= x && m_y <= y && m_w + m_h >= y);
}
// An unconditional click:
bool UIButton::Click()
{
if (m_states.size() == 0 || m_visible == false || m_currentMode == MODE_DISABLED)
return false;
// Play the sound:
if (m_clickSoundID != "")
SoundManager::GetInstance()->PlaySound(m_clickSoundID);
// Push the event into the even queue:
SDL_PushEvent(&m_currentState.event);
// Switch to clicked mode:
m_currentMode = MODE_NORMAL;
return true;
}
// Clicks the button if the coords are valid:
bool UIButton::Click(Uint16 x, Uint16 y)
{
if (IsInButton(x, y))
return Click();
else
return false;
}
// Switch to hover mode.
bool UIButton::Hover()
{
m_currentMode = MODE_HOVER;
return true;
}
// Switch to hover mode, if the cursor is over the button.
bool UIButton::Hover(Uint16 x, Uint16 y)
{
if (m_states.size() == 0 || m_visible == false || m_currentMode == MODE_DISABLED
|| m_currentMode == MODE_CLICKED || m_currentMode == MODE_FLASH)
return false;
if (IsInButton(x, y))
{
if (m_currentMode != MODE_HOVER) // We just started hovering
{
m_currentMode = MODE_HOVER;
// Set the tooltip callback timer:
m_timerID = SDL_AddTimer(TOOLTIP_DELAY, TriggerTooltip, &m_tooltipParam);
return true;
}
}
else if (m_currentMode == MODE_HOVER) // Restore to normal when no longer over button
{
m_currentMode = MODE_NORMAL;
m_showTooltip = false;
SDL_RemoveTimer(m_timerID);
return true;
}
return false;
}
// Switch to disabled mode.
// Clicks on the button will be ignored.
void UIButton::Disable()
{
m_enabled = false;
m_currentMode = MODE_DISABLED;
m_showTooltip = false;
}
// Sets the button's enabled / disabled state.
// Overrides the base class' method, to make it is compatible
// with the button states.
void UIButton::SetEnabled(bool enabled)
{
m_enabled = enabled;
m_showTooltip = false;
if (enabled)
m_currentMode = MODE_NORMAL;
else
m_currentMode = MODE_DISABLED;
}
// Switch to flash mode.
// Set the button to flash every a_iInterval ms.
void UIButton::Flash(Uint32 interval)
{
m_flashStart = SDL_GetTicks();
m_flashInterval = interval;
m_isFlashing = true;
m_currentMode = MODE_FLASH;
}
// Switch to normal (enabled) mode.
void UIButton::Normal()
{
m_currentMode = MODE_NORMAL;
m_showTooltip = false;
}
// Adds a state - User event / Text:
void UIButton::AddState(int eventCode, Font *font, string text, SDL_Color color,
Font *tooltipFont, string tooltipText)
{
SDL_Event event;
event.type = SDL_USEREVENT;
event.user.code = eventCode;
AddState(event, font, text, color, tooltipFont, tooltipText);
}
// Adds a state - SDL event / Text.
void UIButton::AddState(SDL_Event event, Font *font, string text, SDL_Color color,
Font *tooltipFont, string tooltipText)
{
State state;
// Render the text surface:
if (font != NULL && text != "")
state.textSurface = font->RenderPlain(Font::ALN_LEFT, color, text);
// Create the tooltip:
if (tooltipFont != NULL && tooltipText != "")
state.toolTipSurface = CreateTooltip(tooltipFont, tooltipText);
else
state.toolTipSurface = NULL;
// Set the event:
state.event = event;
// Add the state to the map. The name is the event type. For user events,
// the name is the event code.
if (event.type == SDL_USEREVENT)
m_states.insert(pair<int, State>(event.user.code, state));
else
m_states.insert(pair<int, State>(event.type, state));
m_currentState = state;
}
// Adds a state - User event / Image:
void UIButton::AddState(int eventCode, SDL_Surface *surface, Font *tooltipFont, string tooltipText)
{
SDL_Event event;
event.type = SDL_USEREVENT;
event.user.code = eventCode;
AddState(event, surface, tooltipFont, tooltipText);
}
// Adds a state - SDL event / Image:
void UIButton::AddState(SDL_Event event, SDL_Surface *surface, Font *tooltipFont, string tooltipText)
{
State state;
state.textSurface = surface;
// Set the event:
state.event = event;
// Create the tooltip:
if (tooltipFont != NULL && tooltipText != "")
state.toolTipSurface = CreateTooltip(tooltipFont, tooltipText);
else
state.toolTipSurface = NULL;
// Add the state to the map. The name is the event type. For user events,
// the name is the event code.
if (event.type == SDL_USEREVENT)
m_states.insert(pair<int, State>(event.user.code, state));
else
m_states.insert(pair<int, State>(event.type, state));
m_currentState = state;
}
// Sets the button's state.
void UIButton::SetState(int state)
{
map<int, State>::iterator itr = m_states.find(state);
if (itr != m_states.end())
m_currentState = itr->second;
}
// Sets the button's mode:
void UIButton::SetMode(ButtonMode mode)
{
m_currentMode = mode;
}
// Updates the button.
// Needed for flashing buttons.
// Return true if a redraw is needed.
bool UIButton::Update()
{
if (m_enabled != true || m_currentMode != MODE_FLASH)
return false;
bool redraw = false;
if (((SDL_GetTicks() - m_flashStart) / m_flashInterval) % 2) // Flashing
{
if (!m_isFlashing) // ... but was not flashing before
redraw = true;
m_isFlashing = true;
}
else // Not flashing
{
if (m_isFlashing) // ... but was flashing before
redraw = true;
m_isFlashing = false;
}
return redraw;
}
// Draws the button:
void UIButton::Draw(SDL_Surface *screen)
{
if (!m_visible)
return;
// Draw button:
SDL_Rect rect = {m_x, m_y, 0, 0};
// Draw the basic surface:
if (m_currentMode == MODE_FLASH && m_isFlashing)
SDL_BlitSurface(m_surfaces[MODE_NORMAL], NULL, screen, &rect);
else // Not flashing or between flashes
SDL_BlitSurface(m_surfaces[m_currentMode], NULL, screen, &rect);
// Draw text, centered horizontally and vertically:
rect.x = (Sint16) (m_x + (m_surfaces[m_currentMode]->w - m_currentState.textSurface->w) / 2);
rect.y = (Sint16) (m_y + (m_surfaces[m_currentMode]->h - m_currentState.textSurface->h) / 2);
SDL_BlitSurface(m_currentState.textSurface, NULL, screen, &rect);
// Draws the tooltip:
if (m_showTooltip && m_currentState.toolTipSurface != NULL && m_currentMode != MODE_DISABLED)
{
rect.x = (Sint16)(m_x + m_w / 2 - m_currentState.toolTipSurface->w / 2);
rect.y = (Sint16)(m_y + m_h);
SDL_BlitSurface(m_currentState.toolTipSurface, NULL, screen, &rect);
}
}
// Creates a mask from a surface.
// http://sdldoc.csn.ul.ie/guidevideo.php#AEN112
void UIButton::MakeMask(SDL_Surface* maskSurface)
{
if (maskSurface == NULL)
return;
m_maskW = (Uint16) maskSurface->w;
m_maskH = (Uint16) maskSurface->h;
{
m_mask = new Uint8[m_maskW * m_maskH];
}
// Lock the surface:
if(SDL_MUSTLOCK(maskSurface)) {
if(SDL_LockSurface(maskSurface) < 0)
return;
}
// Copy each pixel from the alpha or red channels to the mask:
Uint32 pixel; // Value of the current pixel
Uint8 *pPixel; // Pointer to the current pixel
Uint8 g,b;
for (Uint16 i = 0 ; i < m_maskW ; ++i)
for (Uint16 j = 0 ; j < m_maskH ; ++j)
{
// 32 bit images - the mask is based on the alpha channel:
if (maskSurface->format->BytesPerPixel == 4)
{
pPixel = (Uint8 *) maskSurface->pixels + j * maskSurface->pitch +
i * maskSurface->format->BytesPerPixel;
SDL_PixelFormat *fmt = maskSurface->format;
pixel = *(Uint32 *)pPixel & fmt->Amask; // Isolate alpha component
pixel = pixel >> fmt->Ashift; // Shift it down to 8-bit
pixel = pixel << fmt->Aloss; // Expand to a full 8-bit number
m_mask[j * m_maskW + i] = (Uint8) pixel;
}
// 24 bit images - the mask is based on the red channel:
else if (maskSurface->format->BytesPerPixel == 3)
{
pPixel = (Uint8 *) maskSurface->pixels + j * maskSurface->pitch +
i * maskSurface->format->BytesPerPixel;
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
pixel = pPixel[0] << 16 | pPixel[1] << 8 | pPixel[2];
else
pixel = pPixel[0] | pPixel[1] << 8 | pPixel[2] << 16;
SDL_GetRGB(pixel, maskSurface->format, &m_mask[j * m_maskW + i],
&g, &b);
}
}
// Unlock:
if(SDL_MUSTLOCK(maskSurface))
SDL_UnlockSurface(maskSurface);
}
// Creates a tooltip.
SDL_Surface* UIButton::CreateTooltip(Font *tooltipFont, string tooltipText)
{
// Render the text on a colored background:
SDL_Surface *shadedText =
tooltipFont->RenderShaded(Font::ALN_LEFT, TOOLTIP_FG, TOOLTIP_BG, tooltipText);
// Get a pointer to the screen, so we can create surfaces with
// the same pixel format:
SDL_Surface* screen = SDL_GetVideoSurface();
// Create a surface the will form the tooltip's background:
SDL_Surface *background = SDL_CreateRGBSurface(screen->flags,
shadedText->w + 8, shadedText->h + 4, // Add some spacing
screen->format->BitsPerPixel,
screen->format->Rmask,
screen->format->Gmask,
screen->format->Bmask, 0);
TRAP(background == NULL, "UIButton::MakeTooltip - SDL_CreateRGBSurface failed");
// Fill the surface with the background color:
SDL_FillRect(background, NULL, SDL_MapRGB(background->format, TOOLTIP_BG.r, TOOLTIP_BG.g, TOOLTIP_BG.b));
// Create a surface that will form the tooltip's border.
SDL_Surface *border = SDL_CreateRGBSurface(screen->flags,
background->w + 2, background->h + 2, // Add a 1px border
screen->format->BitsPerPixel,
screen->format->Rmask,
screen->format->Gmask,
screen->format->Bmask, 0);
TRAP(border == NULL, "UIButton::MakeTooltip - SDL_CreateRGBSurface failed");
// Fill the surface with the foreground color:
SDL_FillRect(border, NULL, SDL_MapRGB(border->format, TOOLTIP_FG.r, TOOLTIP_FG.g, TOOLTIP_FG.b));
// Blit the text on to the background surface:
SDL_Rect rect = {4, 2, 0, 0};
SDL_BlitSurface(shadedText, NULL, background, &rect);
// Blit the background + text on the border surface:
rect.x = rect.y = 1;
SDL_BlitSurface(background, NULL, border, &rect);
// The text surface is no longer needed:
SDL_FreeSurface(shadedText);
SDL_FreeSurface(background);
return border;
}
// Trigger tooltip timer callback function.
// If by the time this is called the button is still in hover mode,
// then the tooltip should be shown.
Uint32 UIButton::TriggerTooltip(Uint32 interval, void* param)
{
TooltipParam *tooltipParam = (TooltipParam *) param;
if (tooltipParam == NULL)
return 0;
if (*(tooltipParam->currentMode) == UIButton::MODE_HOVER)
*(tooltipParam->showTooltip) = true;
// Force a redraw:
PushUserEvent(EVENT_REDRAW);
return 0;
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _UIBUTTON_H_
#define _UIBUTTON_H_
// User interface button class.
// A button has several modes (normal, hover etc.), and one
// or more user defined states.
// Once a button is clicked, it pushes an event defined by
// its current state.
// The class also supports tooltips.
#include "../UI/uicontrol.h"
#include "../common/font.h"
#include "SDL.h"
#include <string>
#include <map>
using namespace std;
// Tooltip related:
static const SDL_Color TOOLTIP_FG = {0, 0, 0, 0}; // Foreground color (text and border)
static const SDL_Color TOOLTIP_BG = {250, 250, 150, 0}; // Background color
static const Uint32 TOOLTIP_DELAY = 750; // Time, in ms, until tooltip is shown
class UIButton: public UIControl
{
public:
// Button modes:
enum ButtonMode { MODE_NORMAL,
MODE_DISABLED,
MODE_HOVER,
MODE_CLICKED,
MODE_FLASH,
MODE_MASK,
MODE_MAX};
// The button's state:
typedef struct
{
SDL_Event event; // The event to raise once clicked
SDL_Surface *textSurface; // Button text's surface
SDL_Surface *toolTipSurface; // Button's tooltip surface
} State;
private:
string m_clickSoundID; // Click sound ID
// Modes:
SDL_Surface *m_surfaces[MODE_MAX]; // A surface for every one of the modes
ButtonMode m_currentMode; // Current mode
ButtonMode m_prevMode; // Previous mode (to return to from hover)
// Flash:
bool m_isFlashing; // Are we currently flashing?
Uint32 m_flashStart; // Time flashing has started
Uint32 m_flashInterval; // Flash interval
// States:
map<int, State> m_states; // Map states to their names
State m_currentState; // Current state
// Mask:
Uint8* m_mask; // Masks the button's clickable area
Uint16 m_maskW, m_maskH; // Mask's dimensions
// Tooltip:
bool m_showTooltip; // Should the tooltip be shown?
SDL_TimerID m_timerID; // Tooltip timer ID
typedef struct // Passed to the timer callback fucntion
{
ButtonMode *currentMode; // Current button mode
bool *showTooltip; // Should the tooltip be shown?
} TooltipParam;
TooltipParam m_tooltipParam;
public:
UIButton();
~UIButton();
// Set all of the button's properties:
void Set(Uint16 x, Uint16 y, string clickSoundID, SDL_Surface* normal,
SDL_Surface* disabled = NULL, SDL_Surface* hover = NULL,
SDL_Surface* clicked = NULL, SDL_Surface* flash = NULL,
SDL_Surface* mask = NULL);
bool IsInButton(Uint16 x, Uint16 y); // Are the coordinates inside the button (use mask)?
bool IsInRect(Uint16 x, Uint16 y); // Are the coordinates inside the button?
// Handle mouse down and up events:
bool MouseDown(Uint16 x, Uint16 y);
bool MouseUp(Uint16 x, Uint16 y);
// Click the button:
bool Click(); // Click the button
bool Click(Uint16 x, Uint16 y); // Click the button if the coords are valid
// Hover over the button:
bool Hover();
bool Hover(Uint16 x, Uint16 y);
// Disable the button:
void Disable();
void SetEnabled(bool enabled); // Override the base class' method
// Set the button to normal (enabled) mode:
void Normal();
// Set the button to flash mode:
void Flash(Uint32 interval);
// Add a state to the button:
void AddState(int eventCode, Font *font, string text, SDL_Color color,
Font *tooltipFont = NULL, string tooltipText = "");
void AddState(SDL_Event event, Font *font, string text, SDL_Color color,
Font *tooltipFont = NULL, string tooltipText = "");
void AddState(int eventCode, SDL_Surface *surface, Font *tooltipFont = NULL, string tooltipText = "");
void AddState(SDL_Event event, SDL_Surface *surface, Font *tooltipFont = NULL, string tooltipText = "");
// Set the button's state:
void SetState(int state);
// Set/Get the button's mode:
void SetMode(ButtonMode mode);
ButtonMode GetMode(){return m_currentMode;}
// Update the button:
bool Update();
// Draw the button:
void Draw(SDL_Surface *screen);
// Key down, unimplemented:
virtual bool KeyDown(SDL_KeyboardEvent *event){return false;}
// Button flash interval:
static const int FLASH_INTERVAL = 500;
protected:
void MakeMask(SDL_Surface* maskSurface); // Creates a mask from a surface
SDL_Surface* CreateTooltip(Font *tooltipFont, string tooltipText); // Creates a tooltip
static Uint32 TriggerTooltip(Uint32 interval, void* param); // Trigger tooltip timer callback func.
};
#endif

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "uicontrol.h"
void UIControl::Align(HAlign hAlign, VAlign vAlign, Uint16 x, Uint16 y)
{
switch (hAlign)
{
case HALN_LEFT:
m_x = x;
break;
case HALN_CENTER:
if (x >= m_w / 2)
m_x = x - m_w / 2;
break;
case HALN_RIGHT:
if (x >= m_w)
m_x = x - m_w;
break;
}
switch (vAlign)
{
case VALN_TOP:
m_y = y;
break;
case VALN_MIDDLE:
if (y >= m_h / 2)
m_y = y - m_h / 2;
break;
case VALN_BOTTOM:
if (y >= m_h)
m_y = y - m_h;
break;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _UICONTROL_H_
#define _UICONTROL_H_
#include "SDL.h"
// Abstract base class for user interface controls (buttons, labels, text boxes)
class UIControl
{
protected:
Uint16 m_x, m_y; // Location
Uint16 m_w, m_h; // Dimensions
bool m_visible; // Visibility flag
bool m_enabled; // Enabled flag
public:
UIControl():m_x(0), m_y(0), m_w(0), m_h(0), m_visible(true), m_enabled(true){};
virtual ~UIControl(){};
// Set the control's location:
void SetLocation(Uint16 x, Uint16 y){m_x = x; m_y = y;}
// Align the control, vertically and horizontally:
enum HAlign { HALN_LEFT, HALN_CENTER, HALN_RIGHT};
enum VAlign { VALN_TOP, VALN_MIDDLE, VALN_BOTTOM};
void Align(HAlign hAlign, VAlign vAlign, Uint16 x, Uint16 y);
// Visibility:
void SetVisible(bool visible){m_visible = visible;}
bool GetVisible(){return m_visible;}
// Enable / disable:
virtual void SetEnabled(bool enabled){m_enabled = enabled;}
bool GetEnabled(){return m_enabled;}
// Accessors:
Uint16 GetX(){return m_x;}
Uint16 GetY(){return m_y;}
Uint16 GetWidth(){return m_w;}
Uint16 GetHeight(){return m_h;}
// Mouse events:
virtual bool MouseDown(Uint16 x, Uint16 y) = 0; // Process mouse up events
virtual bool MouseUp(Uint16 x, Uint16 y) = 0; // Process mouse up events
virtual bool Click(Uint16 x, Uint16 y) = 0; // Process user clicks
virtual bool Hover(Uint16 x, Uint16 y) = 0; // Process user mouse hover
// Kyboard events:
virtual bool KeyDown(SDL_KeyboardEvent *event) = 0;
// Update:
virtual bool Update() = 0;
// Draw the control:
virtual void Draw(SDL_Surface *screen) = 0;
};
#endif

View File

@@ -0,0 +1,205 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "uilabel.h"
#include <cstdlib>
#include <cstdarg>
#include "../common/trap.h"
#include "../common/events.h"
// Constructor
UILabel::UILabel():
m_BGSurface(NULL), m_TextSurface(NULL), m_CompSurface(NULL), m_font(NULL), m_Text("")
{
m_clipRect.x = m_clipRect.y = m_clipRect.w = m_clipRect.h = 0;
}
// Destructor - free the SDL surfaces we created.
// Note that the background surface is not freed, since it was
// supplied to the object by the caller.
UILabel::~UILabel()
{
if (m_TextSurface)
SDL_FreeSurface(m_TextSurface);
if (m_CompSurface)
SDL_FreeSurface(m_CompSurface);
SDL_RemoveTimer(m_timerID);
}
// Sets the label's location and background.
void UILabel::Set(Uint16 x, Uint16 y, SDL_Surface* background, Font* font, SDL_Color textColor, float alpha)
{
UIControl::SetLocation(x, y);
m_BGSurface = background;
m_textColor = textColor;
m_alpha = alpha;
if (font != NULL)
m_font = font;
if (m_BGSurface != NULL)
{
m_w = m_clipRect.w = (Uint16) m_BGSurface->w;
m_h = m_clipRect.h = (Uint16) m_BGSurface->h;
}
PushUserEvent(EVENT_REDRAW);
}
// Returns the label's text.
std::string UILabel::GetText() const
{
return m_Text;
}
// Sets the label's text, using printf-like formatting.
// The alignment is only relevant to multi-line strings.
// The text surface itself is always centered in the
// background surface, if once exists.
void UILabel::SetText(HAlign hAlign, const char *format, ...)
{
// Format the text:
char formatted[4096]; // Holds the text after formatting
va_list listOfArgs; // Pointer to the list of arguments
if (format == NULL) // If there's no text, do nothing
{
*formatted = 0;
}
else // Handle the variable-argument list
{
va_start(listOfArgs, format);
vsprintf(formatted, format, listOfArgs);
va_end(listOfArgs);
}
SetText(hAlign, std::string(formatted));
}
// Sets the lable's text.
void UILabel::SetText(HAlign hAlign, const std::string& text)
{
m_Text = text;
if (m_TextSurface != NULL)
SDL_FreeSurface(m_TextSurface);
if (m_Text == "" && m_font == NULL)
return;
if (hAlign == HALN_LEFT)
m_TextSurface = m_font->RenderTransparent(Font::ALN_LEFT, m_textColor, m_alpha, text);
else if (hAlign == HALN_CENTER)
m_TextSurface = m_font->RenderTransparent(Font::ALN_CENTER, m_textColor, m_alpha, text);
else
m_TextSurface = m_font->RenderTransparent(Font::ALN_RIGHT, m_textColor, m_alpha, text);
// If no background surface is defined, the label's dimensions are those of the text surface:
if (m_BGSurface == NULL)
{
m_w = m_clipRect.w = (Uint16) m_TextSurface->w;
m_h = m_clipRect.h = (Uint16) m_TextSurface->h;
}
PushUserEvent(EVENT_REDRAW);
}
// Sets the background surface.
void UILabel::SetBackground(SDL_Surface *background)
{
m_BGSurface = background;
if (m_BGSurface != NULL)
{
m_w = (Uint16) m_BGSurface->w;
m_h = (Uint16) m_BGSurface->h;
}
}
// Sets the clipping rectangle.
// Setting either dimension to a negative number cancels
// clipping of that dimension.
void UILabel::SetClipping(Sint16 w, Sint16 h)
{
m_clipRect.w = (w < 0) ? m_w : w;
m_clipRect.h = (h < 0) ? m_h : h;
}
// Show the label for a set amount of time.
void UILabel::ShowTimed(Uint32 time)
{
m_visible = true;
// Remove any existing timers:
SDL_RemoveTimer(m_timerID);
// Set the tooltip callback timer:
m_timerID = SDL_AddTimer(time, HideLabel, &m_visible);
}
// Draws the label.
// The method can use a clipping rectangle to clip the surface.
void UILabel::Draw(SDL_Surface *screen)
{
if (m_visible == false)
return;
SDL_Rect rect = {0, 0, 0, 0};
if (m_BGSurface != NULL)
{
rect.x = m_x;
rect.y = m_y;
SDL_BlitSurface(m_BGSurface, &m_clipRect, screen, &rect);
}
if (m_TextSurface != NULL)
{
rect.x = (Sint16) (m_x + (m_w - m_TextSurface->w) / 2);
rect.y = (Sint16) (m_y + (m_h - m_TextSurface->h) / 2);
SDL_BlitSurface(m_TextSurface, &m_clipRect, screen, &rect);
}
}
// Hides the label.
// This is an SDL_timer callback function.
Uint32 UILabel::HideLabel(Uint32 interval, void* param)
{
bool *visible = (bool *) param;
*visible = false;
// Force a redraw:
PushUserEvent(EVENT_REDRAW);
return 0;
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _UILABEL_H_
#define _UILABEL_H_
// UI label control
// May contain text and/or a background image.
// The text is always centered in both dimensions.
#include "../UI/uicontrol.h"
#include "../common/font.h"
#include <string>
#include "SDL.h"
class UILabel: public UIControl
{
private:
SDL_Surface *m_BGSurface; // Background surface
SDL_Surface *m_TextSurface; // Text surface
SDL_Surface *m_CompSurface; // The text composited onto the the background
Font *m_font; // Font used to render the label's text
std::string m_Text; // Label's text
SDL_Color m_textColor; // Label's Text color
float m_alpha; // Text's alpha value (0.0-1.0)
SDL_Rect m_clipRect; // Clipping rectangle for the label's surface
public:
UILabel();
~UILabel();
void Set(Uint16 x, Uint16 y, SDL_Surface* background, // Set location, background, font & color
Font *font, SDL_Color textColor, float alpha = 1.0f);
void SetEnabled(bool enabled){};
std::string GetText() const; // Get the label's text
void SetText(HAlign hAlign, const char *format, ...); // Set the label's text (printf-like formatting)
void SetText(HAlign hAlign, const std::string& text); // Set the label's text
void SetClipping(Sint16 w, Sint16 h); // Sets the clipping rectangle
void SetBackground(SDL_Surface *background);// Sets the background surface
void ShowTimed(Uint32 time); // Show the label for a set amount of time
bool Update(){return false;} // Update
void Draw(SDL_Surface *screen); // Draw the label
// Mouse and keyboard events are irrelevant to a label, but required for polymorphism:
bool MouseDown(Uint16 x, Uint16 y){return false;} // Process mouse up events
bool MouseUp(Uint16 x, Uint16 y){return false;} // Process mouse up events
bool Click(Uint16 x, Uint16 y){return false;} // Process user clicks
bool Hover(Uint16 x, Uint16 y){return false;} // Process user mouse hover
bool KeyDown(SDL_KeyboardEvent *event){return false;}
private:
SDL_TimerID m_timerID; // Hide timer ID
static Uint32 HideLabel(Uint32 interval, void* param); // Hide label timer callback func.
};
#endif

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../UI/uiprogress.h"
#include "../common/trap.h"
#include "../common/events.h"
// Constructor
UIProgressBar::UIProgressBar():
m_BGSurface(NULL), m_normalSurface(NULL), m_flashingSurface(NULL), m_disabledSurface(NULL)
{
m_flashingMode = false;
m_isFlashing = false;
m_x = m_y = 0;
m_progress = 0;
m_clipRect.x = m_clipRect.y = m_clipRect.w = m_clipRect.h = 0;
}
// Sets location and surfaces
void UIProgressBar::Set(Uint16 x, Uint16 y, SDL_Surface* BGSurface,
SDL_Surface *normalSurface, SDL_Surface *flashingSurface, SDL_Surface *disabledSurface)
{
m_x = x;
m_y = y;
m_BGSurface = BGSurface;
m_normalSurface = normalSurface;
m_flashingSurface = flashingSurface;
m_disabledSurface = disabledSurface;
if (normalSurface != NULL)
{
m_w = m_clipRect.w = (Uint16) normalSurface->w;
m_h = m_clipRect.h = (Uint16) normalSurface->h;
}
}
// Sets the bar's progress. Valid range is 0.0f - 1.0f.
void UIProgressBar::SetProgress(float progress)
{
if (progress < 0.0f)
m_progress = 0.0f;
else if (progress > 1.0f)
m_progress = 1.0f;
else
m_progress = progress;
// Calculate the progress value in pixels:
Uint16 progressInPixels = (Uint16) (m_progress * m_w);
// If the pixel value has changed, the bar needs to be redrawn:
if (progressInPixels != m_clipRect.w)
{
m_clipRect.w = progressInPixels;
PushUserEvent(EVENT_REDRAW);
}
}
// Starts or stops the bar's flashing
void UIProgressBar::Flash(bool flag)
{
// Ignore requests to start flashing while already flashing.
if (flag == true && m_flashingMode == true)
return;
m_flashingMode = m_isFlashing = flag;
m_flashStart = SDL_GetTicks();
// Force redraw:
PushUserEvent(EVENT_REDRAW);
}
// Updates the progress bar.
bool UIProgressBar::Update()
{
if (m_enabled != true || m_flashingMode == false)
return false;
bool redraw = false;
if (((SDL_GetTicks() - m_flashStart) / FLASH_INTERVAL) % 2) // Flashing
{
if (!m_isFlashing) // ... but was not flashing before
redraw = true;
m_isFlashing = true;
}
else // Not flashing
{
if (m_isFlashing) // ... but was flashing before
redraw = true;
m_isFlashing = false;
}
return redraw;
}
// Draws the progress bar.
void UIProgressBar::Draw(SDL_Surface *screen)
{
if (!m_visible || screen == NULL || m_normalSurface == NULL || m_flashingSurface == NULL)
return;
SDL_Rect rect = {m_x, m_y, 0, 0};
// Blit background:
if (m_BGSurface)
SDL_BlitSurface(m_BGSurface, NULL, screen, &rect);
// Blit foreground:
if (!m_enabled)
SDL_BlitSurface(m_disabledSurface, &m_clipRect, screen, &rect);
else if (m_isFlashing)
SDL_BlitSurface(m_flashingSurface, &m_clipRect, screen, &rect);
else
SDL_BlitSurface(m_normalSurface, &m_clipRect, screen, &rect);
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _UIPROGRESS_H_
#define _UIPROGRESS_H_
// UI progress bar control.
#include "../UI/uicontrol.h"
#include "SDL.h"
class UIProgressBar: public UIControl
{
private:
// Surfaces:
SDL_Surface *m_BGSurface; // Background surface
SDL_Surface *m_normalSurface; // Normal foreground surface
SDL_Surface *m_flashingSurface; // Flashing foreground surface
SDL_Surface *m_disabledSurface; // Disabled foreground surface
SDL_Rect m_clipRect; // Clipping rectangle for the foreground surface
float m_progress; // Bar's progress, between 0.0f and 1.0f
// Flash:
bool m_flashingMode; // Are we in flashing mode?
bool m_isFlashing; // Are we currently flashing?
Uint32 m_flashStart; // Time flashing has started
// Button flash interval:
static const int FLASH_INTERVAL = 500;
public:
UIProgressBar();
~UIProgressBar(){};
void Set(Uint16 x, Uint16 y, SDL_Surface* BGSurface, // Sets location and surfaces
SDL_Surface *normalSurface, SDL_Surface *flashingSurface, SDL_Surface *disabledSurface);
// Set and get the bar's progress:
void SetProgress(float progress);
float GetProgress(){return m_progress;}
void Flash(bool flag); // Starts or stops the bar's flashing
bool Update(); // Updates the progress bar
void Draw(SDL_Surface *screen); // Draws the progress bar
// Mouse and keyboard events are irrelevant to a progress bar, but required for polymorphism:
bool MouseDown(Uint16 x, Uint16 y){return false;} // Process mouse up events
bool MouseUp(Uint16 x, Uint16 y){return false;} // Process mouse up events
bool Click(Uint16 x, Uint16 y){return false;} // Process user clicks
bool Hover(Uint16 x, Uint16 y){return false;} // Process user mouse hover
bool KeyDown(SDL_KeyboardEvent *event){return false;} // Process key down events
};
#endif

View File

@@ -0,0 +1,282 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../UI/uitextbox.h"
#include "../common/trap.h"
// Constructor
UITextBox::UITextBox():
m_BGSurface(NULL), m_textSurface(NULL), m_cursorSurface(NULL), m_font(NULL), m_text("")
{
m_cursorIndex = 0;
m_blinking = true;
}
// Destructor - free the SDL surfaces we created.
// Note that the background and cursor surfaces are not freed,
// since they were supplied to the object by the caller.
UITextBox::~UITextBox()
{
if (m_textSurface)
SDL_FreeSurface(m_textSurface);
}
// Sets the label's location and background.
void UITextBox::Set(Uint16 x, Uint16 y, // Box location
Uint16 textX, Uint16 textY, // Text location relative to the box
SDL_Surface* background, SDL_Surface *cursorSurface, // background and cursor surfaces
Font *font, SDL_Color textColor) // Font and text color
{
UIControl::SetLocation(x, y);
m_textX = textX;
m_textY = textY;
m_BGSurface = background;
m_cursorSurface = cursorSurface;
m_textColor = textColor;
m_font = font;
}
// Clears the text.
void UITextBox::Clear()
{
SetText("");
}
// Returns the label's text.
std::string UITextBox::GetText() const
{
return m_text;
}
// Sets the box's text.
void UITextBox::SetText(string text)
{
m_text = text;
m_cursorIndex = (Uint16) m_text.length();
Refresh();
}
// Update the cursor blink.
bool UITextBox::Update()
{
if (m_enabled != true)
return false;
bool redraw = false;
if (SDL_GetTicks() % (CURSOR_BLINK * 2) < CURSOR_BLINK) // Blink on
{
if (!m_blinking) // ... but was not flashing before
redraw = true;
m_blinking = true;
}
else // Not flashing
{
if (m_blinking) // ... but was flashing before
redraw = true;
m_blinking = false;
}
return redraw;
}
// Draws the text box.
void UITextBox::Draw(SDL_Surface *screen)
{
if (m_visible == false)
return;
SDL_Rect rect = {0, 0, 0, 0};
// Background:
if (m_BGSurface != NULL)
{
rect.x = m_x;
rect.y = m_y;
SDL_BlitSurface(m_BGSurface, NULL, screen, &rect);
}
// Text:
if (m_textSurface != NULL)
{
rect.x = m_textX + m_x;
rect.y = m_textY + m_y;
SDL_BlitSurface(m_textSurface, NULL, screen, &rect);
}
// Cursor:
if (m_cursorSurface != NULL && m_blinking)
//SDL_GetTicks() % (CURSOR_BLINK * 2) < CURSOR_BLINK)
{
rect.x = m_x + m_textX + (m_charOffset.empty() ? 0 : m_charOffset[m_cursorIndex]);
rect.y = m_y + m_textY + 1;
SDL_BlitSurface(m_cursorSurface, NULL, screen, &rect);
}
}
// Process mouse down events.
// A click sets the cursor position.
bool UITextBox::MouseDown(Uint16 x, Uint16 y)
{
// Check if the click in inside the text area:
if (m_textSurface == NULL || x < m_x + m_textX || x > m_x + m_textX + m_textSurface->w
|| y < m_y + m_textY || y > m_y + m_textY + m_textSurface->h)
return false;
// Scan the offset vector to see where to place the cursor:
Uint16 A, B;
for (Uint16 i = 0 ; i < (Uint16) m_charOffset.size() ; ++i)
{
if (i == 0)
A = m_x + m_textX + m_charOffset[i];
else
A = (m_x + m_textX + m_charOffset[i - 1] + m_x + m_textX + m_charOffset[i]) / 2;
if (i == (Uint16) m_charOffset.size())
B = m_x + m_textX + m_charOffset[i];
else
B = (m_x + m_textX + m_charOffset[i] + m_x + m_textX + m_charOffset[i + 1]) / 2;
if (x >= A && x < B)
m_cursorIndex = i;
}
return true;
}
// Handle key down events.
bool UITextBox::KeyDown(SDL_KeyboardEvent *event)
{
switch (event->keysym.sym) // Get the key symbol
{
// Left arrow:
case SDLK_LEFT:
if (m_cursorIndex > 0)
m_cursorIndex--;
break;
// Right arrow:
case SDLK_RIGHT:
if (m_cursorIndex < m_text.length())
m_cursorIndex++;
break;
// Home:
case SDLK_HOME:
m_cursorIndex = 0;
break;
// End:
case SDLK_END:
m_cursorIndex = (Uint16) m_text.length();
break;
// Backspace:
case SDLK_BACKSPACE:
if (m_cursorIndex > 0)
{
m_text.erase(m_cursorIndex - 1, 1);
m_cursorIndex--;
Refresh();
}
break;
// Delete:
case SDLK_DELETE:
if (m_cursorIndex < m_text.length())
{
m_text.erase(m_cursorIndex, 1);
Refresh();
}
break;
// Characters:
default:
{
// Make sure text doesn't graphically overflow the background image:
if (m_textSurface != NULL &&
m_textSurface->w >= (m_BGSurface->w - 3 * m_textX))
break;
char c = 0;
// Convert the unicode value into ASCII:
if ((event->keysym.unicode & 0xFF80) == 0)
{
c = (char)(event->keysym.unicode & 0x7F);
if (c >= ' ' && c <= '~') // Add only displayable chars
{
// Insert the character to the string at the current cursor position:
m_text.insert(m_cursorIndex, string(1,c));
m_cursorIndex++;
Refresh();
}
}
else // International char - ignore
return false;
break;
}
}
return true;
}
// Refreshes the text box when changed.
void UITextBox::Refresh()
{
MeasureOffsets();
SDL_FreeSurface(m_textSurface);
m_textSurface = m_font->RenderPlain(Font::ALN_LEFT, m_textColor, m_text);
}
// Measure the characters' offset.
// The method populates the offset vector with the offsets
// of the string characters, in pixels, when rendered with
// the object's font.
void UITextBox::MeasureOffsets()
{
m_charOffset.clear();
m_charOffset.push_back(0);
for (size_t i = 0 ; i < m_text.length() ; ++i)
{
Uint16 temp = m_font->GetGlyphAdvance((Uint16) m_text[i]);
m_charOffset.push_back(temp + m_charOffset[i]);
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _UITEXTBOX_H_
#define _UITEXTBOX_H_
// UI text box control
#include "../UI/uicontrol.h"
#include "../common/font.h"
#include <string>
#include <vector>
#include "SDL.h"
using namespace std;
class UITextBox: public UIControl
{
private:
SDL_Surface *m_BGSurface; // Background surface
SDL_Surface *m_textSurface; // Text surface
SDL_Surface *m_cursorSurface; // Cursor surface
string m_text; // The box's text
Font *m_font; // Font used to render the text
SDL_Color m_textColor; // Text color
Uint16 m_cursorIndex; // Cursor position - as the index of the
// character in the string. The cursor
// is drawn BEFORE the character with
// the same index.
// Use n+1 to indicate the position after
// the last character.
vector<Uint16> m_charOffset; // A vector of character advance offset.
// E.g. For the string "Hello", the value
// of the second element will be the distance,
// in pixels, from the begining of the rendered
// text until the end of the character 'e'
Uint16 m_textX, m_textY; // Location of text area within the control
bool m_blinking; // Current blinking status
static const int CURSOR_BLINK = 500; // Cursor blink rate, in ms
public:
UITextBox();
~UITextBox();
void Set(Uint16 x, Uint16 y, // Box location
Uint16 textX, Uint16 textY, // Text location relative to the box
SDL_Surface* background, SDL_Surface *cursorSurface, // Background and cursor surfaces
Font *font, SDL_Color textColor); // Font and text color
void SetEnabled(bool enabled){};
void Clear(); // Clears the text
string GetText() const; // Gets the box's text
void SetText(string text); // Sets the box's text
void SetBackground(SDL_Surface *background);// Sets the background surface
bool Update(); // Updates the text box
void Draw(SDL_Surface *screen); // Draws the text box
// Mouse and keyboard events:
bool MouseDown(Uint16 x, Uint16 y); // Processes mouse down events
bool MouseUp(Uint16 x, Uint16 y){return false;} // Processes mouse up events
bool Click(Uint16 x, Uint16 y){return false;} // Processes user clicks
bool Hover(Uint16 x, Uint16 y){return false;} // Processes user mouse hover
bool KeyDown(SDL_KeyboardEvent *event); // Processes keyboard clicks
private:
void Refresh(); // Refreshes the text box when changed
void MeasureOffsets(); // Measure the characters' offset
};
#endif

View File

@@ -0,0 +1,307 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../UI/uiwindow.h"
#include "../common/common.h"
using namespace std;
// Constructor
UIWindow::UIWindow(SDL_Surface *background)
{
m_visible = true;
m_background = background;
if (m_background != NULL)
{
m_w = (Uint16) m_background->w;
m_h = (Uint16) m_background->h;
}
else
{
m_w = m_h = 0;
}
// Set the window to be centered relative to the screen:
m_x = (SCREEN_WIDTH - m_w) / 2;
m_y = (SCREEN_HEIGHT - m_h) / 2;
}
// Destructor - delete the window's controls
UIWindow::~UIWindow()
{
// Delete the individual controls:
map<int, UIControl*>::iterator itr;
for (itr = m_controls.begin() ; itr != m_controls.end() ; itr++)
delete (itr->second);
// Delete the controls within the vectors:
map<int, vector<UIControl *> >::iterator itrCtlVec;
for (itrCtlVec = m_controlsVectors.begin() ; itrCtlVec != m_controlsVectors.end() ; itrCtlVec++)
{
vector<UIControl *>::iterator itrVec;
for (itrVec = itrCtlVec->second.begin() ; itrVec != itrCtlVec->second.end() ; itrVec++)
delete (*itrVec);
}
}
// Enables or disables all of the window's controls.
void UIWindow::SetEnabled(bool enabled)
{
map<int, UIControl*>::iterator itr;
for (itr = m_controls.begin() ; itr != m_controls.end() ; itr++)
itr->second->SetEnabled(enabled);
map<int, vector<UIControl *> >::iterator itrCtlVec;
for (itrCtlVec = m_controlsVectors.begin() ; itrCtlVec != m_controlsVectors.end() ; itrCtlVec++)
{
vector<UIControl *>::iterator itrVec;
for (itrVec = itrCtlVec->second.begin() ; itrVec != itrCtlVec->second.end() ; itrVec++)
(*itrVec)->SetEnabled(enabled);
}
}
// Adds a control to the collection.
void UIWindow::AddControl(int ID, UIControl *control)
{
map<int, UIControl*>::iterator itr = m_controls.find(ID);
if (itr == m_controls.end())
m_controls[ID] = control;
}
// Adds a vector of controls to the collection.
void UIWindow::AddControlVector(int ID, vector<UIControl *> vec)
{
map<int, vector<UIControl *> >::iterator itr = m_controlsVectors.find(ID);
if (itr == m_controlsVectors.end())
m_controlsVectors[ID] = vec;
}
// Gets a UI control by its ID.
UIControl *UIWindow::GetControl(int ID)
{
map<int, UIControl*>::iterator itr = m_controls.find(ID);
if (itr == m_controls.end())
return NULL;
else
return m_controls[ID];
}
// Gets a UI control vector by its ID.
vector<UIControl *> UIWindow::GetControlVector(int ID)
{
return m_controlsVectors[ID];
}
// Gets a UI control, cast to a button, by its ID.
UIButton *UIWindow::GetButton(int ID)
{
return (static_cast<UIButton *>(GetControl(ID)));
}
// Gets a UI control, cast to a label, by its ID.
UILabel *UIWindow::GetLabel(int ID)
{
return (static_cast<UILabel *>(GetControl(ID)));
}
// Gets a UI control, cast to a progress bar, by its ID.
UIProgressBar *UIWindow::GetProgressBar(int ID)
{
return (static_cast<UIProgressBar *>(GetControl(ID)));
}
// Processes mouse down events.
bool UIWindow::MouseDown(Uint16 x, Uint16 y)
{
bool redraw = false;
map<int, UIControl*>::iterator itr;
for (itr = m_controls.begin() ; itr != m_controls.end() ; itr++)
redraw |= itr->second->MouseDown(x, y);
map<int, vector<UIControl *> >::iterator itrCtlVec;
for (itrCtlVec = m_controlsVectors.begin() ; itrCtlVec != m_controlsVectors.end() ; itrCtlVec++)
{
vector<UIControl *>::iterator itrVec;
for (itrVec = itrCtlVec->second.begin() ; itrVec != itrCtlVec->second.end() ; itrVec++)
redraw |= (*itrVec)->MouseDown(x, y);
}
return redraw;
}
// Processes mouse up events.
bool UIWindow::MouseUp(Uint16 x, Uint16 y)
{
bool redraw = false;
map<int, UIControl*>::iterator itr;
for (itr = m_controls.begin() ; itr != m_controls.end() ; itr++)
redraw |= itr->second->MouseUp(x, y);
map<int, vector<UIControl *> >::iterator itrCtlVec;
for (itrCtlVec = m_controlsVectors.begin() ; itrCtlVec != m_controlsVectors.end() ; itrCtlVec++)
{
vector<UIControl *>::iterator itrVec;
for (itrVec = itrCtlVec->second.begin() ; itrVec != itrCtlVec->second.end() ; itrVec++)
redraw |= (*itrVec)->MouseUp(x, y);
}
return redraw;
}
// Processes user clicks.
bool UIWindow::Click(Uint16 x, Uint16 y)
{
bool redraw = false;
map<int, UIControl*>::iterator itr;
for (itr = m_controls.begin() ; itr != m_controls.end() ; itr++)
redraw |= itr->second->Click(x, y);
map<int, vector<UIControl *> >::iterator itrCtlVec;
for (itrCtlVec = m_controlsVectors.begin() ; itrCtlVec != m_controlsVectors.end() ; itrCtlVec++)
{
vector<UIControl *>::iterator itrVec;
for (itrVec = itrCtlVec->second.begin() ; itrVec != itrCtlVec->second.end() ; itrVec++)
redraw |= (*itrVec)->Click(x, y);
}
return redraw;
}
// Processes mouse hover.
bool UIWindow::Hover(Uint16 x, Uint16 y)
{
bool redraw = false;
map<int, UIControl*>::iterator itr;
for (itr = m_controls.begin() ; itr != m_controls.end() ; itr++)
redraw |= itr->second->Hover(x, y);
map<int, vector<UIControl *> >::iterator itrCtlVec;
for (itrCtlVec = m_controlsVectors.begin() ; itrCtlVec != m_controlsVectors.end() ; itrCtlVec++)
{
vector<UIControl *>::iterator itrVec;
for (itrVec = itrCtlVec->second.begin() ; itrVec != itrCtlVec->second.end() ; itrVec++)
redraw |= (*itrVec)->Hover(x, y);
}
return redraw;
}
// Proces key down events:
bool UIWindow::KeyDown(SDL_KeyboardEvent *event)
{
bool redraw = false;
map<int, UIControl*>::iterator itr;
for (itr = m_controls.begin() ; itr != m_controls.end() ; itr++)
redraw |= itr->second->KeyDown(event);
map<int, vector<UIControl *> >::iterator itrCtlVec;
for (itrCtlVec = m_controlsVectors.begin() ; itrCtlVec != m_controlsVectors.end() ; itrCtlVec++)
{
vector<UIControl *>::iterator itrVec;
for (itrVec = itrCtlVec->second.begin() ; itrVec != itrCtlVec->second.end() ; itrVec++)
redraw |= (*itrVec)->KeyDown(event);
}
return redraw;
}
// Update the window.
bool UIWindow::Update()
{
bool redraw = false;
map<int, UIControl*>::iterator itr;
for (itr = m_controls.begin() ; itr != m_controls.end() ; itr++)
redraw |= itr->second->Update();
map<int, vector<UIControl *> >::iterator itrCtlVec;
for (itrCtlVec = m_controlsVectors.begin() ; itrCtlVec != m_controlsVectors.end() ; itrCtlVec++)
{
vector<UIControl *>::iterator itrVec;
for (itrVec = itrCtlVec->second.begin() ; itrVec != itrCtlVec->second.end() ; itrVec++)
redraw |= (*itrVec)->Update();
}
return redraw;
}
// Draws the window.
void UIWindow::Draw(SDL_Surface *screen)
{
if (m_visible == false)
return;
DrawBackground(screen);
DrawControls(screen);
}
// Draws the window's background.
void UIWindow::DrawBackground(SDL_Surface *screen)
{
if (m_visible == false)
return;
// Draw the background:
SDL_Rect rect = {m_x, m_y, m_w, m_h};
SDL_BlitSurface(m_background, NULL, screen, &rect);
}
// Draws the window's controls.
void UIWindow::DrawControls(SDL_Surface *screen)
{
if (m_visible == false)
return;
// Draw the controls:
map<int, UIControl*>::iterator itr;
for (itr = m_controls.begin() ; itr != m_controls.end() ; itr++)
itr->second->Draw(screen);
map<int, vector<UIControl *> >::iterator itrCtlVec;
for (itrCtlVec = m_controlsVectors.begin() ; itrCtlVec != m_controlsVectors.end() ; itrCtlVec++)
{
vector<UIControl *>::iterator itrVec;
for (itrVec = itrCtlVec->second.begin() ; itrVec != itrCtlVec->second.end() ; itrVec++)
(*itrVec)->Draw(screen);
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _UIWINDOW_H_
#define _UIWINDOW_H_
// A base class for windows.
// The window is composed of a background and a collection of
// controls - labels, buttons or other windows.
// The class supports vectors of controls.
#include "../UI/uicontrol.h"
#include "../UI/uibutton.h"
#include "../UI/uilabel.h"
#include "../UI/uiprogress.h"
#include <map>
#include <vector>
#include "SDL.h"
using namespace std;
class UIWindow: public UIControl
{
protected:
SDL_Surface *m_background; // Window background
map<int, UIControl *> m_controls; // Window controls
map<int, vector<UIControl *> > m_controlsVectors; // Window controls vectors
public:
UIWindow(SDL_Surface *background);
virtual ~UIWindow();
// Enable / Disbable the windows' controls:
void SetEnabled(bool enabled);
// Add and get a control:
void AddControl(int ID, UIControl *control);
void AddControlVector(int ID, vector<UIControl *> vec);
UIControl *GetControl(int ID);
vector<UIControl *> GetControlVector(int ID);
// Accessors:
UIButton *GetButton(int ID);
UILabel *GetLabel(int ID);
UIProgressBar *GetProgressBar(int ID);
SDL_Surface *GetBackground(){return m_background;}
// Mouse events:
bool MouseDown(Uint16 x, Uint16 y); // Process mouse up events
bool MouseUp(Uint16 x, Uint16 y); // Process mouse up events
bool Click(Uint16 x, Uint16 y); // Process user clicks
bool Hover(Uint16 x, Uint16 y); // Process user mouse hover
// Key down:
bool KeyDown(SDL_KeyboardEvent *event);
// Update the window:
bool Update();
// Draw the window:
void Draw(SDL_Surface *screen);
void DrawBackground(SDL_Surface *screen);
void DrawControls(SDL_Surface *screen);
};
#endif

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _COMMON_H_
#define _COMMON_H_
#include "SDL.h"
#include <string>
#include <ctime>
using namespace std;
// Application name, version and website:
static const string APP_NAME = "Jooleem";
static const string APP_VERSION = "0.1.4 (20050925)";
static const string APP_URL = "http://jooleem.sourceforge.net";
// Window:
static const string CAPTION = "Jooleem"; // Window caption
static const string ICON = "data/interface/icon.png"; // Window icon
// Screen dimensions:
static const int SCREEN_WIDTH = 640;
static const int SCREEN_HEIGHT = 480;
// Takes a screenshot.
// The file is saved as a Windows bitmap.
inline void ScreenShot(char* fileName = NULL)
{
// If no file name is supplied, create one from the current time:
if (!fileName)
{
char buf[128];
sprintf(buf, "data/screenshots/%ld.bmp", time(NULL));
SDL_SaveBMP(SDL_GetVideoSurface(), buf);
}
else
SDL_SaveBMP(SDL_GetVideoSurface(), fileName);
}
#endif

View File

@@ -0,0 +1,211 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../common/effectmanager.h"
#include "../common/fontmanager.h"
#include "../common/trap.h"
#include <sstream>
EffectManager* EffectManager::m_instance = NULL;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
EffectManager* EffectManager::GetInstance()
{
if (m_instance == NULL)
{
{
m_instance = new EffectManager();
}
}
return m_instance;
}
// Initialize the manager - load fonts.
void EffectManager::Init()
{
m_initialized = true;
}
// Adds a score effect
void EffectManager::AddScoreEffect(SDL_Event* event)
{
TRAP(m_initialized == false, "EffectManager::AddScoreEffect() - Manager has not been initialized");
if (event == NULL)
return;
SDL_Color color = {255, 255, 255, 0};
// Get the score and coordinates:
Uint32 *score = (Uint32 *) event->user.data1;
SDL_Rect *rect = (SDL_Rect *) event->user.data2;
if (score == NULL || rect == NULL)
return;
// Create the string:
ostringstream temp;
temp << *score;
// Add the effect:
Add(rect->x + rect->w / 2,
rect->y + rect->h / 2,
temp.str(),
FontManager::GetInstance()->GetFont("ScoreEffect"),
color,
0.8f,
0.0f,
1500,
0.5f);
}
// Adds a new level effect
void EffectManager::AddLevelEffect(int level)
{
TRAP(m_initialized == false, "EffectManager::AddLevelEffect() - Manager has not been initialized");
SDL_Color color = {255, 255, 255, 0};
// Create the string:
ostringstream temp;
temp << "Level " << level;
// Add the effect:
Add(412,
228,
temp.str(),
FontManager::GetInstance()->GetFont("LevelEffect"),
color,
0.8f,
0.0f,
2000,
-0.3f);
}
// Adds a game over effect.
void EffectManager::AddGameOverEffect()
{
TRAP(m_initialized == false, "EffectManager::AddGameOverEffect() - Manager has not been initialized");
SDL_Color color = {255, 255, 255, 0};
// Add the effect:
Add(412,
50,
"Game Over",
FontManager::GetInstance()->GetFont("GameOverEffect"),
color,
0.8f,
0.0f,
4000,
-0.01f);
}
// Adds a perfect rectangle effect.
void EffectManager::AddPerfectEffect()
{
TRAP(m_initialized == false, "EffectManager::AddLevelEffect() - Manager has not been initialized");
SDL_Color color = {255, 255, 255, 0};
// Add the effect:
Add(412,
300,
"Perfect!",
FontManager::GetInstance()->GetFont("ScoreEffect"),
color,
0.8f,
0.0f,
1500,
0.5f);
}
// Adds an effect to the manager.
void EffectManager::Add(Sint16 x, Sint16 y, string text,
Font *font, SDL_Color color, float initialAlpha,
float velocity, Uint32 lifeTime, float gravity)
{
TRAP(m_initialized == false, "EffectManager::AddScoreEffect() - Manager has not been initialized");
{
TextEffect *effect = new TextEffect(x, y, text, font, color, initialAlpha, velocity, lifeTime, gravity);
// Add the effect to the list:
m_activeEffects.push_back(effect);
}
}
// Updates the effects.
// Returns true if a redraw is required.
bool EffectManager::Update()
{
TRAP(m_initialized == false, "EffectManager::AddScoreEffect() - Manager has not been initialized");
bool redraw = false;
list<TextEffect *>::iterator itr;
for (itr = m_activeEffects.begin() ; itr != m_activeEffects.end() ; itr++)
{
redraw |= (*itr)->Update();
// Remove inactive effects from the list.
if ( (*itr)->IsActive() == false)
{
delete (*itr);
itr = m_activeEffects.erase(itr);
}
}
return redraw;
}
// Draws the effects.
void EffectManager::Draw(SDL_Surface *screen)
{
TRAP(m_initialized == false, "EffectManager::AddScoreEffect() - Manager has not been initialized");
list<TextEffect *>::iterator itr;
for (itr = m_activeEffects.begin() ; itr != m_activeEffects.end() ; itr++)
(*itr)->Draw(screen);
}
// Clean up - free all the effects.
void EffectManager::Cleanup()
{
TRAP(m_initialized == false, "EffectManager::AddScoreEffect() - Manager has not been initialized");
list<TextEffect *>::iterator itr;
for (itr = m_activeEffects.begin() ; itr != m_activeEffects.end() ; itr++)
delete (*itr);
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _EFFECTMANAGER_H_
#define _EFFECTMANAGER_H_
// A singleton effect manager class.
// The class holds a list of active effects. The user can add an effect
// to the list.
// Once an effect becomes inactive (or invisible), it is removed from
// the list.
#include "SDL.h"
#include <list>
#include <string>
#include "../common/font.h"
#include "../common/texteffect.h"
using namespace std;
class EffectManager
{
private:
list<TextEffect*> m_activeEffects; // A list of active effects
public:
// Add effects:
void Add(Sint16 x, Sint16 y, string text, // Adds an effect
Font *font, SDL_Color color, float initialAlpha,
float velocity, Uint32 lifeTime, float gravity);
void AddScoreEffect(SDL_Event *event); // Adds a score effect
void AddLevelEffect(int level); // Adds a new level effect
void AddPerfectEffect(); // Adds a perfect rectangle effect
void AddGameOverEffect(); // Adds a game over effect
bool Update(); // Updates the effects
void Draw(SDL_Surface *screen); // Draws the effects
static EffectManager* GetInstance();
void Init();
void Cleanup();
private:
static EffectManager* m_instance;
EffectManager(){};
EffectManager(const EffectManager&){};
EffectManager& operator= (const EffectManager&){};
bool m_initialized; // Has the manager been initialized?
};
#endif

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _EVENTS_H_
#define _EVENTS_H_
// User event codes.
#include "SDL_events.h"
enum Events
{
EVENT_HINT = SDL_NUMEVENTS + 1, // This ensures there are no collisions with the standard SDL events
EVENT_PAUSE, // Pause the game
EVENT_RESUME, // Resume the game
EVENT_START, // Start a new game
EVENT_RESTART, // Restart the game
EVENT_SELECTION_ADD, // A marble was added to the selection
EVENT_SELECTION_CANCEL, // The user cancelled the current selection
EVENT_SELECTION_INVALID, // The user selected an invalid marble
EVENT_RECT_COMPLETE, // Rectangle was completed
EVENT_PERFECT, // A perfect rectangle was complete
EVENT_NEW_LEVEL, // Level over, advanced to next level
EVENT_TIME_LOW, // Time is running low
EVENT_TIME_OK, // Time increased, and is over the low threshold
EVENT_GAME_OVER, // Game over
EVENT_MUTE, // Mute
EVENT_UNMUTE, // Unmute
EVENT_ABOUT, // Show about window
EVENT_HIGH_SCORES, // Show high scores window
EVENT_CLOSE, // Close the window
EVENT_REDRAW, // Force a screen redraw
EVENT_TRACK_OVER, // A music track has ended
EVENT_WEBSITE, // Visit the website
};
// Pushes a user event on to the SDL queue.
inline void PushUserEvent(Events eventCode, void *data1 = NULL, void *data2 = NULL)
{
SDL_Event event;
event.type = SDL_USEREVENT;
event.user.code = eventCode;
event.user.data1 = data1;
event.user.data2 = data2;
SDL_PushEvent(&event);
}
#endif

View File

@@ -0,0 +1,168 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _FILENAMES_H_
#define _FILENAMES_H_
/*
All of the game's resource files are listed here.
See
*/
#include <string>
// Graphics:
const std::string GRAPHIC_RESOURCES[] = {
// ID Filename
// Window backgrounds:
"MainWindowBackground", "data/interface/background.png",
"AboutWindowBackground", "data/interface/about_window.png",
"GameOverWindowBackground", "data/interface/gameover_window.png",
"HighScoresWindowBackground","data/interface/hs_window.png",
"QuitWindowBackground", "data/interface/quit_window.png",
// Small button:
"SmallButtonNormal", "data/interface/btn_small_normal.png",
"SmallButtonDisabled", "data/interface/btn_small_disabled.png",
"SmallButtonHover", "data/interface/btn_small_hover.png",
"SmallButtonClicked", "data/interface/btn_small_clicked.png",
"SmallButtonMask", "data/interface/btn_small_mask.png",
// Medium button:
"MediumButtonNormal", "data/interface/btn_medium_normal.png",
"MediumButtonDisabled", "data/interface/btn_medium_disabled.png",
"MediumButtonHover", "data/interface/btn_medium_hover.png",
"MediumButtonClicked", "data/interface/btn_medium_clicked.png",
"MediumButtonMask", "data/interface/btn_medium_mask.png",
// Large:
"LargeButtonNormal", "data/interface/btn_large_normal.png",
"LargeButtonDisabled", "data/interface/btn_large_disabled.png",
"LargeButtonHover", "data/interface/btn_large_hover.png",
"LargeButtonClicked", "data/interface/btn_large_clicked.png",
"LargeButtonMask", "data/interface/btn_large_mask.png",
// Text box:
"TextBoxBackground", "data/interface/textbox_bg.png",
"TextBoxCursor", "data/interface/cursor.png",
// Picture button foregrounds:
"MuteButton", "data/interface/mute.png",
"UnmuteButton", "data/interface/unmute.png",
"AboutButton", "data/interface/info.png",
"HighScoresButton", "data/interface/cup.png",
// Time bar label:
"TimeBar", "data/interface/time_bar.png",
"TimeBarFlash", "data/interface/time_bar_flash.png",
"TimeBarPaused", "data/interface/time_bar_paused.png",
// Score label:
"ScoreLabel", "data/interface/label.png",
// Marbles:
"MarbleNormalBlue", "data/marbles/blue.png",
"MarbleNormalGreen", "data/marbles/green.png",
"MarbleNormalRed", "data/marbles/red.png",
"MarbleNormalYellow", "data/marbles/yellow.png",
"MarbleSelectedBlue", "data/marbles/blue_s.png",
"MarbleSelectedGreen", "data/marbles/green_s.png",
"MarbleSelectedRed", "data/marbles/red_s.png",
"MarbleSelectedYellow", "data/marbles/yellow_s.png",
"MarblePaused", "data/marbles/grey.png",
// Misc.:
"Logo", "data/interface/logo.png",
};
// Sound:
const std::string SOUND_RESOURCES[] = {
// ID Filename
"RectangleComplete", "data/sounds/rectangle_complete.ogg",
"NewLevel", "data/sounds/new_level.ogg",
"GameOver", "data/sounds/game_over.ogg",
"TimeAlert", "data/sounds/time_alert.ogg",
"ButtonClick", "data/sounds/button_click.ogg",
"SelectionCancelled", "data/sounds/selection_cancelled.ogg",
"MarbleClick", "data/sounds/marble_click.ogg",
"SelectionInvalid", "data/sounds/selection_invalid.ogg",
"PerfectRectangle", "data/sounds/perfect_rectangle.ogg",
"HighScore", "data/sounds/high_score.ogg",
};
// Music:
const std::string MUSIC_RESOURCES[] = {
// ID Filename
"MusicTrack0", "data/music/track_00.ogg",
"MusicTrack1", "data/music/track_01.ogg",
};
// Fonts:
const std::string FONT_RESOURCES[] = {
// ID Filename Size
// Window:
"WindowTitleFont", "data/fonts/Vera.ttf", "16",
// Buttons:
"MediumButtonFont", "data/fonts/Vera.ttf", "16",
"LargeButtonFont", "data/fonts/Vera.ttf", "24",
"TooltipFont", "data/fonts/Vera.ttf", "10",
// Text box:
"TextBoxFont", "data/fonts/VeraBd.ttf", "16",
// About window:
"AppVersionFont", "data/fonts/VeraBd.ttf", "16",
"LinkFont", "data/fonts/Vera.ttf", "14",
"CreditsFont", "data/fonts/Vera.ttf", "13",
"LicenseFont", "data/fonts/Vera.ttf", "11",
// Game over window:
"GameOverScoreFont", "data/fonts/VeraBd.ttf", "16",
"GameOverCongratsFont", "data/fonts/Vera.ttf", "16",
"GameOverStatsFont", "data/fonts/Vera.ttf", "16",
// High scores window:
"HighScoresFont", "data/fonts/VeraBd.ttf", "16",
// Main window:
"ScoreFont", "data/fonts/VeraBd.ttf", "32",
"LevelFont", "data/fonts/VeraBd.ttf", "24",
// Quit window:
"DialogTextFont", "data/fonts/Vera.ttf", "16",
// Text effects:
"ScoreEffect", "data/fonts/VeraBd.ttf", "64",
"LevelEffect", "data/fonts/VeraBd.ttf", "100",
"GameOverEffect", "data/fonts/VeraBd.ttf", "64",
};
#endif

View File

@@ -0,0 +1,318 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../common/font.h"
#include "../common/surfacemanager.h"
#include <cstdlib>
#include <cstdarg>
#include "../common/trap.h"
// Initializes a font object, using the argument
// TTF file and point size.
Font::Font(string TTFfile, int size)
{
m_font = TTF_OpenFont(TTFfile.c_str(), size);
TRAP(m_font == NULL, "Font::Font() - Could not open " << TTFfile);
}
Font::~Font()
{
TTF_CloseFont(m_font);
}
// Renders a text surface.
SDL_Surface *Font::Render(Font::Alignment alignment, SDL_Color color, SDL_Color BGcolor,
float alpha, string text)
{
TRAP(m_font == NULL, "Font::Render() - Font not initialized");
if (text == "")
return NULL;
// Split the text into seperate lines:
std::vector<std::string> lines;
SplitToLines(text, lines);
// Determine rendering mode: If the foreground and
// background colors are identical, don't render the
// background.
bool shaded = (BGcolor.r == color.r && BGcolor.g == color.g && BGcolor.b == color.b) ? false : true;
// Render each line to a surface, and remember the widest line:
std::vector<SDL_Surface*> lineSurfaces;
int maxLineWidth = 0;
int combinedHeight = 0;
for (size_t i = 0 ; i < lines.size() ; ++i)
{
SDL_Surface *temp;
// Determine rendering mode, and render the line:
if (shaded) // Renders with a colored background
{
SDL_Surface *temp1 = TTF_RenderText_Shaded(m_font, lines[i].c_str(), color, BGcolor);
// The rendered surface must be converted to the display format, otherwise it
// won't show up properly.
temp = SDL_DisplayFormatAlpha(temp1);
SDL_FreeSurface(temp1);
}
else // Renders blended
temp = TTF_RenderText_Blended(m_font, lines[i].c_str(), color);
TRAP(temp == NULL, "Font::Render() - TTF_RenderText_Blended() failed");
if (temp->w > maxLineWidth)
maxLineWidth = temp->w;
combinedHeight += temp->h;
lineSurfaces.push_back(temp);
}
// Calcaulate the line spacing (in pixels):
// int lineSpacing = (TTF_FontLineSkip(m_font) - TTF_FontAscent(m_font)) / 2;
// FIX:
int lineSpacing = -3;
// Create a new surface, to hold all the lines combined:
SDL_Surface *textSurface = SDL_CreateRGBSurface(
lineSurfaces[0]->flags,
maxLineWidth,
(int) (combinedHeight + (lines.size() - 1) * lineSpacing),
lineSurfaces[0]->format->BitsPerPixel,
lineSurfaces[0]->format->Rmask,
lineSurfaces[0]->format->Gmask,
lineSurfaces[0]->format->Bmask,
lineSurfaces[0]->format->Amask);
TRAP(textSurface == NULL, "Font::Render() - SDL_CreateRGBSurface() failed");
// Fill the surface with the background color, if applicable:
if (shaded)
SDL_FillRect(textSurface, NULL,
SDL_MapRGB(textSurface->format, BGcolor.r, BGcolor.g, BGcolor.b));
// Blit the lines to the new surface, freeing their surfaces as we go along:
SDL_Rect rect = {0,0,0,0};
SurfaceManager *sfcMgr = SurfaceManager::GetInstance();
for (size_t i = 0 ; i < lineSurfaces.size() ; ++i)
{
// Horizontal alignment:
switch (alignment)
{
case ALN_LEFT:
rect.x = 0;
break;
case ALN_CENTER:
rect.x = (Sint16)((maxLineWidth - lineSurfaces[i]->w) / 2);
break;
case ALN_RIGHT:
rect.x = (Sint16)(maxLineWidth - lineSurfaces[i]->w);
break;
default:
ERR("Font::Render() - Invalid alignment");
break;
}
// Vertical placing:
if (i == 0)
rect.y = 0;
else
{
rect.y = (Sint16)(i * (lineSurfaces[i - 1]->h + lineSpacing));
SDL_FreeSurface(lineSurfaces[i - 1]);
}
sfcMgr->Blit(lineSurfaces[i], textSurface, alpha, &rect);
}
SDL_FreeSurface(lineSurfaces[lineSurfaces.size() - 1]);
return textSurface;
}
SDL_Surface *Font::Render(Font::Alignment alignment, SDL_Color color, SDL_Color BGcolor,
float alpha, const char *format, ...)
{
// Format the text:
char formatted[MAX_TEXT_LEN]; // Holds the text after formatting
va_list listOfArgs; // Pointer to the list of arguments
if (format == NULL) // If there's no text, do nothing
{
*formatted = 0;
}
else // Handle the variable-argument list
{
va_start(listOfArgs, format);
vsprintf(formatted, format, listOfArgs);
va_end(listOfArgs);
}
return Render(alignment, color, BGcolor, alpha, string(formatted));
}
// Renders transparent text.
SDL_Surface *Font::RenderTransparent(Font::Alignment alignment, SDL_Color color, float alpha, string text)
{
return Render(alignment, color, color, alpha, text);
}
// Renders transparent text, with printf-like formatting.
SDL_Surface *Font::RenderTransparent(Font::Alignment alignment, SDL_Color color, float alpha,
const char *format, ...)
{
// Format the text:
char formatted[MAX_TEXT_LEN]; // Holds the text after formatting
va_list listOfArgs; // Pointer to the list of arguments
if (format == NULL) // If there's no text, do nothing
{
*formatted = 0;
}
else // Handle the variable-argument list
{
va_start(listOfArgs, format);
vsprintf(formatted, format, listOfArgs);
va_end(listOfArgs);
}
return Render(alignment, color, color, alpha, string(formatted));
}
// Renders a string
SDL_Surface *Font::RenderPlain(Font::Alignment alignment, SDL_Color color, string text)
{
return Render(alignment, color, color, 1.0f, text);
}
SDL_Surface *Font::RenderPlain(Font::Alignment alignment, SDL_Color color, const char *format, ...)
{
// Format the text:
char formatted[MAX_TEXT_LEN]; // Holds the text after formatting
va_list listOfArgs; // Pointer to the list of arguments
if (format == NULL) // If there's no text, do nothing
{
*formatted = 0;
}
else // Handle the variable-argument list
{
va_start(listOfArgs, format);
vsprintf(formatted, format, listOfArgs);
va_end(listOfArgs);
}
return Render(alignment, color, color, 1.0f, string(formatted));
}
// Renders shaded text (text on a colored background):
SDL_Surface *Font::RenderShaded(Font::Alignment alignment, SDL_Color color, SDL_Color BGcolor, string text)
{
return Render(alignment, color, BGcolor, 1.0f, text);
}
SDL_Surface *Font::RenderShaded(Font::Alignment alignment, SDL_Color color, SDL_Color BGcolor,
const char *format, ...)
{
// Format the text:
char formatted[MAX_TEXT_LEN]; // Holds the text after formatting
va_list listOfArgs; // Pointer to the list of arguments
if (format == NULL) // If there's no text, do nothing
{
*formatted = 0;
}
else // Handle the variable-argument list
{
va_start(listOfArgs, format);
vsprintf(formatted, format, listOfArgs);
va_end(listOfArgs);
}
return Render(alignment, color, BGcolor, 1.0f, string(formatted));
}
// Gets the advance value of a glyph.
// The advance is the total horizontal space the
// rendered glyph occupies, including the spacing
// between it and the following glyph.
// See http://jcatki.no-ip.org/SDL_ttf/metrics.png
Uint16 Font::GetGlyphAdvance(Uint16 c)
{
int ret = 0;
TTF_GlyphMetrics(m_font, c, NULL, NULL, NULL, NULL, &ret);
return (Uint16) ret;
}
// Sets the font style:
void Font::SetStyle(Style style)
{
if (m_font == NULL)
return;
switch (style)
{
case STYLE_NORMAL:
TTF_SetFontStyle(m_font, TTF_STYLE_NORMAL);
break;
case STYLE_BOLD:
TTF_SetFontStyle(m_font, TTF_STYLE_BOLD);
break;
case STYLE_ITALIC:
TTF_SetFontStyle(m_font, TTF_STYLE_ITALIC);
break;
case STYLE_UNDERLINE:
TTF_SetFontStyle(m_font, TTF_STYLE_UNDERLINE);
break;
default:
return;
}
}
// Splits the text into lines.
// The result is stored in a vector of strings.
void Font::SplitToLines(std::string text, std::vector<std::string>& lines)
{
lines.empty();
size_t nextNewLine = 0;
size_t lastNewLine = 0;
while ((nextNewLine = text.find('\n', lastNewLine)) != text.npos)
{
lines.push_back(text.substr(lastNewLine, nextNewLine - lastNewLine));
lastNewLine = nextNewLine + 1;
}
lines.push_back(text.substr(lastNewLine, text.length() - lastNewLine));
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _FONT_H_
#define _FONT_H_
// Font wrapper class.
// A font is defined as a face (e.g. Times New Roman) of a specific
// point size (e.g. 16).
// The class supports multi-line strings and text alignment.
#include "SDL.h"
#include "SDL_ttf.h"
#include <string>
#include <vector>
using namespace std;
class Font
{
public:
enum Alignment {ALN_LEFT, ALN_CENTER, ALN_RIGHT}; // Text alignment
enum Style {STYLE_NORMAL, STYLE_BOLD, STYLE_ITALIC, STYLE_UNDERLINE}; // Font styles
private:
TTF_Font *m_font; // The SDL_ttf font
public:
Font(string TTFfile, int size);
~Font();
// Renders plain text:
SDL_Surface *RenderPlain(Font::Alignment alignment, SDL_Color color, string text);
SDL_Surface *RenderPlain(Font::Alignment alignment, SDL_Color color, const char *format, ...);
// Renders transparent text:
SDL_Surface *RenderTransparent(Font::Alignment alignment, SDL_Color color, float alpha, string text);
SDL_Surface *RenderTransparent(Font::Alignment alignment, SDL_Color color, float alpha,
const char *format, ...);
// Renders shaded text (text on a colored background):
SDL_Surface *RenderShaded(Font::Alignment alignment, SDL_Color color, SDL_Color BGcolor, string text);
SDL_Surface *RenderShaded(Font::Alignment alignment, SDL_Color color, SDL_Color BGcolor,
const char *format, ...);
// Gets the advance value of a glyph:
Uint16 GetGlyphAdvance(Uint16 c);
// Sets the font style:
void SetStyle(Style style);
private:
static const int MAX_TEXT_LEN = 4096; // Maximum text length
// Full control of text's appearance - color, transparency & background.
// Used by the various Render* methods.
SDL_Surface *Render(Font::Alignment alignment, SDL_Color color, SDL_Color BGcolor,
float alpha, string text);
SDL_Surface *Render(Font::Alignment alignment, SDL_Color color, SDL_Color BGcolor,
float alpha, const char *format, ...);
void SplitToLines(string text, vector<string>& lines); // Splits the text into lines
};
#endif

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../common/fontmanager.h"
#include "../common/trap.h"
FontManager* FontManager::m_instance = NULL;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
FontManager* FontManager::GetInstance()
{
if (m_instance == NULL)
{
{
m_instance = new FontManager();
}
}
return m_instance;
}
// Adds a new font to the manager.
// If a resource with the same ID exists, a pointer to it is returned.
// Otherwise, the method returns a pointer to the new font.
Font* FontManager::AddFont(string ID, string fileName, int size)
{
// Make sure the ID does not already exist in the map:
map<string, Font*>::iterator itr = m_map.find(ID);
if (itr != m_map.end())
return itr->second;
Font *font;
{
font = new Font(fileName, size);
}
m_map.insert(pair<string, Font*>(ID, font));
return font;
}
// Gets a font by its ID.
// If the ID does not exist, NULL is returned.
Font *FontManager::GetFont(string ID)
{
map<string, Font*>::iterator itr = m_map.find(ID);
if (itr == m_map.end())
return NULL;
return itr->second;
}
// Releases all the loaded fonts.
void FontManager::Cleanup()
{
map<string, Font*>::iterator itr;
for (itr = m_map.begin() ; itr != m_map.end() ; itr++)
delete itr->second;
m_map.clear();
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _FONTMANAGER_H_
#define _FONTMANAGER_H_
// A singleton font manager class.
// The user can load fonts into the manager. On loading, the user defines
// a unique string identifier that is associated with the font. The user can
// then access the stored fonts using that ID.
//
// Example:
// FontManager::GetInstance()->AddFont("MainFont", "arial.ttf", 16);
// Font *font = FontManager::GetInstance()->GetFont("MainFont");
#include <map>
#include <string>
#include "../common/font.h"
using namespace std;
class FontManager
{
private:
map<string, Font*> m_map; // Map string IDs to font objects
public:
Font *AddFont(string ID, string fileName, int size);
Font *GetFont(string ID);
static FontManager* GetInstance();
void Cleanup();
private:
static FontManager* m_instance;
FontManager(){};
FontManager(const FontManager&){};
FontManager& operator= (const FontManager&){};
};
#endif

View File

@@ -0,0 +1,183 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../common/musicmanager.h"
#include "../common/events.h"
#include "../common/trap.h"
#include <cstdlib>
#include <ctime>
MusicManager* MusicManager::m_instance = NULL;
const float MusicManager::DEFAULT_VOLUME = 0.25f;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
MusicManager* MusicManager::GetInstance()
{
if (m_instance == NULL)
{
{
m_instance = new MusicManager();
srand((unsigned)time(NULL));
}
}
return m_instance;
}
// Adds a new track to the manager.
// If a resource with the same ID exists, a pointer to it is returned.
// Otherwise, the method returns a pointer to the new surface.
Mix_Music *MusicManager::AddTrack(string ID, string fileName)
{
// Make sure the ID does not already exist in the map:
map<string, Mix_Music*>::iterator itr = m_map.find(ID);
if (itr != m_map.end())
return itr->second;
Mix_Music *track = Mix_LoadMUS(fileName.c_str());
TRAP(track == NULL, "MusicManager::AddTrack() - Could not open " << fileName);
m_map.insert(pair<string, Mix_Music*>(ID, track));
m_currentTrack = m_map.find(ID);
return track;
}
// Gets a chunk by its ID.
// If the ID does not exist, NULL is returned.
Mix_Music *MusicManager::GetTrack(string ID)
{
map<string, Mix_Music*>::iterator itr = m_map.find(ID);
if (itr == m_map.end())
return NULL;
return itr->second;
}
// Plays a track.
void MusicManager::PlayTrack(string ID)
{
map<string, Mix_Music*>::iterator itr = m_map.find(ID);
if (itr != m_map.end())
{
Mix_PlayMusic(itr->second, 0);
Mix_HookMusicFinished(TrackOver);
}
m_currentTrack = itr;
}
// Plays a random track
void MusicManager::PlayRandomTrack()
{
int i = rand() % (int) m_map.size(); // NOTE: We assume the RNG has already been seeded
map<string, Mix_Music*>::iterator itr = m_map.begin();
for (int j = 0 ; j < i ; ++j)
itr++;
m_currentTrack = itr;
Mix_PlayMusic(itr->second, 0);
Mix_HookMusicFinished(TrackOver);
}
// Plays the next track.
// The track order is set by their order in the map.
void MusicManager::PlayNextTrack()
{
m_currentTrack++;
if (m_currentTrack == m_map.end())
m_currentTrack = m_map.begin();
Mix_PlayMusic(m_currentTrack->second, 0);
Mix_HookMusicFinished(TrackOver);
}
// Pauses the currently playing track.
void MusicManager::Pause()
{
Mix_PauseMusic();
}
// Resumes playing.
void MusicManager::Resume()
{
Mix_ResumeMusic();
}
// Is a track currently playing?
// Note: Does not check if the track has been paused.
bool MusicManager::IsPlaying()
{
return (Mix_PlayingMusic() == 1);
}
// Sets the music volume.
// 0.0f - Silence, 1.0f - Max volume
void MusicManager::SetVolume(float volume)
{
if (volume < 0.0f || volume > 1.0f)
return;
Mix_VolumeMusic((int)(MIX_MAX_VOLUME * volume));
}
// Releases all the loaded tracks.
void MusicManager::Cleanup()
{
// FIX: This causes an exception on UIButton::TriggerTooltip
// Add a nice fadeout:
// Mix_FadeOutMusic(500);
// SDL_Delay(500);
///////
Mix_HaltMusic();
// Free the tracks:
map<string, Mix_Music*>::iterator itr;
for (itr = m_map.begin() ; itr != m_map.end() ; itr++)
Mix_FreeMusic(itr->second);
m_map.clear();
}
// Automatically called when a track is over.
// This is a callback function for Mix_HookMusicFinished.
void MusicManager::TrackOver()
{
PushUserEvent(EVENT_TRACK_OVER);
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _MUSICMANAGER_H_
#define _MUSICMANAGER_H_
// A singleton music manager class.
#include "SDL.h"
#include "SDL_mixer.h"
#include <map>
#include <string>
using namespace std;
class MusicManager
{
private:
map<string, Mix_Music*> m_map; // Map string IDs to music tracks
map<string, Mix_Music*>::iterator m_currentTrack; // Currently playing track
public:
Mix_Music *AddTrack(string ID, string fileName); // Adds a track to the manager
Mix_Music *GetTrack(string ID); // Gets a track by its ID
void PlayTrack(string ID); // Plays a track
void PlayRandomTrack(); // Plays a random track
void PlayNextTrack(); // Plays the next track
void Pause(); // Pauses the currently playing track
void Resume(); // Resumes playing
bool IsPlaying(); // Is a track currently playing?
void SetVolume(float volume); // Sets the music volume
static MusicManager* GetInstance();
void Cleanup();
static const float DEFAULT_VOLUME; // Music default volume
private:
static MusicManager* m_instance;
MusicManager(){};
MusicManager(const MusicManager&){};
MusicManager& operator= (const MusicManager&){};
// Callback function, called when a track is over:
static void TrackOver();
};
#endif

View File

@@ -0,0 +1,146 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../common/soundmanager.h"
#include "../common/trap.h"
SoundManager* SoundManager::m_instance = NULL;
Uint32 SoundManager::m_lastChannel = 0;
const float SoundManager::DEFAULT_VOLUME = 1.0f;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
SoundManager* SoundManager::GetInstance()
{
if (m_instance == NULL)
{
{
m_instance = new SoundManager();
}
}
return m_instance;
}
// Adds a new chunk to the manager.
// If a resource with the same ID exists, a pointer to it is returned.
// Otherwise, the method returns a pointer to the new surface.
Mix_Chunk *SoundManager::AddSound(string ID, string fileName)
{
// Make sure the ID does not already exist in the map:
map<string, pair<Mix_Chunk*, int> >::iterator itr = m_map.find(ID);
if (itr != m_map.end())
return (itr->second).first;
Mix_Chunk *chunk = Mix_LoadWAV(fileName.c_str());
TRAP(chunk == NULL, "SoundManager::AddSound() - Could not open " << fileName);
pair<Mix_Chunk*, int> chunkChannel = pair<Mix_Chunk*, int>(chunk, ++m_lastChannel);
pair<string, pair<Mix_Chunk*, int> > IDChunkChannel =
pair<string, pair<Mix_Chunk*, int> > (ID, chunkChannel);
m_map.insert(IDChunkChannel);
//m_map.insert(pair<string, <Mix_Chunk*, int channel> >(ID, chunkChannel));
return chunk;
}
// Gets a chunk by its ID.
// If the ID does not exist, NULL is returned.
Mix_Chunk *SoundManager::GetSound(string ID)
{
map<string, pair<Mix_Chunk*, int> >::iterator itr = m_map.find(ID);
if (itr == m_map.end())
return NULL;
return (itr->second).first;
}
// Plays a sound.
void SoundManager::PlaySound(string ID, bool loop)
{
map<string, pair<Mix_Chunk*, int> >::iterator itr = m_map.find(ID);
if (itr != m_map.end())
Mix_PlayChannel((itr->second).second, (itr->second).first, loop ? -1 : 0);
}
// Stops a playing sound.
void SoundManager::StopSound(string ID)
{
map<string, pair<Mix_Chunk*, int> >::iterator itr = m_map.find(ID);
if (itr != m_map.end())
Mix_HaltChannel((itr->second).second);
}
// Stops all sounds.
void SoundManager::StopAll()
{
/*
map<string, pair<Mix_Chunk*, int> >::iterator itr;
for (itr = m_map.begin() ; itr != m_map.end() ; itr++)
Mix_HaltChannel((itr->second).second);
*/
Mix_HaltChannel(-1);
}
// Sets the sound volume.
// 0.0f - Silence, 1.0f - Max volume
void SoundManager::SetVolume(float volume)
{
if (volume < 0.0f || volume > 1.0f)
return;
Mix_Volume(-1, (int)(MIX_MAX_VOLUME * volume));
}
// Sets the a sample's volume.
// 0.0f - Silence, 1.0f - Max volume
void SoundManager::SetVolume(string ID, float volume)
{
if (volume < 0.0f || volume > 1.0f)
return;
map<string, pair<Mix_Chunk*, int> >::iterator itr = m_map.find(ID);
if (itr != m_map.end())
Mix_Volume((itr->second).second, (int)(MIX_MAX_VOLUME * volume));
}
// Releases all the loaded chunks.
void SoundManager::Cleanup()
{
StopAll();
map<string, pair<Mix_Chunk*, int> >::iterator itr;
for (itr = m_map.begin() ; itr != m_map.end() ; itr++)
Mix_FreeChunk((itr->second).first);
m_map.clear();
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SOUNDMANAGER_H_
#define _SOUNDMANAGER_H_
// A singleton SDL mixer chunks manager class.
// The user can use the class to load mixer chunks from sound files. On loading, the
// user defines a unique string identifier that is associated with the chunk. The user
// can then access the stored chunks using that ID.
//
// Example:
// SoundManager::GetInstance()->AddSound("ButtonClick", "click.wav");
// Mix_Chunk *chunk = SoundManager::GetInstance()->GetSound("ButtonClick");
#include "SDL.h"
#include "SDL_mixer.h"
#include <map>
#include <string>
using namespace std;
class SoundManager
{
private:
map<string, pair<Mix_Chunk*, int> > m_map; // Map string IDs to (sound chunks / channels)
public:
Mix_Chunk *AddSound(string ID, string fileName);
Mix_Chunk *GetSound(string ID);
void PlaySound(string ID, bool loop = false); // Plays a sound
void StopSound(string ID); // Stops a playing sound
void StopAll(); // Stops all sounds
void SetVolume(float volume); // Sets the sound's volume
void SetVolume(string ID, float volume); // Sets a sample's volume
static SoundManager* GetInstance();
void Cleanup();
static const float DEFAULT_VOLUME; // Sound effects volume
private:
static SoundManager* m_instance;
SoundManager(){};
SoundManager(const SoundManager&){};
SoundManager& operator= (const SoundManager&){};
static Uint32 m_lastChannel; // Number of last mixing channel allocated to a chunk
};
#endif

View File

@@ -0,0 +1,182 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../common/surfacemanager.h"
#include "../common/trap.h"
#include "SDL_image.h"
SurfaceManager* SurfaceManager::m_instance = NULL;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
SurfaceManager* SurfaceManager::GetInstance()
{
if (m_instance == NULL)
{
{
m_instance = new SurfaceManager();
}
}
return m_instance;
}
// Adds a new surface to the manager.
// If a resource with the same ID already exists, a pointer
// to it is returned. Otherwise, the method returns a pointer
// to the new surface.
SDL_Surface* SurfaceManager::AddSurface(string ID, string fileName)
{
// Check whether the ID already exists in the map:
map<string, SDL_Surface*>::iterator itr = m_map.find(ID);
if (itr != m_map.end())
itr->second;
// Load the image:
SDL_Surface *surface = IMG_Load(fileName.c_str());
TRAP(surface == NULL, "SurfaceManager::AddSurface() - Could not open " << fileName);
// Convert it to the framebuffer's display format:
SDL_Surface *converted = SDL_DisplayFormatAlpha(surface);
SDL_FreeSurface(surface);
m_map[ID] = converted;
return converted;
}
// Adds a new surface to the manager.
// If a resource with the same ID exists, it is overwritten.
// The method returns a pointer to the new surface.
SDL_Surface* SurfaceManager::AddSurface(string ID, SDL_Surface *surface)
{
// Check whether the ID already exists in the map:
map<string, SDL_Surface*>::iterator itr = m_map.find(ID);
if (itr != m_map.end())
SDL_FreeSurface(itr->second);
TRAP(surface == NULL, "SurfaceManager::AddSurface() - adding an NULL surface");
m_map[ID] = surface;
return surface;
}
// Gets a surface by its ID.
// If the ID does not exist, NULL is returned.
SDL_Surface *SurfaceManager::GetSurface(string ID)
{
map<string, SDL_Surface*>::iterator itr = m_map.find(ID);
if (itr == m_map.end())
return NULL;
return itr->second;
}
// Releases all the loaded surfaces.
void SurfaceManager::Cleanup()
{
map<string, SDL_Surface*>::iterator itr;
for (itr = m_map.begin() ; itr != m_map.end() ; itr++)
SDL_FreeSurface(itr->second);
m_map.clear();
}
// Blits the source surface onto the destination surface, while
// combining their alpha values. This allows to blit onto a
// transparent surface, which SDL_BlitSurface does not support.
// The user can also specify the source alpha value to create
// transparent text (0.0f = transparent, 1.0 = opaque).
// Bledning equation:
// result(r,g,b) = source(r,g,b) * source(a) + dest(r,g,b) * (1 - source(a))
// TO DO: Alpha should loook better. Review blending equation.
void SurfaceManager::Blit(SDL_Surface* source, SDL_Surface* dest, float srcAlpha, SDL_Rect *rect)
{
if (source == NULL || dest == NULL || source->format->BitsPerPixel != 32
|| source->format->BitsPerPixel != 32 || rect->x > dest->w || rect->y > dest->h)
return;
// Result, source and destination RGBA values:
Uint8 rr, rg, rb, ra;
Uint8 sr, sg, sb, sa;
Uint8 dr, dg, db, da;
// Lock both surfaces:
if(SDL_MUSTLOCK(source))
if(SDL_LockSurface(source) < 0)
return;
if(SDL_MUSTLOCK(dest))
if(SDL_LockSurface(dest) < 0)
{
if SDL_MUSTLOCK(source)
SDL_UnlockSurface(source);
return;
}
// Make sure we stay in bounds:
int maxX = (rect->x + source->w >= dest->w) ? dest->w - rect->x : source->w;
int maxY = (rect->y + source->h >= dest->h) ? dest->h - rect->y : source->h;
Uint8 *sourcePixel, *destPixel;
float alpha;
for (int x = 0 ; x < maxX ; x++)
for (int y = 0 ; y < maxY ; y++)
{
// Get the source and destaination pixels:
sourcePixel = (Uint8 *) source->pixels + y * source->pitch + x * source->format->BytesPerPixel;
destPixel = (Uint8 *) dest->pixels + (y + rect->y) * dest->pitch +
(x + rect->x) * dest->format->BytesPerPixel;
// Extract the pixels' RGBA components:
SDL_GetRGBA(*(Uint32*)sourcePixel, source->format, &sr, &sg, &sb, &sa);
SDL_GetRGBA(*(Uint32*)destPixel, dest->format, &dr, &dg, &db, &da);
// Blend and write the result back to the destination pixel:
alpha = sa / 255.0f; // Convert from 0..255 to 0.0..1.0
rr = (Uint8) (sr * alpha + dr * (1.0f - alpha));
rg = (Uint8) (sg * alpha + dg * (1.0f - alpha));
rb = (Uint8) (sb * alpha + db * (1.0f - alpha));
ra = (Uint8) (sa * alpha + da * (1.0f - alpha));
// A = A1 (1 - A2) + A2 A2
//float A1 = sa / 255.0f;
//float A2 = da / 255.0f;
//ra = (Uint8) (A2 * (1.0f - A1) + (A1 * A1));
*(Uint32 *)destPixel = SDL_MapRGBA(source->format, rr, rg, rb, (Uint8) (ra * srcAlpha));
}
if SDL_MUSTLOCK(source)
SDL_UnlockSurface(source);
if SDL_MUSTLOCK(dest)
SDL_UnlockSurface(dest);
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SURFACEMANAGER_H_
#define _SURFACEMANAGER_H_
// A singleton SDL surface manager class.
// The user can use the class to load surfaces from image files. On loading, the
// user defines a unique string identifier that is associated with the surface. The user
// can then access the stored surfaces using that ID.
//
// Example:
// SurfaceManager::GetInstance()->AddSurface("SmallButton", "small_button.png");
// SDL_Surface *surface = SurfaceManager::GetInstance()->GetSurface("SmallButton");
#include "SDL.h"
#include <map>
#include <string>
using namespace std;
class SurfaceManager
{
private:
map<string, SDL_Surface*> m_map; // Map string IDs to font objects
public:
SDL_Surface *AddSurface(string ID, string fileName);
SDL_Surface *AddSurface(string ID, SDL_Surface *surface);
SDL_Surface *GetSurface(string ID);
static SurfaceManager* GetInstance();
void Cleanup();
static void Blit(SDL_Surface *source, SDL_Surface *dest, float alpha, SDL_Rect *rect); // Improved blitting
private:
static SurfaceManager* m_instance;
SurfaceManager(){};
SurfaceManager(const SurfaceManager&){};
SurfaceManager& operator= (const SurfaceManager&){};
};
#endif

View File

@@ -0,0 +1,140 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "texteffect.h"
#include "../common/trap.h"
#include "../common/common.h"
// Constructor.
TextEffect::TextEffect(Sint16 x, Sint16 y, string text, Font *font, SDL_Color color, float initialAlpha,
float velocity, Uint32 lifeTime, float gravity)
{
m_x = x;
m_y = y;
m_text = text;
m_font = font;
m_color = color;
if (initialAlpha > 1.0f || initialAlpha < 0.0f)
m_alpha = 255;
else
m_alpha = (Uint8) (255 * initialAlpha);
m_visible = (m_alpha > 0.0f);
m_velocity = velocity;
m_lifeTime = lifeTime;
m_gravity = gravity;
m_surface = NULL;
Render(true);
m_startTime = SDL_GetTicks();
}
// Destrcutor.
// Free the surface.
TextEffect::~TextEffect()
{
if (m_surface)
SDL_FreeSurface(m_surface);
}
// Updates the effect.
// Returns true if a redraw is required.
bool TextEffect::Update()
{
if (m_visible == false)
return false;
bool redraw = false;
// Calculate the alpha value, as a function of the time.
// A signed int is used to prevent underflow (the effect will become opaque again).
Sint16 alpha = 255 - (Sint16) (255 * ((SDL_GetTicks() - m_startTime) / (float) m_lifeTime));
if (alpha < 0)
alpha = 0;
if (alpha != (Sint16) m_alpha)
{
m_alpha = (Uint8) alpha;
redraw = true;
//cerr << alpha << endl;
// Check if the surface is now fully transparent:
if (alpha == 0)
m_visible = false;
Render(false); // The surface needs to be re-rendered with each change to its alpha
}
// Update the velocity, as a function of m_gravity and time:
m_velocity += ((SDL_GetTicks() - m_startTime) / 1000.0f) * m_gravity;
// Update the location:
Sint16 y = m_y - (Sint16) m_velocity;
if (y != m_y)
{
m_y = y;
redraw = true;
// Check if the surface went out of bounds:
if (y + m_h < 0 || y > SCREEN_HEIGHT)
m_visible = false;
}
return redraw;
}
// Draws the effect.
void TextEffect::Draw(SDL_Surface *screen)
{
SDL_Rect rect;
rect.x = m_x;
rect.y = m_y;
SDL_BlitSurface(m_surface, NULL, screen, &rect);
}
// Renders the surface.
void TextEffect::Render(bool center)
{
if (m_surface)
SDL_FreeSurface(m_surface);
m_surface = m_font->RenderTransparent(Font::ALN_CENTER, m_color, m_alpha / 255.0f, m_text);
m_w = (Sint16) m_surface->w;
m_h = (Sint16) m_surface->h;
// Center the text:
if (center)
{
m_x -= m_w / 2;
m_y -= m_h / 2;
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _TEXTEFFECT_H_
#define _TEXTEFFECT_H_
// Text effect.
// Basically, a surface with a text message that can move and fade out.
#include "SDL.h"
#include <string>
#include "../common/font.h"
using namespace std;
class TextEffect
{
private:
string m_text; // The effect's text
SDL_Surface *m_surface; // The current surface
Font *m_font; // Font used to render the text
SDL_Color m_color; // Font color
Sint16 m_x, m_y, m_w, m_h; // Location and dimensions
Uint8 m_alpha; // Current alpha value
bool m_visible; // Flag indicating the effect's visibilty
Uint32 m_startTime; // Starting time
float m_velocity; // Effect's current velocity (pixels per second)
Uint32 m_lifeTime; // The effect's lifetime, in ms
float m_gravity; // m_gravity factor (in pixels per second per second)
public:
// Constructor / destructor:
TextEffect(Sint16 x, Sint16 y, string text, Font *font, SDL_Color color, float initialAlpha = 1.0f,
float velocity = 0.0f, Uint32 lifeTime = 5000, float gravity = 0.5f);
~TextEffect();
bool IsActive(){return m_visible;}
bool Update(); // Updates the effect
void Draw(SDL_Surface *screen); // Draws the effect
private:
void Render(bool center); // Renders the surface
};
#endif

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _TRAP_H_
#define _TRAP_H_
// Error trapping macros.
#include <iostream>
#include <sstream>
using namespace std;
#ifdef ANDROID
#include <android/log.h>
// Trap - throws a string message if the condition is true.
// A nicer alternative to assert.
#undef TRAP
#define TRAP(cond, msg) \
{ \
if(cond) { \
ostringstream __TRAP_stream; \
__TRAP_stream << msg << flush; \
__android_log_print(ANDROID_LOG_FATAL, "Jooleem", "%s:%i: error: %s", __FILE__, __LINE__, __TRAP_stream.str().c_str()); \
exit(1);\
} \
}
#else
// Trap - throws a string message if the condition is true.
// A nicer alternative to assert.
#undef TRAP
#define TRAP(cond, msg) \
{ \
if(cond) { \
ostringstream __TRAP_stream; \
__TRAP_stream << msg << "\n(" << __FILE__ << ", line " << __LINE__ << ")" << endl; \
throw(__TRAP_stream.str()); \
} \
}
#endif
// Unconditional throw. Best used in places where the program should
// never be, like switch defaults etc.
#undef ERR
#define ERR(msg) TRAP(true, msg)
#endif

View File

@@ -0,0 +1,291 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../engine/aboutstate.h"
#include "../engine/quitstate.h"
#include "../UI/mainwindow.h"
#include "../common/trap.h"
#include "../common/events.h"
#include "../common/surfacemanager.h"
#include "../common/soundmanager.h"
#include "../common/musicmanager.h"
#include "../UI/uitextbox.h"
// Platform specific includes for lauching the web browser.
// See AboutState::LaunchBrowser().
#ifdef _WIN32
#include "windows.h"
#include "SDL_syswm.h"
#endif
#ifdef __APPLE__
#include <Carbon/Carbon.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
#endif
//////////////////////////
AboutState* AboutState::m_instance = NULL;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
AboutState* AboutState::GetInstance()
{
if (m_instance == NULL)
{
m_instance = new AboutState();
if (m_instance == NULL)
{
exit(1);
}
}
return m_instance;
}
// Initializes the state.
// Loads state specific resources, should be called only once.
void AboutState::Init(Engine* engine)
{
if (m_initialized)
return;
m_aboutWindow = new AboutWindow(SurfaceManager::GetInstance()->GetSurface("AboutWindowBackground"));
m_aboutWindow->Align(UIControl::HALN_CENTER, UIControl::VALN_MIDDLE, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
m_initialized = true;
}
void AboutState::Enter(Engine* engine)
{
TRAP(m_initialized == false, "AboutState::Enter() - State has not been initialized");
MainWindow* mainWindow = engine->GetMainWindow();
m_aboutWindow->SetEnabled(true);
// Set the buttons:
mainWindow->SetEnabled(false);
// Grey out the time bar:
mainWindow->GetProgressBar(MainWindow::PRG_TIMEBAR)->SetEnabled(false);
// Pause the game:
engine->GetGame()->SetPaused(true);
// Mute alert sound:
SoundManager::GetInstance()->SetVolume("TimeAlert", 0.0f);
engine->Redraw();
}
void AboutState::Exit(Engine* engine)
{
TRAP(m_initialized == false, "AboutState::Exit() - State has not been initialized");
// Restore alert sound
if (!engine->GetMute())
SoundManager::GetInstance()->SetVolume("TimeAlert", 1.0f);
m_aboutWindow->SetEnabled(false);
}
void AboutState::HandleEvents(Engine* engine)
{
TRAP(m_initialized == false, "AboutState::HandleEvents() - State has not been initialized");
// This flag determines whether the screen needs to be redrawn.
bool redraw = false;
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
// Check for user events:
case SDL_USEREVENT:
switch (event.user.code)
{
// Close the about window:
case EVENT_CLOSE:
engine->PopState();
break;
// Website link:
case EVENT_WEBSITE:
LaunchBrowser(APP_URL);
break;
// Music track over:
case EVENT_TRACK_OVER:
MusicManager::GetInstance()->PlayNextTrack();
break;
// Forced redraw:
case EVENT_REDRAW:
redraw = true;
break;
}
break;
// Send mouse clicks to the game object:
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= m_aboutWindow->MouseUp(event.button.x, event.button.y);
}
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= m_aboutWindow->MouseDown(event.button.x, event.button.y);
}
break;
// Mouse motion for hover:
case SDL_MOUSEMOTION:
{
redraw |= m_aboutWindow->Hover(event.motion.x, event.motion.y);
}
break;
// Handle keyboard input:
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym) // Get the key symbol
{
// Take a screenshot:
case SDLK_F12:
ScreenShot();
break;
// Enter or escape close the window:
case SDLK_RETURN:
case SDLK_ESCAPE:
engine->PopState();
return;
default:
break;
}
}
break;
case SDL_QUIT:
engine->PushState(QuitState::GetInstance());
break;
}
}
if (redraw)
engine->Redraw();
}
// The computer makes another move.
void AboutState::Update(Engine* engine)
{
TRAP(m_initialized == false, "AboutState::Update() - State has not been initialized");
// Redraw if one of the window's controls requires:
if (m_aboutWindow->Update())
engine->Redraw();
}
void AboutState::Draw(Engine* engine)
{
TRAP(m_initialized == false, "AboutState::Draw() - State has not been initialized");
engine->GetMainWindow()->Draw(engine->GetScreen());
engine->GetGame()->Draw(engine->GetScreen());
m_aboutWindow->Draw(engine->GetScreen());
}
// Cleans up any state specific resources loaded in Init().
void AboutState::Cleanup(Engine* engine)
{
TRAP(m_initialized == false, "AboutState::Cleanup() - State has not been initialized");
delete m_aboutWindow;
m_initialized = false;
}
// Launch the web browser to the specified URL.
// NOTE: This is the only platform specific piece of code
// in the project since it calls the operating system to launch the
// URL.
// Supported platforms:
// * Win32
// * OS X (Carbon)
// TODO: Linux etc.
void AboutState::LaunchBrowser(string URL)
{
#ifdef _WIN32
// Get the window handle:
SDL_SysWMinfo info;
SDL_GetWMInfo(&info);
ShellExecute(info.window, // Handle to a parent window
"open", // The action, or "verb", to be performed
URL.c_str(), // The file on which to execute the specified verb
NULL, // Parameters to be passed to the application
NULL, // Default directory
SW_SHOW); // Activates the window and displays it in its current size and position
#endif // WIN32
#ifdef __APPLE__
CFURLRef url = NULL;
// Create a string ref of the URL:
CFStringRef urlStr = CFStringCreateWithCString( NULL, URL.c_str(), kCFStringEncodingASCII);
// Create a URL object:
url = CFURLCreateWithString (NULL, urlStr, NULL);
// Open the URL:
LSOpenCFURLRef(url, NULL);
// Release the created resources:
CFRelease(url);
CFRelease(urlStr);
#endif // __APPLE__
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ABOUTSTATE_H_
#define _ABOUTSTATE_H_
// About screen engine state. Singleton.
#include "../engine/enginestate.h"
#include "../UI/aboutwindow.h"
using namespace std;
class AboutState: public EngineState
{
private:
AboutWindow *m_aboutWindow; // The "About" window
public:
void Init(Engine* engine);
void Enter(Engine* engine);
void Exit(Engine* engine);
void HandleEvents(Engine* engine);
void Update(Engine* engine);
void Draw(Engine* engine);
void Cleanup(Engine* engine);
static AboutState* GetInstance();
private:
static AboutState* m_instance;
AboutState(){};
AboutState(const AboutState&);
AboutState& operator= (const AboutState&);
void LaunchBrowser(string URL); // Launch the web browser to the specified URL
};
#endif

View File

@@ -0,0 +1,451 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../engine/engine.h"
#include "../engine/enginestate.h"
#include "../engine/introstate.h"
#include "../engine/gameonstate.h"
#include "../engine/pausedstate.h"
#include "../engine/gameoverstate.h"
#include "../engine/aboutstate.h"
#include "../engine/highscoresstate.h"
#include "../engine/quitstate.h"
#include "../common/soundmanager.h"
#include "../common/musicmanager.h"
#include "../common/fontmanager.h"
#include "../common/surfacemanager.h"
#include "../common/effectmanager.h"
#include "../common/trap.h"
#include "../common/filenames.h"
#include "SDL.h"
#include "SDL_mixer.h"
#include "SDL_ttf.h"
#include "SDL_image.h"
#include <iostream>
#include <cstdlib> // For atoi()
// Constructor - initialize SDL and allocate the data members.
Engine::Engine()
{
m_quit = false;
m_mute = false;
m_redraw = true;
m_screen = NULL;
m_game = NULL;
m_highScores = NULL;
m_mainWindow = NULL;
// Initialize SDL:
InitSDL();
// Show the loading screen:
ShowLoadingScreen();
// Setup progress bar:
SDL_Color color = {0, 0, 0, 0};
SurfaceManager::GetInstance()->AddSurface("TimeBar", "data/interface/time_bar.png");
m_progessBar.Set(111, 285, SurfaceManager::GetInstance()->GetSurface("TimeBar"), NULL, color);
UpdateProgressBar(0.0f);
// Load resources:
LoadResources(0.0f, 0.9f);
// Allocate the game and the main window:
{
m_game = new Game();
m_highScores = new HighScores();
m_mainWindow = new MainWindow(SurfaceManager::GetInstance()->GetSurface("MainWindowBackground"));
m_mainWindow->SetVisible(true);
}
// Initialize the game states while updating the progress bar:
InitStates(0.9f, 0.1f);
// Initialize effects manager:
EffectManager::GetInstance()->Init();
// Show the loading screen for a little while more
SDL_Delay(500);
// Set initial audio levels:
MusicManager::GetInstance()->SetVolume(0.25f);
SoundManager::GetInstance()->SetVolume(1.0f);
// Set the initial engine state:
PushState(IntroState::GetInstance());
}
// Destructor - deallocate and clean up.
Engine::~Engine()
{
// Cleanup the game states:
IntroState::GetInstance()->Cleanup(this);
GameOnState::GetInstance()->Cleanup(this);
PausedState::GetInstance()->Cleanup(this);
GameOverState::GetInstance()->Cleanup(this);
AboutState::GetInstance()->Cleanup(this);
HighScoresState::GetInstance()->Cleanup(this);
QuitState::GetInstance()->Cleanup(this);
// Cleanup local objects:
SDL_FreeSurface(m_screen);
delete m_mainWindow;
delete m_game;
delete m_highScores;
// Free all the resources handled by the managers:
SurfaceManager::GetInstance()->Cleanup();
FontManager::GetInstance()->Cleanup();
SoundManager::GetInstance()->Cleanup();
EffectManager::GetInstance()->Cleanup();
MusicManager::GetInstance()->Cleanup();
// Cleanup SDL:
CleanupSDL();
}
// The main game loop.
// The engine envokes the current state's
// methodes.
void Engine::Run()
{
Uint32 prevFrame; // Time of previous rendered frame
while (m_quit == false)
{
prevFrame = SDL_GetTicks();
m_stateStack.back()->Update(this);
// Redraw only if necessary:
if (m_redraw)
m_stateStack.back()->Draw(this);
m_redraw = false;
m_stateStack.back()->HandleEvents(this);
SDL_Flip(m_screen); // Flip the screen buffers
// Limit framerate:
if (SDL_GetTicks() - prevFrame < FRAME_DELAY)
SDL_Delay(FRAME_DELAY - (SDL_GetTicks() - prevFrame));
}
m_stateStack.back()->Exit(this);
}
// Quit the game:
void Engine::Quit()
{
m_quit = true;
}
// Mute and unmute:
void Engine::Mute(bool flag)
{
m_mute = flag;
if (m_mute)
{
MusicManager::GetInstance()->SetVolume(0.0f);
SoundManager::GetInstance()->SetVolume(0.0f);
}
else
{
MusicManager::GetInstance()->SetVolume(MusicManager::DEFAULT_VOLUME);
SoundManager::GetInstance()->SetVolume(SoundManager::DEFAULT_VOLUME);
}
}
// Changes the engine state.
void Engine::ChangeState(EngineState* state)
{
// Exit the current states in the stack:
while (!m_stateStack.empty())
{
m_stateStack.back()->Exit(this);
m_stateStack.pop_back();
}
// Push the current state, and enter it:
m_stateStack.push_back(state);
m_stateStack.back()->Enter(this);
m_redraw = true;
}
// Pushes an engine state on to the state stack.
void Engine::PushState(EngineState* state)
{
m_stateStack.push_back(state);
m_stateStack.back()->Enter(this);
m_redraw = true;
}
// Pops an engine state from the state stack.
void Engine::PopState()
{
// Exit the current state:
if (!m_stateStack.empty())
{
m_stateStack.back()->Exit(this);
m_stateStack.pop_back();
}
// Enter the previous state:
TRAP(m_stateStack.empty() == true, "Engine::PopState() - Trying to pop an empty stack");
m_stateStack.back()->Enter(this);
m_redraw = true;
}
// Initialize SDL and prepare the screen surface for rendering.
// Returns 0 on success.
void Engine::InitSDL()
{
const SDL_VideoInfo* vidInfo = NULL; // Information about the current video settings
// Initialize SDL:
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) != 0)
{
ERR("Engine::InitSDL() - SDL_Init failed (" << SDL_GetError() << ")");
}
// Initialize sound mixer:
if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) != 0)
{
ERR("Engine::InitSDL() - Mix_OpenAudio failed (" << SDL_GetError() << ")");
}
// Allocate the audio channels. One for each sound chunk plus one for music:
int numOfSounds = (sizeof(SOUND_RESOURCES) / sizeof(std::string)) / 2;
Mix_AllocateChannels(numOfSounds + 1);
// Initialize font renderer:
if(TTF_Init() != 0)
{
ERR("Engine::InitSDL() - TTF_Init failed (" << SDL_GetError() << ")");
}
// Get video settings info:
if((vidInfo = SDL_GetVideoInfo()) == 0)
{
ERR("Engine::InitSDL() - SDL_GetVideoInfo failed (" << SDL_GetError() << ")");
}
// Set the key repeat:
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
// Enable Unicode keyboard translation. This allows us to obtain
// the character codes corresponding to received keyboard events.
SDL_EnableUNICODE(1);
// Set the window icon:
// FIX: Looks like an 8 bit image. SDL doesn't support 8 bit alpha on icons.
SDL_Surface *icon = IMG_Load(ICON.c_str());
SDL_WM_SetIcon(icon, NULL);
SDL_FreeSurface(icon);
// Set the video mode:
if((m_screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, vidInfo->vfmt->BitsPerPixel,
SDL_HWSURFACE|SDL_HWPALETTE|0)) == 0) /* The code does not support SDL_DOUBLEBUF, I wonder how it worked before */
{
ERR("Engine::InitSDL() - SDL_SetVideoMode failed (" << SDL_GetError() << ")");
}
// Set the window caption:
SDL_WM_SetCaption(CAPTION.c_str(), CAPTION.c_str());
}
// Cleanup SDL:
void Engine::CleanupSDL()
{
// FIX: This causes a crash sometimes.
Mix_CloseAudio();
TTF_Quit();
SDL_Quit();
}
// Show a loading message while the game is initializing.
void Engine::ShowLoadingScreen()
{
SDL_Surface *surface = IMG_Load("data/interface/loading.png");
TRAP(surface == NULL, "Engine::ShowLoadingScreen() - File not found");
SDL_FillRect(m_screen, NULL, 0x000000);
SDL_BlitSurface(surface, NULL, m_screen, NULL);
SDL_Flip(m_screen);
SDL_FreeSurface(surface);
}
// Updates the loading progress bar.
// The input is a value between 0.0 and 1.0, indicating
// the current progress (1.0 = full bar)
void Engine::UpdateProgressBar(float val)
{
m_progessBar.SetClipping((Sint16)(SurfaceManager::GetInstance()->GetSurface("TimeBar")->w * val), -1);
m_progessBar.Draw(m_screen);
SDL_Flip(m_screen);
}
// Loads game resources while updating the progress bar.
// basePercentage - Initial progress bar position (0.0..1.0)
// prgBarPercentage - What percentage of the progress bar is to be filled
// by the method (0.0..1.0)
void Engine::LoadResources(float basePercentage, float prgBarPercentage)
{
int numOfGraphics = (sizeof(GRAPHIC_RESOURCES) / sizeof(std::string)) / 2;
int numOfSounds = (sizeof(SOUND_RESOURCES) / sizeof(std::string)) / 2;
int numOfMusic = (sizeof(MUSIC_RESOURCES) / sizeof(std::string)) / 2;
int numOfFonts = (sizeof(FONT_RESOURCES) / sizeof(std::string)) / 3;
int totalResources = numOfGraphics + numOfSounds + numOfMusic + numOfFonts;
int resourceIndex = 0;
// Load graphics:
SurfaceManager *sfcMgr = SurfaceManager::GetInstance();
for (int i = 0 ; i < numOfGraphics ; ++i)
{
sfcMgr->AddSurface(GRAPHIC_RESOURCES[2 * i], GRAPHIC_RESOURCES [2 * i + 1]);
resourceIndex++;
//Update progress bar:
UpdateProgressBar(basePercentage + (resourceIndex / (float) totalResources) * prgBarPercentage);
}
// Load sounds:
SoundManager *sndMgr = SoundManager::GetInstance();
for (int i = 0 ; i < numOfSounds ; ++i)
{
sndMgr->AddSound(SOUND_RESOURCES[2 * i], SOUND_RESOURCES [2 * i + 1]);
resourceIndex++;
//Update progress bar:
UpdateProgressBar(basePercentage + (resourceIndex / (float) totalResources) * prgBarPercentage);
}
// Load music:
MusicManager *musicMgr = MusicManager::GetInstance();
for (int i = 0 ; i < numOfMusic ; ++i)
{
musicMgr->AddTrack(MUSIC_RESOURCES[2 * i], MUSIC_RESOURCES [2 * i + 1]);
resourceIndex++;
//Update progress bar:
UpdateProgressBar(basePercentage + (resourceIndex / (float) totalResources) * prgBarPercentage);
}
// Load fonts:
FontManager *fontMgr = FontManager::GetInstance();
for (int i = 0 ; i < numOfFonts ; ++i)
{
fontMgr->AddFont(FONT_RESOURCES[3 * i],
FONT_RESOURCES [3 * i + 1],
atoi((FONT_RESOURCES [3 * i + 2]).c_str()));
resourceIndex++;
//Update progress bar:
UpdateProgressBar(basePercentage + (resourceIndex / (float) totalResources) * prgBarPercentage);
}
}
// Initializes the game states while updating the progress bar.
// basePercentage - Initial progress bar position (0.0..1.0)
// prgBarPercentage - What percentage of the progress bar is to be filled
// by the method (0.0..1.0)
void Engine::InitStates(float basePercentage, float prgBarPercentage)
{
int numOfStates = 7;
float step = prgBarPercentage / numOfStates;
IntroState::GetInstance()->Init(this);
UpdateProgressBar(basePercentage + step * 1.0f);
GameOnState::GetInstance()->Init(this);
UpdateProgressBar(basePercentage + step * 2.0f);
PausedState::GetInstance()->Init(this);
UpdateProgressBar(basePercentage + step * 3.0f);
GameOverState::GetInstance()->Init(this);
UpdateProgressBar(basePercentage + step * 4.0f);
AboutState::GetInstance()->Init(this);
UpdateProgressBar(basePercentage + step * 5.0f);
HighScoresState::GetInstance()->Init(this);
UpdateProgressBar(basePercentage + step * 6.0f);
QuitState::GetInstance()->Init(this);
UpdateProgressBar(basePercentage + step * 7.0f);
}
#ifdef WIN32
void Engine::LoadWinIcon()
{
}
#endif
////
/*
HANDLE LoadImage( HINSTANCE hinst,
LPCTSTR lpszName,
UINT uType,
int cxDesired,
int cyDesired,
UINT fuLoad
);
lResult = SendMessage(// returns LRESULT in lResult
(HWND) hWndControl, // handle to destination control
(UINT) WM_SETICON, // message ID
(WPARAM) wParam, // = (WPARAM) () wParam;
(LPARAM) lParam // = (LPARAM) () lParam; );
*/
///

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ENGINE_H_
#define _ENGINE_H_
// The game engine
#include "../common/common.h"
#include "../game/game.h"
#include "../game/highscores.h"
#include "../UI/mainwindow.h"
#include "../UI/gameoverwindow.h"
#include "../UI/uilabel.h"
#include "SDL.h"
class EngineState;
class Engine
{
private:
Game *m_game; // Game object
HighScores *m_highScores; // High scores table
MainWindow *m_mainWindow; // The user interface's main window
UILabel m_progessBar; // Loading progress bar
SDL_Surface *m_screen; // The screen surface
vector<EngineState *> m_stateStack; // Stack of engine states
bool m_mute; // Mute flag
bool m_quit; // Quit flag
bool m_redraw; // Redraw screen flag
public:
Engine();
~Engine();
// The main loop:
void Run();
// Quit the game:
void Quit();
// Mute and unmute the game:
void Mute(bool flag);
bool GetMute(){return m_mute;}
// Forces a redraw:
void Redraw(){m_redraw = true;}
// State stack operations:
void ChangeState(EngineState* state);
void PushState(EngineState* state);
void PopState();
// Accessors:
Game* GetGame(){return m_game;}
HighScores* GetHighScores(){return m_highScores;}
MainWindow* GetMainWindow(){return m_mainWindow;}
SDL_Surface* GetScreen(){return m_screen;}
// Helper methods:
private:
void InitSDL(); // Initialize SDL
void CleanupSDL(); // Clean up SDL
// Loading screen:
void ShowLoadingScreen(); // Displays the loading screen
void UpdateProgressBar(float val); // Updates the loading progress bar
// Load resources into managers:
void LoadResources(float basePercentage, float prgBarPercentage);
void LoadSounds();
// Initialize the game states:
void InitStates(float basePercentage, float prgBarPercentage);
// Frame rate:
static const Uint32 FPS = 60; // Frames per second
static const Uint32 FRAME_DELAY = (Uint32) (1000 / FPS); // Delay between frames, in ms
#ifdef WIN32
void LoadWinIcon();
#endif
};
#endif

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ENGINESTATE_H_
#define _ENGINESTATE_H_
// A base class for engine states.
// Inspired by http://tonyandpaige.com/tutorials/game1.html
#include "../engine/engine.h"
class EngineState
{
public:
virtual void Init(Engine* engine) = 0;
virtual void Enter(Engine* engine) = 0;
virtual void Exit(Engine* engine) = 0;
virtual void HandleEvents(Engine* engine) = 0;
virtual void Update(Engine* engine) = 0;
virtual void Draw(Engine* engine) = 0;
virtual void Cleanup(Engine* engine) = 0;
protected:
EngineState():m_initialized(false){} // Force the derived classes to be singletons
bool m_initialized; // Has the state been initialized?
};
#endif

View File

@@ -0,0 +1,398 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../engine/gameonstate.h"
#include "../engine/gameoverstate.h"
#include "../engine/pausedstate.h"
#include "../engine/aboutstate.h"
#include "../engine/highscoresstate.h"
#include "../engine/quitstate.h"
#include "../UI/uibutton.h"
#include "../UI/uilabel.h"
#include "../common/surfacemanager.h"
#include "../common/fontmanager.h"
#include "../common/effectmanager.h"
#include "../common/musicmanager.h"
#include "../common/soundmanager.h"
#include "../common/events.h"
#include "../common/trap.h"
#include <iostream>
GameOnState* GameOnState::m_instance = NULL;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
GameOnState* GameOnState::GetInstance()
{
if (m_instance == NULL)
{
m_instance = new GameOnState();
if (m_instance == NULL)
{
exit(1);
}
}
return m_instance;
}
// Initializes the state.
// Loads state specific resources, should be called only once.
void GameOnState::Init(Engine* engine)
{
if (m_initialized)
return;
m_initialized = true;
}
void GameOnState::Enter(Engine* engine)
{
TRAP(m_initialized == false, "GameOnState::Enter() - State has not been initialized");
Game *game = engine->GetGame();
// Set the buttons:
MainWindow *mainWindow = engine->GetMainWindow();
mainWindow->SetEnabled(true);
mainWindow->GetButton(MainWindow::BTN_START)->SetState(EVENT_RESTART);
mainWindow->GetButton(MainWindow::BTN_PAUSE)->Normal();
mainWindow->GetButton(MainWindow::BTN_START)->Normal();
// Set the time bar:
mainWindow->GetProgressBar(MainWindow::PRG_TIMEBAR)->SetEnabled(true);
// Set the score and level labels:
mainWindow->GetLabel(MainWindow::LBL_SCORE)->SetText(UIControl::HALN_LEFT,
"%d", engine->GetGame()->GetScore() % 1000000);
mainWindow->GetLabel(MainWindow::LBL_LEVEL)->SetText(UIControl::HALN_LEFT,
"Level %d", game->GetLevel());
mainWindow->GetLabel(MainWindow::LBL_LEVEL)->Align(UIControl::HALN_CENTER,
UIControl::VALN_TOP, 94, 44);
engine->GetGame()->SetPaused(false);
engine->Redraw();
}
void GameOnState::Exit(Engine* engine)
{
TRAP(m_initialized == false, "GameOnState::Exit() - State has not been initialized");
}
void GameOnState::HandleEvents(Engine* engine)
{
TRAP(m_initialized == false, "GameOnState::HandleEvents() - State has not been initialized");
// This flag determines whether the screen needs to be redrawn.
bool redraw = false;
SDL_Event event;
Game *game = engine->GetGame();
MainWindow *mainWindow = engine->GetMainWindow();
while(SDL_PollEvent(&event))
{
switch(event.type)
{
// Check for user events:
case SDL_USEREVENT:
redraw |= HandleUserEvents(engine, &event);
break;
// Window was minimised:
case SDL_ACTIVEEVENT:
if (event.active.state & SDL_APPACTIVE)
if (event.active.gain == 0)
mainWindow->GetButton(MainWindow::BTN_PAUSE)->Click();
break;
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= game->Click(event.button.x, event.button.y);
redraw |= mainWindow->MouseUp(event.button.x, event.button.y);
}
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= game->Hover(event.button.x, event.button.y);
redraw |= mainWindow->MouseDown(event.button.x, event.button.y);
}
else if (event.button.button == SDL_BUTTON_RIGHT)
{
redraw |= game->RightClick(event.button.x, event.button.y);
}
break;
// Mouse motion for UI hover:
case SDL_MOUSEMOTION:
{
if( event.motion.state )
redraw |= game->Hover(event.motion.x, event.motion.y);
redraw |= mainWindow->Hover(event.motion.x, event.motion.y);
}
break;
// Handle keyboard input:
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym) // Get the key symbol
{
// Pause / resume:
case SDLK_p:
mainWindow->GetButton(MainWindow::BTN_PAUSE)->Click();
redraw = true;
break;
// Hint:
case SDLK_h:
game->Hint();
redraw = true;
break;
// Quit:
case SDLK_ESCAPE:
engine->PushState(QuitState::GetInstance());
return;
// Take a screenshot:
case SDLK_F12:
ScreenShot();
break;
default:
break;
}
}
break;
case SDL_QUIT:
engine->PushState(QuitState::GetInstance());
break;
}
}
if (redraw)
engine->Redraw();
}
void GameOnState::Update(Engine* engine)
{
TRAP(m_initialized == false, "GameOnState::Update() - State has not been initialized");
MainWindow *mainWindow = engine->GetMainWindow();
Game *game = engine->GetGame();
// Update the game:
if (game->Update())
engine->Redraw();
// Update time bar:
float progress = ((float) game->GetTimeLeft()) / Game::TIME_MAX;
mainWindow->GetProgressBar(MainWindow::PRG_TIMEBAR)->SetProgress(progress);
// Redraw if one of the window's controls requires:
if (mainWindow->Update())
engine->Redraw();
// Update the effects:
if (EffectManager::GetInstance()->Update())
engine->Redraw();
}
void GameOnState::Draw(Engine* engine)
{
TRAP(m_initialized == false, "GameOnState::Draw() - State has not been initialized");
engine->GetMainWindow()->DrawBackground(engine->GetScreen());
engine->GetGame()->Draw(engine->GetScreen());
engine->GetMainWindow()->DrawControls(engine->GetScreen());
EffectManager::GetInstance()->Draw(engine->GetScreen());
}
// Cleans up any state specific resources loaded in Init().
void GameOnState::Cleanup(Engine* engine)
{
TRAP(m_initialized == false, "GameOnState::Cleanup() - State has not been initialized");
m_initialized = false;
}
// Handles user events.
// Returns true if a redraw is necessary.
bool GameOnState::HandleUserEvents(Engine *engine, SDL_Event *event)
{
bool redraw = false;
MainWindow *mainWindow = engine->GetMainWindow();
Game *game = engine->GetGame();
switch (event->user.code)
{
// Restart the game:
case EVENT_RESTART:
engine->GetGame()->Restart();
MusicManager::GetInstance()->PlayNextTrack();
redraw = true;
break;
// Hint:
case EVENT_HINT:
game->Hint();
redraw = true;
break;
// Mute:
case EVENT_MUTE:
engine->Mute(true);
mainWindow->GetButton(MainWindow::BTN_MUTE)->SetState(EVENT_UNMUTE);
redraw = true;
break;
// Unmute:
case EVENT_UNMUTE:
engine->Mute(false);
mainWindow->GetButton(MainWindow::BTN_MUTE)->SetState(EVENT_MUTE);
redraw = true;
break;
// Pause:
case EVENT_PAUSE:
engine->PushState(PausedState::GetInstance());
break;
// About:
case EVENT_ABOUT:
engine->PushState(AboutState::GetInstance());
break;
// High scores:
case EVENT_HIGH_SCORES:
engine->PushState(HighScoresState::GetInstance());
break;
// Game over:
case EVENT_GAME_OVER:
engine->ChangeState(GameOverState::GetInstance());
break;
// Rectangle complete:
case EVENT_RECT_COMPLETE:
// Update score label:
mainWindow->GetLabel(MainWindow::LBL_SCORE)->SetText(UIControl::HALN_LEFT,
"%d", engine->GetGame()->GetScore() % 1000000);
// Add the score effect:
EffectManager::GetInstance()->AddScoreEffect(event);
break;
// Level up:
case EVENT_NEW_LEVEL:
// Update level label:
mainWindow->GetLabel(MainWindow::LBL_LEVEL)->SetText(UIControl::HALN_LEFT,
"Level %d", game->GetLevel());
mainWindow->GetLabel(MainWindow::LBL_LEVEL)->Align(UIControl::HALN_CENTER,
UIControl::VALN_TOP, 94, 44);
// Add the new level effect:
EffectManager::GetInstance()->AddLevelEffect(game->GetLevel());
// Play sound:
if (game->GetLevel() != 1)
SoundManager::GetInstance()->PlaySound("NewLevel");
break;
// Perfect rectangle:
case EVENT_PERFECT:
// Add the prefect rectangle effect:
EffectManager::GetInstance()->AddPerfectEffect();
//SoundManager::GetInstance()->PlaySound("PerfectRectangle");
break;
// Music track over:
case EVENT_TRACK_OVER:
MusicManager::GetInstance()->PlayNextTrack();
break;
// Forced redraw:
case EVENT_REDRAW:
redraw = true;
break;
// Running low on time:
case EVENT_TIME_LOW:
// Flash the time bar:
engine->GetMainWindow()->GetProgressBar(MainWindow::PRG_TIMEBAR)->Flash(true);
// Play the alert sound:
SoundManager::GetInstance()->PlaySound("TimeAlert", true);
// Disable the hint button:
mainWindow->GetButton(MainWindow::BTN_HINT)->SetEnabled(false);
engine->Redraw();
break;
// Time is no longer running low:
case EVENT_TIME_OK:
// Stop flashing the time bar:
engine->GetMainWindow()->GetProgressBar(MainWindow::PRG_TIMEBAR)->Flash(false);
// Stop the alert sound:
SoundManager::GetInstance()->StopSound("TimeAlert");
// Enable the hint button:
mainWindow->GetButton(MainWindow::BTN_HINT)->SetEnabled(true);
engine->Redraw();
break;
default:
break;
}
return redraw;
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _GAMESONTATE_H_
#define _GAMEONSTATE_H_
// Game engine state. Singleton.
#include "../engine/enginestate.h"
class GameOnState: public EngineState
{
private:
public:
void Init(Engine* engine);
void Enter(Engine* engine);
void Exit(Engine* engine);
void HandleEvents(Engine* engine);
void Update(Engine* engine);
void Draw(Engine* engine);
void Cleanup(Engine* engine);
static GameOnState* GetInstance();
private:
static GameOnState* m_instance;
GameOnState(){};
GameOnState(const GameOnState&);
GameOnState& operator= (const GameOnState&);
// Handle user events:
bool HandleUserEvents(Engine *engine, SDL_Event *event);
};
#endif

View File

@@ -0,0 +1,327 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../engine/gameoverstate.h"
#include "../engine/gameonstate.h"
#include "../engine/highscoresstate.h"
#include "../UI/uitextbox.h"
#include "../game/highscores.h"
#include "../common/musicmanager.h"
#include "../common/soundmanager.h"
#include "../common/surfacemanager.h"
#include "../common/effectmanager.h"
#include "../common/events.h"
#include "../common/trap.h"
#include "SDL_ttf.h"
#include <iostream>
using namespace std;
GameOverState* GameOverState::m_instance = NULL;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
GameOverState* GameOverState::GetInstance()
{
if (m_instance == NULL)
{
m_instance = new GameOverState();
if (m_instance == NULL)
{
exit(1);
}
}
return m_instance;
}
// Initializes the state.
// Loads state specific resources, should be called only once.
void GameOverState::Init(Engine* engine)
{
if (m_initialized)
return;
m_gameOverWindow = new GameOverWindow(SurfaceManager::GetInstance()->GetSurface("GameOverWindowBackground"));
m_gameOverWindow->Align(UIControl::HALN_CENTER, UIControl::VALN_MIDDLE, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
m_initialized = true;
}
// Set the button modes:
void GameOverState::Enter(Engine* engine)
{
TRAP(m_initialized == false, "GameOverState::Enter() - State has not been initialized");
engine->GetGame()->SetPaused(true);
m_stats = engine->GetGame()->GetStats();
// Disable main window:
MainWindow *mainWindow = engine->GetMainWindow();
mainWindow->SetEnabled(false);
// Grey out the time bar:
mainWindow->GetProgressBar(MainWindow::PRG_TIMEBAR)->SetEnabled(false);
mainWindow->GetProgressBar(MainWindow::PRG_TIMEBAR)->Flash(false);
// Stop the alert sound:
SoundManager::GetInstance()->StopSound("TimeAlert");
// Play the game over sound:
SoundManager::GetInstance()->PlaySound("GameOver");
// Add the text effect:
EffectManager::GetInstance()->AddGameOverEffect();
// Enable the main controls: (WHY?)
m_gameOverWindow->SetEnabled(true);
// Check if the current game's score qualifies for the high score table:
if (engine->GetHighScores()->Qualifies(engine->GetGame()->GetScore()))
{
m_gameOverWindow->GetControl(GameOverWindow::LBL_SCORE)->SetVisible(false);
m_gameOverWindow->GetControl(GameOverWindow::LBL_CONGRATS)->SetVisible(true);
m_gameOverWindow->GetControl(GameOverWindow::TXT_NAME)->SetVisible(true);
m_gameOverWindow->GetControl(GameOverWindow::BTN_OK)->SetVisible(true);
m_gameOverWindow->GetControl(GameOverWindow::BTN_QUIT)->SetVisible(false);
m_gameOverWindow->GetControl(GameOverWindow::BTN_RESTART)->SetVisible(false);
// Clear the text box:
UITextBox *temp = (UITextBox*) m_gameOverWindow->GetControl(GameOverWindow::TXT_NAME);
temp->Clear();
// Play the high score sound:
SoundManager::GetInstance()->PlaySound("HighScore");
}
else // Score does NOT qualify
{
m_gameOverWindow->GetControl(GameOverWindow::LBL_SCORE)->SetVisible(true);
m_gameOverWindow->GetControl(GameOverWindow::LBL_CONGRATS)->SetVisible(false);
m_gameOverWindow->GetControl(GameOverWindow::TXT_NAME)->SetVisible(false);
m_gameOverWindow->GetControl(GameOverWindow::BTN_OK)->SetVisible(false);
m_gameOverWindow->GetControl(GameOverWindow::BTN_QUIT)->SetVisible(true);
m_gameOverWindow->GetControl(GameOverWindow::BTN_RESTART)->SetVisible(true);
// Update the score label:
m_gameOverWindow->GetLabel(GameOverWindow::LBL_SCORE)->SetText(
UIControl::HALN_LEFT,
"Your final score is %s",
(HighScores::AddCommas(engine->GetGame()->GetScore())).c_str());
m_gameOverWindow->GetLabel(GameOverWindow::LBL_SCORE)->Align(UIControl::HALN_CENTER, UIControl::VALN_MIDDLE,
320, 170);
}
// Render stats:
m_gameOverWindow->GetLabel(GameOverWindow::LBL_STATS_VAL)->SetText(
UIControl::HALN_RIGHT,
"%d\n%02d:%02d\n%d\n%d\n%.1f\n%d\n%d",
engine->GetGame()->GetLevel(), // Final level
(m_stats.TotalTime % 3600000) / 60000, // Minutes
(m_stats.TotalTime % 60000) / 1000, // Seconds
m_stats.MarblesCleared, // Marbles cleared
m_stats.RectCleared, // Rectangles cleared
(m_stats.RectCleared == 0) ? 0.0f : m_stats.MarblesCleared / (float) m_stats.RectCleared, // Avg. rect size
m_stats.BestMove, // Best move
m_stats.NumOfPerfect); // Number of perfect moves
m_gameOverWindow->GetLabel(GameOverWindow::LBL_STATS_VAL)->Align(UIControl::HALN_RIGHT, UIControl::VALN_BOTTOM,
436, 337);
engine->Redraw();
}
void GameOverState::Exit(Engine* engine)
{
TRAP(m_initialized == false, "GameOverState::Exit() - State has not been initialized");
m_gameOverWindow->SetEnabled(false);
}
void GameOverState::HandleEvents(Engine* engine)
{
TRAP(m_initialized == false, "GameOverState::HandleEvents() - State has not been initialized");
// This flag determines whether the screen needs to be redrawn.
bool redraw = false;
SDL_Event event;
Game *game = engine->GetGame();
UITextBox *textBox = (UITextBox *) m_gameOverWindow->GetControl(GameOverWindow::TXT_NAME);
while(SDL_PollEvent(&event))
{
switch(event.type)
{
// Check for user events:
case SDL_USEREVENT:
switch (event.user.code)
{
// OK - show high scores
case EVENT_CLOSE:
// Add the current game to the high scores table:
engine->GetHighScores()->Add(textBox->GetText(), game->GetScore());
engine->ChangeState(HighScoresState::GetInstance());
break;
case EVENT_RESTART:
// Stop the time bar from flashing:
engine->GetMainWindow()->GetProgressBar(MainWindow::PRG_TIMEBAR)->Flash(false);
// Restart the music:
MusicManager::GetInstance()->PlayNextTrack();
engine->GetGame()->Restart();
EffectManager::GetInstance()->AddLevelEffect(1);
engine->ChangeState(GameOnState::GetInstance());
break;
// Music track over:
case EVENT_TRACK_OVER:
MusicManager::GetInstance()->PlayNextTrack();
break;
// Forced redraw:
case EVENT_REDRAW:
redraw = true;
break;
}
break;
// Send mouse clicks to the game object:
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= m_gameOverWindow->MouseUp(event.button.x, event.button.y);
}
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= m_gameOverWindow->MouseDown(event.button.x, event.button.y);
}
break;
// Mouse motion for hover:
case SDL_MOUSEMOTION:
{
redraw |= m_gameOverWindow->Hover(event.motion.x, event.motion.y);
}
break;
// Handle keyboard input:
case SDL_KEYDOWN:
{
redraw |= m_gameOverWindow->KeyDown(&event.key);
switch (event.key.keysym.sym) // Get the key symbol
{
// Take a screenshot:
case SDLK_F12:
ScreenShot();
break;
// Enter or escape close the window:
case SDLK_RETURN:
case SDLK_ESCAPE:
if (engine->GetHighScores()->Qualifies(engine->GetGame()->GetScore()))
{
// Add the current game to the high scores table:
engine->GetHighScores()->Add(textBox->GetText(), game->GetScore());
engine->ChangeState(HighScoresState::GetInstance());
return;
}
else
{
MusicManager::GetInstance()->PlayNextTrack();
engine->GetGame()->Restart();
EffectManager::GetInstance()->AddLevelEffect(1);
engine->ChangeState(GameOnState::GetInstance());
break;
}
default:
break;
}
}
break;
case SDL_QUIT:
engine->Quit();
break;
}
}
if (redraw)
engine->Redraw();
}
void GameOverState::Update(Engine* engine)
{
TRAP(m_initialized == false, "GameOverState::Update() - State has not been initialized");
// Redraw if one of the window's controls requires:
bool redraw = EffectManager::GetInstance()->Update();
redraw |= m_gameOverWindow->Update();
if (redraw)
engine->Redraw();
}
void GameOverState::Draw(Engine* engine)
{
TRAP(m_initialized == false, "GameOverState::Draw() - State has not been initialized");
SDL_Surface *screen = engine->GetScreen();
engine->GetMainWindow()->Draw(screen);
engine->GetGame()->Draw(screen);
EffectManager::GetInstance()->Draw(screen);
m_gameOverWindow->Draw(screen);
}
// Cleans up any state specific resources loaded in Init().
void GameOverState::Cleanup(Engine* engine)
{
TRAP(m_initialized == false, "GameOverState::Cleanup() - State has not been initialized");
delete m_gameOverWindow;
m_initialized = false;
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _GAMEOVERSTATE_H_
#define _GAMEOVERSTATE_H_
// Intro engine state. Singleton.
#include "../engine/enginestate.h"
#include "../UI/gameoverwindow.h"
#include "../game/game.h"
#include "SDL.h"
class GameOverState: public EngineState
{
private:
Statistics m_stats; // Game statistics
GameOverWindow *m_gameOverWindow; // Game over window
public:
void Init(Engine* engine);
void Enter(Engine* engine);
void Exit(Engine* engine);
void HandleEvents(Engine* engine);
void Update(Engine* engine);
void Draw(Engine* engine);
void Cleanup(Engine* engine);
static GameOverState* GetInstance();
private:
static GameOverState* m_instance;
GameOverState(){};
GameOverState(const GameOverState&);
GameOverState& operator= (const GameOverState&);
};
#endif

View File

@@ -0,0 +1,282 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../engine/highscoresstate.h"
#include "../engine/gameonstate.h"
#include "../common/fontmanager.h"
#include "../common/surfacemanager.h"
#include "../common/soundmanager.h"
#include "../UI/mainwindow.h"
#include "../common/trap.h"
#include "../common/events.h"
HighScoresState* HighScoresState::m_instance = NULL;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
HighScoresState* HighScoresState::GetInstance()
{
if (m_instance == NULL)
{
m_instance = new HighScoresState();
if (m_instance == NULL)
{
exit(1);
}
}
return m_instance;
}
// Initializes the state.
// Loads state specific resources, should be called only once.
void HighScoresState::Init(Engine* engine)
{
if (m_initialized)
return;
m_highScoresWindow = new HighScoresWindow(SurfaceManager::GetInstance()->GetSurface("HighScoresWindowBackground"));
m_highScoresWindow->Align(UIControl::HALN_CENTER, UIControl::VALN_MIDDLE, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
m_initialized = true;
}
void HighScoresState::Enter(Engine* engine)
{
TRAP(m_initialized == false, "HighScoresState::Enter() - State has not been initialized");
MainWindow* mainWindow = engine->GetMainWindow();
m_highScoresWindow->SetEnabled(true);
// Set the buttons:
mainWindow->SetEnabled(false);
if (engine->GetGame()->GetTimeLeft() > 0) // Game on
{
m_highScoresWindow->GetControl(HighScoresWindow::BTN_CLOSE)->SetVisible(true);
m_highScoresWindow->GetControl(HighScoresWindow::BTN_QUIT)->SetVisible(false);
m_highScoresWindow->GetControl(HighScoresWindow::BTN_RESTART)->SetVisible(false);
}
else // Game over
{
m_highScoresWindow->GetControl(HighScoresWindow::BTN_CLOSE)->SetVisible(false);
m_highScoresWindow->GetControl(HighScoresWindow::BTN_QUIT)->SetVisible(true);
m_highScoresWindow->GetControl(HighScoresWindow::BTN_RESTART)->SetVisible(true);
}
// Grey out the time bar:
mainWindow->GetProgressBar(MainWindow::PRG_TIMEBAR)->SetEnabled(false);
// Pause the game:
engine->GetGame()->SetPaused(true);
// Populate the table labels:
PopulateLabels(engine);
// Mute alert sound:
SoundManager::GetInstance()->SetVolume("TimeAlert", 0.0f);
engine->Redraw();
}
void HighScoresState::Exit(Engine* engine)
{
TRAP(m_initialized == false, "HighScoresState::Exit() - State has not been initialized");
// Restore alert sound:
if (!engine->GetMute())
SoundManager::GetInstance()->SetVolume("TimeAlert", 1.0f);
m_highScoresWindow->SetEnabled(false);
}
void HighScoresState::HandleEvents(Engine* engine)
{
TRAP(m_initialized == false, "HighScoresState::HandleEvents() - State has not been initialized");
// This flag determines whether the screen needs to be redrawn.
bool redraw = false;
SDL_Event event;
Game *game = engine->GetGame();
while(SDL_PollEvent(&event))
{
switch(event.type)
{
// Check for user events:
case SDL_USEREVENT:
switch (event.user.code)
{
// Close the about window:
case EVENT_CLOSE:
engine->PopState();
break;
case EVENT_RESTART:
engine->GetGame()->Restart();
engine->ChangeState(GameOnState::GetInstance());
break;
// Forced redraw:
case EVENT_REDRAW:
redraw = true;
break;
}
break;
// Send mouse clicks to the game object:
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= m_highScoresWindow->MouseUp(event.button.x, event.button.y);
}
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= m_highScoresWindow->MouseDown(event.button.x, event.button.y);
}
break;
// Mouse motion for hover:
case SDL_MOUSEMOTION:
{
redraw |= m_highScoresWindow->Hover(event.motion.x, event.motion.y);
}
break;
// Handle keyboard input:
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym) // Get the key symbol
{
// Take a screenshot:
case SDLK_F12:
ScreenShot();
break;
// Enter or escape close the window:
case SDLK_RETURN:
case SDLK_ESCAPE:
if (game->GetTimeLeft() > 0)
{
engine->PopState();
return;
}
else // Game over
{
engine->GetGame()->Restart();
engine->ChangeState(GameOnState::GetInstance());
}
default:
break;
}
}
break;
case SDL_QUIT:
engine->Quit();
break;
}
}
if (redraw)
engine->Redraw();
}
// The computer makes another move.
void HighScoresState::Update(Engine* engine)
{
TRAP(m_initialized == false, "HighScoresState::Update() - State has not been initialized");
// Redraw if one of the window's controls requires:
if (m_highScoresWindow->Update())
engine->Redraw();
}
void HighScoresState::Draw(Engine* engine)
{
TRAP(m_initialized == false, "HighScoresState::Draw() - State has not been initialized");
engine->GetMainWindow()->Draw(engine->GetScreen());
engine->GetGame()->Draw(engine->GetScreen());
m_highScoresWindow->Draw(engine->GetScreen());
}
// Cleans up any state specific resources loaded in Init().
void HighScoresState::Cleanup(Engine* engine)
{
TRAP(m_initialized == false, "HighScoresState::Cleanup() - State has not been initialized");
delete m_highScoresWindow;
m_initialized = false;
}
// Populates the labels making up the high scores table.
void HighScoresState::PopulateLabels(Engine* engine)
{
HighScores *highScores = engine->GetHighScores();
// Name labels vector:
vector<UIControl *> namesVec =
m_highScoresWindow->GetControlVector(HighScoresWindow::VEC_NAMES);
// Scores labels vector:
vector<UIControl *> scoresVec =
m_highScoresWindow->GetControlVector(HighScoresWindow::VEC_SCORES);
UILabel *nameLabel, *scoreLabel;
for (Uint16 i = 0 ; i < highScores->GetSize() ; ++i)
{
scoreLabel = static_cast<UILabel *>(scoresVec[i]);
scoreLabel->SetText(UILabel::HALN_LEFT, highScores->GetScore(i));
scoreLabel->Align(UIControl::HALN_RIGHT, UIControl::VALN_TOP, 435, 136 + 20 * i);
nameLabel = static_cast<UILabel *>(namesVec[i]);
string name = highScores->GetName(i);
nameLabel->SetText(UILabel::HALN_LEFT, name);
// If the name is too long to fit, trim it and add ellipsis and try again.
while (nameLabel->GetX() + nameLabel->GetWidth() >= scoreLabel->GetX() - 8)
{
name = name.substr(0, name.length() - 1);
nameLabel->SetText(UILabel::HALN_LEFT, "%s...", name.c_str());
}
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HIGHSCORESSTATE_H_
#define _HIGHSCORESSTATE_H_
// About screen engine state. Singleton.
#include "../engine/enginestate.h"
#include "../UI/highscoreswindow.h"
class HighScoresState: public EngineState
{
private:
HighScoresWindow *m_highScoresWindow; // The high scores window
public:
void Init(Engine* engine);
void Enter(Engine* engine);
void Exit(Engine* engine);
void HandleEvents(Engine* engine);
void Update(Engine* engine);
void Draw(Engine* engine);
void Cleanup(Engine* engine);
static HighScoresState* GetInstance();
private:
static HighScoresState* m_instance;
HighScoresState(){};
HighScoresState(const HighScoresState&);
HighScoresState& operator= (const HighScoresState&);
void PopulateLabels(Engine* engine); // Populates the labels making up the high scores table
};
#endif

View File

@@ -0,0 +1,394 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../engine/introstate.h"
#include "../engine/gameonstate.h"
#include "../engine/aboutstate.h"
#include "../engine/highscoresstate.h"
#include "../engine/quitstate.h"
#include "../UI/mainwindow.h"
#include "../common/surfacemanager.h"
#include "../common/effectmanager.h"
#include "../common/musicmanager.h"
#include "../common/soundmanager.h"
#include "../common/trap.h"
#include "../common/events.h"
IntroState* IntroState::m_instance = NULL;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
IntroState* IntroState::GetInstance()
{
if (m_instance == NULL)
{
m_instance = new IntroState();
if (m_instance == NULL)
{
exit(1);
}
}
return m_instance;
}
// Initializes the state.
// Loads state specific resources, should be called only once.
void IntroState::Init(Engine* engine)
{
if (m_initialized)
return;
m_initialized = true;
// Restart the game:
engine->GetGame()->Restart();
}
void IntroState::Enter(Engine* engine)
{
TRAP(m_initialized == false, "IntroState::Enter() - State has not been initialized");
m_iLastMove = SDL_GetTicks();
Game *game = engine->GetGame();
MainWindow *mainWindow = engine->GetMainWindow();
mainWindow->SetEnabled(true);
mainWindow->GetButton(MainWindow::BTN_START)->SetState(EVENT_START);
mainWindow->GetButton(MainWindow::BTN_PAUSE)->Disable();
mainWindow->GetButton(MainWindow::BTN_HINT)->Disable();
mainWindow->GetButton(MainWindow::BTN_START)->Flash(UIButton::FLASH_INTERVAL);
// Set the time bar:
mainWindow->GetProgressBar(MainWindow::PRG_TIMEBAR)->SetEnabled(true);
// Set the score and level labels:
mainWindow->GetLabel(MainWindow::LBL_SCORE)->SetText(UIControl::HALN_LEFT,
"%d", engine->GetGame()->GetScore() % 1000000);
mainWindow->GetLabel(MainWindow::LBL_LEVEL)->SetText(UIControl::HALN_LEFT,
"Level %d", game->GetLevel());
mainWindow->GetLabel(MainWindow::LBL_LEVEL)->Align(UIControl::HALN_CENTER,
UIControl::VALN_TOP, 94, 44);
engine->GetGame()->SetPaused(false);
game->ClearSelection();
m_selection.Clear();
m_iMarbleIndex = 0;
if (MusicManager::GetInstance()->IsPlaying() == false)
MusicManager::GetInstance()->PlayRandomTrack();
engine->Redraw();
}
void IntroState::Exit(Engine* engine)
{
TRAP(m_initialized == false, "IntroState::Exit() - State has not been initialized");
// Restart the game:
engine->GetGame()->Restart();
}
void IntroState::HandleEvents(Engine* engine)
{
TRAP(m_initialized == false, "IntroState::HandleEvents() - State has not been initialized");
// This flag determines whether the screen needs to be redrawn.
bool redraw = false;
SDL_Event event;
MainWindow *mainWindow = engine->GetMainWindow();
while(SDL_PollEvent(&event))
{
switch(event.type)
{
// Check for user events:
case SDL_USEREVENT:
redraw |= HandleUserEvents(engine, &event);
break;
// Send mouse clicks to the game object:
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= mainWindow->MouseUp(event.button.x, event.button.y);
}
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= mainWindow->MouseDown(event.button.x, event.button.y);
}
break;
// Mouse motion for hover:
case SDL_MOUSEMOTION:
{
redraw |= mainWindow->Hover(event.motion.x, event.motion.y);
}
break;
// Handle keyboard input:
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym) // Get the key symbol
{
// Quit:
case SDLK_ESCAPE:
engine->PushState(QuitState::GetInstance());
return;
// Take a screenshot:
case SDLK_F12:
ScreenShot();
break;
// Any other key starts the game:
default:
engine->ChangeState(GameOnState::GetInstance());
break;
}
}
break;
case SDL_QUIT:
engine->PushState(QuitState::GetInstance());
break;
}
}
if (redraw)
engine->Redraw();
}
// The computer makes another move.
void IntroState::Update(Engine* engine)
{
TRAP(m_initialized == false, "IntroState::Update() - State has not been initialized");
MainWindow *mainWindow = engine->GetMainWindow();
Game *game = engine->GetGame();
// Update the game:
if (game->Update())
engine->Redraw();
if (m_selection.GetSize() == 0)
game->GetRectangle(&m_selection);
// Update time bar:
float progress = ((float) game->GetTimeLeft()) / Game::TIME_MAX;
mainWindow->GetProgressBar(MainWindow::PRG_TIMEBAR)->SetProgress(progress);
// If enough time has passed since the last move, make aother one:
if (SDL_GetTicks() - m_iLastMove >= INTRO_DELAY && game->CanMove())
{
// Translate to screen coordinates to simulate a user's click:
game->Click(m_selection[m_iMarbleIndex].x * MARBLE_IMAGE_SIZE + BOARD_X,
m_selection[m_iMarbleIndex].y * MARBLE_IMAGE_SIZE + BOARD_Y);
m_iLastMove = SDL_GetTicks();
m_iMarbleIndex++;
if (m_iMarbleIndex > 3)
{
m_iMarbleIndex = 0;
// Get a new rectangle:
game->GetRectangle(&m_selection);
}
engine->Redraw();
}
// Redraw if one of the window's controls requires:
if (mainWindow->Update())
engine->Redraw();
// Update the effects:
if (EffectManager::GetInstance()->Update())
engine->Redraw();
}
void IntroState::Draw(Engine* engine)
{
TRAP(m_initialized == false, "IntroState::Draw() - State has not been initialized");
engine->GetMainWindow()->DrawBackground(engine->GetScreen());
engine->GetGame()->Draw(engine->GetScreen());
engine->GetMainWindow()->DrawControls(engine->GetScreen());
EffectManager::GetInstance()->Draw(engine->GetScreen());
}
// Cleans up any state specific resources loaded in Init().
void IntroState::Cleanup(Engine* engine)
{
TRAP(m_initialized == false, "IntroState::Cleanup() - State has not been initialized");
m_initialized = false;
}
// Handles user events.
// Returns true if a redraw is necessary.
bool IntroState::HandleUserEvents(Engine *engine, SDL_Event *event)
{
bool redraw = false;
MainWindow *mainWindow = engine->GetMainWindow();
Game *game = engine->GetGame();
switch (event->user.code)
{
// Start the game:
case EVENT_START:
MusicManager::GetInstance()->PlayNextTrack();
engine->ChangeState(GameOnState::GetInstance());
break;
// Mute:
case EVENT_MUTE:
engine->Mute(true);
mainWindow->GetButton(MainWindow::BTN_MUTE)->SetState(EVENT_UNMUTE);
redraw = true;
break;
// Unmute:
case EVENT_UNMUTE:
engine->Mute(false);
mainWindow->GetButton(MainWindow::BTN_MUTE)->SetState(EVENT_MUTE);
redraw = true;
break;
// About:
case EVENT_ABOUT:
engine->PushState(AboutState::GetInstance());
break;
// High scores:
case EVENT_HIGH_SCORES:
engine->PushState(HighScoresState::GetInstance());
break;
// Game over:
case EVENT_GAME_OVER:
m_iLastMove = SDL_GetTicks(); // Time of last move
m_iMarbleIndex = 0; // Index of marble within selection (0..3)
m_selection.Clear();
game->Restart();
redraw = true;
break;
// Score was changed:
case EVENT_RECT_COMPLETE:
// Update score label:
mainWindow->GetLabel(MainWindow::LBL_SCORE)->SetText(UIControl::HALN_LEFT,
"%d", engine->GetGame()->GetScore() % 1000000);
// Add the score effect:
EffectManager::GetInstance()->AddScoreEffect(event);
break;
// Level up:
case EVENT_NEW_LEVEL:
// Update level label:
mainWindow->GetLabel(MainWindow::LBL_LEVEL)->SetText(UIControl::HALN_LEFT,
"Level %d", game->GetLevel());
mainWindow->GetLabel(MainWindow::LBL_LEVEL)->Align(UIControl::HALN_CENTER,
UIControl::VALN_TOP, 94, 44);
// Add the new level effect:
EffectManager::GetInstance()->AddLevelEffect(game->GetLevel());
// Play sound:
if (game->GetLevel() != 1)
SoundManager::GetInstance()->PlaySound("NewLevel");
break;
// Perfect rectangle:
case EVENT_PERFECT:
// Add the prefect rectangle effect:
EffectManager::GetInstance()->AddPerfectEffect();
break;
// Music track over:
case EVENT_TRACK_OVER:
MusicManager::GetInstance()->PlayNextTrack();
break;
// Running low on time:
case EVENT_TIME_LOW:
// Flash the time bar:
engine->GetMainWindow()->GetProgressBar(MainWindow::PRG_TIMEBAR)->Flash(true);
// Play the alert sound:
SoundManager::GetInstance()->PlaySound("TimeAlert", true);
engine->Redraw();
break;
// Time is no longer running low:
case EVENT_TIME_OK:
// Stop flashing the time bar:
engine->GetMainWindow()->GetProgressBar(MainWindow::PRG_TIMEBAR)->Flash(false);
// Stop the alert sound:
SoundManager::GetInstance()->StopSound("TimeAlert");
engine->Redraw();
break;
// Forced redraw:
case EVENT_REDRAW:
redraw = true;
break;
default:
break;
}
return redraw;
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _INTROSTATE_H_
#define _INTROSTATE_H_
// Intro engine state. Singleton.
// Simulate a game.
#include "../engine/enginestate.h"
#include "../game/selection.h"
#include "../UI/uilabel.h"
#include "SDL.h"
class IntroState: public EngineState
{
private:
Selection m_selection; // Selection for simulated game
Uint32 m_iLastMove; // Time of last move
int m_iMarbleIndex; // Index of marble within selection (0..3)
static const int INTRO_DELAY = 750; // Delay between simulated clicks
public:
void Init(Engine* engine);
void Enter(Engine* engine);
void Exit(Engine* engine);
void HandleEvents(Engine* engine);
void Update(Engine* engine);
void Draw(Engine* engine);
void Cleanup(Engine* engine);
static IntroState* GetInstance();
private:
static IntroState* m_instance;
IntroState(){};
IntroState(const IntroState&);
IntroState& operator= (const IntroState&);
// Handle user events:
bool HandleUserEvents(Engine *engine, SDL_Event *event);
};
#endif

View File

@@ -0,0 +1,255 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../engine/pausedstate.h"
#include "../engine/aboutstate.h"
#include "../engine/highscoresstate.h"
#include "../engine/quitstate.h"
#include "../common/surfacemanager.h"
#include "../common/musicmanager.h"
#include "../common/soundmanager.h"
#include "../UI/mainwindow.h"
#include "../common/trap.h"
#include "../common/events.h"
PausedState* PausedState::m_instance = NULL;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
PausedState* PausedState::GetInstance()
{
if (m_instance == NULL)
{
m_instance = new PausedState();
if (m_instance == NULL)
{
exit(1);
}
}
return m_instance;
}
// Initializes the state.
// Loads state specific resources, should be called only once.
void PausedState::Init(Engine* engine)
{
if (m_initialized)
return;
m_initialized = true;
}
void PausedState::Enter(Engine* engine)
{
TRAP(m_initialized == false, "PausedState::Enter() - State has not been initialized");
MainWindow* mainWindow = engine->GetMainWindow();
// Set the buttons:
mainWindow->SetEnabled(true);
mainWindow->GetButton(MainWindow::BTN_PAUSE)->SetState(EVENT_RESUME);
mainWindow->GetButton(MainWindow::BTN_HINT)->Disable();
mainWindow->GetButton(MainWindow::BTN_START)->Disable();
mainWindow->GetButton(MainWindow::BTN_PAUSE)->Flash(UIButton::FLASH_INTERVAL);
// Grey out the time bar:
mainWindow->GetProgressBar(MainWindow::PRG_TIMEBAR)->SetEnabled(false);
// Pause the game:
engine->GetGame()->SetPaused(true);
// Pause the music:
MusicManager::GetInstance()->Pause();
// Mute alert sound:
SoundManager::GetInstance()->SetVolume("TimeAlert", 0.0f);
// Redraw:
engine->Redraw();
}
void PausedState::Exit(Engine* engine)
{
TRAP(m_initialized == false, "PausedState::Exit() - State has not been initialized");
// Reset the pause button:
engine->GetMainWindow()->GetButton(MainWindow::BTN_PAUSE)->SetState(EVENT_PAUSE);
// Resume the music:
MusicManager::GetInstance()->Resume();
// Restore alert sound
if (!engine->GetMute())
SoundManager::GetInstance()->SetVolume("TimeAlert", 1.0f);
}
void PausedState::HandleEvents(Engine* engine)
{
TRAP(m_initialized == false, "PausedState::HandleEvents() - State has not been initialized");
// This flag determines whether the screen needs to be redrawn.
bool redraw = false;
SDL_Event event;
MainWindow *mainWindow = engine->GetMainWindow();
Game *game = engine->GetGame();
while(SDL_PollEvent(&event))
{
switch(event.type)
{
// Check for user events:
case SDL_USEREVENT:
switch (event.user.code)
{
// Resume the game:
case EVENT_RESUME:
game->SetPaused(false);
engine->PopState();
break;
// About:
case EVENT_ABOUT:
engine->PushState(AboutState::GetInstance());
break;
// High scores:
case EVENT_HIGH_SCORES:
engine->PushState(HighScoresState::GetInstance());
break;
// Mute:
case EVENT_MUTE:
engine->Mute(true);
mainWindow->GetButton(MainWindow::BTN_MUTE)->SetState(EVENT_UNMUTE);
redraw = true;
break;
// Unmute:
case EVENT_UNMUTE:
engine->Mute(false);
mainWindow->GetButton(MainWindow::BTN_MUTE)->SetState(EVENT_MUTE);
redraw = true;
break;
// Forced redraw:
case EVENT_REDRAW:
redraw = true;
break;
}
break;
// Send mouse clicks to the game object:
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= mainWindow->MouseUp(event.button.x, event.button.y);
}
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= mainWindow->MouseDown(event.button.x, event.button.y);
}
break;
// Mouse motion for hover:
case SDL_MOUSEMOTION:
{
redraw |= mainWindow->Hover(event.motion.x, event.motion.y);
}
break;
// Handle keyboard input:
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym) // Get the key symbol
{
// Quit:
case SDLK_ESCAPE:
engine->PushState(QuitState::GetInstance());
return;
// Take a screenshot:
case SDLK_F12:
ScreenShot();
break;
// P - resume the game:
case SDLK_p:
game->SetPaused(false);
engine->PopState();
break;
default:
break;
}
}
break;
case SDL_QUIT:
engine->PushState(QuitState::GetInstance());
break;
}
}
if (redraw)
engine->Redraw();
}
// The computer makes another move.
void PausedState::Update(Engine* engine)
{
TRAP(m_initialized == false, "PausedState::Update() - State has not been initialized");
// Redraw if one of the window's controls requires:
if (engine->GetMainWindow()->Update())
engine->Redraw();
}
void PausedState::Draw(Engine* engine)
{
TRAP(m_initialized == false, "PausedState::Draw() - State has not been initialized");
engine->GetMainWindow()->Draw(engine->GetScreen());
engine->GetGame()->Draw(engine->GetScreen());
}
// Cleans up any state specific resources loaded in Init().
void PausedState::Cleanup(Engine* engine)
{
TRAP(m_initialized == false, "PausedState::Cleanup() - State has not been initialized");
m_initialized = false;
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _PAUSEDSTATE_H_
#define _PAUSEDSTATE_H_
// Game paused engine state. Singleton.
#include "../engine/enginestate.h"
class PausedState: public EngineState
{
private:
public:
void Init(Engine* engine);
void Enter(Engine* engine);
void Exit(Engine* engine);
void HandleEvents(Engine* engine);
void Update(Engine* engine);
void Draw(Engine* engine);
void Cleanup(Engine* engine);
static PausedState* GetInstance();
private:
static PausedState* m_instance;
PausedState(){};
PausedState(const PausedState&);
PausedState& operator= (const PausedState&);
};
#endif

View File

@@ -0,0 +1,214 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../engine/quitstate.h"
#include "../common/fontmanager.h"
#include "../UI/mainwindow.h"
#include "../common/trap.h"
#include "../common/events.h"
#include "../common/surfacemanager.h"
#include "../common/soundmanager.h"
QuitState* QuitState::m_instance = NULL;
// Returns an m_instance of the class. If no m_instance exists, the method
// creates a new one.
QuitState* QuitState::GetInstance()
{
if (m_instance == NULL)
{
m_instance = new QuitState();
if (m_instance == NULL)
{
exit(1);
}
}
return m_instance;
}
// Initializes the state.
// Loads state specific resources, should be called only once.
void QuitState::Init(Engine* engine)
{
if (m_initialized)
return;
m_quitWindow = new QuitWindow(SurfaceManager::GetInstance()->GetSurface("QuitWindowBackground"));
m_quitWindow->Align(UIControl::HALN_CENTER, UIControl::VALN_MIDDLE, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
m_initialized = true;
}
void QuitState::Enter(Engine* engine)
{
TRAP(m_initialized == false, "QuitState::Enter() - State has not been initialized");
MainWindow* mainWindow = engine->GetMainWindow();
m_quitWindow->SetEnabled(true);
// Set the buttons:
mainWindow->SetEnabled(false);
// Grey out the time bar:
mainWindow->GetProgressBar(MainWindow::PRG_TIMEBAR)->SetEnabled(false);
// Pause the game:
engine->GetGame()->SetPaused(true);
// Mute alert sound:
SoundManager::GetInstance()->SetVolume("TimeAlert", 0.0f);
engine->Redraw();
}
void QuitState::Exit(Engine* engine)
{
TRAP(m_initialized == false, "QuitState::Exit() - State has not been initialized");
// Restore alert sound:
if (!engine->GetMute())
SoundManager::GetInstance()->SetVolume("TimeAlert", 1.0f);
m_quitWindow->SetEnabled(false);
}
void QuitState::HandleEvents(Engine* engine)
{
TRAP(m_initialized == false, "QuitState::HandleEvents() - State has not been initialized");
// This flag determines whether the screen needs to be redrawn.
bool redraw = false;
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
// Check for user events:
case SDL_USEREVENT:
switch (event.user.code)
{
// Close the about window:
case EVENT_CLOSE:
engine->PopState();
break;
// Forced redraw:
case EVENT_REDRAW:
redraw = true;
break;
}
break;
// Send mouse clicks to the game object:
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= m_quitWindow->MouseUp(event.button.x, event.button.y);
}
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT)
{
redraw |= m_quitWindow->MouseDown(event.button.x, event.button.y);
}
break;
// Mouse motion for hover:
case SDL_MOUSEMOTION:
{
redraw |= m_quitWindow->Hover(event.motion.x, event.motion.y);
}
break;
// Handle keyboard input:
case SDL_KEYDOWN:
{
switch (event.key.keysym.sym) // Get the key symbol
{
// Take a screenshot:
case SDLK_F12:
ScreenShot();
break;
// Enter or escape close the window:
case SDLK_RETURN:
case SDLK_ESCAPE:
engine->PopState();
return;
default:
break;
}
}
break;
// Quit:
case SDL_QUIT:
engine->Quit();
break;
}
}
if (redraw)
engine->Redraw();
}
// The computer makes another move.
void QuitState::Update(Engine* engine)
{
TRAP(m_initialized == false, "QuitState::Update() - State has not been initialized");
// Redraw if one of the window's controls requires:
if (m_quitWindow->Update())
engine->Redraw();
}
void QuitState::Draw(Engine* engine)
{
TRAP(m_initialized == false, "QuitState::Draw() - State has not been initialized");
engine->GetMainWindow()->Draw(engine->GetScreen());
engine->GetGame()->Draw(engine->GetScreen());
m_quitWindow->Draw(engine->GetScreen());
}
// Cleans up any state specific resources loaded in Init().
void QuitState::Cleanup(Engine* engine)
{
TRAP(m_initialized == false, "QuitState::Cleanup() - State has not been initialized");
delete m_quitWindow;
m_initialized = false;
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _QUITSTATE_H_
#define _QUITSTATE_H_
// About screen engine state. Singleton.
#include "../engine/enginestate.h"
#include "../UI/quitwindow.h"
class QuitState: public EngineState
{
private:
QuitWindow *m_quitWindow; // The quit dialog window
public:
void Init(Engine* engine);
void Enter(Engine* engine);
void Exit(Engine* engine);
void HandleEvents(Engine* engine);
void Update(Engine* engine);
void Draw(Engine* engine);
void Cleanup(Engine* engine);
static QuitState* GetInstance();
private:
static QuitState* m_instance;
QuitState(){};
QuitState(const QuitState&);
QuitState& operator= (const QuitState&);
};
#endif

View File

@@ -0,0 +1,740 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../game/board.h"
#include <SDL_image.h>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include "../game/selection.h"
#include "../common/soundmanager.h"
#include "../common/surfacemanager.h"
#include "../common/events.h"
#include "../common/trap.h"
using namespace std;
// Constructor
Board::Board()
{
// Init the PRNG:
srand((unsigned)time(NULL));
// Load the marble surfaces:
SurfaceManager* surfaceMgr = SurfaceManager::GetInstance();
m_normalSurfaces[BLUE] = surfaceMgr->GetSurface("MarbleNormalBlue");
m_normalSurfaces[GREEN] = surfaceMgr->GetSurface("MarbleNormalGreen");
m_normalSurfaces[RED] = surfaceMgr->GetSurface("MarbleNormalRed");
m_normalSurfaces[YELLOW] = surfaceMgr->GetSurface("MarbleNormalYellow");
m_selectedSurfaces[BLUE] = surfaceMgr->GetSurface("MarbleSelectedBlue");
m_selectedSurfaces[GREEN] = surfaceMgr->GetSurface("MarbleSelectedGreen");
m_selectedSurfaces[RED] = surfaceMgr->GetSurface("MarbleSelectedRed");
m_selectedSurfaces[YELLOW] = surfaceMgr->GetSurface("MarbleSelectedYellow");
m_pausedSurface = surfaceMgr->GetSurface("MarblePaused");
m_isDropping = false;
m_isAnimating = false;
m_Highlighted.x = -1;
Reset();
}
// Destructor - free resources
Board::~Board()
{
}
// Resets the board.
void Board::Reset()
{
#ifdef MARBLE_DROP
if (m_isDropping)
SDL_FreeSurface(m_droppingRectSfc);
#endif
m_isDropping = false;
m_isAnimating = false;
m_flashStart = 0;
#ifdef MARBLE_DROP
m_dropStartTime = 0;
m_dropVelocity = 0.0f;
m_droppingRectSfc = NULL;
#endif
// Mark all the marbles as visible:
memset(m_isVisible, 1, sizeof(bool) * BOARD_SIZE * BOARD_SIZE);
// Populate the board:
do
{
Populate(0, 0, BOARD_SIZE - 1, BOARD_SIZE - 1);
} while (!ContainsRectangle());
}
// Returns the color of a marble:
COLOR Board::GetMarbleColor(int x, int y)
{
// Sanity check:
if (x < 0 || y < 0 || x >= BOARD_SIZE || y >= BOARD_SIZE)
return NUM_OF_COLORS;
return m_marbles[x][y];
}
// Returns a marble's color:
COLOR Board::GetMarbleColor(Coordinate coord)
{
return GetMarbleColor(coord.x, coord.y);
}
// Flash a rectangle.
void Board::Flash(Coordinate coord1, Coordinate coord2)
{
// Sanity check:
TRAP(coord1.x < 0 || coord1.y < 0 || coord2.x >= BOARD_SIZE || coord2.y >= BOARD_SIZE ||
coord1.x >= coord2.x || coord1.y >= coord2.y, "Board::Flash() - Invalid arguments");
m_isFlashing = true;
m_flashColor = m_marbles[coord1.x][coord1.y];
m_flashCoord1 = coord1;
m_flashCoord2 = coord2;
m_flashStart = SDL_GetTicks();
// Force redraw:
PushUserEvent(EVENT_REDRAW);
}
// Clears a rectangle, and starts the dropping animation for
// the marbles that will fill in the void.
void Board::ClearRectangle(Coordinate coord1, Coordinate coord2)
{
// Sanity check:
TRAP(coord1.x < 0 || coord1.y < 0 || coord2.x >= BOARD_SIZE || coord2.y >= BOARD_SIZE ||
coord1.x >= coord2.x || coord1.y >= coord2.y, "Board::ClearRectangle() - Invalid arguments");
// Setup flashing:
Flash(coord1, coord2);
// Start animating:
m_isAnimating = true;
#ifdef MARBLE_DROP
// Save the affected rectangle (cleared + marbles above):
m_coordTL.x = coord1.x; m_coordTL.y = 0; // Top left
m_coordBR.x = coord2.x; m_coordBR.y = coord2.y; // Bottom right
// Make the rectangle and the marbles above it invisible.
ChangeVisibility(m_coordTL, m_coordBR, false);
// Drop the rectangle to fill in the void, and randomize the new void:
DropRectLogic(coord1, m_coordBR);
// Render the surface used in the dropping animation:
RenderDroppingRect(m_coordTL, m_coordBR);
// Set the dropping rectangle surface's location:
m_dropRectX = (Sint16)(BOARD_X + (coord1.x * MARBLE_IMAGE_SIZE) - (MARBLE_IMAGE_DELTA / 2));
m_dropRectY = (Sint16)(BOARD_Y - ((coord2.y - coord1.y + 1) * MARBLE_IMAGE_SIZE) - MARBLE_IMAGE_DELTA / 2);
// Calcualte where to stop dropping:
m_dropMaxY = BOARD_Y;
#else
// Repopulate while making sure the board contains a rectangle:
do {
Populate(coord1.x, coord1.y, coord2.x, coord2.y);
} while (!ContainsRectangle());
#endif // MARBLE_DROP
}
// Fills the argument vector of vectors of coordinates with the
// coordinates of up to num valid rectangles.
// The method returns the number of valid rectangles found.
// If a_opCoordVect is NULL, the rectangles are just counted.
// If num is 0 or less, the method processes all of the
// board's rectangles.
int Board::GetRectangles(vector<vector<Coordinate> > *a_opCoordVect, int num)
{
a_opCoordVect->clear();
Coordinate l_oCoord;
int l_iCount = 0;
for (int i = 0 ; i < BOARD_SIZE - 1 ; ++i)
for (int j = 0 ; j < BOARD_SIZE - 1 ; ++j)
{
COLOR l_eColor = m_marbles[i][j];
// Keep moving to the right, until a marble of the same color is found.
int X = -1;
for (int k = j + 1 ; k < BOARD_SIZE ; ++k)
if (m_marbles[i][k] == l_eColor)
{
X = k;
break;
}
// If no match found, continue with next marble.
if (X == -1)
continue;
// Keep moving down, until a marble of the same color is found.
int Y = -1;
for (int k = i + 1 ; k < BOARD_SIZE ; ++k)
if (m_marbles[k][j] == l_eColor)
{
Y = k;
break;
}
// If no match found, continue with next marble.
if (Y == -1)
continue;
// Check the fourth marble:
if (m_marbles[Y][X] == l_eColor)
{
if (a_opCoordVect != NULL)
{
vector<Coordinate> rect;
l_oCoord.x = i ; l_oCoord.y = j;
rect.push_back(l_oCoord);
l_oCoord.x = Y ; l_oCoord.y = j;
rect.push_back(l_oCoord);
l_oCoord.x = i ; l_oCoord.y = X;
rect.push_back(l_oCoord);
l_oCoord.x = Y ; l_oCoord.y = X;
rect.push_back(l_oCoord);
a_opCoordVect->push_back(rect);
}
l_iCount++;
if (num > 0 && (int) l_iCount == num)
return l_iCount;
}
}
return l_iCount;
}
// Gets a valid rectangle.
// Returns false if no rectangle found.
bool Board::GetRectangle(Selection* selection)
{
if (selection != NULL)
selection->Clear();
for (int i = 0 ; i < BOARD_SIZE - 1 ; ++i)
for (int j = 0 ; j < BOARD_SIZE - 1 ; ++j)
{
COLOR l_eColor = m_marbles[i][j];
// Keep moving to the right, until a marble of the same color is found.
int X = -1;
for (int k = j + 1 ; k < BOARD_SIZE ; ++k)
if (m_marbles[i][k] == l_eColor)
{
X = k;
break;
}
// If no match found, continue with next marble.
if (X == -1)
continue;
// Keep moving down, until a marble of the same color is found.
int Y = -1;
for (int k = i + 1 ; k < BOARD_SIZE ; ++k)
if (m_marbles[k][j] == l_eColor)
{
Y = k;
break;
}
// If no match found, continue with next marble.
if (Y == -1)
continue;
// Check the fourth marble:
if (m_marbles[Y][X] == l_eColor)
{
// Populate the selection:
if (selection != NULL)
{
selection->Add(i, j, this);
selection->Add(Y, j, this);
selection->Add(i, X, this);
selection->Add(Y, X, this);
}
return true;
}
}
// If we are here, no match was found.
return false;
}
// Does the board contain a rectangle?
bool Board::ContainsRectangle()
{
return GetRectangle(NULL);
}
// Update the board.
// If the board is flashing, push a redraw event.
bool Board::Update()
{
bool redraw = false;
Uint32 flashElapsed = SDL_GetTicks() - m_flashStart; // Time elapsed since last flash
#ifdef MARBLE_DROP
// Handle dropping rectangle animation:
if (m_isDropping)
{
// Update the velocity, as a function of m_gravity and time:
m_dropVelocity += ((SDL_GetTicks() - m_dropStartTime) / 1000.0f) * RECT_DROP_GRAVITY;
//m_dropVelocity += ((SDL_GetTicks() - m_dropStartTime) / 1000.0f) * 0.75f;
// Update the location:
Sint16 temp = m_dropRectY;
m_dropRectY += (Sint16) m_dropVelocity;
// Check if the rectangle has fallen into place:
if (m_dropRectY >= m_dropMaxY)
{
m_dropRectY = m_dropMaxY;
m_isDropping = false;
m_isAnimating = false;
// Make the marbles visible again:
ChangeVisibility(m_coordTL, m_coordBR, true);
// Free the dropping surfaces:
SDL_FreeSurface(m_droppingRectSfc);
SDL_FreeSurface(m_droppingRectSfcPaused);
// Play the sound:
SoundManager::GetInstance()->PlaySound("RectangleDrop");
}
// Redraw only if the rectangle's location has actually changed:
return (temp != m_dropRectY);
}
#endif // MARBLE DROP
// Handle flashing rectangle:
if (m_isAnimating && flashElapsed <= FLASH_DURATION)
{
// Determine the flashing status:
if (flashElapsed < FLASH_DURATION && ((flashElapsed / (FLASH_DURATION / FLASH_COUNT)) % 2) == 0) // Flashing
{
if (!m_isFlashing) // ... but was not flashing before
redraw = true;
m_isFlashing = true;
}
else // Not flashing
{
if (m_isFlashing) // ... but was flashing before
redraw = true;
m_isFlashing = false;
}
}
#ifdef MARBLE_DROP
// If flash is over, start dropping:
else if (m_isAnimating && !m_isDropping && flashElapsed > FLASH_DURATION)
{
// Start dropping:
m_isDropping = true;
m_dropVelocity = 0.0f;
m_dropStartTime = SDL_GetTicks();
}
#else
// Turn off animation flag if flash time has expired:
else if (m_isAnimating && flashElapsed > FLASH_DURATION)
m_isAnimating = false;
#endif
return redraw;
}
// Converts a rectangle's board coordinates to its location on screen, in pixels.
void Board::CoordToPixels(Coordinate *coord1, Coordinate *coord2,
Uint16 *x1, Uint16 *y1, Uint16 *x2, Uint16 *y2)
{
if (coord1 == NULL || coord2 == NULL || x1 == NULL || x2 == NULL || y1 == NULL || y2 == NULL)
return;
// Upper left corner:
*x1 = (Sint16)(BOARD_X + coord1->x * MARBLE_IMAGE_SIZE);
*y1 = (Sint16)(BOARD_Y + coord1->y * MARBLE_IMAGE_SIZE);
// Lower right corner:
*x2 = (Sint16)(BOARD_X + (coord2->x + 1) * MARBLE_IMAGE_SIZE);
*y2 = (Sint16)(BOARD_Y + (coord2->y + 1) * MARBLE_IMAGE_SIZE);
}
// Converts a rectangle's screen location, in pixels, to its board coordinates.
void Board::PixelsToCoord(Coordinate *coord1, Coordinate *coord2,
Uint16 *x1, Uint16 *y1, Uint16 *x2, Uint16 *y2)
{
if (coord1 == NULL || coord2 == NULL || x1 == NULL || x2 == NULL || y1 == NULL || y2 == NULL)
return;
// Upper left corner:
coord1->x = (*x1 - BOARD_X) / MARBLE_IMAGE_SIZE;
coord1->y = (*y1 - BOARD_Y) / MARBLE_IMAGE_SIZE;
// Lower right corner:
coord2->x = (*x2 - BOARD_X) / MARBLE_IMAGE_SIZE;
coord2->y = (*y2 - BOARD_Y) / MARBLE_IMAGE_SIZE;
}
// Converts a rectangle's board coordinates to its location on screen, in pixels.
// The result is stored in an SDL_Rect structure.
void Board::CoordToSDLRect(Coordinate *coord1, Coordinate *coord2, SDL_Rect *rect)
{
if (coord1 == NULL || coord2 == NULL)
return;
Uint16 x1, y1, x2, y2;
CoordToPixels(coord1, coord2, &x1, &y1, &x2, &y2);
rect->x = x1;
rect->y = y1;
rect->w = x2 - x1;
rect->h = y2 - y1;
}
// Draws the board to screen:
void Board::Draw(SDL_Surface *screen, Selection *selection, bool paused)
{
SDL_Rect rect = {0, 0, 0, 0};
Uint32 flashElapsed = SDL_GetTicks() - m_flashStart; // Time elapsed since last flash
#ifdef MARBLE_DROP
// Draw dropping rectangle:
if (m_isAnimating)//m_isDropping)
{
rect.x = m_dropRectX;
rect.y = m_dropRectY;
if (paused)
SDL_BlitSurface(m_droppingRectSfcPaused, NULL, screen, &rect);
else
SDL_BlitSurface(m_droppingRectSfc, NULL, screen, &rect);
}
#endif // MARBLE_DROP
// Draw the marbles:
for (int i = 0 ; i < BOARD_SIZE ; ++i)
for (int j = 0 ; j < BOARD_SIZE ; ++j)
{
rect.x = (Sint16) (BOARD_X + i * MARBLE_IMAGE_SIZE - (m_normalSurfaces[0]->w - MARBLE_IMAGE_SIZE) / 2);
rect.y = (Sint16) (BOARD_Y + j * MARBLE_IMAGE_SIZE - (m_normalSurfaces[0]->h - MARBLE_IMAGE_SIZE) / 2);
if (!paused)
{
// Flash:
if (flashElapsed < FLASH_DURATION
&& m_flashCoord1.x <= i && m_flashCoord2.x >= i
&& m_flashCoord1.y <= j && m_flashCoord2.y >= j)
{
if (!m_isFlashing)
SDL_BlitSurface(m_normalSurfaces[m_flashColor], NULL, screen, &rect);
else
SDL_BlitSurface(m_selectedSurfaces[m_flashColor], NULL, screen, &rect);
continue;
}
// Don't render invisible marbles (unless flashing):
if (!m_isVisible[i][j])
continue;
// Selected:
else if (selection->IsSelected(i, j)) // Marble is selected
SDL_BlitSurface(m_selectedSurfaces[m_marbles[i][j]], NULL, screen, &rect);
/*
else if ( m_Highlighted == Coordinate(i, j) ) // Marble is highlighted
SDL_BlitSurface(m_selectedSurfaces[m_marbles[i][j]], NULL, screen, &rect);
*/
// Normal:
else
SDL_BlitSurface(m_normalSurfaces[m_marbles[i][j]], NULL, screen, &rect);
}
else // Game is paused, use greyed out marbles
if (m_isVisible[i][j])
SDL_BlitSurface(m_pausedSurface, NULL, screen, &rect);
}
if( m_Highlighted.x >=0 && m_Highlighted.y >=0 )
{
SDL_Rect r, r2;
CoordToSDLRect(&m_Highlighted, &m_Highlighted, &r);
r.x += MARBLE_IMAGE_SIZE / 2;
r.y += MARBLE_IMAGE_SIZE / 2;
enum {LINE_WIDTH = 4};
r2.x = r.x - LINE_WIDTH/2;
r2.y = r.y - MARBLE_IMAGE_SIZE * 2;
r2.w = LINE_WIDTH;
r2.h = MARBLE_IMAGE_SIZE * 4;
SDL_FillRect(screen, &r2, SDL_MapRGB(screen->format, 255, 255, 128));
r2.x = r.x - MARBLE_IMAGE_SIZE * 2;
r2.y = r.y - LINE_WIDTH/2;
r2.w = MARBLE_IMAGE_SIZE * 4;
r2.h = LINE_WIDTH;
SDL_FillRect(screen, &r2, SDL_MapRGB(screen->format, 255, 255, 128));
}
}
// Populates a section of the board with random marbles:
void Board::Populate(int x0, int y0, int x1, int y1)
{
// Sanity check:
TRAP(x0 < 0 || y0 < 0 || x1 >= BOARD_SIZE || y1 >= BOARD_SIZE
|| x0 >= x1 || y0 >= y1, "Board::Populate() - Invalid arguments");
for (int i = x0 ; i <= x1 ; ++i)
for (int j = y0 ; j <= y1 ; ++j)
m_marbles[i][j] = static_cast<COLOR>(rand() % (NUM_OF_MARBLE_COLORS));
}
void Board::Highlight(Coordinate c)
{
m_Highlighted = c;
};
////////////// Marble drop methods - disabled by default ////////////////
#ifdef MARBLE_DROP
// Changes a rectangle's visibility.
void Board::ChangeVisibility(Coordinate coord1, Coordinate coord2, bool visible)
{
TRAP(coord1.x < 0 || coord1.y < 0 || coord2.x >= BOARD_SIZE || coord2.y >= BOARD_SIZE ||
coord1.x >= coord2.x || coord1.y >= coord2.y, "Board::ChangeVisibility() - Invalid arguments");
for (int i = coord1.x ; i <= coord2.x ; ++i)
for (int j = coord1.y ; j <= coord2.y ; ++j)
m_isVisible[i][j] = visible;
}
// Eliminates the given rectangle, drops the marbles above it
// to fill in the void, and fills what's left with new marbles.
// This method is LOGICAL, and not visual.
//
// To illustrate, lets define two rectangles.
// Rectangle A is the rectangle being cleared, whose coordinates
// are the method's arguments.
// Rectangle B is a rectangle of exisitng marbles, located between
// the top of A and the board's top. It has the same horizontal
// size a A.
// Rectangle C is composed of the "new" marbles, filling up the
// void left. It has the same dimensions as A.
//
// Step 1: Copy B into A, starting from the bottom.
// Step 2: Randomize C.
//
// Before: Step 1: Step 2:
//
// ...BBBB... ...BBBB... ...CCCC...
// ...AAAA... ...AAAA... ...CCCC...
// ...AAAA... ...BBBB... ...BBBB...
// .......... .......... ..........
//
void Board::DropRectLogic(Coordinate coord1, Coordinate coord2)
{
TRAP(coord1.x < 0 || coord1.y < 0 || coord2.x >= BOARD_SIZE || coord2.y >= BOARD_SIZE ||
coord1.x >= coord2.x || coord1.y >= coord2.y, "Board::DropRectLogic() - Invalid arguments");
/*
//////
#ifdef _DEBUG
ScreenShot("DropRectLogic.bmp");
cout << "(" << coord1.x << "," << coord1.y << ") - (" << coord2.x << "," << coord2.y << ")" << endl;
PrintBoard(&coord1, &coord2);
cout << endl;
#endif
////////
*/
// Get the rectangles' heights:
int hA = coord2.y - coord1.y + 1;
int hB = coord1.y;
// Step 1:
for (int j = coord2.y ; j > coord2.y - hB ; --j)
for (int i = coord1.x ; i <= coord2.x ; ++i)
m_marbles[i][j] = m_marbles[i][j - hA];
// Step 2:
// Repopulate while making sure the board contains a rectangle:
do {
Populate(coord1.x, 0, coord2.x, hA - 1);
} while (!ContainsRectangle());
/*
//////
#ifdef _DEBUG
PrintBoard(&coord1, &coord2);
#endif
//////
*/
}
// Renders a rectangle of marbles to an SDL surface.
// The method renders two versions of the surface - paused and unpaused.
void Board::RenderDroppingRect(Coordinate coord1, Coordinate coord2)
{
TRAP(coord1.x < 0 || coord1.y < 0 || coord2.x >= BOARD_SIZE || coord2.y >= BOARD_SIZE ||
coord1.x >= coord2.x || coord1.y >= coord2.y, "Board::RenderDroppingRect() - Invalid arguments");
// Calculate surface dimensions:
Uint16 width = (Uint16) ((coord2.x - coord1.x + 1) * MARBLE_IMAGE_SIZE + MARBLE_IMAGE_DELTA);
Uint16 height = (Uint16) ((coord2.y - coord1.y + 1) * MARBLE_IMAGE_SIZE + MARBLE_IMAGE_DELTA);
// Create the new surface:
m_droppingRectSfc = SDL_CreateRGBSurface(
m_normalSurfaces[BLUE]->flags,
width,
height,
m_normalSurfaces[BLUE]->format->BitsPerPixel,
m_normalSurfaces[BLUE]->format->Rmask,
m_normalSurfaces[BLUE]->format->Gmask,
m_normalSurfaces[BLUE]->format->Bmask,
m_normalSurfaces[BLUE]->format->Amask);
// Create the puased version of the surface
m_droppingRectSfcPaused = SDL_CreateRGBSurface(
m_normalSurfaces[BLUE]->flags,
width,
height,
m_normalSurfaces[BLUE]->format->BitsPerPixel,
m_normalSurfaces[BLUE]->format->Rmask,
m_normalSurfaces[BLUE]->format->Gmask,
m_normalSurfaces[BLUE]->format->Bmask,
m_normalSurfaces[BLUE]->format->Amask);
TRAP(m_droppingRectSfc == NULL || m_droppingRectSfcPaused == NULL,
"Board::RenderDroppingRect() - Could not create surface");
// Blit the marbles on to the surface:
SDL_Rect rect = {0, 0, 0, 0};
SDL_Rect rect1 = {0, 0, 0, 0};
for (int i = coord1.x ; i <= coord2.x ; ++i)
for (int j = coord1.y ; j <= coord2.y ; ++j)
{
rect.x = rect1.x = (Sint16)((i - coord1.x) * MARBLE_IMAGE_SIZE);
rect.y = rect1.y = (Sint16)((j - coord1.y) * MARBLE_IMAGE_SIZE);
// Normal surface:
SurfaceManager::Blit(
m_normalSurfaces[m_marbles[i][j]], // Source - a single marble
m_droppingRectSfc, // Destination - the dropping rect surface
1.0f, // Alpha
&rect); // Location, relative to the destination
// Paused surface:
SurfaceManager::Blit(
m_pausedSurface, // Source - paused marble surface
m_droppingRectSfcPaused, // Destination - the dropping rect surface
1.0f, // Alpha
&rect1); // Location, relative to the destination
}
}
#endif // MARBLE_DROP
#ifdef _DEBUG
// Prints the board to the console:
void Board::PrintBoard(Coordinate *coord1, Coordinate *coord2)
{
bool inRect;
for (int i = 0 ; i < BOARD_SIZE ; i++)
{
for (int j = 0 ; j < BOARD_SIZE ; j++)
{
if (coord1 && coord2 && j >= coord1->x && j <= coord2->x && i >= coord1->y && i <= coord2->y)
inRect = true;
else
inRect = false;
switch (m_marbles[j][i])
{
case BLUE:
cout << (inRect ? "B" : "b");
break;
case YELLOW:
cout << (inRect ? "Y" : "y");
break;
case RED:
cout << (inRect ? "R" : "r");
break;
case GREEN:
cout << (inRect ? "G" : "g");
break;
default:
cout << "!";
}
}
cout << endl;
}
}
#endif // _DEBUG

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// The game board.
#ifndef _BOARD_H_
#define _BOARD_H_
#include <SDL.h>
#include <vector>
#include "../common/common.h"
class Selection;
using namespace std;
// Marble coordinate:
struct Coordinate
{
int x;
int y;
Coordinate(int _x = -1, int _y = -1): x(_x), y(_y) {};
bool operator== ( const Coordinate & c )
{
return x == c.x && y == c.y;
}
};
// Marble colors:
enum COLOR {BLUE, GREEN, RED, YELLOW, NUM_OF_COLORS};
static const int NUM_OF_MARBLE_COLORS = NUM_OF_COLORS;
// Size of a marble image (in pixels):
static const Uint16 MARBLE_IMAGE_SIZE = 44;
// This is the difference between the actual size of the marble image, and its
// "logical" size, which is used to position it on screen.
static const Uint16 MARBLE_IMAGE_DELTA = 64 - 44;
// Gravity affecting dropping marble rectangles, in pixels per second per second:
static const float RECT_DROP_GRAVITY = 0.75f;
// Board dimensions and location:
static const int BOARD_SIZE = 10; // Game board size, in marbles. The board is square.
static const Uint16 BORDER_SIZE = 8; // Size of window border, in pixels
static Uint16 BOARD_X = SCREEN_WIDTH - BOARD_SIZE * MARBLE_IMAGE_SIZE - BORDER_SIZE; // = 192
static Uint16 BOARD_Y = BORDER_SIZE; // = 8
// Rectangle flash:
static const int FLASH_DURATION = 300; // Duration of rectangle flash sequnece, in ms
static const int FLASH_COUNT = 3; // Number of flashes in a flash sequence
class Board
{
private:
COLOR m_marbles[BOARD_SIZE][BOARD_SIZE]; // The board's contents
bool m_isVisible[BOARD_SIZE][BOARD_SIZE]; // Marbles' visibility
SDL_Surface *m_normalSurfaces[NUM_OF_COLORS]; // Normal marbles' surfaces
SDL_Surface *m_selectedSurfaces[NUM_OF_COLORS]; // Selected marbles' surfaces
SDL_Surface *m_pausedSurface; // Surface for greyed out marble
// Marble flash:
bool m_isFlashing; // Are we currently flashing
COLOR m_flashColor; // Color of flashing rectangle
Uint32 m_flashStart; // Time flashing started
Coordinate m_flashCoord1, m_flashCoord2; // Flashing rectangle coordinates
Coordinate m_Highlighted;
// Drop animation:
bool m_isAnimating; // Are we curretly animating (flashing or dropping)
bool m_isDropping; // Is a rectangle currently dropping?
#ifdef MARBLE_DROP
SDL_Surface *m_droppingRectSfc; // Dropping rectangle surface
SDL_Surface *m_droppingRectSfcPaused; // Dropping rectangle surface (for paused game)
Sint16 m_dropRectX, m_dropRectY; // Dropping rectangle's location
float m_dropVelocity; // Dropping rectangle's velocity
Sint16 m_dropMaxY; // Where to stop the dropping rectangle
Uint32 m_dropStartTime; // Drop Starting time
Coordinate m_coordTL, m_coordBR; // Coordinates of affected rectangle
#endif
public:
Board();
~Board();
void Reset(); // Resets the board
void Populate(int x0, int y0, int x1, int y1); // Populates a section of the board with random marbles
COLOR GetMarbleColor(int x, int y); // Returns the color of a marble
COLOR GetMarbleColor(Coordinate coord);
int GetRectangles(vector<vector<Coordinate> > *a_opCoordVect, int num = -1); // Returns a vector of N valid rects
bool GetRectangle(Selection* selection); // Returns a valid rectangle
bool ContainsRectangle(); // Does the board contain a valid rectangle?
bool IsAnimating(){return (m_isAnimating);} // Is the board currently animating?
bool Update(); // Update (for flashing)
// Converts between marble coordinates and its screen location, in pixels:
static void CoordToPixels(Coordinate *coord1, Coordinate *coord2,
Uint16 *x1, Uint16 *y1, Uint16 *x2, Uint16 *y2);
static void PixelsToCoord(Coordinate *coord1, Coordinate *coord2,
Uint16 *x1, Uint16 *y1, Uint16 *x2, Uint16 *y2);
static void CoordToSDLRect(Coordinate *coord1, Coordinate *coord2, SDL_Rect *rect);
void Draw(SDL_Surface *screen, Selection *selection, bool paused = false); // Draws the board
// Rectangle clearing:
void ClearRectangle(Coordinate coord1, Coordinate coord2); // Starts the rectangle clear sequence
void Highlight(Coordinate c = Coordinate(-1, -1));
private:
// Helper methods for rectangle clearing and dropping animation:
void Flash(Coordinate coord1, Coordinate coord2); // Flashes a rectangle
#ifdef MARBLE_DROP
void DropRectLogic(Coordinate coord1, Coordinate coord2); // Eliminates the given rect, and drops a new one
void ChangeVisibility(Coordinate coord1, Coordinate coord2, bool visible); // Changes a rect's visibility
void RenderDroppingRect(Coordinate coord1, Coordinate coord2); // Renders the dropping rect to a surface
#endif
#ifdef _DEBUG
// Prints the board to the console:
void PrintBoard(Coordinate *coord1, Coordinate *coord2);
#endif
};
#endif

View File

@@ -0,0 +1,344 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../game/game.h"
#include "../common/events.h"
#include "../game/highscores.h"
#include "../common/surfacemanager.h"
#include "../common/soundmanager.h"
#include <iostream>
#include <cstdio>
using namespace std;
// Constructor - initializes the class' members
Game::Game()
{
Restart();
}
// Destructor - free resources
Game::~Game()
{
}
// Get the playing time left (in ms):
Sint32 Game::GetTimeLeft()
{
return m_timeLeft;
}
// Clears the current selection
void Game::ClearSelection()
{
m_selection.Clear(false);
}
// Interprets a mouse click:
bool Game::Click(int x, int y)
{
if (m_paused)
return false;
m_board.Highlight(); // Clear highlight
if (x < BOARD_X || x > BOARD_X + MARBLE_IMAGE_SIZE * BOARD_SIZE ||
y < BOARD_Y || y > BOARD_X + MARBLE_IMAGE_SIZE * BOARD_SIZE)
return false;
// Convert the coordinates from pixels to marbles:
int X = (x - BOARD_X) / MARBLE_IMAGE_SIZE;
int Y = (y - BOARD_Y) / MARBLE_IMAGE_SIZE;
m_selection.Add(X, Y, &m_board);
// If a rectangle has been completed, add to the score and repopulate
// the area:
if (m_selection.IsRect())
RectangleComplete();
return true;
}
// Interprets a right mouse button click.
// Right clicking anywhere on the game board clears
// the current selection.
bool Game::RightClick(int x, int y)
{
if (m_paused)
return false;
m_board.Highlight(); // Clear highlight
if (x < BOARD_X || x > BOARD_X + MARBLE_IMAGE_SIZE * BOARD_SIZE ||
y < BOARD_Y || y > BOARD_X + MARBLE_IMAGE_SIZE * BOARD_SIZE)
return false;
if (m_selection.GetSize() > 0)
m_selection.Clear(true);
return true;
}
// Interprets a mouse over:
bool Game::Hover(int x, int y)
{
if (m_paused)
return false;
if (x < BOARD_X || x > BOARD_X + MARBLE_IMAGE_SIZE * BOARD_SIZE ||
y < BOARD_Y || y > BOARD_X + MARBLE_IMAGE_SIZE * BOARD_SIZE)
return false;
// Convert the coordinates from pixels to marbles:
int X = (x - BOARD_X) / MARBLE_IMAGE_SIZE;
int Y = (y - BOARD_Y) / MARBLE_IMAGE_SIZE;
m_board.Highlight(Coordinate(X,Y));
return true;
}
// Provide the user with a hint.
// This changes the selection: only one marble is now selected, and it is
// part of a rectangle.
// The user pays a time penalty for getting a hint.
void Game::Hint()
{
if (m_paused)
return;
if (m_timeLeft > HINT_PENALTY)
{
m_timeLeft -= HINT_PENALTY;
// Get a valid rectangle:
vector<vector<Coordinate> > l_oValidRects;
m_board.GetRectangles(&l_oValidRects);
// Get a random coordinate:
Coordinate l_oCoord = l_oValidRects[rand() % l_oValidRects.size()][rand() % 4];
// Replace the current selection with a random marble from the rectangle:
m_selection.Clear();
m_selection.Add(l_oCoord, &m_board);
// Check if time is running low:
if (m_timeLeft <= HINT_PENALTY)
PushUserEvent(EVENT_TIME_LOW);
}
}
// Populates the argument selection with a valid rectangle.
void Game::GetRectangle(Selection *a_opSelection)
{
vector<vector<Coordinate> > l_oValidRects;
m_board.GetRectangles(&l_oValidRects);
size_t i = rand() % l_oValidRects.size();
a_opSelection->Clear();
a_opSelection->Add(l_oValidRects[i][0], &m_board);
a_opSelection->Add(l_oValidRects[i][1], &m_board);
a_opSelection->Add(l_oValidRects[i][2], &m_board);
a_opSelection->Add(l_oValidRects[i][3], &m_board);
}
// Pauses or resumes the game:
void Game::SetPaused(bool paused)
{
// Pause:
if (paused == true)
{
m_paused = true;
}
// Resume:
else
{
m_paused = false;
m_lastTick = SDL_GetTicks();
}
}
// Restart the game:
void Game::Restart()
{
// Reset the board:
m_board.Reset();
// Reset score and time:
memset(&m_stats, 0, sizeof(m_stats));
m_selection.Clear();
m_paused = false;
m_score = 0;
m_level = 1;
m_timeLeft = TIME_BASE;
m_lastTick = SDL_GetTicks();
// Score and level were changed:
PushUserEvent(EVENT_RECT_COMPLETE);
PushUserEvent(EVENT_NEW_LEVEL);
// Time is not running low:
PushUserEvent(EVENT_TIME_OK);
}
// Returns the current score.
Uint32 Game::GetScore()
{
return m_score;
}
// Returns game statistics.
Statistics Game::GetStats()
{
return m_stats;
}
// Returns the current level.
Uint32 Game::GetLevel()
{
return m_level;
}
// Can the user make a move?
bool Game::CanMove()
{
return (!m_board.IsAnimating());
}
// Update the game.
bool Game::Update()
{
Sint32 prevTime = m_timeLeft;
if (!m_paused)
{
// Update the time:
m_stats.TotalTime += (SDL_GetTicks() - m_lastTick);
// DIFFICULTY //
// This controls the rate the timer counts down as a function of the current level:
m_timeLeft -= (Sint32) ((SDL_GetTicks() - m_lastTick) * (m_level / 5.0f + 0.2f));
//m_timeLeft -= (Sint32) ((SDL_GetTicks() - m_lastTick) * (m_level / 1.0f + 1.5f));
////
m_lastTick = SDL_GetTicks();
}
// If time is up, push the game over event into the queue:
if (m_timeLeft <= 0)
PushUserEvent(EVENT_GAME_OVER);
// If the time bar has been filled, advance to the next level:
else if (m_timeLeft >= TIME_MAX)
{
m_level++;
m_timeLeft = TIME_BASE;
// Push the level over event:
PushUserEvent(EVENT_NEW_LEVEL);
}
// Check if time is running low:
if (m_timeLeft <= HINT_PENALTY && prevTime > HINT_PENALTY)
PushUserEvent(EVENT_TIME_LOW);
return m_board.Update();
}
// Draws the game elements.
void Game::Draw(SDL_Surface *screen)
{
// Render the game board:
m_board.Draw(screen, &m_selection, m_paused);
}
// Handle rectangle completion:
void Game::RectangleComplete()
{
// Update stats:
m_stats.RectCleared++;
// Get the rectangle:
m_selection.GetRectangle(&m_A, &m_B);
// Get its screen location:
m_board.CoordToSDLRect(&m_A, &m_B, &m_rectLocation);
// Clear the rectangle:
m_board.ClearRectangle(m_A, m_B);
// Calculate the rectangle's size:
Uint32 rectSize = ((m_B.x - m_A.x + 1) * (m_B.y - m_A.y + 1));
// Check if the extra time earned takes us out of low time mode:
if (m_timeLeft <= HINT_PENALTY &&
(m_timeLeft + TIME_BONUS * rectSize) > HINT_PENALTY)
PushUserEvent(EVENT_TIME_OK);
// Update time:
m_timeLeft += TIME_BONUS * rectSize;
// Update score:
m_movePoints = (Uint32) (rectSize * (m_level / 2.0));
m_score += m_movePoints;
// Update statistics:
m_stats.MarblesCleared += rectSize;
m_stats.BestMove = (m_movePoints > m_stats.BestMove) ? m_movePoints : m_stats.BestMove;
m_stats.NumOfPerfect += (rectSize == BOARD_SIZE * BOARD_SIZE) ? 1 : 0;
// Clear the selection:
m_selection.Clear();
// Push the score event, in case anyone is interested:
PushUserEvent(EVENT_RECT_COMPLETE,
(void *) &m_movePoints, // Move's points
(void *) &m_rectLocation); // Rectangle's screen coordinates
// If a perfect rectangle was cleared, push an event:
if (rectSize == BOARD_SIZE * BOARD_SIZE)
{
PushUserEvent(EVENT_PERFECT);
SoundManager::GetInstance()->PlaySound("PerfectRectangle");
}
else
SoundManager::GetInstance()->PlaySound("RectangleComplete");
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _GAME_H_
#define _GAME_H_
#include "SDL.h"
#include "../common/common.h"
#include "../game/board.h"
#include "../game/selection.h"
// Game statistics:
typedef struct
{
Uint32 RectCleared; // Total rectangles cleared
Uint32 MarblesCleared; // Total marbles cleared
Uint32 TotalTime; // Total playing time
Uint32 BestMove; // Best move (in points)
Uint32 NumOfPerfect; // The number of perfect moves
Uint32 OverflowBonus; // Total points earned due to time overflow
} Statistics;
class Game
{
private:
Uint32 m_score; // Score
Statistics m_stats; // Game statistics
Uint32 m_level; // Current game level
Sint32 m_timeLeft; // Time left
Uint32 m_lastTick; // The last timer tick recorded
Board m_board; // Game board
Selection m_selection; // Selected marbles
bool m_paused; // Is the game paused?
Coordinate m_A, m_B; // Corners of last completed rectangle (A - top-left, B - bottom-right)
Uint32 m_movePoints; // Points earned is the latest move
SDL_Rect m_rectLocation; // Screen location (in pixels) of the last completed rectangle
public:
Game();
~Game();
bool CanMove(); // Can the user make a move?
Sint32 GetTimeLeft(); // Get the time left to play
bool Click(int x, int y); // Interprets a left mouse button click
bool RightClick(int x, int y); // Interprets a right mouse button click
bool Hover(int x, int y); // Interprets a mouse-over
void SetPaused(bool paused); // Sets the game's pause state
void Restart(); // Restarts the game
void Hint(); // Give the user a hint
void ClearSelection(); // Clears the current selection
void GetRectangle(Selection *selection); // Returns a valid rectangle
Uint32 GetScore(); // Returns the score
Statistics GetStats(); // Returns the game statistics
Uint32 GetLevel(); // Returns the level
bool Update(); // Updates the game
void Draw(SDL_Surface *screen); // Draws the game elements
// Timing (all units are in ms):
static const Sint32 TIME_BASE = 45000; // Base time for a new level
static const Sint32 TIME_BONUS = 350; // Time bonus per marble cleared
static const Sint32 TIME_MAX = 2 * TIME_BASE; // Maximum allowed time
static const Sint32 HINT_PENALTY = 8000; // Time penalty for requesting a hint
private:
void RectangleComplete(); // Handles rectangle completion
};
#endif

View File

@@ -0,0 +1,211 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../game/highscores.h"
#include "../common/trap.h"
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstdlib>
// Constructor.
HighScores::HighScores()
{
m_fileName = DEFAULT_FILENAME;
Read();
}
HighScores::~HighScores(){};
// Get the table's size (number of entries)
Uint32 HighScores::GetSize()
{
return (Uint32) m_table.size();
}
// Gets the name of the i-th table entry.
string HighScores::GetName(Uint32 i)
{
multimap<Uint32, string, std::greater<Uint32> >::iterator itr = m_table.begin();
Uint32 j = 0;
while (j < i)
{
itr++;
++j;
}
return itr->second;
}
// Gets the comma formatted score of the i-th entry.
string HighScores::GetScore(Uint32 i)
{
multimap<Uint32, string, std::greater<Uint32> >::iterator itr = m_table.begin();
Uint32 j = 0;
while (j < i)
{
itr++;
++j;
}
return AddCommas(itr->first);
}
// Determines whether the score qualify as a high score.
bool HighScores::Qualifies(Uint32 score)
{
// Since the table (STL map) is guaranteed to be
// sorted in a descending order, the last element
// is always the smallest.
return (score > (--m_table.end())->first);
}
// Add an entry to the high score table
void HighScores::Add(string playerName, Uint32 score)
{
// Make sure the score should be added:
if (!Qualifies(score))
return;
// Remove the lowest score from the table:
m_table.erase(--m_table.end());
if (playerName == "")
playerName = "Anonymous";
// Add the new entry:
m_table.insert(make_pair(score, playerName));
// Write the modified table to disk:
HighScores::Write();
}
// Reads the table from disk.
// If the file is missing or invalid, the table is reset
// to default values.
void HighScores::Read()
{
m_table.clear();
ifstream inputFile(m_fileName.c_str(), ios::in);
if (!inputFile.is_open())
{
SetDefault();
return;
}
string line = "";
for (int i = 0 ; i < NUM_OF_HIGH_SCORES ; ++i)
{
if (std::getline(inputFile, line).eof())
{
// File too short
inputFile.close();
SetDefault();
return;
}
Uint32 score;
string playerName;
size_t comma; // Index of comma in string
if ((comma = line.find_first_of(",")) == line.npos // Get comma location, and make sure it exists
|| (playerName = line.substr(0, comma)).length() <= 0 // Get player name, make sure it is not empty
|| (line.length() - comma) <= 1) // No score
{
// File malformed
inputFile.close();
SetDefault();
return;
}
score = atoi(line.substr(comma + 1).c_str());
// Add the data to the table in memory:
m_table.insert(make_pair(score, playerName));
}
inputFile.close();
}
// Writes the high scores to a file.
void HighScores::Write()
{
if (m_fileName == "")
m_fileName = DEFAULT_FILENAME;
ofstream outputFile(m_fileName.c_str(), ios::out);
TRAP(!outputFile.is_open(), "HighScores::Write - Could not open \"" << m_fileName << "\" for writing.");
/*
// Maybe silent failure is better?
if(!outputFile.is_open())
return;
*/
multimap<Uint32, string, std::greater<Uint32> >::iterator itr;
for (itr = m_table.begin() ; itr != m_table.end() ; itr++)
outputFile << itr->second << "," << itr->first << endl;
outputFile.close();
}
// Sets the table to the default values
void HighScores::SetDefault()
{
m_table.clear();
for (int i = 0 ; i < NUM_OF_HIGH_SCORES ; ++i)
m_table.insert(make_pair(DEFAULT_SCORE[i], DEFAULT_NAME[i]));
}
// Adds commas to a number (e.g. 1520 -> 1,520).
string HighScores::AddCommas(Uint32 num)
{
string result = "";
int i = 0;
while (num > 9)
{
result += '0' + (char) (num % 10);
++i;
if (i % 3 == 0)
result+= ',';
num /= 10;
}
result += '0' + (char) (num % 10);
// Reverse the string:
reverse(result.begin(), result.end());
return result;
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HIGHSCORES_H_
#define _HIGHSCORES_H_
/*
High scores table.
File format:
playerName,score<\n>
For example:
RandomJoe,666<\n>
*/
#include "SDL.h"
#include <string>
#include <map>
#include <functional>
using namespace std;
static const int NUM_OF_HIGH_SCORES = 10; // Number of high scores to keep
static const string DEFAULT_FILENAME = "highscores.dat"; // Default high scores file name
// Default player names and scores.
// This is used when the high scores file is missing or invalid.
static const string DEFAULT_NAME[NUM_OF_HIGH_SCORES] = {
"Player 1",
"Player 2",
"Player 3",
"Player 4",
"Player 5",
"Player 6",
"Player 7",
"Player 8",
"Player 9",
"Player 10"
};
static const Uint32 DEFAULT_SCORE[NUM_OF_HIGH_SCORES] = {
1000,
2000,
3000,
4000,
5000,
6000,
7000,
8000,
9000,
10000
};
/*
static const Uint32 DEFAULT_SCORE[NUM_OF_HIGH_SCORES] = {
500,
1000,
1500,
2000,
2500,
3000,
3500,
4000,
4500,
5000
};
*/
/*
static const Uint32 DEFAULT_SCORE[NUM_OF_HIGH_SCORES] = {
5,
10,
15,
20,
25,
30,
35,
40,
45,
50
};
*/
class HighScores
{
private:
multimap<Uint32, string, std::greater<Uint32> > m_table; // Sorted high scores table (score/player)
string m_fileName; // High scores file name
public:
HighScores();
~HighScores();
Uint32 GetSize(); // Gets the table's size (number of entries)
string GetName(Uint32 i); // Gets the name of the i-th table entry
string GetScore(Uint32 i); // Gets the comma formatted score of the i-th entry
bool Qualifies(Uint32 score); // Does the score qualify as a high score?
void Add(string playerName, Uint32 score); // Adds an entry to the high score table
static string AddCommas(Uint32 num); // Adds commas to a number (e.g. 1520 -> "1,520")
private:
void Read(); // Reads the table from disk
void Write(); // Writes the table to disk
void SetDefault(); // Sets the table to the default values
// No copying:
HighScores(const HighScores&){};
HighScores& operator= (const HighScores&){};
};
#endif

View File

@@ -0,0 +1,215 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../game/selection.h"
#include "../common/soundmanager.h"
#include "../common/trap.h"
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include "SDL_image.h"
using namespace std;
// Constructor
Selection::Selection()
{
m_selected.clear();
}
// Destructor - free resources
Selection::~Selection()
{
}
// Is the selection complete (represents a rectangle)?
bool Selection::IsRect()
{
return (m_selected.size() == 4);
}
// Clears the selection.
void Selection::Clear(bool playSound)
{
if (playSound)
SoundManager::GetInstance()->PlaySound("SelectionCancelled");
m_selected.clear();
}
// Index operator.
Coordinate& Selection::operator[](int i)
{
TRAP(i < 0 || i >= (int) m_selected.size(),"Selection::operator[] - Out of bounds");
return m_selected[i];
}
// Gets the selected rectangle.
// Returns 0 on success.
int Selection::GetRectangle(Coordinate* A, Coordinate* B)
{
if (A == NULL || B == NULL || m_selected.size() != 4)
return -1;
// Get the bounds:
A->x = A->y = BOARD_SIZE;
B->x = B->y = -1;
for (int i = 0 ; i < 4 ; ++i)
{
if (m_selected[i].x < A->x)
A->x = m_selected[i].x;
else if (m_selected[i].x > B->x)
B->x = m_selected[i].x;
if (m_selected[i].y < A->y)
A->y = m_selected[i].y;
else if (m_selected[i].y > B->y)
B->y = m_selected[i].y;
}
return 0;
}
// Adds a marble to the current selection.
// The marble is added only if it is valid. Otherwise, the selection is cleared.
//
// Rules to determine validity of adding a new marble (T) to the selection:
// 1. T is not already selected
// 2. T is the same color as everyone else
// 3. If 2 marbles are already selected, T must align with one of them
// 4. If 3 marbles are already selected, T must align with 2 of them
void Selection::Add(Coordinate coord, Board *board)
{
if (board == NULL)
return;
// Sanity check:
TRAP(m_selected.size() < 0 || m_selected.size() > 4,
"Selection::Add() - Invalid number of marbles selected ("
<< (unsigned int) m_selected.size() << ")");
// Bounds check (does not clear selection):
if (coord.x < 0 || coord.y < 0 || coord.x >= BOARD_SIZE || coord.y >= BOARD_SIZE)
return;
// Check validity:
int l_iHAlign = 0, l_iVAlign = 0; // Number of marbles the new marbles is aligned with
for (unsigned int i = 0 ; i < m_selected.size() ; ++i)
{
// Rules 1:
// If the new marble is already selected, remove it from the selection:
if (coord.x == m_selected[i].x && coord.y == m_selected[i].y)
{
SoundManager::GetInstance()->PlaySound("SelectionCancelled");
m_selected.erase(m_selected.begin() + i);
return;
}
// Rule 2:
// Is the new marble the same color as everyone else?
if (board->GetMarbleColor(m_selected[i]) != board->GetMarbleColor(coord) )
{
SoundManager::GetInstance()->PlaySound("SelectionInvalid");
m_selected.clear();
return;
}
// Check for alignment:
if (coord.y == m_selected[i].y)
l_iHAlign++;
if (coord.x == m_selected[i].x)
l_iVAlign++;
for (unsigned int j = 0 ; j < m_selected.size() ; ++j)
{
if (i != j)
{
if (m_selected[i].y == m_selected[j].y)
l_iHAlign++;
if (m_selected[i].x == m_selected[j].x)
l_iVAlign++;
}
}
}
// Rule 3 - If 2 marbles are already selected, T must align with one of them:
if (m_selected.size() == 2 && !(
(l_iHAlign == 1 && l_iVAlign == 1) ||
(l_iHAlign + l_iVAlign == 3)
))
{
SoundManager::GetInstance()->PlaySound("SelectionInvalid");
m_selected.clear();
return;
}
// Rule 4 - If 3 marbles are already selected, T must align with both of them:
if (m_selected.size() == 3 && (l_iHAlign != 3 || l_iVAlign != 3))
{
SoundManager::GetInstance()->PlaySound("SelectionInvalid");
m_selected.clear();
return;
}
// If we are here, the new marble is valid. Add it to the selection:
m_selected.push_back(coord);
// Play the click sound:
if (m_selected.size() != 4)
SoundManager::GetInstance()->PlaySound("MarbleClick");
}
// Adds a coordinate to the selection.
void Selection::Add(int x, int y, Board *board)
{
Coordinate l_oCoord;
l_oCoord.x = x;
l_oCoord.y = y;
Add(l_oCoord, board);
}
// Returns whether a coordinate is selected.
bool Selection::IsSelected(Coordinate coord)
{
vector<Coordinate>::iterator itr;
for (itr = m_selected.begin() ; itr != m_selected.end() ; itr++)
if (itr->x == coord.x && itr->y == coord.y)
return true;
return false;
}
// Returns whether a coordinate is selected.
bool Selection::IsSelected(int x, int y)
{
Coordinate coord (x, y);
return IsSelected(coord);
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SELECTION_H_
#define _SELECTION_H_
// This class represents the currently selected marbles.
// It enforces the selection rules so that at any given moment,
// the current selection is valid.
#include "SDL.h"
#include "../game/board.h"
#include <vector>
using namespace std;
class Selection
{
private:
vector<Coordinate> m_selected; // Coordinates of the selected marbles
public:
Selection();
~Selection();
bool IsRect(); // Is the selection a rectangle?
void Clear(bool playSound = false); // Clears selection
Coordinate& operator[](int i); // Index operator
int GetRectangle(Coordinate* A, Coordinate* B); // Gets the selected rectangle
int GetSize(){return (int) m_selected.size();} // Gets selection size
bool IsSelected(Coordinate); // Returns whether a coordinate is selected
bool IsSelected(int x, int y);
void Add(Coordinate coord, Board *board); // Adds a marble to the selection
void Add(int x, int y, Board *board);
};
#endif

View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2005 Chai Braudo (braudo@users.sourceforge.net)
*
* This file is part of Jooleem - http://sourceforge.net/projects/jooleem
*
* Jooleem is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Jooleem is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jooleem; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
Jooleem is a simple yet extremely addictive puzzle game. The player is
presented with a 10x10 board of colored marbles, and must click on four
marbles of the same color that form a rectangle. Time is constantly
running out, but forming rectangles earns the player more time, as well
as points. The larger the rectangle, the more time and points are won.
Inspired by Nick Kouvaris' ZNAX:
http://www.freestuff.gr/lightforce/znax.html
*/
// Platform specific headers, to display a dialog box. See MsgBox().
#ifdef _WIN32
#include <windows.h>
#elif defined( __APPLE__ ) && defined( __MACH__ )
#include <Carbon/Carbon.h>
#endif
#include <iostream>
#include "engine/engine.h"
#include "SDL_main.h"
using namespace std;
void MsgBox(string message); // Show a messagebox (cross platform)
int main(int argc, char* argv[])
{
Engine engine;
engine.Run();
return 0;
}
// Shows an exception in an OS message box (cross platform).
// FIX: the message doesn't get here properly
void MsgBox(string message)
{
// Prepare the error message:
char buffer[4096];
sprintf(buffer,
"The game has encountered an unrecoverable error. Please send\n"
"the error message below to braudo@users.sourceforge.net.\n\n%s",
message.c_str());
/*
sprintf(buffer,
"The game has encountered an unrecoverable error\n"
"and will shut down. Downloading and installing\n"
"the game again might solve the problem.\n\n"
"If the problem persists, please contact\n"
"braudo@users.sourceforge.net"
);
*/
// Windows:
#ifdef WIN32
MessageBox(NULL, buffer, "Critical Error", MB_OK | MB_ICONERROR);
// Mac OS X:
#elif defined( __APPLE__ ) && defined( __MACH__ )
// Reference:
// http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/hitb-wind_cont_tasks/chapter_3_section_4.html
DialogRef theItem;
DialogItemIndex itemIndex;
// Create a string ref of the message:
CFStringRef msgStrRef = CFStringCreateWithCString(NULL, message.c_str(), kCFStringEncodingASCII);
// Create the dialog:
CreateStandardAlert(kAlertStopAlert, CFSTR("Critical Error"), msgStrRef, NULL, &theItem);
// Show it:
RunStandardAlert(theItem, NULL, &itemIndex);
// Release the string:
CFRelease(msgStrRef);
// Default to standard error:
#else
// Note that only the basic error message is displayed here.
cerr << message << endl;
#endif
}

View File

@@ -0,0 +1,17 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Jooleem.rc
//
#define IDI_ICON1 101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif