Sci Fi Demo Project [Unity & WebGL]

Sci Fi Demo Project >>> PLAY NOW <<<

sci-fi-demo-project-thumbnail

This is the Sci Fi Demo Project by Jonathan Weinberger on Udemy.
Use the “E” button to pick up the coin from the vending machine and buy a weapon from the Shark also with “E” once you picked up the coin.
There is a destructible crate on the opposite side, in front of the fruit vendor.

In case you want to test play the game, here you go!

This is the project for you to download: Sci Fi Project

Galaxy Shooter [Unity & WebGL]

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

galaxy-shooter-thumbnail

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!).

This is the project for you to download: Galaxy Shooter

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;

	// had to add void clear_points() { points.clear(); }
	// 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;
		add(Point(x, y));
		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;
	Menu graph_type_menu;

	// 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 graph_type_menu_pressed() { graph_type.hide(); graph_type_menu.show(); }

	void sin_graph();
	void cos_graph();	

	// callback functions
	static void cb_quit(Address, Address pw) { reference_to<application_window>(pw).quit(); }
	static void cb_calculate(Address, Address pw) { reference_to<application_window>(pw).draw_graph(); }

	static void cb_graph_type_menu_pressed(Address, Address pw) { reference_to<application_window>(pw).graph_type_menu_pressed(); }

	static void cb_sin_graph(Address, Address pw) { reference_to<application_window>(pw).sin_graph(); }
	static void cb_cos_graph(Address, Address pw) { reference_to<application_window>(pw).cos_graph(); }

	//------------- 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)
	, graph_type_menu(Point(20, 0), 100, 20, Menu::vertical, "Graph Type")
	, 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));

	attach(graph_type_menu);

	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);

	graph_type_menu.hide();
}

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

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

void application_window::cos_graph()
{
	graph_type_menu.hide();
	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 ',':
	{
		return Token(ch);
	}
	case '#':
	{
		return Token(let);
	}
	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;
		return Token(number, 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
			if (s == "quit") return Token(quitProg);
			if (s == "sqrt") return Token(sqroot);
			if (s == "pow") return Token(power);
			if (s == "const") return Token(constant);
			if (s == "reset") return Token(reset);
			if (s == "help" || s == "Help") return Token(help);
			return Token(name, s);
		}
		error("Bad token");
		return Token(' ');
	}
	}
}

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
	static void cb_quit(Address, Address pw) { reference_to<application_window>(pw).quit(); }
	static void cb_calculate(Address, Address pw) { reference_to<application_window>(pw).cal(); }

	//------------- 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;

	// menu button
	Button from_menu_button;
	Button to_menu_button;

	// menu
	Menu from_menu;
	Menu to_menu;

	// 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 hide_from_menu() { from_menu.hide(); from_menu_button.show(); }
	void hide_to_menu() { to_menu.hide(); to_menu_button.show(); }

	void from_menu_pressed() { from_menu_button.hide(); from_menu.show(); }
	void to_menu_pressed() { to_menu_button.hide(); to_menu.show(); }

	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
	static void cb_quit(Address, Address pw) { reference_to<application_window>(pw).quit(); }

	static void cb_convert(Address, Address pw) { reference_to<application_window>(pw).convert(); }

	static void cb_from_menu(Address, Address pw) {	reference_to<application_window>(pw).from_menu_pressed(); }
	static void cb_from_euro(Address, Address pw) { reference_to<application_window>(pw).from_euro_pressed(); }
	static void cb_from_pound(Address, Address pw) { reference_to<application_window>(pw).from_pound_pressed(); }

	static void cb_to_menu(Address, Address pw) { reference_to<application_window>(pw).to_menu_pressed(); }
	static void cb_to_euro(Address, Address pw) { reference_to<application_window>(pw).to_euro_pressed(); }
	static void cb_to_pound(Address, Address pw) { reference_to<application_window>(pw).to_pound_pressed(); }

	//------------- 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)
	, from_menu_button(Point(0, 20), 70, 20, "From", cb_from_menu)
	, to_menu_button(Point(x_max() / 2, 20), 70, 20, "To", cb_to_menu)
	, from_menu(Point(0, 20), 70, 20, Menu::vertical, "From")
	, to_menu(Point(x_max() / 2, 20), 70, 20, Menu::vertical, "To")
	, 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(from_menu_button);
	attach(to_menu_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));

	attach(to_menu);
	attach(from_menu);

	to_menu.hide();
	from_menu.hide();
}

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);
	image0.set_mask(Point(100, 70), image_width, image_height);

	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:

	static void cb_quit(Address, Address addr) { reference_to<animation_window>(addr).quit(); }
	static void cb_start_stop(Address, Address addr) { reference_to<animation_window>(addr).start_stop(); }

	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)
	{
		add(Point(center));
		add(Point(end));
		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);

	static void cb_quit(Address, Address addr) { reference_to<Analog_clock_window>(addr).quit(); }
	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;

		Point rotated_pt1 = Point(cos(rad) * pt1.x - sin(rad) * pt1.y, sin(rad) * pt1.x + cos(rad) * pt1.y);
		Point rotated_pt2 = Point(cos(rad) * pt2.x - sin(rad) * pt2.y, sin(rad) * pt2.x + cos(rad) * pt2.y);

		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);
	Point rotated_Pt1 = Point(cos(rad) * origin_Pt1.x - sin(rad) * origin_Pt1.y, sin(rad) * origin_Pt1.x + cos(rad) * origin_Pt1.y);
	
	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);
	Point rotated_Pt2 = Point(cos(rad) * origin_Pt2.x - sin(rad) * origin_Pt2.y, sin(rad) * origin_Pt2.x + cos(rad) * origin_Pt2.y);

	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;
	Point rotated_Pt3 = Point(cos(rad) * origin_Pt3.x - sin(rad) * origin_Pt3.y, sin(rad) * origin_Pt3.x + cos(rad) * origin_Pt3.y);

	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;
}