I know this topic is abundant in forums, but I need help for this specific issue. I'm following this tutorial to make a basic sfml ImageManager class for a tic tac toe game. I'm having trouble understanding how to implement this class in my game engine though. I'm going to post a lot of code as there are multiple classes involved:
Board.h: my tic-tac-toe game board.
#pragma once
#include "stdafx.h"
#include <vector>
#include "Box.h"
#include "SFML/Graphics.hpp"
#include "ImageManager.h"
class Board{
public:
Board();
~Board();
std::vector<Box> &GetBoxes();
sf::Sprite GetGameBoard();
private:
sf::Sprite gameBoard;
std::vector<Box> boxes;
};
And here's Board.cpp:
#include "stdafx.h"
#include "Board.h"
#include "SFML/Graphics.hpp"
Board::Board(){
ImageManager imgr;
imgr.AddResourceDirectory("images/");
gameBoard.setTexture(imgr.GetImage("images/t3board.png"));
}
Board::~Board(){
}
std::vector<Box> &Board::GetBoxes(){
return boxes;
}
sf::Sprite Board::GetGameBoard(){
return gameBoard;
}
Here's what is relevant from the ImageManager class from the tutorial:
const sf::Texture &ImageManager::GetImage(const std::string &filename){
for(std::map<std::string, sf::Texture>::const_iterator it = textures_.begin(); it != textures_.end(); ++it){
if(filename == it->first){
std::cout << "DEBUG_MESSAGE: " << filename << " using existing image.\n";
return it->second;
}
}
//if image doesn't exist (no need for else since it will return if filename is found
sf::Texture texture;
if(texture.loadFromFile(filename)){
//create both a string and matching image in the map
textures_[filename] = texture;
std::cout << "DEBUG_MESSAGE: " << filename << " loading image.\n";
return textures_[filename];
}
// If the image has still not been found, search all registered directories
//of course, it will be empty until I specify extra directories by adding them into the vector
for(std::vector< std::string >::iterator it = resourceDirectories_.begin(); it != resourceDirectories_.end(); ++it){
if(texture.loadFromFile((*it) + filename )){
textures_[filename] = texture;
std::cout << "DEBUG_MESSAGE: " << filename << " loading image 2.\n";
return textures_[filename];
}
}
//again, notice there's no elses because returns serve as breaks
std::cout << "GAME_ERROR: Image was not found. It is filled with an empty image.\n";
textures_[filename] = texture;
return textures_[filename];
}
Finally, in my engine, I get gameBoard and draw it to my window:
void Engine::Render(){
window.clear();
window.draw(board.GetGameBoard());
window.display();
}
My window just shows a complete white background, but it's still functional otherwise. Can anybody see what I've done wrong?
I assume that textures_ is a private member of the ImageManager class? In that case you have undefined behavior because ImageManager::GetImage returns a reference to data stored in a container that is destroyed (remember that imgr is a local variable in the constructor).
Ok I have it. It's a pretty embarrasing solution, but declaring my ImageManager imgr in the constructor of Board was destroying my ImageManager instantly, so I just cut that instance and pasted it in the header file. And for some reason returning a reference instead of the actual texture value was necessary, that also stumped me.
Related
Im a second year CS student and Im attempting to make a hangman game for fun during my winter break. Ive implemented the beginning of a menu class here, and yes I know this is too much oop for a project of this scope but I intent to reuse all these classes.
Anyways valgrind is telling me an Invalid read of size 8 and it returns the following lines in order:
menu::getName (menu.cpp:13) (this is at menu.cpp\getName()\return name;)
menu::print() (menu.cpp:21) (this is at menu.cpp\print()\cout<<". return to "<getName();)
main (main.cppp:28) (this is at main.cpp\main()\thisMenu->print();)
Im usually very good at solving these types of problems, and I searched the web but I couldnt find a solution and Im completely stumped. I feel like it could be a simple issue and Im missing something but Im not sure. Any help is greatly appreciated! Thanks!
menu.cpp:
#include <vector>
using namespace std;
//contains a list of menus, allowing for us to navigate menus and keep track of where we are via linked list
class menu{
private:
//we will keep track of which menus this one can access via a vector and a parent pointer
vector<menu*> options;
string name="";
menu* parent;
public:
string getName(){
return name;
}
void insert(menu* obj){
options.push_back(obj);
}
//print all the menus this one connects to, i.e. the menus the user can access from here
void print(){
int size=options.size();
**if (parent!=nullptr){
cout<<". return to "<<parent->getName();
}**
for(int i=0; i<size; i++){
cout<<i+2<<". "<<options[i]->getName()<<endl;
}
}
menu* nextMenu(int input){
try{
return(options.at(input));
}
catch(...){
return this;
}
}
menu(string str, menu *parentIn){
parent=parentIn;
name=str;
}
};
main.cpp:
#include "SkipList.h"
#include "menu.cpp"
#include <string>
using namespace std;
int main(int argc, char** argv) {
SkipList *letterBank=new SkipList;
vector<string> wordbank();
//fill the letter bank with all lower case letters
for(char currLetter=97; currLetter<123; currLetter++){
Key currKey=to_string((int)currLetter);
Value currVal=to_string(currLetter);
letterBank->insert(currKey, currVal);
}
menu *MainMenu=new menu(string("Main Menu"), nullptr);
menu *NumOfPlayers=new menu(string("Number of Players"), MainMenu);
menu *PlayerSelect=new menu(string("Player Select"), NumOfPlayers);
menu *Game=new menu(string("Game"), NumOfPlayers);
menu *WordBankMenu=new menu(string("Word Bank Modification"), MainMenu);
MainMenu->insert(NumOfPlayers);
NumOfPlayers->insert(PlayerSelect);
PlayerSelect->insert(Game);
Game->insert(nullptr);
MainMenu->insert(WordBankMenu);
menu *thisMenu= MainMenu;
int input;
while(thisMenu!=nullptr){
thisMenu->print();
cin>>input;
thisMenu=thisMenu->nextMenu(input);
}
}
If you look at this line:
cout<<". return to "<<parent->getName();
You access the parent's name here;
But for MainMenu, parent is nullptr, therefore it's an invalid access!
The line needs to be made conditional on parent being different from nullptr.
I m learning C++ by creating simple traffic light logic using classes. In which I found this UML diagram and I want to create object types based on this. However, I created the TrafficLight class object struggling to understand control class logic part.
EDIT
To me, I just want to create traffic light for N, W, S and E. I can set light individually. Perhaps I want to deviate from the UML. I just want to learn an efficient way to do that, any help appreciated. I see UML operations overlap with constructors.
This is the UML image I m implementing in C++
I don't understand the control object part. What I understood is control is directly associated with TrafficLight class.
Added the detailed object diagram
In which each UML arrows shows 1.1 that I don't know what it means?
Here do I need to have class control with the interface name N,W,E,S or just four class instance is enough?
From this UML how can I implement the control class that has four objects N,W,E,S?
This is my code, use -std=c++11 compiler flag.
#include <iostream>
using namespace std;
class TrafficLight {
public:
enum light { red, amber, green};
// Setting the light by default red
TrafficLight(light=red){
cout << "constructed" << '\n';
} // Default constructor
// light state() {
// std::cout << "Setting the t light" << '\n';
// }
void CreateLight(light l) {
std::cout << "Creating lights" << '\n';
// show on console which lights are turned on.
if (l == light::green)
cout << "Green ligh is ON" << '\n';
else if (l == light::amber)
cout << "Amber ligh is ON" << '\n';
else
cout << "Red ligh is ON" << '\n';
}
void SwitchLight(light l) {
// switchLight operations executed
}
private:
light _state;
};
// Wondering how to proceed here? Create Light control for west, east, north and south.
class Control : public TrafficLight {
};
int main(void) {
/* code */
std::cout << " Welcome to Trafficlight signaling system " << '\n';
TrafficLight x(TrafficLight::green);
TrafficLight::light l;
// l = x.state();
l = TrafficLight::green;
x.CreateLight(TrafficLight::green);
x.CreateLight(TrafficLight::red);
x.CreateLight(TrafficLight::amber);
x.CreateLight(TrafficLight::green);
// run the derived class instance to create N,S,W,E
// Control c_obj;
return 0;
}
Base on the diagram you have, your Control would have 4 instance of TrafficLight.
While it doesn't say how exactly the would work, I would assume the intend is to call switchLight and createLight from switchControl and createLights, and you should not need to use switchLight and createLight directly.
Some code would be look somewhat like:
class TrafficLight
{
public:
enum lightColor {red, amber, green};
TrafficLight(lightColor color) : color(color){}
void SwitchLight()
{
// Change to the next state.
if(color == green) color = red;
else ++color;
}
private:
lightColor color;
}
class Control
{
public:
Control() : N(green), W(red), S(green), E(red){}
void SwitchControl()
{
// All lights change to the next state.
N.SwitchLight();
W.SwitchLight();
E.SwitchLight();
S.SwitchLight();
}
private:
TrafficLight N, W, S, E;
}
int main()
{
Control c; // N and S are green, W and E are red.
c.SwitchControl(); // N and S are red, W and E are amber.
c.SwitchControl(); // N and S are amber, W and E are green.
}
The only function you would want to call is the constructor for Control, and SwitchControl().
Note that I didn't call the full name for lightColors, where you would actually need to do that to make the code work. I also removed Create functions, as they are kind of overlapping with the ctors.
Is it possible to create text displayed on a picture with nana?
I tried this
int main() {
using namespace nana;
form fm;
place plc(fm);
picture pic(fm);
label lbl(fm, "LBL", true);
pic.load(paint::image("xxx.png"));
pic.caption("PIC");
pic.align::center, align_v::center);
lbl.transparent(true);
lbl.text_align(align::center, align_v::center);
plc.div("<<here>>");
plc["here"] << pic;
plc["here"] << lbl; // (1)
plc.collocate();
lbl.move(pic.pos());
fm.show();
exec();
}
But its shifting both to the left as nana creates a grid for 2 elements in the layout. Without adding it, so deleting (1), the label will not be shown in the layout at all.
I couldnt find any information on it online. nana::image::caption(std::string) method seems to be ignored
Is there a way to get two elements on top of each other, in a place of one element? My goal is make a picture of a waterdrop and then writing the humidity-% in the middle of it.
Thank you
Display your picture, then use nana::paint::graphics::string to write your text on top of the picture.
This
is produced by
#include <iostream>
#include <nana/gui.hpp>
#include <nana/gui/widgets/picture.hpp>
#include <nana/gui/widgets/label.hpp>
int main()
{
using namespace nana;
paint::image I("xxx.bmp");
if (I.empty())
{
msgbox err("Error");
err << "Cannot read image";
err.show();
exit(1);
}
form fm({50,50,400,700});
drawing dw(fm);
dw.draw([&I](paint::graphics& g)
{
I.paste(g, {0,0} );
g.string({200,400}, "THIS IS A TEST", colors::black);
});
fm.show();
exec();
}
I'm currently creating a little video sequence for a game in Unreal and have written a CameraDirector-class for this purpose. At the name says, it controls the players view around different camera objects played in the world.
Now I want to make my program more flexible, so I decided to put all the Camera's into an std::vector-container and use a for file to iterate through it. Now here is the problem:
#include <vector>
using namespace std;
When I put this in the header to import the std::vector, a LOT of the standard stuff created automatically by Unreal-Engine was underlined red and was no longer recognized by VS. I didn't touch a lot of this stuff, but nevertheless it wont compile anymore.
When I remove these two lines everything is fine again but I can't use std::vector.
Why does my import interferes with the program so much?
I'm using VS-2015 and Unreal Engine 4.17.1
Edit:
Due to being marked as a duplicate, it also breaks as well when I ONLY write #include <vector>. I don't see the connection to the linked question
Code in the header:
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "CameraDirector.generated.h"
#include <vector>
UCLASS()
class HOWTO_AUTOCAMERA_API ACameraDirector : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ACameraDirector();
APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
const float TimeBetweenCameraChanges = 4.0f;
const float SmoothBlendTime = 0.75f;
const float SlowBlendTime = 1.5f;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
bool isAllCamerasSelected();
void createNewCameraMove(AActor* Camera, float movingTime);
UPROPERTY(EditAnywhere)
AActor* CameraOne;
UPROPERTY(EditAnywhere)
AActor* CameraTwo;
UPROPERTY(EditAnywhere)
AActor* CameraThree;
float TimeToNextCameraChange;
};
.cpp :
// Fill out your copyright notice in the Description page of Project Settings.
#include "CameraDirector.h"
#include "Kismet/GameplayStatics.h"
// Sets default values
ACameraDirector::ACameraDirector()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ACameraDirector::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ACameraDirector::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
TimeToNextCameraChange -= DeltaTime;
if (TimeToNextCameraChange <= 0.0f)
{
TimeToNextCameraChange += TimeBetweenCameraChanges;
if (OurPlayerController && isAllCamerasSelected())
{
if ((OurPlayerController->GetViewTarget() != CameraTwo) && (OurPlayerController->GetViewTarget() != CameraThree))
{
// Blend smoothly to camera two.
OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);
}
else if ((OurPlayerController->GetViewTarget() != CameraOne) && (OurPlayerController->GetViewTarget() != CameraThree))
{
// Blend slowly to camera three.
OurPlayerController->SetViewTargetWithBlend(CameraThree, SlowBlendTime);
}
else if ((OurPlayerController->GetViewTarget() != CameraTwo) && (OurPlayerController->GetViewTarget() != CameraOne))
{
// Cut instantly to camera one.
OurPlayerController->SetViewTarget(CameraOne);
}
}
}
}
bool ACameraDirector::isAllCamerasSelected()
{
return ((CameraOne != nullptr) && (CameraTwo != nullptr) && (CameraThree != nullptr));
}
void ACameraDirector::createNewCameraMove(AActor * Camera, float movingTime)
{
OurPlayerController->SetViewTargetWithBlend(Camera, movingTime);
}
Severity Code Description Project File Line Error (active) name
followed by '::' must be a class or namespace
name HowTo_AutoCamera d:\Leon\Unreal\HowTo_AutoCamera\Source\HowTo_AutoCamera\CameraDirector.cpp 10
I'm currently stuck on some issue and don't know how to fix it.
I started working on a simple 2D engine using SFML for rendering stuff and Lua as my scripting language.
The engine starts with a splash screen first before Lua code is loaded ...
My problem is I don't know how to write a "good" draw loop for my Lua objects.
Maybe you'll understand when we take a look on my code:
Main.cpp:
...
int draw_stuff()
{
sf::RenderWindow window(sf::VideoMode(640, 480), TITLE);
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
if (!success) {
window.draw(sp_splash_screen);
}
if (clock.getElapsedTime().asSeconds() > 2) {
for (static bool first = true; first; first = false)
{
std::thread thr(&lua_module);
thr.detach();
success = true;
}
}
for (sf::CircleShape obj : CircleDrawList) {
window.draw(obj);
//window.draw(CircleDrawList.front());
}
}
return 0;
}
My CircleShape wrapper class for Lua:
/////shapes.h
extern std::list<sf::CircleShape> CircleDrawList;
class Circle
{
public:
Circle();
...
void draw();
private:
sf::CircleShape circleShape;
protected:
//~Circle();();
};
/////shapes.cpp
std::list<sf::CircleShape> CircleDrawList;
...
void Circle::draw()
{
//std::cout << "DRAW IN LIST" << std::endl;
CircleDrawList.push_front(circleShape);
//if (drawableList.size() == 4)
//drawableList.pop_front();
}
...
int luaopen_shapes(lua_State *L)
{
luabridge::getGlobalNamespace(L)
.beginClass<Circle>("Circle")
.addConstructor <void(*) (void)>()
... "other stuff to register" ...
.addFunction("draw", &Circle::draw)
.endClass();
return 1;
}
and finally (if needed) my lua script:
local ball = Circle()
ball:setColor(255,0,0,255)
while true do
ball:draw()
end
Result when the Lua Circle is moving by increasing one of the Vector2 values:
Hope you can help and I described it good :x
Thanks :)
-- Updated code in main.cpp
I'm not sure what is happening, but I see some problems in the code.
First: you don't remove "old" CircleShapes from CircleDrawList.
In the function Circle::draw() you are pushing object to the front of the list with CircleDrawList.push_front(circleShape); but you never remove anything from it. Using CircleDrawList.front() gives you access to the first element but you have to use method pop_front() to remove it.
Second thing. Look at the code:
//iterating through whole list with range-for:
for (sf::CircleShape obj : CircleDrawList)
{
//why do you use CircleDrawList.front()?
//You should probably use obj here!
window.draw(CircleDrawList.front());
}
As for now this code draws first element of the list n times where n is the length of the CircleDrawList. Do you really want to do this?
Moreover you are drawing splash every frame. If you wish to display splash only at the beginning, then the line window.draw(splash_screen); // splash screen before Lua script is loaded should probably be in some sort of conditional instruction.
I don't know what is between drawing splash_screen and drawing circles. It could have some impact on what we see on the screen.
And one more thing: it is strongly recommended to avoid using global variables. CircleDrawList is a global variable and my advice would be to put it at least in some namespace, or even better to enclose it in some class.