The problem I'm having is that when I change an attribute of an Object the change isn't 'saving'. Easier to show you what's happening.
I'm learning c++ and decided to build a small chess app. Each Piece is a seperate Object.
They're stored in a std::vector as such
std::vector<Piece> pieces;
They're initialised like so
for (int i = 0; i < 2; i++)
{
Piece p;
p.Init(i*2+1, 1, renderer, SQUARE_SIZE, "king");
pieces.push_back(p);
}
When I click the mouse I want to select all pieces (temporarily)
for (int i = 0; i < pieces.size(); i++)
{
Piece p = pieces[i];
p.Select();
}
The issue is that while the Select() function is being called, by the time I get to rendering their selected attribute is false. Strangely this does not happen to the piece not contained within in the vector, referred to as k.
Before you ask there is nowhere in my code that I set selected to false :) (Except the constructor :P )
Also if you feel like downvoting, send me a comment first and I'll try fix whatever it is!
Here are the entire files. (not sure if this is the proper way to insert them)
Piece.h
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDl_image.h>
#include <array>
#include <vector>
class Piece
{
public:
Piece();
void Init(int _x, int _y, SDL_Renderer* renderer, int SQUARE_SIZE, std::string type);
void SetPos(int _x, int _y, int _w);
void LoadTexture(SDL_Renderer* renderer, std::string type);
void LoadMovementVector(std::string type);
void Render(SDL_Renderer* renderer);
void Select(){ selected = true; std::cout << "called\n";}
bool isSelected(){ return selected; }
int GetX(){ return x; } // SDL_Point
int GetY(){ return y; }
private:
int x, y;
std::vector<int> move_vector;
bool selected;
SDL_Rect rect;
SDL_Texture* texture;
};
Piece.cpp
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDl_image.h>
#include <vector>
#include "Piece.h"
Piece::Piece()
: x(0)
, y(0)
, selected(false)
{
}
void Piece::Init(int _x, int _y, SDL_Renderer* renderer, int SQUARE_SIZE, std::string type)
{
SetPos(_x, _y, SQUARE_SIZE);
LoadTexture(renderer, type);
LoadMovementVector(type);
}
void Piece::Render(SDL_Renderer* renderer)
{
//selected = true;
//std::cout << selected << std::endl;
if (selected)
{
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderFillRect(renderer, &rect);
}
if (texture != nullptr)
{
SDL_RenderCopy(renderer, texture, nullptr, &rect);
}
else
{
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderFillRect(renderer, &rect);
}
}
void Piece::LoadMovementVector(std::string type)
{
if (type == "king"){ // There literally has to be a better way to init std::vector
int arr[4] = {1,1,1,0};
for (int i = 0; i < 4; i++){ move_vector.push_back(arr[i]); }
}
for (int i = 0; i < move_vector.size(); i++)
{
std::cout << move_vector[i];
}
std::cout << std::endl;
}
void Piece::LoadTexture(SDL_Renderer* renderer, std::string type)
{
std::string source;
if (type == "king"){
source = "wk.png";
}
texture = IMG_LoadTexture(renderer, "res/wk.png");
}
void Piece::SetPos(int _x, int _y, int _w)
{
x = _x;
y = _y;
rect.x = _w*(_x-1);
rect.y = _w*(8-_y);
rect.w = _w;
rect.h = _w;
std::cout << x << y << std::endl;
}
Main.cpp
#include <iostream>
#include <math.h>
#include <SDL2/SDL.h>
#include <SDL2/SDl_image.h>
#include "Piece.h"
using namespace std::chrono;
// Would be 'const int' but I want to make the board resizeable
int SCREEN_WIDTH = 800;
int SCREEN_HEIGHT = 800;
int BOARD_WIDTH, BOARD_HEIGHT, SQUARE_SIZE;
SDL_Window* window;
SDL_Renderer* renderer;
std::vector<Piece> pieces;
Piece k;
bool InitEverything();
bool InitSDL();
bool CreateWindow();
bool CreateRenderer();
void SetupRenderer();
void Quit();
void RunGame();
void Render();
void HandleInput();
void UpdateDimensions();
double GetDelta();
void RenderGameBoard();
bool loop = true;
auto timePrev = high_resolution_clock::now();
int main(int argc, char* args[])
{
if (!InitEverything())
return -1;
std::cout << "Running Game..." << std::endl;
for (int i = 0; i < 2; i++)
{
Piece p;
p.Init(i*2+1, 1, renderer, SQUARE_SIZE, "king");
pieces.push_back(p);
}
k.Init(5, 1, renderer, SQUARE_SIZE, "king");
RunGame();
Quit();
return 0;
}
void RunGame()
{
while (loop)
{
HandleInput();
Render();
double delta = GetDelta();
}
}
void Render()
{
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
RenderGameBoard();
for (int i = 0; i < pieces.size(); i++)
{
pieces[i].Render(renderer);
}
k.Render(renderer);
SDL_RenderPresent(renderer);
}
void RenderGameBoard()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if ((j%2==0&&i%2==0)||(j%2!=0&&i%2!=0))
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
else
SDL_SetRenderDrawColor(renderer, 180, 180, 180, 255);
SDL_Rect r = {i*SQUARE_SIZE, j*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE};
SDL_RenderFillRect(renderer, &r);
}
}
}
void HandleInput()
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
loop = false;
else if (event.type == SDL_KEYDOWN)
{
}
else if (event.type == SDL_MOUSEBUTTONDOWN)
{
if (event.button.button == SDL_BUTTON_LEFT)
{
k.Select();
for (int i = 0; i < pieces.size(); i++)
{
Piece p = pieces[i];
p.Select();
}
int x = floor(event.button.x/SQUARE_SIZE)+1;
int y = 8-floor(event.button.y/SQUARE_SIZE);
for (int i = 0; i < pieces.size(); i++)
{
Piece p = pieces[i];
if (p.GetX() == x && p.GetY() == y)
{
p.Select();
}
}
}
}
}
}
void UpdateDimensions()
{
BOARD_WIDTH = SCREEN_WIDTH;
BOARD_HEIGHT = SCREEN_HEIGHT;
SQUARE_SIZE = BOARD_WIDTH/8;
}
double GetDelta()
{
auto timeCurrent = high_resolution_clock::now();
auto timeDiff = duration_cast< nanoseconds >( timeCurrent - timePrev );
double delta = timeDiff.count();
delta /= 1000000000;
timePrev = timeCurrent;
return delta;
}
bool InitEverything()
{
if (!InitSDL())
return false;
if (!CreateWindow())
return false;
if (!CreateRenderer())
return false;
SetupRenderer();
UpdateDimensions();
return true;
}
bool InitSDL()
{
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
std::cout << "SDL failed to initialize : " << SDL_GetError() << std::endl;
return false;
}
return true;
}
bool CreateWindow()
{
window = SDL_CreateWindow("Chess", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (!window)
{
std::cout << "Failed to create window : " << SDL_GetError() << std::endl;
return false;
}
return true;
}
bool CreateRenderer()
{
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer)
{
std::cout << "Failed to create renderer : " << SDL_GetError() << std::endl;
return false;
}
return true;
}
void SetupRenderer()
{
SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT);
}
void Quit()
{
SDL_DestroyWindow(window);
SDL_Quit();
}
This:
Piece p = pieces[i];
is creating a copy of the piece at index i in the vector.
Any methods you call after that are operating on the copy, not on the piece in the array.
Instead, take a reference to it:
Piece& p = pieces[i];
After that, p is a reference to element i in the vector and any operations you perform on it are performed on the vector element.
Related
so i've been working on a game system/engine, for my 2D Platformer, and when i press the w, a, s, or d keys it won't move when called in the main loop event.
Here is all of my project files and everything that i've written:
main.cpp:
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include <vector>
#include "RenderWindow.hpp"
#include "Entity.hpp"
#include "Utils.hpp"
int main(int argc, char const *argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) > 0)
std::cout << "ERROR: SDL_Init() HAS FAILED: SDL_ERROR => " << SDL_GetError() << std::endl;
if (!(IMG_Init(IMG_INIT_PNG)))
std::cout << "ERROR: IMG_Init() HAS FAILED: SDL_ERROR => " << SDL_GetError() << std::endl;
RenderWindow window("GAME v1.0", 1280, 720);
SDL_Texture* grassTexture = window.loadTexture("res/gfx/ground_grass.png");
SDL_Texture* playerTexture = window.loadTexture("res/gfx/ghost.png");
std::vector<Entity> platforms = {Entity(Vector2f(0, 30), grassTexture),
Entity(Vector2f(30, 30), grassTexture),
Entity(Vector2f(30, 30), grassTexture),
Entity(Vector2f(60, 30), grassTexture)};
Entity player(Vector2f(30, 8), playerTexture);
bool gameRunning = true;
SDL_Event event;
const float timeStep = 0.01f;
float accumulator = 0.0f;
float currentTime = utils::hireTimeInSeconds();
while(gameRunning)
{
int startTicks = SDL_GetTicks();
float newTime = utils::hireTimeInSeconds();
float frameTime = newTime - currentTime;
currentTime = newTime;
accumulator += frameTime;
while(accumulator >= timeStep)
{
// Get out controls and events
while(SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
gameRunning = false;
break;
// window.freeTexture(grassTexture);
// window.freeTexture(playerTexture);
}
// Add code to move the player texture
const Uint8* currentKeyStates = SDL_GetKeyboardState(NULL);
Vector2f& playerPos = player.getPos();
if(currentKeyStates[SDL_SCANCODE_W]) {
playerPos.y -= 1;
break;
}
if(currentKeyStates[SDL_SCANCODE_S]) {
playerPos.y += 1;
break;
}
if(currentKeyStates[SDL_SCANCODE_A]) {
playerPos.x -= 1;
break;
}
if(currentKeyStates[SDL_SCANCODE_D]) {
playerPos.x += 1;
break;
}
}
window.clear();
for (Entity& e : platforms)
{
window.render(e);
window.render(player);
}
window.display();
// // Add code to move the player texture
// const Uint8* currentKeyStates = SDL_GetKeyboardState(NULL);
// Vector2f& playerPos = player.getPos();
// if(currentKeyStates[SDL_SCANCODE_W]) {
// playerPos.y -= 1;
// }
// if(currentKeyStates[SDL_SCANCODE_S]) {
// playerPos.y += 1;
// }
// if(currentKeyStates[SDL_SCANCODE_A]) {
// playerPos.x -= 1;
// }
// if(currentKeyStates[SDL_SCANCODE_D]) {
// playerPos.x += 1;
// }
//playerPos.print();
accumulator -= timeStep;
// std::cout << accumulator << std::endl;
}
// const float alpha = accumulator / timeStep; // 50%?
// window.freeTexture(grassTexture);
// window.freeTexture(playerTexture);
int frameTicks = SDL_GetTicks() - startTicks;
if (frameTicks < 1000 / window.getRefreshRate())
SDL_Delay(100 / window.getRefreshRate() - frameTicks);
}
window.cleanUp();
SDL_Quit();
return 0;
}
renderwindow.hpp:
#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "Entity.hpp"
class RenderWindow
{
public:
RenderWindow(const char* p_title, int p_w, int p_h);
SDL_Texture* loadTexture(const char* p_filePath);
int getRefreshRate();
void cleanUp();
void clear();
void render(Entity& p_entity);
//void freeTexture(SDL_Texture* p_tex);
void display();
private:
SDL_Window* window;
SDL_Renderer* renderer;
};
renderwindow.cpp:
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include "RenderWindow.hpp"
#include "Entity.hpp"
RenderWindow::RenderWindow(const char* p_title, int p_w, int p_h)
:window(NULL), renderer(NULL)
{
window = SDL_CreateWindow(p_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, p_w, p_h, SDL_WINDOW_SHOWN);
if (window == NULL)
{
std::cout << "ERROR: Window has failed to init! SDL_Error: " << SDL_GetError() << std::endl;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
}
SDL_Texture* RenderWindow::loadTexture(const char* p_filePath)
{
SDL_Texture* texture = NULL;
texture = IMG_LoadTexture(renderer, p_filePath);
if (texture == NULL)
std::cout << "ERROR: Failed to load texture! SDL_Error: " << SDL_GetError() << std::endl;
return texture;
}
int RenderWindow::getRefreshRate()
{
int displayIndex = SDL_GetWindowDisplayIndex(window);
SDL_DisplayMode mode;
SDL_GetDisplayMode(displayIndex, 0, &mode);
return mode.refresh_rate;
}
void RenderWindow::cleanUp()
{
SDL_DestroyWindow(window);
}
void RenderWindow::clear()
{
SDL_RenderClear(renderer);
}
void RenderWindow::render(Entity& p_entity)
{
SDL_Rect src;
src.x = p_entity.getCurrentFrame().x;
src.y = p_entity.getCurrentFrame().y;
src.w = p_entity.getCurrentFrame().w;
src.h = p_entity.getCurrentFrame().h;
SDL_Rect dst;
dst.x = p_entity.getPos().x * 4;
dst.y = p_entity.getPos().y * 4;
dst.w = p_entity.getCurrentFrame().w * 4;
dst.h = p_entity.getCurrentFrame().h * 4;
SDL_RenderCopy(renderer, p_entity.getTex(), &src, &dst);
}
// void RenderWindow::freeTexture(SDL_Texture* p_tex) {
// SDL_DestroyTexture(p_tex);
// }
void RenderWindow::display()
{
SDL_RenderPresent(renderer);
}
Entity.hpp:
#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "Math.hpp"
class Entity
{
public:
Entity(Vector2f p_pos, SDL_Texture* p_tex);
Vector2f& getPos()
{
return pos;
}
void setPos(Vector2f p_pos)
{
pos = p_pos;
}
SDL_Texture* getTex();
SDL_Rect getCurrentFrame();
private:
Vector2f pos;
SDL_Rect currentFrame;
SDL_Texture* tex;
};
entity.cpp:
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "Entity.hpp"
#include "Math.hpp"
Entity::Entity(Vector2f p_pos, SDL_Texture* p_tex)
:pos(p_pos), tex(p_tex)
{
currentFrame.x = 0;
currentFrame.y = 0;
currentFrame.w = 32;
currentFrame.h = 32;
}
SDL_Texture* Entity::getTex()
{
return tex;
}
SDL_Rect Entity::getCurrentFrame()
{
return currentFrame;
}
math.hpp:
#pragma once
#include <iostream>
struct Vector2f
{
Vector2f()
:x(0.0f), y(0.0f)
{}
Vector2f(float p_x, float p_y)
:x(p_x), y(p_y)
{}
void print()
{
std::cout << x << ", " << y << std::endl;
}
float x, y;
};
Utils.hpp:
#pragma once
#include <SDL2/SDL.h>
namespace utils
{
inline float hireTimeInSeconds()
{
float t = SDL_GetTicks();
t *= 0.001f;
return t;
}
}
Thanks!
This is an updated version of my code, i've figured it out.
It turns out the problem was:
if (frameTicks < 1000 / window.getRefreshRate())
SDL_Delay(100 / window.getRefreshRate() - frameTicks);
was actually delaying it by 100 instead of 1000.
I'm making a little game as a small project but I can't get an if statement to do anything. If I make it !statement it works though. I run this if statement to find which cube on the "grid" (An array or cubes I render in a for loop I didn't show) the mouse clicked on. I use C++ and SDL2 on a Mac. This is my code:
#include <iostream>
#include <SDL2/SDL.h>
void RenderRects(SDL_Renderer *renderer);
void ToggleRect(int MouseX, int MouseY);
struct Grid
{
bool IsActive;
SDL_Rect Rect;
};
Grid grid[228960];
int main()
{
bool IsRunning = true;
bool IsRunningSim;
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = SDL_CreateWindow("My Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 780, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
int h, w;
SDL_MaximizeWindow(window);
SDL_GetRendererOutputSize(renderer, &w, &h);
while (IsRunning)
{
// std::cout << w << std::endl;
// std::cout << h << std::endl;
SDL_Event ev;
while (SDL_PollEvent(&ev))
{
if (ev.type == SDL_QUIT)
{
IsRunning = false;
}
if (ev.type == SDL_MOUSEBUTTONDOWN)
{
int x, y;
SDL_GetMouseState(&x, &y);
ToggleRect(x, y);
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
//rendering
RenderRects(renderer);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
void RenderRects(SDL_Renderer *renderer)
{
for (int i = 0; i < 1440; i += 10)
{
for (int j = 0; j < 795; j += 10)
{
SDL_Rect Rect = {i, j, 10, 10};
grid[i].Rect = Rect;
SDL_SetRenderDrawColor(renderer, 100, 100, 100, 225);
SDL_RenderDrawRect(renderer, &grid[i].Rect);
}
}
}
void ToggleRect(int MouseX, int MouseY)
{
SDL_Point MousePos;
MousePos.x = MouseX;
MousePos.y = MouseY;
for (int i = 0; i < 228961; i++)
{
if (SDL_PointInRect(&MousePos, &grid[i].Rect)) //This is the if that doesn't work.
{
std::cout << i << std::endl;
}
}
}
I have fixed this. I had to change my method of drawing since it was drawing over the rect and then showing after I changed its color. There was also an issue with generating the Rects that was probably effect it.
I have a base class cGameObject which has a virtual update function. I wish to have many derived game objects each with their own specific update function.
I want to add the derived gameobjects to a vector and iterate through them to call each of their update methods.
What is wrong with my iterator?
//In Header file
std::vector <cGameObject*> vGameObjs;
std::vector <cGameObject*>::iterator Iter;
cGameObject *AGameObj;
/In cpp file - add object pointer to vector
AGameObj = new BrickBat(128, 32, (1024 - 128) / 2, 768 - 64, 0);
vGameObjs.push_back(AGameObj);
AGameObj = new BrickBall(64, 512, 384, 1, 1, 0);
vGameObjs.push_back(AGameObj);
//Iterator Crashing??
for (Iter = vGameObjs.begin(); Iter != vGameObjs.end(); ++Iter)
{
//Call Each Objects Update() method here?
}
When I run this, it throws an exception: read access violation. _Mycont was nullptr.
Not sure what to do.
error thrown
Header of Class App Class:
#ifndef _H_AGK_TEMPLATE_
#define _H_AGK_TEMPLATE_
// Link to GDK libraries
#include "AGK.h"
#include "Brickbat.h"
#include "BrickBall.h"
#include "cGameObject.h"
#include <vector>
#define DEVICE_WIDTH 1024
#define DEVICE_HEIGHT 768
#define DEVICE_POS_X 32
#define DEVICE_POS_Y 32
#define FULLSCREEN false
// used to make a more unique folder for the write path
#define COMPANY_NAME "BitMaNip:Play"
// Global values for the app
class app
{
public:
// constructor
app() { memset ( this, 0, sizeof(app)); }
// main app functions - mike to experiment with a derived class for this..
void Begin( void );
int Loop( void );
void End( void );
private:
//Vector of GameObject Pointers;
std::vector <cGameObject*> vGameObjs;
//Iterator of GameObjects
std::vector <cGameObject*>::iterator Iter;
BrickBat *MyBat;
BrickBall *MyBall;
cGameObject *AGameObj;
};
extern app App;
#endif
// Allow us to use the LoadImage function name
#ifdef LoadImage
#undef LoadImage
#endif
cpp file for Header
// Includes
#include "template.h"
#include "cGameObject.h"
#include
// Namespace
using namespace AGK;
app App;
void app::Begin(void)
{
agk::SetVirtualResolution (DEVICE_WIDTH, DEVICE_HEIGHT);
agk::SetClearColor( 151,170,204 ); // light blue
agk::SetSyncRate(60,0);
agk::SetScissor(0,0,0,0);
//Test
/*BrickBall = agk::CreateSprite(0);
agk::SetSpriteSize(BrickBall, 64, 64);
agk::SetSpriteColor(BrickBall, 255, 255, 255, 255);
xPos = (DEVICE_WIDTH - 64) / 2;
yPos = (DEVICE_HEIGHT - 64) / 2;
agk::SetSpritePosition(BrickBall, xPos , yPos );
xDir = 1;
yDir = 1;
iSpeed = 8;*/
MyBat = new BrickBat(128, 32, (1024-128)/2, 768-64, 0);
AGameObj = new BrickBat(128, 32, (1024 - 128) / 2, 768 - 64, 0);
vGameObjs.push_back(AGameObj);
MyBall = new BrickBall(64, 512, 384, 1, 1, 0);
AGameObj = new BrickBall(64, 512, 384, 1, 1, 0);
vGameObjs.push_back(AGameObj);
}
int app::Loop (void)
{
agk::Print( agk::ScreenFPS() );
if (agk::GetRawKeyState(37) == 1)
{
MyBat->MoveLeft();
}
if (agk::GetRawKeyState(39) == 1)
{
MyBat->MoveRight();
}
MyBat->Update();
MyBall->Update();
MyBall->Collided(MyBat->iGetBatID());
for (Iter = vGameObjs.begin(); Iter != vGameObjs.end(); ++Iter)
{
//(*Iter)->Update();
//(*Iter)->Collided(MyBat->iGetBatID());
}
Derived class
include "cGameObject.h"
class BrickBall: public cGameObject
{
private:
bool bHoriDir;
bool bVertDir;
int iSpeed;
bool bPause; //in case game is paused
public:
BrickBall(int iSize, int xPos, int yPos, bool bHori, bool bVert, int ImageID);
virtual void Update() override;
virtual void Collided(int OtherSpriteToCheck) override;
};
agk::Sync();
return 0; // return 1 to close app
}
void app::End (void)
{
}
Base Class:
#pragma once
class cGameObject
{
protected:
bool bInit = false;
int iSprID;
int iImageID;
int iXPos;
int iYPos;
int iAngle;
int iAlpha;
int iWidth;
int iHeight;
int iColour;
//Movement
float fDeltaX;
float fDeltaY;
//Animation
int iAniType; //Type of animation
//0 = No Animation
//1 = Repeating Loop of Frames (All image is animation)
//2 =
int iFrameW; //Width of Animation Frame
int iFrameH; //Height of Animation frame
int iFPS; //Animation Delay
int iNumFrames; //Number of animation frames
int iAniCount; //Frame Counter
public:
// set up default for constructor
cGameObject(int width = 16, int height = 16, int xPos = 0, int yPos = 0, int ImageID = 0);
void SetPosition(int ixPos, int iyPos);
void SetSize(int iWidth, int iHeight);
void SetWidth(int Width);
void SetAngle(int iAngle);
void SetTransparency(int iAlpha);
void SetAnimation(int Type, int FrameW, int FrameH, int FPS, int NumFrames);
virtual void Collided(int OtherSpriteToCheck) {};
virtual void Update() {};
int iGetWidth();
int iGetHeight();
int iGetX();
int iGetY();
int iGetSprID();
~cGameObject();
};
Base Class cpp
#include "cGameObject.h"
#include "agk.h"
void cGameObject::SetAngle(int iAngle)
{
if (bInit == true)
{
if (iAngle > 0 && iAngle < 359)
{
agk::SetSpriteAngle(iSprID, iAngle);
}
}
}
//cGameObject::cGameObject(int width, int height, int xPos, int yPos, const char * szImageFile)
cGameObject::cGameObject(int width, int height, int xPos, int yPos, int ImageID)
{
bInit = true;
iImageID = 0;
/*if (std::strlen(szImageFile) > 0)
{
iImageID = agk::LoadImage(szImageFile);
if (iImageID < 1)
{
bInit = false;
}
}*/
iColour = agk::MakeColor(255, 255, 255);
//init animation code
iAniType = 0; //Type of animation
iFrameW = 64; //Width of Animation Frame
iFrameH = 64; //Height of Animation frame
iFPS = 10; //Animation Delay
iNumFrames = 1; //Number of animation frames
iAniCount = 0; //Frame Counter
iSprID = agk::CreateSprite(iImageID);
if (iSprID < 1)
{
bInit = false;
}
else
{
agk::SetSpriteSize(iSprID, width, height);
agk::SetSpritePosition(iSprID, xPos, yPos);
fDeltaX = 4.0;
fDeltaY = 4.0;
}
}
void cGameObject::SetPosition(int ixPos, int iyPos)
{
if (bInit == true)
{
agk::SetSpritePosition(iSprID, ixPos, iyPos);
}
}
void cGameObject::SetSize(int iWidth, int iHeight)
{
if (bInit == true)
{
if (iWidth > 0 && iWidth < 1024 && iHeight > 0 && iHeight < 1024)
{
agk::SetSpriteSize(iSprID, iWidth, iHeight);
}
}
}
void cGameObject::SetWidth(int Width)
{
if (bInit == true)
{
agk::GetSpriteWidth(Width);
}
}
void cGameObject::SetTransparency(int iAlpha)
{
if (bInit == true)
{
if (iAlpha > 0 && iAlpha < 256)
{
agk::SetSpriteTransparency(iSprID, iAlpha);
}
}
}
void cGameObject::SetAnimation(int Type, int FrameW, int FrameH, int FPS, int NumFrames)
{
//Animation
iAniType = Type;
iFrameW = FrameW; //Width of Animation Frame
iFrameH = FrameH; //Height of Animation frame
iFPS = FPS; //Animation Delay
iNumFrames = NumFrames; //Number of animation frames
iAniCount = 0; //Frame Counter
agk::SetSpriteAnimation(iSprID, iFrameW, iFrameH, iNumFrames);
if (iAniType > 0)
{
agk::PlaySprite(iSprID, iFPS);
}
}
int cGameObject::iGetWidth()
{
if (bInit == true)
{
return agk::GetSpriteWidth(iSprID);
}
else
{
return 0;
}
}
int cGameObject::iGetHeight()
{
if (bInit == true)
{
return agk::GetSpriteHeight(iSprID);
}
else
{
return 0;
}
}
int cGameObject::iGetX()
{
if (bInit == true)
{
return agk::GetSpriteX(iSprID);
}
else
{
return 0;
}
}
int cGameObject::iGetY()
{
if (bInit == true)
{
return agk::GetSpriteY(iSprID);
}
else
{
return 0;
}
}
int cGameObject::iGetSprID()
{
if (bInit == true)
{
return iSprID;
}
else
{
return 0;
}
}
cGameObject::~cGameObject()
{
if (bInit == true)
{
agk::DeleteSprite(iSprID);
}
}
Derived Class Header:
#include "cGameObject.h"
class BrickBall: public cGameObject
{
private:
bool bHoriDir;
bool bVertDir;
int iSpeed;
bool bPause; //in case game is paused
public:
BrickBall(int iSize, int xPos, int yPos, bool bHori, bool bVert, int ImageID);
virtual void Update() override;
virtual void Collided(int OtherSpriteToCheck) override;
};
Derived Class cpp
#include "BrickBall.h"
BrickBall::BrickBall(int Size, int xPos, int yPos, bool bHori, bool bVert, int ImageID):cGameObject(Size, Size, xPos, yPos, ImageID)
{
iWidth = Size;
iHeight = Size;
iXPos = xPos;
iYPos = yPos;
bHoriDir = bHori;
bVertDir = bVert;
/*iSprID = agk::CreateSprite(0);
agk::SetSpriteColor(iSprIdx, 255, 255, 255, 255);
//agk::SetSpriteSize(iSprIdx, iSize, iSize);
agk::SetSpriteSize(iSprIdx, 64, 64);
//agk::SetSpritePosition(iSprIdx, ixPos, iyPos);
agk::SetSpritePosition(iSprIdx, ixPos, iyPos);
bInit = true;*/
iSpeed = 8;
}
void BrickBall::Update()
{
if (bInit==true)// && BatID > 0)
{
//Move Ball
agk::SetSpriteColor(iSprID, 100, 100, 100, 255);
agk::PrintC("BallX:");
agk::Print(iXPos);
if (bHoriDir == 1) //Right
{
iXPos = iXPos + iSpeed;
if (iXPos > 1024 - iWidth)
{
bHoriDir = 0;
}
}
else
{
iXPos = iXPos - iSpeed;
if (iXPos < 0)
{
bHoriDir = 1;
}
}
if (bVertDir == 1) //down
{
iYPos = iYPos + iSpeed;
if (iYPos > 768 - 64)
{
bVertDir = 0;
}
}
else
{
iYPos = iYPos - iSpeed;
if (iYPos < 0)
{
bVertDir = 1;
}
}
agk::SetSpritePosition(iSprID, iXPos, iYPos);
//END Move Ball
//Bat2Ball Collisions
/*if (agk::GetSpriteCollision(iSprID, BatID))
{
//We have collided.
//As Ball is bigger than the gap below the bat must have hit top or sides
//so just flip the vertcal direction
if (bVertDir == 1)
{
bVertDir = 0;
}
}*/
}
}
void BrickBall::Collided(int OtherSpriteToCheck)
{
if (agk::GetSpriteCollision(iSprID, OtherSpriteToCheck))
{
if (bVertDir == 1)
{
bVertDir = 0;
}
}
}
I don't know the cause of your error, but I got this exact error because I had an iterator to a vector, then I updated the vector, then I tried to dereference the iterator (e.g. access *myIterator). I'm new to C++, but it seems that if you alter a collection after getting an iterator for it, your iterator is no longer valid. You need to repoint your iterator to wherever it was.
i am following SDL game development book by shaun mitcchel and was trying to compile the code and was getting error of constructor is private. i am using mingw for compiling.
main.cpp
#include "game.h"
game* g_game = 0;
int main(int argc, char* args[])
{
g_game = new game;
g_game->init("SDL",100,100,640,480,SDL_WINDOW_SHOWN);
while(g_game->running())
{
g_game->handleEvents();
g_game->update();
g_game->render();
}
g_game->clean();
return 0;
}
game.h
#ifndef GAME_H
#define GAME_H
#include <SDL.h>
#include <SDL_image.h>
#include <iostream>
#include "TextureManager.h"
class game
{
public:
game(){}
virtual ~game();
bool init(char* title, int xpos, int ypos, int width, int height, int flags);
void render();
void update();
void handleEvents();
void clean();
bool running()
{
return m_bRunning;
}
protected:
private:
SDL_Window* m_pWindow;
SDL_Renderer* m_pRenderer;
int m_currentFrame;
textureManager m_textureManager;
bool m_bRunning;
};
#endif // GAME_H
game.cpp
#include "game.h"
bool game::init(char* title,int xpos, int ypos, int width, int height,int flags)
{
//initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING)== 0)
{
std::cout << "SDL init success\n";
//init window
m_pWindow = SDL_CreateWindow(title,xpos,ypos,width,height,flags);
if(m_pWindow != 0)
{
std::cout << "window creation successful\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow,-1,0);
if(m_pRenderer != 0) {
std::cout << "render init success\n";
SDL_SetRenderDrawColor(m_pRenderer,255,0,0,255);
}
else {
std::cout << "render init fail\n";
return false;
}
}
else {
std::cout << "Window init fail\n";
return false;
}
}
else {
std::cout << "Sdl init failed\n";
return false;
}
std::cout << "init success\n";
m_bRunning = true;
//to load
if(!ThetextureManager::Instance()->load("assets/animate- alpha.png","animate",m_pRenderer))
{
return false;
}
}
void game::render()
{
SDL_RenderClear(m_pRenderer);
ThetextureManager::Instance()->draw("animate", 0, 0,128,82,m_pRenderer);
ThetextureManager::Instance()->drawFrame("animate", 100,100,128,82,1,m_currentFrame,m_pRenderer);
SDL_RenderPresent(m_pRenderer);
}
void game::handleEvents()
{
SDL_Event event;
if(SDL_PollEvent(&event)) {
switch(event.type)
{
case SDL_QUIT:
m_bRunning = false;
break;
default:
break;
}
}
}
void game::clean()
{
std::cout << "cleaning game\n";
SDL_DestroyRenderer(m_pRenderer);
SDL_DestroyWindow(m_pWindow);
SDL_Quit();
}
void game::update()
{
m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
}
TextureManager.h
#ifndef TEXTUREMANAGER_H_INCLUDED
#define TEXTUREMANAGER_H_INCLUDED
#include <iostream>
#include<map>
#include<SDL.h>
#include<SDL_image.h>
class textureManager {
public:
static textureManager* Instance()
{
if(s_pInstance == 0)
{
s_pInstance = new textureManager();
return s_pInstance;
}
return s_pInstance;
}
bool load(std::string fileName, std::string id,SDL_Renderer* pRenderer);
void draw(std::string id,int x,int y,int width,int height,SDL_Renderer* pRenderer,SDL_RendererFlip flip);
void drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer* pRenderer,SDL_RendererFlip flip);
std::map<std::string, SDL_Texture*> m_textureMap;
private:
textureManager() {}
textureManager(const textureManager&);
textureManager& operator=(const textureManager&);
static textureManager* s_pInstance;
};
typedef textureManager ThetextureManager;
#endif // TEXTUREMANAGER_H_INCLUDED
texturemanagement.cpp
#include "TextureManager.h"
textureManager* textureManager::s_pInstance = 0;
bool textureManager::load(std::string fileName, std::string id,SDL_Renderer* pRenderer)
{
SDL_Surface* pTempSurface = IMG_Load(fileName.c_str());
if(pTempSurface == 0)
{
return false;
}
SDL_Texture* pTexture = SDL_CreateTextureFromSurface(pRenderer, pTempSurface);
SDL_FreeSurface(pTempSurface);
if(pTexture != 0)
{
m_textureMap[id] = pTexture;
return true;
}
return false;
}
void textureManager::draw(std::string id,int x,int y,int width,int height,SDL_Renderer* pRenderer,SDL_RendererFlip flip)
{
SDL_Rect srcRect;
SDL_Rect destRect;
srcRect.x = 0;
srcRect.y = 0;
srcRect.w = destRect.w = width;
srcRect.h = destRect.h = height;
destRect.x = x;
destRect.y = y;
SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect, &destRect,0 , 0, flip);
}
void textureManager::drawFrame(std::string id, int x, int y, int width, int height, int currentRow, int currentFrame, SDL_Renderer* pRenderer,SDL_RendererFlip flip)
{
SDL_Rect srcRect;
SDL_Rect destRect;
srcRect.x = width * currentFrame;
srcRect.y = height * (currentRow - 1);
srcRect.w = destRect.w = width;
srcRect.h = destRect.h = height;
destRect.x = x;
destRect.y = y;
SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect, &destRect,0, 0, flip);
}
errors
C:\Users\lenovo\Desktop\node project\sdl\TextureManager.h||In constructor 'game::game()':|
C:\Users\lenovo\Desktop\node project\sdl\TextureManager.h|28|error: 'textureManager::textureManager()' is private|
C:\Users\lenovo\Desktop\node project\sdl\game.h|12|error: within this context|
C:\Users\lenovo\Desktop\node project\sdl\game.cpp||In member function 'void game::render()':|
C:\Users\lenovo\Desktop\node project\sdl\game.cpp|46|error: no matching function for call to 'textureManager::draw(const char [8], int, int, int, int, SDL_Renderer*&)'|
C:\Users\lenovo\Desktop\node project\sdl\game.cpp|47|error: no matching function for call to 'textureManager::drawFrame(const char [8], int, int, int, int, int, int&, SDL_Renderer*&)'|
You have textureManager m_textureManager member in class game (file game.h)
But in game.cpp you always use ThetextureManager::Instance()
You just need to remove m_textureManager member.
I'm trying to write a small game where boxes drop down from the top of the window. But for some reason, I can't change a internal variable in the class, the y-coordinate. I don' knowif I'm missing something basic, but I can't find the bug.
Box.h
#pragma once
#include "SDL.h"
class Box
{
public:
Box();
~Box();
void setX (int a);
void setY (int a);
void setSpeed (int a);
void setSurface ();
void render(SDL_Surface *source, SDL_Window *win);
void update();
private:
int x;
int y;
int speed;
SDL_Surface *sur;
SDL_Rect rect;
};
Box.cpp
#include "Box.h"
#include "SDL_image.h"
#include <iostream>
void Box::setX(int a)
{
x = a;
}
void Box::setY (int a)
{
y = a;
}
void Box::setSpeed (int a)
{
speed = a;
}
void Box::setSurface()
{
sur = IMG_Load("C:/hello.bmp");
if (sur == NULL)
{
std::cout << IMG_GetError();
}
}
Box::Box()
{
speed = 5;
y = 0;
x = 3;
rect.x = 0;
rect.y = 0;
}
Box::~Box()
{
}
void Box::render(SDL_Surface *source, SDL_Window *win)
{
SDL_BlitSurface(sur, NULL, source, &rect);
SDL_UpdateWindowSurface(win);
}
void Box::update()
{
setY(y + speed); //I've also tried y = y + speed
rect.y = y;
}
main.cpp
#include "SDL.h"
#include "Box.h"
#include "SDL_image.h"
#include <iostream>
bool init();
void update(Box test);
void render(Box test);
SDL_Window *win;
SDL_Surface *source;
int main(int argc, char *argv[])
{
init();
bool quit = false;
SDL_Event e;
Box test;
test.setSurface();
test.render(source, win);
while (quit ==false)
{
while( SDL_PollEvent( &e ) != 0 )
{
if( e.type == SDL_QUIT )
{
quit = true;
}
}
update(test);
render(test);
}
return 0;
}
void update(Box test)
{
test.update();
}
void render(Box test)
{
test.render(source, win);
}
bool init()
{
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
{
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (win == NULL)
{
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
return 1;
}
source = SDL_GetWindowSurface(win);
return true;
}
update takes its Box argument by value, so a copy of the original Box is always made when update(test) is called. This copy is then modified, and the original is left unchanged. To fix this, make update take its argument by reference.
void update(Box& test);
void update(Box& test)
{
test.update();
}