summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/blocks.cxx253
1 files changed, 139 insertions, 114 deletions
diff --git a/test/blocks.cxx b/test/blocks.cxx
index f0359e0cf..75a964f02 100644
--- a/test/blocks.cxx
+++ b/test/blocks.cxx
@@ -3,7 +3,7 @@
//
// "Block Attack!" scrolling blocks game using the Fast Light Tool Kit (FLTK).
//
-// Copyright 2006-2010 by Michael Sweet.
+// Copyright 2006-2017 by Michael Sweet.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -42,7 +42,7 @@
#ifndef WIN32
# include <unistd.h>
-# include <sys/time.h>
+# include <sys/time.h> // gettimeofday()
#endif // !WIN32
#ifdef HAVE_ALSA_ASOUNDLIB_H
@@ -56,6 +56,7 @@
# include <mmsystem.h>
#endif // WIN32
+#define DEBUG_TIMER 0 // 0 = do not ..., 1 = debug timer callback
#define BLOCK_COLS 20
#define BLOCK_ROWS 10
@@ -355,14 +356,13 @@ BlockSound::~BlockSound() {
#ifdef __APPLE__
// Callback function for writing audio data...
-OSStatus
-BlockSound::audio_cb(AudioDeviceID device,
- const AudioTimeStamp *current_time,
- const AudioBufferList *data_in,
- const AudioTimeStamp *time_in,
- AudioBufferList *data_out,
- const AudioTimeStamp *time_out,
- void *client_data) {
+OSStatus BlockSound::audio_cb(AudioDeviceID device,
+ const AudioTimeStamp *current_time,
+ const AudioBufferList *data_in,
+ const AudioTimeStamp *time_in,
+ AudioBufferList *data_out,
+ const AudioTimeStamp *time_out,
+ void *client_data) {
BlockSound *ss = (BlockSound *)client_data;
int count;
float *buffer;
@@ -387,8 +387,7 @@ BlockSound::audio_cb(AudioDeviceID device,
// Play a note for the given amount of time...
-void
-BlockSound::play_explosion(float duration) {
+void BlockSound::play_explosion(float duration) {
Fl::check();
if (duration <= 0.0)
@@ -415,7 +414,8 @@ BlockSound::play_explosion(float duration) {
waveOutPrepareHeader(device, header_ptr, sizeof(WAVEHDR));
waveOutWrite(device, header_ptr, sizeof(WAVEHDR));
- } else Beep(440, (int)(1000.0 * duration));
+ } else
+ Beep(440, (int)(1000.0 * duration));
#elif defined(HAVE_ALSA_ASOUNDLIB_H)
if (handle) {
@@ -430,19 +430,16 @@ BlockSound::play_explosion(float duration) {
}
-class BlockWindow : public Fl_Double_Window
-{
+class BlockWindow : public Fl_Double_Window {
public:
- struct Block
- {
+ struct Block {
int color;
bool bomb;
int y;
};
- struct Column
- {
+ struct Column {
int num_blocks;
Block blocks[BLOCK_ROWS];
int x;
@@ -494,8 +491,7 @@ class BlockWindow : public Fl_Double_Window
Fl_Preferences BlockWindow::prefs_(Fl_Preferences::USER, "fltk.org", "blocks");
-int
-main(int argc, char *argv[]) {
+int main(int argc, char *argv[]) {
Fl::scheme("plastic");
Fl::visible_focus(0);
@@ -530,8 +526,7 @@ BlockWindow::~BlockWindow() {
// Initialize a block window...
-void
-BlockWindow::_BlockWindow() {
+void BlockWindow::_BlockWindow() {
init();
help_button_ = new Fl_Button(0, 0, 20, 20, "?");
@@ -552,8 +547,7 @@ BlockWindow::_BlockWindow() {
// Bomb all blocks of a given color and return the number of affected blocks
-int
-BlockWindow::bomb(int color) {
+int BlockWindow::bomb(int color) {
int j, k;
int count;
Block *b;
@@ -575,8 +569,7 @@ BlockWindow::bomb(int color) {
// Tag all blocks connected to the clicked block and return the number
// of affected blocks
-int
-BlockWindow::click(int col, int row) {
+int BlockWindow::click(int col, int row) {
Block *b;
Column *c;
int count, color;
@@ -619,8 +612,7 @@ BlockWindow::click(int col, int row) {
// Draw the block window...
-void
-BlockWindow::draw() {
+void BlockWindow::draw() {
int j, k, xx, yy;
Block *b;
Column *c;
@@ -680,8 +672,7 @@ BlockWindow::draw() {
// Show sample waveform...
short *sample_ptr;
- for (i = 0; i < 2; i ++)
- {
+ for (i = 0; i < 2; i++) {
fl_color(FL_RED + i);
fl_begin_line();
for (j = 0, sample_ptr = sound_->sample_data + i;
@@ -693,9 +684,12 @@ BlockWindow::draw() {
}
#endif // DEBUG
- if (num_columns_ && (time(NULL) & 7) < 4) s = "Game Over";
- else s = "Block Attack!\nby Michael R Sweet";
- } else s = "Paused";
+ if (num_columns_ && (time(NULL) & 7) < 4)
+ s = "Game Over";
+ else
+ s = "Block Attack!\nby Michael R Sweet";
+ } else
+ s = "Paused";
fl_font(FL_HELVETICA_BOLD, 32);
fl_color(FL_BLACK);
@@ -717,14 +711,12 @@ BlockWindow::draw() {
sprintf(s, "High Score: %d ", high_score_);
fl_draw(s, 0, 0, w(), 20, FL_ALIGN_RIGHT);
- if (level_ > 1 || title_y_ <= 0)
- {
+ if (level_ > 1 || title_y_ <= 0) {
sprintf(s, "Level: %d ", level_);
fl_draw(s, 0, 0, w(), 20, FL_ALIGN_CENTER);
}
- if (title_y_ > 0 && interval_ > 0.0)
- {
+ if (title_y_ > 0 && interval_ > 0.0) {
int sz = 14 + title_y_ * 86 / h();
fl_font(FL_HELVETICA_BOLD, sz);
@@ -735,8 +727,7 @@ BlockWindow::draw() {
// Handle mouse clicks, etc.
-int
-BlockWindow::handle(int event) {
+int BlockWindow::handle(int event) {
int j, k, mx, my, count;
Block *b;
Column *c;
@@ -746,57 +737,61 @@ BlockWindow::handle(int event) {
else if (interval_ < 0.0 || paused_) return (0);
switch (event) {
+
case FL_KEYBOARD:
- if (Fl::event_text()) {
- if (strcmp(Fl::event_text(), "+") == 0)
- up_level();
- }
- break;
- case FL_PUSH :
- mx = w() - Fl::event_x() + BLOCK_SIZE;
- my = h() - Fl::event_y();
- count = 0;
- b = 0;
-
- for (j = 0, c = columns_; !count && j < num_columns_; j ++, c ++)
- for (k = 0, b = c->blocks; !count && k < c->num_blocks; k ++, b ++)
- if (mx >= c->x && mx < (c->x + BLOCK_SIZE) &&
- my >= b->y && my < (b->y + BLOCK_SIZE)) {
- if (b->bomb) count = bomb(b->color);
- else count = click(j, k);
-
- break;
- }
-
- if (count < 2) {
- for (j = 0, c = columns_; j < num_columns_; j ++, c ++)
- for (k = 0, b = c->blocks; k < c->num_blocks; k ++, b ++)
- if (b->color < 0) b->color = -b->color;
- } else {
- count --;
+ if (Fl::event_text()) {
+ if (strcmp(Fl::event_text(), "+") == 0)
+ up_level();
+ }
+ break;
+
+ case FL_PUSH:
+ mx = w() - Fl::event_x() + BLOCK_SIZE;
+ my = h() - Fl::event_y();
+ count = 0;
+ b = 0;
+
+ for (j = 0, c = columns_; !count && j < num_columns_; j ++, c ++)
+ for (k = 0, b = c->blocks; !count && k < c->num_blocks; k ++, b ++)
+ if (mx >= c->x && mx < (c->x + BLOCK_SIZE) &&
+ my >= b->y && my < (b->y + BLOCK_SIZE)) {
+ if (b->bomb) count = bomb(b->color);
+ else count = click(j, k);
+ break;
+ }
- if (b->bomb) {
- sound_->play_explosion(0.19 + 0.005 * count);
+ if (count < 2) {
+ for (j = 0, c = columns_; j < num_columns_; j ++, c ++)
+ for (k = 0, b = c->blocks; k < c->num_blocks; k ++, b ++)
+ if (b->color < 0) b->color = -b->color;
+ } else {
+ count --;
- interval_ *= 0.995;
- score_ += count;
- } else {
- sound_->play_explosion(0.09 + 0.005 * count);
+ if (b->bomb) {
+ sound_->play_explosion(0.19 + 0.005 * count);
- interval_ *= 0.999;
- score_ += count * count;
- }
+ interval_ *= 0.995;
+ score_ += count;
+ } else {
+ sound_->play_explosion(0.09 + 0.005 * count);
- if (score_ > high_score_) {
- high_score_ = score_;
- prefs_.set("high_score", high_score_);
- }
+ interval_ *= 0.999;
+ score_ += count * count;
+ }
- for (j = 0, c = columns_; j < num_columns_; j ++, c ++)
- for (k = 0, b = c->blocks; k < c->num_blocks; k ++, b ++)
- if (b->color < 0) b->color = BLOCK_BLAST;
+ if (score_ > high_score_) {
+ high_score_ = score_;
+ prefs_.set("high_score", high_score_);
}
- return (1);
+
+ for (j = 0, c = columns_; j < num_columns_; j ++, c ++)
+ for (k = 0, b = c->blocks; k < c->num_blocks; k ++, b ++)
+ if (b->color < 0) b->color = BLOCK_BLAST;
+ }
+ return (1);
+
+ default:
+ break;
}
return (0);
@@ -804,8 +799,7 @@ BlockWindow::handle(int event) {
// Toggle the on-line help...
-void
-BlockWindow::help_cb(Fl_Widget *, BlockWindow *bw) {
+void BlockWindow::help_cb(Fl_Widget *, BlockWindow *bw) {
bw->paused_ = bw->help_ = !bw->help_;
bw->play_button_->label("@>");
bw->redraw();
@@ -813,8 +807,7 @@ BlockWindow::help_cb(Fl_Widget *, BlockWindow *bw) {
// Initialize the block window...
-void
-BlockWindow::init() {
+void BlockWindow::init() {
count_ = 0;
help_ = false;
interval_ = -1.0;
@@ -829,8 +822,7 @@ BlockWindow::init() {
// Start a new game...
-void
-BlockWindow::new_game() {
+void BlockWindow::new_game() {
// Seed the random number generator...
srand(time(NULL));
@@ -847,8 +839,7 @@ BlockWindow::new_game() {
// Play/pause...
-void
-BlockWindow::play_cb(Fl_Widget *wi, BlockWindow *bw) {
+void BlockWindow::play_cb(Fl_Widget *wi, BlockWindow *bw) {
if (bw->interval_ < 0) bw->new_game();
else bw->paused_ = !bw->paused_;
@@ -870,26 +861,66 @@ void BlockWindow::up_level() {
}
// Animate the game...
-void
-BlockWindow::timeout_cb(BlockWindow *bw) {
+void BlockWindow::timeout_cb(BlockWindow *bw) {
int i, j;
Block *b;
Column *c;
int lastx, lasty;
+#if DEBUG_TIMER
+ static double lasttime;
+ static double delta_sum;
+ static double interval;
+ double curtime;
+ static int ntime = 0;
+ static int level = 0;
-#ifdef DEBUG
- struct timeval curtime;
- static struct timeval lasttime;
-
+#if !defined(WIN32)
+ {
+ struct timeval atime;
+ gettimeofday(&atime, NULL);
+ curtime = atime.tv_sec % 60 + 0.000001 * atime.tv_usec;
+ }
+#else // (WIN32)
+ {
+ SYSTEMTIME atime;
+ GetLocalTime(&atime);
+ curtime = atime.wSecond + 0.001 * atime.wMilliseconds;
+ }
+#endif // (WIN32)
+
+ // platform independent part of timer debugging code
+ if (bw->interval_ > 0) { // game is active
+ if (bw->level_ != level) {
+ if (ntime > 0) {
+ printf("*** average delta time = %9.6f, n =%4d, level %d, interval %f\n",
+ delta_sum / ntime, ntime, level, interval);
+ fflush(stdout);
+ }
+ delta_sum = 0; // reset average
+ ntime = 0;
+ interval = bw->interval_;
+ }
- gettimeofday(&curtime, NULL);
- printf("%.3f (%+f - %f)\n",
- curtime.tv_sec + 0.000001 * curtime.tv_usec,
- curtime.tv_sec - lasttime.tv_sec +
- 0.000001 * (curtime.tv_usec - lasttime.tv_usec), bw->interval_);
+ double delta = curtime - lasttime;
+ if (delta < 0)
+ delta += 60;
+
+ printf("%9.6f (%+f - %f = %9.6f), level: %d\n",
+ curtime, delta, interval, delta - interval, level);
+ fflush(stdout);
+
+ interval = bw->interval_;
+ level = bw->level_;
+ delta = delta - interval;
+ delta_sum += delta > 0 ? delta : -delta; // abs(delta)
+ ntime++;
+ } else { // waiting ...
+ // printf("[OFF] %6.2f\n", curtime);
+ // fflush(stdout);
+ }
lasttime = curtime;
-#endif // DEBUG
+#endif // DEBUG_TIMER
// Update blocks that have been destroyed...
for (i = 0, c = bw->columns_; i < bw->num_columns_; i ++, c ++)
@@ -920,9 +951,7 @@ BlockWindow::timeout_cb(BlockWindow *bw) {
}
// Let the rest of the blocks fall and/or move...
- for (i = bw->num_columns_, c = bw->columns_, lastx = c->x;
- i > 0;
- i --, c ++) {
+ for (i = bw->num_columns_, c = bw->columns_, lastx = c->x; i > 0; i--, c++) {
if (c->x > lastx) {
c->x -= 8;
bw->redraw();
@@ -987,9 +1016,7 @@ BlockWindow::timeout_cb(BlockWindow *bw) {
}
}
}
- }
- else
- {
+ } else {
bw->count_ --;
if (bw->count_ <= 0) {
@@ -1016,11 +1043,9 @@ BlockWindow::timeout_cb(BlockWindow *bw) {
}
if (bw->interval_ > 0.0) {
- Fl::repeat_timeout(bw->interval_, (Fl_Timeout_Handler)timeout_cb,
- (void *)bw);
+ Fl::repeat_timeout(bw->interval_, (Fl_Timeout_Handler)timeout_cb, (void *)bw);
} else {
- Fl::repeat_timeout(0.1, (Fl_Timeout_Handler)timeout_cb,
- (void *)bw);
+ Fl::repeat_timeout(0.1, (Fl_Timeout_Handler)timeout_cb, (void *)bw);
}
}