Some of the member variables are not accessible - c++

I'm trying to make a simple game, basically there is a map that you can put walls on, after that the enemy will spawn and walk to the finish tile.
Here's the call stack
Game constructor (setscene etc, create buildwall object that handles the wall placement) -> BuildWall (inputs are handled by this object, after user pressed Enter, call the game.generatePath) -> game.generatePath(here's where some of the member variables are not accessible)
Here is the code:
Game.h
#ifndef GAME
#define GAME
#include "Wall.h"
#include "Tile.h"
#include "Enemy.h"
#include "Path.h"
#include <QGraphicsView>
#include "Tower.h"
class BuildWall;
class Game: public QGraphicsView{
Q_OBJECT
public:
Game();
QGraphicsScene * scene;
Wall * build_wall;
// map and tile details
int map_width_in_tiles; // number of tiles in x axis
int map_height_in_tiles;
int map_tile_size; // in pixels
// tiles are indexed in int for easy sorting in QMap. We must use indexOfPoint(x,y) to get an index of a tile
QMap<int,Tile*> tiles;
// spawning entities
void spawnBlueSlime(Tile &spawn, Tile &dest, Path &path);
int getTileSize();
QMap<int,Tile*> getTiles();
void generatePath();
// tile indexing
int indexOfPoint(int x, int y);
// convert tile coordinate to scene coordinate
int x_scene(int x);
int y_scene(int y);
Tower *tower;
void mouseMoveEvent(QMouseEvent *event);
private:
// game initializations
void createMapTiles(QString filename);
void createScene();
void setMapTile(int map_width_in_tiles, int map_height_in_tiles, int map_tile_size_);
// debugging
void drawTilesOverlay(QString filename);
void drawTilesPoint();
//
void printAllTiles();
// mouse input
// spawn dest
Tile *spawn1;
Tile *dest1;
Tile *spawn2;
Tile *dest2;
BuildWall *buildwall;
};
#endif // GAME
Game.cpp
Game::Game()
{
setMouseTracking(true);
grabMouse();
setMapTile(20,10,64); // but start from 0
createScene();
createMapTiles(":/floor/assets/floor/dirt.png");
//drawTilesOverlay(":/util/assets/util/sTrackBorder_0.png");
//drawTilesPoint();
//printAllTiles();
int index = indexOfPoint(19,4);
Tower *tower = new Tower(*this,this->tiles.value(index)->x(),this->tiles.value(index)->y());
BuildWall *buildwall = new BuildWall(*this);
}
void Game::generatePath() {
delete buildwall;
Tile *spawn1 = tiles.value(indexOfPoint(1,5));
Tile *dest1 = tiles.value(indexOfPoint(19,5));
Path *path = new Path(*this,*spawn1,*dest1);
spawnBlueSlime(*spawn1,*dest1, *path);
}
//
// others methods
BuildWall.h
class Game;
class BuildWall: public QGraphicsPixmapItem{
public:
BuildWall(Game &game_);
Game &game;
private:
void keyPressEvent(QKeyEvent *ev);
};
BuildWall.cpp
BuildWall::BuildWall(Game &game_) : game(game_)
{
setPixmap(QPixmap(":/wall/assets/wall/brick_red.png"));
setScale(0.5);
game.scene->addItem(this);
this->setFlag(QGraphicsItem::ItemIsFocusable, true);
this->setFocus();
}
void BuildWall::keyPressEvent(QKeyEvent *ev)
{
int grid = game.map_tile_size;
switch (ev->key())
{
//other keys
case Qt::Key_Return:
this->setFlag(QGraphicsItem::ItemIsFocusable, false);
this->setFocus();
game.generatePath();
break;
}
}
Here you can see I can access some of the member variables such as tiles which are generated in Game constructor

You are shadowing member variables.
In the constructor it should only say:
buildwall = new BuildWall(*this);
This is the case for all member variables (spawn1, dest1, spawn2, dest2, buildwall) and in all functions where you want to call these variables.

Related

Faster every Frame/Second UnrealEngine C++

MyPawn.cpp
// Called every frame
void AMyPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// Handle growing and shrinking based on our "Grow" action
{
float CurrentScale = OurVisibleComponent->GetComponentScale().X;
if (bGrowing)
{
// Grow to double size over the course of one second
CurrentScale = CurrentScale + 2;
}
else
{
// Shrink half as fast as we grow
CurrentScale -= (DeltaTime * 0.5f);
}
// Make sure we never drop below our starting size, or increase past double size.
CurrentScale = FMath::Clamp(CurrentScale, 1.0f, 2.0f);
OurVisibleComponent->SetWorldScale3D(FVector(CurrentScale));
}
// Handle movement based on our "MoveX" and "MoveY" axes
{
if (!CurrentVelocity.IsZero())
{
FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
SetActorLocation(NewLocation);
}
}
}
MyPawn.h
#include "GameFramework/Pawn.h"
#include "MyPawn.generated.h"
UCLASS()
class MYPROJECT_API AMyPawn : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AMyPawn();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
UPROPERTY(EditAnywhere)
USceneComponent* OurVisibleComponent;
//Input functions
void Move_XAxis(float AxisValue);
void Move_YAxis(float AxisValue);
void StartGrowing();
void StopGrowing();
//Input variables
FVector CurrentVelocity;
bool bGrowing;
};
I want to add a statement that make my Spawn move faster every Frame or Second while one of the key input pressed (Forward,Backward,Left or Right),
I've tried to add
CurrentVelocity.X += CurrentVelocity.X
or
CurrentVelocity.X += 1
in the AMyPawn::Tick, and tried some more combination with no success, hope u can help me solve this .

Snake game grid system

I am currently stuck trying to create a grid for my controllable snake to move around. Currently. I am using a resolution of 1024x768 and would like the snake to move between a 16x16 grid (64x48 resolution)
So far the snake just moves pixel by pixel at a set speed.
I'll paste the .cpp and .hpp files below which i think are relevant to where i need to implement the code. If anyone could provide any suggestions/code that would be great!
snake.cpp
#include "snake.hpp"
#include <cstdlib>
void Snake::move()
{
switch(direction_){
case Direction::North:
position_.y += 1;
break;
case Direction::East:
position_.x += 1;
break;
case Direction::South:
position_.y -= 1;
break;
case Direction::West:
position_.x -= 1;
}
if (position_.x < 0) position_.x = 63; else if (position_.x > 63) position_.x = 0;
if (position_.y < 0) position_.y = 47; else if (position_.y > 47) position_.y = 0;
}
void Snake::render(prg::Canvas& canvas) const
{
canvas.drawCircle(getPosition().x * 16, getPosition().y * 16,16,prg::Colour::WHITE);
}
void Snake::changeDirection(Direction new_direction)
{
direction_ = new_direction;
}
snake.hpp
#if !defined SNAKE_HPP
#define SNAKE_HPP
#include <prg_interactive.hpp>
enum class Direction {
North = 1, East, South, West
};
struct Position final {
int x{0}, y{0};
Position(int ix, int iy) : x{ix}, y{iy} {}
};
class Snake {
public:
virtual ~Snake() {}
virtual void move();
void render(prg::Canvas& canvas) const;
void changeDirection(Direction new_direction);
const Position& getPosition() const {return position_;}
void setPosition(const Position& position){ position_ = position;}
private:
Direction direction_ {Direction::North};
Position position_ {0,0};
};
class PlayerSnake : public Snake,
public prg::IKeyEvent {
public:
PlayerSnake();
virtual ~PlayerSnake();
bool onKey(const prg::IKeyEvent::KeyEvent& key_event) override;
};
#endif // SNAKE_HPP
play_state.cpp
#include "play_state.hpp"
#include "ai_snake.hpp"
#include "player_snake.hpp"
#include <iostream>
const size_t MaxShapes {5};
const unsigned int MaxScale {5};
bool PlayState::onCreate()
{
snakes_.push_back(new AISnake);
snakes_.back()->setPosition(Position(100,100));
snakes_.push_back(new PlayerSnake);
snakes_.back()->setPosition(Position(50,50));
double x, y;
for(unsigned shape = 0;shape < MaxShapes;shape++)
{
x = (double)(rand() % prg::application.getScreenWidth());
y = (double)(rand() % prg::application.getScreenHeight());
shapes_.push_back(Square({x, y}));
}
return true;
}
bool PlayState::onDestroy()
{
return true;
}
void PlayState::onEntry()
{
prg::application.addKeyListener(*this);
game_timer_.start();
}
void PlayState::onExit()
{
prg::application.removeKeyListener(*this);
game_timer_.stop();
}
void PlayState::onUpdate()
{
}
void PlayState::onRender(prg::Canvas& canvas)
{
const std::string text = "";
canvas.blitFast(
background_,
canvas.getWidth() / 2 - background_.getWidth() / 2,
canvas.getHeight() / 2 - background_.getHeight() / 2
);
prg::uint text_dims[2];
prg::Font::MASSIVE.computePrintDimensions(text_dims, text);
prg::Font::MASSIVE.print(
canvas,
prg::application.getScreenWidth() / 2 - text_dims[0] / 2,
prg::application.getScreenHeight() / 2 - text_dims[1] / 2,
prg::Colour::RED,
text);
for(const auto snake : snakes_) {
snake->render(canvas);
}
for(Shape shapes : shapes_) {
shapes.render(canvas);
}
}
bool PlayState::onKey(const prg::IKeyEvent::KeyEvent& key_event)
{
if(key_event.key_state == KeyEvent::KB_DOWN) {
switch(key_event.key) {
case KeyEvent::KB_ESC_KEY:
prg::application.exit();
break;
}
}
return true;
}
void PlayState::onTimer(prg::Timer& timer)
{
for(auto snake : snakes_) {
snake->move();
}
}
play_state.hpp
#if !defined PLAY_STATE_HPP
#define PLAY_STATE_HPP
#include <prg_interactive.hpp>
#include "snake.hpp"
#include "square.hpp"
#include <list>
//Example of forward declaration of Snake class
class Snake;
class PlayState final : public prg::IAppState,
public prg::IKeyEvent,
public prg::ITimerEvent {
public:
PlayState() = default;
bool onCreate() override;
bool onDestroy() override;
void onEntry() override;
void onExit() override;
void onUpdate() override;
void onRender(prg::Canvas& canvas) override;
bool onKey(const prg::IKeyEvent::KeyEvent& key_event) override;
void onTimer(prg::Timer& timer) override;
private:
//Snake* snakes_[2] {nullptr,nullptr};
std::list<Snake*> snakes_;
prg::Timer game_timer_ {0, 1000 / 30, *this};
const prg::Image background_ {prg::ImageFile("resources/images/border.bmp").load()};
std::vector<Shape> shapes_;
};
#endif // PLAY_STATE_HPP
player_snake.cpp
#include "player_snake.hpp"
//PlayerSnake Implementation
//
PlayerSnake::PlayerSnake()
{
prg::application.addKeyListener(*this);
}
PlayerSnake::~PlayerSnake()
{
prg::application.removeKeyListener(*this);
}
bool PlayerSnake::onKey(const prg::IKeyEvent::KeyEvent& key_event)
{
if(key_event.key_state == KeyEvent::KB_DOWN) {
switch(key_event.key) {
case KeyEvent::KB_LEFT_KEY:
changeDirection(Direction::West);
break;
case KeyEvent::KB_RIGHT_KEY:
changeDirection(Direction::East);
break;
case KeyEvent::KB_UP_KEY:
changeDirection(Direction::North);
break;
case KeyEvent::KB_DOWN_KEY:
changeDirection(Direction::South);
break;
}
}
return true;
}
player_snake.hpp
#if !defined PLAYER_SNAKE_HPP
#define PLAYER_SNAKE_HPP
#include "snake.hpp"
#include <prg_interactive.hpp>
#endif //PLAYER_SNAKE_HPP
You snake is initially set out of bounds:
snakes_.push_back(new AISnake);
snakes_.back()->setPosition(Position(100,100));
snakes_.push_back(new PlayerSnake);
snakes_.back()->setPosition(Position(50,50));
Because in the move function, you limit the snake to (64, 48) as the maximum location. The x position 100 is past the limit. The y positions are past the limit.
You may want to set them at different locations based on the MAXIMUM_WIDTH and MAXIMUM_HEIGHT constants (see my comments):
Snake AISnake;
AISnake.setPosition(MAXIMUM_WIDTH / 4, MAXIMUM_HEIGHT / 4);
snakes_.push_back(AISnake);
Snake PlayerSnake;
PlayerSnake.setPosition(MAXIMUM_WIDTH * 3 / 4,
MAXIMUM_HEIGHT * 3 / 4);
snakes_.push_back(PlayerSnake);
Also note that in the above code fragment, there is no dynamic memory allocation. The variables (snakes) are defined locally and copied into the snakes_ container. This means that there is no need to worry about memory leaks or memory management (like when to delete the memory occupied by the snake).
More Out Of Bounds
Some places, you use the screen dimensions for the boundaries, others, you use a hard coded value:
x = (double)(rand() % prg::application.getScreenWidth());
y = (double)(rand() % prg::application.getScreenHeight());
You need to decide whether the game board occupies the entire screen dimensions or is a fixed size. If you keep the above statements, you should test the positions to verify they are within the game borders.
If this is a GUI application, you need to decide on a fixed size game board or a board set to the size of the window or expanding to the entire screen. For a fixed size board, you should consider a "viewport" design. This means that the window is a view or port showing a small portion of the board (the board is bigger than the window).
Separation of Screen Vs. Board
You should separate the concepts between a logical board and the physical screen. This concept lets you adapt the board to the screen without affecting any other modules.
For example, the Board draws onto the screen. A Board cell may have different pixel dimensions depending on the screen resolution. However, a part of the snake will always occupy at least one Board cell. So the snake movement doesn't depend on the screen resolution, only the Board dimensions.
By placing the objects, Board and Screen, in separate files, you can change the screen dimensions without having to recompile any of the snake or main files.

How to make my own classes with C++ and SFML

I have currently started working with SFML after learning the basics of C++. I have learnt about Arrays, References and everything that comes before it but have struggled to grasp the concept of using classes.
In SFML I have created a simple sprite movement program but, I would like to move this information into a class (lets say it will be called "Player"). I have messed around a lot but I can not get it to work.
I have tried creating a function in a class that would check for player input, but I can not access my sprite that I created in main. I would like to move everything related to the player into a Player class but need some advice.
What is the correct way to do this? (Please don't say go back and learn about classes, this is where I want to learn about them!)
main.cpp
#include <SFML/Graphics.hpp>
#include <string>
#include <iostream>
int main()
{
//character position
enum Direction{ Down, Left, Right, Up };
sf::Vector2i source(1, Down);
//window
sf::RenderWindow window(sf::VideoMode(1200, 700), "Testing");
window.setKeyRepeatEnabled(false);
//player character
sf::Texture pTexture;
sf::Sprite pSprite;
if(!pTexture.loadFromFile("image/playerSprite.png"))
std::cout << "Texture Error" << std::endl;
pSprite.setTexture(pTexture);
pSprite.setScale(1.5f, 1.5f);
//game loop
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) //move up
{
source.y = Up;
pSprite.move(0, -0.2);
//animation
source.x++;
if(source.x * 32 >= pTexture.getSize().x)
{
source.x = 0;
}
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) //move down
{
source.y = Down;
pSprite.move(0, 0.2);
//animation
source.x++;
if(source.x * 32 >= pTexture.getSize().x)
{
source.x = 0;
}
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) //move right
{
source.y = Right;
pSprite.move(0.2, 0);
//animation
source.x++;
if(source.x * 32 >= pTexture.getSize().x)
{
source.x = 0;
}
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) //move left
{
source.y = Left;
pSprite.move(-0.2, 0);
//animation
source.x++;
if(source.x * 32 >= pTexture.getSize().x)
{
source.x = 0;
}
}
pSprite.setTextureRect(sf::IntRect(source.x * 32, source.y * 32, 32, 32));
window.draw(pSprite);
window.display();
}
return 0;
}
Disclaimer: You shouldn't expect that kind of answer, you really should read more on OOP to get the point, this has nothing to do with SFML, this is just basic refactoring.
How to think with OOP
First thing first, before coding a feature, you should design the OOP structure that really suits the situation. See each class as part of a whole, that is your program. A class in fact is just an aggregation of data with useful methods that only affects the data inside the class (or the data provided via method parameters) in a meaningful way.
See the basics of C++ (more the OOP part for you) to understand how to get it to work in C++. The concepts are similar in other programming languages.
Working with your provided code
What you asked for was a Player class and it's a great idea to get the player code out of the program main logic. You need to ask yourself: "What my player code needs to work?"
The player class
Basically, your player is only a sprite and a position. So you encapsulate those data into your Player class as private members. That keeps other code from messing with the player data. To use the player data, you need to provide methods in the class that each affects only the Player.
Texture and Sprite
I have kept the Texture outside of the player on purpose. Textures are heavy objects, that's why the Sprite object only keeps a pointer to it. Sprites are lightweight and can be changed and copied easily. The managing of texture objects and other assets is another subject, though here's my own resource manager code.
Optional
I did not took the time to change your code much, but you could change the way you handle the movement to only make one "move" method that takes a Player::Direction has a parameter.
To help you a little more and to give you some more guidelines on the subject, I used "forward declaration" and moved your Direction enum inside the class. It's maybe not the best way to achieve what you want, but I've only change your own code to avoid getting you lost.
The Code
Anyway, here's my go at this.
Player.h
#ifndef PLAYER_H_
#define PLAYER_H_
#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Sprite.hpp>
// Forward Declaration
namespace sf {
class Texture;
}
// provide your namespace to avoid collision/ambiguities
namespace test {
/*
*
*/
class Player: public sf::Drawable {
public:
enum Direction {
Down, Left, Right, Up
};
Player(const sf::Texture& playerTexture);
virtual ~Player();
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
void moveUp();
void moveDown();
void moveLeft();
void moveRight();
private:
sf::Sprite mSprite;
sf::Vector2i mSource;
};
} /* end namespace test */
#endif /* PLAYER_H_ */
Player.cpp
#include "Player.h"
// you need this because of forward declaration
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
namespace test {
Player::Player(const sf::Texture& imagePath) :
mSprite(imagePath),
mSource(1, Player::Down) {
// do not need that line anymore, thanks to initialiser list
//pSprite.setTexture(pTexture);
mSprite.setScale(1.5f, 1.5f);
}
Player::~Player() {
// TODO Auto-generated destructor stub
}
void Player::draw(sf::RenderTarget& target, sf::RenderStates states) const {
target.draw(mSprite, states);
}
void Player::moveUp() {
mSource.y = Up;
mSprite.move(0, -0.2);
//animation
mSource.x++;
if (mSource.x * 32 >= (int) mSprite.getTexture()->getSize().x) {
mSource.x = 0;
}
mSprite.setTextureRect(sf::IntRect(mSource.x * 32, mSource.y * 32, 32, 32));
}
void Player::moveDown() {
mSource.y = Down;
mSprite.move(0, 0.2);
//animation
mSource.x++;
if (mSource.x * 32 >= (int) mSprite.getTexture()->getSize().x) {
mSource.x = 0;
}
}
void Player::moveLeft() {
mSource.y = Left;
mSprite.move(-0.2, 0);
//animation
mSource.x++;
if (mSource.x * 32 >= (int) mSprite.getTexture()->getSize().x) {
mSource.x = 0;
}
}
void Player::moveRight() {
mSource.y = Right;
mSprite.move(0.2, 0);
//animation
mSource.x++;
if (mSource.x * 32 >= (int) mSprite.getTexture()->getSize().x) {
mSource.x = 0;
}
}
} /* end namespace test */
main.cpp
#include <SFML/Graphics.hpp>
//#include <string> // not used for now
#include <iostream>
// don't forget to include your own header
#include "Player.h"
int main() {
// just to save typing the "std::"
using std::cout;
using std::endl;
using std::cerr;
//window
sf::RenderWindow window(sf::VideoMode(1200, 700), "Testing");
window.setKeyRepeatEnabled(false);
//player texture
sf::Texture pTexture;
if (!pTexture.loadFromFile("image/playerSprite.png")) {
cerr << "Texture Error" << endl;
}
test::Player thePlayer(pTexture);
//game loop
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
}
window.clear();
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) //move up
{
thePlayer.moveUp();
} else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) //move down
{
thePlayer.moveDown();
} else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) //move right
{
thePlayer.moveRight();
} else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) //move left
{
thePlayer.moveLeft();
}
window.draw(thePlayer);
window.display();
}
return 0;
}
Other good practices
Accessors, or Getters/Setters, are member functions that gives one the access to a class private member.
In your code, you could do something like that:
class Player {
public:
Player(const sf::Texture& playerTexture);
virtual ~Player();
// to give access to a const reference of the sprite
// One could call it like: sf::Sprite mySprite = myPlayerObject.getSprite();
// notice also that the method itself is const, which assure you that
// myPlayerObject won't change by calling getSprite()
const sf::Sprite& getSprite() const{
return mSprite;
}
// setSprite is not a const method, so it will change the data
// inside myPlayerObject
void setSprite(const sf::Sprite& newSprite){
mSprite = newSprite;
}
private:
sf::Sprite mSprite;
sf::Vector2i mSource;
};

C calling a class function inside of another Class that is currently an Object

new here, so be gentle, I'm currently doing my Major Project for my course and, I'm not asking for homework to be done for me, i just can't wrap my head around a strange problem i am having and have not been able to find an answer for it, even on here. I'm using SDL for my Drawing.
I'm doing Object Orientated Programming with my Project or a "state Machine" (which sounds less painful in a newbies mind, believe me), and in the render part of my Class Game1.cpp i am trying to call a Draw Function of my Player Class, but for some unknown reason that i can not fathom, it just skips this function call completely.
I have no errors, i even used breakpoints to find out what was happening, but it just skipped it completely every time, it is drawing the screen black as well without fail. Any help as t why it is skipping this would be really appreciated.
I honestly feel like it's a simple rookie mistake, but any and all scrutiny is welcome of my code, anything i can do to better myself is appreciated.
Game1.cpp:
#include "Game1.h"
#include "PlayerCharacter.h"
Game1::Game1( World * worldObject )
{
//object setup
this->worldObject = worldObject;
setDone (false);
}
Game1::~Game1()
{
}
void Game1::handle_events()
{
//*******************************************
//**//////////////Call Input///////////////**
//*******************************************
//******Check for Keyboard Input*************
//******Check Keyboard Logic*****************
//******Check for Mouse Input****************
//The mouse offsets
x = 0, y = 0;
//If the mouse moved
if (SDL_PollEvent(&worldObject->event))
{
if( worldObject->event.type == SDL_MOUSEMOTION )
{
//Get the mouse offsets
x = worldObject->event.motion.x;
y = worldObject->event.motion.y;
}
}
//******Check Mouse Logic********************
}
void Game1::logic()
{
//*******************************************
//**//////////Collision Detection//////////**
//*******************************************
//******Check Player Bullet Collision Loop***
//Check for collision with enemies
//Check for collision with bitmap mask (walls)
//******Check Enemy Bullet Collision Loop****
//Check for Collision with Player
//Check for collision with bitmap mask (walls)
}
void Game1::render()
{
//*******************************************
//**////////////////Drawing////////////////**
//*******************************************
//******Blit Black Background****************
SDL_FillRect(worldObject->Screen , NULL , 0xff000000);
//******Blit Bitmap Mask*********************
//******Blit Flashlight**********************
//******Blit Map*****************************
//******Blit Pickups*************************
//******Blit Bullets*************************
//******Blit Player**************************
&PlayerCharacter.Draw; // <----- Skips this line completely, no idea why
//******Blit Enemies*************************
//******Blit Blackened Overlay***************
//******Blit HUD*****************************
//******Flip Screen**************************
SDL_Flip(worldObject->Screen);
}
Game1.h
#ifndef __Game1_H_INLUDED__
#define __Game1_H_INLUDED__
#include "GameState.h"
#include "SDL.h"
#include "ImageLoader.h"
using namespace IMGLoader;
class Game1 : public GameState
{
private:
//Menu Image
World * worldObject;
SDL_Rect PauseMenu,Item1Tile,Item2Tile,Item3Tile;
/*bool bPauseMenu, bItem1Tile, bItem2Tile, bItem3Tile;
int ButtonSpace,ButtonSize;
float x,y;
int Alpha1,Alpha2;*/
//Clipping Window
//SDL_Rect sclip,dclip;
public:
//Loads Menu resources
Game1 (World * worldObject);
//Frees Menu resources
~Game1();
//Main loop functions
void handle_events();
void logic();
void render();
};
#endif
PlayerCharacter.cpp
#include "PlayerCharacter.h"
SDL_Rect psclip,pdclip;
PlayerCharacter::PlayerCharacter ( float X, float Y, float dX, float dY, float Angle, float Speed, bool Existance, int Height, int Width, int Health, int Shield, SDL_Surface* Player ):Characters ( X, Y, dX, dY, Angle, Speed, Existance, Height, Width, Health )
{
this->Player = Player;
this->Shield = Shield;
this->Player = load_image("image\Player1.png");
}
void PlayerCharacter::setShield ( int Shield )
{
this->Shield = Shield;
}
int PlayerCharacter::getShield ( void )
{
return Shield;
}
void PlayerCharacter::Draw( )
{
psclip.x = 0; psclip.y = 0; psclip.w = 64; psclip.h = 64;
pdclip.x = 640; pdclip.y = 318; pdclip.w = 64; pdclip.h = 64;
SDL_BlitSurface(Player, &psclip, worldObject->Screen, &pdclip);
}
PlayerCharacter.h
#ifndef __PlayerCharacter_H_INCLUDED__
#define __PlayerCharacter_H_INCLUDED__
#include "Characters.h"
class PlayerCharacter : public Characters
{
private:
int Shield;
SDL_Surface* Player;
World *worldObject;
public:
PlayerCharacter ( float X, float Y, float dX, float dY, float Angle, float Speed, bool Existance, int Height, int Width, int Health, int Shield, SDL_Surface* Player );
void setShield ( int Shield );
int getShield ( void );
void Draw ( );
};
#endif
The line
&PlayerCharacter.Draw; // <----- Skips this line completely, no idea why
is not actually a function call. It's an expression that take the address of the Draw function in the PlayerCharacter class and does nothing with it.
I'm actually kind of surprised it compiles without errors, or at least tons of warnings.
You need to create a PlayerCharacter object, and then call the function in the object.
&PlayerCharacter.Draw is not a function call. PlayerCharacter::Draw() is not a static class method, so you need a PlayerCharacter object to invoke this method on.
You have a class PlayerCharacter, which defines what a PlayerCharacter is and what can be done with it. But as far as I see, you don't have a single PlayerCharacter object, i.e. no player character. If you had one, let's call him pc, then you could draw him with pc.Draw(). For that, you would have to instantiate the class, e.g. via PlayerCharacter pc( ... ), with the ... replaced by some appropriate values for the multitude of constructor parameters you have there. (You really want a default constructor, initializing all those to zero or other appropriate "start" value...)

How to create an object inside another class with a constructor?

So I was working on my code, which is designed in a modular way. Now, one of my classes; called Splash has to create a object of another class which is called Emitter. Normally you would just create the object and be done with it, but that doesn't work here, as the Emitter class has a custom constructor. But when I try to create an object, it doesn't work.
As an example;
Emitter has a constructor like so: Emitter::Emitter(int x, int y, int amount); and needs to be created so it can be accessed in the Splash class.
I tried to do this, but it didn't work:
class Splash{
private:
Emitter ps(100, 200, 400, "firstimage.png", "secondimage.png"); // Try to create object, doesn't work.
public:
// Other splash class functions.
}
I also tried this, which didn't work either:
class Splash{
private:
Emitter ps; // Try to create object, doesn't work.
public:
Splash() : ps(100, 200, 400, "firstimage.png", "secondimage.png")
{};
}
Edit: I know the second way is supposed to work, however it doesn't. If I remove the Emitter Section, the code works. but when I do it the second way, no window opens, no application is executed.
So how can I create my Emitter object for use in Splash?
Edit:
Here is my code for the emitter class and header:
Header
// Particle engine for the project
#ifndef _PARTICLE_H_
#define _PARTICLE_H_
#include <vector>
#include <string>
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "image.h"
extern SDL_Surface* gameScreen;
class Particle{
private: // Particle settings
int x, y;
int lifetime;
private: // Particle surface that shall be applied
SDL_Surface* particleScreen;
public: // Constructor and destructor
Particle(int xA, int yA, string particleSprite);
~Particle(){};
public: // Various functions
void show();
bool isDead();
};
class Emitter{
private: // Emitter settings
int x, y;
int xVel, yVel;
private: // The particles for a dot
vector<Particle> particles;
SDL_Surface* emitterScreen;
string particleImg;
public: // Constructor and destructor
Emitter(int amount, int x, int y, string particleImage, string emitterImage);
~Emitter();
public: // Helper functions
void move();
void show();
void showParticles();
};
#endif
and here is the emitter functions:
#include "particle.h"
// The particle class stuff
Particle::Particle(int xA, int yA, string particleSprite){
// Draw the particle in a random location about the emitter within 25 pixels
x = xA - 5 + (rand() % 25);
y = yA - 5 + (rand() % 25);
lifetime = rand() % 6;
particleScreen = Image::loadImage(particleSprite);
}
void Particle::show(){
// Apply surface and age particle
Image::applySurface(x, y, particleScreen, gameScreen);
++lifetime;
}
bool Particle::isDead(){
if(lifetime > 11)
return true;
return false;
}
// The emitter class stuff
Emitter::Emitter(int amount, int x, int y, string particleImage, string emitterImage){
// Seed the time for random emitter
srand(SDL_GetTicks());
// Set up the variables and create the particles
x = y = xVel = yVel = 0;
particles.resize(amount, Particle(x, y, particleImage));
emitterScreen = Image::loadImage(emitterImage);
particleImg = particleImage;
}
Emitter::~Emitter(){
particles.clear();
}
void Emitter::move(){
}
void Emitter::show(){
// Show the dot image.
Image::applySurface(x, y, emitterScreen, gameScreen);
}
void Emitter::showParticles(){
// Go through all the particles
for(vector<Particle>::size_type i = 0; i != particles.size(); i++){
if(particles[i].isDead() == true){
particles.erase(particles.begin() + i);
particles.insert(particles.begin() + i, Particle(x, y, particleImg));
}
}
// And show all the particles
for(vector<Particle>::size_type i = 0; i != particles.size(); i++){
particles[i].show();
}
}
Also here is the Splash Class and the Splash Header.
The second option should work, and I would start looking at compilation errors to see why it doesn't. In fact, please post any compilation errors you have related to this code.
In the meantime, you can do something like this:
class Splash{
private:
Emitter* ps;
public:
Splash() { ps = new Emitter(100,200,400); }
Splash(const Splash& copy_from_me) { //you are now responsible for this }
Splash & operator= (const Splash & other) { //you are now responsible for this}
~Splash() { delete ps; }
};
Well, I managed to fix it, in a hackish way though. What I did was create a default constructor, and move my normal Constructor code into a new function. Then I created the object and called the the new init function to set everything up.