示例#1
0
XBMCVideoChecker::XBMCVideoChecker(const std::string & address, uint16_t port, bool grabVideo, bool grabPhoto, bool grabAudio, bool grabMenu, bool grabScreensaver, bool enable3DDetection) :
	QObject(),
	_address(QString::fromStdString(address)),
	_port(port),
	_activePlayerRequest(R"({"id":666,"jsonrpc":"2.0","method":"Player.GetActivePlayers"})"),
	_currentPlayingItemRequest(R"({"id":667,"jsonrpc":"2.0","method":"Player.GetItem","params":{"playerid":%1,"properties":["file"]}})"),
	_checkScreensaverRequest(R"({"id":668,"jsonrpc":"2.0","method":"XBMC.GetInfoBooleans","params":{"booleans":["System.ScreenSaverActive"]}})"),
	_getStereoscopicMode(R"({"jsonrpc":"2.0","method":"GUI.GetProperties","params":{"properties":["stereoscopicmode"]},"id":669})"),
	_getXbmcVersion(R"({"jsonrpc":"2.0","method":"Application.GetProperties","params":{"properties":["version"]},"id":670})"),
	_socket(),
	_grabVideo(grabVideo),
	_grabPhoto(grabPhoto),
	_grabAudio(grabAudio),
	_grabMenu(grabMenu),
	_grabScreensaver(grabScreensaver),
	_enable3DDetection(enable3DDetection),
	_previousScreensaverMode(false),
	_previousGrabbingMode(GRABBINGMODE_INVALID),
	_previousVideoMode(VIDEO_2D),
	_xbmcVersion(0)
{
	// setup socket
	connect(&_socket, SIGNAL(readyRead()), this, SLOT(receiveReply()));
	connect(&_socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
	connect(&_socket, SIGNAL(connected()), this, SLOT(connected()));
	connect(&_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectionError(QAbstractSocket::SocketError)));
}

void XBMCVideoChecker::start()
{
	reconnect();
}

void XBMCVideoChecker::receiveReply()
{
	// expect that the reply is received as a single message. Probably oke considering the size of the expected reply
	QString reply(_socket.readAll());

	std::cout << "Message from XBMC: " << reply.toStdString() << std::endl;

	if (reply.contains("\"method\":\"Player.OnPlay\""))
	{
		// send a request for the current player state
		_socket.write(_activePlayerRequest.toUtf8());
		return;
	}
	else if (reply.contains("\"method\":\"Player.OnStop\""))
	{
		// the player has stopped
		setGrabbingMode(_grabMenu ? GRABBINGMODE_MENU : GRABBINGMODE_OFF);
		setVideoMode(VIDEO_2D);
	}
	else if (reply.contains("\"method\":\"GUI.OnScreensaverActivated\""))
	{
		setScreensaverMode(!_grabScreensaver);
	}
	else if (reply.contains("\"method\":\"GUI.OnScreensaverDeactivated\""))
	{
		setScreensaverMode(false);
	}
	else if (reply.contains("\"id\":666"))
	{
		// Result of Player.GetActivePlayers

		// always start a new video in 2D mode
		emit videoMode(VIDEO_2D);

		if (reply.contains("video"))
		{
			// video is playing
			setGrabbingMode(_grabVideo ? GRABBINGMODE_VIDEO : GRABBINGMODE_OFF);

			// we need to get the filename
			// first retrieve the playerid
			QString key = "\"playerid\":";
			QRegExp regex(key + "(\\d+)");
			int pos = regex.indexIn(reply);
			if (pos > 0)
			{
				// now request info of the playing item
				QStringRef idText(&reply, pos + key.length(), regex.matchedLength() - key.length());
				_socket.write(_currentPlayingItemRequest.arg(idText.toString()).toUtf8());
			}
		}
		else if (reply.contains("picture"))
		{
			// picture viewer is playing
			setGrabbingMode(_grabPhoto ? GRABBINGMODE_PHOTO : GRABBINGMODE_OFF);
		}
		else if (reply.contains("audio"))
		{
			// audio is playing
			setGrabbingMode(_grabAudio ? GRABBINGMODE_AUDIO : GRABBINGMODE_OFF);
		}
		else
		{
			// Nothing is playing.
			setGrabbingMode(_grabMenu ? GRABBINGMODE_MENU : GRABBINGMODE_OFF);
		}
	}
	else if (reply.contains("\"id\":667"))
	{
		if (_xbmcVersion >= 13)
		{
			// check of active stereoscopicmode
			_socket.write(_getStereoscopicMode.toUtf8());
		}
		else
		{
			// result of Player.GetItem
			// TODO: what if the filename contains a '"'. In Json this should have been escaped
			QRegExp regex("\"file\":\"((?!\").)*\"");
			int pos = regex.indexIn(reply);
			if (pos > 0)
			{
				QStringRef filename = QStringRef(&reply, pos+8, regex.matchedLength()-9);
				if (filename.contains("3DSBS", Qt::CaseInsensitive) || filename.contains("HSBS", Qt::CaseInsensitive))
				{
					setVideoMode(VIDEO_3DSBS);
				}
				else if (filename.contains("3DTAB", Qt::CaseInsensitive) || filename.contains("HTAB", Qt::CaseInsensitive))
				{
					setVideoMode(VIDEO_3DTAB);
				}
				else
				{
					setVideoMode(VIDEO_2D);
				}
			}
		}
	}
	else if (reply.contains("\"id\":668"))
	{
		// result of System.ScreenSaverActive
		bool active = reply.contains("\"System.ScreenSaverActive\":true");
		setScreensaverMode(!_grabScreensaver && active);

		// check here xbmc version
		if (_socket.state() == QTcpSocket::ConnectedState)
		{
			if (_xbmcVersion == 0)
			{
				_socket.write(_getXbmcVersion.toUtf8());
			}
		}
	}
	else if (reply.contains("\"id\":669"))
	{
		QRegExp regex("\"mode\":\"(split_vertical|split_horizontal)\"");
		int pos = regex.indexIn(reply);
		if (pos > 0)
		{
			QString sMode = regex.cap(1);
			if (sMode == "split_vertical")
			{
				setVideoMode(VIDEO_3DSBS);
			}
			else if (sMode == "split_horizontal")
			{
				setVideoMode(VIDEO_3DTAB);
			}
		}
	}
	else if (reply.contains("\"id\":670"))
	{
		QRegExp regex("\"major\":(\\d+)");
		int pos = regex.indexIn(reply);
		if (pos > 0)
		{
			_xbmcVersion = regex.cap(1).toInt();
		}
	}
}
示例#2
0
int main()
{
	//
	//		
	//	Because I need it to randomize 
	//	duck's vector and spikes 
	//
	srand(time(NULL));

	//
	//	Create Window 
	//	
	sf::VideoMode videoMode(WINDOW_X, WINDOW_Y);
	sf::RenderWindow window(videoMode, WINDOW_TITLE, sf::Style::Titlebar);


	//
	// Set Window max FPS to 100
	// and play music in background
	//
	window.setFramerateLimit(100);
	sf::Music music;
	music.openFromFile( MUSIC_FOLDER "Courage.ogg" );
	music.play();



	//
	//		
	//	Create window border: line by line. 
	//
	// line thickness 10px;
	// color Black
	//
	
	sf::RectangleShape lineTOP;
	lineTOP.setFillColor(sf::Color::Black);
	lineTOP.setPosition(sf::Vector2f(0, 0));
	lineTOP.setSize(sf::Vector2f(300, 10));

	sf::RectangleShape lineLEFT;
	lineLEFT.setFillColor(sf::Color::Black);
	lineLEFT.setPosition(sf::Vector2f(0, 0));
	lineLEFT.setSize(sf::Vector2f(10, 450));

	sf::RectangleShape lineRIGHT;
	lineRIGHT.setFillColor(sf::Color::Black);
	lineRIGHT.setPosition(sf::Vector2f(290, 0));
	lineRIGHT.setSize(sf::Vector2f(10, 440));


	sf::RectangleShape LineBOTTOM;
	LineBOTTOM.setFillColor(sf::Color::Black);
	LineBOTTOM.setPosition(sf::Vector2f(0, 440));
	LineBOTTOM.setSize(sf::Vector2f(300, 10));




	//
	//		
	//	Create Circle
	//  With color RGB(242,242,242) and alpha 199 where alhpa is between 0 and 255;
	//  
	//  Circle radius : 100px;
	//  Circle position: center of window
	sf::CircleShape circle(100);
	circle.setFillColor(sf::Color(242, 242, 242, 199));
	circle.setOrigin(sf::Vector2f(100, 100));
	circle.setPosition(sf::Vector2f(WINDOW_X / 2, WINDOW_Y / 2));


	
	
	//
	//		
	//	Create 10 el array of colors
	//
	sf::Color colors[10];
	colors[0] = sf::Color(209, 250, 142);
	colors[1] = sf::Color(168, 255, 142);
	colors[2] = sf::Color(250, 255, 142);
	colors[3] = sf::Color(255, 189, 190);
	colors[4] = sf::Color(255, 189, 223);
	colors[5] = sf::Color(221, 189, 255);
	colors[6] = sf::Color(189, 190, 255);
	colors[7] = sf::Color(195, 195, 216);
	colors[8] = sf::Color(213, 213, 213);
	colors[9] = sf::Color(233, 255, 142);



	
	
	//
	// Load Font from file to font object;
	//
	// if font not exist them return FONT_NOT_FOUND;
	sf::Font font;
	if (!font.loadFromFile(WINDOW_FONT)) return FONT_NOT_FOUND;




	
	currentCOLOR = colors[0]; // set starts color
	colorbyPoint = colors[0]; // set starts color


	//
	// Create and initialize Duck object
	// 
	// @param App wios
	// @param array of randomized bool values 
	// 
	CDuck Duck(window, SpikeTab);



	// player is playing ? 	
	bool Game = false;


	//
	//		
	//	Main Game loop 
	//  executing until player don't close window.
	//
	//
	//
	while (window.isOpen())
	{


	
		//
		//  Text object 
		// @param current points 
		// @param loaded font;
		sf::Text circleText(points, font);
		setFadeColor(currentCOLOR, colorbyPoint, window, circleText);


		//
		//	Keys Support 	
		//
		sf::Event event;
		while (window.pollEvent(event))
		{
			if ((event.type == sf::Event::Closed) || (event.type == sf::Event::KeyPressed))
			{
				if (event.key.code == sf::Keyboard::Escape)  window.close();
				if (event.key.code == sf::Keyboard::Space && Game == true) Duck.Jump();
				if (event.key.code == sf::Keyboard::Space && Game == false) Game = true;
			}


		} // end While window.pollEvent


		//
		//		
		//	If player is playing
		//
		if (Game == true)
		{


			//
			// set text size to 102 		
			// set text pos to center of window
			// set text origin 
			circleText.setCharacterSize(102);
			circleText.setPosition(sf::Vector2f(WINDOW_X / 2, WINDOW_Y / 2 -25));
			circleText.setOrigin((circleText.getLocalBounds().width / 2) + 5, (circleText.getLocalBounds().height / 2));




			//
			// from unsigned to string;
			// if uPoints < 10 add 0 to string;
			points = (uPoints < 10 ? "0" + std::to_string(uPoints) : std::to_string(uPoints));


			//
			// Change next background
			//

			switch (uPoints)
			{
			case 5:
				colorbyPoint = colors[1];
				break;
			case 10:
				colorbyPoint = colors[2];
				break;
			case 15:
				colorbyPoint = colors[3];
				break;
			case 20:
				colorbyPoint = colors[4];
				break;
			case 25:
				colorbyPoint = colors[5];
				break;
			case 30:
				colorbyPoint = colors[6];
				break;
			case 40:
				colorbyPoint = colors[7];
				break;
			case 45:
				colorbyPoint = colors[8];
				break;
			case 50:
				colorbyPoint = colors[9];
				break;

			default:
				break;
			}




			//
			//	Create Left or Right spikes	
			//
			//
			for (int z = 0; z < static_cast<unsigned>(WINDOW_Y /  SPIKE_H) - 1; z++)
			{
 
 
				if (SpikeTab[z] == true)
				{

					//
					//	Create spikes  	
					// 
					// @param Window
					// @param enum Position  
					// @param x cord
					// @param y cord
					CSpike Spike(window, (Duck.cSide == 0 ? Right : Left), 10, (z * 41) + 11);
					//if (z != static_cast<unsigned>(WINDOW_Y /  SPIKE_H) - 1)
						Spike.Update();
						
						
					//
					//	Detect collision between Duck and Spike	
					//
					if (Collision::PixelPerfectTest(Duck.model, Spike.model))
					{
						Game = false; // player lose
						Duck.model.setPosition(WINDOW_X / 2, WINDOW_Y / 2); // set model pos to center
						Duck.cSide = rand() % 2; // rand duck's vector
						uPoints = 0; // set 0 points
						Duck.modelMove.y = 0; // set grav to 0
						Duck.RandSpike(); // randomize Spikes
						currentCOLOR = colors[0]; // set current color to default
					}

				}


			}


			
			for (int z = 0; z <= static_cast<unsigned>(WINDOW_X /   SPIKE_H); z++)
			{

				//
				// Top and bottom spikes
				//
				CSpike Spike2(window, Top, (z *   SPIKE_H) + 10, 10);
				Spike2.Update();

				CSpike Spike3(window, Bottom, (z *   SPIKE_H) + 10, WINDOW_Y - 10);
				if (z != static_cast<unsigned>(WINDOW_X /   SPIKE_H))
					Spike3.Update();


					
				if (Collision::PixelPerfectTest(Duck.model, Spike2.model) || Collision::PixelPerfectTest(Duck.model, Spike3.model))
				{
					Game = false;
					Duck.model.setPosition(WINDOW_X / 2, WINDOW_Y / 2);
					Duck.cSide = rand() % 2;
					uPoints = 0;
					Duck.modelMove.y = 0;
					Duck.RandSpike();
					currentCOLOR = colors[0];
				}

			}


		} // if GAME true
		else
		{
			//
			//	Create Start Screen
			//  
			//
			sf::Texture start_modelTeX; // Texture file 
			sf::Sprite start_model;	      // Model 

			
			
			// Load model
			// set texture
			//  position
			// set origin
			if (!start_modelTeX.loadFromFile(TEXTURE_FOLDER "logo.png")) exit(TEXTURE_NOT_FOUND);
			start_model.setTexture(start_modelTeX);
			start_model.setTextureRect(sf::IntRect(0, 0, 274, 291));
			start_model.setOrigin(274 / 2, 291 / 2);
			start_model.setPosition(WINDOW_X / 2, (WINDOW_Y / 2));


			
			
			// score text
			
			circleText.setCharacterSize(50);
			circleText.setPosition(sf::Vector2f(WINDOW_X / 2, WINDOW_Y / 2  -25));
			circleText.setOrigin((circleText.getLocalBounds().width / 2) + 5, (circleText.getLocalBounds().height / 2));


			
			
			//
			//
			window.draw(start_model);
			window.draw(circleText);

		} // else game false


		
		
		//
		//
		window.draw(lineTOP);
		window.draw(lineLEFT);
		window.draw(lineRIGHT);
		window.draw(LineBOTTOM);



		if (Game == true)
		{
			// layer with circle and text on it	
			window.draw(circle);
			window.draw(circleText);


			// firs layer : ONLY MOVING OBJECT
			Duck.Update();
		}


		window.display();
	} // end while window.isOpen
	return EXIT_SUCCESS;
}
示例#3
0
void App::createWindow()
{
	// Creamos un modo de video con los valores por defecto
	sf::VideoMode videoMode(this->DEFAULT_VIDEO_WIDTH, this->DEFAULT_VIDEO_HEIGHT, this->DEFAULT_VIDEO_BPP);
	// Creamos un estilo por defecto
	sf::Int32 style = sf::Style::Default;
	// Establecemos fullscreen a false
	bool fullscreen = false;
	// Valor inicial del redisionamiento de la ventana
	bool resize = true;
	// Activamos la sincronización vertical por defecto
	bool vsync = true;

	GDE::ConfigReader conf;
	// Si existe un archivo de configuración lo usamos para cargar los datos
	if(conf.loadFromFile("window.cfg")) // FIX: Deberá ser argado con el gestor de recursos
	{
		// Comprobamos si esta activado el modo fullscreen
		if (conf.getBool("window", "fullscreen", false))
		{
			fullscreen = true;
			// Si esta en modo fullscreen obtenemos la resolución del escritorio
			videoMode = sf::VideoMode::getDesktopMode();
			// Establecemos el estilo de fullScreen
			style = sf::Style::Fullscreen;
		}
		else
		{
			// Establecemos la configuración obtenida del archivo
			videoMode.width = conf.getUint32("window", "width", this->DEFAULT_VIDEO_WIDTH);
			videoMode.height = conf.getUint32("window", "height", this->DEFAULT_VIDEO_HEIGHT);
			videoMode.bitsPerPixel = conf.getUint32("window", "bpp", this->DEFAULT_VIDEO_BPP);
			// Comprobamos si la ventana se puede redimensionar
			if (!conf.getBool("window", "resize", true))
			{
				resize = false;
				style = sf::Style::Close | sf::Style::Titlebar;
			}
		}

		// Comprobamos si vsync está activado
		vsync = (conf.getBool("this->window", "vsync", true));
	}

	// Creamos la ventana con los valores resulantes
	this->window.create(videoMode, "Genbeta Dev Engine", style);
	// FIX: Hay que dar opción también a usar setFrameLimit
	this->window.setVerticalSyncEnabled(vsync);

	// Escribimos la configuración en el archivo
	GDE::ConfigCreate newConf;
	newConf.open("window.cfg");
	newConf.putSection("window");
	newConf.putValue("width", GDE::convertInt32(videoMode.width));
	newConf.putValue("height", GDE::convertInt32(videoMode.height));
	newConf.putValue("bpp", GDE::convertInt32(videoMode.bitsPerPixel));
	newConf.putValue("fullscreen", GDE::convertBool(fullscreen));
	newConf.putValue("resize", GDE::convertBool(resize));
	newConf.putValue("vsync", GDE::convertBool(vsync));
	newConf.close();

	// Escribimos en el log
	GDE::Log::info("App::createWindow", "Ventana creada");
	GDE::Log::info("Modo de Video", GDE::convertInt32(videoMode.width) + 
		"x" + GDE::convertInt32(videoMode.height) + 
		"x" + GDE::convertInt32(videoMode.bitsPerPixel));
	GDE::Log::info("Vsync", GDE::convertBool(vsync));
	GDE::Log::info("Fullscreen", GDE::convertBool(fullscreen));
}
示例#4
0
int main(int argc, char** argv)
{
	std::cout << "Application build time: " << __DATE__ << " " << __TIME__ << std::endl;

	// Initialising QCoreApplication
	QCoreApplication app(argc, argv);
	std::cout << "QCoreApplication initialised" << std::endl;

	signal(SIGINT,  signal_handler);
	signal(SIGTERM, signal_handler);

	// force the locale
	setlocale(LC_ALL, "C");
	QLocale::setDefault(QLocale::c());

	if (argc < 2)
	{
		std::cout << "Missing required configuration file. Usage:" << std::endl;
		std::cout << "hyperiond [config.file]" << std::endl;
		return 1;
	}

	const std::string configFile = argv[1];
	std::cout << "Selected configuration file: " << configFile.c_str() << std::endl;
	const Json::Value config = loadConfig(configFile);

	Hyperion hyperion(config);
	std::cout << "Hyperion created and initialised" << std::endl;

	// create boot sequence if the configuration is present
	if (config.isMember("bootsequence"))
	{
		const Json::Value effectConfig = config["bootsequence"];

		// Get the parameters for the bootsequence
		const std::string effectName = effectConfig["effect"].asString();
		const unsigned duration_ms   = effectConfig["duration_ms"].asUInt();
		const int priority = 0;
		
		hyperion.setColor(priority+1, ColorRgb::BLACK, duration_ms, false);

		if (effectConfig.isMember("args"))
		{
			const Json::Value effectConfigArgs = effectConfig["args"];
			if (hyperion.setEffect(effectName, effectConfigArgs, priority, duration_ms) == 0)
			{
					std::cout << "Boot sequence(" << effectName << ") with user-defined arguments created and started" << std::endl;
			}
			else
			{
					std::cout << "Failed to start boot sequence: " << effectName << " with user-defined arguments" << std::endl;
			}
		}
		else
		{
			if (hyperion.setEffect(effectName, priority, duration_ms) == 0)
			{
				std::cout << "Boot sequence(" << effectName << ") created and started" << std::endl;
			}
			else
			{
				std::cout << "Failed to start boot sequence: " << effectName << std::endl;
			}
		}
	}

	// create XBMC video checker if the configuration is present
	XBMCVideoChecker * xbmcVideoChecker = nullptr;
	if (config.isMember("xbmcVideoChecker"))
	{
		const Json::Value & videoCheckerConfig = config["xbmcVideoChecker"];
		xbmcVideoChecker = new XBMCVideoChecker(
			videoCheckerConfig["xbmcAddress"].asString(),
			videoCheckerConfig["xbmcTcpPort"].asUInt(),
			videoCheckerConfig["grabVideo"].asBool(),
			videoCheckerConfig["grabPictures"].asBool(),
			videoCheckerConfig["grabAudio"].asBool(),
			videoCheckerConfig["grabMenu"].asBool(),
			videoCheckerConfig.get("grabScreensaver", true).asBool(),
			videoCheckerConfig.get("enable3DDetection", true).asBool());

		xbmcVideoChecker->start();
		std::cout << "XBMC video checker created and started" << std::endl;
	}

#ifdef ENABLE_DISPMANX
	// Construct and start the frame-grabber if the configuration is present
	DispmanxWrapper * dispmanx = nullptr;
	if (config.isMember("framegrabber"))
	{
		const Json::Value & frameGrabberConfig = config["framegrabber"];
		dispmanx = new DispmanxWrapper(
			frameGrabberConfig["width"].asUInt(),
			frameGrabberConfig["height"].asUInt(),
			frameGrabberConfig["frequency_Hz"].asUInt(),
			&hyperion);

		if (xbmcVideoChecker != nullptr)
		{
			QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), dispmanx, SLOT(setGrabbingMode(GrabbingMode)));
			QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), dispmanx, SLOT(setVideoMode(VideoMode)));
		}

		dispmanx->start();
		std::cout << "Frame grabber created and started" << std::endl;
	}
#else
#if !defined(ENABLE_OSX) && !defined(ENABLE_FB)
	if (config.isMember("framegrabber"))
	{
		std::cerr << "The dispmanx framegrabber can not be instantiated, becuse it has been left out from the build" << std::endl;
	}
#endif
#endif

#ifdef ENABLE_V4L2
	// construct and start the v4l2 grabber if the configuration is present
	V4L2Wrapper * v4l2Grabber = nullptr;
	if (config.isMember("grabber-v4l2"))
	{
		const Json::Value & grabberConfig = config["grabber-v4l2"];
		v4l2Grabber = new V4L2Wrapper(
					grabberConfig.get("device", "/dev/video0").asString(),
					grabberConfig.get("input", 0).asInt(),
					parseVideoStandard(grabberConfig.get("standard", "no-change").asString()),
					parsePixelFormat(grabberConfig.get("pixelFormat", "no-change").asString()),
					grabberConfig.get("width", -1).asInt(),
					grabberConfig.get("height", -1).asInt(),
					grabberConfig.get("frameDecimation", 2).asInt(),
					grabberConfig.get("sizeDecimation", 8).asInt(),
					grabberConfig.get("redSignalThreshold", 0.0).asDouble(),
					grabberConfig.get("greenSignalThreshold", 0.0).asDouble(),
					grabberConfig.get("blueSignalThreshold", 0.0).asDouble(),
					&hyperion,
					grabberConfig.get("priority", 800).asInt());
		v4l2Grabber->set3D(parse3DMode(grabberConfig.get("mode", "2D").asString()));
		v4l2Grabber->setCropping(
					grabberConfig.get("cropLeft", 0).asInt(),
					grabberConfig.get("cropRight", 0).asInt(),
					grabberConfig.get("cropTop", 0).asInt(),
					grabberConfig.get("cropBottom", 0).asInt());

		v4l2Grabber->start();
		std::cout << "V4l2 grabber created and started" << std::endl;
	}
#else
	if (config.isMember("grabber-v4l2"))
	{
		std::cerr << "The v4l2 grabber can not be instantiated, becuse it has been left out from the build" << std::endl;
	}
#endif
	
#ifdef ENABLE_FB
	// Construct and start the framebuffer grabber if the configuration is present
	FramebufferWrapper * fbGrabber = nullptr;
	if (config.isMember("framegrabber"))
	{
		const Json::Value & grabberConfig = config["framegrabber"];
		fbGrabber = new FramebufferWrapper(
			grabberConfig.get("device", "/dev/fb0").asString(),
			grabberConfig["width"].asUInt(),
			grabberConfig["height"].asUInt(),
			grabberConfig["frequency_Hz"].asUInt(),
			&hyperion);

		if (xbmcVideoChecker != nullptr)
		{
			QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), fbGrabber, SLOT(setGrabbingMode(GrabbingMode)));
			QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), fbGrabber, SLOT(setVideoMode(VideoMode)));
		}

		fbGrabber->start();
		std::cout << "Framebuffer grabber created and started" << std::endl;
	}
#else
#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX)
	if (config.isMember("framegrabber"))
	{
		std::cerr << "The framebuffer grabber can not be instantiated, becuse it has been left out from the build" << std::endl;
	}
#endif
#endif
    
#ifdef ENABLE_OSX
    // Construct and start the osx grabber if the configuration is present
    OsxWrapper * osxGrabber = nullptr;
    if (config.isMember("framegrabber"))
    {
        const Json::Value & grabberConfig = config["framegrabber"];
        osxGrabber = new OsxWrapper(
                                           grabberConfig.get("display", 0).asUInt(),
                                           grabberConfig["width"].asUInt(),
                                           grabberConfig["height"].asUInt(),
                                           grabberConfig["frequency_Hz"].asUInt(),
                                           &hyperion);
        
        if (xbmcVideoChecker != nullptr)
        {
            QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), osxGrabber, SLOT(setGrabbingMode(GrabbingMode)));
            QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), osxGrabber, SLOT(setVideoMode(VideoMode)));
        }
        
        osxGrabber->start();
        std::cout << "OSX grabber created and started" << std::endl;
    }
#else
#if !defined(ENABLE_DISPMANX) && !defined(ENABLE_FB)
    if (config.isMember("framegrabber"))
    {
        std::cerr << "The osx grabber can not be instantiated, becuse it has been left out from the build" << std::endl;
    }
#endif
#endif

	// Create Json server if configuration is present
	JsonServer * jsonServer = nullptr;
	if (config.isMember("jsonServer"))
	{
		const Json::Value & jsonServerConfig = config["jsonServer"];
		jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt());
		std::cout << "Json server created and started on port " << jsonServer->getPort() << std::endl;
	}

#ifdef ENABLE_PROTOBUF
	// Create Proto server if configuration is present
	ProtoServer * protoServer = nullptr;
	if (config.isMember("protoServer"))
	{
		const Json::Value & protoServerConfig = config["protoServer"];
		protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt());
		std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl;
	}
#endif

	// Create Boblight server if configuration is present
	BoblightServer * boblightServer = nullptr;
	if (config.isMember("boblightServer"))
	{
		const Json::Value & boblightServerConfig = config["boblightServer"];
		boblightServer = new BoblightServer(&hyperion, boblightServerConfig["port"].asUInt());
		std::cout << "Boblight server created and started on port " << boblightServer->getPort() << std::endl;
	}

	// run the application
	int rc = app.exec();
	std::cout << "Application closed with code " << rc << std::endl;

	// Delete all component
#ifdef ENABLE_DISPMANX
	delete dispmanx;
#endif
#ifdef ENABLE_FB
	delete fbGrabber;
#endif
#ifdef ENABLE_OSX
    delete osxGrabber;
#endif
#ifdef ENABLE_V4L2
	delete v4l2Grabber;
#endif
	delete xbmcVideoChecker;
	delete jsonServer;
#ifdef ENABLE_PROTOBUF
	delete protoServer;
#endif
	delete boblightServer;

	// leave application
	return rc;
}
示例#5
0
文件: VideoMode.cpp 项目: Jebbs/CSFML
sfBool sfVideoMode_isValid(sfVideoMode mode)
{
    sf::VideoMode videoMode(mode.width, mode.height, mode.bitsPerPixel);
    return videoMode.isValid() ? sfTrue : sfFalse;
}
示例#6
0
int main(int argc, char** argv)
{
	std::cout << "Application build time: " << __DATE__ << " " << __TIME__ << std::endl;

	// Initialising QCoreApplication
	QCoreApplication app(argc, argv);
	std::cout << "QCoreApplication initialised" << std::endl;

	signal(SIGINT,  signal_handler);
	signal(SIGTERM, signal_handler);

	if (argc < 2)
	{
		std::cout << "Missing required configuration file. Usage:" << std::endl;
		std::cout << "hyperiond [config.file]" << std::endl;
		return 1;
	}

	const std::string configFile = argv[1];
	std::cout << "Selected configuration file: " << configFile.c_str() << std::endl;
	const Json::Value config = loadConfig(configFile);

	Hyperion hyperion(config);
	std::cout << "Hyperion created and initialised" << std::endl;

	// create boot sequence if the configuration is present
	if (config.isMember("bootsequence"))
	{
		const Json::Value effectConfig = config["bootsequence"];

		// Get the parameters for the bootsequence
		const std::string effectName = effectConfig["effect"].asString();
		const unsigned duration_ms   = effectConfig["duration_ms"].asUInt();
		const int priority = 0;

		if (hyperion.setEffect(effectName, priority, duration_ms) == 0)
		{
			std::cout << "Boot sequence(" << effectName << ") created and started" << std::endl;
		}
		else
		{
			std::cout << "Failed to start boot sequence: " << effectName << std::endl;
		}
	}

	// create XBMC video checker if the configuration is present
	XBMCVideoChecker * xbmcVideoChecker = nullptr;
	if (config.isMember("xbmcVideoChecker"))
	{
		const Json::Value & videoCheckerConfig = config["xbmcVideoChecker"];
		xbmcVideoChecker = new XBMCVideoChecker(
			videoCheckerConfig["xbmcAddress"].asString(),
			videoCheckerConfig["xbmcTcpPort"].asUInt(),
			videoCheckerConfig["grabVideo"].asBool(),
			videoCheckerConfig["grabPictures"].asBool(),
			videoCheckerConfig["grabAudio"].asBool(),
			videoCheckerConfig["grabMenu"].asBool(),
			videoCheckerConfig.get("grabScreensaver", true).asBool(),
			videoCheckerConfig.get("enable3DDetection", true).asBool());

		xbmcVideoChecker->start();
		std::cout << "XBMC video checker created and started" << std::endl;
	}

#ifdef ENABLE_DISPMANX
	// Construct and start the frame-grabber if the configuration is present
	DispmanxWrapper * dispmanx = nullptr;
	if (config.isMember("framegrabber"))
	{
		const Json::Value & frameGrabberConfig = config["framegrabber"];
		dispmanx = new DispmanxWrapper(
			frameGrabberConfig["width"].asUInt(),
			frameGrabberConfig["height"].asUInt(),
			frameGrabberConfig["frequency_Hz"].asUInt(),
			&hyperion);

		if (xbmcVideoChecker != nullptr)
		{
			QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), dispmanx, SLOT(setGrabbingMode(GrabbingMode)));
			QObject::connect(xbmcVideoChecker, SIGNAL(videoMode(VideoMode)), dispmanx, SLOT(setVideoMode(VideoMode)));
		}

		dispmanx->start();
		std::cout << "Frame grabber created and started" << std::endl;
	}
#else
	if (config.isMember("framegrabber"))
	{
		std::cerr << "The dispmanx framegrabber can not be instantiated, becuse it has been left out from the build" << std::endl;
	}
#endif

	// Create Json server if configuration is present
	JsonServer * jsonServer = nullptr;
	if (config.isMember("jsonServer"))
	{
		const Json::Value & jsonServerConfig = config["jsonServer"];
		jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt());
		std::cout << "Json server created and started on port " << jsonServer->getPort() << std::endl;
	}

	// Create Proto server if configuration is present
	ProtoServer * protoServer = nullptr;
	if (config.isMember("protoServer"))
	{
		const Json::Value & protoServerConfig = config["protoServer"];
		protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt());
		std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl;
	}

	// Create Boblight server if configuration is present
	BoblightServer * boblightServer = nullptr;
	if (config.isMember("boblightServer"))
	{
		const Json::Value & boblightServerConfig = config["boblightServer"];
		boblightServer = new BoblightServer(&hyperion, boblightServerConfig["port"].asUInt());
		std::cout << "Boblight server created and started on port " << boblightServer->getPort() << std::endl;
	}

	// run the application
	int rc = app.exec();
	std::cout << "Application closed with code " << rc << std::endl;

	// Delete all component
#ifdef ENABLE_DISPMANX
	delete dispmanx;
#endif
	delete xbmcVideoChecker;
	delete jsonServer;
	delete protoServer;
	delete boblightServer;

	// leave application
	return rc;
}
示例#7
0
bool Client::applyDisplaySettings()
{
    //The context settings apply to the opengl context that we create.
    sf::ContextSettings contextSettings;

    contextSettings.depthBits = 24;
    contextSettings.stencilBits = 8;

    contextSettings.antialiasingLevel = Config::getAALevel();
    contextSettings.majorVersion = 4;
    contextSettings.minorVersion = 4;
    // We want to create the window after the settings were loaded in case
    // anything client setting is different that the defaults.
    sf::VideoMode videoMode(Config::getWidth(), Config::getHeight(), 32);

    // Don't warn in fullscreen since anything works really.
    if (!Config::getFullscreen()) {

        //Just warn the user if they have a non optimal video mode selected.
        if (!videoMode.isValid()) {
            Log::error(std::string("non optimal video mode selected in the config file!"));
            //return false;
        }
    }

    //Here we check to go full screen
    //We just get the first full screen mode.
    //TODO (Tyler): Figure out a way to properly handle this stuff.
    if (Config::getFullscreen()) {
        m_window.create(sf::VideoMode::getFullscreenModes()[0],
            WINDOW_TITLE, sf::Style::Fullscreen, contextSettings);
    }
    else {
         m_window.create(videoMode, WINDOW_TITLE, sf::Style::Default, contextSettings);
    }

    m_window.setVerticalSyncEnabled(Config::getVSync());

    //Make sure we don't set the framerate limit to zero.
    if (Config::getFpsLimit() > 0) {
        m_window.setFramerateLimit(Config::getFpsLimit());
    }


    //Here we are just getting the settings after we have created the window.
    //And simply writing some debug about the current context settings.
    sf::ContextSettings windowSettings = m_window.getSettings();

    std::stringstream sb;
    sb << "depthBits: " << windowSettings.depthBits << ", ";
    sb << "stencilBits: " << windowSettings.stencilBits << ", ";
    sb << "antialiasingLevel: " << windowSettings.antialiasingLevel << ", ";
    sb << "majorVersion: " << windowSettings.majorVersion << ", ";
    sb << "minorVersion: " << windowSettings.minorVersion << ", ";

    //The renderer is the device that is actually getting the data from opengl.
    sb << "renderer: " << std::string((char*)glGetString(GL_RENDERER));

    Log::debug(sb.str());

    //Return true since the display settings were applied properly.
    return true;
}
示例#8
0
int main() {
	std::mt19937 generator(time(nullptr));

	sys::ComputeSystem cs;

	cs.create(sys::ComputeSystem::_gpu);

	sys::ComputeProgram prog;

	prog.loadFromFile("resources/neoKernels.cl", cs);

	std::vector<neo::AgentSPG::LayerDesc> layerDescs(3);

	layerDescs[0]._size = { 32, 32 };
	layerDescs[0]._alpha = { 0.1f, 0.001f };
	layerDescs[0]._predictiveRadius = 12;
	layerDescs[0]._feedBackRadius = 12;
	layerDescs[1]._size = { 24, 24 };
	layerDescs[2]._size = { 16, 16 };

	neo::AgentSPG agent;

	int inWidth = 32;
	int inHeight = 32;
	int aWidth = 3;
	int aHeight = 3;
	int frameSkip = 3;

	agent.createRandom(cs, prog, { inWidth, inHeight }, { aWidth, aHeight }, 12, layerDescs, { -0.05f, 0.05f }, generator);

	cl::Image2D inputImage = cl::Image2D(cs.getContext(), CL_MEM_READ_WRITE, cl::ImageFormat(CL_R, CL_FLOAT), inWidth, inHeight);
	cl::Image2D actionImage = cl::Image2D(cs.getContext(), CL_MEM_READ_WRITE, cl::ImageFormat(CL_R, CL_FLOAT), aWidth, aHeight);

	sf::VideoMode videoMode(1280, 720);

	sf::RenderWindow renderWindow;

	renderWindow.create(videoMode, "Reinforcement Learning", sf::Style::Default);

	renderWindow.setVerticalSyncEnabled(true);

	renderWindow.setFramerateLimit(60);

	// --------------------------------- Game Init -----------------------------------

	const float slimeRadius = 94.5f;
	const float ballRadius = 23.5f;
	const float wallRadius = 22.5f;
	const float fieldRadius = 640.0f;

	const float gravity = 900.0f;
	const float slimeBounce = 100.0f;
	const float wallBounceDecay = 0.8f;
	const float slimeJump = 500.0f;
	const float maxSlimeSpeed = 1000.0f;
	const float slimeMoveAccel = 5000.0f;
	const float slimeMoveDeccel = 8.0f;

	std::uniform_real_distribution<float> dist01(0.0f, 1.0f);

	sf::Vector2f fieldCenter = sf::Vector2f(renderWindow.getSize().x * 0.5f, renderWindow.getSize().y * 0.5f + 254.0f);
	sf::Vector2f wallCenter = fieldCenter + sf::Vector2f(0.0f, -182.0f);

	PhyObj blue;
	PhyObj red;
	PhyObj ball;

	blue._position = fieldCenter + sf::Vector2f(-200.0f, 0.0f);
	blue._velocity = sf::Vector2f(0.0f, 0.0f);
	red._position = fieldCenter + sf::Vector2f(200.0f, 0.0f);
	red._velocity = sf::Vector2f(0.0f, 0.0f);
	ball._position = fieldCenter + sf::Vector2f(2.0f, -300.0f);
	ball._velocity = sf::Vector2f((dist01(generator)) * 600.0f, -(dist01(generator)) * 500.0f);

	sf::Texture backgroundTexture;
	backgroundTexture.loadFromFile("resources/slimevolleyball/background.png");

	sf::Texture blueSlimeTexture;
	blueSlimeTexture.loadFromFile("resources/slimevolleyball/slimeBodyBlue.png");

	sf::Texture redSlimeTexture;
	redSlimeTexture.loadFromFile("resources/slimevolleyball/slimeBodyRed.png");

	sf::Texture ballTexture;
	ballTexture.loadFromFile("resources/slimevolleyball/ball.png");

	sf::Texture eyeTexture;
	eyeTexture.loadFromFile("resources/slimevolleyball/slimeEye.png");
	eyeTexture.setSmooth(true);

	sf::Texture arrowTexture;
	arrowTexture.loadFromFile("resources/slimevolleyball/arrow.png");

	sf::Font scoreFont;
	scoreFont.loadFromFile("resources/slimevolleyball/scoreFont.ttf");

	int scoreRed = 0;
	int scoreBlue = 0;

	int prevScoreRed = 0;
	int prevScoreBlue = 0;

	float prevBallX = fieldCenter.x;

	sf::RenderTexture blueRT;

	blueRT.create(inWidth, inHeight);

	// ------------------------------- Simulation Loop -------------------------------

	bool quit = false;

	float dt = 0.017f;

	int skipFrameCounter = 0;

	float blueReward = 0.0f;
	float redReward = 0.0f;

	std::vector<float> actionTemp(aWidth * aHeight, 0.5f);
	std::vector<float> actionTemp2(aWidth * aHeight * 2, 0.5f);

	do {
		sf::Event event;

		while (renderWindow.pollEvent(event)) {
			switch (event.type) {
			case sf::Event::Closed:
				quit = true;
				break;
			}
		}

		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
			quit = true;

		// ---------------------------------- Physics ----------------------------------

		bool blueBounced = false;
		bool redBounced = false;

		// Ball
		{
			ball._velocity.y += gravity * dt;
			ball._position += ball._velocity * dt;

			// To floor (game restart)
			if (ball._position.y + ballRadius > fieldCenter.y) {
				if (ball._position.x < fieldCenter.x)
					scoreRed++;
				else
					scoreBlue++;

				blue._position = fieldCenter + sf::Vector2f(-200.0f, 0.0f);
				blue._velocity = sf::Vector2f(0.0f, 0.0f);
				red._position = fieldCenter + sf::Vector2f(200.0f, 0.0f);
				red._velocity = sf::Vector2f(0.0f, 0.0f);
				ball._position = fieldCenter + sf::Vector2f(2.0f, -300.0f);
				ball._velocity = sf::Vector2f(((dist01(generator))) * -600.0f, -(dist01(generator)) * 500.0f);
			}

			// To wall
			if (((ball._position.x + ballRadius) > (wallCenter.x - wallRadius) && ball._position.x < wallCenter.x) || ((ball._position.x - ballRadius) < (wallCenter.x + wallRadius) && ball._position.x > wallCenter.x)) {
				// If above rounded part
				if (ball._position.y < wallCenter.y) {
					sf::Vector2f delta = ball._position - wallCenter;

					float dist = std::sqrt(delta.x * delta.x + delta.y * delta.y);

					if (dist < wallRadius + ballRadius) {
						sf::Vector2f normal = delta / dist;

						// Reflect velocity
						sf::Vector2f reflectedVelocity = ball._velocity - 2.0f * (ball._velocity.x * normal.x + ball._velocity.y * normal.y) * normal;

						ball._velocity = reflectedVelocity * wallBounceDecay;

						ball._position = wallCenter + normal * (wallRadius + ballRadius);
					}
				}
				else {
					// If on left side
					if (ball._position.x < wallCenter.x) {
						ball._velocity.x = wallBounceDecay * -ball._velocity.x;
						ball._position.x = wallCenter.x - wallRadius - ballRadius;
					}
					else {
						ball._velocity.x = wallBounceDecay * -ball._velocity.x;
						ball._position.x = wallCenter.x + wallRadius + ballRadius;
					}
				}
			}

			// To blue slime			
			{
				sf::Vector2f delta = ball._position - blue._position;

				float dist = std::sqrt(delta.x * delta.x + delta.y * delta.y);

				if (dist < slimeRadius + ballRadius) {
					sf::Vector2f normal = delta / dist;

					// Reflect velocity
					sf::Vector2f reflectedVelocity = ball._velocity - 2.0f * (ball._velocity.x * normal.x + ball._velocity.y * normal.y) * normal;

					float magnitude = std::sqrt(reflectedVelocity.x * reflectedVelocity.x + reflectedVelocity.y * reflectedVelocity.y);

					sf::Vector2f normalizedReflected = reflectedVelocity / magnitude;

					ball._velocity = blue._velocity + (magnitude > slimeBounce ? reflectedVelocity : normalizedReflected * slimeBounce);

					ball._position = blue._position + normal * (wallRadius + slimeRadius);

					blueBounced = true;
				}
			}

			// To red slime			
			{
				sf::Vector2f delta = ball._position - red._position;

				float dist = std::sqrt(delta.x * delta.x + delta.y * delta.y);

				if (dist < slimeRadius + ballRadius) {
					sf::Vector2f normal = delta / dist;

					// Reflect velocity
					sf::Vector2f reflectedVelocity = ball._velocity - 2.0f * (ball._velocity.x * normal.x + ball._velocity.y * normal.y) * normal;

					float magnitude = std::sqrt(reflectedVelocity.x * reflectedVelocity.x + reflectedVelocity.y * reflectedVelocity.y);

					sf::Vector2f normalizedReflected = reflectedVelocity / magnitude;

					ball._velocity = red._velocity + (magnitude > slimeBounce ? reflectedVelocity : normalizedReflected * slimeBounce);

					ball._position = red._position + normal * (wallRadius + slimeRadius);

					redBounced = true;
				}
			}

			// Out of field, left and right
			{
				if (ball._position.x - ballRadius < fieldCenter.x - fieldRadius) {
					ball._velocity.x = wallBounceDecay * -ball._velocity.x;
					ball._position.x = fieldCenter.x - fieldRadius + ballRadius;
				}
				else if (ball._position.x + ballRadius > fieldCenter.x + fieldRadius) {
					ball._velocity.x = wallBounceDecay * -ball._velocity.x;
					ball._position.x = fieldCenter.x + fieldRadius - ballRadius;
				}
			}
		}

		// Blue slime
		{
			blue._velocity.y += gravity * dt;
			blue._velocity.x += -slimeMoveDeccel * blue._velocity.x * dt;
			blue._position += blue._velocity * dt;

			bool moveLeft;
			bool moveRight;
			bool jump;

			sf::Image img = blueRT.getTexture().copyToImage();

			std::vector<float> greyData(img.getSize().x * img.getSize().y);

			for (int x = 0; x < img.getSize().x; x++)
				for (int y = 0; y < img.getSize().y; y++) {
					sf::Color c = img.getPixel(x, y);
					greyData[x + y * img.getSize().x] = 0.333f * (c.r / 255.0f + c.g / 255.0f + c.b / 255.0f);
				}
	
			if (skipFrameCounter == 0) {
				cs.getQueue().enqueueWriteImage(inputImage, CL_TRUE, { 0, 0, 0 }, { static_cast<cl::size_type>(inWidth), static_cast<cl::size_type>(inHeight), 1 }, 0, 0, greyData.data());

				cs.getQueue().enqueueWriteImage(actionImage, CL_TRUE, { 0, 0, 0 }, { static_cast<cl::size_type>(inWidth), static_cast<cl::size_type>(inHeight), 1 }, 0, 0, actionTemp.data());

				agent.simStep(cs, blueReward * 0.01f, inputImage, actionImage, generator);
				
				cs.getQueue().enqueueReadImage(agent.getAction(), CL_TRUE, { 0, 0, 0 }, { static_cast<cl::size_type>(aWidth), static_cast<cl::size_type>(aHeight), 1 }, 0, 0, actionTemp2.data());
			
				for (int i = 0; i < actionTemp.size(); i++) {
					if (dist01(generator) < 0.1f)
						actionTemp[i] = dist01(generator);
					else
						actionTemp[i] = actionTemp2[i * 2 + 0];
				}

				actionTemp[2] = actionTemp[0] * 3.0f + 1.0f;
				actionTemp[3] = actionTemp[0] * -2.0f + 0.4f;
				actionTemp[4] = actionTemp[0] * 2.0f - 0.4f;
				actionTemp[5] = actionTemp[0] * -2.0f - 0.4f;
				actionTemp[6] = actionTemp[1] * -1.5f + 0.2f;
				actionTemp[7] = actionTemp[1] * 2.1f - 0.4f;
				actionTemp[8] = actionTemp[1] * -2.0f + 0.4f;

				cs.getQueue().finish();
			}

			moveLeft = actionTemp[0] > 0.75f;
			moveRight = actionTemp[0] < 0.25f;
			jump = actionTemp[1] > 0.75f;

			std::cout << blueReward << " " << actionTemp[0 * 2 + 0] << " " << actionTemp[1 * 2 + 0] << std::endl;

			if (moveLeft) {
				blue._velocity.x += -slimeMoveAccel * dt;

				if (blue._velocity.x < -maxSlimeSpeed)
					blue._velocity.x = -maxSlimeSpeed;
			}
			else if (moveRight) {
				blue._velocity.x += slimeMoveAccel * dt;

				if (blue._velocity.x > maxSlimeSpeed)
					blue._velocity.x = maxSlimeSpeed;
			}

			if (blue._position.y > fieldCenter.y) {
				blue._velocity.y = 0.0f;
				blue._position.y = fieldCenter.y;

				if (jump)
					blue._velocity.y -= slimeJump;
			}

			if (blue._position.x - slimeRadius < fieldCenter.x - fieldRadius) {
				blue._velocity.x = 0.0f;
				blue._position.x = fieldCenter.x - fieldRadius + slimeRadius;
			}

			if (blue._position.x + slimeRadius > wallCenter.x - wallRadius) {
				blue._velocity.x = 0.0f;
				blue._position.x = wallCenter.x - wallRadius - slimeRadius;
			}
		}

		// Red slime
		{
			red._velocity.y += gravity * dt;
			red._velocity.x += -slimeMoveDeccel * red._velocity.x * dt;
			red._position += red._velocity * dt;

			bool moveLeft;
			bool moveRight;
			bool jump;

			moveLeft = sf::Keyboard::isKeyPressed(sf::Keyboard::Left);
			moveRight = sf::Keyboard::isKeyPressed(sf::Keyboard::Right);
			jump = sf::Keyboard::isKeyPressed(sf::Keyboard::Up);

			if (moveLeft) {
				red._velocity.x += -slimeMoveAccel * dt;

				if (red._velocity.x < -maxSlimeSpeed)
					red._velocity.x = -maxSlimeSpeed;
			}
			else if (moveRight) {
				red._velocity.x += slimeMoveAccel * dt;

				if (red._velocity.x > maxSlimeSpeed)
					red._velocity.x = maxSlimeSpeed;
			}

			if (red._position.y > fieldCenter.y) {
				red._velocity.y = 0.0f;
				red._position.y = fieldCenter.y;

				if (jump)
					red._velocity.y -= slimeJump;
			}

			if (red._position.x + slimeRadius > fieldCenter.x + fieldRadius) {
				red._velocity.x = 0.0f;
				red._position.x = fieldCenter.x + fieldRadius - slimeRadius;
			}

			if (red._position.x - slimeRadius < wallCenter.x + wallRadius) {
				red._velocity.x = 0.0f;
				red._position.x = wallCenter.x + wallRadius + slimeRadius;
			}
		}

		blueReward = scoreBlue - prevScoreBlue - (scoreRed - prevScoreRed);// -0.00005f * std::abs(ball._position.x - blue._position.x) + (blueBounced ? 0.2f : 0.0f);
		redReward = scoreRed - prevScoreRed - (scoreBlue - prevScoreBlue);// -0.00005f * std::abs(ball._position.x - red._position.x) + (redBounced ? 0.2f : 0.0f);

		prevScoreRed = scoreRed;
		prevScoreBlue = scoreBlue;
		prevBallX = ball._position.x;

		// --------------------------------- Rendering ---------------------------------

		if (!sf::Keyboard::isKeyPressed(sf::Keyboard::T)) {
			{
				renderWindow.clear();

				{
					sf::Sprite s;
					s.setTexture(backgroundTexture);
					s.setOrigin(backgroundTexture.getSize().x * 0.5f, backgroundTexture.getSize().y * 0.5f);
					s.setPosition(renderWindow.getSize().x * 0.5f, renderWindow.getSize().y * 0.5f);

					renderWindow.draw(s);
				}

				{
					sf::Sprite s;
					s.setTexture(blueSlimeTexture);
					s.setOrigin(blueSlimeTexture.getSize().x * 0.5f, blueSlimeTexture.getSize().y);
					s.setPosition(blue._position);

					renderWindow.draw(s);
				}

				{
					sf::Sprite s;
					s.setTexture(eyeTexture);
					s.setOrigin(eyeTexture.getSize().x * 0.5f, eyeTexture.getSize().y * 0.5f);
					s.setPosition(blue._position + sf::Vector2f(50.0f, -28.0f));

					sf::Vector2f delta = ball._position - s.getPosition();

					float angle = std::atan2(delta.y, delta.x);

					s.setRotation(angle * 180.0f / 3.141596f);

					renderWindow.draw(s);
				}

				{
					sf::Sprite s;
					s.setTexture(redSlimeTexture);
					s.setOrigin(redSlimeTexture.getSize().x * 0.5f, redSlimeTexture.getSize().y);
					s.setPosition(red._position);

					renderWindow.draw(s);
				}

				{
					sf::Sprite s;
					s.setTexture(eyeTexture);
					s.setOrigin(eyeTexture.getSize().x * 0.5f, eyeTexture.getSize().y * 0.5f);
					s.setPosition(red._position + sf::Vector2f(-50.0f, -28.0f));

					sf::Vector2f delta = ball._position - s.getPosition();

					float angle = std::atan2(delta.y, delta.x);

					s.setRotation(angle * 180.0f / 3.141596f);

					renderWindow.draw(s);
				}

				{
					sf::Sprite s;
					s.setTexture(ballTexture);
					s.setOrigin(ballTexture.getSize().x * 0.5f, ballTexture.getSize().y * 0.5f);
					s.setPosition(ball._position);

					renderWindow.draw(s);
				}

				if (ball._position.y + ballRadius < 0.0f) {
					sf::Sprite s;
					s.setTexture(arrowTexture);
					s.setOrigin(arrowTexture.getSize().x * 0.5f, 0.0f);
					s.setPosition(ball._position.x, 0.0f);

					renderWindow.draw(s);
				}

				{
					sf::Text scoreText;
					scoreText.setFont(scoreFont);
					scoreText.setString(std::to_string(scoreBlue));
					scoreText.setCharacterSize(100);

					float width = scoreText.getLocalBounds().width;

					scoreText.setPosition(fieldCenter.x - width * 0.5f - 100.0f, 10.0f);

					scoreText.setColor(sf::Color(100, 133, 255));

					renderWindow.draw(scoreText);
				}

				{
					sf::Text scoreText;
					scoreText.setFont(scoreFont);
					scoreText.setString(std::to_string(scoreRed));
					scoreText.setCharacterSize(100);

					float width = scoreText.getLocalBounds().width;

					scoreText.setPosition(fieldCenter.x - width * 0.5f + 100.0f, 10.0f);

					scoreText.setColor(sf::Color(255, 100, 100));

					renderWindow.draw(scoreText);
				}

				{
					sf::Sprite visionSprite;
					visionSprite.setTexture(blueRT.getTexture());
					visionSprite.scale(4.0f, 4.0f);

					renderWindow.draw(visionSprite);
				}
			}

			renderWindow.display();
		}

		blueRT.setView(renderWindow.getView());

		{
			blueRT.clear();

			{
				sf::Sprite s;
				s.setTexture(backgroundTexture);
				s.setOrigin(backgroundTexture.getSize().x * 0.5f, backgroundTexture.getSize().y * 0.5f);
				s.setPosition(renderWindow.getSize().x * 0.5f, renderWindow.getSize().y * 0.5f);

				blueRT.draw(s);
			}

			{
				sf::Sprite s;
				s.setTexture(blueSlimeTexture);
				s.setOrigin(blueSlimeTexture.getSize().x * 0.5f, blueSlimeTexture.getSize().y);
				s.setPosition(blue._position);

				blueRT.draw(s);
			}

			{
				sf::Sprite s;
				s.setTexture(eyeTexture);
				s.setOrigin(eyeTexture.getSize().x * 0.5f, eyeTexture.getSize().y * 0.5f);
				s.setPosition(blue._position + sf::Vector2f(50.0f, -28.0f));

				sf::Vector2f delta = ball._position - s.getPosition();

				float angle = std::atan2(delta.y, delta.x);

				s.setRotation(angle * 180.0f / 3.141596f);

				blueRT.draw(s);
			}

			{
				sf::Sprite s;
				s.setTexture(redSlimeTexture);
				s.setOrigin(redSlimeTexture.getSize().x * 0.5f, redSlimeTexture.getSize().y);
				s.setPosition(red._position);

				blueRT.draw(s);
			}

			{
				sf::Sprite s;
				s.setTexture(eyeTexture);
				s.setOrigin(eyeTexture.getSize().x * 0.5f, eyeTexture.getSize().y * 0.5f);
				s.setPosition(red._position + sf::Vector2f(-50.0f, -28.0f));

				sf::Vector2f delta = ball._position - s.getPosition();

				float angle = std::atan2(delta.y, delta.x);

				s.setRotation(angle * 180.0f / 3.141596f);

				blueRT.draw(s);
			}

			{
				sf::Sprite s;
				s.setTexture(ballTexture);
				s.setOrigin(ballTexture.getSize().x * 0.5f, ballTexture.getSize().y * 0.5f);
				s.setPosition(ball._position);

				blueRT.draw(s);
			}

			if (ball._position.y + ballRadius < 0.0f) {
				sf::Sprite s;
				s.setTexture(arrowTexture);
				s.setOrigin(arrowTexture.getSize().x * 0.5f, 0.0f);
				s.setPosition(ball._position.x, 0.0f);

				blueRT.draw(s);
			}

			{
				sf::Text scoreText;
				scoreText.setFont(scoreFont);
				scoreText.setString(std::to_string(scoreBlue));
				scoreText.setCharacterSize(100);

				float width = scoreText.getLocalBounds().width;

				scoreText.setPosition(fieldCenter.x - width * 0.5f - 100.0f, 10.0f);

				scoreText.setColor(sf::Color(100, 133, 255));

				blueRT.draw(scoreText);
			}

			{
				sf::Text scoreText;
				scoreText.setFont(scoreFont);
				scoreText.setString(std::to_string(scoreRed));
				scoreText.setCharacterSize(100);

				float width = scoreText.getLocalBounds().width;

				scoreText.setPosition(fieldCenter.x - width * 0.5f + 100.0f, 10.0f);

				scoreText.setColor(sf::Color(255, 100, 100));

				blueRT.draw(scoreText);
			}

			blueRT.display();
		}

		skipFrameCounter = (skipFrameCounter + 1) % frameSkip;
	} while (!quit);

	return 0;
}