I've been trying to create a sprite in visual studio using sfml and c++, the code itself is running fine and there appear to be no errors.
PLAYER.H
#pragma once
#include "pSprite.h"
#include "Sprite.h"
#include "Enemy.h"
#include "Input.h"
#include <Windows.h>
class Player : public pSprite
{
public:
Input input;
Player(const sf::Vector2f & size = sf::Vector2f(0, 0));
~Player();
pSprite playerSprite;
sf::Texture texture;
float playerWidth;
float playerHeight;
float playerSpeed;
void update(float dt);
void initPlayer(float x, float y);
void kill(); // set to gameover
bool isAlive();
void move();
sf::Vector2f position;
Here is the header file for the Player class which is derived from a pSprite class which itself is derived from a Sprite class in order to get around the "Cannot instantiate abstract class" error.
PLAYER.CPP
void Player::initPlayer(float x, float y)
{
position.x = x;
position.y = y;
playerWidth = 60;
playerHeight = 50;
texture.loadFromFile("player1.png");
playerSprite.setTexture(&texture);
playerSprite.setSize(sf::Vector2f(playerWidth, playerHeight));
playerSpeed = 10;
playerSprite.setPosition(position);
}
Here is the code for the function which loads the texture and should set the sprite.
initPlayer is called in the main function and should set it up ready for all other functions called in the main and for drawing and displaying.
Related
I am working on creating pong but I have been having trouble with Collision.How can I add a pixel accurate Collision? I've created a collision when only using a main file but I can't figure it out when using header files.Can someone write out the code for Collision and add to a Collision.h and Collision.cpp for easy storage and modification.
main.cpp
#include "stdafx.h"
#include <SFML\Graphics.hpp>
#include "Paddle.h"
#include "Ball.h"
#include <iostream>
int main()
{
sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "Pong",
sf::Style::Close| sf::Style::Resize| sf::Style::Titlebar);
Paddle paddle1;
Paddle paddle2;
Ball ball;
while (window.isOpen()) {
sf::Event evnt;
while (window.pollEvent(evnt))
{
switch (evnt.type)
{
case sf::Event::Closed:
window.close();
break;
}
}
paddle1.Update();
paddle2.Update();
ball.Update(ballDirectionX,ballDirectionY);
window.clear();
paddle1.Draw(window);
paddle2.Draw(window);
ball.Draw(window);
window.display();
}
return 0;
}
Paddle.h
#pragma once
#include <SFML\Graphics.hpp>
class Paddle
{
public:
Paddle();
~Paddle();
void Draw(sf::RenderWindow& window);
void Update();
sf::RectangleShape paddle1;
sf::RectangleShape paddle2;
private:
};
Paddle.cpp
#include "stdafx.h"
#include "Paddle.h"
Paddle::Paddle()
{
paddle1.setSize(sf::Vector2f(20.0f, 120.0f));
paddle1.setFillColor(sf::Color::Red);
paddle2.setSize(sf::Vector2f(20.0f, 120.0f));
paddle2.setFillColor(sf::Color::Green);
paddle2.setPosition(sf::Vector2f(1900.0f, 0.0f));
}
Paddle::~Paddle()
{
}
void Paddle::Draw(sf::RenderWindow& window)
{
window.draw(paddle1);
window.draw(paddle2);
}
void Paddle::Update()
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
paddle1.move(sf::Vector2f(0, -3));
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
paddle1.move(sf::Vector2f(0, 3));
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
paddle2.move(sf::Vector2f(0, -3));
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
paddle2.move(sf::Vector2f(0, 3));
}
}
Ball.h
#pragma once
#include <SFML\Graphics.hpp>
class Ball
{
public:
Ball();
~Ball();
void Draw(sf::RenderWindow& window);
void Update() {
}
sf::CircleShape ball;
private:
};
Ball.cpp
#include "stdafx.h"
#include "Ball.h"
Ball::Ball()
{
ball.setRadius(20);
ball.setPosition(sf::Vector2f(400, 540));
}
Ball::~Ball()
{
}
void Ball::Draw(sf::RenderWindow & window)
{
window.draw(ball);
}
void Ball::Update()
{
}
Since Pong is a very simple game, I suggest you to create an intersect function with a sf::CircleShape and a sf::RectangleShape as arguments, because that's how you are representing your ball and paddles respectively.
I suggest you the following implementation, but there are better ones:
bool intersects(const sf::CircleShape &c, const sf::RectangleShape &r){
sf::FloatRect fr = r.getGlobalBounds();
sf::Vector2f topLeft(fr.left, fr.top);
sf::Vector2f topRight(fr.left + fr.width, fr.top);
sf::Vector2f botLeft(fr.left, fr.top + fr.height);
sf::Vector2f botRight(fr.left + fr.width, fr.top + fr.height);
return contains(c, topLeft) ||
contains(c, topRight) ||
contains(c, botLeft) ||
contains(c, botRight);
}
This is easy, simply check if each corner of the rectangle is inside of the circle, if none of them is contained, that circle and that rectangle don't intersect.
If any of the corners are contained into the circle, they intersects.
The contains() function quite simple in fact:
bool contains(const sf::CircleShape &c, const sf::Vector2f &p){
sf::Vector2f center = c.getPosition();
float a = (p.x - center.x);
float b = (p.y - center.y);
a *= a;
b *= b;
float r = c.getRadius() * c.getRadius();
return (( a + b ) < r);
}
Is based in this question, but I've separated it in each step for better comprehension.
EDIT
Note that this method only works if rectangles are in a vertical/horizontal orientation, this is, no rotations.
I made a character class for the player, and I want to add a player member to the class then draw the player. I am using sfml and xcode. The error I am getting is: No matching member function for call to 'draw' on the: window.draw(player); line. It looks like I need to put a sprite object into .draw() so how do I make player sprite that is part of the class and draw it onto the window? I am new to c++ and sfml so any help is very much appreciated thanks.
#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;
class Character{
public:
string sprite;
int health;
int defense;
int speed;
int experience;
bool move;
int x_pos;
int y_pos;
sf::Texture texture;
//Constructor - Ran everytime a new instance of the class is created
Character(string image){
health = 100;
defense = 100;
speed = 100;
experience = 0;
x_pos = 0;
y_pos = 0;
texture.loadFromFile(image);
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(0, 0, 100, 100));
sprite.setPosition(x_pos, y_pos);
}
//Destructor - Ran when the object is destroyed
~Character(){
}
//Methods
void forward();
void backward();
void left();
void right();
void attack();
};
void Character::forward(){
cout << "Go Forward";
}
void Character::backward(){
cout << "Go Backward";
}
void Character::left(){
cout << "Go Left";
}
void Character::right(){
cout << "Go Right";
}
Character player("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Player.png");
int main() {
// insert code here...
int windowWidth = 1150;
int windowHeight = 750;
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight ), "Awesome Game" );
while(window.isOpen()){
window.draw(player);
window.display();
window.setFramerateLimit(60);
}
}
You could simply add a member function that would return your player's sprite:
sf::Sprite Character::getSprite() {
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(0, 0, 100, 100));
sprite.setPosition(x_pos, y_pos);
return sprite;
}
Then pass the result to window.draw:
window.draw(player.getSprite());
Alternatively, you could invert the dependency and make the player responsible for all the drawing:
void Character::draw(sf::RenderWindow& w) {
w.draw(...);
}
There are other approaches, and the choice depends largely on a lot of external factors. This should get you started, though.
I am working with my first small project in SFML. I made a ball (projectile) which is bouncing around on the screen and a player which is movable. The problem however, occurred when I tried to make an Objecthandler to my objects. After letting the handler taking control of the drawing and updating of the objects, the player and the ball just stopped and became unmovable. My question is why?
The ball:
#ifndef PROJECTILE_H
#define PROJECTILE_H
#include <SFML\Graphics.hpp>
using namespace std;
class Projectile : public sf::Drawable {
private:
sf::Texture texture;
sf::Sprite sprite;
public:
Projectile();
virtual ~Projectile();
sf::Sprite getSprite() const;
virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;
};
#endif //PROJECTILE_H
#include "Projectile.h"
#include <iostream>
Projectile::Projectile() {
if (!this->texture.loadFromFile("../Resources/projectile.png")) {
cout << "Error! Projectile sprite could not be loaded!" << endl;
}
this->sprite.setPosition(sf::Vector2f(0.0f, 0.0f));
this->sprite.setTexture(this->texture);
sf::FloatRect boundingBoxProjectile = this->sprite.getGlobalBounds();
}
Projectile::~Projectile() {
}
sf::Sprite Projectile::getSprite() const{
return this->sprite;
}
void Projectile::draw(sf::RenderTarget & target, sf::RenderStates states) const {
target.draw(sprite, states);
}
The handler:
#ifndef OBJECTHANDLER_H
#define OBJECTHANDLER_H
#include "Block.h"
#include "Player.h"
#include "Projectile.h"
using namespace std;
class ObjectHandler : public sf::Drawable {
private:
Player player;
Block block;
Projectile projectile;
int hitX = 0;
int hitY = 0;
float checkX;
float checkY;
float keyFrameDuration = 0.0f;
float speed = 500.0f;
public:
ObjectHandler();
virtual ~ObjectHandler();
void updateProjectile(float dt);
void updatePlayer(float dt);
void updateBlock(float dt);
virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;
};
#endif OBJECTHANDLER_H
#include "ObjectHandler.h"
ObjectHandler::ObjectHandler() {
this->projectile = projectile;
this->block = block;
this->player = player;
}
ObjectHandler::~ObjectHandler() {
}
void ObjectHandler::updateProjectile(float dt) {
sf::Vector2f direction;
if (hitX == 0) {
direction = sf::Vector2f(0.5f, checkY);
checkX = 0.5f;
if (this->projectile.getSprite().getPosition().x >= 700) {
hitX = 1;
}
}
else if (hitX == 1) {
direction = sf::Vector2f(-0.5f, checkY);
checkX = -0.5f;
if (this->projectile.getSprite().getPosition().x <= 0) {
hitX = 0;
}
}
if (hitY == 0) {
direction = sf::Vector2f(checkX, 0.5f);
checkY = 0.5f;
if (this->projectile.getSprite().getPosition().y >= 460) {
hitY = 1;
}
}
else if (hitY == 1) {
direction = sf::Vector2f(checkX, -0.5f);
checkY = -0.5f;
if (this->projectile.getSprite().getPosition().y <= 0) {
hitY = 0;
}
}
this->projectile.getSprite().move(direction * speed * dt);
}
void ObjectHandler::draw(sf::RenderTarget & target, sf::RenderStates states) const {
this->block.draw(target, states);
this->projectile.draw(target, states);
this->player.draw(target, states);
}
And Game:
#ifndef GAME_H
#define GAME_H
#include <SFML\Graphics.hpp>
#include "ObjectHandler.h"
class Game : public sf::Drawable {
private:
virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;
sf::Texture backgroundTexture;
sf::Sprite backgroundSprite;
ObjectHandler object;
public:
Game();
virtual ~Game();
void update(float dt);
};
#endif // GAME_H
#include "Game.h"
#include <iostream>
using namespace std;
void Game::draw(sf::RenderTarget & target, sf::RenderStates states) const {
target.draw(backgroundSprite, states);
target.draw(this->object, states);
}
Game::Game() {
if (!backgroundTexture.loadFromFile("../Resources/levelOne.jpg")) {
cout << "The background could not be loaded!" << endl;
}
backgroundSprite.setTexture(backgroundTexture);
}
Game::~Game() {
}
void Game::update(float dt) {
this->object.updatePlayer(dt);
this->object.updateProjectile(dt);
this->object.updateBlock(dt);
}
The problem is your sf::Sprite Projectile::getSprite()const returns a copy of the actual sprite. Hence projectile.getSprite().move(...) are called by the copy.
Make a method move for your Projectile:
void Projectile::move(const sf::Vector2f& amount)
{
sprite.move(amount);
}
and call it in ObjectHandler: projectile.move(...).
You might also want to return a constant reference to your sprite in getSprite to avoid multiple copies: const sf::Sprite& Projectile::getSprite()const. It will cause an error when you try to modify it by calling projectile.getSprite().move(...) and you will see the bug faster.
As far as I can see the code for this class works yet it will not compile and is throwing the error mentioned in the title. Below is the header file.
This is using the SDL standard libraries.
texture2D.h
#ifndef TEXTURE2D_H
#define TEXTURE2D_H
#include <SDL.h>
#include <string>
#include "Commons.h"
using namespace::std;
class Texture2D
{
SDL_Renderer* mRenderer;
SDL_Texture* mTexture;
int mWidth;
int mHeight;
public:
Texture2D(SDL_Renderer* renderer);
~Texture2D();
bool LoadFromFile(string path);
void Free();
void Render(Vector2D newPosition, SDL_RendererFlip flip, double angle = 0.0f);
int GetWidth() { return mWidth; }
int GetHeight() { return mHeight; }
};
#endif
I imagine your definition of Render looks like this
In .cpp
void Texture2D::Render(Vector2D newPosition, SDL_RendererFlip flip, double angle = 0.0f)
{
...
}
When it should be
void Texture2D::Render(Vector2D newPosition, SDL_RendererFlip flip, double angle )
{
...
}
You only supply the default value in the declaration ( normally .h )
i developped game "mario bross" with SDL and c++ to simplify things , i have two rectangle and i had to change the coordinates one of them three steps up (-3) and after three steps down(+3) where ever the two rectangles go throught collision .
the problem is when the two rectangle goes throught collision one of them move up (-3) but it does not move down(+3) i redirect the coordinates of the rectangle it change up and down but it only render the up movement.
// surprise.h
#ifndef SURPRISE_H_INCLUDED
#define SURPRISE_H_INCLUDED
#include <SDL/SDL.h>
#include <vector>
#include "base.h"
class surprise:public baseclass
{
SDL_Rect box;
int xvel,yvel;
SDL_Surface* image;
bool ground;
double frame;
SDL_Rect clips[4];
public:
surprise(SDL_Surface*,int x,int y,int xvel,int yvel);
void show(SDL_Surface*);
void setFrame(double);
void move(int xvel);
double getFrame();
SDL_Rect* getRect();
int getyvel();
void setyvel(int y);
};
#endif // SURPRISE_H_INCLUDED
//surprise.cpp
#include"surprise.h"
#include <SDL/SDL.h>
surprise::surprise(SDL_Surface* img ,int x,int y,int xVel,int yVel)
{
image=img;
box.x=x;
box.y=y;
box.w=image->w/2;
box.h=image->h;
xvel=xVel;
yvel=yVel;
ground=0;
for(int i=0;i<3;i++)
{
clips[i].x=i*30;
clips[i].y=0;
clips[i].w=30;
clips[i].h=30;
}
frame=0.0;
}
double surprise::getFrame()
{
return frame;
}
void surprise::setFrame(double fr)
{
frame=fr;
}
void surprise::show(SDL_Surface* screen)
{
SDL_Rect tmp={box.x-coord.x,box.y,30,30};
if (frame>=2)
{
frame=0.1;
SDL_BlitSurface(image,&clips[(int)(frame+0.5)],screen,&tmp);
}
else
{
SDL_BlitSurface(image,&clips[(int)(frame+0.5)],screen,&tmp);
}
frame+=0.1;
}
SDL_Rect* surprise::getRect()
{
return &box;
}
int surprise::getyvel()
{
return box.y;
}
void surprise::setyvel(int y)
{
box.y+=y;
// part of game .cpp
// the surprise is the first box the player is the second box
//logique part
// i put the surprise class into vector
for (int i=0;i<surprises.size();i++)
{
SDL_Rect tmprect ={surprises[i]->getRect()->x-baseclass::coord.x,surprises[i]->getRect()->y,30,30};
if(collision(&tmprect,player1->getRect()))
{
for (int j=0;j<3;j++)
{
surprises[i]->setyvel(-1);
std::cout<<"increase the y coordinates "<<surprises[i]->getyvel()->y<<std::endl;
}
for (int k=0;k<3;k++)
{
surprises[i]->setyvel(+1);
std::cout<<"decrease the y coordinates "<<surprises[i]->getRect()->y<<std::endl;
}
}
}
//render part
SDL_Flip(screen);