init commit
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
.idea/
|
||||
bin/
|
||||
cmake-build-debug/
|
||||
include/
|
||||
lib/
|
||||
35
Asteroid.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// Created by benmo on 9/28/2020.
|
||||
//
|
||||
|
||||
#ifndef SFML_TEMPLATE_ASTEROID_H
|
||||
#define SFML_TEMPLATE_ASTEROID_H
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
class Asteroid : public Entity {
|
||||
public:
|
||||
Asteroid(int health, int points, const sf::Texture &texture, float scale, float xPos, float yPos, float velocity, float direction) : Entity(health, points, texture, scale, xPos, yPos, velocity, direction) {
|
||||
size = health;
|
||||
type = "asteroid";
|
||||
}
|
||||
|
||||
int getSize() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
void hit(vector<MySprite*> &animations, Sound &sound, Texture &explosion, default_random_engine &gen) {
|
||||
uniform_int_distribution<int> angle(0, 359);
|
||||
animations.push_back(new MySprite(explosion, getSize()*65, getXPos(), getYPos(), 0, angle(gen)));
|
||||
animations[animations.size() - 1]->makeAnimated(5, 5, 0.01,23);
|
||||
|
||||
sound.setVolume(100.0/((4-size)/1.5));
|
||||
sound.play();
|
||||
}
|
||||
|
||||
private:
|
||||
int size;
|
||||
};
|
||||
|
||||
|
||||
#endif //SFML_TEMPLATE_ASTEROID_H
|
||||
58
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
cmake_minimum_required(VERSION 3.12)
|
||||
project(SFML_Template)
|
||||
|
||||
include_directories(include)
|
||||
link_directories(lib)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin)
|
||||
|
||||
add_executable(SFML_Template main.cpp Game.h Menu.h MySprite.h Ship.h Entity.h Asteroid.h Collision.cpp Collision.h)
|
||||
target_link_libraries(SFML_Template sfml-audio sfml-graphics sfml-system sfml-window sfml-network sfml-main)
|
||||
|
||||
# Copy single files
|
||||
macro(resource_files files)
|
||||
foreach(file ${files})
|
||||
message(STATUS " Copying resource ${file} to ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
||||
file(COPY ${file} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Copy full directories
|
||||
macro(resource_dirs dirs)
|
||||
foreach(dir ${dirs})
|
||||
# Replace / at the end of the path (copy dir content VS copy dir)
|
||||
string(REGEX REPLACE "/+$" "" dirclean "${dir}")
|
||||
file(GLOB files "${dirclean}/*.dll")
|
||||
message(STATUS "Copying directory ${dirclean}")
|
||||
foreach(file ${files})
|
||||
resource_files(${file})
|
||||
endforeach()
|
||||
message(STATUS "Done copying directory ${dirclean}")
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Copy single files
|
||||
macro(data_files files)
|
||||
foreach(file ${files})
|
||||
message(STATUS " Copying resource ${file} to ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/data")
|
||||
file(COPY ${file} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/data)
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Copy full directories
|
||||
macro(data_dirs dirs)
|
||||
foreach(dir ${dirs})
|
||||
# Replace / at the end of the path (copy dir content VS copy dir)
|
||||
string(REGEX REPLACE "/+$" "" dirclean "${dir}")
|
||||
file(GLOB files "${dirclean}/*")
|
||||
message(STATUS "Copying directory ${dirclean}")
|
||||
foreach(file ${files})
|
||||
data_files(${file})
|
||||
endforeach()
|
||||
message(STATUS "Done copying directory ${dirclean}")
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
resource_dirs(bin/)
|
||||
data_dirs(data/)
|
||||
190
Collision.cpp
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* File: collision.cpp
|
||||
* Author: Nick (original version), ahnonay (SFML2 compatibility)
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include "Collision.h"
|
||||
|
||||
namespace Collision
|
||||
{
|
||||
class BitmaskManager
|
||||
{
|
||||
public:
|
||||
~BitmaskManager() {
|
||||
std::map<const sf::Texture*, sf::Uint8*>::const_iterator end = Bitmasks.end();
|
||||
for (std::map<const sf::Texture*, sf::Uint8*>::const_iterator iter = Bitmasks.begin(); iter!=end; iter++)
|
||||
delete [] iter->second;
|
||||
}
|
||||
|
||||
sf::Uint8 GetPixel (const sf::Uint8* mask, const sf::Texture* tex, unsigned int x, unsigned int y) {
|
||||
if (x>tex->getSize().x||y>tex->getSize().y)
|
||||
return 0;
|
||||
|
||||
return mask[x+y*tex->getSize().x];
|
||||
}
|
||||
|
||||
sf::Uint8* GetMask (const sf::Texture* tex) {
|
||||
sf::Uint8* mask;
|
||||
std::map<const sf::Texture*, sf::Uint8*>::iterator pair = Bitmasks.find(tex);
|
||||
if (pair==Bitmasks.end())
|
||||
{
|
||||
sf::Image img = tex->copyToImage();
|
||||
mask = CreateMask (tex, img);
|
||||
}
|
||||
else
|
||||
mask = pair->second;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
sf::Uint8* CreateMask (const sf::Texture* tex, const sf::Image& img) {
|
||||
sf::Uint8* mask = new sf::Uint8[tex->getSize().y*tex->getSize().x];
|
||||
|
||||
for (unsigned int y = 0; y<tex->getSize().y; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x<tex->getSize().x; x++)
|
||||
mask[x+y*tex->getSize().x] = img.getPixel(x,y).a;
|
||||
}
|
||||
|
||||
Bitmasks.insert(std::pair<const sf::Texture*, sf::Uint8*>(tex,mask));
|
||||
|
||||
return mask;
|
||||
}
|
||||
private:
|
||||
std::map<const sf::Texture*, sf::Uint8*> Bitmasks;
|
||||
};
|
||||
|
||||
BitmaskManager Bitmasks;
|
||||
|
||||
bool PixelPerfectTest(const sf::Sprite& Object1, const sf::Sprite& Object2, sf::Uint8 AlphaLimit) {
|
||||
sf::FloatRect Intersection;
|
||||
if (Object1.getGlobalBounds().intersects(Object2.getGlobalBounds(), Intersection)) {
|
||||
sf::IntRect O1SubRect = Object1.getTextureRect();
|
||||
sf::IntRect O2SubRect = Object2.getTextureRect();
|
||||
|
||||
sf::Uint8* mask1 = Bitmasks.GetMask(Object1.getTexture());
|
||||
sf::Uint8* mask2 = Bitmasks.GetMask(Object2.getTexture());
|
||||
|
||||
// Loop through our pixels
|
||||
for (int i = Intersection.left; i < Intersection.left+Intersection.width; i++) {
|
||||
for (int j = Intersection.top; j < Intersection.top+Intersection.height; j++) {
|
||||
|
||||
sf::Vector2f o1v = Object1.getInverseTransform().transformPoint(i, j);
|
||||
sf::Vector2f o2v = Object2.getInverseTransform().transformPoint(i, j);
|
||||
|
||||
// Make sure pixels fall within the sprite's subrect
|
||||
if (o1v.x > 0 && o1v.y > 0 && o2v.x > 0 && o2v.y > 0 &&
|
||||
o1v.x < O1SubRect.width && o1v.y < O1SubRect.height &&
|
||||
o2v.x < O2SubRect.width && o2v.y < O2SubRect.height) {
|
||||
|
||||
if (Bitmasks.GetPixel(mask1, Object1.getTexture(), (int)(o1v.x)+O1SubRect.left, (int)(o1v.y)+O1SubRect.top) > AlphaLimit &&
|
||||
Bitmasks.GetPixel(mask2, Object2.getTexture(), (int)(o2v.x)+O2SubRect.left, (int)(o2v.y)+O2SubRect.top) > AlphaLimit)
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CreateTextureAndBitmask(sf::Texture &LoadInto, const std::string& Filename)
|
||||
{
|
||||
sf::Image img;
|
||||
if (!img.loadFromFile(Filename))
|
||||
return false;
|
||||
if (!LoadInto.loadFromImage(img))
|
||||
return false;
|
||||
|
||||
Bitmasks.CreateMask(&LoadInto, img);
|
||||
return true;
|
||||
}
|
||||
|
||||
sf::Vector2f GetSpriteCenter (const sf::Sprite& Object)
|
||||
{
|
||||
sf::FloatRect AABB = Object.getGlobalBounds();
|
||||
return sf::Vector2f (AABB.left+AABB.width/2.f, AABB.top+AABB.height/2.f);
|
||||
}
|
||||
|
||||
sf::Vector2f GetSpriteSize (const sf::Sprite& Object)
|
||||
{
|
||||
sf::IntRect OriginalSize = Object.getTextureRect();
|
||||
sf::Vector2f Scale = Object.getScale();
|
||||
return sf::Vector2f (OriginalSize.width*Scale.x, OriginalSize.height*Scale.y);
|
||||
}
|
||||
|
||||
bool CircleTest(const sf::Sprite& Object1, const sf::Sprite& Object2) {
|
||||
sf::Vector2f Obj1Size = GetSpriteSize(Object1);
|
||||
sf::Vector2f Obj2Size = GetSpriteSize(Object2);
|
||||
float Radius1 = (Obj1Size.x + Obj1Size.y) / 4;
|
||||
float Radius2 = (Obj2Size.x + Obj2Size.y) / 4;
|
||||
|
||||
sf::Vector2f Distance = GetSpriteCenter(Object1)-GetSpriteCenter(Object2);
|
||||
|
||||
return (Distance.x * Distance.x + Distance.y * Distance.y <= (Radius1 + Radius2) * (Radius1 + Radius2));
|
||||
}
|
||||
|
||||
class OrientedBoundingBox // Used in the BoundingBoxTest
|
||||
{
|
||||
public:
|
||||
OrientedBoundingBox (const sf::Sprite& Object) // Calculate the four points of the OBB from a transformed (scaled, rotated...) sprite
|
||||
{
|
||||
sf::Transform trans = Object.getTransform();
|
||||
sf::IntRect local = Object.getTextureRect();
|
||||
Points[0] = trans.transformPoint(0.f, 0.f);
|
||||
Points[1] = trans.transformPoint(local.width, 0.f);
|
||||
Points[2] = trans.transformPoint(local.width, local.height);
|
||||
Points[3] = trans.transformPoint(0.f, local.height);
|
||||
}
|
||||
|
||||
sf::Vector2f Points[4];
|
||||
|
||||
void ProjectOntoAxis (const sf::Vector2f& Axis, float& Min, float& Max) // Project all four points of the OBB onto the given axis and return the dotproducts of the two outermost points
|
||||
{
|
||||
Min = (Points[0].x*Axis.x+Points[0].y*Axis.y);
|
||||
Max = Min;
|
||||
for (int j = 1; j<4; j++)
|
||||
{
|
||||
float Projection = (Points[j].x*Axis.x+Points[j].y*Axis.y);
|
||||
|
||||
if (Projection<Min)
|
||||
Min=Projection;
|
||||
if (Projection>Max)
|
||||
Max=Projection;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool BoundingBoxTest(const sf::Sprite& Object1, const sf::Sprite& Object2) {
|
||||
OrientedBoundingBox OBB1 (Object1);
|
||||
OrientedBoundingBox OBB2 (Object2);
|
||||
|
||||
// Create the four distinct axes that are perpendicular to the edges of the two rectangles
|
||||
sf::Vector2f Axes[4] = {
|
||||
sf::Vector2f (OBB1.Points[1].x-OBB1.Points[0].x,
|
||||
OBB1.Points[1].y-OBB1.Points[0].y),
|
||||
sf::Vector2f (OBB1.Points[1].x-OBB1.Points[2].x,
|
||||
OBB1.Points[1].y-OBB1.Points[2].y),
|
||||
sf::Vector2f (OBB2.Points[0].x-OBB2.Points[3].x,
|
||||
OBB2.Points[0].y-OBB2.Points[3].y),
|
||||
sf::Vector2f (OBB2.Points[0].x-OBB2.Points[1].x,
|
||||
OBB2.Points[0].y-OBB2.Points[1].y)
|
||||
};
|
||||
|
||||
for (int i = 0; i<4; i++) // For each axis...
|
||||
{
|
||||
float MinOBB1, MaxOBB1, MinOBB2, MaxOBB2;
|
||||
|
||||
// ... project the points of both OBBs onto the axis ...
|
||||
OBB1.ProjectOntoAxis(Axes[i], MinOBB1, MaxOBB1);
|
||||
OBB2.ProjectOntoAxis(Axes[i], MinOBB2, MaxOBB2);
|
||||
|
||||
// ... and check whether the outermost projected points of both OBBs overlap.
|
||||
// If this is not the case, the Separating Axis Theorem states that there can be no collision between the rectangles
|
||||
if (!((MinOBB2<=MaxOBB1)&&(MaxOBB2>=MinOBB1)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
77
Collision.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* File: collision.h
|
||||
* Authors: Nick Koirala (original version), ahnonay (SFML2 compatibility)
|
||||
*
|
||||
* Collision Detection and handling class
|
||||
* For SFML2.
|
||||
|
||||
Notice from the original version:
|
||||
|
||||
(c) 2009 - LittleMonkey Ltd
|
||||
|
||||
This software is provided 'as-is', without any express or
|
||||
implied warranty. In no event will the authors be held
|
||||
liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute
|
||||
it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented;
|
||||
you must not claim that you wrote the original software.
|
||||
If you use this software in a product, an acknowledgment
|
||||
in the product documentation would be appreciated but
|
||||
is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such,
|
||||
and must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any
|
||||
source distribution.
|
||||
|
||||
*
|
||||
* Created on 30 January 2009, 11:02
|
||||
*/
|
||||
|
||||
#ifndef SFML_TEMPLATE_COLLISION_H
|
||||
#define SFML_TEMPLATE_COLLISION_H
|
||||
|
||||
#include <SFML\Graphics.hpp>
|
||||
|
||||
namespace Collision {
|
||||
//////
|
||||
/// Test for a collision between two sprites by comparing the alpha values of overlapping pixels
|
||||
/// Supports scaling and rotation
|
||||
/// AlphaLimit: The threshold at which a pixel becomes "solid". If AlphaLimit is 127, a pixel with
|
||||
/// alpha value 128 will cause a collision and a pixel with alpha value 126 will not.
|
||||
///
|
||||
/// This functions creates bitmasks of the textures of the two sprites by
|
||||
/// downloading the textures from the graphics card to memory -> SLOW!
|
||||
/// You can avoid this by using the "CreateTextureAndBitmask" function
|
||||
//////
|
||||
bool PixelPerfectTest(const sf::Sprite& Object1 ,const sf::Sprite& Object2, sf::Uint8 AlphaLimit = 0);
|
||||
|
||||
//////
|
||||
/// Replaces Texture::loadFromFile
|
||||
/// Load an imagefile into the given texture and create a bitmask for it
|
||||
/// This is much faster than creating the bitmask for a texture on the first run of "PixelPerfectTest"
|
||||
///
|
||||
/// The function returns false if the file could not be opened for some reason
|
||||
//////
|
||||
bool CreateTextureAndBitmask(sf::Texture &LoadInto, const std::string& Filename);
|
||||
|
||||
//////
|
||||
/// Test for collision using circle collision dection
|
||||
/// Radius is averaged from the dimensions of the sprite so
|
||||
/// roughly circular objects will be much more accurate
|
||||
//////
|
||||
bool CircleTest(const sf::Sprite& Object1, const sf::Sprite& Object2);
|
||||
|
||||
//////
|
||||
/// Test for bounding box collision using the Separating Axis Theorem
|
||||
/// Supports scaling and rotation
|
||||
//////
|
||||
bool BoundingBoxTest(const sf::Sprite& Object1, const sf::Sprite& Object2);
|
||||
}
|
||||
|
||||
#endif //SFML_TEMPLATE_COLLISION_H
|
||||
39
Entity.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Created by benmo on 9/28/2020.
|
||||
//
|
||||
|
||||
#ifndef SFML_TEMPLATE_ENTITY_H
|
||||
#define SFML_TEMPLATE_ENTITY_H
|
||||
|
||||
class Entity : public MySprite {
|
||||
public:
|
||||
Entity(int health, int points, const sf::Texture &texture, float scale, float xPos, float yPos, float velocity, float direction) : MySprite(texture, scale, xPos, yPos, velocity, direction) {
|
||||
this->health = health;
|
||||
this->points = points;
|
||||
}
|
||||
|
||||
int getHealth() const {
|
||||
return health;
|
||||
}
|
||||
|
||||
void setHealth(int health) {
|
||||
this->health = health;
|
||||
}
|
||||
|
||||
void hit() {};
|
||||
|
||||
string getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
int getPoints() const {
|
||||
return points;
|
||||
}
|
||||
protected:
|
||||
int health, points;
|
||||
|
||||
string type = "entity";
|
||||
};
|
||||
|
||||
|
||||
#endif //SFML_TEMPLATE_ENTITY_H
|
||||
385
Game.h
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
class Game {
|
||||
public:
|
||||
int result;
|
||||
|
||||
Game() {
|
||||
result = init();
|
||||
}
|
||||
private:
|
||||
bool ended = false;
|
||||
|
||||
int init() {
|
||||
// display "Hello, World!" -- this still appears in our Run terminal as before
|
||||
cout << "Hello, World!" << endl;
|
||||
|
||||
default_random_engine gen(random_device{}());
|
||||
Clock fireClock, spawnClock, shieldTimer;
|
||||
|
||||
// create a RenderWindow object
|
||||
// specify the size to be 640x640
|
||||
// set the title to be "SFML Example Window"
|
||||
RenderWindow window(VideoMode(1240, 640), "Asteroids");
|
||||
window.setFramerateLimit(30);
|
||||
window.setPosition(sf::Vector2i(window.getPosition().x, window.getPosition().y - 50));
|
||||
|
||||
//********************************************
|
||||
// GRAPHICS
|
||||
//********************************************
|
||||
Texture ship;
|
||||
ship.loadFromFile("data\\Ship.png");
|
||||
|
||||
Texture shield;
|
||||
shield.loadFromFile("data\\bubble.png");
|
||||
|
||||
Texture background;
|
||||
background.loadFromFile("data\\back.png");
|
||||
|
||||
Texture blueLaser;
|
||||
Collision::CreateTextureAndBitmask(blueLaser, "data\\blue.png");
|
||||
|
||||
Texture explosion;
|
||||
explosion.loadFromFile("data\\explodeSheet.png");
|
||||
|
||||
vector < Texture * > largeAsteroids;
|
||||
for (int i = 1; i <= 7; i++) {
|
||||
largeAsteroids.push_back(new Texture);
|
||||
Collision::CreateTextureAndBitmask(*largeAsteroids[largeAsteroids.size() - 1],
|
||||
"data\\Asteroids\\(" + to_string(i) + ").png");
|
||||
}
|
||||
|
||||
vector < Texture * > mediumAsteroids;
|
||||
for (int i = 8; i <= 17; i++) {
|
||||
mediumAsteroids.push_back(new Texture);
|
||||
Collision::CreateTextureAndBitmask(*mediumAsteroids[mediumAsteroids.size() - 1],
|
||||
"data\\Asteroids\\(" + to_string(i) + ").png");
|
||||
}
|
||||
|
||||
vector < Texture * > smallAsteroids;
|
||||
for (int i = 18; i <= 23; i++) {
|
||||
smallAsteroids.push_back(new Texture);
|
||||
Collision::CreateTextureAndBitmask(*smallAsteroids[smallAsteroids.size() - 1],
|
||||
"data\\Asteroids\\(" + to_string(i) + ").png");
|
||||
}
|
||||
|
||||
//********************************************
|
||||
// SOUNDS
|
||||
//********************************************
|
||||
|
||||
Sound pew;
|
||||
SoundBuffer pewBuff;
|
||||
pewBuff.loadFromFile("data\\Sounds\\pew.wav");
|
||||
pew.setBuffer(pewBuff);
|
||||
pew.setVolume(25);
|
||||
|
||||
Sound enemyBoom;
|
||||
SoundBuffer enemyBoomBuff;
|
||||
enemyBoomBuff.loadFromFile("data\\Sounds\\explosions.wav");
|
||||
enemyBoom.setBuffer(enemyBoomBuff);
|
||||
|
||||
Sound newLife;
|
||||
SoundBuffer newLifeBuff;
|
||||
newLifeBuff.loadFromFile("data\\Sounds\\pling.wav");
|
||||
newLife.setBuffer(newLifeBuff);
|
||||
|
||||
//********************************************
|
||||
// Text
|
||||
//********************************************
|
||||
|
||||
Text score;
|
||||
Font f;
|
||||
score.setFillColor(Color::White);
|
||||
score.setPosition(10, 10);
|
||||
f.loadFromFile("data\\Fonts\\arial.ttf");
|
||||
score.setFont(f);
|
||||
score.setString("Score: 0");
|
||||
score.setCharacterSize(20);
|
||||
|
||||
Text destroyed;
|
||||
Font sk;
|
||||
destroyed.setFillColor(Color::White);
|
||||
sk.loadFromFile("data\\Fonts\\Sk.ttf");
|
||||
destroyed.setFont(sk);
|
||||
destroyed.setCharacterSize(70);
|
||||
destroyed.setString("Destroyed");
|
||||
destroyed.setOrigin(destroyed.getGlobalBounds().width/2.0, destroyed.getGlobalBounds().height/2.0);
|
||||
destroyed.setPosition(window.getSize().x/2.0, window.getSize().y/3.0);
|
||||
|
||||
Text pressEnter;
|
||||
Font monkirta;
|
||||
pressEnter.setFillColor(Color::White);
|
||||
monkirta.loadFromFile("data\\Fonts\\Monkirta Pursuit NC.ttf");
|
||||
pressEnter.setFont(monkirta);
|
||||
pressEnter.setCharacterSize(20);
|
||||
pressEnter.setString("Press ENTER to return to the menu...");
|
||||
pressEnter.setOrigin(pressEnter.getGlobalBounds().width/2.0, pressEnter.getGlobalBounds().height/2.0);
|
||||
pressEnter.setPosition(window.getSize().x/2.0, window.getSize().y/2.25);
|
||||
|
||||
//********************************************
|
||||
// Resource loading above here
|
||||
//********************************************
|
||||
|
||||
vector < MySprite * > projectiles;
|
||||
vector < MySprite * > animations;
|
||||
vector < Entity * > enemies;
|
||||
vector < Drawable * > gui;
|
||||
vector < Drawable * > lost;
|
||||
|
||||
lost.push_back(&destroyed);
|
||||
lost.push_back(&pressEnter);
|
||||
|
||||
gui.push_back(new MySprite(background, 100, window.getSize().x / 2, window.getSize().y / 2, 0, 0));
|
||||
Ship player(ship, 30, window.getSize().x / 2, window.getSize().y / 2, 0, 0);
|
||||
player.setMaxVelocity(15);
|
||||
player.setMinVelocity(-7);
|
||||
player.setEdgeBehavior(MySprite::EdgeBehavior::LOOP);
|
||||
player.setShield(true, &shield, 12, &shieldTimer);
|
||||
|
||||
for (int i = 0; i < player.getLives(); i++)
|
||||
gui.push_back(new MySprite(ship, 20, window.getSize().x - (i * 40 + 25), 25, 0, 270));
|
||||
|
||||
gui.push_back(&score);
|
||||
|
||||
// while our window is open, keep it open
|
||||
// this is our draw loop
|
||||
while (window.isOpen()) {
|
||||
window.clear(Color::Black); // clear the contents of the old frame
|
||||
// by setting the window to black
|
||||
|
||||
if (shieldTimer.getElapsedTime().asSeconds() > 5) {
|
||||
player.setShield(false);
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// Handle keypresses below here
|
||||
//****************************************
|
||||
|
||||
if ((Keyboard::isKeyPressed(Keyboard::Up) || Keyboard::isKeyPressed(Keyboard::W))) player.accelerate(0.5);
|
||||
if ((Keyboard::isKeyPressed(Keyboard::Down) || Keyboard::isKeyPressed(Keyboard::S))) player.accelerate(-.5);
|
||||
if ((Keyboard::isKeyPressed(Keyboard::Right) || Keyboard::isKeyPressed(Keyboard::D))) player.turn(10);
|
||||
if ((Keyboard::isKeyPressed(Keyboard::Left) || Keyboard::isKeyPressed(Keyboard::A))) player.turn(-10);
|
||||
if (Keyboard::isKeyPressed(Keyboard::Space) && fireClock.getElapsedTime().asSeconds() > 0.4) {
|
||||
player.shoot(&projectiles, pew, blueLaser, 0.3, player.getPosition().x, player.getPosition().y, 20,
|
||||
player.getDirection());
|
||||
fireClock.restart();
|
||||
}
|
||||
if (Keyboard::isKeyPressed(Keyboard::Enter) && ended) return 0;
|
||||
|
||||
//****************************************
|
||||
// Handle keypresses above here
|
||||
//****************************************
|
||||
|
||||
//****************************************
|
||||
// Spawn cycle below here
|
||||
//****************************************
|
||||
|
||||
uniform_int_distribution<int> stroidChance(1, 4), stroidSize(1, 3),
|
||||
smallTexture(0, smallAsteroids.size() - 1),
|
||||
mediumTexture(0, mediumAsteroids.size() - 1),
|
||||
largeTexture(0, largeAsteroids.size() - 1), side(1, 4),
|
||||
xPos(0, window.getSize().x), yPos(0, window.getSize().y),
|
||||
scale(70, 110), scaleLarge(65, 85);
|
||||
|
||||
uniform_real_distribution<double> velocity(0.5, 4);
|
||||
|
||||
if (spawnClock.getElapsedTime().asSeconds() >= 0.10) { //spawn chances every .1 sec
|
||||
if (stroidChance(gen) == 1) { //stroid spawns happen approx. every half sec
|
||||
uniform_int_distribution<int> angle;
|
||||
int x = 0, y = 0, s = side(gen);
|
||||
switch (s) { //decide which side of window to spawn stroid
|
||||
case 1: //top
|
||||
x = xPos(gen); //get random xPos
|
||||
if (x <= window.getSize().x /
|
||||
2) { //if on left half of window (calculate angle to point towards window)
|
||||
angle = uniform_int_distribution<int>(
|
||||
285 - ((double) x) / (window.getSize().x / 2.0) * 75, 330);
|
||||
} else { //else
|
||||
angle = uniform_int_distribution<int>(210, 330 -
|
||||
((double) (x - window.getSize().x / 2.0)) /
|
||||
(window.getSize().x / 2.0) * 75);
|
||||
}
|
||||
break;
|
||||
case 2: //left
|
||||
y = yPos(gen); //get random yPos
|
||||
if (y <= window.getSize().y /
|
||||
2) { //if on top half of window (calculate angle to point towards window)
|
||||
angle = uniform_int_distribution<int>(
|
||||
300, 345 + ((double) y) / (window.getSize().y / 2.0) * 75);
|
||||
} else { //else
|
||||
angle = uniform_int_distribution<int>(-60 + ((double) (y - window.getSize().y / 2.0)) /
|
||||
(window.getSize().y / 2.0) * 75, 60);
|
||||
}
|
||||
break;
|
||||
case 3: //bottom
|
||||
x = xPos(gen); //get random xPos
|
||||
y = window.getSize().y;
|
||||
if (x <= window.getSize().x /
|
||||
2) { //if on left half of window (calculate angle to point towards window)
|
||||
angle = uniform_int_distribution<int>(
|
||||
30, 150 - ((double) x) / (window.getSize().x / 2.0) * 75);
|
||||
} else { //else
|
||||
angle = uniform_int_distribution<int>(105 - ((double) (x - window.getSize().x / 2.0)) /
|
||||
(window.getSize().x / 2.0) * 75, 150);
|
||||
}
|
||||
break;
|
||||
case 4: //right
|
||||
y = yPos(gen); //get random yPos
|
||||
x = window.getSize().x;
|
||||
if (y <= window.getSize().y /
|
||||
2) { //if on top half of window (calculate angle to point towards window)
|
||||
angle = uniform_int_distribution<int>(
|
||||
195 - ((double) y) / (window.getSize().y / 2.0) * 75, 240);
|
||||
} else { //else
|
||||
angle = uniform_int_distribution<int>(120, 165 +
|
||||
((double) (y - window.getSize().y / 2.0)) /
|
||||
(window.getSize().y / 2.0) * 75);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int size = stroidSize(gen);
|
||||
switch (size) {
|
||||
case 1:
|
||||
enemies.push_back(
|
||||
new Asteroid(size, size * 100, *smallAsteroids[smallTexture(gen)], scale(gen), x, y,
|
||||
velocity(gen), (360 + angle(gen)) % 360));
|
||||
break;
|
||||
case 2:
|
||||
enemies.push_back(
|
||||
new Asteroid(size, size * 100, *mediumAsteroids[mediumTexture(gen)], scale(gen), x,
|
||||
y, velocity(gen), (360 + angle(gen)) % 360));
|
||||
break;
|
||||
case 3:
|
||||
enemies.push_back(
|
||||
new Asteroid(size, size * 100, *largeAsteroids[largeTexture(gen)], scaleLarge(gen),
|
||||
x, y, velocity(gen), (360 + angle(gen)) % 360));
|
||||
break;
|
||||
}
|
||||
}
|
||||
spawnClock.restart();
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// Spawn cycle above here
|
||||
//****************************************
|
||||
|
||||
//****************************************
|
||||
// Object updates/deletion
|
||||
//****************************************
|
||||
|
||||
player.update(&window);
|
||||
|
||||
for (int i = 0; i < projectiles.size(); i++) {
|
||||
projectiles[i]->update(&window);
|
||||
|
||||
if (projectiles[i]->toBeErased()) {
|
||||
projectiles.erase(projectiles.begin() + i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < enemies.size(); i++) {
|
||||
enemies[i]->update(&window);
|
||||
|
||||
if (enemies[i]->toBeErased()) {
|
||||
enemies.erase(enemies.begin() + i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < enemies.size(); i++) {
|
||||
for (int j = 0; j < projectiles.size(); j++) {
|
||||
if (Collision::PixelPerfectTest(*enemies[i], *projectiles[j], 0)) {
|
||||
uniform_int_distribution<int> angle(0, 359);
|
||||
enemies[i]->setHealth(enemies[i]->getHealth() - 1);
|
||||
if (enemies[i]->getHealth() <= 0) {
|
||||
if (enemies[i]->getType() == "asteroid")
|
||||
((Asteroid *) enemies[i])->hit(animations, enemyBoom, explosion, gen);
|
||||
player.setScore(player.getScore() + enemies[i]->getPoints());
|
||||
enemies.erase(enemies.begin() + i);
|
||||
} else {
|
||||
animations.push_back(
|
||||
new MySprite(explosion, 20, projectiles[j]->getXPos(), projectiles[j]->getYPos(), 0,
|
||||
angle(gen)));
|
||||
animations[animations.size() - 1]->makeAnimated(5, 5, 0.01, 23);
|
||||
}
|
||||
|
||||
projectiles.erase(projectiles.begin() + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < enemies.size(); i++) {
|
||||
if (player.hasShield() && Collision::CircleTest(*enemies[i], *player.getRider().sprite)) {
|
||||
if (enemies[i]->getType() == "asteroid")
|
||||
((Asteroid *) enemies[i])->hit(animations, enemyBoom, explosion, gen);
|
||||
enemies.erase(enemies.begin() + i);
|
||||
} else if (Collision::CircleTest(*enemies[i], player)) {
|
||||
if (!ended && player.hit(window, animations, explosion, gen, shield, 12, shieldTimer)) {
|
||||
ended = true;
|
||||
}
|
||||
gui.erase(gui.begin() + player.getLives() + 1); //remove player icon from top corner
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < animations.size(); i++) {
|
||||
animations[i]->update(&window);
|
||||
if (animations[i]->getAnimation().isPlayed)
|
||||
animations.erase(animations.begin() + i);
|
||||
}
|
||||
|
||||
score.setString("Score: " + to_string(player.getScore()));
|
||||
|
||||
if (player.getScore() - (player.getNewLifeScore() * player.getNumLivesAdded()) >=
|
||||
player.getNewLifeScore()) {
|
||||
player.newLife(gui, ship, window, newLife);
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// Object updates, deletions, collisions above
|
||||
//****************************************
|
||||
|
||||
//****************************************
|
||||
// ADD ALL OF OUR DRAWING BELOW HERE
|
||||
//****************************************
|
||||
|
||||
window.draw(*gui[0]); //draw background
|
||||
|
||||
for (int i = 0; i < projectiles.size(); i++)
|
||||
window.draw(*projectiles[i]);
|
||||
for (int i = 0; i < enemies.size(); i++)
|
||||
window.draw(*enemies[i]);
|
||||
|
||||
for (MySprite *a : animations)
|
||||
window.draw(*a);
|
||||
|
||||
if (!ended) {
|
||||
window.draw(player);
|
||||
|
||||
if (player.getRider().sprite != nullptr)
|
||||
window.draw(*player.getRider().sprite);
|
||||
} else {
|
||||
for (auto d : lost) window.draw(*d);
|
||||
}
|
||||
|
||||
for (int i = 1; i < gui.size(); i++) {
|
||||
window.draw(*gui[i]);
|
||||
}
|
||||
//****************************************
|
||||
// ADD ALL OF OUR DRAWING ABOVE HERE
|
||||
//****************************************
|
||||
|
||||
window.display(); // display the window
|
||||
|
||||
//****************************************
|
||||
// HANDLE EVENTS BELOW HERE
|
||||
//****************************************
|
||||
Event event;
|
||||
while (window.pollEvent(event)) { // ask the window if any events occurred
|
||||
if (event.type == Event::Closed) { // if event type is a closed event
|
||||
// i.e. they clicked the X on the window
|
||||
window.close(); // then close our window
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1; // report our program exited successfully
|
||||
}
|
||||
};
|
||||
472
Menu.h
Normal file
|
|
@ -0,0 +1,472 @@
|
|||
//
|
||||
// Created by benmo on 2/20/2020.
|
||||
//
|
||||
|
||||
#ifndef SFML_TEMPLATE_MENU_H
|
||||
#define SFML_TEMPLATE_MENU_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <winuser.h>
|
||||
|
||||
class Menu {
|
||||
public:
|
||||
int result;
|
||||
bool soundOn = true, musicOn = true;
|
||||
|
||||
Menu() {
|
||||
result = init();
|
||||
}
|
||||
private:
|
||||
sf::SoundBuffer bip;
|
||||
sf::Sound bipSound;
|
||||
bool playedBip = false;
|
||||
|
||||
int init() {
|
||||
const int MENU = 0, CREDITS = 1;
|
||||
int screen = 0;
|
||||
|
||||
std::vector<MySprite*> buttons;
|
||||
std::vector<sf::Text*> text;
|
||||
|
||||
std::vector<sf::Text*> credits;
|
||||
std::vector<sf::Sprite*> creditsGUI;
|
||||
|
||||
sf::RenderWindow window( sf::VideoMode(1240, 640), "Asteroids" );
|
||||
sf::View mainView;
|
||||
mainView.setCenter(window.getSize().x/(float)2.0, window.getSize().y/(float)2.0);
|
||||
mainView.setSize(window.getSize().x, window.getSize().y);
|
||||
window.setView(mainView);
|
||||
window.setPosition(sf::Vector2i(window.getPosition().x, window.getPosition().y - 50));
|
||||
|
||||
/*************************************************
|
||||
* File Input && Processing
|
||||
*************************************************/
|
||||
sf::Font sk;
|
||||
sk.loadFromFile("data/Fonts/Sk.ttf");
|
||||
|
||||
sf::Font skME;
|
||||
skME.loadFromFile("data/Fonts/SKoME.ttf");
|
||||
|
||||
sf::Font xolo;
|
||||
xolo.loadFromFile("data/Fonts/Xolonium-Bold.ttf");
|
||||
|
||||
sf::Font monkirta;
|
||||
monkirta.loadFromFile("data/Fonts/Monkirta Pursuit NC.ttf");
|
||||
|
||||
sf::Font oxan;
|
||||
oxan.loadFromFile("data/Fonts/Oxanium-Light.ttf");
|
||||
|
||||
sf::Texture back;
|
||||
back.loadFromFile("data/Gui/space.png");
|
||||
back.setRepeated(true);
|
||||
|
||||
sf::Texture button;
|
||||
button.loadFromFile("data/Gui/button.png");
|
||||
|
||||
sf::Texture box;
|
||||
box.loadFromFile("data/Gui/window.png");
|
||||
|
||||
sf::Texture boxSm;
|
||||
boxSm.loadFromFile("data/Gui/windowSm.png");
|
||||
|
||||
sf::Texture cloud;
|
||||
cloud.loadFromFile("data/Gui/cloud.png");
|
||||
|
||||
sf::Texture leftArrow;
|
||||
leftArrow.loadFromFile("data/Gui/Backward_BTN.png");
|
||||
|
||||
sf::Texture soundBTN;
|
||||
soundBTN.loadFromFile("data/Gui/Sound.png");
|
||||
|
||||
sf::Texture musicBTN;
|
||||
musicBTN.loadFromFile("data/Gui/Music.png");
|
||||
|
||||
sf::Texture initials;
|
||||
initials.loadFromFile("data/Morgan Ben initials.png");
|
||||
|
||||
sf::Music menuLoop;
|
||||
menuLoop.openFromFile("data/Sounds/Unknown Theme.wav");
|
||||
menuLoop.setLoop(true);
|
||||
menuLoop.play();
|
||||
|
||||
bip.loadFromFile("data/Sounds/rollover.wav");
|
||||
|
||||
/*************************************************
|
||||
* Object Initialization
|
||||
*************************************************/
|
||||
|
||||
//Background pan sprite
|
||||
sf::Sprite background(back);
|
||||
sf::FloatRect fBounds(mainView.getCenter().x, mainView.getCenter().y, background.getTexture()->getSize().x * 3, background.getTexture()->getSize().y * 3);
|
||||
sf::IntRect iBounds(fBounds);
|
||||
|
||||
background.setTextureRect(iBounds);
|
||||
background.setPosition(mainView.getCenter());
|
||||
background.setOrigin(iBounds.width/(float)2.0,iBounds.height/(float)2.0);
|
||||
|
||||
//Sound settings
|
||||
MySprite soundButton(soundBTN, 25, 35, 37, 0, 0);
|
||||
MySprite musicButton(musicBTN, 25, soundButton.getXPos() + soundButton.getGlobalBounds().width, soundButton.getYPos(), 0, 0);
|
||||
|
||||
//Title text
|
||||
sf::Text title("Asteroids", skME, 90);
|
||||
title.setPosition(mainView.getCenter().x, mainView.getCenter().y - window.getSize().y / (float)3.0);
|
||||
title.setFillColor(sf::Color::White);
|
||||
title.setLetterSpacing(title.getLetterSpacing() + (float)0.5);
|
||||
title.setOrigin(title.getGlobalBounds().width/(float)2.0, title.getGlobalBounds().height/(float)2.0);
|
||||
|
||||
MySprite inits(initials, 15);
|
||||
inits.setPosition(window.getSize().x - inits.getGlobalBounds().width + 10, window.getSize().y - inits.getGlobalBounds().height);
|
||||
|
||||
//Start button & text
|
||||
MySprite startButton(button, 55);
|
||||
startButton.setPosition(mainView.getCenter().x, mainView.getCenter().y - window.getSize().y / (float)12.0);
|
||||
|
||||
//default button color
|
||||
sf::Color defButtonColor = startButton.getColor();
|
||||
|
||||
sf::Text startText("Start", sk, 28);
|
||||
startText.setPosition(startButton.getPosition().x, startButton.getPosition().y - 7);
|
||||
startText.setFillColor(sf::Color(0,0,0,0));
|
||||
startText.setOutlineColor(sf::Color::White);
|
||||
startText.setOutlineThickness(1);
|
||||
startText.setLetterSpacing(startText.getLetterSpacing() + 1);
|
||||
startText.setOrigin(startText.getLocalBounds().width/2, startText.getLocalBounds().height/2);
|
||||
|
||||
//Credits button & text
|
||||
MySprite creditsButton(button, 55);
|
||||
creditsButton.setPosition(mainView.getCenter().x, mainView.getCenter().y);
|
||||
|
||||
sf::Text creditsText("Credits", sk, 28);
|
||||
creditsText.setPosition(creditsButton.getPosition().x, creditsButton.getPosition().y - 6);
|
||||
creditsText.setFillColor(sf::Color(0,0,0,0));
|
||||
creditsText.setOutlineColor(sf::Color::White);
|
||||
creditsText.setOutlineThickness(1);
|
||||
creditsText.setLetterSpacing(creditsText.getLetterSpacing() + 1);
|
||||
creditsText.setOrigin(creditsText.getLocalBounds().width/2, creditsText.getLocalBounds().height/2);
|
||||
|
||||
//Exit button & text
|
||||
MySprite exitButton(button, 55);
|
||||
exitButton.setPosition(mainView.getCenter().x, mainView.getCenter().y + window.getSize().y / (float)12.0);
|
||||
|
||||
sf::Text exitText("Exit", sk, 28);
|
||||
exitText.setPosition(mainView.getCenter().x, exitButton.getPosition().y - 6);
|
||||
exitText.setFillColor(sf::Color(0,0,0,0));
|
||||
exitText.setOutlineColor(sf::Color::White);
|
||||
exitText.setOutlineThickness(1);
|
||||
exitText.setLetterSpacing(exitText.getLetterSpacing() + 1);
|
||||
exitText.setOrigin(exitText.getLocalBounds().width/2, exitText.getLocalBounds().height/2);
|
||||
|
||||
buttons.push_back(&startButton);
|
||||
buttons.push_back(&creditsButton);
|
||||
buttons.push_back(&exitButton);
|
||||
|
||||
text.push_back(&startText);
|
||||
text.push_back(&creditsText);
|
||||
text.push_back(&exitText);
|
||||
|
||||
//Credits
|
||||
sf::Text creditsTitle("Credits + Resources", sk, 70);
|
||||
creditsTitle.setPosition(mainView.getCenter().x, window.getSize().y / (float)14.0);
|
||||
creditsTitle.setFillColor(sf::Color::White);
|
||||
creditsTitle.setOrigin(creditsTitle.getGlobalBounds().width/2, creditsTitle.getGlobalBounds().height/2);
|
||||
|
||||
//Credits box
|
||||
sf::Text credsTitle("Credits", xolo, 28);
|
||||
credsTitle.setOrigin(credsTitle.getGlobalBounds().width/2, credsTitle.getGlobalBounds().height/2);
|
||||
credsTitle.setPosition(mainView.getSize().x/(float)5.1, mainView.getSize().y/2 + mainView.getSize().y/22);
|
||||
credsTitle.setFillColor(sf::Color::White);
|
||||
|
||||
sf::Text music("River Schreckengost - ", monkirta, 20);
|
||||
music.setOrigin(music.getGlobalBounds().width/2, music.getGlobalBounds().height/2);
|
||||
music.setPosition(mainView.getSize().x/(float)5.8, mainView.getSize().y/(float)2 + mainView.getSize().y/(float)8.5);
|
||||
music.setFillColor(sf::Color::White);
|
||||
|
||||
sf::Text musicText("Music", oxan, 15);
|
||||
musicText.setPosition(mainView.getSize().x/(float)5.8 + music.getGlobalBounds().width/2, mainView.getSize().y/(float)2 + mainView.getSize().y/(float)8.925);
|
||||
musicText.setFillColor(sf::Color::White);
|
||||
|
||||
sf::Text musicLabel("Instagram - ", monkirta, 15);
|
||||
musicLabel.setPosition(mainView.getSize().x/(float)11.5, mainView.getSize().y/(float)2 + mainView.getSize().y/(float)7.3);
|
||||
musicLabel.setFillColor(sf::Color::White);
|
||||
|
||||
sf::Text musicText0("@river.schreck", oxan, 12);
|
||||
musicText0.setPosition(mainView.getSize().x/(float)11.5 + musicLabel.getGlobalBounds().width, mainView.getSize().y/(float)2 + mainView.getSize().y/(float)7.15);
|
||||
musicText0.setFillColor(sf::Color::White);
|
||||
musicText0.setStyle(sf::Text::Style::Underlined);
|
||||
|
||||
sf::Text musicLabel0("SoundCloud - ", monkirta, 15);
|
||||
musicLabel0.setPosition(mainView.getSize().x/(float)11.5, mainView.getSize().y/(float)2 + mainView.getSize().y/(float)6.1);
|
||||
musicLabel0.setFillColor(sf::Color::White);
|
||||
|
||||
sf::Text musicText1("River Ethans", oxan, 12);
|
||||
musicText1.setPosition(mainView.getSize().x/(float)11.5 + musicLabel0.getGlobalBounds().width, mainView.getSize().y/(float)2 + mainView.getSize().y/(float)5.95);
|
||||
musicText1.setFillColor(sf::Color::White);
|
||||
musicText1.setStyle(sf::Text::Style::Underlined);
|
||||
|
||||
//Resources Box
|
||||
sf::Text resourcesTitle("Resources", xolo, 28);
|
||||
resourcesTitle.setOrigin(resourcesTitle.getGlobalBounds().width/2, resourcesTitle.getGlobalBounds().height/2);
|
||||
resourcesTitle.setPosition(mainView.getSize().x - mainView.getSize().x/(float)4.95, mainView.getSize().y/(float)4.8);
|
||||
resourcesTitle.setFillColor(sf::Color::White);
|
||||
|
||||
//Dev box
|
||||
sf::Text developerTitle("Developer: ", xolo, 25);
|
||||
developerTitle.setPosition(mainView.getSize().x/13, mainView.getSize().y/(float)5.2);
|
||||
developerTitle.setFillColor(sf::Color(0,0,0,0));
|
||||
developerTitle.setOutlineThickness(.8);
|
||||
developerTitle.setOutlineColor(sf::Color::White);
|
||||
|
||||
sf::Text developer("Benjamin Morgan", monkirta, 20);
|
||||
developer.setOrigin(developer.getGlobalBounds().width/2, developer.getGlobalBounds().height/2);
|
||||
developer.setPosition(mainView.getSize().x/(float)6.725, mainView.getSize().y/(float)3.95);
|
||||
developer.setFillColor(sf::Color::White);
|
||||
|
||||
sf::Text devLabel("Site - ", monkirta, 15);
|
||||
devLabel.setPosition(mainView.getSize().x/(float)11.5, mainView.getSize().y/(float)3.65);
|
||||
devLabel.setFillColor(sf::Color::White);
|
||||
|
||||
sf::Text devText("https://www.benrmorgan.com/", oxan, 12);
|
||||
devText.setPosition(mainView.getSize().x/(float)11.5 + devLabel.getGlobalBounds().width, mainView.getSize().y/(float)3.6);
|
||||
devText.setFillColor(sf::Color::White);
|
||||
devText.setStyle(sf::Text::Style::Underlined);
|
||||
|
||||
sf::Text devLabel0("Github - ", monkirta, 15);
|
||||
devLabel0.setPosition(mainView.getSize().x/(float)11.5, mainView.getSize().y/(float)3.35);
|
||||
devLabel0.setFillColor(sf::Color::White);
|
||||
|
||||
sf::Text devText0("bMorgan01", oxan, 12);
|
||||
devText0.setPosition(mainView.getSize().x/(float)11.5 + devLabel0.getGlobalBounds().width, mainView.getSize().y/(float)3.3);
|
||||
devText0.setFillColor(sf::Color::White);
|
||||
devText0.setStyle(sf::Text::Style::Underlined);
|
||||
|
||||
sf::Text devLabel1("Email - ", monkirta, 15);
|
||||
devLabel1.setPosition(mainView.getSize().x/(float)11.5, mainView.getSize().y/(float)3.1);
|
||||
devLabel1.setFillColor(sf::Color::White);
|
||||
|
||||
sf::Text devText1("ben@benrmorgan.com", oxan, 12);
|
||||
devText1.setPosition(mainView.getSize().x/(float)11.5 + devLabel1.getGlobalBounds().width, mainView.getSize().y/(float)3.05);
|
||||
devText1.setFillColor(sf::Color::White);
|
||||
|
||||
sf::Text devLabel2("Repo - ", monkirta, 15);
|
||||
devLabel2.setPosition(mainView.getSize().x/(float)11.5, mainView.getSize().y/(float)2.87);
|
||||
devLabel2.setFillColor(sf::Color::White);
|
||||
|
||||
sf::Text devText2("https://github.com/bMorgan01/StarCap", oxan, 12);
|
||||
devText2.setPosition(mainView.getSize().x/(float)11.5 + devLabel2.getGlobalBounds().width, mainView.getSize().y/(float)2.83);
|
||||
devText2.setFillColor(sf::Color::White);
|
||||
devText2.setStyle(sf::Text::Style::Underlined);
|
||||
|
||||
//Credits GUI
|
||||
sf::Sprite backButton(leftArrow);
|
||||
backButton.setScale(.3, .3);
|
||||
backButton.setPosition(33, 100);
|
||||
|
||||
sf::Sprite textBox(box);
|
||||
textBox.setScale(.35, .35);
|
||||
textBox.setPosition(mainView.getSize().x - mainView.getSize().x/3, mainView.getSize().y/(float)5.5);
|
||||
|
||||
sf::Sprite textBoxSm(boxSm);
|
||||
textBoxSm.setScale(.35, .35);
|
||||
textBoxSm.setPosition(mainView.getSize().x/15, mainView.getSize().y/2 + mainView.getSize().y/50);
|
||||
|
||||
sf::Sprite devBox(cloud);
|
||||
devBox.setScale(.442, .442);
|
||||
devBox.setPosition(mainView.getSize().x/15 - 2, mainView.getSize().y/(float)5.5);
|
||||
|
||||
sf::Sprite issueButton(button);
|
||||
issueButton.setColor(sf::Color::Red);
|
||||
issueButton.setScale(40.0/100.0, 40.0/100.0);
|
||||
issueButton.setOrigin(issueButton.getGlobalBounds().width/2, issueButton.getGlobalBounds().height/2);
|
||||
issueButton.setPosition(mainView.getSize().x/(float)6.2, mainView.getSize().y/(float)2.52);
|
||||
|
||||
sf::Text issueText("Report Bug", sk, 16);
|
||||
issueText.setPosition(issueButton.getPosition().x - 21, issueButton.getPosition().y);
|
||||
issueText.setFillColor(sf::Color(0,0,0,0));
|
||||
issueText.setFillColor(sf::Color::White);
|
||||
|
||||
credits.push_back(&creditsTitle);
|
||||
credits.push_back(&developerTitle);
|
||||
credits.push_back(&credsTitle);
|
||||
credits.push_back(&music);
|
||||
credits.push_back(&musicText);
|
||||
credits.push_back(&musicLabel);
|
||||
credits.push_back(&musicText0);
|
||||
credits.push_back(&musicLabel0);
|
||||
credits.push_back(&musicText1);
|
||||
credits.push_back(&resourcesTitle);
|
||||
credits.push_back(&developer);
|
||||
credits.push_back(&devLabel);
|
||||
credits.push_back(&devText);
|
||||
credits.push_back(&devLabel0);
|
||||
credits.push_back(&devText0);
|
||||
credits.push_back(&devLabel1);
|
||||
credits.push_back(&devText1);
|
||||
credits.push_back(&devLabel2);
|
||||
credits.push_back(&devText2);
|
||||
credits.push_back(&issueText);
|
||||
|
||||
creditsGUI.push_back(&backButton);
|
||||
creditsGUI.push_back(&textBox);
|
||||
creditsGUI.push_back(&textBoxSm);
|
||||
creditsGUI.push_back(&devBox);
|
||||
creditsGUI.push_back(&issueButton);
|
||||
|
||||
while( window.isOpen() ) {
|
||||
/*********************************************
|
||||
* Pre-draw ops here.
|
||||
*********************************************/
|
||||
|
||||
|
||||
/*********************************************
|
||||
* Drawing goes here.
|
||||
*********************************************/
|
||||
|
||||
window.clear( sf::Color::Black ); // clear the contents of the old frame
|
||||
|
||||
window.draw(background);
|
||||
|
||||
switch(screen) {
|
||||
case MENU:
|
||||
/**************
|
||||
* Draw Menu
|
||||
**************/
|
||||
backButton.setPosition(33, 100);
|
||||
|
||||
//Sound buttons
|
||||
window.draw(soundButton);
|
||||
window.draw(musicButton);
|
||||
|
||||
//Title text
|
||||
window.draw(title);
|
||||
|
||||
for (int i = 0; i < buttons.size(); i++) {
|
||||
window.draw(*buttons[i]);
|
||||
window.draw(*text[i]);
|
||||
}
|
||||
|
||||
window.draw(inits);
|
||||
break;
|
||||
case CREDITS:
|
||||
/**************
|
||||
* Draw Credits
|
||||
**************/
|
||||
backButton.setPosition(33, 27);
|
||||
|
||||
for (sf::Sprite *s : creditsGUI) {
|
||||
window.draw(*s);
|
||||
}
|
||||
|
||||
for (sf::Text *t : credits) {
|
||||
window.draw(*t);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
window.display(); // display the window
|
||||
|
||||
sf::Event event{};
|
||||
while( window.pollEvent(event) ) { // ask the window if any events occurred
|
||||
|
||||
/*********************************************
|
||||
* Event handling here.
|
||||
*********************************************/
|
||||
sf::Vector2i mousePos = sf::Mouse::getPosition( window );
|
||||
sf::Vector2f mousePosF( static_cast<float>( mousePos.x ), static_cast<float>( mousePos.y ) );
|
||||
|
||||
switch (event.type) {
|
||||
case sf::Event::Closed: //user clicked X button
|
||||
window.close();
|
||||
break;
|
||||
case sf::Event::MouseButtonPressed: //User clicked mouse
|
||||
if (exitButton.getGlobalBounds().contains(mousePosF) && screen == MENU) {
|
||||
playBip();
|
||||
return EXIT_FAILURE;
|
||||
} else if (startButton.getGlobalBounds().contains(mousePosF) && screen == MENU) {
|
||||
playBip();
|
||||
return EXIT_SUCCESS;
|
||||
} else if (creditsButton.getGlobalBounds().contains(mousePosF) && screen == MENU) {
|
||||
playBip();
|
||||
screen = CREDITS;
|
||||
} else if (issueButton.getGlobalBounds().contains(mousePosF) && screen == CREDITS) {
|
||||
playBip();
|
||||
ShellExecute(nullptr, "open", "https://github.com/bMorgan01/StarCap/issues", nullptr, nullptr, SW_SHOWNORMAL);
|
||||
} else if (devText.getGlobalBounds().contains(mousePosF) && screen == CREDITS) {
|
||||
playBip();
|
||||
ShellExecute(nullptr, "open", "https://www.benrmorgan.com", nullptr, nullptr, SW_SHOWNORMAL);
|
||||
} else if (devText0.getGlobalBounds().contains(mousePosF) && screen == CREDITS) {
|
||||
playBip();
|
||||
ShellExecute(nullptr, "open", "https://github.com/bMorgan01", nullptr, nullptr, SW_SHOWNORMAL);
|
||||
} else if (devText2.getGlobalBounds().contains(mousePosF) && screen == CREDITS) {
|
||||
playBip();
|
||||
ShellExecute(nullptr, "open", "https://github.com/bMorgan01/StarCap", nullptr, nullptr, SW_SHOWNORMAL);
|
||||
} else if (musicText0.getGlobalBounds().contains(mousePosF) && screen == CREDITS) {
|
||||
playBip();
|
||||
ShellExecute(nullptr, "open", "https://www.instagram.com/river.schreck/", nullptr, nullptr, SW_SHOWNORMAL);
|
||||
} else if (musicText1.getGlobalBounds().contains(mousePosF) && screen == CREDITS) {
|
||||
playBip();
|
||||
ShellExecute(nullptr, "open", "https://soundcloud.com/riverethans", nullptr, nullptr, SW_SHOWNORMAL);
|
||||
} else if (backButton.getGlobalBounds().contains(mousePosF) && screen == CREDITS) {
|
||||
playBip();
|
||||
screen = MENU;
|
||||
} else if (soundButton.getGlobalBounds().contains(mousePosF) && screen == MENU) {
|
||||
soundOn = !soundOn;
|
||||
playBip();
|
||||
} else if (musicButton.getGlobalBounds().contains(mousePosF) && screen == MENU) {
|
||||
playBip();
|
||||
musicOn = !musicOn;
|
||||
if (!musicOn) menuLoop.setVolume(0);
|
||||
else menuLoop.setVolume(100);
|
||||
}
|
||||
break;
|
||||
case sf::Event::MouseMoved:
|
||||
if (exitButton.getGlobalBounds().contains(mousePosF) && screen == MENU) exitButton.setColor(sf::Color::Red);
|
||||
else if (startButton.getGlobalBounds().contains(mousePosF) && screen == MENU) startButton.setColor(sf::Color::Red);
|
||||
else if (creditsButton.getGlobalBounds().contains(mousePosF) && screen == MENU) creditsButton.setColor(sf::Color::Red);
|
||||
else if (issueButton.getGlobalBounds().contains(mousePosF) && screen == CREDITS) issueButton.setColor(sf::Color::Green);
|
||||
else if (devText.getGlobalBounds().contains(mousePosF) && screen == CREDITS) devText.setFillColor(sf::Color::Red);
|
||||
else if (devText0.getGlobalBounds().contains(mousePosF) && screen == CREDITS) devText0.setFillColor(sf::Color::Red);
|
||||
else if (devText2.getGlobalBounds().contains(mousePosF) && screen == CREDITS) devText2.setFillColor(sf::Color::Red);
|
||||
else if (musicText0.getGlobalBounds().contains(mousePosF) && screen == CREDITS) musicText0.setFillColor(sf::Color::Red);
|
||||
else if (musicText1.getGlobalBounds().contains(mousePosF) && screen == CREDITS) musicText1.setFillColor(sf::Color::Red);
|
||||
else if (backButton.getGlobalBounds().contains(mousePosF) && screen == CREDITS) backButton.setColor(sf::Color::Red);
|
||||
else if (soundButton.getGlobalBounds().contains(mousePosF) && soundOn && screen == MENU) soundButton.setColor(sf::Color::Red);
|
||||
else if (musicButton.getGlobalBounds().contains(mousePosF) && musicOn && screen == MENU) musicButton.setColor(sf::Color::Red);
|
||||
else if (soundButton.getGlobalBounds().contains(mousePosF) && !soundOn && screen == MENU) soundButton.setColor(sf::Color::White);
|
||||
else if (musicButton.getGlobalBounds().contains(mousePosF) && !musicOn && screen == MENU) musicButton.setColor(sf::Color::White);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!exitButton.getGlobalBounds().contains(mousePosF)) exitButton.setColor(defButtonColor);
|
||||
if (!startButton.getGlobalBounds().contains(mousePosF)) startButton.setColor(defButtonColor);
|
||||
if (!creditsButton.getGlobalBounds().contains(mousePosF)) creditsButton.setColor(defButtonColor);
|
||||
if (!issueButton.getGlobalBounds().contains(mousePosF)) issueButton.setColor(sf::Color::Red);
|
||||
if (!devText.getGlobalBounds().contains(mousePosF)) devText.setFillColor(sf::Color::White);
|
||||
if (!devText0.getGlobalBounds().contains(mousePosF)) devText0.setFillColor(sf::Color::White);
|
||||
if (!devText2.getGlobalBounds().contains(mousePosF)) devText2.setFillColor(sf::Color::White);
|
||||
if (!musicText0.getGlobalBounds().contains(mousePosF)) musicText0.setFillColor(sf::Color::White);
|
||||
if (!musicText1.getGlobalBounds().contains(mousePosF)) musicText1.setFillColor(sf::Color::White);
|
||||
if (!backButton.getGlobalBounds().contains(mousePosF)) backButton.setColor(defButtonColor);
|
||||
if (!soundButton.getGlobalBounds().contains(mousePosF) && soundOn) soundButton.setColor(sf::Color::White);
|
||||
if (!musicButton.getGlobalBounds().contains(mousePosF) && musicOn) musicButton.setColor(sf::Color::White);
|
||||
if (!soundButton.getGlobalBounds().contains(mousePosF) && !soundOn) soundButton.setColor(sf::Color::Red);
|
||||
if (!musicButton.getGlobalBounds().contains(mousePosF) && !musicOn) musicButton.setColor(sf::Color::Red);
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
void playBip() {
|
||||
if (soundOn) {
|
||||
bipSound.setBuffer(bip);
|
||||
bipSound.setVolume(100);
|
||||
bipSound.play();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif //SFML_TEMPLATE_MENU_H
|
||||
328
MySprite.h
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
//
|
||||
// Created by benmo on 2/14/2020.
|
||||
//
|
||||
|
||||
#ifndef SFML_TEMPLATE_SPRITE_H
|
||||
#define SFML_TEMPLATE_SPRITE_H
|
||||
|
||||
#include <string>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <cmath>
|
||||
|
||||
using namespace sf;
|
||||
|
||||
class MySprite: public sf::Sprite{
|
||||
protected:
|
||||
struct Physics {
|
||||
float velocity, direction, acceleration, maxVelocity, minVelocity;
|
||||
float rotVelocity, rotAcceleration, maxRotVelocity;
|
||||
float xPos, yPos;
|
||||
};
|
||||
|
||||
struct Animation {
|
||||
float frameLength;
|
||||
unsigned int currframe = 0, columns, height, width, numFrames;
|
||||
Clock clock;
|
||||
bool isAnimated = false, isPlayed = false;
|
||||
IntRect textureRect;
|
||||
};
|
||||
|
||||
struct Rider {
|
||||
MySprite* sprite;
|
||||
bool followsDirection = false, followsPosition = true;
|
||||
};
|
||||
|
||||
Physics spritePhysics{};
|
||||
|
||||
Animation spriteAnimation{};
|
||||
|
||||
Rider spriteRider{};
|
||||
|
||||
bool toErase = false, circularHitbox = false;
|
||||
public:
|
||||
enum EdgeBehavior {
|
||||
IGNORE, LOOP, BOUNCE
|
||||
};
|
||||
|
||||
EdgeBehavior edgeBehavior = IGNORE;
|
||||
|
||||
constexpr static const double PI = 3.1415926;
|
||||
|
||||
static double distance(sf::Vector2f pos1, sf::Vector2f pos2) {
|
||||
return sqrt(pow(pos2.x - pos1.x, 2) + pow(pos2.y - pos1.y, 2));
|
||||
}
|
||||
|
||||
MySprite() : sf::Sprite() {
|
||||
spritePhysics.velocity = 0;
|
||||
spritePhysics.xPos = 0;
|
||||
spritePhysics.yPos = 0;
|
||||
spritePhysics.direction = 0;
|
||||
|
||||
setOrigin(getGlobalBounds().width/2,getGlobalBounds().height/2);
|
||||
}
|
||||
|
||||
explicit MySprite(const sf::Texture &texture) : sf::Sprite(texture) {
|
||||
spritePhysics.velocity = 0;
|
||||
spritePhysics.xPos = 0;
|
||||
spritePhysics.yPos = 0;
|
||||
spritePhysics.direction = 0;
|
||||
|
||||
setOrigin(getGlobalBounds().width/2,getGlobalBounds().height/2);
|
||||
}
|
||||
|
||||
MySprite(const sf::Texture &texture, float scale) : sf::Sprite(texture) {
|
||||
spritePhysics.velocity = 0;
|
||||
spritePhysics.xPos = 0;
|
||||
spritePhysics.yPos = 0;
|
||||
spritePhysics.direction = 0;
|
||||
|
||||
setOrigin(getGlobalBounds().width/2,getGlobalBounds().height/2);
|
||||
setScale(scale/100, scale/100);
|
||||
}
|
||||
|
||||
MySprite(const sf::Texture &texture, const sf::IntRect &rectangle) : sf::Sprite(texture, rectangle) {
|
||||
spritePhysics.velocity = 0;
|
||||
spritePhysics.xPos = 0;
|
||||
spritePhysics.yPos = 0;
|
||||
spritePhysics.direction = 0;
|
||||
|
||||
setOrigin(rectangle.width/(float)2.0,rectangle.height/(float)2.0);
|
||||
|
||||
}
|
||||
|
||||
MySprite(const sf::Texture &texture, float scale, float xPos, float yPos, float velocity, float direction) : sf::Sprite(texture) {
|
||||
spritePhysics.velocity = velocity;
|
||||
spritePhysics.xPos = xPos;
|
||||
spritePhysics.yPos = yPos;
|
||||
spritePhysics.direction = direction;
|
||||
|
||||
setScale(scale/100, scale/100);
|
||||
setOrigin(getLocalBounds().width/2, getLocalBounds().height/2);
|
||||
setPosition(spritePhysics.xPos,spritePhysics.yPos);
|
||||
setRotation(direction);
|
||||
}
|
||||
|
||||
MySprite(const sf::Texture &texture, float scale, float xPos, float yPos, float velocity, float maxVelocity, float direction, float rotVelocity, float maxRotVelocity) : sf::Sprite(texture) {
|
||||
spritePhysics.velocity = velocity;
|
||||
spritePhysics.xPos = xPos;
|
||||
spritePhysics.yPos = yPos;
|
||||
spritePhysics.direction = direction;
|
||||
spritePhysics.rotVelocity = rotVelocity;
|
||||
spritePhysics.maxVelocity = maxVelocity;
|
||||
spritePhysics.maxRotVelocity = maxRotVelocity;
|
||||
|
||||
setScale(scale/100, scale/100);
|
||||
setOrigin(getLocalBounds().width/2, getLocalBounds().height/2);
|
||||
setPosition(spritePhysics.xPos,spritePhysics.yPos);
|
||||
setRotation(direction);
|
||||
}
|
||||
|
||||
MySprite(const sf::Texture &texture, float scale, float xPos, float yPos, float velocity, float acceleration, float maxVelocity, float direction, float rotVelocity, float rotAcceleration, float maxRotVelocity) : sf::Sprite(texture) {
|
||||
spritePhysics.velocity = velocity;
|
||||
spritePhysics.xPos = xPos;
|
||||
spritePhysics.yPos = yPos;
|
||||
spritePhysics.direction = direction;
|
||||
spritePhysics.rotVelocity = rotVelocity;
|
||||
spritePhysics.maxVelocity = maxVelocity;
|
||||
spritePhysics.maxRotVelocity = maxRotVelocity;
|
||||
spritePhysics.acceleration = acceleration;
|
||||
spritePhysics.rotAcceleration = rotAcceleration;
|
||||
|
||||
setScale(scale/100, scale/100);
|
||||
setOrigin(getLocalBounds().width/2, getLocalBounds().height/2);
|
||||
setPosition(spritePhysics.xPos,spritePhysics.yPos);
|
||||
setRotation(direction);
|
||||
}
|
||||
|
||||
MySprite(const sf::Texture &texture, float scale, float xPos, float yPos, float velocity, float maxVelocity, float direction) : sf::Sprite(texture) {
|
||||
spritePhysics.velocity = velocity;
|
||||
spritePhysics.xPos = xPos;
|
||||
spritePhysics.yPos = yPos;
|
||||
spritePhysics.direction = direction;
|
||||
spritePhysics.maxVelocity = maxVelocity;
|
||||
|
||||
setScale(scale/100, scale/100);
|
||||
setOrigin(getLocalBounds().width/2, getLocalBounds().height/2);
|
||||
setPosition(spritePhysics.xPos,spritePhysics.yPos);
|
||||
setRotation(direction);
|
||||
}
|
||||
|
||||
void makeAnimated(int rows, int columns, float length, int frames = 0) {
|
||||
spriteAnimation.height = getTexture()->getSize().y/rows;
|
||||
spriteAnimation.width = getTexture()->getSize().x/columns;
|
||||
spriteAnimation.frameLength = length;
|
||||
spriteAnimation.columns = columns;
|
||||
|
||||
if (frames == 0) spriteAnimation.numFrames = rows*columns;
|
||||
else spriteAnimation.numFrames = frames;
|
||||
|
||||
spriteAnimation.isAnimated = true;
|
||||
|
||||
spriteAnimation.textureRect = IntRect(0, 0, spriteAnimation.width, spriteAnimation.height);
|
||||
setTextureRect(spriteAnimation.textureRect);
|
||||
|
||||
setOrigin(spriteAnimation.width/2.0, spriteAnimation.height/2.0);
|
||||
}
|
||||
|
||||
void update(RenderWindow* window = nullptr) {
|
||||
spritePhysics.xPos += cos(spritePhysics.direction * (PI/180)) * spritePhysics.velocity;
|
||||
spritePhysics.yPos += -(sin(spritePhysics.direction * (PI/180)) * spritePhysics.velocity);
|
||||
|
||||
if (edgeBehavior == LOOP) {
|
||||
if (spritePhysics.xPos <= -getGlobalBounds().width)
|
||||
spritePhysics.xPos = window->getSize().x + getGlobalBounds().width;
|
||||
else if (spritePhysics.xPos >= window->getSize().x + getGlobalBounds().width)
|
||||
spritePhysics.xPos = -getGlobalBounds().width;
|
||||
|
||||
if (spritePhysics.yPos <= -getGlobalBounds().height)
|
||||
spritePhysics.yPos = window->getSize().y + getGlobalBounds().height;
|
||||
else if (spritePhysics.yPos >= window->getSize().y + getGlobalBounds().height)
|
||||
spritePhysics.yPos = -getGlobalBounds().height;
|
||||
} else if (edgeBehavior == IGNORE) {
|
||||
if (spritePhysics.xPos <= -getGlobalBounds().width ||
|
||||
spritePhysics.xPos >= window->getSize().x + getGlobalBounds().width ||
|
||||
spritePhysics.yPos <= -getGlobalBounds().height ||
|
||||
spritePhysics.yPos >= window->getSize().y + getGlobalBounds().height)
|
||||
toErase = true;
|
||||
}
|
||||
|
||||
spritePhysics.direction -= spritePhysics.rotVelocity;
|
||||
spritePhysics.direction = fmod(spritePhysics.direction, 360);
|
||||
if (spritePhysics.direction < 0)
|
||||
spritePhysics.direction += 360;
|
||||
|
||||
if (spriteAnimation.isAnimated) {
|
||||
if (spriteAnimation.clock.getElapsedTime().asSeconds() > spriteAnimation.frameLength) {
|
||||
spriteAnimation.currframe++;
|
||||
if (spriteAnimation.currframe % spriteAnimation.columns == 0) {
|
||||
spriteAnimation.textureRect.left = 0;
|
||||
spriteAnimation.textureRect.top += spriteAnimation.height;
|
||||
} else
|
||||
spriteAnimation.textureRect.left += spriteAnimation.height;
|
||||
|
||||
setTextureRect(spriteAnimation.textureRect);
|
||||
spriteAnimation.clock.restart();
|
||||
|
||||
if (spriteAnimation.currframe == spriteAnimation.numFrames) {
|
||||
spriteAnimation.isPlayed = true;
|
||||
spriteAnimation.currframe = 0;
|
||||
|
||||
spriteAnimation.textureRect.left = 0;
|
||||
spriteAnimation.textureRect.top = 0;
|
||||
}
|
||||
|
||||
spriteAnimation.clock.restart();
|
||||
}
|
||||
}
|
||||
|
||||
if (spriteRider.sprite != nullptr) {
|
||||
if (spriteRider.followsPosition) spriteRider.sprite->setPosition(spritePhysics.xPos, spritePhysics.yPos);
|
||||
|
||||
if (spriteRider.followsDirection) spriteRider.sprite->setDirection(spritePhysics.direction);
|
||||
}
|
||||
|
||||
setPosition(spritePhysics.xPos, spritePhysics.yPos);
|
||||
setRotation(-spritePhysics.direction);
|
||||
}
|
||||
|
||||
void accelerate(float override = 0, bool ignoreMax = false) {
|
||||
if (override != 0) spritePhysics.velocity += override;
|
||||
else spritePhysics.velocity += spritePhysics.acceleration;
|
||||
|
||||
if (!ignoreMax && spritePhysics.velocity > spritePhysics.maxVelocity) spritePhysics.velocity = spritePhysics.maxVelocity;
|
||||
if (!ignoreMax && spritePhysics.velocity < spritePhysics.minVelocity) spritePhysics.velocity = spritePhysics.minVelocity;
|
||||
}
|
||||
|
||||
void rotAccel(float override = 0, bool ignoreMax = false) {
|
||||
if (override != 0) spritePhysics.rotVelocity += override;
|
||||
else spritePhysics.rotVelocity += spritePhysics.rotAcceleration;
|
||||
|
||||
if (!ignoreMax && spritePhysics.rotVelocity > spritePhysics.maxRotVelocity) spritePhysics.rotVelocity = spritePhysics.maxRotVelocity;
|
||||
else if (!ignoreMax && -spritePhysics.rotVelocity > spritePhysics.maxRotVelocity) spritePhysics.rotVelocity = -spritePhysics.maxRotVelocity;
|
||||
}
|
||||
|
||||
void turn(float degrees) {
|
||||
spritePhysics.direction -= degrees;
|
||||
|
||||
setRotation(-spritePhysics.direction);
|
||||
}
|
||||
|
||||
float getXPos() {
|
||||
return spritePhysics.xPos;
|
||||
}
|
||||
|
||||
float getYPos() {
|
||||
return spritePhysics.yPos;
|
||||
}
|
||||
|
||||
void setPosition(float xPos, float yPos) {
|
||||
spritePhysics.xPos = xPos;
|
||||
spritePhysics.yPos = yPos;
|
||||
|
||||
sf::Sprite::setPosition(sf::Vector2f(xPos, yPos));
|
||||
}
|
||||
|
||||
void setPosition(const sf::Vector2f &vec) {
|
||||
spritePhysics.xPos = vec.x;
|
||||
spritePhysics.yPos = vec.y;
|
||||
|
||||
sf::Sprite::setPosition(vec);
|
||||
}
|
||||
|
||||
float getDirection() {
|
||||
return spritePhysics.direction;
|
||||
}
|
||||
|
||||
void setDirection(float angle) {
|
||||
spritePhysics.direction = angle;
|
||||
|
||||
setRotation(-angle);
|
||||
}
|
||||
|
||||
void setVelocity(float velo) {
|
||||
spritePhysics.velocity = velo;
|
||||
}
|
||||
|
||||
float getVelocity() {
|
||||
return spritePhysics.velocity;
|
||||
}
|
||||
|
||||
float getRotVelocity() {
|
||||
return spritePhysics.rotVelocity;
|
||||
};
|
||||
|
||||
void setMaxVelocity(float velo) {
|
||||
spritePhysics.maxVelocity = velo;
|
||||
}
|
||||
|
||||
void setMinVelocity(float velo) {
|
||||
spritePhysics.minVelocity = velo;
|
||||
}
|
||||
|
||||
void setMaxRotVelocity(float velo) {
|
||||
spritePhysics.maxRotVelocity = velo;
|
||||
}
|
||||
|
||||
void setEdgeBehavior(EdgeBehavior behavior) {
|
||||
edgeBehavior = behavior;
|
||||
}
|
||||
|
||||
bool toBeErased() const {
|
||||
return toErase;
|
||||
}
|
||||
|
||||
void setRider(MySprite* sprite) {
|
||||
spriteRider.sprite = sprite;
|
||||
}
|
||||
|
||||
Rider getRider() {
|
||||
return spriteRider;
|
||||
}
|
||||
|
||||
Animation getAnimation() {
|
||||
return spriteAnimation;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif //SFML_TEMPLATE_SPRITE_H
|
||||
87
Ship.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
//
|
||||
// Created by benmo on 9/25/2020.
|
||||
//
|
||||
|
||||
#ifndef SFML_TEMPLATE_SHIP_H
|
||||
#define SFML_TEMPLATE_SHIP_H
|
||||
|
||||
|
||||
class Ship : public MySprite {
|
||||
public:
|
||||
Ship(const sf::Texture &texture, float scale, float xPos, float yPos, float velocity, float direction) : MySprite(texture, scale, xPos, yPos, velocity, direction) {}
|
||||
|
||||
static void shoot(std::vector<MySprite*>* projectiles, Sound &sound, sf::Texture &texture, float scale, float xPos, float yPos, float velocity, float direction) {
|
||||
projectiles->push_back(new MySprite(texture, scale, xPos, yPos, velocity, direction));
|
||||
sound.play();
|
||||
}
|
||||
|
||||
bool hit(RenderWindow &window, vector<MySprite*> &animations, Texture &explosionTexture, default_random_engine &gen, Texture &shieldTexture, int scale, Clock &timer) {
|
||||
uniform_int_distribution<int> angle(0, 359);
|
||||
animations.push_back(new MySprite(explosionTexture, 100, getXPos(), getYPos(), 0, angle(gen)));
|
||||
animations[animations.size() - 1]->makeAnimated(5, 5, 0.01,23);
|
||||
|
||||
setPosition(window.getSize().x/2, window.getSize().y/2);
|
||||
setDirection(0);
|
||||
setVelocity(0);
|
||||
lives--;
|
||||
setShield(true, &shieldTexture, scale, &timer);
|
||||
|
||||
return lives <= 0;
|
||||
}
|
||||
|
||||
void newLife(vector<Drawable*> &gui, Texture &life, RenderWindow &window, Sound &sound) {
|
||||
setNumLivesAdded(getNumLivesAdded() + 1);
|
||||
setLives(getLives() + 1);
|
||||
gui.insert(gui.begin() + getLives(),new MySprite(life, 20, window.getSize().x - ((getLives()-1)*40 + 25), 25, 0, 270));
|
||||
sound.play();
|
||||
}
|
||||
|
||||
int getLives() const {
|
||||
return lives;
|
||||
}
|
||||
|
||||
void setLives(int lives) {
|
||||
this->lives = lives;
|
||||
}
|
||||
|
||||
void setShield(bool shield, Texture* texture = nullptr, int scale = 0, Clock* timer = nullptr) {
|
||||
this->shield = shield;
|
||||
|
||||
if (shield) {
|
||||
setRider(new MySprite(*texture, scale));
|
||||
timer->restart();
|
||||
} else
|
||||
setRider(nullptr);
|
||||
}
|
||||
|
||||
bool hasShield() const {
|
||||
return shield;
|
||||
}
|
||||
|
||||
int getScore() const {
|
||||
return score;
|
||||
}
|
||||
|
||||
void setScore(int score) {
|
||||
this->score = score;
|
||||
}
|
||||
|
||||
int getNewLifeScore() const {
|
||||
return newLifeScore;
|
||||
}
|
||||
|
||||
int getNumLivesAdded() const {
|
||||
return newLives;
|
||||
}
|
||||
|
||||
void setNumLivesAdded(int numLives) {
|
||||
newLives = numLives;
|
||||
}
|
||||
private:
|
||||
int lives = 3, score = 0, newLifeScore = 10000, newLives = 0;
|
||||
|
||||
bool shield;
|
||||
};
|
||||
|
||||
|
||||
#endif //SFML_TEMPLATE_SHIP_H
|
||||
BIN
data/Asteroids/(1).png
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
data/Asteroids/(10).png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
data/Asteroids/(11).png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
data/Asteroids/(12).png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
data/Asteroids/(13).png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
data/Asteroids/(14).png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
data/Asteroids/(15).png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
data/Asteroids/(16).png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
data/Asteroids/(17).png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
data/Asteroids/(18).png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
data/Asteroids/(19).png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
data/Asteroids/(2).png
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
data/Asteroids/(20).png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
data/Asteroids/(21).png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
data/Asteroids/(22).png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
data/Asteroids/(23).png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
data/Asteroids/(3).png
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
data/Asteroids/(4).png
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
data/Asteroids/(5).png
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
data/Asteroids/(6).png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
data/Asteroids/(7).png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
data/Asteroids/(8).png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
data/Asteroids/(9).png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
data/Fonts/Monkirta Pursuit NC.ttf
Normal file
BIN
data/Fonts/Oxanium-Light.ttf
Normal file
BIN
data/Fonts/SKoME.TTF
Normal file
BIN
data/Fonts/Sk.ttf
Normal file
BIN
data/Fonts/Xolonium-Bold.ttf
Normal file
BIN
data/Fonts/arial.ttf
Normal file
BIN
data/Gui/Armor_Icon.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
data/Gui/Backward_BTN.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
data/Gui/FuelBar.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
data/Gui/HP_Icon.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
data/Gui/LoadingBarEmpty.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
data/Gui/LoadingBarFull.png
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
data/Gui/Music.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
data/Gui/Sound.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
data/Gui/Speed_Icon.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
data/Gui/Stats_Bar.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
data/Gui/arrow.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
data/Gui/ball.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
data/Gui/button.png
Normal file
|
After Width: | Height: | Size: 8 KiB |
BIN
data/Gui/cloud.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
data/Gui/filter.xcf
Normal file
BIN
data/Gui/mapBox.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
data/Gui/money_bar.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
data/Gui/planetDialog.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
data/Gui/planetDialog.xcf
Normal file
BIN
data/Gui/smallButton.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
data/Gui/space.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
data/Gui/space.xcf
Normal file
BIN
data/Gui/unexplored.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
data/Gui/unexplored.xcf
Normal file
BIN
data/Gui/window.png
Normal file
|
After Width: | Height: | Size: 417 KiB |
BIN
data/Gui/windowSm.png
Normal file
|
After Width: | Height: | Size: 313 KiB |
BIN
data/Morgan Ben initials.png
Normal file
|
After Width: | Height: | Size: 6 KiB |
BIN
data/Ship.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
data/Sounds/Menu Loop.wav
Normal file
BIN
data/Sounds/Unknown Theme.wav
Normal file
BIN
data/Sounds/error.wav
Normal file
BIN
data/Sounds/explosions.wav
Normal file
BIN
data/Sounds/pew.wav
Normal file
BIN
data/Sounds/pling.wav
Normal file
BIN
data/Sounds/rollover.wav
Normal file
BIN
data/back.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
data/blue.png
Normal file
|
After Width: | Height: | Size: 4.6 MiB |
BIN
data/bubble.png
Normal file
|
After Width: | Height: | Size: 435 KiB |
BIN
data/explodeSheet.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
29
main.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include <iostream> // for standard input/output
|
||||
#include <random>
|
||||
using namespace std; // using the standard namespace
|
||||
|
||||
#include <SFML/Graphics.hpp> // include the SFML Graphics Library
|
||||
#include <SFML/Audio.hpp>
|
||||
#include "Collision.h"
|
||||
using namespace sf; // using the sf namespace
|
||||
|
||||
#include "MySprite.h"
|
||||
#include "Ship.h"
|
||||
#include "Asteroid.h"
|
||||
#include "Menu.h"
|
||||
#include "Game.h"
|
||||
|
||||
int main() {
|
||||
bool play = true;
|
||||
|
||||
while (play) {
|
||||
Menu menu;
|
||||
if (menu.result == EXIT_SUCCESS) {
|
||||
Game game;
|
||||
if (game.result == 1) play = false;
|
||||
}
|
||||
else play = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||