From 16f624421a464abed84a8b27fc436b1ddcf8af07 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 12 Jun 2019 20:18:27 +0200 Subject: [PATCH] Demos: Import Fire demo contributed by "pd". --- Base/res/icons/16x16/app-demo.png | Bin 0 -> 3401 bytes Demos/Fire/.gitignore | 3 + Demos/Fire/Fire.cpp | 236 ++++++++++++++++++++++++++++++ Demos/Fire/Makefile | 22 +++ Kernel/build-root-filesystem.sh | 1 + Kernel/makeall.sh | 1 + 6 files changed, 263 insertions(+) create mode 100644 Base/res/icons/16x16/app-demo.png create mode 100644 Demos/Fire/.gitignore create mode 100644 Demos/Fire/Fire.cpp create mode 100644 Demos/Fire/Makefile diff --git a/Base/res/icons/16x16/app-demo.png b/Base/res/icons/16x16/app-demo.png new file mode 100644 index 0000000000000000000000000000000000000000..b0e2faffe2f8c67051535a591afae1656df9706c GIT binary patch literal 3401 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#define FIRE_WIDTH 320 +#define FIRE_HEIGHT 168 +#define FIRE_MAX 29 + +const Color palette[] = { + Color(0x07, 0x07, 0x07), Color(0x1F, 0x07, 0x07), Color(0x2F, 0x0F, 0x07), + Color(0x47, 0x0F, 0x07), Color(0x57, 0x17, 0x07), Color(0x67, 0x1F, 0x07), + Color(0x77, 0x1F, 0x07), Color(0x9F, 0x2F, 0x07), Color(0xAF, 0x3F, 0x07), + Color(0xBF, 0x47, 0x07), Color(0xC7, 0x47, 0x07), Color(0xDF, 0x4F, 0x07), + Color(0xDF, 0x57, 0x07), Color(0xD7, 0x5F, 0x07), Color(0xD7, 0x5F, 0x07), + Color(0xD7, 0x67, 0x0F), Color(0xCF, 0x6F, 0x0F), Color(0xCF, 0x7F, 0x0F), + Color(0xCF, 0x87, 0x17), Color(0xC7, 0x87, 0x17), Color(0xC7, 0x8F, 0x17), + Color(0xC7, 0x97, 0x1F), Color(0xBF, 0x9F, 0x1F), Color(0xBF, 0xA7, 0x27), + Color(0xBF, 0xAF, 0x2F), Color(0xB7, 0xAF, 0x2F), Color(0xB7, 0xB7, 0x37), + Color(0xCF, 0xCF, 0x6F), Color(0xEF, 0xEF, 0xC7), Color(0xFF, 0xFF, 0xFF) +}; + +/* Random functions... + * These are from musl libc's prng/rand.c +*/ +static uint64_t seed; + +void my_srand(unsigned s) +{ + seed = s - 1; +} + +static int my_rand(void) +{ + seed = 6364136223846793005ULL * seed + 1; + return seed >> 33; +} + +/* + * Fire Widget +*/ +class Fire : public GWidget { +public: + explicit Fire(GWidget* parent = nullptr); + virtual ~Fire() override; + void set_stat_label(GLabel* l) { stats = l; }; + +private: + RetainPtr bitmap; + GLabel* stats; + + virtual void paint_event(GPaintEvent&) override; + virtual void timer_event(CTimerEvent&) override; + virtual void mousedown_event(GMouseEvent& event) override; + virtual void mousemove_event(GMouseEvent& event) override; + virtual void mouseup_event(GMouseEvent& event) override; + + bool dragging; + int timeAvg; + int cycles; + int phase; +}; + +Fire::Fire(GWidget* parent) + : GWidget(parent) +{ + bitmap = GraphicsBitmap::create(GraphicsBitmap::Format::Indexed8, { 320, 200 }); + + /* Initialize fire palette */ + for (int i = 0; i < 30; i++) + bitmap->set_palette_color(i, palette[i]); + + /* Set remaining entries to white */ + for (int i = 30; i < 256; i++) + bitmap->set_palette_color(i, Color::White); + + dragging = false; + timeAvg = 0; + cycles = 0; + phase = 0; + + my_srand(time(nullptr)); + stop_timer(); + start_timer(20); + + /* Draw fire "source" on bottom row of pixels */ + for (int i = 0; i < FIRE_WIDTH; i++) + bitmap->bits(bitmap->height() - 1)[i] = FIRE_MAX; + + /* Set off initital paint event */ + //update(); +} + +Fire::~Fire() +{ +} + +void Fire::paint_event(GPaintEvent& event) +{ + CElapsedTimer timer; + timer.start(); + + GPainter painter(*this); + painter.add_clip_rect(event.rect()); + + /* Blit it! */ + painter.draw_scaled_bitmap(event.rect(), *bitmap, bitmap->rect()); + + timeAvg += timer.elapsed(); + cycles++; +} + +void Fire::timer_event(CTimerEvent&) +{ + /* Update only even or odd columns per frame... */ + phase++; + if (phase > 1) + phase = 0; + + /* Paint our palettized buffer to screen */ + for (int px = 0 + phase; px < FIRE_WIDTH; px += 2) { + for (int py = 1; py < 200; py++) { + int rnd = my_rand() % 3; + + /* Calculate new pixel value, don't go below 0 */ + byte nv = bitmap->bits(py)[px]; + if (nv > 0) + nv -= (rnd & 1); + + /* ...sigh... */ + int epx = px + (1 - rnd); + if (epx < 0) + epx = 0; + else if (epx > FIRE_WIDTH) + epx = FIRE_WIDTH; + + bitmap->bits(py - 1)[epx] = nv; + } + } + + if ((cycles % 50) == 0) { + dbgprintf("%d total cycles. finished 50 in %d ms, avg %d ms\n", cycles, timeAvg, timeAvg / 50); + stats->set_text(String::format("%d ms", timeAvg / 50)); + timeAvg = 0; + } + + update(); +} + +/* + * Mouse handling events +*/ +void Fire::mousedown_event(GMouseEvent& event) +{ + if (event.button() == GMouseButton::Left) + dragging = true; + + return GWidget::mousedown_event(event); +} + +/* FIXME: needs to account for the size of the window rect */ +void Fire::mousemove_event(GMouseEvent& event) +{ + if (dragging) { + if (event.y() >= 2 && event.y() < 398 && event.x() <= 638) { + int ypos = event.y() / 2; + int xpos = event.x() / 2; + bitmap->bits(ypos - 1)[xpos] = FIRE_MAX + 5; + bitmap->bits(ypos - 1)[xpos + 1] = FIRE_MAX + 5; + bitmap->bits(ypos)[xpos] = FIRE_MAX + 5; + bitmap->bits(ypos)[xpos + 1] = FIRE_MAX + 5; + } + } + + return GWidget::mousemove_event(event); +} + +void Fire::mouseup_event(GMouseEvent& event) +{ + if (event.button() == GMouseButton::Left) + dragging = false; + + return GWidget::mouseup_event(event); +} + +/* + * Main +*/ +int main(int argc, char** argv) +{ + GApplication app(argc, argv); + + auto* window = new GWindow; + window->set_should_exit_event_loop_on_close(true); + window->set_double_buffering_enabled(false); + window->set_title("Fire"); + window->set_resizable(false); + window->set_rect(100, 100, 640, 400); + + auto* fire = new Fire; + window->set_main_widget(fire); + + auto* time = new GLabel(fire); + time->set_relative_rect({ 0, 4, 40, 10 }); + time->move_by({ window->width() - time->width(), 0 }); + time->set_foreground_color(Color::from_rgb(0x444444)); + fire->set_stat_label(time); + + window->show(); + window->set_icon_path("/res/icons/16x16/app-demo.png"); + + return app.exec(); +} diff --git a/Demos/Fire/Makefile b/Demos/Fire/Makefile new file mode 100644 index 0000000000..2bfd381499 --- /dev/null +++ b/Demos/Fire/Makefile @@ -0,0 +1,22 @@ +include ../../Makefile.common + +OBJS = \ + Fire.o + +APP = Fire + +DEFINES += -DUSERLAND + +all: $(APP) + +$(APP): $(OBJS) + $(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lgui -lcore -lc + +.cpp.o: + @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< + +-include $(OBJS:%.o=%.d) + +clean: + @echo "CLEAN"; rm -f $(APP) $(OBJS) *.d + diff --git a/Kernel/build-root-filesystem.sh b/Kernel/build-root-filesystem.sh index 2b63035fb2..8ffa9fe642 100755 --- a/Kernel/build-root-filesystem.sh +++ b/Kernel/build-root-filesystem.sh @@ -75,6 +75,7 @@ cp ../Applications/PaintBrush/PaintBrush mnt/bin/PaintBrush cp ../Demos/HelloWorld/HelloWorld mnt/bin/HelloWorld cp ../Demos/RetroFetch/RetroFetch mnt/bin/RetroFetch cp ../Demos/WidgetGallery/WidgetGallery mnt/bin/WidgetGallery +cp ../Demos/Fire/Fire mnt/bin/Fire cp ../DevTools/VisualBuilder/VisualBuilder mnt/bin/VisualBuilder cp ../Games/Minesweeper/Minesweeper mnt/bin/Minesweeper cp ../Games/Snake/Snake mnt/bin/Snake diff --git a/Kernel/makeall.sh b/Kernel/makeall.sh index fec59e291a..9b04f3339f 100755 --- a/Kernel/makeall.sh +++ b/Kernel/makeall.sh @@ -36,6 +36,7 @@ build_targets="$build_targets ../Shell" build_targets="$build_targets ../Demos/HelloWorld" build_targets="$build_targets ../Demos/RetroFetch" build_targets="$build_targets ../Demos/WidgetGallery" +build_targets="$build_targets ../Demos/Fire" build_targets="$build_targets ." # the kernel for targ in $build_targets; do