How can I declare a SFML window to all my class functions? - c++

This might be a noob question, but I'm trying to make a simple player move in a 2D-grid in SFML. I'm creating a while loop for rendering what is happening, and I can get it to work, but I want to use classes for the grid and players etc. The problem is that when I create a window called 'window', I don't know how to implement classes since these don't know what the 'window' is. I hope I have described my problem sufficiently, and I would like any respons on how to make this work or if my method of doing it is already bad and should be changed for another method. Here is a snippet of my code for the class and the undeclared window error.
class myEvents {
public:
//Variables
int tSize = 40;
int tileCount = 20;
int width = tileCount * tSize;
int height = tileCount * tSize;
//Function to create a grid with RectangleShapes
void grid() {
for (int i = 0; i < tileCount; i++)
{
for (int j = 0; j < tileCount; j++)
{
sf::RectangleShape tile(sf::Vector2f(40, 40));
tile.setFillColor(sf::Color::Magenta);
tile.setPosition(i*tSize, j*tSize);
window.draw(tile); //Problem occurs here, 'window' is not declared, it is in the next function
//window.draw(tile); must execute in the loop to render a full grid
}
}
}
//Includes while loop for rendering and events. Could be written without class, but I'd still like a class for the grid and later on a player.
//So I need the window to work with my classes.
void loop() {
sf::RenderWindow window(sf::VideoMode(width, height), "Game"); //'window' declared here. Can I move this statement
//somewhere so that my funcions know where it comes from?
while (window.isOpen) {
sf::Event event;
while (window.pollEvent(e))
{
//to be further developed
}
}
}
};

Try making the window a class member:
class myEvents {
public:
//Variables
int tSize = 40;
int tileCount = 20;
int width = tileCount * tSize;
int height = tileCount * tSize;
sf::RenderWindow window{sf::VideoMode(width, height), "Game"};
void grid() {
for (int i = 0; i < tileCount; i++)
{
for (int j = 0; j < tileCount; j++)
{
sf::RectangleShape tile(sf::Vector2f(40, 40));
tile.setFillColor(sf::Color::Magenta);
tile.setPosition(i*tSize, j*tSize);
window.draw(tile);
}
}
}
void loop() {
while (window.isOpen) {
sf::Event event;
while (window.pollEvent(e))
{
//to be further developed
}
}
}
};
Alternatively, pass the window around:
class myEvents {
public:
//Variables
int tSize = 40;
int tileCount = 20;
int width = tileCount * tSize;
int height = tileCount * tSize;
void grid(sf::RenderWindow& window) {
for (int i = 0; i < tileCount; i++)
{
for (int j = 0; j < tileCount; j++)
{
sf::RectangleShape tile(sf::Vector2f(40, 40));
tile.setFillColor(sf::Color::Magenta);
tile.setPosition(i*tSize, j*tSize);
window.draw(tile);
}
}
}
void loop() {
sf::RenderWindow window{sf::VideoMode(width, height), "Game"};
while (window.isOpen) {
sf::Event event;
while (window.pollEvent(e))
{
//to be further developed
// call grid(window)
}
}
}
};

Well an easy thing for the window you can do is to create a class and
add the window in it, then include the .h where the class is as you've set the sf::window in the public section. Now I will show you how you can use it
we've got an .h file named window.h (you can name it whatever is comfortable for you)
#include <SFML/Grpahics.hpp>
class window
{
public:
sf::RenderWindow window;
}
and you have the main.cpp(or whatever file you want)
#include "window.h"
window w;
int main()
{
w.window.create(sf::VideoMode(800,600),"Title");
}
the int main() can be whatever function you want it just has to be
called as soon as possible so the window will show.
I hope this helps you with your problem =)
[EDID]:
As the "sf::RenderWindow window" is public every file that has the header with the public "sf::RenderWindow window" can use the window as it is not private. I think you know that but in any case to add it.

Related

access to variable in c++ inner class

I'm using cairomm, opencv4, box2d(not revealed in below code) to make physics education video.
My plan is like this.
Many Sobject(Scientific obect) constitute a Scene.
So I decided to use inner-class.(I don't know it's best design, I'm newbie to programming)
My problem is in below.
cv::Mat Surface2Mat(Cairo::RefPtr<Cairo::ImageSurface> surface)
{
cv::Mat Frame(surface->get_height(), surface->get_width(), CV_8UC4, surface->get_data(), surface->get_stride());
cv::cvtColor(Frame, Frame, cv::ColorConversionCodes::COLOR_BGRA2BGR);
return Frame;
}
class Scene
{
private:
int surface_width = 1920;
int surface_height = 1080;
int second = 4;
cv::Size resolution = {surface_width, surface_height};
const int mp4 = cv::VideoWriter::fourcc('a', 'v', 'c', '1');
cv::VideoWriter video;
double FPS;
public:
class Sobject
{
private:
double width;
double height;
double color[3] = {1, 1, 1};
public:
Cairo::RefPtr<Cairo::Context> cr;
Cairo::RefPtr<Cairo::ImageSurface> surface;
Sobject()
{
surface = Cairo::ImageSurface::create(Cairo::Format::FORMAT_ARGB32, 1920, 1080);
cr = Cairo::Context::create(surface);
}
void
set_position(double x = 0, double y = 0)
{
cr->move_to(960, 540);
}
void drawCircle()
{
cr->arc(0, 0, 40, 0.0, 2 * M_PI);
}
};
Scene(int width = 1920, int height = 1080)
{
video.open("Scene.mp4", mp4, FPS = 30, resolution, true);
}
~Scene()
{
video.release();
}
void write()
{
for (int i = 0; i < (FPS * second); i++)
{
video.write(Surface2Mat(surface));
}
}
};
The "video.write(Surface2Mat(surface));" at last makes problem.
How can I access to the surface?
You have not created an instance of Sobject. You can do something like:
class Scene
{
....
public:
class Sobject
{...};
Sobject mSobject; // can have it public or private depending on other requirements
....
void write()
{
for (int i = 0; i < (FPS * second); i++)
{
// now that you have an instance of Sobject, you can use surface from it
video.write(Surface2Mat(mSobject.surface));
}
}

Why does the platform created with for cycle go over the border limit?

I've started programming just recently and I've learned the basic concepts of classes and objects and how to create them. So I decided to try and create a simple game of breakout with what I've learned so far. I've only created the main movable platform with a for cycle and make it move horizontally with the directional keys so far. I've also created a void so the platform doesn't go over the border of the screen but it doesn't work and I've tried all I could think of. Can someone please tell me what I'm doing wrong?
Game::Game( MainWindow& wnd )
:
wnd( wnd ),
gfx( wnd )
{
}
void Game::Go()
{
gfx.BeginFrame();
UpdateModel();
ComposeFrame();
gfx.EndFrame();
}
void Game::UpdateModel()
{
if (wnd.kbd.KeyIsPressed(VK_RIGHT))
{
platform.vx += 3;
}
if (wnd.kbd.KeyIsPressed(VK_LEFT))
{
platform.vx -= 3;
}
platform.ScreenLimit();
}
void Game::ComposeFrame()
{
for (platform.x = 460; platform.x <= platform.w; platform.x++)
{
for (platform.y = 500; platform.y <= platform.h; platform.y++)
{
gfx.PutPixel(platform.x + platform.vx, platform.y, 255, 255, 255);
}
}
}
and here's the header file and source file of the class I created for the platform:
Platform.h
#pragma once
#include "Graphics.h"
class Platform
{
public:
int x = 460;
int y = 500;
int vx = 0;
int width = 60;
int heigth = 10;
int w = x + width;
int h = y + heigth;
void ScreenLimit();
private:
};
Platform.cpp
#include "Platform.h"
void Platform::ScreenLimit()
{
const int left_base = x;
const int right_base = w;
if (right_base >= Graphics::ScreenWidth)
{
x = (Graphics::ScreenWidth - 6) - width;
}
else if (left_base <= 0)
{
x = 0;
}
}

GTKMM buttons in a grid

just learned the concept of GTKMM and found out that I enjoyed this, compared to just C++, which is pretty boring just programming in the terminal. As I decided to create a code that will make a 8 x 8 buttons of table, I encountered a problem, which is how to set every button to my desired position, because the code I created just makes 64 buttons horizontally. Can anyone help me here? Thanks
examplewindow.h (The code the class attributes and methods)
#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H
#include <gtkmm.h>
class ExampleWindow : public Gtk::Window
{
public:
ExampleWindow();
virtual ~ExampleWindow();
private:
// Signal handlers:
void on_button_numbered(const Glib::ustring& data);
// Child widgets:
Gtk::Grid m_grid;
Gtk::Button button[8][8];
};
#endif /* GTKMM_EXAMPLEWINDOW_H */
examplewindow.cc (The code for modifying the attributes and methods)
#include <iostream>
#include "examplewindow.h"
ExampleWindow::ExampleWindow()
{
set_title("Mr. Sandman");
set_border_width(12);
int i, j;
add(m_grid);
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
m_grid.add(button[i][j]);
}
}
for (int i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
button[i][j].signal_clicked().connect(
sigc::bind<Glib::ustring>( sigc::mem_fun(*this,
&ExampleWindow::on_button_numbered), "button 1") );
}
}
m_grid.show_all();
}
ExampleWindow::~ExampleWindow()
{
}
void
ExampleWindow::on_button_numbered(const Glib::ustring& data)
{
std::cout << data << " was pressed" << std::endl;
}
main.cc (The main function)
#include "examplewindow.h"
#include <gtkmm/application.h>
int main(int argc, char *argv[])
{
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
ExampleWindow window;
// Shows the window and returns when it is closed.
return app->run(window);
}
instead of using m_Grid.add() try using attach() or attach_next_to()
so you can either give row/column position in your loop or attach button 9 below button 1 and button 2 to the right of button 1
https://developer.gnome.org/gtkmm/unstable/classGtk_1_1Grid.html#a9c425e95660daff60a77fc0cafc18115

My array of sprites is not getting drawn on my renderwindow

So I am trying to make a chessgame, and of course I am starting out with just making the board. For this I am creating a two-dimensional array like 8x8. Each tile has their own object sprite called tileSprite and I am trying to define them as 1/8th of the width and height of the screen, which has a fixed size of 1024x768. The textures that are loaded in are just 1 pixel black or white. The program gives no definitive error, but the drawn tiles aren't getting displayed onto my window, and all I see is a red screen, which I get from clearing the screen (following the standard clear/draw/display cycle of SFML).
#include "SFML/Window.hpp"
#include "SFML/Graphics.hpp"
#include "SFML/Audio.hpp"
#include <iostream>
#include <vector>
#include <array>
bool playing = true;
class Textures {
public:
static void loadTextures();
sf::Texture static blackTile;
sf::Texture static whiteTile;
};
/*---Class--Definitions----*/
sf::Texture Textures::blackTile;
sf::Texture Textures::whiteTile;
/*-------------------------*/
void Textures::loadTextures() {
if (blackTile.loadFromFile("Images/blackTile.PNG")) {
return;
}
else if (whiteTile.loadFromFile("Images/whiteTile.PNG")) {
return;
}
}
class ChessBoard_Tiles {
public:
static void _initialize();
static void draw(sf::RenderWindow& window);
enum TileStatus { EMPTY, OCCUPIED, HIGHLIGHTED };
struct TileSlot {
sf::Sprite tileSprite;
TileStatus tileStatus;
};
private:
typedef std::array< std::array<TileSlot*, 8>, 8 > TileType;
static TileType tileBoard;
};
/*-Class Definition that has to be called-*/
ChessBoard_Tiles::TileType ChessBoard_Tiles::tileBoard = ChessBoard_Tiles::TileType();
void ChessBoard_Tiles::_initialize() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
tileBoard[i][j] = new TileSlot();
if ((i + j) % 2 == 0) {
tileBoard[i][j]->tileSprite.setTexture(Textures::whiteTile);
}
else {
tileBoard[i][j]->tileSprite.setTexture(Textures::blackTile);
}
tileBoard[i][j]->tileSprite.setPosition(128 * j, 96 * i);
tileBoard[i][j]->tileSprite.setScale(128, 96);
tileBoard[i][j]->tileStatus = EMPTY;
}
}
}
void ChessBoard_Tiles::draw(sf::RenderWindow& window) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
window.draw(tileBoard[i][j]->tileSprite);
}
}
}
int main(int argc, char* argv[]) {
sf::RenderWindow renderWindow;
renderWindow.create(sf::VideoMode(1024, 768), "Chess");
Textures::loadTextures();
ChessBoard_Tiles::_initialize();
while (playing) {
sf::Event currentEvent;
renderWindow.pollEvent(currentEvent);
if (currentEvent.type == sf::Event::Closed) {
renderWindow.close();
playing = false;
}
if (currentEvent.type == sf::Event::KeyPressed) {
if (currentEvent.key.code == sf::Keyboard::Escape) {
renderWindow.close();
playing = false;
}
}
renderWindow.clear(sf::Color::Red);
std::cout << "Clear\n";
ChessBoard_Tiles::draw(renderWindow);
std::cout << "Draw\n";
renderWindow.display();
std::cout << "Display\n";
}
return 0;
}
If anyone knows what is wrong then that would be a big help for me.. Otherwise I'd probably have to entirely remake this program, which I think should work so far, but I haven't the slightest idea why it doesn't. Big thanks in advance =)
EDIT: Read a little about how the sprites seem to disappear if the textures are running out of scope.. If this is the case, could that just be pointed out and then I can work on that, because I have tried so many different things by now that I feel like I'm just going in circles?
The fault was from the loadTextures() function, where I had forgotten to include the file extension of the file to be loaded, and I screwed the logic about the loadFromFile() function up so the program only continued when it couldn't load the file..

X in namespace 'sf' does not name a type [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I am working with SFML1.6 to produce a graphical app (a game). It was working fine when I only had one file beyond the Main file. Now I added a new file, Level, and I get these errors:
C:\Users\...\Window.hpp|6|error: 'RenderWindow' in namespace 'sf' does not name a type|
C:\Users\...\Window.hpp|7|error: 'Image' in namespace 'sf' does not name a type|
C:\Users\...\Window.hpp|8|error: 'Sprite' in namespace 'sf' does not name a type|
C:\Users\...\Window.hpp|9|error: 'Color' in namespace 'sf' does not name a type|
Since it was working fine, I suppose it is due to the new file:
Level.cpp
#include <SFML/Window.hpp>
#include <iostream>
#include "Window.hpp"
class Level
{
sf::Window* pResultScreen;
public:
Level( sf::Window& );
};
Level::Level( sf::Window &app)
{
pResultScreen = &app;
};
Level.hpp
#ifndef Level_hpp
#define Level_hpp
class Level
{
sf::Window* pResultScreen;
public:
Level( sf::Window& );
};
#endif
Does anyone see a problem with the above code?
EDIT:
Window.cpp
class Window
{
sf::RenderWindow appWindow;
sf::Image charImage;
sf::Sprite charSpriteSheet;
sf::Color deleteColor;
bool keyPressed;
int curFrame;
int stateChar;
int timerFrame;
int flipChar;
public:
Window();
int Loop();
void SheetCutter(int); // Prepares tiles
void Animate(int); // Loop through animations
void ColourCleaner(); // Remove the sprite's color.
};
Window::Window()
{
stateChar = 0;
curFrame = 0;
flipChar = 1;
deleteColor.a = 255;
deleteColor.r = 255;
deleteColor.g = 47;
deleteColor.b = 198;
appWindow.Create(sf::VideoMode( 800, 600, 32), "AI_Fighter");
appWindow.SetFramerateLimit(30);
if( !charImage.LoadFromFile("Bass.png") )
{
std::cout << "Problem opening file 'Bass.png'";
}
charImage.SetSmooth(false);
ColourCleaner();
charSpriteSheet.SetImage(charImage);
SheetCutter(curFrame); // This allows it to not show the entire tile set at the beginning.
};
int Window::Loop()
{
// Start game loop
while (appWindow.IsOpened())
{
sf::Event evt;
while (appWindow.GetEvent(evt))
{
// Window closed
if (evt.Type == sf::Event::Closed)
appWindow.Close();
// Escape key pressed
if ((evt.Type == sf::Event::KeyPressed) && (evt.Key.Code == sf::Key::Escape))
appWindow.Close();
if (evt.Type == sf::Event::KeyPressed)
keyPressed = true;
else
keyPressed = false;
}
// Get elapsed time
float ElapsedTime = appWindow.GetFrameTime();
// Move the sprite
if ( appWindow.GetInput().IsKeyDown(sf::Key::Left) || appWindow.GetInput().IsKeyDown(sf::Key::Right) || appWindow.GetInput().IsKeyDown(sf::Key::Up) || appWindow.GetInput().IsKeyDown(sf::Key::Down) )
{
if (appWindow.GetInput().IsKeyDown(sf::Key::Left))
{
charSpriteSheet.Move(-100 * ElapsedTime, 0);
stateChar = 1;
flipChar = 0;
Animate(6);
}
if (appWindow.GetInput().IsKeyDown(sf::Key::Right))
{
charSpriteSheet.Move( 100 * ElapsedTime, 0);
stateChar = 1;
flipChar = 1;
Animate(6);
}
if (appWindow.GetInput().IsKeyDown(sf::Key::Up))
{
charSpriteSheet.Move(0, -100 * ElapsedTime);
stateChar = 2;
Animate(6);
}
if (appWindow.GetInput().IsKeyDown(sf::Key::Down)) charSpriteSheet.Move(0, 100 * ElapsedTime);
}
else
{
stateChar = 0;
Animate(12);
}
// Clear the screen (fill it with black color)
appWindow.Clear(sf::Color( 0, 0, 0));
appWindow.Draw(charSpriteSheet);
// Display window contents on screen
appWindow.Display();
}
return 0;
};
void Window::SheetCutter(int offset)
{
charSpriteSheet.SetSubRect(sf::IntRect((offset * 26), 0, ((offset * 26) + 26), 35));
};
// This changes the curFrame, so that animations loop and stuff. Pretty easy, although unelegant.
void Window::Animate(int rate)
{
charSpriteSheet.FlipX(flipChar);
if((timerFrame%rate) == 0) // This is, rather obviously, a variable designed to allow to change the frames at the right rate.
{
if(stateChar == 0) // ? Not getting activated. Not getting called...
{
if(curFrame >= 2)
{
curFrame = 0;
}
else
{
curFrame++;
}
}
else if(stateChar == 1) // Walking.
{
if(curFrame >= 5 || curFrame <= 2 )
{
curFrame = 3;
}
else
{
curFrame++;
}
}
else curFrame = 6; // Jump.
SheetCutter(curFrame);
}
std::cout << stateChar;
timerFrame++;
};
// This removes the magenta background, changing the colour to tempClr. Color doesn't really matter as long as the fourth digit is set
// to 0, since it's the alpha value.
void Window::ColourCleaner()
{
sf::Color tempClr(0, 0, 0, 0);
for(int i = 0; i < 182; i++ )
{
for(int j = 0; j < 35; j++)
{
sf::Color CLR = charImage.GetPixel(i, j);
if(deleteColor == CLR)
{
charImage.SetPixel(i, j, tempClr);
}
}
}
};
Window.hpp
#ifndef Window_hpp
#define Window_hpp
class Window
{
sf::RenderWindow appWindow;
sf::Image charImage;
sf::Sprite charSpriteSheet;
sf::Color deleteColor;
int curFrame;
int stateChar;
int timerFrame;
public:
Window();
int Loop();
void SheetCutter();
void Animate(int rate);
void ColourCleaner();
};
#endif
You should put the #include <SFML/Window.hpp> into your header file, as you need its definitions there. (the source file should then include the header instead of duplicating its contents