# Galaxy Shooter [Unity & WebGL]

My first from game to deployment Unity project! >>> PLAY NOW <<<

Hi guys, I have been playing around and following some tutorials with Unity which truly is great fun and a fantastic way of learning to code in a playful way. Of course the game I have been developing following the Udemy tutorial by Jonathan Weinberger is very simple, but it was critical to see how the whole process could look like, from the idea of the game, asset management, programming the game, post-processing and building the game with WebGL and finally hosting it on GitHub (which I added, because I wanted to share the game with friends). So now I know how to go through this steps and am ready to look into adding complexity along the way.

In case you want to test play the game, here you go! I know its not perfect, and there is room for improvement, but the excitement holds up for at least 30 seconds (yay!).

# visual graphing program [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 10
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

```Output:

```
```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 16 Exercise 10

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include "std_lib_facilities.h"
#include <functional>

// layout
constexpr int xmax = 600;
constexpr int ymax = 600;

constexpr int x_orig = xmax / 2;
constexpr int y_orig = ymax / 2;
Point orig(x_orig, y_orig);

constexpr int r_min = -10;
constexpr int r_max = 10;

constexpr int n_points = 40;

constexpr int x_scale = 20;
constexpr int y_scale = 20;

// layout
constexpr int xoffset = 100;
constexpr int yoffset = 100;

constexpr int xspace = 100;
constexpr int yspace = 100;

constexpr int xlength = xmax - xoffset - xspace;
constexpr int ylength = ymax - yoffset - yspace;

typedef double Fcti(double);

double mysin(double x) { return sin(x); }
double mycos(double x) { return cos(x); }

template <class T> class myFct : public Shape {
public:
myFct(Fcti* f, double r1, double r2, Point orig, int count = 100, double xscale = 25, double yscale = 25, T precision = 1.0);
~myFct() {}

void set_f(Fcti* p) { f = p; }
void set_r1(double r) { r1 = r; }
void set_r2(double r) { r2 = r; }
void set_orig(Point o) { orig = o; }
void set_count(int c) { count = c; }
void set_xscale(double x) { xscale = x; }
void set_yscale(double y) { yscale = y; }
void set_precision(T p) { precision = p; }

double get_r1() { return r1; }
double get_r2() { return r2; }
Point get_orig() { return orig; }
int get_count() { return count; }
double get_xscale() { return xscale; }
double get_yscale() { return yscale; }
T get_precision() { return precision; }

void calc();
void reset(Fcti* f, double r1, double r2, Point orig, int count = 100, double xscale = 25, double yscale = 25, T precision = 1.0);

private:
Fcti* f;
double r1;
double r2;
Point orig;
int count;
double xscale;
double yscale;
T precision;
};

template <class T> myFct<T>::myFct(Fcti* f, double r1, double r2, Point orig, int count, double xscale, double yscale, T precision)
:f(f), r1(r1), r2(r2), orig(orig), count(count), xscale(xscale), yscale(yscale), precision(precision)
{
calc();
}

template <class T> void myFct<T>::calc()
{
if (r2 - r1 <= 0) error("bad graphing range");
if (count <= 0) error("non-positive graphing count");
double dist = (r2 - r1) / count;
double r = r1;

// to the protected section of the Shape class - annoying
clear_points();

for (int i = 0; i < count; ++i) {
int x = orig.x + int(int(r * xscale) / precision) * precision;
int y = orig.y - int(int(f(r) * yscale) / precision) * precision;
r += dist;
}
}

template <class T> void myFct<T>::reset(Fcti* f, double r1, double r2, Point orig, int count, double xscale, double yscale, T precision)
{
set_f(f);
set_r1(r1);
set_r2(r2);
set_orig(orig);
set_count(count);
set_xscale(xscale);
set_yscale(yscale);
set_precision(precision);

calc();
}

// ------------------------------ GRAPHING END-------------------------

struct application_window : Window {
enum graph_enum
{
sin_g, cos_g
};

application_window(Point xy, int w, int h, const string& title);

void draw_graph();

private:

//------------- LAYOUT

// quit button
Button quit_button;

// convert button
Button graph_button;

// graph type button;
Button graph_type;

// in
In_box x_parameter;
Out_box base_equation;
Out_box equation;

//
graph_enum g_type;

// axis
Axis x_axis;
Axis y_axis;

// function
myFct<double> funct;

//double x_manipulation(double x, int m) { return x * m; }
double my_sin(double x) { return sin(x); }
double my_cos(double x) { return cos(x); }

// actions invoked by callbacks
void quit() { hide(); }

void sin_graph();
void cos_graph();

// callback functions

//------------- LAYOUT END
};

application_window::application_window(Point xy, int w, int h, const string& title)
: Window(xy, w, h, title)
, quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
, graph_button(Point(x_max() - 70, 20), 70, 20, "Graph", cb_calculate)
, graph_type(Point(20, 0), 100, 20, "Graph Type", cb_graph_type_menu_pressed)
, base_equation(Point(x_max() / 2, 0), 90, 20, "equation")
, x_parameter(Point(100, 40), 20, 20, "t-paramter")
, equation(Point(x_max() / 2, 40), 90, 20, "equation")
, x_axis(Axis::x, Point(orig.x - 200, orig.y), 400, 20, "1 == 20")
, y_axis(Axis::y, Point(orig.x, orig.y + 200), 400, 20, "1 == 20")
, funct(mysin, r_min, r_max, orig, n_points, x_scale, y_scale)
{
attach(quit_button);
attach(graph_button);
attach(graph_type);
attach(base_equation);
attach(x_parameter);
attach(equation);

graph_type_menu.attach(new Button(Point(0, 0), 0, 0, "sin", cb_sin_graph));
graph_type_menu.attach(new Button(Point(0, 0), 0, 0, "cos", cb_cos_graph));

x_axis.set_color(Color::black);
y_axis.set_color(Color::black);
attach(x_axis);
attach(y_axis);

funct.set_color(FL_BLACK);
attach(funct);
funct.set_color(Color::invisible);

}

void application_window::sin_graph()
{
graph_type.show();

base_equation.put("y = sin(x) * t");
g_type = sin_g;
}

void application_window::cos_graph()
{
graph_type.show();

base_equation.put("y = cos(x) * t");
g_type = cos_g;
}

void application_window::draw_graph()
{
// GRAPHS
if(g_type == sin_g)
{
equation.put("y = sin(x) * " + x_parameter.get_string());

// most painful lambda to function pointer work-around ever.
// saved the day:
// https://deviorel.wordpress.com/2015/01/27/obtaining-function-pointers-from-lambdas-in-c/

int t = x_parameter.get_int();
auto la = [=](double x) { return sin(x) * t; };

static function< double(double) > static_variable;
static_variable = la;
double(*ptr)(double) = [](double x) { return static_variable(x); };

funct.reset(
[](double x) { return static_variable(x); }
, r_min
, r_max
, orig
, n_points
, x_scale
, y_scale
);

}
if(g_type == cos_g)
{
equation.put("y = cos(x) * " + x_parameter.get_string());

int t = x_parameter.get_int();
auto la = [=](double x) { return cos(x) * t; };

static function< double(double) > static_variable;
static_variable = la;
double(*ptr)(double) = [](double x) { return static_variable(x); };

funct.reset(
[](double x) { return static_variable(x); }
, r_min
, r_max
, orig
, n_points
, x_scale
, y_scale
);
}

funct.set_color(Color::visible);
redraw();
}

// ------------------------------ INTERFACE END-------------------------

int main()
try {
application_window win(Point(100, 100), xmax, ymax + 20, "currency converter");

return gui_main();
}
catch (exception& e) {
cerr << "exception: " << e.what() << endl;
char c;
while (cin >> c&& c != ';');
return 1;
}
catch (...) {
cerr << "exception\n";
char c;
while (cin >> c && c != ';');
return 2;
}
```

# visual calculator [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 9
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

```Output:

```
```//	Philipp Siedler
//	Bjarne Stroustrup's PP
//	Chapter 16 Exercise 9

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include "std_lib_facilities.h"

// ------------------------------ CALCULATOR ---------------------------

const char let = '#';
const char quitProg = 'Q';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sqroot = 'S';
const char power = 'P';
const char constant = 'C';
const char reset = 'R';
const char help = 'H';

struct Token {
char kind;
double value;
string name;
Token(char ch) :kind(ch), value(0) { }
Token(char ch, double val) :kind(ch), value(val) { }
Token(char ch, string val) :kind(ch), name(val) { }
};

class Token_stream {
bool full;
Token buffer;
;
public:
Token_stream() :full(0), buffer(0) { }
Token get(stringstream& ist);
void unget(Token t) { buffer = t; full = true; }
void ignore(char);
};

Token Token_stream::get(stringstream& ist)
{
/*
if (full) {
full = false;
return buffer;
}

char ch;
ist >> ch;
*/

if (full) {
full = false; return buffer;
}
char ch;
ist.get(ch);

while (isspace(ch)) {
if (ch == '\n') return Token(print); // if newline detected, return print Token
ist.get(ch);
}

switch (ch) {
case '(':
case ')':
case '+':
case '-':
case '*':
case '/':
case '%':
case ';':
case '=':
case 'k':
case ',':
{
}
case '#':
{
}
case '.':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
ist.unget();
double val;
ist >> val;
}
default:
{
if (isalpha(ch) || ch == '_') { //is ch a letter?
string s;
s += ch;
while (ist.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) { //reads chars, strings or digits
s += ch;
}
ist.unget(); //puts the most recently read character back into the stream
}
}
}
}

void Token_stream::ignore(char c)
{
if (full && c == buffer.kind) {
full = false;
return;
}
full = false;
char ch;
while (cin >> ch) {
if (ch == c) return;
}
}

struct Variable {
string name;
double value;
bool immutable;
Variable(string n, double v, bool i) :name(n), value(v), immutable(i) { }
};

class Symbol_table {
public:
vector<Variable> var_table;
double get(string);
void set(string, double);
bool is_declared(string);
double declare(char, stringstream& ist);
bool is_immutable(string);
};

Token_stream ts;
double expression(stringstream& ist);
double primary(stringstream& ist);

double Symbol_table::get(string s)
{
for (int i = 0; i < var_table.size(); ++i) {
if (var_table[i].name == s) {
return var_table[i].value;
}
}
error("get: undefined name ", s);
return 0.0;
}

void Symbol_table::set(string s, double d)
{
for (int i = 0; i <= var_table.size(); ++i) {
if (var_table[i].name == s) {
var_table[i].value = d;
return;
}
}
error("set: undefined name ", s);
}

bool Symbol_table::is_declared(string s)
{
for (int i = 0; i < var_table.size(); ++i) {
if (var_table[i].name == s) return true;
}
return false;
}

double Symbol_table::declare(char kind, stringstream& ist)
{
Token t = ts.get(ist);
if (t.kind != name) {
error("name expected in declaration");
}

string name = t.name;
if (kind == let || kind == constant) {
if (is_declared(name)) error(name, " declared twice");
}
else if (kind == reset) {
if (!is_declared(name))
error(name, " has not been declared");
if (is_immutable(name))
error(name, " is a constant");
}
else {
error("unknown statement");
}

Token t2 = ts.get(ist);
if (t2.kind != '=') error("= missing in declaration of ", name);
double d = expression(ist);
if (is_declared(name))
set(name, d);
else
var_table.push_back(Variable(name, d, (kind == constant)));
return d;
}

bool Symbol_table::is_immutable(string s)
{
for (int i = 0; i<int(var_table.size()); ++i)
if (var_table[i].name == s && var_table[i].immutable) return true;
return false;
}

double pow_function(Token _t, stringstream& ist) {
_t = ts.get(ist);
if (_t.kind != '(') {
error("'(' expected");
}

double x = expression(ist);

_t = ts.get(ist);
if (_t.kind != ',') {
error("',' expected");
}

double n = expression(ist);
_t = ts.get(ist);
if (_t.kind == ')') {
return pow(x, n);
}
else {
error("Expected ')'");
}
}

double sqrt_function(Token _t, stringstream& ist) {
_t = ts.get(ist);
if (_t.kind != '(') {
error("'(' expected");
}
ts.unget(_t);
double d = primary(ist);
if (d < 0.0) {
error("negative square root");
}
return sqrt(d);
}

Symbol_table st;

double primary(stringstream& ist)
{
Token t = ts.get(ist);
switch (t.kind) {
case '(':
{
double d = expression(ist);
t = ts.get(ist);
if (t.kind != ')') error("')' expected");
return d;
}
case '-':
{
return -primary(ist);
}
case '+':
{
return primary(ist);
}
case number:
{
return t.value;
}
case sqroot:
{
return sqrt_function(t, ist);
}
case power:
{
return pow_function(t, ist);
}
case name:
{
return st.get(t.name);
}
default:
{
error("primary expected");
return 0.0;
}
}
}

double term(stringstream& ist)
{
double left = primary(ist);
while (true) {
Token t = ts.get(ist);
switch (t.kind) {
case 'k':
{
left *= 1000;
break;
}
case '*':
{
left *= primary(ist);
break;
}
case '/':
{
double d = primary(ist);
if (d == 0) error("divide by zero");
left /= d;
break;
}
case '%':
{
int i1 = narrow_cast<int>(left);
int i2 = narrow_cast<int>(primary(ist));
if (i2 == 0) error("%: divide by zero");
left = i1%i2;
break;
}

default: {
ts.unget(t);
return left;
}
}
}
}

double expression(stringstream& ist)
{
double left = term(ist);
while (true) {
Token t = ts.get(ist);
switch (t.kind) {
case '+':
{
left += term(ist);
break;
}
case '-':
{
left -= term(ist);
break;
}
default:
{
ts.unget(t);
return left;
}
}
}
}

double statement(stringstream& ist)
{
Token t = ts.get(ist);
double d;
if (t.kind == let || t.kind == reset || t.kind == constant) {
d = st.declare(t.kind, ist);
}
else {
ts.unget(t);
d = expression(ist);
}
t = ts.get(ist);
if (t.kind != print) {
error("Missing terminator");
}

return d;
}

void clean_up_mess()
{
ts.ignore(print);
}

static void calculate(stringstream& ist, ostringstream& ost)
{
while (ist) try {
Token t = ts.get(ist);
ts.unget(t);
ost << statement(ist);
break;
}
catch (runtime_error& e) {
ost << e.what() << endl;
clean_up_mess();
}
}

// ------------------------------ CALCULATOR END------------------------

// ------------------------------ INTERFACE ----------------------------

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

struct application_window : Window {
application_window(Point xy, int w, int h, const string& title);

private:

//------------- LAYOUT

// quit button
Button quit_button;

// convert button
Button calculate_button;

// in
In_box value_in;
Out_box value_out;

// actions invoked by callbacks
void quit() { hide(); }
void cal();

// callback functions

//------------- LAYOUT END
};

application_window::application_window(Point xy, int w, int h, const string& title)
: Window(xy, w, h, title)
, quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
, calculate_button(Point(x_max() - 70, 20), 70, 20, "Calculate", cb_calculate)
, value_in(Point(70, 60), 70, 20, "equation")
, value_out(Point(x_max() / 2, 60), 70, 20, "solution")
{
attach(quit_button);
attach(calculate_button);
attach(value_in);
attach(value_out);
}

void application_window::cal()
{
ostringstream os;
stringstream ss;
ss.str(value_in.get_string() + ";");

calculate(ss, os);

string s(os.str());
value_out.put(s);
}

// ------------------------------ INTERFACE END-------------------------

int main()
try {
application_window win(Point(100, 100), xmax, ymax + 20, "currency converter");
return gui_main();
}
catch (exception& e) {
cerr << "exception: " << e.what() << endl;
char c;
while (cin >> c&& c != ';');
return 1;
}
catch (...) {
cerr << "exception\n";
char c;
while (cin >> c && c != ';');
return 2;
}
```

# visual currency converter [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 8
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

```Output:

```
```//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 8

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include <time.h>

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

enum currencies
{
euro = 0, pound
};

struct application_window : Window {
application_window(Point xy, int w, int h, const string& title, const string& conversion_rate_file_location);

private:

//------------- DATA

currencies from;
currencies to;

// data
float conversion_rate;

// methods
float get_conversion(const string& crfl);

//------------- DATA END

//------------- LAYOUT

// quit button
Button quit_button;

// convert button
Button convert_button;

// in
In_box value_in;
Out_box value_out;
Out_box value_in_currency;
Out_box value_out_currency;

// actions invoked by callbacks
void quit() { hide(); }

void convert();

void from_euro_pressed() { hide_from_menu(); value_in_currency.put("euro"); from = euro; }
void from_pound_pressed() { hide_from_menu(); value_in_currency.put("pound"); from = pound; }

void to_euro_pressed() { hide_to_menu(); value_out_currency.put("euro"); to = euro; }
void to_pound_pressed() { hide_to_menu(); value_out_currency.put("pound"); to = pound; }

// callback functions

//------------- LAYOUT END
};

application_window::application_window(Point xy, int w, int h, const string& title, const string& conversion_rate_file_location)
: Window(xy, w, h, title)
, quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
, convert_button(Point(x_max() - 70, 20), 70, 20, "Convert", cb_convert)
, value_in(Point(0, 60), 70, 20, "enter value")
, value_out(Point(x_max() / 2, 60), 70, 20, "")
, value_in_currency(Point(70, 60), 70, 20, "")
, value_out_currency(Point(x_max() / 2 + 70, 60), 70, 20, "")
{
conversion_rate = get_conversion(conversion_rate_file_location);

from = euro;
to = euro;

attach(quit_button);
attach(convert_button);

attach(value_in);
attach(value_out);

attach(value_in_currency);
attach(value_out_currency);

value_in_currency.put("euro");
value_out_currency.put("euro");

from_menu.attach(new Button(Point(0, 0), 0, 0, "euro", cb_from_euro));
from_menu.attach(new Button(Point(0, 0), 0, 0, "pound", cb_from_pound));

to_menu.attach(new Button(Point(0, 0), 0, 0, "euro", cb_to_euro));
to_menu.attach(new Button(Point(0, 0), 0, 0, "pound", cb_to_pound));

}

float application_window::get_conversion(const string& crfl)
{
string iname = crfl;
ifstream ist(iname);

float rate;
if (!ist) { error("File could not be read: ", iname); }
else { ist >> rate; }

return rate;
}

void application_window::convert()
{
float input = strtof((value_in.get_string()).c_str(), 0);

if (from == euro && to == pound)
{
input *= conversion_rate;

ostringstream ss;
ss << input;
string s(ss.str());

value_out.put(s);
}
else if (from == pound && to == euro)
{
input *= 1.0 + (1.0 - conversion_rate);

ostringstream ss;
ss << input;
string s(ss.str());

value_out.put(s);
}
else
{
ostringstream ss;
ss << input;
string s(ss.str());

value_out.put(s);
}
}

int main()
try
{
application_window win(Point(100, 100), xmax, ymax + 20, "currency converter", "Data/conversion_rate.txt");
return gui_main();
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
keep_window_open();
return 1;
}
catch (...) {
cerr << "Unknown exception!\n";
keep_window_open();
return 2;
}
```
```Input:
Text file: Data/conversion_rate.txt
0.87
```

# flying airplane image animation [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 7
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

```Output:

```
```//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 7

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include <time.h>

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

// HANDS
struct Airplane : Shape
{
Airplane(string content_location, Point& position, int canvas_width, int canvas_height)
: content_location(content_location)
, position(position)
, canvas_width(canvas_width)
, canvas_height(canvas_height)
{
image_width = 250;
image_height = 150;
velocity = Point(1, 1);
}

void move();
void draw_lines() const;

string content_location;
Point position;

Point velocity;

int image_width;
int image_height;

int canvas_width;
int canvas_height;
};

void Airplane::move()
{

if (position.x <= canvas_width - image_width)
{
position.x += velocity.x;
}
if (position.y <= canvas_height - image_height)
{
position.y += velocity.y;
}

if (position.x == canvas_width - image_width || position.x == 0)
{
velocity.x *= -1;
}
if (position.y == canvas_height - image_height || position.y == 0)
{
velocity.y *= -1;
}

}

void Airplane::draw_lines() const
{
Image image0(position, content_location);

if (color().visibility()) {
// draw content image
image0.draw();
}
}

struct animation_window : Window {
animation_window(Point xy, int w, int h, const string& title)
: Window(xy, w, h, title),
quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit),
start_stop_button(Point(x_max() - 70, 20), 70, 20, "Start/Stop", cb_start_stop)
{
attach(quit_button);
attach(start_stop_button);
//position = Point(0, 0);
Airplane plane("Data/airplanes-work-1.jpg", Point(0, 0), w, h);
run = false;

while (true) {
Fl::wait();
Sleep(10);
draw_shape(plane);
if (run)
{
plane.move();
Fl::redraw();
}

}
}

Vector_ref<Shape> s;
void draw_shape(Airplane& plane);

Button quit_button;
Button start_stop_button;

bool run;

private:

void quit() { hide(); }
void start_stop()
{
if (run) { run = false; }
else { run = true; }
}

};

void animation_window::draw_shape(Airplane& plane)
{
if (s.size() != 0)
{
for (int i = 0; i < s.size(); i++)
{
detach(s[i]);
}
}

s.push_back(plane);
attach(s[s.size() - 1]);
}

int main()
try
{
animation_window win(Point(100, 100), xmax, ymax + 20, "flying airplane");

return gui_main();
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
keep_window_open();
return 1;
}
catch (...) {
cerr << "Unknown exception!\n";
keep_window_open();
return 2;
}
```

# analog clock [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 6
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

```Output:

```
```//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 6

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include <time.h>

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

// HANDS
struct Hands : Open_polyline
{
Hands(Point center, Point end, Fl_Color color)
{
c = color;
}

void draw_lines() const;
Fl_Color c;
};

void Hands::draw_lines() const
{
fl_color(c);
Open_polyline::draw_lines();
}

struct Analog_clock_window : Window {
Analog_clock_window(Point xy, int w, int h, const string& title)
: Window(xy, w, h, title),
quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
{
attach(quit_button);

while (true) {
Fl::wait();
Sleep(1000);
cout << "sleep" << endl;
draw_shape();
Fl::redraw();
}
}

Vector_ref<Shape> s;
void draw_shape();

Button quit_button;

private:
time_t rawtime;
bool button_pushed;

void print_current_time(time_t &rt);

void quit() { hide(); }
};

void Analog_clock_window::print_current_time(time_t &rt)
{
#pragma warning(disable : 4996) //_CRT_SECURE_NO_WARNINGS

struct tm * timeinfo;
timeinfo = localtime(&rt);
printf("Current local time and date: %s", asctime(timeinfo));

cout << timeinfo->tm_sec << endl;
}

void Analog_clock_window::draw_shape()
{
if (s.size() != 0)
{
for (int i = 0; i < s.size(); i++)
{
detach(s[i]);
}
}

Point center(xmax / 2, ymax / 2);

for (int i = 0; i < 12; i++)
{
Point pt1(0, -100);
Point pt2(0, -95);
double rad = ((2 * M_PI) / 12) * i;

s.push_back(new Hands(Point(rotated_pt1.x + center.x, rotated_pt1.y + center.y), Point(rotated_pt2.x + center.x, rotated_pt2.y + center.y), Color::black));
attach(s[s.size() - 1]);
}

#pragma warning(disable : 4996) //_CRT_SECURE_NO_WARNINGS
time_t rawT;
time(&rawT);

struct tm * timeinfo;
timeinfo = localtime(&rawT);
asctime(timeinfo);

printf("Current local time and date: %s", asctime(timeinfo));

// SECOND HAND
Point origin_Pt1(0, -100);

double rad = timeinfo->tm_sec * ((2 * M_PI) / 60);

s.push_back(new Hands(center, Point(rotated_Pt1.x + center.x , rotated_Pt1.y + center.y), Color::red));
attach(s[s.size() - 1]);

// MINUTE HAND
Point origin_Pt2(0, -80);

rad = timeinfo->tm_min * ((2 * M_PI) / 60);

s.push_back(new Hands(center, Point(rotated_Pt2.x + center.x, rotated_Pt2.y + center.y), Color::blue));
attach(s[s.size() - 1]);

// HOUR HAND
Point origin_Pt3(0, -60);

rad = timeinfo->tm_hour * ((2 * M_PI) / 12) + (timeinfo->tm_min * ((2 * M_PI) / 60)) / 12;

s.push_back(new Hands(center, Point(rotated_Pt3.x + center.x, rotated_Pt3.y + center.y), Color::black));
attach(s[s.size() - 1]);
}

int main()
try
{
Analog_clock_window win(Point(100, 100), xmax, ymax + 20, "analog clock");

return gui_main();
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
keep_window_open();
return 1;
}
catch (...) {
cerr << "Unknown exception!\n";
keep_window_open();
return 2;
}
```

# randomly moving shape [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 5
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

```Output:

```
```//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 5

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

struct My_window : Window {
My_window(Point xy, int w, int h, const string& title, string url)
: Window(xy, w, h, title),
next_button_pushed(false),
next_button(Point(x_max() - 140, 0), 70, 20, "Next", cb_next),
quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit),
url(url),
counter(0)
{
attach(next_button);
attach(quit_button);

// open input stream
ifstream ist(url);
int input_x;
char comma;
int input_y;

// store data in vectors
while (ist >> input_x >> comma >> input_y)
{
in_x.push_back(input_x);
in_y.push_back(input_y);
}
}

void wait_for_button()
{
while (!next_button_pushed) Fl::wait();
next_button_pushed = false;
Fl::redraw();
}

Button next_button;
Button quit_button;

private:
bool next_button_pushed;
string url;
int counter;
Vector_ref<Shape> s;

vector<int> in_x;
vector<int> in_y;

{
}

{
}

void next();
void quit() { hide(); }
};

void My_window::next()
{
if (s.size() < in_x.size())
{
if (s.size() != 0) { detach(s[s.size() - 1]); }
s.push_back(new Circle(Point(in_x[counter], in_y[counter]), 20));
attach(s[s.size() - 1]);
redraw();
counter++;
}
}

int main()
try
{
My_window win(Point(100, 100), xmax, ymax + 20, "next buttons window", "Data/point_sequence.txt");
return gui_main();
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
keep_window_open();
return 1;
}
catch (...) {
cerr << "Unknown exception!\n";
keep_window_open();
return 2;
}
```

# shape drawing with menu [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 4
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

```Output:

```
```//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 4

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"

// layout
constexpr int xmax = 600;
constexpr int ymax = 400;

{
Quad_center(Point center, int w, int h)
{
add(Point(center.x - w / 2, center.y - h / 2));
add(Point(center.x + w / 2, center.y - h / 2));
add(Point(center.x + w / 2, center.y + h / 2));
add(Point(center.x - w / 2, center.y + h / 2));

}

void draw_lines() const;
};

{
fl_color(FL_BLACK);
Closed_polyline::draw_lines();
}

// TRIANGLE
struct Triangle : Closed_polyline
{
Triangle(Point origin, int edge_length)
{
int h = sqrt(3) / 2 * edge_length;

Point p(origin.x - edge_length / 2, origin.y + edge_length / 2);
add(Point(p.x + edge_length / 2, p.y - h));
}

void draw_lines() const;
};

void Triangle::draw_lines() const
{
fl_color(FL_BLACK);
Closed_polyline::draw_lines();
}

// HEXAGON
struct Hexagon : Closed_polyline
{
{
int n = 6;
for (int i = 0; i < n; i++) {
add(Point(origin.x + radius * cos(2 * M_PI * i / n), origin.y + radius * sin(2 * M_PI * i / n)));
}
}

void draw_lines() const;
};

void Hexagon::draw_lines() const
{
fl_color(FL_BLACK);
Closed_polyline::draw_lines();
}

// DRAW SHAPES WINDOW
struct Shapes_window : Window {
Shapes_window(Point xy, int w, int h, const string& title);
private:
// data
enum Shapes
{
circle, square, triangle , hexagon
};

Vector_ref<Shape> s;

// widgets
Button quit_button;	// end program
In_box draw_pos_x;
In_box draw_pos_y;
Out_box xy_out;

// actions invoked by callbacks
void draw_shape(Shapes s);
void quit();

// callback functions
};

Shapes_window::Shapes_window(Point xy, int w, int h, const string& title)
:Window(xy, w, h, title),
quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit),
draw_pos_x(Point(x_max() - 310, 0), 50, 20, "pos x:"),
draw_pos_y(Point(x_max() - 210, 0), 50, 20, "pos y:"),
xy_out(Point(100, 0), 100, 20, "drawn at (x,y):"),
{
attach(quit_button);
attach(draw_pos_x);
attach(draw_pos_y);
attach(xy_out);

xy_out.put("no shape");

shape_menu.attach(new Button(Point(0, 0), 0, 0, "circle", cb_circle));
shape_menu.attach(new Button(Point(0, 0), 0, 0, "square", cb_square));
shape_menu.attach(new Button(Point(0, 0), 0, 0, "triangle", cb_triangle));
shape_menu.attach(new Button(Point(0, 0), 0, 0, "hexagon", cb_hexagon));

}

void Shapes_window::draw_shape(Shapes shape)
{

if (draw_pos_x.get_int() == -999999)
{
xy_out.put("enter position");
}
else {

int x = draw_pos_x.get_int();
int y = draw_pos_y.get_int();

switch (shape)
{
case circle: { s.push_back(new Circle(Point(x, y), 20)); break; }
case square: { s.push_back(new Quad_center(Point(x, y), 40, 40)); break; }
case triangle: { s.push_back(new Triangle(Point(x, y), 40)); break; }
case hexagon: { s.push_back(new Hexagon(Point(x, y), 20)); break; }
}

ostringstream ss;
ss << '(' << x << ',' << y << ')';
xy_out.put(ss.str());

attach(s[s.size() - 1]);
redraw();
}
}

void Shapes_window::quit()
{
hide();
}

{
reference_to<Shapes_window>(pw).draw_shape(circle);
}

{
reference_to<Shapes_window>(pw).draw_shape(square);
}

{
reference_to<Shapes_window>(pw).draw_shape(triangle);
}

{
reference_to<Shapes_window>(pw).draw_shape(hexagon);
}

{
}

{
reference_to<Shapes_window>(pw).quit();
}

int main()
try
{
Shapes_window win(Point(100, 100), xmax, ymax, "lines");
return gui_main();
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
keep_window_open();
return 1;
}

catch (...) {
cerr << "Unknown exception!\n";
keep_window_open();
return 2;
}
```

# button changing random location on click [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 3
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

```Output:

```
```//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 3

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"
#include <random>

inline int rand_int(int min, int max)
{
static default_random_engine ran;
return uniform_int_distribution<>(min, max)(ran);
}

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

struct My_window : Window {
My_window(Point xy, int w, int h, const string& title)
: Window(xy, w, h, title),
next_button_pushed(false),
next_button(Point(x_max() - 140, 0), 70, 20, "Next", cb_next),
quit_button_pushed(false),
quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
{
attach(next_button);
attach(quit_button);
}

void wait_for_button()
{
while (!next_button_pushed) Fl::wait();
next_button_pushed = false;
Fl::redraw();
}

Button next_button;
Button quit_button;

private:
bool next_button_pushed;
bool quit_button_pushed;

{
}

{
}

void next() { next_button_pushed = true; }
void quit() { hide(); }
};

struct Random_button_win : My_window
{
Random_button_win(Point xy, int w, int h, const string& title, const string& url)
:My_window(xy, w, h, title),
url(url),
rand_button(Point(xmax/2, ymax/2), 40, 40, "", cb_rand),
button_image(Point(xmax / 2, ymax / 2), url)
{
attach(rand_button);
button_image.set_mask(Point(xmax / 2, ymax / 2), 40, 40);
attach(button_image);
}

Button rand_button;
Image button_image;

private:
string url;

{
}

void change_button_pos()
{
rand_button.hide();

int current_x = rand_button.loc.x;
int current_y = rand_button.loc.y;

int new_x = rand_int(0, xmax - 40) - current_x;
int new_y = rand_int(20, ymax - 40) - current_y;

rand_button.move(new_x, new_y);
button_image.move(new_x, new_y);
redraw();
}
};

int main()
try
{
Random_button_win win(Point(100, 100), xmax, ymax + 20, "random buttons window", "Data/supercell.jpg");
return gui_main();
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
keep_window_open();
return 1;
}
catch (...) {
cerr << "Unknown exception!\n";
keep_window_open();
return 2;
}
```

# checker board square buttons [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 16 Exercise 2
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

```Output:

```
```//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 16 Exercise 2

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>
#include "GUI.h"

// layout
constexpr int xmax = 400;
constexpr int ymax = 400;

struct My_window : Window {
My_window(Point xy, int w, int h, const string& title)
: Window(xy, w, h, title),
next_button_pushed(false),
next_button(Point(x_max() - 140, 0), 70, 20, "Next", cb_next),
quit_button_pushed(false),
quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit)
{
attach(next_button);
attach(quit_button);
}

void wait_for_button()
// modified event loop
// handle all events (as per default), but quit when button_pushed becomes true
// this allows graphics without control inversion
{
while (!next_button_pushed) Fl::wait();
next_button_pushed = false;
Fl::redraw();
}

Button next_button;
Button quit_button;

private:
bool next_button_pushed;
bool quit_button_pushed;

{
}

{
}

void next() { next_button_pushed = true; }
void quit() { hide(); }
};

struct cheker_board_buttons : My_window
{
cheker_board_buttons(Point xy, int w, int h, const string& title)
:My_window(xy, w, h, title)
{
int x_size = xmax / 4;
int y_size = ymax / 4;

// initialize buttons
buttons.push_back(new Button(Point(0, 20), x_size, y_size, "b0", cb_change_0));
buttons.push_back(new Button(Point(x_size, 20), x_size, y_size, "b1", cb_change_1));
buttons.push_back(new Button(Point(x_size * 2, 20), x_size, y_size, "b2", cb_change_2));
buttons.push_back(new Button(Point(x_size * 3, 20), x_size, y_size, "b3", cb_change_3));
buttons.push_back(new Button(Point(0, y_size + 20), x_size, y_size, "b4", cb_change_4));
buttons.push_back(new Button(Point(x_size, y_size + 20), x_size, y_size, "b5", cb_change_5));
buttons.push_back(new Button(Point(x_size * 2, y_size + 20), x_size, y_size, "b6", cb_change_6));
buttons.push_back(new Button(Point(x_size * 3, y_size + 20), x_size, y_size, "b7", cb_change_7));
buttons.push_back(new Button(Point(0, y_size * 2 + 20), x_size, y_size, "b8", cb_change_8));
buttons.push_back(new Button(Point(x_size, y_size * 2 + 20), x_size, y_size, "b9", cb_change_9));
buttons.push_back(new Button(Point(x_size * 2, y_size * 2 + 20), x_size, y_size, "b10", cb_change_10));
buttons.push_back(new Button(Point(x_size * 3, y_size * 2 + 20), x_size, y_size, "b11", cb_change_11));
buttons.push_back(new Button(Point(0, y_size * 3 + 20), x_size, y_size, "b12", cb_change_12));
buttons.push_back(new Button(Point(x_size, y_size * 3 + 20), x_size, y_size, "b13", cb_change_13));
buttons.push_back(new Button(Point(x_size * 2, y_size * 3 + 20), x_size, y_size, "b14", cb_change_14));
buttons.push_back(new Button(Point(x_size * 3, y_size * 3 + 20), x_size, y_size, "b15", cb_change_15));

// attach buttons
for (int i = 0; i < buttons.size(); i++) { attach(buttons[i]); }
}

// button setup
Vector_ref<Button> buttons;
int last = 16;
void reset_button() { if(last != 16) { buttons[last].show(); } }

// button behaviour
void change_b0() { reset_button(); last = 0; buttons[0].hide(); };
void change_b1() { reset_button(); last = 1; buttons[1].hide(); };
void change_b2() { reset_button(); last = 2; buttons[2].hide(); };
void change_b3() { reset_button(); last = 3; buttons[3].hide(); };
void change_b4() { reset_button(); last = 4; buttons[4].hide(); };
void change_b5() { reset_button(); last = 5; buttons[5].hide(); };
void change_b6() { reset_button(); last = 6; buttons[6].hide(); };
void change_b7() { reset_button(); last = 7; buttons[7].hide(); };
void change_b8() { reset_button(); last = 8; buttons[8].hide(); };
void change_b9() { reset_button(); last = 9; buttons[9].hide(); };
void change_b10() { reset_button(); last = 10; buttons[10].hide(); };
void change_b11() { reset_button(); last = 11; buttons[11].hide(); };
void change_b12() { reset_button(); last = 12; buttons[12].hide(); };
void change_b13() { reset_button(); last = 13; buttons[13].hide(); };
void change_b14() { reset_button(); last = 14; buttons[14].hide(); };
void change_b15() { reset_button(); last = 15; buttons[15].hide(); };

private:
vector<bool> pressed;

// call back functions
};

int main()
try
{
cheker_board_buttons win(Point(100, 100), xmax, ymax + 20, "checker board buttons");
return gui_main();
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
keep_window_open();
return 1;
}

catch (...) {
cerr << "Unknown exception!\n";
keep_window_open();
return 2;
}
```