Here is the relevant code:
Canvas.cpp
#ifndef CANVAS
#define CANVAS
#include "graphicsDatatypes.h"
class Canvas
{
private:
// Current and next points to draw to
struct cartesianPoint currentPoint, nextPoint;
public:
Canvas::Canvas() { numLinesDrawn = 0; };
Canvas::~Canvas();
struct cartesianPoint getCurrentPoint() { return currentPoint; };
void setCurrentPoint(int x, int y)
{
currentPoint.x = x;
currentPoint.y = y;
}
};
#endif
main.cpp
#include "glut-3.7.6-bin\glut.h"
#include "Canvas.cpp"
// Window size
int winWidth, winHeight;
// User's drawing space - current maximum of 4000 lines
Canvas userDrawSpace();
void callbackMouse(int button, int state, int x, int y)
{
userDrawSpace.setCurrentPoint(x, y);
}
The error I am getting is - error C2228: left of '.setCurrentPoint' must have class/struct/union
Any idea why? The class is pretty clearly defined, and include should simply be bringing in the text. Visual studios recognizes that Canvas is a class when I hover over it with my mouse, so I have no clue what's going on. Any help is appreciated, thanks.
The line
Canvas userDrawSpace();
looks like it should be creating Canvas object, but in fact it declares a function called userDrawSpace returning a Canvas object :-(.
That's a very common gotcha in C++.
Just get rid of the () and it should be ok.
Related
I am using SFML to create a space invaders clone with C++. I am quite new to C++ and I'm learning it as I'm working on this project.
I am getting the following error when trying to create a new enemy using the constructor and array to set settings for each created enemy:
1>enemy.cpp
1>C:\Users\dzamm\source\repos\SFML\enemy.cpp(35,1): error C2280: 'Enemy &Enemy::operator =(const Enemy &)': attempting to reference a deleted function
1>C:\Users\dzamm\source\repos\SFML\enemy.h(55): message : compiler has generated 'Enemy::operator =' here
1>C:\Users\dzamm\source\repos\SFML\enemy.h(55,1): message : 'Enemy &Enemy::operator =(const Enemy &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'sf::RenderWindow &sf::RenderWindow::operator =(const sf::RenderWindow &)'
Enemy Constructor:
Enemy alienArray[NUMBER_OF_ALIENS];
//constructor sets ID number, loads sprite
Enemy::Enemy(const int id, float sp)
{
//set alive
mIsAlive = true;
//set speed
enemySpeed = sp;
// Load an enemy texture
if (!mEnemyTexture.loadFromFile("Media/Textures/PixelSpaceships/red_01.png")) {
// Handle loading error
std::cout << "Oh No! File not loaded." << std::endl;
}
//scale sprite and set texture so we know size
enemySprite.setTexture(mEnemyTexture);
}
Enemy loader method
void Enemy::loader(int noOfAliens) { // might add xPosition;yPosition
for (int i = 0; i < noOfAliens; i++)
{
Enemy alien(i, 10.f); // speed issue
alien.setLocation(i * 100.f + 50.f, alien.getSprite().getGlobalBounds().height / 2);
line 35 alienArray[i] = alien;
//alienArray.push_back(alien);
}
}
1>C:\Users\dzamm\source\repos\SFML\enemy.cpp(35,1): error C2280: 'Enemy &Enemy::operator =(const Enemy &)': attempting to reference a deleted function
Enemy Header file:
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#pragma once
#define NUMBER_OF_ALIENS 4
//class Game;
class Enemy
{
public:
//constructor sets ID number, loads sprite
Enemy() {};
Enemy(const int, float);
sf::Sprite& getSprite();
void kill();
bool isAlive();
void load();
void loader(const int noOfAliens);
void setLocation(float xPosition, float yPosition);
void enemyInstantiator(int noOfEnemies, float xPosition, float yPosition);
void update();
void render(sf::RenderWindow& window);
private:
void enemyBehaviour(std::vector<sf::Sprite>& enemyList);
void enemyMovement(std::vector<Enemy>& enemyList);
private:
sf::Texture mEnemyTexture;
sf::Sprite enemySprite;
//std::vector<Enemy> alienArray;
//std::vector<sf::Sprite> mEnemies;
sf::RectangleShape mEnemyBounds;
sf::RenderWindow mWindow;
bool mIsShooting;
bool mIsAlive;
float enemySpeed;
};
I read on forums that issue is related to working with a copy of the object instead of the original object, however I am not sure how to handle this to reference the original object I'm modifying.
To reproduce create a constructor for Enemy.cpp class, create an entity Enemy alien using for loop in method as shown in Enemy::loader and store the created entity in the Enemy alienArray as shown by index.
The issue was related to an sf::RenderWindow reference that was not being even utilised in the code.
sf::RenderWindow &sf::RenderWindow::operator =(const sf::RenderWindow &)
Once I removed this all errors disappeared.
I have been attempting to make some code, but I am a bit new to c++ and need some help.
I cannot instantiate class Player as a pointer, because it's an "incomplete type" (or undefined type, vs says both). Below are some (simplified, albeit not very) versions of my code:
Entity.h
#pragma once
#include <vector>
class Entity
{
public:
static void init();
class EntityObject;
class Player;
static std::vector<EntityObject*> entities;
};
Entity.cpp
#include "Entity.h"
void Entity::init()
{
entities = std::vector<EntityObject*>();
}
class Entity::EntityObject
{
private:
float velX, velY, x, y;
public:
EntityObject(float xa, float ya) { x = xa; y = ya; }
float getVelX() { return velX; }
float getVelY() { return velY; }
float getX() { return x; }
float getY() { return y; }
};
class Entity::Player : EntityObject
{
public:
Player(float xa, float ya) : EntityObject(xa, ya)
{
printf("Player created");
}
};
Can anyone tell me why
#include "Entity.h"
int main(int argc, char* argv)
{
Entity::init();
Entity::EntityObject* player = new Entity::Player(10.0f, 10.0f);
Entity::entities.push_back(player);
}
gives an incomplete/undefined type?
Thanks.
Edit:
The errors are:
Both errors direct to this line: Entity::EntityObject* player = new Entity::Player(10.0f, 10.0f);
Error (active) E0070 incomplete type is not allowed
Error C2027 use of undefined type 'Entity::Player'
You defined the Entity::Player class in the .cpp file, not in the .h file. Therefore, even though the main() includes the .h file, it does not know about Entity::Player.
Entity::Player is forward declared in Entity.h.
When the compiler compiles your main.cpp module, it does not know anything about this class except that it exists, in particular it has no idea that this class as a constructor taking two float : Player(float xa, float ya)
=> Your issue is related to forward declaring, not nested class.
Read this thread to understand your problem
What are forward declarations in C++?
Read this one to understand what you can and what you can't do with forward declaration
When can I use a forward declaration?
I'm a game designer coming from a Basic-like programming language and moving to C++.
For a new game I'd like to have a gui programmed using OOP.
My gui currently consists of a gui-class (the outer wrapper), a g_element-class (the middle wrapper containing all the common attributes) and a button-class (overriding and extending the g_element-class).
The problem is I'm getting the following error:
Severity Code Description Project File Line Suppression State
Error LNK2001 unresolved external symbol "public: static class
std::list,class std::allocator > > gui
::el_stack"(?el_stack#?$gui#V?$g_element#Vbutton######2V?$list#V?$g_element#Vbutton####V?$allocator#V?$g_element#Vbutton#####std###std##A)
I really think that this error is not the only problem - I might have a completely wrong approach for this whole thing. I'm also not really sure about that template-thing - I thought I'd be able to expand my g_element-class with gui-elements later (i.e. buttons, sliders, windows...) - but give me a hint if there's something that I can optimise.
Here is my gui.cpp file (so far):
using namespace std;
template <class GUI_ELEMENT> class gui {
protected:
void add_to_stack(GUI_ELEMENT elem) {
// The error comes from here..
// I wanted a list of all my g_elements (buttons)
el_stack.push_back(elem);
printf("size now: %d", el_stack.size());
}
unsigned int get_stack_size() {
return el_stack.size();
}
public:
static list<GUI_ELEMENT> el_stack; // The elements list
void render() {
// here, I'd like to iterate over all i.e. buttons to draw them
}
};
template <class GUI_ELEMENT> class g_element : public gui<g_element<GUI_ELEMENT> >{
private:
float x;
float y;
float w;
float h;
public:
void set_width(float width) {
this->w = width;
}
float get_width() {
return this->w;
}
};
class button : public g_element<button> {
protected:
char* caption;
public:
button(float x, float y, float w, float h, char* caption) {
this->set_width(w);
this->set_caption(caption);
this->add_to_stack(*this);
}
void set_caption(char* caption) {
this->caption = caption;
}
char* get_caption() {
return this->caption;
}
};
I'd like to use my gui like so:
// Create a few test buttons
button b1(50, 50, 100, 50, "Test");
b1.set_width(150);
float s = b1.get_width();
printf("size w: %f", s);
printf("\ncaption: %s", b1.get_caption());
button b2(50, 50, 100, 50, "Test");
button b3(50, 50, 100, 50, "Test2");
button b4(50, 50, 100, 50, "Test3");
// Rendering currently (all buttons at once)
gui<button> G;
G.render();
// but this would be nicer:
gui::render_buttons()
// or
gui<button>::render()
Is there somebody who might help me? Really big thanks in advance!
All static fields should be defined outside of the class definition. In your case you have to add these lines of code after a class definition:
template<class GUI_ELEMENT>
list<GUI_ELEMENT> gui<GUI_ELEMENT>::el_stack;
The problem says:
Define a class Arc, which draws a part of an ellipse. Hint: fl_arc().
Ellipse is predefined class which draws an ellipse on the window by a statement, e.g., Ellipse e1(Point(200,200),50,50);
and fl_arc() is part of FLTK which I've previously installed it on my Windows machine.
Since the problem has wanted to draw a part of an ellipse by creating a new class named Arc, I think I should make a new class with that name and also use the definition of the class Ellipse and modify it so that it shows a part of an ellipse instead of whole of an ellipse as wanted. This problem is in Programming Principle and practice using C++ book and the only definition that I found in that book about the Ellipse class was this:
struct Ellipse :Shape {
Ellipse(Point p, int w, int h); //center, max and min distance from center
void draw_lines()const;
Point center()const;
Point focus1()const;
Point focus2()const;
void set_major(int ww) {w=ww;}
int major() const {return w;}
void set_minor(int hh) {h=hh;}
int minor() const {return h;}
private:
int w;
int h;
};
and also I found a case of using the fl_arc() in the book which was used for drawing a Circle like this:
fl_arc(point(0).x,point(0).y,r+r,r+r,0,360);
Here r is radius.
So on my think, I changed the parameters of the fl_arc() and wrote the bellow code to give me what the problem has wanted:
#include <Simple_window.h>
struct arc : Shape {
arc(Point p, int w, int h) // center, min, and max distance from center
: w(w), h(h)
{
add(Point(p.x-w,p.y-h));
}
void draw_lines() const {fl_arc(point(0).x,point(0).y,w+w,h+h,0,120);}
Point center() const { return Point(point(0).x+w,point(0).y+h); }
Point focus1() const { return Point(center().x+int(sqrt(double(w*w-h*h))),center().y); }
Point focus2() const { return Point(center().x-int(sqrt(double(w*w-h*h))),center().y); }
void set_major(int ww) { w=ww; }
int major() const { return w; }
void set_minor(int hh) { h=hh; }
int minor() const { return h; }
private:
int w;
int h;
};
int main()
{
using namespace Graph_lib;
Point t(100,100);
Simple_window win(t,600,400, "semi-ellipse");
arc a(Point(200,200),150,50);
a.draw_lines();
win.wait_for_button();
}
The code runs successfully fortunately but it doesn't show any part of an ellipse.
Question:
Does anyone know why?
PS: If we can find some way for modifying a class we can tell that new class to does some new work for us.
Here is one possible implementation, where you use the already existing facilities of class Ellipse, overwriting the function draw_lines(), to define the class Arc:
#include"Simple_window.h"
#include"Graph.h"
#include<iostream>
using namespace Graph_lib;
//---------------------------------------------------------------------------
//Class Arc
namespace Graph_lib{
class Arc : public Ellipse {
public:
Arc(Point p, int w, int h, int arc_n, int arc_x) : Ellipse(p,w,h), arc_min(arc_n), arc_max(arc_x) {}
void draw_lines() const;
private:
int arc_min;
int arc_max;
};
void Arc::draw_lines() const
{
if(color().visibility())
fl_arc(point(0).x,point(0).y, major()*2, minor()*2, arc_min, arc_max);
}
}
//---------------------------------------------------------------------------
int main()
try
{
Simple_window win(Point(100,100), 800, 600, "Exercise #1");
Graph_lib::Arc arc1(Point(100,100),50,50,0,90);
win.attach(arc1);
win.wait_for_button();
}
catch(exception& e)
{
std::cout << e.what() << std::endl;
return 1;
}
catch(...)
{
std::cout << "unknown error..." << std::endl;
return 2;
}
Programming - Principles and Practice Using C++ (pg.477, exercise 1)
solution by Francisco Tavares
Although I could to find the bug of that code but still I have some issues about that exercise that I like to mention them among you professional guys.
If the line a.draw_lines(); will be replaced by this line win.attach(a); the problem runs successfully.
The remained problems are these:
1- Now when I use the name "Arc" instead of the "arc" in above code I get this error.
Error 8 error C2146: syntax error : missing ';' before identifier 'a' c:\users\cs\documents\visual studio 2012\projects\test2\test2\test2.cpp 25
Error 10
error C3861: 'a': identifier not found c:\users\cs\documents\visual studio 2012\projects\test2\test2\test2.cpp 25
2- The problem has wanted us to define a class (not a struct) so when I replace struct with class and put keyword public just after class arc : Shape {, I get this error.
*Error 8 error C2243: 'type cast' : conversion from 'arc *' to 'Graph_lib::Shape &' exists, but is inaccessible c:\users\cs\documents\visual studio 2012\projects\test2\test2\test2.cpp 29
Error 9 error C2243: 'type cast' : conversion from 'arc ' to 'Graph_lib::Shape &' exists, but is inaccessible c:\users\cs\documents\visual studio 2012\projects\test2\test2\test2.cpp 30
Any idea?
I am trying to create a generic menu button class that is templated to a class, so I can make this button in any class. I want to create a void function pointer to different functions in that class, so when you click on the New Game button, it will call the NewGame() function etc.
I'm still a little new to the idea of creating function pointers and would like some advice.
I get a crazy link error everytime I try to compile my code now with this Menubutton.
here is the error:
Error 1 error LNK2019: unresolved
external symbol "public: void
__thiscall MENUBUTTON::Draw(void)"
(?Draw#?$MENUBUTTON#VTitleScreen####QAEXXZ)
referenced in function "public:
virtual void __thiscall
TitleScreen::Draw(void)"
(?Draw#TitleScreen##UAEXXZ) TitleScreen.obj
MenuButton.h
template <class t>
struct MENUBUTTON
{
SPRITE Normal; // Sprite to display when not hovered over or pressed down
SPRITE Hover; // Sprite to display when hovered over
RECTANGLE HoverBounds; // The Rectangle that activates the hover flag
t* pClass; // Pointer to the templated class
void (t::*ClickFunction)(); // Pointer to void function
void SetButton(int xPos, int yPos, int width, int height, int hPadLeft, int hPadTop, int hWidth, int hHeight, LPCTSTR normalFilePath, LPCTSTR hoverFilePath, t* objectClass, void (t::*ClickFunction)());
bool IsMouseHover();
void CheckPressed();
void Draw();
};
MenuButton.cpp
#include "Global.h"
template <class t>
void MENUBUTTON<t>::SetButton(int xPos, int yPos, int width, int height, int hPadLeft, int hPadTop, int hWidth, int hHeight, LPCTSTR normalFilePath, LPCTSTR hoverFilePath, t* objectClass, void (t::*ClickFunction)())
{
// Position
Hover.position.x = Normal.position.x = xPos;
Hover.position.y = Normal.position.y = yPos;
Hover.position.z = Normal.position.z = 0;
// Width / Height
Hover.width = Normal.width = width;
Hover.height = Normal.height = height;
// Hover RECTANGLE
HoverBounds.x = xPos + hPadLeft;
HoverBounds.y = yPos + hPadTop;
HoverBounds.width = hWidth;
HoverBounds.height = hHeight;
// Load the Sprites
LoadSprite(&Normal, normalFilePath, width, height, 1, 1);
LoadSprite(&Hover, hoverFilePath, width, height, 1, 1);
// Set the Click function pointer
this->pClass = objectClass;
this->ClickFunction = ClickFunction;
}
template <class t>
void MENUBUTTON<t>::Draw()
{
if(IsMouseHover())
{
DrawSprite(&Hover, 0, Hover.position.x, Hover.position.y, Hover.position.z);
}
else
{
DrawSprite(&Normal, 0, Normal.position.x, Normal.position.y, Normal.position.z);
}
}
template <class t>
bool MENUBUTTON<t>::IsMouseHover()
{
return (((InputData.MousePosition.x >= HoverBounds.x) && (InputData.MousePosition.x <= (HoverBounds.x + HoverBounds.width))) &&
((InputData.MousePosition.y >= HoverBounds.y) && (InputData.MousePosition.y <= (HoverBounds.y + HoverBounds.height)))) ? true : false;
}
Here is my Title Screen which is using the menu button.
TitleScreen.h
class TitleScreen : public BaseState
{
// SPRITES
SPRITE titleScreenBG;
// MENU BUTTONS
MENUBUTTON<TitleScreen> playButton;
MENUBUTTON<TitleScreen> quitButton;
public:
TitleScreen();
virtual void Initialize();
virtual void End();
virtual void Update(float dt, INPUTDATA* input);
virtual void Draw();
void QuitGame();
void NewGame();
};
TitleScreen.cpp
#include "Global.h"
// Constructors
TitleScreen::TitleScreen()
{
}
// Virtual Voids
void TitleScreen::End()
{
}
void TitleScreen::Initialize()
{
this->Enabled = true;
this->Visible = true;
// Initialize sprites
ZeroMemory(&titleScreenBG, sizeof(SPRITE));
LoadSprite(&titleScreenBG, TEXT("../../PNG/TitleScreenBG.png"), 1440, 900, 1, 1);
titleScreenBG.position.x = titleScreenBG.position.y = titleScreenBG.position.z = 0;
// Initialize buttons
ZeroMemory(&playButton, sizeof(MENUBUTTON<TitleScreen>));
playButton.SetButton(55, 170, // x , y
512, 128, // width, height
10, 10, // Left, Top Padding
400, 70, // Hover width, Hover height
TEXT("../../PNG/NewGame.png"), TEXT("../../PNG/NewGameH.png"),
this, &TitleScreen::NewGame);
ZeroMemory(&quitButton, sizeof(MENUBUTTON<TitleScreen>));
quitButton.SetButton(55, 240, // x , y
512, 128, // width, height
10, 10, // Left, Top Padding
190, 70, // Hover width, Hover height
TEXT("../../PNG/QuitButton.png"), TEXT("../../PNG/QuitButtonH.png"),
this, &TitleScreen::QuitGame);
}
void TitleScreen::Update(float dt, INPUTDATA* input)
{
}
void TitleScreen::Draw()
{
StartRender();
DrawSprite(&titleScreenBG, 0, titleScreenBG.position.x, titleScreenBG.position.y, titleScreenBG.position.z);
playButton.Draw();
quitButton.Draw();
EndRender();
}
// Public Methods
void TitleScreen::QuitGame()
{
CloseDirect3D();
}
void TitleScreen::NewGame()
{
CloseDirect3D();
}
If anyone has any advice on how I can make the buttons dynamic for any case in a different way, or know what this problem is, please help! :)
To get rid of the link error, move all method definitions starting with template from the .cpp file to the .h file. In your code, move these:
template <class t> void MENUBUTTON<t>::SetButton ... { ... }
template <class t> void MENUBUTTON<t>::Draw ... { ... }
The reason why it doesn't work with the .cpp file is that the compiler treats MENUBUTTON<Foo> and MENUBUTTON<Bar> etc. as different classes, and it generates and compiles such a class whenever it is used. So if you use MENUBUTTON<TitleScreen> when compiling titlescreen.cpp, then the MENUBUTTON<TitleScreen> code will be compiled into the object file titlescreen.o. But the methods SetButton and Draw will be missing at link time, because they are not defined in titlescreen.cpp or any of the .h files it includes. MenuButton.o won't contain it either, because MenuButton.cpp does not need MENUBUTTON<TitleScreen>.
Just to clarify the first answer, you can't have a template class that is declared in a header and then implemented in a separated compiled translation unit (i.e. .cpp file). You've got to put all the code in the header. You can either put it all in the initial class declaration, or using "inline" declare the class first with the functions, then implement the specific functions further down in the header.
Speaking of a better way ... why do you need a template here?
Plain old virtual function or pointer to member would do.
This would be a perfect application of the Command Design Pattern.
Templates give you compile-time polymorphism, while you are probably looking for run-time polymorphism here.