Hallo zusammen,
ich habe in meinem Spiel, das ich in C++ schreibe (übrigens mein erstes C++ Projekt) eine Player-Klasse mit player.h und player.cpp.
Nun möchte ich ein einer anderen Klasse, dem LanPlayState, im Header (also LanPlayState.h) die Variable
Player PlayerOne erstellen und später in der .cpp
PlayerOne.create(//argumente)...ausführen.
Ich habe für Player sowohl einen Default Constructor als auch einen der mehere Argumente übernimmt.
Die gleichen Argumente die auch zur create-funktion gehören.
Der Sinn im definieren in der Headerdatei liegt darin den Scope klassenweit zu bekommen.
Hier meine Player.h:
Die Player.cpp:
Die LanPlayState.h:
und die LanPlayState.cpp: Hier Zeile(146)!
Der Fehler lautet:
1>c:\users\vinc\documents\visual studio 2017\projects\curvefever4\curvefever4\lanplaystate.h(31): error C3646: "PlayerOne": Unbekannter Überschreibungsspezifizierer
1>c:\users\vinc\documents\visual studio 2017\projects\curvefever4\curvefever4\lanplaystate.h(31): error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.
Ich denke meine eigentliche Frage ist:
Wie kann ich ein eigenes Objekt in der Header-Datei definieren, und erst später konstruieren. Ich habe das so verstanden:
Um das Objekt in der Headerdatei zu definieren braucht man trotzdem einen default-constructor.
Und das was der eigentliche Konstructor erledigen würde, kann man dann in eine Funktion verschieben wie "init()" oder bei mir eben "create()".
Ok also obwohl Visual nicht gemeckert hat beim erstellen eines Player objekts in LanPlayState, hat das zusaätliche includieren der player.h den fehler beseitigt!
ich habe in meinem Spiel, das ich in C++ schreibe (übrigens mein erstes C++ Projekt) eine Player-Klasse mit player.h und player.cpp.
Nun möchte ich ein einer anderen Klasse, dem LanPlayState, im Header (also LanPlayState.h) die Variable
Player PlayerOne erstellen und später in der .cpp
PlayerOne.create(//argumente)...ausführen.
Ich habe für Player sowohl einen Default Constructor als auch einen der mehere Argumente übernimmt.
Die gleichen Argumente die auch zur create-funktion gehören.
Der Sinn im definieren in der Headerdatei liegt darin den Scope klassenweit zu bekommen.
Hier meine Player.h:
Code:
#pragma once
#include <iostream>
#include <SFML\Graphics.hpp>
#include <SFML\System\Vector2.hpp>
#include <SFML\Graphics\Rect.hpp>
#include <SFML\OpenGL.hpp>
#define _USE_MATH_DEFINES
#include <math.h>
#include <cmath>
#include "PowerUp.h"
#include "Timer.h"
class Game;
class Player
{
public:
Player();
Player(sf::Color col, sf::Vector2<int> pos, sf::Keyboard::Key K1, sf::Keyboard::Key K2);
void create(sf::Color col, sf::Vector2<int> pos, sf::Keyboard::Key K1, sf::Keyboard::Key K2);
void Update(float &elapsedTime);
void Draw(Game& game);
void PchangeSpeed(float s);
void PchangeThickness(int d);
void changeKeys();
sf::Vector2f getHead();
sf::Vector2<float> R;
sf::VertexArray vertices;
std::pair<int, double> allPPowerUp;
bool gameoverB = false;
bool startphase;
bool drawBorder;
private:
void Collision();
void Timerdesolve();
std::vector<std::pair<Timer, int>> TimersandType;
sf::Font font;
sf::Text playtxt;
sf::CircleShape circle;
sf::Keyboard::Key Key1, Key2,KeyTemp;
sf::RectangleShape rect;
static sf::Texture arrowtxt;
sf::Sprite arrow;
sf::Color Col, oldCol;
sf::Vector2f Pos, N, LP, RP, holeStart;
int n = 0;
int m = 0;
int eT, holetimer, holedis, traceN, radius,dis;
int randomN;
bool hole = false;
bool Peaten = false;
float speed, turnspeed, alpha;
};
Die Player.cpp:
Code:
#pragma once
#include "Player.h"
#include "Game.h"
#include "eV.h"
std::vector< unsigned char > pixels(1 * 1 * 3);
std::vector< unsigned char > pixelsSide1(1 * 1 * 3);
std::vector< unsigned char > pixelsSide2(1 * 1 * 3);
sf::Texture Player::arrowtxt;
Player::Player()
{}
Player::Player(sf::Color col, sf::Vector2<int> pos, sf::Keyboard::Key K1, sf::Keyboard::Key K2)
{
circle.setRadius(4);
circle.setOrigin(circle.getRadius(), circle.getRadius());
circle.setPosition(pos.x,pos.y);
circle.setFillColor(col);
Pos.x=pos.x;
Pos.y = pos.y;
arrowtxt.loadFromFile("arrow.png");
arrow.setTexture(arrowtxt);
arrow.setOrigin(0, 10);
arrow.setPosition(circle.getPosition());
arrow.setColor(col);
vertices.setPrimitiveType(sf::TriangleStrip);
vertices.append(sf::Vertex(circle.getPosition(), col));
Col = col;
Key1 = K1;
Key2 = K2;
speed = 0.115;
turnspeed = 0.004;
alpha = 0;
R = { 1.0f,0.0f };
holetimer = 0;
traceN = 0;
randomN = 1000000;
allPPowerUp.first = -1;
allPPowerUp.second = 1;
drawBorder = true;
}
void Player::create(sf::Color col, sf::Vector2<int> pos, sf::Keyboard::Key K1, sf::Keyboard::Key K2)
{
//Player(col, pos, K1, K2);
circle.setRadius(4);
circle.setOrigin(circle.getRadius(), circle.getRadius());
circle.setPosition(pos.x, pos.y);
circle.setFillColor(col);
Pos.x = pos.x;
Pos.y = pos.y;
arrowtxt.loadFromFile("arrow.png");
arrow.setTexture(arrowtxt);
arrow.setOrigin(0, 10);
arrow.setPosition(circle.getPosition());
arrow.setColor(col);
vertices.setPrimitiveType(sf::TriangleStrip);
vertices.append(sf::Vertex(circle.getPosition(), col));
Col = col;
Key1 = K1;
Key2 = K2;
speed = 0.115;
turnspeed = 0.004;
alpha = 0;
R = { 1.0f,0.0f };
holetimer = 0;
traceN = 0;
randomN = 1000000;
allPPowerUp.first = -1;
allPPowerUp.second = 1;
drawBorder = true;
}
void Player::changeKeys()
{
KeyTemp = Key1;
Key1 = Key2;
Key2 = KeyTemp;
}
float norm(sf::Vector2f r)
{
int l= sqrtf(r.x*r.x + r.y*r.y);
return l;
}
void Player::Update(float &elapsedTime)
{
eT = elapsedTime;
if (gameoverB == false) {
if (sf::Keyboard::isKeyPressed(Key1))
{
R += sf::Vector2f(-R.y, R.x)*elapsedTime/1000.0f* turnspeed;
R /= norm(R);
}
if (sf::Keyboard::isKeyPressed(Key2))
{
R -= sf::Vector2f(-R.y, R.x)*elapsedTime / 1000.0f* turnspeed;
R /= norm(R);
}
if (startphase == false) {
Collision();
Pos += R*elapsedTime / 1000.0f*speed;
circle.setPosition(Pos);
}
if(startphase==true)
{
alpha = std::atan(R.y / R.x) * 180 / M_PI;
if (R.x < 0) { alpha += 180; }
arrow.setRotation(alpha);
}
}
}
void Player::PchangeSpeed(float s)
{
speed = speed*s;
}
void Player::PchangeThickness(int d)
{
circle.setRadius(circle.getRadius() +d);
circle.setOrigin(circle.getRadius(), circle.getRadius());
radius = circle.getRadius();
}
void Player::Timerdesolve() //Liste der PowerUp-Timer abarbeiten und PowerUps rueckgaengig machen
{
if (TimersandType.size() > 0)
{
for (int i = 0; i < TimersandType.size(); i++)
{
if (TimersandType[i].first.TimerCheck() == true)
{
switch (TimersandType[i].second)
{
case 0://sich selber langsam rückgängig
PchangeSpeed(1 / 0.7);
TimersandType.erase(TimersandType.begin() + i);
break;
case 1://andere langsam rückgängig
allPPowerUp.first = 1;
allPPowerUp.second = 1 / 0.7;
PchangeSpeed(0.7);
TimersandType.erase(TimersandType.begin() + i);
break;
case 2://sich selber schnell rückgängig
PchangeSpeed(1 / 1.7);
TimersandType.erase(TimersandType.begin() + i);
break;
case 3://andere schnell rückgängig
allPPowerUp.first = 3;
allPPowerUp.second = 1 / 1.7;
PchangeSpeed(1.7);
TimersandType.erase(TimersandType.begin() + i);
break;
case 4://sich selber duenn rückgängig
PchangeThickness(3);
TimersandType.erase(TimersandType.begin() + i);
break;
case 5: //andere dick rückgängig
allPPowerUp.first = 5;
allPPowerUp.second = -3;
PchangeThickness(3);
TimersandType.erase(TimersandType.begin() + i);
break;
case 6://andere Controls verdrehen rückgängig
allPPowerUp.first = 6;
allPPowerUp.second = 1;
changeKeys();
TimersandType.erase(TimersandType.begin() + i);
break;
case 7://Spuren löschen rückgängig
break;
case 8://Rand öffnen/schließen rückgängig
break;
}
}
}
}
}
sf::Vector2f Player::getHead()
{
return sf::Vector2f(circle.getPosition());
}
void Player::Collision()
{ //Collisions-Erkennung in jedem Frame
LP = sf::Vector2f(1.732*R.x-0.5*R.y , 0.5*R.x+1.732*R.y); //30° nach links
RP = sf::Vector2f(1.732*R.x + 0.5*R.y , 1.732*R.y-0.5*R.x); //30°nach rechts
glReadBuffer(GL_FRONT); //pixel auslesen
glReadPixels(Pos.x + (R.x* (1.0 * radius+1)), height - Pos.y - (R.y*(1.0*radius+1)), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixels[0]); //Pixel Pos vorm kopf
glReadPixels(Pos.x + (LP.x* (1.0 * radius+1)), height - Pos.y - (LP.y*(1.0*radius+1)), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixelsSide1[0]);//Pixel seitlich 30°
glReadPixels(Pos.x + (RP.x* (1.0 * radius+1)), height - Pos.y - (RP.y*(1.0*radius+1)), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixelsSide2[0]);//pixel andere Seite -30°
//std::cout << std::to_string(pixels[0]) << " " << std::to_string(pixels[1]) << " " << std::to_string(pixels[2]) << std::endl;
if (pixels[0] == 0 && pixels[1] == 0 && pixels[2] == 0 && pixelsSide1[0] == 0 && pixelsSide1[1] == 0 && pixelsSide1[2] == 0 && pixelsSide2[0] == 0 && pixelsSide2[1] == 0 && pixelsSide2[2] == 0)
{//wenn schwarz passiert nichts
}
else if (powerups.size() > 0)
{//sonst Überprüfung ob Powerup gegessen
for (int i = 0; i < powerups.size(); i++)
{ // wenn ja wende powerup an
int m = powerups[i].Eaten(Pos,radius);
if (m == 0)//sich selber langsam
{
PchangeSpeed(0.7);
Timer T(7000000);
std::pair<Timer, int> Pair(T, 0);
TimersandType.push_back(Pair);//Timer mit Wirkungsdauer und Typ in die Liste stecken
powerups.erase(powerups.begin() + i);
Peaten = true;
break;
}
else if (m == 1)//andere langsam
{
allPPowerUp.first = 1;
allPPowerUp.second = 0.7;
PchangeSpeed(1 / 0.7);
Timer T(7000000);
std::pair<Timer, int> Pair(T, 1);
TimersandType.push_back(Pair);
powerups.erase(powerups.begin() + i);
Peaten = true;
break;
}
else if (m == 2) //sich selber schnell
{
PchangeSpeed(1.7);
Timer T(4000000);
std::pair<Timer, int> Pair(T, 2);
TimersandType.push_back(Pair);
powerups.erase(powerups.begin() + i);
Peaten = true;
break;
}
else if (m == 3) //andere schnell
{
allPPowerUp.first = 3;
allPPowerUp.second = 1.7;
PchangeSpeed(1 / 1.7);
Timer T(4000000);
std::pair<Timer, int> Pair(T, 3);
TimersandType.push_back(Pair);
powerups.erase(powerups.begin() + i);
Peaten = true;
break;
}
else if (m == 4) //sich selber duenn
{
if (radius > 3) {
PchangeThickness(-3);
Timer T(7000000);
std::pair<Timer, int> Pair(T, 4);
TimersandType.push_back(Pair);
}
powerups.erase(powerups.begin() + i);
Peaten = true;
break;
}
else if (m == 5) //andere dick
{
allPPowerUp.first = 5;
allPPowerUp.second = 3;
PchangeThickness(-3);
Timer T(7000000);
std::pair<Timer, int> Pair(T, 5);
TimersandType.push_back(Pair);
powerups.erase(powerups.begin() + i);
Peaten = true;
break;
}
else if (m == 6) //andere Controls verdrehen
{
allPPowerUp.first = 6;
allPPowerUp.second = 1;
changeKeys();
Timer T(7000000);
std::pair<Timer, int> Pair(T, 6);
TimersandType.push_back(Pair);
powerups.erase(powerups.begin() + i);
Peaten = true;
break;
}
else if (m == 7) //Alle Spuren löschen
{
allPPowerUp.first = 7;
allPPowerUp.second = 1;
powerups.erase(powerups.begin() + i);
Peaten = true;
break;
}
else if (m == 8) //Rand öffnen/schließen
{
allPPowerUp.first = 8;
allPPowerUp.second = 1;
powerups.erase(powerups.begin() + i);
Peaten = true;
break;
}
}
if (Peaten == false)
{
if (startphase == false)
{
//std::cout << "gameover" << std::endl;
R = { 0,0 };
gameoverB = true;
}
}
if (Peaten == true)
{
Peaten = false;
}
}
else
{
if (startphase == false)
{
//std::cout << "gameover" << std::endl;
R = { 0,0 };
gameoverB = true;
}
}
}
void Player::Draw(Game& game)
{
radius = circle.getRadius();
holetimer += eT;
traceN += eT;
if (traceN > 40000)//Spur zeichnen in 0,04s Schritten
{
traceN = 0;
//Loch erzeugung nach random zeit
if (holetimer>randomN)
{
hole = true;
holeStart = Pos;
oldCol = Col;
Col = sf::Color::Transparent;
holedis = (rand() % 30) + 15;
vertices.append(sf::Vertex(Pos + N*float(radius), Col));
vertices.append(sf::Vertex(Pos + -N*float(radius), Col));
}
if (hole == true) //Loch zeichnung
{
holetimer = 0;
dis = sqrt((Pos.x - holeStart.x)*(Pos.x - holeStart.x) + (Pos.y - holeStart.y)*(Pos.y - holeStart.y));
if (dis>holedis)
{
vertices.append(sf::Vertex(Pos + N*float(radius), Col));
vertices.append(sf::Vertex(Pos + -N*float(radius), Col));
Col = oldCol;
hole = false;
dis = 0;
randomN = (rand() % 4) * 1000000 + 500000;
}
}
N = sf::Vector2f(-R.y, R.x);
vertices.append(sf::Vertex(Pos + N*float(radius), Col));
vertices.append(sf::Vertex(Pos + -N*float(radius), Col));
}
//Randbedingungen prüfen in jedem Frame;
if (drawBorder == false) {
if (Pos.x + 2 * radius > width - 205)
{
vertices.append(sf::Vertex(sf::Vector2f(width - 200, Pos.y), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(width - 200, Pos.y), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(0, Pos.y), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(0, Pos.y), sf::Color::Transparent));
Pos.x = 0 + 2 * radius;
}
if (Pos.x - 2 * radius < 0)
{
vertices.append(sf::Vertex(sf::Vector2f(0, Pos.y), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(0, Pos.y), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(width - 200, Pos.y), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(width - 200, Pos.y), sf::Color::Transparent));
Pos.x = width - 205 - 2 * radius;
}
if (Pos.y + 2 * radius > height)
{
vertices.append(sf::Vertex(sf::Vector2f(Pos.x, height), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(Pos.x + 1, height), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(Pos.x, 0), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(Pos.x + 1, 0), sf::Color::Transparent));
Pos.y = 2 * radius;
}
if (Pos.y - 2 * radius < 0)
{
vertices.append(sf::Vertex(sf::Vector2f(Pos.x, 0), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(Pos.x, 0), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(Pos.x, height), sf::Color::Transparent));
vertices.append(sf::Vertex(sf::Vector2f(Pos.x, height), sf::Color::Transparent));
Pos.y = height - 2 * radius;
}
}
Timerdesolve();
game.window.draw(vertices);
game.window.draw(circle);
if (startphase == true)
{
game.window.draw(arrow);
}
}
Die LanPlayState.h:
Code:
#pragma once
#ifndef LANPLAYSTATE_HPP
#define LANPLAYSTATE_HPP
#include <SFML/Graphics.hpp>
#include "Game.h"
#include "Gamestate.h"
#include <SFML\Network.hpp>
class LanPlayState : public Gamestate
{
public:
LanPlayState();
~LanPlayState();
void HandleEvents(Game& game);
void Update(Game& game);
void Draw(Game& game);
private:
void NSetup();
void InBox(sf::Packet packet);
void gamestart();
sf::Texture turtlegreen, turtlered, blitzgreen, blitzred, duengreen, dickred, controlswitch, radierer, dBorder;
sf::RectangleShape rectsplit, border;
sf::Font font;
sf::Text scoretxt;
std::vector<sf::Color> C;
bool drawBorder = true;
Player PlayerOne;
sf::TcpSocket socket;
sf::SocketSelector selector;
sf::Time t1;
};
#endif
und die LanPlayState.cpp: Hier Zeile(146)!
Code:
#pragma once
#include "LanPlayState.h"
#include "eV.h"
LanPlayState::LanPlayState()
{
turtlegreen.loadFromFile("0.png"); //sich selber langsam
turtlered.loadFromFile("1.png");//andere langsam
blitzgreen.loadFromFile("2.png");//sich selber schnell
blitzred.loadFromFile("3.png");//andere schnell
duengreen.loadFromFile("4.png"); //sich selber duenn
dickred.loadFromFile("5.png");//andere dick
controlswitch.loadFromFile("6.png");//andere Controls verdrehen
radierer.loadFromFile("7.png");//Spuren löschen
dBorder.loadFromFile("8.png");//Rand öffnen
rectsplit.setSize(sf::Vector2f(5, height));
rectsplit.setPosition(sf::Vector2f(width - 200, 0));
rectsplit.setFillColor(sf::Color(180, 180, 180));
font.loadFromFile("Jokerman.TTF");
scoretxt.setFont(font);
scoretxt.setPosition(width - 150, 50);
scoretxt.setCharacterSize(30);
scoretxt.setString("Score:");
scoretxt.setFillColor(sf::Color(220, 220, 220));
border.setFillColor(sf::Color::Transparent);
border.setSize(sf::Vector2f(width - 200, height));
border.setOutlineThickness(-5);
border.setOutlineColor(sf::Color(250, 150, 100));
C.resize(4);
C[0] = sf::Color::Blue;
C[1] = sf::Color::Red;
C[2] = sf::Color::Green;
C[3] = sf::Color::Yellow;
t1 = sf::milliseconds(10);
NSetup();
/*sf::Vector2<int> x((rand() % (width - 280)) + 20, (rand() % (height - 40)) + 20);
Player nP(C[playernumber], x, K[i], K[i + 4]);
nP.startphase = true;*/
}
void LanPlayState::HandleEvents(Game& game)
{
sf::Event event;
while (game.window.pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
game.window.close();
game.running = false;
break;
case sf::Event::KeyPressed:
if (event.key.code == sf::Keyboard::Escape)
{
}
if (event.key.code == sf::Keyboard::Return)
{
}
break;
}
}
}
void LanPlayState::Update(Game& game)
{
if (selector.wait(t1)) //check for data
{
if (selector.isReady(socket))//test socket for recv data
{
sf::Packet packet;
if (socket.receive(packet) != sf::Socket::Done)
{
std::cout << "recieve FAIL" << std::endl;
}
else
{
InBox(packet);
}
}
}
}
void LanPlayState::Draw(Game& game)
{
game.window.draw(rectsplit);
game.window.draw(scoretxt);
if (drawBorder == true)
{
game.window.draw(border);
PlayerOne.Draw(game);
}
}
void LanPlayState::NSetup()
{
sf::Socket::Status status = socket.connect("127.0.0.1", 54345);
if (status != sf::Socket::Done)
{
std::cout << "socket connect error" << std::endl;
}
else
{
selector.add(socket);
}
}
void LanPlayState::InBox(sf::Packet packet)
{
int x = 0;
int y = 0;
packet >> x >> y;
if (x == 111)
{
gamestart();
}
std::cout << x << " " << y << std::endl;
}
void LanPlayState::gamestart()
{
int n;
for (int i = 0; i < connectionInfo.size(); i++)
{
if (connectionInfo[i][0] == 1)
{
n = connectionInfo[i][1];
}
}
sf::Vector2<int> x((rand() % (width - 280)) + 20, (rand() % (height - 40)) + 20);
PlayerOne.create(C[n], x, sf::Keyboard::Right, sf::Keyboard::Left);
PlayerOne.startphase = true;
}
LanPlayState::~LanPlayState()
{
std::cout << "LanPlayState wurde zerstört" << std::endl;
}
Der Fehler lautet:
1>c:\users\vinc\documents\visual studio 2017\projects\curvefever4\curvefever4\lanplaystate.h(31): error C3646: "PlayerOne": Unbekannter Überschreibungsspezifizierer
1>c:\users\vinc\documents\visual studio 2017\projects\curvefever4\curvefever4\lanplaystate.h(31): error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.
Ich denke meine eigentliche Frage ist:
Wie kann ich ein eigenes Objekt in der Header-Datei definieren, und erst später konstruieren. Ich habe das so verstanden:
Um das Objekt in der Headerdatei zu definieren braucht man trotzdem einen default-constructor.
Und das was der eigentliche Konstructor erledigen würde, kann man dann in eine Funktion verschieben wie "init()" oder bei mir eben "create()".
Ergänzung ()
Ok also obwohl Visual nicht gemeckert hat beim erstellen eines Player objekts in LanPlayState, hat das zusaätliche includieren der player.h den fehler beseitigt!
Zuletzt bearbeitet: