Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F126510
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
31 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/init.cpp b/util/init.cpp
new file mode 100644
index 00000000..68d5fc1e
--- /dev/null
+++ b/util/init.cpp
@@ -0,0 +1,417 @@
+#ifdef USE_ALLEGRO
+#include <allegro.h>
+#ifdef ALLEGRO_WINDOWS
+#include <winalleg.h>
+#endif
+#endif
+
+#ifdef USE_SDL
+#include <SDL.h>
+#endif
+
+#ifndef WINDOWS
+#include <signal.h>
+#include <string.h>
+#endif
+
+/* don't be a boring tuna */
+// #warning you are ugly
+
+#include "globals.h"
+#include "init.h"
+#include "network/network.h"
+#include "util/thread.h"
+#include <time.h>
+
+#include <ostream>
+#include "util/dumb/include/dumb.h"
+#ifdef USE_ALLEGRO
+#include "util/dumb/include/aldumb.h"
+#include "util/loadpng/loadpng.h"
+#include "util/gif/algif.h"
+#endif
+#include "util/bitmap.h"
+#include "util/funcs.h"
+#include "util/file-system.h"
+#include "util/font.h"
+#include "util/sound.h"
+#include "configuration.h"
+#include "script/script.h"
+#include "util/music.h"
+#include "util/loading.h"
+
+#ifdef WII
+#include <fat.h>
+#endif
+
+using namespace std;
+
+volatile int Global::speed_counter = 0;
+
+/* enough seconds for 136 years */
+volatile unsigned int Global::second_counter = 0;
+
+/* the original engine was running at 90 ticks per second, but we dont
+ * need to render that fast, so TICS_PER_SECOND is really fps and
+ * LOGIC_MULTIPLIER will be used to adjust the speed counter to its
+ * original value.
+ */
+const int Global::TICS_PER_SECOND = 40;
+const double Global::LOGIC_MULTIPLIER = (double) 90 / (double) Global::TICS_PER_SECOND;
+
+
+#ifdef USE_ALLEGRO
+const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
+const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;
+#else
+/* FIXME: use enums here or something */
+const int Global::WINDOWED = 0;
+const int Global::FULLSCREEN = 1;
+#endif
+
+/* game counter, controls FPS */
+static void inc_speed_counter(){
+ /* probably put input polling here, InputManager::poll() */
+ Global::speed_counter += 1;
+}
+#ifdef USE_ALLEGRO
+END_OF_FUNCTION( inc_speed_counter )
+#endif
+
+/* if you need to count seconds for some reason.. */
+static void inc_second_counter() {
+ Global::second_counter += 1;
+}
+#ifdef USE_ALLEGRO
+END_OF_FUNCTION( inc_second_counter )
+#endif
+
+#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(NDS)
+static void handleSigSegV(int i, siginfo_t * sig, void * data){
+ const char * message = "Bug! Caught a memory violation. Shutting down..\n";
+ int dont_care = write(1, message, 48);
+ dont_care = dont_care;
+ // Global::shutdown_message = "Bug! Caught a memory violation. Shutting down..";
+ Bitmap::setGfxModeText();
+#ifdef USE_ALLEGRO
+ allegro_exit();
+#endif
+ /* write to a log file or something because sigsegv shouldn't
+ * normally happen.
+ */
+ exit(1);
+}
+#else
+#endif
+
+/* catch a socket being closed prematurely on unix */
+#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(NDS)
+static void handleSigPipe( int i, siginfo_t * sig, void * data ){
+}
+
+/*
+static void handleSigUsr1( int i, siginfo_t * sig, void * data ){
+ pthread_exit( NULL );
+}
+*/
+#endif
+
+static void registerSignals(){
+#if !defined(WINDOWS) && !defined(WII) && !defined(MINPSPW) && !defined(NDS)
+ struct sigaction action;
+ memset( &action, 0, sizeof(struct sigaction) );
+ action.sa_sigaction = handleSigPipe;
+ sigaction( SIGPIPE, &action, NULL );
+
+ memset( &action, 0, sizeof(struct sigaction) );
+ action.sa_sigaction = handleSigSegV;
+ sigaction( SIGSEGV, &action, NULL );
+
+ /*
+ action.sa_sigaction = handleSigUsr1;
+ sigaction( SIGUSR1, &action, NULL );
+ */
+#endif
+}
+
+/* should probably call the janitor here or something */
+static void close_paintown(){
+ Music::pause();
+ Bitmap::setGfxModeText();
+#ifdef USE_ALLEGRO
+ allegro_exit();
+#endif
+ exit(0);
+}
+
+namespace Global{
+ extern int do_shutdown;
+}
+
+static void close_window(){
+ /* when do_shutdown is 1 the game will attempt to throw ShutdownException
+ * wherever it is. If the game is stuck or the code doesn't throw
+ * ShutdownException then when the user tries to close the window
+ * twice we just forcifully shutdown.
+ */
+ Global::do_shutdown += 1;
+ if (Global::do_shutdown == 2){
+ close_paintown();
+ }
+}
+#ifdef USE_ALLEGRO
+END_OF_FUNCTION(close_window)
+#endif
+
+#ifdef USE_ALLEGRO
+static void initSystem(ostream & out){
+ out << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
+ out << "Allegro init: " <<allegro_init()<<endl;
+ out << "Install timer: " <<install_timer()<<endl;
+
+ /* png */
+ loadpng_init();
+ algif_init();
+
+ out<<"Install keyboard: "<<install_keyboard()<<endl;
+ /* do we need the mouse?? */
+ // out<<"Install mouse: "<<install_mouse()<<endl;
+ out<<"Install joystick: "<<install_joystick(JOY_TYPE_AUTODETECT)<<endl;
+ /* 16 bit color depth */
+ set_color_depth(16);
+
+ LOCK_VARIABLE( speed_counter );
+ LOCK_VARIABLE( second_counter );
+ LOCK_FUNCTION( (void *)inc_speed_counter );
+ LOCK_FUNCTION( (void *)inc_second_counter );
+ /* set up the timers */
+ out<<"Install game timer: "<< install_int_ex(inc_speed_counter, BPS_TO_TIMER(Global::TICS_PER_SECOND))<<endl;
+ out<<"Install second timer: "<<install_int_ex(inc_second_counter, BPS_TO_TIMER(1))<<endl;
+
+ /* keep running in the background */
+ set_display_switch_mode(SWITCH_BACKGROUND);
+
+ /* close window when the X is pressed */
+ LOCK_FUNCTION(close_window);
+ set_close_button_callback(close_window);
+}
+
+#endif
+#ifdef USE_SDL
+
+// static pthread_t events;
+
+struct TimerInfo{
+ TimerInfo(void (*x)(), int y):
+ tick(x), frequency(y){}
+
+ void (*tick)();
+ int frequency;
+};
+
+static void * do_timer(void * arg){
+ TimerInfo info = *(TimerInfo *) arg;
+ uint32_t delay = (uint32_t)(1000.0 / (double) info.frequency);
+
+ /* assuming SDL_GetTicks() starts at 0, this should last for about 50 days
+ * before overflowing. overflow should work out fine. Assuming activate occurs
+ * when the difference between now and ticks is at least 6, the following will happen.
+ * ticks now now-ticks
+ * 4294967294 4294967294 0
+ * 4294967294 4294967295 1
+ * 4294967294 0 2
+ * 4294967294 1 3
+ * 4294967294 2 4
+ * 4294967294 3 5
+ * 4294967294 4 6
+ * Activate
+ * 3 5 2
+ * 3 6 3
+ * 3 7 4
+ * 3 8 5
+ * 3 9 6
+ * Activate
+ *
+ * Can 'now' ever be much larger than 'ticks' due to overflow?
+ * It doesn't seem like it.
+ */
+ uint32_t ticks = SDL_GetTicks();
+
+ /* TODO: pass in some variable that tells this loop to quit */
+ while (true){
+ uint32_t now = SDL_GetTicks();
+ while (now - ticks >= delay){
+ // Global::debug(0) << "Tick!" << endl;
+ info.tick();
+ ticks += delay;
+ }
+ SDL_Delay(1);
+ }
+
+ delete (TimerInfo *) arg;
+
+ return NULL;
+}
+
+static Util::Thread::Id start_timer(void (*func)(), int frequency){
+ TimerInfo * speed = new TimerInfo(func, frequency);
+ /*
+ speed.tick = func;
+ speed.frequency = frequency;
+*/
+ Util::Thread::Id thread;
+ Util::Thread::createThread(&thread, NULL, (Util::Thread::ThreadFunction) do_timer, (void*) speed);
+ return thread;
+}
+
+#if 0
+static void * handleEvents(void * arg){
+ bool done = false;
+ while (!done){
+ SDL_Event event;
+ int ok = SDL_WaitEvent(&event);
+ if (ok){
+ switch (event.type){
+ case SDL_QUIT : {
+ done = true;
+ close_window();
+ break;
+ }
+ default : {
+ // Global::debug(0) << "Ignoring SDL event " << event.type << endl;
+ break;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+#endif
+
+/*
+static void doSDLQuit(){
+ SDL_Event quit;
+ quit.type = SDL_QUIT;
+ SDL_PushEvent(&quit);
+ Global::debug(0) << "Waiting for SDL event handler to finish" << endl;
+ pthread_join(events, NULL);
+ SDL_Quit();
+}
+*/
+
+static void initSystem(ostream & out){
+ out << "SDL Init: ";
+ int ok = SDL_Init(SDL_INIT_VIDEO |
+ SDL_INIT_AUDIO |
+ SDL_INIT_TIMER |
+ SDL_INIT_JOYSTICK |
+ SDL_INIT_NOPARACHUTE);
+ if (ok == 0){
+ out << "Ok" << endl;
+ } else {
+ out << "Failed (" << ok << ") - " << SDL_GetError() << endl;
+ exit(ok);
+ }
+
+ /* Just do SDL thread init
+#ifdef MINPSPW
+ pthread_init();
+#endif
+*/
+
+ start_timer(inc_speed_counter, Global::TICS_PER_SECOND);
+ start_timer(inc_second_counter, 1);
+
+ try{
+ SDL_Surface * icon = SDL_LoadBMP(Filesystem::find(Filesystem::RelativePath("menu/icon.bmp")).path().c_str());
+ if (icon != NULL){
+ SDL_WM_SetIcon(icon, NULL);
+ }
+ } catch (const Filesystem::NotFound & failed){
+ Global::debug(0) << "Could not find window icon: " << failed.getTrace() << endl;
+ }
+
+ SDL_WM_SetCaption("Paintown", NULL);
+
+ SDL_EnableUNICODE(1);
+ SDL_JoystickEventState(1);
+ SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+
+ atexit(SDL_Quit);
+ // atexit(doSDLQuit);
+}
+#endif
+
+bool Global::init(int gfx){
+
+ ostream & out = Global::debug( 0 );
+ out << "-- BEGIN init --" << endl;
+ out << "Data path is " << Util::getDataPath2().path() << endl;
+ out << "Paintown version " << Global::getVersionString() << endl;
+ out << "Build date " << __DATE__ << " " << __TIME__ << endl;
+
+#ifdef WII
+ fatInitDefault();
+#endif
+
+ /* do implementation specific setup */
+ initSystem(out);
+
+ dumb_register_stdfiles();
+
+ Sound::initialize();
+
+ Bitmap::SCALE_X = GFX_X;
+ Bitmap::SCALE_Y = GFX_Y;
+
+ Configuration::loadConfigurations();
+ const int sx = Configuration::getScreenWidth();
+ const int sy = Configuration::getScreenHeight();
+ if (gfx == -1){
+ gfx = Configuration::getFullscreen() ? Global::FULLSCREEN : Global::WINDOWED;
+ } else {
+ Configuration::setFullscreen(gfx == Global::FULLSCREEN);
+ }
+
+ /* set up the screen */
+ int gfxCode = Bitmap::setGraphicsMode(gfx, sx, sy);
+ if (gfxCode == 0){
+ out << "Set graphics mode: Ok" << endl;
+ } else {
+ out << "Set graphics mode: Failed! (" << gfxCode << ")" << endl;
+ return false;
+ }
+
+ /* music */
+ atexit(&dumb_exit);
+
+ out << "Initialize random number generator" << endl;
+ /* initialize random number generator */
+ srand(time(NULL));
+
+ registerSignals();
+
+#ifdef HAVE_NETWORKING
+ out << "Initialize network" << endl;
+ Network::init();
+ atexit(Network::closeAll);
+#endif
+
+ /* this mutex is used to show the loading screen while the game loads */
+ // Util::Thread::initializeLock(&Loader::loading_screen_mutex);
+
+ out << "-- END init --" << endl;
+
+ /*
+ const Font & font = Font::getDefaultFont();
+ // font.setSize(30, 30);
+ Bitmap temp(font.textLength("Loading") + 1, font.getHeight("Loading") + 1);
+ font.printf(0, 0, Bitmap::makeColor(255, 255, 255), temp, "Loading", 0);
+ temp.BlitToScreen(sx / 2, sy / 2);
+ */
+ Bitmap white(sx, sy);
+ white.fill(Bitmap::makeColor(255, 255, 255));
+ white.BlitToScreen();
+
+ return true;
+}
diff --git a/util/init.h b/util/init.h
new file mode 100644
index 00000000..0516b3a8
--- /dev/null
+++ b/util/init.h
@@ -0,0 +1,27 @@
+#ifndef _paintown_init_h
+#define _paintown_init_h
+
+/* global vars */
+
+#define GFX_X 640
+#define GFX_Y 480
+
+namespace Global{
+ extern volatile int speed_counter;
+ extern volatile unsigned int second_counter;
+
+ extern const double LOGIC_MULTIPLIER;
+ extern const int TICS_PER_SECOND;
+
+ extern const int WINDOWED;
+ extern const int FULLSCREEN;
+
+ bool init( int gfx );
+}
+
+/*
+#define GFX_X 320
+#define GFX_Y 240
+*/
+
+#endif
diff --git a/util/loading.cpp b/util/loading.cpp
index c9d08d3b..ff7d9457 100644
--- a/util/loading.cpp
+++ b/util/loading.cpp
@@ -1,529 +1,529 @@
-#include "util/bitmap.h"
-#include "util/trans-bitmap.h"
+#include "bitmap.h"
+#include "trans-bitmap.h"
#include <math.h>
#include <iostream>
#include "level/utils.h"
-#include "util/messages.h"
+#include "messages.h"
#include "loading.h"
-#include "util/file-system.h"
-#include "util/font.h"
-#include "util/funcs.h"
-#include "util/gradient.h"
-#include "util/thread.h"
+#include "file-system.h"
+#include "font.h"
+#include "funcs.h"
+#include "gradient.h"
+#include "thread.h"
#include "globals.h"
#include <vector>
-#include "util/thread.h"
-#include "util/message-queue.h"
+#include "thread.h"
+#include "message-queue.h"
#include "init.h"
using namespace std;
namespace Loader{
// Util::Thread::Lock loading_screen_mutex;
volatile bool done_loading = true;
typedef struct pair{
int x, y;
} ppair;
class Info{
public:
Info(){
Global::registerInfo(&messages);
}
bool transferMessages(Messages & box){
bool did = false;
while (messages.hasAny()){
const string & str = messages.get();
box.addMessage(str);
did = true;
}
return did;
}
~Info(){
Global::unregisterInfo(&messages);
}
private:
MessageQueue messages;
};
void * loadingScreenSimple1(void * arg);
#if 0
void startLoading(Util::Thread::Id * thread, void * arg, Kind kind){
bool create = false;
Util::Thread::acquireLock(&loading_screen_mutex);
create = done_loading;
done_loading = false;
Util::Thread::releaseLock(&loading_screen_mutex);
/* prevent multiple loading threads from being made */
if (create){
switch (kind){
case Default: Util::Thread::createThread(thread, NULL, (Util::Thread::ThreadFunction) loadingScreen, arg); break;
case SimpleCircle: Util::Thread::createThread(thread, NULL, (Util::Thread::ThreadFunction) loadingScreenSimple1, arg); break;
}
}
}
void stopLoading(Util::Thread::Id thread){
bool needJoin = false;
Util::Thread::acquireLock( &loading_screen_mutex );
needJoin = ! done_loading;
done_loading = true;
Util::Thread::releaseLock( &loading_screen_mutex );
if (needJoin){
Util::Thread::joinThread(thread);
}
}
#endif
static void setupBackground(const Bitmap & background, int load_x, int load_y, int load_width, int load_height, int infobox_x, int infobox_y, int infoWidth, int infoHeight, const Bitmap & infoBackground, const Bitmap & work){
background.Blit(load_x, load_y, load_width, load_height, 0, 0, work);
Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2 - Font::getDefaultFont().getHeight(), Bitmap::makeColor( 192, 192, 192 ), background, "Paintown version %s", 0, Global::getVersionString().c_str());
Font::getDefaultFont().printf( 400, 480 - Font::getDefaultFont().getHeight() * 5 / 2, Bitmap::makeColor( 192, 192, 192 ), background, "Made by Jon Rafkind", 0 );
background.BlitToScreen();
background.Blit(infobox_x, infobox_y, infoWidth, infoHeight, 0, 0, infoBackground);
}
static vector<ppair> generateFontPixels(const Font & myFont, const string & message, int width, int height){
Bitmap letters(width, height);
letters.fill( Bitmap::MaskColor() );
myFont.printf( 0, 0, Bitmap::makeColor(255, 255, 255), letters, message.c_str(), 0 );
vector< ppair > pairs;
/* store every pixel we need to draw */
for ( int x = 0; x < letters.getWidth(); x++ ){
for ( int y = 0; y < letters.getHeight(); y++ ){
int pixel = letters.getPixel(x, y);
if (pixel != Bitmap::MaskColor()){
ppair p;
p.x = x;
p.y = y;
pairs.push_back( p );
}
}
}
return pairs;
}
/* shows time elapsed */
class TimeCounter{
public:
TimeCounter():
work(200, 40){
start = Global::second_counter;
last = 0;
}
void draw(int x, int y){
const Font & font = Font::getDefaultFont(24, 24);
if (Global::second_counter != last){
work.clear();
last = Global::second_counter;
font.printf(0, 0, Bitmap::makeColor(192, 192, 192), work, "Waiting.. %d", 0, last - start);
work.BlitAreaToScreen(x, y);
}
}
Bitmap work;
unsigned int start;
unsigned int last;
};
/* FIXME: get rid of this method */
#if 0
void * loadingScreen(void * arg){
int load_x = 80;
int load_y = 220;
const int infobox_width = 300;
const int infobox_height = 150;
Info info;
const Font & myFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
const Font & infoFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
Level::LevelInfo levelInfo;
if (arg != NULL){
levelInfo = *(Level::LevelInfo*) arg;
}
if (levelInfo.getPositionX() != -1){
load_x = levelInfo.getPositionX();
}
if (levelInfo.getPositionY() != -1){
load_y = levelInfo.getPositionY();
}
// const char * the_string = (arg != NULL) ? (const char *) arg : "Loading...";
int load_width = myFont.textLength(levelInfo.loadingMessage().c_str());
int load_height = myFont.getHeight(levelInfo.loadingMessage().c_str());
const int infobox_x = load_x;
const int infobox_y = load_y + load_height * 2;
Global::debug( 2 ) << "loading screen" << endl;
Bitmap work( load_width, load_height );
vector<ppair> pairs = generateFontPixels(myFont, levelInfo.loadingMessage(), load_width, load_height);
Messages infobox(infobox_width, infobox_height);
Bitmap infoWork(infobox_width, infobox_height);
Bitmap infoBackground(infobox_width, infobox_height);
const int MAX_COLOR = 200;
/* blend from dark grey to light red */
Effects::Gradient gradient(MAX_COLOR, Bitmap::makeColor(16, 16, 16), Bitmap::makeColor(192, 8, 8));
Global::speed_counter = 0;
if (levelInfo.getBackground() != 0){
setupBackground(*levelInfo.getBackground(), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
} else {
setupBackground(Bitmap(levelInfo.loadingBackground().path()), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
}
Util::ThreadBoolean quit(done_loading, loading_screen_mutex);
TimeCounter counter;
bool firstDraw = true;
while ( ! quit.get() ){
/* true if a logic loop has passed */
bool draw = firstDraw;
/* will be true if any new info messages appeared */
bool drawInfo = firstDraw;
firstDraw = false;
if ( Global::speed_counter > 0 ){
double think = Global::speed_counter;
Global::speed_counter = 0;
draw = true;
while ( think > 0 ){
gradient.backward();
think -= 1;
}
/* if no new messages appeared this will be false */
drawInfo = info.transferMessages(infobox);
} else {
Util::rest( 1 );
}
if (draw){
for ( vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++ ){
int color = gradient.current(it->x);
work.putPixel(it->x, it->y, color);
}
// counter.draw(200, 100);
/* we might not have to draw the whole info box again if no new
* messages appeared.
*/
if (drawInfo){
infoBackground.Blit(infoWork);
/* cheesy hack to change the font size. the font
* should store the size and change it on its own
*/
Font::getFont(Global::DEFAULT_FONT, 13, 13);
infobox.draw(0, 0, infoWork, infoFont);
Font::getFont(Global::DEFAULT_FONT, 24, 24);
infoWork.BlitAreaToScreen(infobox_x, infobox_y);
}
/* work already contains the correct background */
// work.Blit( load_x, load_y, *Bitmap::Screen );
work.BlitAreaToScreen(load_x, load_y);
}
}
return NULL;
}
#endif
static void loadingScreen1(LoadingContext & context, const Level::LevelInfo & levelInfo){
int load_x = 80;
int load_y = 220;
const int infobox_width = 300;
const int infobox_height = 150;
Info info;
const Font & myFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
const Font & infoFont = Font::getFont(Global::DEFAULT_FONT, 24, 24);
if (levelInfo.getPositionX() != -1){
load_x = levelInfo.getPositionX();
}
if (levelInfo.getPositionY() != -1){
load_y = levelInfo.getPositionY();
}
// const char * the_string = (arg != NULL) ? (const char *) arg : "Loading...";
int load_width = myFont.textLength(levelInfo.loadingMessage().c_str());
int load_height = myFont.getHeight(levelInfo.loadingMessage().c_str());
const int infobox_x = load_x;
const int infobox_y = load_y + load_height * 2;
Global::debug(2) << "loading screen" << endl;
Bitmap work(load_width, load_height);
vector<ppair> pairs = generateFontPixels(myFont, levelInfo.loadingMessage(), load_width, load_height);
Messages infobox(infobox_width, infobox_height);
Bitmap infoWork(infobox_width, infobox_height);
Bitmap infoBackground(infobox_width, infobox_height);
const int MAX_COLOR = 200;
/* blend from dark grey to light red */
Effects::Gradient gradient(MAX_COLOR, Bitmap::makeColor(16, 16, 16), Bitmap::makeColor(192, 8, 8));
Global::speed_counter = 0;
if (levelInfo.getBackground() != 0){
setupBackground(*levelInfo.getBackground(), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
} else {
setupBackground(Bitmap(levelInfo.loadingBackground().path()), load_x, load_y, load_width, load_height, infobox_x, infobox_y, infoBackground.getWidth(), infoBackground.getHeight(), infoBackground, work);
}
TimeCounter counter;
bool firstDraw = true;
while (! context.done()){
/* true if a logic loop has passed */
bool draw = firstDraw;
/* will be true if any new info messages appeared */
bool drawInfo = firstDraw;
firstDraw = false;
if ( Global::speed_counter > 0 ){
double think = Global::speed_counter;
Global::speed_counter = 0;
draw = true;
while ( think > 0 ){
gradient.backward();
think -= 1;
}
/* if no new messages appeared this will be false */
drawInfo = info.transferMessages(infobox);
} else {
Util::rest( 1 );
}
if (draw){
for ( vector< ppair >::iterator it = pairs.begin(); it != pairs.end(); it++ ){
int color = gradient.current(it->x);
work.putPixel(it->x, it->y, color);
}
// counter.draw(200, 100);
/* we might not have to draw the whole info box again if no new
* messages appeared.
*/
if (drawInfo){
infoBackground.Blit(infoWork);
/* cheesy hack to change the font size. the font
* should store the size and change it on its own
*/
Font::getFont(Global::DEFAULT_FONT, 13, 13);
infobox.draw(0, 0, infoWork, infoFont);
Font::getFont(Global::DEFAULT_FONT, 24, 24);
infoWork.BlitAreaToScreen(infobox_x, infobox_y);
}
/* work already contains the correct background */
// work.Blit( load_x, load_y, *Bitmap::Screen );
work.BlitAreaToScreen(load_x, load_y);
}
}
}
/* shows some circles rotating around a center point */
/* FIXME: get rid of this method */
#if 0
void * loadingScreenSimple1(void * arg){
Bitmap work(40, 40);
Bitmap original(40, 40);
original.BlitFromScreen(0, 0);
Util::ThreadBoolean quit(done_loading, loading_screen_mutex);
Global::speed_counter = 0;
int angle = 0;
int color1 = Bitmap::makeColor(0, 0, 0);
int color2 = Bitmap::makeColor(0x00, 0x99, 0xff);
int color3 = Bitmap::makeColor(0xff, 0x22, 0x33);
int color4 = Bitmap::makeColor(0x44, 0x77, 0x33);
/* the length of this array is the number of circles to show */
int colors[4] = {color1, color2, color3, color4};
Bitmap::transBlender(0, 0, 0, 64);
/* speed of rotation */
int speed = 7;
while (! quit.get()){
bool draw = false;
if (Global::speed_counter > 0){
double think = Global::speed_counter;
Global::speed_counter = 0;
draw = true;
while (think > 0){
angle += speed;
think -= 1;
}
} else {
Util::rest(1);
}
if (draw){
int max = sizeof(colors) / sizeof(int);
double middleX = work.getWidth() / 2;
double middleY = work.getHeight() / 2;
original.Blit(work);
for (int i = 0; i < max; i++){
double x = cos(Util::radians(angle + 360 / max * i)) * 15;
double y = sin(Util::radians(angle + 360 / max * i)) * 15;
/* ghost circle */
work.translucent().circleFill(middleX + x, middleY + y, 2, colors[i]);
x = cos(Util::radians(angle + speed + 360 / max * i)) * 15;
y = sin(Util::radians(angle + speed + 360 / max * i)) * 15;
/* real circle */
work.circleFill(middleX + x, middleY + y, 2, colors[i]);
}
work.BlitAreaToScreen(0, 0);
}
}
return NULL;
}
#endif
static void loadingScreenSimpleX1(LoadingContext & context, const Level::LevelInfo & levelInfo){
Bitmap work(40, 40);
Bitmap original(40, 40);
original.BlitFromScreen(0, 0);
Global::speed_counter = 0;
int angle = 0;
int color1 = Bitmap::makeColor(0, 0, 0);
int color2 = Bitmap::makeColor(0x00, 0x99, 0xff);
int color3 = Bitmap::makeColor(0xff, 0x22, 0x33);
int color4 = Bitmap::makeColor(0x44, 0x77, 0x33);
/* the length of this array is the number of circles to show */
int colors[4] = {color1, color2, color3, color4};
Bitmap::transBlender(0, 0, 0, 64);
/* speed of rotation */
int speed = 7;
while (! context.done()){
bool draw = false;
if (Global::speed_counter > 0){
double think = Global::speed_counter;
Global::speed_counter = 0;
draw = true;
while (think > 0){
angle += speed;
think -= 1;
}
} else {
Util::rest(1);
}
if (draw){
int max = sizeof(colors) / sizeof(int);
double middleX = work.getWidth() / 2;
double middleY = work.getHeight() / 2;
original.Blit(work);
for (int i = 0; i < max; i++){
double x = cos(Util::radians(angle + 360 / max * i)) * 15;
double y = sin(Util::radians(angle + 360 / max * i)) * 15;
/* ghost circle */
work.translucent().circleFill(middleX + x, middleY + y, 2, colors[i]);
x = cos(Util::radians(angle + speed + 360 / max * i)) * 15;
y = sin(Util::radians(angle + speed + 360 / max * i)) * 15;
/* real circle */
work.circleFill(middleX + x, middleY + y, 2, colors[i]);
}
work.BlitAreaToScreen(0, 0);
}
}
}
LoadingContext::LoadingContext():
finished(false){
Util::Thread::initializeLock(&lock);
}
LoadingContext::~LoadingContext(){
}
void LoadingContext::doLoad(){
this->load();
Util::Thread::acquireLock(&lock);
finished = true;
Util::Thread::releaseLock(&lock);
}
bool LoadingContext::done(){
bool ok = false;
Util::Thread::acquireLock(&lock);
ok = this->finished;
Util::Thread::releaseLock(&lock);
return ok;
}
void * LoadingContext::load_it(void * arg){
LoadingContext * context = (LoadingContext*) arg;
context->doLoad();
return NULL;
}
static void showLoadMessage(){
int screenX = 80;
int screenY = 50;
Bitmap work(110, 50);
work.BlitFromScreen(screenX, screenY);
Bitmap top(110, 50);
top.fill(Bitmap::makeColor(0, 0, 0));
Font::getDefaultFont(25, 25).printf(10, 5, Bitmap::makeColor(192, 192, 192), top, "Loading", 0);
Bitmap::transBlender(0, 0, 0, 200);
top.drawTrans(0, 0, work);
work.BlitAreaToScreen(screenX, screenY);
}
void loadScreen(LoadingContext & context, const Level::LevelInfo & info, Kind kind){
Util::Thread::Id loadingThread;
bool created = Util::Thread::createThread(&loadingThread, NULL, (Util::Thread::ThreadFunction) LoadingContext::load_it, &context);
if (!created){
Global::debug(0) << "Could not create loading thread. Loading will occur in the main thread" << endl;
showLoadMessage();
LoadingContext::load_it(&context);
// throw LoadException(__FILE__, __LINE__, "Could not create loader thread");
} else {
switch (kind){
case Default: loadingScreen1(context, info); break;
case SimpleCircle: loadingScreenSimpleX1(context, info); break;
default: loadingScreen1(context, info); break;
}
Util::Thread::joinThread(loadingThread);
}
}
}
diff --git a/util/loading.h b/util/loading.h
index 0d648219..1c2b4cd7 100644
--- a/util/loading.h
+++ b/util/loading.h
@@ -1,44 +1,44 @@
#ifndef _paintown_loading_h
#define _paintown_loading_h
-#include "util/thread.h"
+#include "thread.h"
namespace Level{
class LevelInfo;
}
namespace Loader{
/* Kind of loader to show */
enum Kind{
Default,
SimpleCircle
};
class LoadingContext{
public:
LoadingContext();
virtual ~LoadingContext();
virtual void doLoad();
virtual void load() = 0;
virtual bool done();
static void * load_it(void * arg);
protected:
Util::Thread::Lock lock;
bool finished;
};
extern volatile bool done_loading;
// extern Util::Thread::Lock loading_screen_mutex;
/* deprecated, remove */
void startLoadingX(Util::Thread::Id * thread, void * arg = 0, Kind kind = Default);
void stopLoadingX(Util::Thread::Id thread);
void loadScreen(LoadingContext & context, const Level::LevelInfo & info, Kind kind = Default);
void * loadingScreen(void *);
}
#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jun 11, 11:49 AM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68878
Default Alt Text
(31 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline