2018-11-08 21:39:26 +08:00
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
# include "Game.h"
# include "Node.h"
# include "Scene.h"
# include "Transition.h"
# include "Image.h"
# include "time.h"
# include "render.h"
# include "input.h"
# include "audio.h"
# include "modules.h"
2018-11-12 02:10:35 +08:00
# include "../utils/Player.h"
# include "../math/Matrix.hpp"
2018-11-08 21:39:26 +08:00
# include <thread>
namespace easy2d
{
Game : : Game ( )
: quit_ ( true )
, curr_scene_ ( nullptr )
, next_scene_ ( nullptr )
, transition_ ( nullptr )
, debug_mode_ ( false )
{
: : CoInitialize ( nullptr ) ;
}
Game : : ~ Game ( )
{
SafeRelease ( transition_ ) ;
SafeRelease ( curr_scene_ ) ;
SafeRelease ( next_scene_ ) ;
: : CoUninitialize ( ) ;
}
2018-11-12 20:46:54 +08:00
void Game : : Initialize ( const Options & options )
2018-11-08 21:39:26 +08:00
{
2018-11-12 22:36:50 +08:00
debug_mode_ = options . debug ;
Window : : Instance ( ) . Initialize ( options . title , options . width , options . height , options . icon , debug_mode_ ) ;
devices : : Graphics : : Instance ( ) . Initialize ( Window : : Instance ( ) . GetHandle ( ) , debug_mode_ ) ;
devices : : Input : : Instance ( ) . Initialize ( debug_mode_ ) ;
devices : : Audio : : Instance ( ) . Initialize ( debug_mode_ ) ;
2018-11-08 21:39:26 +08:00
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ˵<EFBFBD> <CBB5> <EFBFBD> ģʽ <C4A3> <CABD> <EFBFBD> <EFBFBD> <F2BFAABF> <EFBFBD> ̨
HWND console = : : GetConsoleWindow ( ) ;
// <20> رտ<D8B1> <D5BF> <EFBFBD> ̨
if ( debug_mode_ )
{
if ( console = = nullptr )
{
// <20> <> ʾ һ <CABE> <D2BB> <EFBFBD> ¿<EFBFBD> <C2BF> <EFBFBD> ̨
if ( : : AllocConsole ( ) )
{
console = : : GetConsoleWindow ( ) ;
// <20> ض<EFBFBD> <D8B6> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
FILE * stdoutStream , * stdinStream , * stderrStream ;
freopen_s ( & stdoutStream , " conout$ " , " w+t " , stdout ) ;
freopen_s ( & stdinStream , " conin$ " , " r+t " , stdin ) ;
freopen_s ( & stderrStream , " conout$ " , " w+t " , stderr ) ;
// <20> <> <EFBFBD> ÿ<EFBFBD> <C3BF> <EFBFBD> ̨<EFBFBD> رհ <D8B1> ť
HMENU hmenu = : : GetSystemMenu ( console , FALSE ) ;
: : RemoveMenu ( hmenu , SC_CLOSE , MF_BYCOMMAND ) ;
}
}
}
else
{
if ( console )
{
: : ShowWindow ( console , SW_HIDE ) ;
}
}
: : SetWindowLongPtrW (
2018-11-12 20:46:54 +08:00
Window : : Instance ( ) . GetHandle ( ) ,
2018-11-08 21:39:26 +08:00
GWLP_USERDATA ,
PtrToUlong ( this )
) ;
}
void Game : : Run ( )
{
quit_ = false ;
if ( next_scene_ )
{
next_scene_ - > OnEnter ( ) ;
curr_scene_ = next_scene_ ;
next_scene_ = nullptr ;
}
2018-11-12 20:46:54 +08:00
: : ShowWindow ( Window : : Instance ( ) . GetHandle ( ) , SW_SHOWNORMAL ) ;
: : UpdateWindow ( Window : : Instance ( ) . GetHandle ( ) ) ;
2018-11-08 21:39:26 +08:00
2018-11-11 16:32:12 +08:00
const int64_t min_interval = 5 ;
2018-11-08 21:39:26 +08:00
auto last = time : : Now ( ) ;
MSG msg = { 0 } ;
while ( ! quit_ )
{
auto now = time : : Now ( ) ;
auto dur = now - last ;
if ( dur . Milliseconds ( ) > min_interval )
{
float dt = ( now - last ) . Seconds ( ) ;
last = now ;
2018-11-12 20:46:54 +08:00
devices : : Input : : Instance ( ) . Update (
Window : : Instance ( ) . GetHandle ( ) ,
Window : : Instance ( ) . GetContentScaleX ( ) ,
Window : : Instance ( ) . GetContentScaleY ( )
2018-11-08 21:39:26 +08:00
) ;
OnUpdate ( dt ) ;
UpdateScene ( dt ) ;
DrawScene ( ) ;
while ( : : PeekMessage ( & msg , nullptr , 0 , 0 , PM_REMOVE ) )
{
: : TranslateMessage ( & msg ) ;
: : DispatchMessage ( & msg ) ;
}
}
else
{
// ID2D1HwndRenderTarget <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ˴ <EFBFBD> ֱͬ<D6B1> <CDAC> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ⱦʱ<C8BE> <CAB1> <EFBFBD> ȴ<EFBFBD> <C8B4> <EFBFBD> ʾ <EFBFBD> <CABE> ˢ<EFBFBD> £<EFBFBD>
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ˷dz<CBB7> <C7B3> ȶ<EFBFBD> <C8B6> <EFBFBD> <EFBFBD> <EFBFBD> ʱ<EFBFBD> <CAB1> <EFBFBD> ã<EFBFBD> <C3A3> <EFBFBD> <EFBFBD> Դ<D4B4> ʱ<EFBFBD> <CAB1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ҫ<EFBFBD> ֶ<EFBFBD> <D6B6> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ߳̽<DFB3> <CCBD> <EFBFBD> <EFBFBD> <EFBFBD> ʱ<EFBFBD> <CAB1>
// <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ĵ<EFBFBD> <C4B4> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> һ Щ<D2BB> <D0A9> <EFBFBD> <EFBFBD> <EFBFBD> £<EFBFBD> <C2A3> <EFBFBD> <EFBFBD> 細<EFBFBD> <E7B4B0> <EFBFBD> <EFBFBD> С <EFBFBD> <D0A1> ʱ<EFBFBD> <CAB1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ̣߳<DFB3> <CCA3> <EFBFBD> ֹռ <D6B9> ù<EFBFBD> <C3B9> <EFBFBD> CPU <20> <>
2018-11-11 16:32:12 +08:00
int64_t wait = min_interval - dur . Milliseconds ( ) ;
if ( wait > 1LL )
2018-11-08 21:39:26 +08:00
{
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( wait ) ) ;
}
}
}
}
void Game : : Quit ( )
{
quit_ = true ;
}
void Game : : EnterScene ( Scene * scene , Transition * transition )
{
if ( scene = = nullptr )
{
E2D_WARNING ( " Next scene is null pointer! " ) ;
return ;
}
if ( curr_scene_ = = scene ) { return ; }
if ( next_scene_ )
{
next_scene_ - > Release ( ) ;
}
next_scene_ = scene ;
next_scene_ - > Retain ( ) ;
if ( transition )
{
if ( transition_ )
{
transition_ - > Stop ( ) ;
transition_ - > Release ( ) ;
}
transition_ = transition ;
transition_ - > Retain ( ) ;
transition_ - > Initialize ( curr_scene_ , next_scene_ , this ) ;
}
}
Scene * Game : : GetCurrentScene ( )
{
return curr_scene_ ;
}
bool Game : : IsTransitioning ( ) const
{
return transition_ ! = nullptr ;
}
void Game : : UpdateScene ( float dt )
{
auto update = [ & ] ( Scene * scene ) - > void
{
if ( scene )
{
scene - > OnUpdate ( dt ) ;
Node * root = scene - > GetRoot ( ) ;
if ( root )
{
root - > UpdateChildren ( dt ) ;
}
}
} ;
update ( curr_scene_ ) ;
update ( next_scene_ ) ;
if ( transition_ )
{
transition_ - > Update ( ) ;
if ( transition_ - > IsDone ( ) )
{
transition_ - > Release ( ) ;
transition_ = nullptr ;
}
else
{
return ;
}
}
if ( next_scene_ )
{
if ( curr_scene_ )
{
curr_scene_ - > OnExit ( ) ;
curr_scene_ - > Release ( ) ;
}
next_scene_ - > OnEnter ( ) ;
curr_scene_ = next_scene_ ;
next_scene_ = nullptr ;
}
}
void Game : : DrawScene ( )
{
2018-11-12 22:36:50 +08:00
auto & graphics = devices : : Graphics : : Instance ( ) ;
graphics . BeginDraw ( Window : : Instance ( ) . GetHandle ( ) ) ;
2018-11-08 21:39:26 +08:00
if ( transition_ )
{
transition_ - > Draw ( ) ;
}
else if ( curr_scene_ )
{
curr_scene_ - > Draw ( ) ;
}
if ( debug_mode_ )
{
if ( curr_scene_ & & curr_scene_ - > GetRoot ( ) )
{
2018-11-12 22:36:50 +08:00
graphics . SetTransform ( math : : Matrix ( ) ) ;
graphics . SetBrushOpacity ( 1.f ) ;
2018-11-08 21:39:26 +08:00
curr_scene_ - > GetRoot ( ) - > DrawBorder ( ) ;
}
if ( next_scene_ & & next_scene_ - > GetRoot ( ) )
{
2018-11-12 22:36:50 +08:00
graphics . SetTransform ( math : : Matrix ( ) ) ;
graphics . SetBrushOpacity ( 1.f ) ;
2018-11-08 21:39:26 +08:00
next_scene_ - > GetRoot ( ) - > DrawBorder ( ) ;
}
2018-11-12 22:36:50 +08:00
graphics . DrawDebugInfo ( ) ;
2018-11-08 21:39:26 +08:00
}
2018-11-12 22:36:50 +08:00
graphics . EndDraw ( ) ;
2018-11-08 21:39:26 +08:00
}
}