diff --git a/CPP/SFMLEngine/LICENSE b/CPP/SFMLEngine/LICENSE new file mode 100644 index 0000000..37b2665 --- /dev/null +++ b/CPP/SFMLEngine/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Krzysztof Rudnicki + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/CPP/SFMLEngine/helloWorld/app b/CPP/SFMLEngine/helloWorld/app new file mode 100755 index 0000000..f812d09 Binary files /dev/null and b/CPP/SFMLEngine/helloWorld/app differ diff --git a/CPP/SFMLEngine/helloWorld/hello.cpp b/CPP/SFMLEngine/helloWorld/hello.cpp new file mode 100644 index 0000000..b5cc814 --- /dev/null +++ b/CPP/SFMLEngine/helloWorld/hello.cpp @@ -0,0 +1,24 @@ +#include + +int main() +{ + sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!"); + sf::CircleShape shape(100.f); + shape.setFillColor(sf::Color::Green); + + while (window.isOpen()) + { + sf::Event event; + while (window.pollEvent(event)) + { + if (event.type == sf::Event::Closed) + window.close(); + } + + window.clear(); + window.draw(shape); + window.display(); + } + + return 0; +} diff --git a/CPP/SFMLEngine/helloWorld/hello.o b/CPP/SFMLEngine/helloWorld/hello.o new file mode 100644 index 0000000..747fcc6 Binary files /dev/null and b/CPP/SFMLEngine/helloWorld/hello.o differ diff --git a/CPP/SFMLEngine/helloWorld/makefile b/CPP/SFMLEngine/helloWorld/makefile new file mode 100644 index 0000000..cef3057 --- /dev/null +++ b/CPP/SFMLEngine/helloWorld/makefile @@ -0,0 +1,6 @@ +compile:./hello.cpp + g++ -c ./hello.cpp + g++ hello.o -o app -lsfml-graphics -lsfml-window -lsfml-system + +run: + ./app diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/Other/resources.hpp b/CPP/SFMLEngine/makingAGameTick/Classes/Other/resources.hpp new file mode 100644 index 0000000..e564470 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/Other/resources.hpp @@ -0,0 +1,42 @@ +#ifndef RESOURCES_HPP +#define RESOURCES_HPP + +#include +// Mostly Chapter 2 +// Handles resource management + + + + +namespace Textures // This gives us a scope for the enumerators which allows us to write Textures::Airplane instead of just Airplane to avoid name collisions in the global scope +{ + enum ID + { + Eagle, + Raptor, + Desert + }; +} + +template +class ResourceHolder +{ + public: + void load(Identifier id, const std::string& filename); + Resource& get(Identifier id); + const Resource& get(Identifier id) const; + template + void load(Identifier id, const std::string& filename, const Parameter& secondParameter); + // Second parameter can be of sf::Shader::Type or std::string& + private: + std::map< Identifier, std::unique_ptr > mResourceMap; + // unique_ptr are class templates that act like pointers, this allows us to work with heavyweight objects without copying them all the time, or we can store classes that are non-cpyable like sf::Shader +}; + +typedef ResourceHolder TextureHolder; + + + +#include "resources.inl" + +#endif // RESOURCES_HPP diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/Other/resources.inl b/CPP/SFMLEngine/makingAGameTick/Classes/Other/resources.inl new file mode 100644 index 0000000..0bae324 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/Other/resources.inl @@ -0,0 +1,46 @@ +#ifndef RESOURCES_INL +#define RESOURCES_INL + +template +void ResourceHolder::load(Identifier id, const std::string& filename) +// Function to load a resource, it takes one parameter for filename and one for identifier +{ + std::unique_ptr resource(new Resource()); // Create sf:Texture and store it in the unique pointer + if(!resource -> loadFromFile(filename))// Load the resource from the filename + { + throw std::runtime_error(TEXTURE_LOAD_ERROR + filename); + } + auto inserted = mResourceMap.insert(std::make_pair(id, std::move(resource))); // Insert resource into map mResourceMap, std::move used to take ownership from resource variable and transfer it to std::make_pair(), std::move moves the resource into a new place and removes it from earlier place https://en.cppreference.com/w/cpp/utility/move + assert(inserted.second); +} + +template +Resource& ResourceHolder::get(Identifier id) // returns a reference to a resource +{ + auto found = mResourceMap.find(id); // find returns an iterator to the found element or end() if nothing was found + assert(found != mResourceMap.end()); + return *found -> second; // We have to access the second member of the pointer, then we deference it and get a resource +} + +template +const Resource& ResourceHolder::get(Identifier id) const // we need to be able to invoke get() also if we only have a pointer/reference to the const ResourceHolder, it returns const Resource so the resource cannot be changed by caller +{ + auto found = mResourceMap.find(id); // find returns an iterator to the found element or end() if nothing was found + assert(found != mResourceMap.end()); + return *found -> second; // We have to access the second member of the pointer, then we deference it and get a resource +} + +template +template +void ResourceHolder::load(Identifier id, const std::string& filename, const Parameter& secondParameter) // loads Shaders +{ + std::unique_ptr resource(new Resource()); // Create sf:Texture and store it in the unique pointer + if(!resource -> loadFromFile(filename, secondParameter))// Load the resource from the filename + { + throw std::runtime_error(TEXTURE_LOAD_ERROR + filename); + } + auto inserted = mResourceMap.insert(std::make_pair(id, std::move(resource))); // Insert resource into map mResourceMap, std::move used to take ownership from resource variable and transfer it to std::make_pair(), std::move moves the resource into a new place and removes it from earlier place https://en.cppreference.com/w/cpp/utility/move + assert(inserted.second); +} + +#endif // RESOURCES_INL diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/Other/world.cpp b/CPP/SFMLEngine/makingAGameTick/Classes/Other/world.cpp new file mode 100644 index 0000000..efe393c --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/Other/world.cpp @@ -0,0 +1,94 @@ +#ifndef WORLD_CPP // ZA WARUDO +#define WORLD_CPP + +#include // std::size_t +#include "../SceneNodeDerrivatives/SpriteNode.hpp" +#include "../SceneNodeDerrivatives/entity.hpp" + +World::World(sf::RenderWindow& window) +: mWindow(window) +, mWorldView(window.getDefaultView()) +, mWorldBounds +( + WORLD_LEFT_X_POSITION, + WORLD_TOP_Y_POSITION, + mWorldView.getSize().x, + WORLD_HEIGHT +) +, mSpawnPosition +( + mWorldView.getSize().x / 2.f, + mWorldBounds.height - mWorldView.getSize().y +) +, mScrollSpeed ( WORLD_SCROLL_SPEED ) +, mPlayerAircraft(nullptr) +{ + loadTextures(); + buildScene(); + mWorldView.setCenter(mSpawnPosition); +} + +void World::loadTextures() +{ + mTextures.load(Textures::Eagle, PATH_TO_EAGLE_TEXTURE); + mTextures.load(Textures::Raptor, PATH_TO_RAPTOR_TEXTURE); + mTextures.load(Textures::Desert, PATH_TO_DESERT_TEXTURE); +} + +void World::buildScene() +{ + for (std::size_t i = 0; i < LayerCount; i++) // initialization of scene layers, iterate through array of layer node pointers + { + SceneNode::ScenePointer layer(new SceneNode()); + mSceneLayers[i] = layer.get(); // initialize elments of this arry + + mSceneGraph.attachChild(std::move(layer)); // attach new node to the scene graph's root node + } + + sf::Texture& texture = mTextures.get(Textures::Desert); + sf::IntRect textureRect(mWorldBounds); + texture.setRepeated(true); // make desert texture repeat itself + + std::unique_ptr backgroundSprite(new SpriteNode(texture, textureRect)); // SpriteNode class that links to the desrt texture, our sprite will be as big as the whole world because we passed the texture rectangle + backgroundSprite -> setPosition(mWorldBounds.left, mWorldBounds.top); + mSceneLayers[Background] -> attachChild(std::move(backgroundSprite)); + + // Adding airplanes + std::unique_ptr leader(new Aircraft(Aircraft::Eagle, mTextures)); // we create the player's airplane + mPlayerAircraft = leader.get(); + mPlayerAircraft -> setPosition(mSpawnPosition); // Set player position + mPlayerAircraft -> SetVelocity(PLAYER_SIDEWARD_VELOCITY, mScrollSpeed); // forward velocity equals scroll speed, sideward velocity equals PLAYER_SIDEWARD_VELOCITY + mSceneLayers[Air] -> attachChild(std::move(leader)); // we attach the plane to the Air scene layer + + std::unique_ptr leftEscort(new Aircraft(Aircraft::Raptor, mTextures)); // create new airplane + leftEscort -> setPosition(LEFT_ESCORT_X_POSITION, LEFT_ESCORT_Y_POSITION); // Set new airplane position + mPlayerAircraft -> attachChild(std::move(leftEscort)); // leftEscort is now a child of player aircraft and it will folow it! + + std::unique_ptr rightEscort(new Aircraft(Aircraft::Raptor, mTextures)); // create new airplane + rightEscort -> setPosition(RIGHT_ESCORT_X_POSITION, RIGHT_ESCORT_Y_POSITION); // Set new airplane position + mPlayerAircraft -> attachChild(std::move(rightEscort)); // leftEscort is now a child of player aircraft and it will folow it! +} + +void World::draw() +{ + mWindow.setView(mWorldView); + mWindow.draw(mSceneGraph); +} + +void World::update(sf::Time deltaTime) // controls world scrolling and entity movement +{ + mWorldView.move(0.f, mScrollSpeed * deltaTime.asSeconds()); + + sf::Vector2f position = mPlayerAircraft -> getPosition(); + sf::Vector2f velocity = mPlayerAircraft -> getVelocity(); + + if(position.x <= mWorldBounds.left + WORLD_MAX_DISTANCE_FROM_BOUNDARY || position.x >= mWorldBounds.left + mWorldBounds.width - WORLD_MAX_DISTANCE_FROM_BOUNDARY) // if the player gets too close to world bounds make its velocity negative so it comes back + { + velocity.x = -velocity.x; + mPlayerAircraft -> SetVelocity(velocity); + } + + mSceneGraph.update(deltaTime); // mSceneGraph actaully applies these velocities +} + +#endif // WORLD_CPP diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/Other/world.hpp b/CPP/SFMLEngine/makingAGameTick/Classes/Other/world.hpp new file mode 100644 index 0000000..c0e2f55 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/Other/world.hpp @@ -0,0 +1,42 @@ +#ifndef WORLD_HPP // ZA WARUDO +#define WORLD_HPP + +#include +#include "../SceneNodeDerrivatives/SceneNode.hpp" +#include "../SceneNodeDerrivatives/aircraft.hpp" + +class World : private sf::NonCopyable // We only have one world and we do not want to copy it #StopClimateChange amiright +{ + public: + explicit World(sf::RenderWindow& window); + void update(sf::Time deltaTime); + void draw(); + private: + void loadTextures(); + void buildScene(); + + private: + enum Layer + { + Background, + Air, + LayerCount + }; + + private: + sf::RenderWindow& mWindow; // reference to the render window + sf::View mWorldView; // current world's view + TextureHolder mTextures; // All the textures needed inside the world + SceneNode mSceneGraph; + std::array mSceneLayers; // Pointers to access the scene graph's layerr nodes + + sf::FloatRect mWorldBounds; // Bounding rectangle of the world + sf::Vector2f mSpawnPosition; // Where player plane appears in the beginning + float mScrollSpeed; // Speed with which the world is scrolled + Aircraft* mPlayerAircraft; // Pointer to player aircraft +}; + +// std::array is a class template for fixed size static arrays, same functionality, performance as C arrays but allows copies, assignment, passing or returning objects from the function, additional safety and usefull methods like size(), begin() or end() + +#include "world.cpp" +#endif // WORLD_HPP diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SceneNode.cpp b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SceneNode.cpp new file mode 100644 index 0000000..dfd5508 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SceneNode.cpp @@ -0,0 +1,86 @@ +#ifndef SCENE_NODE_CPP +#define SCENE_NODE_CPP + + +void SceneNode::attachChild(ScenePointer child) // takes ownership of the scene node +{ + child -> mParent = this; + mChildren.push_back(std::move(child)); +} + +SceneNode::ScenePointer SceneNode::detachChild(const SceneNode& node) // finds node, releases it and returns it to caller +{ + auto found = std::find_if + ( + mChildren.begin(), mChildren.end(), + [&] (ScenePointer& p) -> bool { return p.get() == &node; } + ); + // This is lambda expression + // [&] (ScenePointer& p) -> bool { return p.get() == &node; } + // [&] - how many and in what way will the lambda expression have access to the variables in surrounding scope, [] - no variables [&] - all variables by reference [=] - all variables by value + // (ScenePointer& p) - parameters passed to the function + // -> bool - return type + // function body encolsed in {} + assert(found != mChildren.end()); // We check validity of the iterator of the found element + + ScenePointer result = std::move(*found); // we move the found node out of the container to result + result -> mParent = nullptr; // node's parent is set to null pointer + mChildren.erase(found); // we erase this element from the container + return result; // and we return the pointer to the node +} + +void SceneNode::drawCurrent(sf::RenderTarget& target, sf::RenderStates states) const +{ + +} + +void SceneNode::draw(sf::RenderTarget& target, sf::RenderStates states) const +{ + states.transform *= getTransform(); + // *= combines the parent's absolute transform with the relative one of the current node; + // states.transform contains the absolute world transform + drawCurrent(target, states); // now we can draw the derived object using states, this is similar to how sf::Sprite handles transforms + + for (const ScenePointer& child : mChildren) + { + child -> draw(target, states); // we also need to draw all the child nodes + } +} + +void SceneNode::updateCurrent(sf::Time deltaTime) +{ + +} + +void SceneNode::updateChildren(sf::Time deltaTime) +{ + for (const ScenePointer& child : mChildren) + { + child -> update(deltaTime); // we also need to draw all the child nodes + } +} + +void SceneNode::update(sf::Time deltaTime) +{ + updateCurrent(deltaTime); + updateChildren(deltaTime); +} + +sf::Transform SceneNode::getWorldTransform() const +{ + sf::Transform transform = sf::Transform::Identity; // sf::Transform::Identity represents the identity transform - it does not have any effecft on the object, it is not necessary in the code but it clarifies how transforms are applied + for (const SceneNode* node = this; node != nullptr; node = node -> mParent) + { + transform = node -> getTransform() * transform; + } + return transform; +} + +sf::Vector2f SceneNode::getWorldPosition() const +{ + return getWorldTransform() * sf::Vector2f(); +} + + + +#endif diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SceneNode.hpp b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SceneNode.hpp new file mode 100644 index 0000000..aed2ff9 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SceneNode.hpp @@ -0,0 +1,39 @@ +#ifndef SCENE_NODE_HPP +#define SCENE_NODE_HPP + +class SceneNode : public sf::Transformable, public sf::Drawable, private sf::NonCopyable +// we derrive from transformable - to be able to store and modify position, rotation and scale +// we derrive from drawable - to be able to draw it on screen +// we derrive from noncopyable - so that copy constructor and copy assignemnt operators are disabled +// This is used to create scene graph (tree data structure) in order to manage transform hierarchies +{ + public: + typedef std::unique_ptr ScenePointer; // element types must be complete types and we do not want to manage memory ourselves so we use std::unique_ptr + public: + //SceneNode(); + void attachChild(ScenePointer child); + ScenePointer detachChild(const SceneNode& node); + void update(sf::Time deltaTime); + private: + virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const; // we override draw() function of sf::Drawable + // Virtual functions are member functions whose behavior can be overridden in derived classes + // draw() function allows our class to be used like this: + /* + sf::RenderWindow window(...); // window class calls our draw() function + SceneNode::ScenePointer node(...); + window.draw(*node); + */ + virtual void drawCurrent(sf::RenderTarget& target, sf::RenderStates states) const; // draws only the current object, and not the children + virtual void updateCurrent(sf::Time deltaTime); // we reuse scene graph to reach all entities with world update, this one updates current node + void updateChildren(sf::Time deltaTime); // this one updates child nodes + sf::Transform getWorldTransform() const; // it takes into account all the parent transform + sf::Vector2f getWorldPosition() const; + private: + std::vector mChildren; + SceneNode* mParent; + +}; + +#include "SceneNode.cpp" + +#endif diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SpriteNode.cpp b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SpriteNode.cpp new file mode 100644 index 0000000..5fa3157 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SpriteNode.cpp @@ -0,0 +1,19 @@ +#ifndef SPRITE_NODE_CPP +#define SPRITE_NODE_CPP + +SpriteNode::SpriteNode(const sf::Texture& texture) +: mSprite(texture) +{ +} + +SpriteNode::SpriteNode(const sf::Texture& texture, const sf::IntRect& textureRect) +: mSprite(texture, textureRect) +{ +} + +void SpriteNode::drawCurrent(sf::RenderTarget& target, sf::RenderStates states) const +{ + target.draw(mSprite, states); +} + +#endif // SPRITE_NODE_CPP diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SpriteNode.hpp b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SpriteNode.hpp new file mode 100644 index 0000000..3922939 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/SpriteNode.hpp @@ -0,0 +1,20 @@ +#ifndef SPRITE_NODE_HPP +#define SPRITE_NODE_HPP + +class SpriteNode : public SceneNode +{ + public: + explicit SpriteNode(const sf::Texture& texture); + SpriteNode(const sf::Texture& texture, const sf::IntRect& rectangle); + + private: + virtual void drawCurrent(sf::RenderTarget& target, sf::RenderStates states) const; + + private: + sf::Sprite mSprite; +}; + + +#include "SpriteNode.cpp" + +#endif // SPRITE_NODE_HPP diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/aircraft.cpp b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/aircraft.cpp new file mode 100644 index 0000000..e75bb9d --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/aircraft.cpp @@ -0,0 +1,32 @@ +#ifndef AIRCRAFT_CPP +#define AIRCRAFT_CPP + +Textures::ID toTextureID(Aircraft::Type type) +{ + switch (type) + { + case Aircraft::Eagle: + return Textures::Eagle; + + case Aircraft::Raptor: + return Textures::Raptor; + + default: + return Textures::Eagle; + } + return Textures::Eagle; +} + + +Aircraft::Aircraft(Type type, const TextureHolder& textures) : mType(type), mSprite(textures.get(toTextureID(type))) +{ + sf::FloatRect bounds = mSprite.getLocalBounds(); // we get local bounding rectangle which means that we do not take transforms into account, as opposed to getGlobalBounds() + mSprite.setOrigin(bounds.width / 2.f, bounds.height / 2.f); // we want to set origin of the sprite to the middle of a rectangle around it +} + +void Aircraft::drawCurrent(sf::RenderTarget& target, sf::RenderStates states) const +{ + target.draw(mSprite, states); +} + +#endif diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/aircraft.hpp b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/aircraft.hpp new file mode 100644 index 0000000..1343d84 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/aircraft.hpp @@ -0,0 +1,25 @@ +#ifndef AIRCRAFT_HPP +#define AIRCRAFT_HPP + +#include "entity.hpp" + +class Aircraft : public Entity +{ + public: + enum Type + { + Eagle, + Raptor + }; + public: + explicit Aircraft(Type type, const TextureHolder& textures); + virtual void drawCurrent(sf::RenderTarget& target, sf::RenderStates states) const; + + private: + Type mType; + sf::Sprite mSprite; + +}; + +#include "aircraft.cpp" +#endif diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/entity.cpp b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/entity.cpp new file mode 100644 index 0000000..aa03a70 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/entity.cpp @@ -0,0 +1,25 @@ +#ifndef ENTITY_CPP +#define ENTITY_CPP + +void Entity::SetVelocity(sf::Vector2f velocity) +{ + mVelocity = velocity; +} + +void Entity::SetVelocity(float velocityX, float velocityY) +{ + mVelocity.x = velocityX; + mVelocity.y = velocityY; +} + +sf::Vector2f Entity::getVelocity() const +{ + return mVelocity; +} + +void Entity::updateCurrent(sf::Time deltaTime) +{ + move(mVelocity * deltaTime.asSeconds()); // shortcut for setPosition(getPosition() + offset) +} + +#endif diff --git a/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/entity.hpp b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/entity.hpp new file mode 100644 index 0000000..3816ef2 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/Classes/SceneNodeDerrivatives/entity.hpp @@ -0,0 +1,21 @@ +#ifndef ENTITY_HPP +#define ENTITY_HPP +#include "SceneNode.hpp" +#include "SceneNode.cpp" + +class Entity : public SceneNode +{ + public: + void SetVelocity(sf::Vector2f velocity); + void SetVelocity(float velocityX, float velocityY); + sf::Vector2f getVelocity() const; + + private: + sf::Vector2f mVelocity; // default ocnstructor initializes this vector to a zero vector + virtual void updateCurrent(sf::Time deltaTime); + +}; + +#include "entity.cpp" + +#endif diff --git a/CPP/SFMLEngine/makingAGameTick/Textures/Desert.jpg b/CPP/SFMLEngine/makingAGameTick/Textures/Desert.jpg new file mode 100644 index 0000000..3554b2d Binary files /dev/null and b/CPP/SFMLEngine/makingAGameTick/Textures/Desert.jpg differ diff --git a/CPP/SFMLEngine/makingAGameTick/Textures/Eagle.png b/CPP/SFMLEngine/makingAGameTick/Textures/Eagle.png new file mode 100644 index 0000000..f06466b Binary files /dev/null and b/CPP/SFMLEngine/makingAGameTick/Textures/Eagle.png differ diff --git a/CPP/SFMLEngine/makingAGameTick/Textures/Player.png b/CPP/SFMLEngine/makingAGameTick/Textures/Player.png new file mode 100644 index 0000000..f06466b Binary files /dev/null and b/CPP/SFMLEngine/makingAGameTick/Textures/Player.png differ diff --git a/CPP/SFMLEngine/makingAGameTick/Textures/Raptor.png b/CPP/SFMLEngine/makingAGameTick/Textures/Raptor.png new file mode 100644 index 0000000..8249b10 Binary files /dev/null and b/CPP/SFMLEngine/makingAGameTick/Textures/Raptor.png differ diff --git a/CPP/SFMLEngine/makingAGameTick/Textures/Raptor.xcf b/CPP/SFMLEngine/makingAGameTick/Textures/Raptor.xcf new file mode 100644 index 0000000..67ff582 Binary files /dev/null and b/CPP/SFMLEngine/makingAGameTick/Textures/Raptor.xcf differ diff --git a/CPP/SFMLEngine/makingAGameTick/Textures/shipsheetparts2-highercontrast.PNG b/CPP/SFMLEngine/makingAGameTick/Textures/shipsheetparts2-highercontrast.PNG new file mode 100644 index 0000000..b344a4b Binary files /dev/null and b/CPP/SFMLEngine/makingAGameTick/Textures/shipsheetparts2-highercontrast.PNG differ diff --git a/CPP/SFMLEngine/makingAGameTick/app b/CPP/SFMLEngine/makingAGameTick/app new file mode 100755 index 0000000..cebf48e Binary files /dev/null and b/CPP/SFMLEngine/makingAGameTick/app differ diff --git a/CPP/SFMLEngine/makingAGameTick/basic.cpp b/CPP/SFMLEngine/makingAGameTick/basic.cpp new file mode 100644 index 0000000..54d3c64 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/basic.cpp @@ -0,0 +1,10 @@ +#ifndef BASIC_CPP +#define BASIC_CPP +#include + +void print(const std::string s) +{ + std::cout << s << std::endl; +} + +#endif // BASIC_CPP diff --git a/CPP/SFMLEngine/makingAGameTick/constants b/CPP/SFMLEngine/makingAGameTick/constants new file mode 100644 index 0000000..c8be05a Binary files /dev/null and b/CPP/SFMLEngine/makingAGameTick/constants differ diff --git a/CPP/SFMLEngine/makingAGameTick/constants.hpp b/CPP/SFMLEngine/makingAGameTick/constants.hpp new file mode 100644 index 0000000..347ca85 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/constants.hpp @@ -0,0 +1,47 @@ +#ifndef CONSTANTS_HPP +#define CONSTANTS_HPP + +#include + +// Paths +const std::string PATH_TO_PLAYER_TEXTURE = "Textures/Player.png"; +const std::string PATH_TO_EAGLE_TEXTURE = "Textures/Eagle.png"; +const std::string PATH_TO_RAPTOR_TEXTURE = "Textures/Raptor.png"; +const std::string PATH_TO_DESERT_TEXTURE = "Textures/Desert.jpg"; + +// Player constants +const float PLAYER_RADIUS = 40; +const float PLAYER_X_POSITION = 100; +const float PLAYER_Y_POSITION = 100; +const sf::Color PLAYER_COLOR = sf::Color::Cyan; +const float PLAYER_SIDEWARD_VELOCITY = 40; + +// Other sprites constants +const float LEFT_ESCORT_X_POSITION = -80; +const float LEFT_ESCORT_Y_POSITION = 50; +const float RIGHT_ESCORT_X_POSITION = -LEFT_ESCORT_X_POSITION; +const float RIGHT_ESCORT_Y_POSITION = LEFT_ESCORT_Y_POSITION; + +// Movement constants +// const sf::Vector2f INITIAL_MOVEMENT (0.f, 0.f); + +const float MOVING_UP_SPEED = -100; +const float MOVING_DOWN_SPEED = -MOVING_UP_SPEED; +const float MOVING_RIGHT_SPEED = 100; +const float MOVING_LEFT_SPEED = -MOVING_RIGHT_SPEED; + +// Time constants +const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 60.f); // 1 frame is 1 / 60 of the second so we get 60 frames in a second + +// Error strings +const std::string TEXTURE_LOAD_ERROR = "TextureHolder::load - Failed to load "; + +// World constants +const float WORLD_LEFT_X_POSITION = 0; +const float WORLD_TOP_Y_POSITION = 0; +// const float WORLD_WIDTH = 0; by default mWorldView.getSize().x +const float WORLD_HEIGHT = 2000; +const float WORLD_SCROLL_SPEED = -1; +const float WORLD_MAX_DISTANCE_FROM_BOUNDARY = 150; + +#endif // CONSTANTS_HPP diff --git a/CPP/SFMLEngine/makingAGameTick/game.cpp b/CPP/SFMLEngine/makingAGameTick/game.cpp new file mode 100644 index 0000000..fa824f5 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/game.cpp @@ -0,0 +1,161 @@ +#ifndef GAME_CPP +#define GAME_CPP + +#include +#include +#include "constants.hpp" +#include "./Classes/Other/resources.hpp" +#include "./Classes/Other/world.hpp" +#include "./Classes/SceneNodeDerrivatives/SceneNode.hpp" +#include "./Classes/SceneNodeDerrivatives/SpriteNode.hpp" +#include "./Classes/SceneNodeDerrivatives/entity.hpp" +#include "./Classes/SceneNodeDerrivatives/aircraft.hpp" +#include "basic.cpp" + + + + + +class Game : private sf::NonCopyable +{ + public: + Game(); // Sets up player radius, position and fill color + void run(); // runs the processEvents, update and render methods + + private: + void processEvents(); // playerInput, mainLoop + void update(sf::Time deltaTime); // code that updates the game + void render(); // code that renders the game + void handlePlayerInput(sf::Keyboard::Key key, bool isPressed); + bool mIsMovingUp = false; + bool mIsMovingRight = false; + bool mIsMovingLeft = false; + bool mIsMovingDown = false; + private: + sf::RenderWindow mWindow; + TextureHolder mTexture; + sf::Sprite mPlayer; + World mWorld; +}; + +Game::Game() +: mWindow(sf::VideoMode(640, 480), "World", sf::Style::Close) +, mWorld(mWindow) +/* , mFont() +, mStatisticsText() +, mStatisticsUpdateTime() +, mStatisticsNumFrames(0) +*/ +{ + /* mFont.loadFromFile("Media/Sansation.ttf"); + mStatisticsText.setFont(mFont); + mStatisticsText.setPosition(5.f, 5.f); + mStatisticsText.setCharacterSize(10); + */ +} + + +// Resposible for managing game loop - fetching input form the window system, updating the world, and ordering the rendering of the game +void Game::run() +{ + /* Other useful frame rate related tecnhiques: + sf::sleep - interrupts the execution for a given time, not very accurate + sf::RenderWindow::setFramerateLimit() - tries to achieve the frame rate by calling sf::sleep, nice for testing purposes + sf::RenderWindow::setVerticalSyncEnabled() - enables V-sync which adapts the rate of graphical updates from sf::RenderWindow::display() to the refresh rate of the monitor + */ + sf::Clock clock; + sf::Time timeSinceLastUpdateFunction = sf::Time::Zero; + while (mWindow.isOpen()) // this loop calls the render method + { + processEvents(); + timeSinceLastUpdateFunction += clock.restart(); + while(timeSinceLastUpdateFunction > TIME_PER_FRAME) // fixed time stamps + // this loop collects user input and computes game logic + { + timeSinceLastUpdateFunction -= TIME_PER_FRAME; + processEvents(); + update(TIME_PER_FRAME); + } + + render(); + } +} + +/* +const std::vector < pair > PLAYER_MOVEMENT = +{ + {mIsMovingUp, sf::Keyboard::W}, + {mIsMovingDown, sf::Keyboard::S}, + {mIsMovingLeft, sf::Keyboard::A}, + {mIsMovingRight, sf::Keyboard::D} +} +*/ + +void Game::handlePlayerInput(sf::Keyboard::Key key, bool isPressed) +{ + if (key == sf::Keyboard::W) mIsMovingUp = isPressed; + else if (key == sf::Keyboard::S) mIsMovingDown = isPressed; + else if (key == sf::Keyboard::A) mIsMovingLeft = isPressed; + else if (key == sf::Keyboard::D) mIsMovingRight = isPressed; +} + +void Game::processEvents() +{ + sf::Event event; + while (mWindow.pollEvent(event)) // mainLoop/gameLoop + { + // each time while loop iterates it means that we got a new event registered by the window. + switch (event.type) + { + case sf::Event::KeyPressed: + handlePlayerInput(event.key.code, true); + break; + case sf::Event::KeyReleased: + handlePlayerInput(event.key.code, false); + break; + case sf::Event::Closed: + mWindow.close(); + break; + default: + break; + } + } +} + +void Game::update(sf::Time deltaTime) +{ + + sf::Vector2f movement (0.f, 0.f); // movement from the origin of the current coordinate system, in this case origin is the shape's positon + movement.y += mIsMovingUp * MOVING_UP_SPEED + mIsMovingDown * MOVING_DOWN_SPEED; + movement.x += mIsMovingLeft * MOVING_LEFT_SPEED + mIsMovingRight * MOVING_RIGHT_SPEED; + mPlayer.move(movement * deltaTime.asSeconds()); + // from physics formula distance = speed * time + // this allows us to move exactly the distance we want it to move in one second, no matter what computer are we on + // delta time / time step - time that has elapsed since the last frame + // mWorldView.move(0.f, mScrollSpeed * deltaTime.asSeconds()); we scroll up the map, we update both the map and the player so he does not get left behind, we multiple by time to ensure that we have the same speed of n pixels per second no matter the simulation frame rate +} + +void Game::render() +{ + mWindow.clear(); + mWorld.draw(); + + mWindow.setView(mWindow.getDefaultView()); + // mWindow.draw(mStatisticsText); + mWindow.display(); +} + +int main() +{ + try + { + Game game; + game.run(); + } + catch (std::exception& e) + { + std::cout << "\nEXCEPTION: " << e.what() << std::endl; + } +} + +#endif // GAME_CPP diff --git a/CPP/SFMLEngine/makingAGameTick/game.o b/CPP/SFMLEngine/makingAGameTick/game.o new file mode 100644 index 0000000..fbc9db9 Binary files /dev/null and b/CPP/SFMLEngine/makingAGameTick/game.o differ diff --git a/CPP/SFMLEngine/makingAGameTick/makefile b/CPP/SFMLEngine/makingAGameTick/makefile new file mode 100644 index 0000000..e3a10a6 --- /dev/null +++ b/CPP/SFMLEngine/makingAGameTick/makefile @@ -0,0 +1,9 @@ +CXXFLAGS = -Wextra -Wall -Wfloat-equal -Wundef -Wshadow -Wpointer-arith -Wcast-align -Wstrict-overflow=5 -Wwrite-strings -Wcast-qual -Wunreachable-code -pedantic -Wswitch-default -Wno-unused-parameter +# https://stackoverflow.com/a/3376483 + +compile:./game.cpp + g++ $(CXXFLAGS) -c ./game.cpp + g++ game.o -o app -lsfml-graphics -lsfml-window -lsfml-system + +run: + ./app diff --git a/CPP/SFMLEngine/minimalExample/app b/CPP/SFMLEngine/minimalExample/app new file mode 100755 index 0000000..5c0970c Binary files /dev/null and b/CPP/SFMLEngine/minimalExample/app differ diff --git a/CPP/SFMLEngine/minimalExample/example.cpp b/CPP/SFMLEngine/minimalExample/example.cpp new file mode 100644 index 0000000..86420c8 --- /dev/null +++ b/CPP/SFMLEngine/minimalExample/example.cpp @@ -0,0 +1,34 @@ +// SFML is split into 5 modules: +// #include +// #include +// #include +// #include +// #include +// We can include them like this or we can include just a specific header file: +// #include +// Each module is compiled to separate library, it can be built for release or debug, linked statically or dynamically + +#include + +int main() +{ + sf::RenderWindow window(sf::VideoMode(640, 480), "SFML Application"); + sf::CircleShape shape; + const float CIRCLE_RADIUS = 40; + shape.setRadius(CIRCLE_RADIUS); + const float CIRCLE_POSITION_X = 100; + const float CIRCLE_POSITION_Y = 100; + shape.setPosition(CIRCLE_POSITION_X, CIRCLE_POSITION_Y); + shape.setFillColor(sf::Color::Cyan); + while(window.isOpen()) + { + sf::Event event; + while(window.pollEvent(event)) + { + if(event.type == sf::Event::Closed) window.close(); + } + window.clear(); + window.draw(shape); + window.display(); + } +} diff --git a/CPP/SFMLEngine/minimalExample/example.o b/CPP/SFMLEngine/minimalExample/example.o new file mode 100644 index 0000000..93f26bf Binary files /dev/null and b/CPP/SFMLEngine/minimalExample/example.o differ diff --git a/CPP/SFMLEngine/minimalExample/makefile b/CPP/SFMLEngine/minimalExample/makefile new file mode 100644 index 0000000..9e16676 --- /dev/null +++ b/CPP/SFMLEngine/minimalExample/makefile @@ -0,0 +1,6 @@ +compile:./example.cpp + g++ -c ./example.cpp + g++ example.o -o app -lsfml-graphics -lsfml-window -lsfml-system + +run: + ./app diff --git a/CPP/SFMLEngine/readme.md b/CPP/SFMLEngine/readme.md new file mode 100644 index 0000000..17056c1 --- /dev/null +++ b/CPP/SFMLEngine/readme.md @@ -0,0 +1,3 @@ +# Textures and Audio used: +## Space Game Starter Set by [hc](https://opengameart.org/users/hc) - https://opengameart.org/content/space-game-starter-set +## 100 seamless textures by [Mitch Featherston](http://pdtextures.blogspot.com/) (Submitted by [Clint Bellanger](https://opengameart.org/users/clint-bellanger) - https://opengameart.org/content/100-seamless-textures