BlinkenArea - GitList
Repositories
Blog
Wiki
Blinker
Code
Commits
Branches
Tags
Search
Tree:
8432360
Branches
Tags
master
Blinker
src
common
Game.cpp
pong: activate when player joins
Stefan Schuermans
commited
8432360
at 2019-06-15 21:44:37
Game.cpp
Blame
History
Raw
/* Blinker Copyright 2011-2019 Stefan Schuermans <stefan@blinkenarea.org> Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html a blinkenarea.org project */ #include <string> #include <vector> #include <BlinkenLib/BlinkenFrame.h> #include "File.h" #include "Format.h" #include "FormatFile.h" #include "Game.h" #include "Mgrs.h" #include "Module.h" #include "OutStreamFile.h" namespace Blinker { /** * @brief constructor * @param[in] name module name * @param[in] mgrs managers * @param[in] dirBase base directory */ Game::Game(const std::string &name, Mgrs &mgrs, const Directory &dirBase): Module(name, mgrs, dirBase), m_fileFormat(dirBase.getFile("format")), m_fileBackgroundColor(dirBase.getFile("backgroundColor")), m_fileOutStream(dirBase.getFile("outstream"), mgrs.m_streamMgr), m_height(0), m_width(0), m_channels(0), m_imgBuf(), m_backgroundColor() { } /// virtual destructor Game::~Game() { // clean up deactivate(); } /// check for update of configuration void Game::updateConfig() { bool doReinit = false; bool doRedraw = false; // format file was modified -> re-create canvas and schedule redraw if (m_fileFormat.checkModified()) { m_fileFormat.update(); createImgBuf(); doReinit = true; } // color file was modified -> convert color, schedule redraw if (colorUpdate(m_fileBackgroundColor, m_backgroundColor)) { doRedraw = true; } // output stream name file was modified -> re-get output stream if (m_fileOutStream.checkModified()) { m_fileOutStream.update(); } // check config update of derived game if (updateConfigGame()) { doRedraw = true; } // re-initialize / redraw if (doReinit) { reinitialize(); doRedraw = true; } if (doRedraw) { redraw(); } } /// activate game: set up image buffer, call redraw() void Game::activate() { createImgBuf(); reinitialize(); redraw(); } /// deactivate game: tear down image buffer, deactivate output void Game::deactivate() { destroyImgBuf(); sendFrame(); } /// check if game is active bool Game::isActive() const { return ! m_imgBuf.empty(); // game is active if there is an image buffer } /// set pixel in image buffer void Game::pixel(int y, int x, ColorData const &cd) { if (m_imgBuf.empty() || ! checkLimitInt(y, 0, m_height - 1) || ! checkLimitInt(x, 0, m_width - 1)) { return; } int pos = (y * m_width + x) * m_channels; std::copy(cd.begin(), cd.end(), m_imgBuf.begin() + pos); } /// draw horizontal line to image buffer void Game::lineHor(int y, int x1, int x2, ColorData const &cd) { if (m_imgBuf.empty() || ! checkLimitInt(y, 0, m_height - 1) || ! checkIntRangeLimit(x1, x2, 0, m_width - 1)) { return; } int pos = (y * m_width + x1) * m_channels; int dx = m_channels; for (int x = x1; x <= x2; ++x) { std::copy(cd.begin(), cd.end(), m_imgBuf.begin() + pos); pos += dx; } } /// draw vertical line to image buffer void Game::lineVert(int y1, int y2, int x, ColorData const &cd) { if (m_imgBuf.empty() || ! checkIntRangeLimit(y1, y2, 0, m_height - 1) || ! checkLimitInt(x, 0, m_width - 1)) { return; } int pos = (y1 * m_width + x) * m_channels; int dy = m_width * m_channels; for (int y = y1; y <= y2; ++y) { std::copy(cd.begin(), cd.end(), m_imgBuf.begin() + pos); pos += dy; } } /// draw non-filled rectangle to image buffer void Game::rect(int y1, int y2, int x1, int x2, ColorData const &cd) { lineHor(y1, x1, x2, cd); lineHor(y2, x1, x2, cd); lineVert(y1, y2, x1, cd); lineVert(y1, y2, x2, cd); } /// draw filled rectangle to image buffer void Game::rectFill(int y1, int y2, int x1, int x2, ColorData const &cd) { if (m_imgBuf.empty() || ! checkIntRangeLimit(y1, y2, 0, m_height - 1) || ! checkIntRangeLimit(x1, x2, 0, m_width - 1)) { return; } int pos = (y1 * m_width + x1) * m_channels; int dx = m_channels; int dy = m_width - (x2 - x1 + 1) * m_channels; for (int y = y1; y <= y2; ++y) { for (int x = x1; x <= x2; ++x) { std::copy(cd.begin(), cd.end(), m_imgBuf.begin() + pos); pos += dx; } pos += dy; } } /// process update of color file, return true on update bool Game::colorUpdate(ColorFile &colorFile, ColorData &data) const { if (colorFile.checkModified()) { colorFile.update(); color2data(colorFile, data); return true; } else { return false; } } /// convert color to raw color data void Game::color2data(ColorFile const &colorFile, ColorData &data) const { if (! m_fileFormat.m_valid) { data.clear(); } else { unsigned int channels = m_fileFormat.m_obj.m_channels; unsigned int maxval = m_fileFormat.m_obj.m_maxval; data.resize(m_fileFormat.m_obj.m_channels); Color const &color = colorFile.m_obj; if (channels == 1) { // single channel // convert to monochrome according to CIE XYZ double val = 0.2125 * color.m_red + 0.7154 * color.m_green + 0.0721 * color.m_blue; // adapt to maxval and round data.at(0) = (unsigned char)(val * maxval / 255.0 + 0.5); } else if (channels == 2) { // two channels // adapt to maxval and round, ignore blue data.at(0) = (unsigned char)(color.m_red * maxval / 255.0 + 0.5); data.at(1) = (unsigned char)(color.m_green * maxval / 255.0 + 0.5); } else if (channels >= 3) { // three channels (more than three channels: further channels are dark) // adapt to maxval and round data.at(0) = (unsigned char)(color.m_red * maxval / 255.0 + 0.5); data.at(1) = (unsigned char)(color.m_green * maxval / 255.0 + 0.5); data.at(2) = (unsigned char)(color.m_blue * maxval / 255.0 + 0.5); } } } /// send current image buffer as frame to output stream void Game::sendFrame() { // image buffer available -> send its contents as frame if (! m_imgBuf.empty()) { Format const &fmt = m_fileFormat.m_obj; stBlinkenFrame *pFrame = BlinkenFrameNew(fmt.m_height, fmt.m_width, fmt.m_channels, fmt.m_maxval, 1); BlinkenFrameSetPixelData(pFrame, 0, m_height, 0, m_width, 0, m_channels, m_imgBuf.data()); m_fileOutStream.setFrame(pFrame); BlinkenFrameFree(pFrame); } // no image buffer available -> send "no frame" information else { m_fileOutStream.setFrame(NULL); } } /// (re-)create image buffer void Game::createImgBuf() { // get rid of old image buffer destroyImgBuf(); // read format from format file m_fileFormat.update(); if (! m_fileFormat.m_valid) return; // read background color m_fileBackgroundColor.update(); if (! m_fileBackgroundColor.m_valid) return; // store parameters m_height = m_fileFormat.m_obj.m_height; m_width = m_fileFormat.m_obj.m_width; m_channels = m_fileFormat.m_obj.m_channels; // create image buffer m_imgBuf.resize(m_height * m_width * m_channels); // convert background color color2data(m_fileBackgroundColor, m_backgroundColor); } /// tear down image buffer void Game::destroyImgBuf() { m_imgBuf.clear(); m_backgroundColor.clear(); } } // namespace Blinker