-
-
Save sillyboyization/216b6898582c2d1ec6e0d22832be2d38 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SFML/Graphics.hpp> | |
#include <SFML/System.hpp> | |
#include <vector> | |
#include <list> | |
#include <string> | |
#include <iostream> | |
#include <algorithm> | |
enum EntityType { | |
PLAYER = 0x0, | |
ENEMY = 0x10, | |
SKELETON = 0x01, | |
PARTICLE = 0x20, | |
PROJECTILE = 0x30, | |
BULLET = 0x01 | |
}; | |
enum EntityState { | |
IDLE = 0x001, | |
FRONT_WALK = 0x003, | |
RIGHT_WALK = 0x004, | |
LEFT_WALK = 0x006 | |
}; | |
typedef sf::Int64 int64; | |
typedef struct { | |
int type; | |
sf::Vector3f pos; | |
sf::Vector3f velocity; | |
sf::RectangleShape rect; | |
std::string name; | |
sf::Clock clock; | |
sf::Clock clock2; | |
int idx; | |
int total_health; | |
int health; | |
int state; | |
} Entity; | |
float lerp(float, float, float); | |
bool render_order_sort(Entity*, Entity*); | |
void do_damage_screen(); | |
void shoot(); | |
bool shoot_flag = false; | |
bool shot = false; | |
bool dmg_flag = false; | |
bool player_dying = false; | |
int game_state = 1; | |
int phase = 0; | |
int score = 0; | |
float near_view = 5; | |
float far_view = 100; | |
float screen_center_x = 0.f; | |
float screen_center_y = 0.f; | |
float crosshair_speed = 250.f; | |
int main() | |
{ | |
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Window"); | |
sf::View gview = window.getView(); | |
screen_center_x = window.getSize().x / 2.f; | |
screen_center_y = window.getSize().y / 2.f; | |
std::list<Entity*> ents; | |
/* | |
-- Skeleton -- | |
Front | |
97, 15, 13, 17 | |
113, 15, 13, 17 | |
129, 15, 13, 17 | |
-- Glow Pew Pew -- | |
95, 159, 14 14 | |
/*/ | |
sf::Image base_image; | |
if (!base_image.loadFromFile("rpg_sprite_sheet.png")) { | |
std::cout << "Texture Missing!: The main texture file is missing, redownload the application." << std::endl; | |
} | |
sf::Texture | |
skele_tex_1, | |
skele_tex_2, | |
skele_tex_3, | |
skele_tex_4, | |
skele_tex_5, | |
skele_tex_6, | |
skele_tex_7, | |
skele_tex_8, | |
skele_tex_9, | |
cross_hair, | |
pew_pew, | |
heart1, heart2, | |
floor_tex; | |
skele_tex_1.loadFromImage(base_image, sf::IntRect(97, 15, 13, 17)); | |
skele_tex_2.loadFromImage(base_image, sf::IntRect(113, 15, 13, 17)); | |
skele_tex_3.loadFromImage(base_image, sf::IntRect(129, 15, 13, 17)); | |
skele_tex_4.loadFromImage(base_image, sf::IntRect(97, 79, 13, 17)); | |
skele_tex_5.loadFromImage(base_image, sf::IntRect(113, 79, 13, 17)); | |
skele_tex_6.loadFromImage(base_image, sf::IntRect(129, 79, 13, 17)); | |
skele_tex_7.loadFromImage(base_image, sf::IntRect(97, 111, 13, 17)); | |
skele_tex_8.loadFromImage(base_image, sf::IntRect(113, 111, 13, 17)); | |
skele_tex_9.loadFromImage(base_image, sf::IntRect(129, 111, 13, 17)); | |
cross_hair.loadFromImage(base_image, sf::IntRect(183, 134, 53, 53)); | |
pew_pew.loadFromImage(base_image, sf::IntRect(95, 159, 14, 14)); | |
heart1.loadFromImage(base_image, sf::IntRect(95, 145, 13, 11)); | |
heart2.loadFromImage(base_image, sf::IntRect(109, 145, 13, 11)); | |
floor_tex.loadFromImage(base_image, sf::IntRect(124, 146, 23, 18)); | |
sf::Texture *texture_bank[9] = { | |
&skele_tex_1, | |
&skele_tex_2, | |
&skele_tex_3, | |
&skele_tex_4, | |
&skele_tex_5, | |
&skele_tex_6, | |
&skele_tex_7, | |
&skele_tex_8, | |
&skele_tex_9 | |
}; | |
int texture_indicies[0xFFF][3]; | |
int skel = EntityType::ENEMY | EntityType::SKELETON; | |
texture_indicies[skel | EntityState::FRONT_WALK][0] = 0; | |
texture_indicies[skel | EntityState::FRONT_WALK][1] = 2; | |
texture_indicies[skel | EntityState::FRONT_WALK][2] = 350; | |
texture_indicies[skel | EntityState::RIGHT_WALK][0] = 3; | |
texture_indicies[skel | EntityState::RIGHT_WALK][1] = 5; | |
texture_indicies[skel | EntityState::RIGHT_WALK][2] = 350; | |
texture_indicies[skel | EntityState::LEFT_WALK][0] = 6; | |
texture_indicies[skel | EntityState::LEFT_WALK][1] = 8; | |
texture_indicies[skel | EntityState::LEFT_WALK][2] = 350; | |
texture_indicies[skel | EntityState::IDLE][0] = 0; | |
texture_indicies[skel | EntityState::IDLE][1] = 0; | |
texture_indicies[skel | EntityState::IDLE][2] = 200; | |
sf::RectangleShape player_rect(sf::Vector2f(50.f, 50.f)); | |
sf::RectangleShape enim_rect(sf::Vector2f(30.f, 26.f)); | |
sf::RectangleShape enim_rect2(sf::Vector2f(25.f, 50.f)); | |
enim_rect.setTexture(&skele_tex_1); | |
enim_rect2.setFillColor(sf::Color::Blue); | |
sf::RectangleShape crosshair_rect(sf::Vector2f(53.f, 53.f)); | |
crosshair_rect.setTexture(&cross_hair); | |
crosshair_rect.setFillColor(sf::Color::Red); | |
crosshair_rect.setOrigin(crosshair_rect.getSize() / 2.f); | |
crosshair_rect.setPosition(gview.getCenter()); | |
sf::RectangleShape pew_pew_rect(sf::Vector2f(75.f, 75.f)); | |
pew_pew_rect.setTexture(&pew_pew); | |
pew_pew_rect.setOrigin(pew_pew_rect.getSize() / 2.f); | |
sf::Color pew_pew_color(255, 255, 255, 200); | |
pew_pew_rect.setFillColor(sf::Color(0, 0, 0, 0)); | |
sf::Clock pew_limit_clock; | |
sf::RectangleShape damage_screen(gview.getSize()); | |
sf::Color damage_red(255, 0, 0, 100); | |
sf::Color trans_red(255, 0, 0, 0); | |
damage_screen.setFillColor(trans_red); | |
sf::Font font; | |
sf::Text game_over_text, retry_text; | |
font.loadFromFile("PressStart2P.ttf"); | |
game_over_text.setFont(font); | |
game_over_text.setString("YOU DIED"); | |
sf::FloatRect got_size = game_over_text.getLocalBounds(); | |
game_over_text.setOrigin(got_size.width / 2.f, got_size.height / 2.f); | |
game_over_text.setPosition(gview.getCenter()); | |
// game_over_text.setFillColor(sf::Color(255, 255/*, 255, 0)); | |
//*/ | |
retry_text.setFont(font); | |
retry_text.setString("Shoot this message to try again."); | |
retry_text.setFillColor(sf::Color(150, 0, 0, 255)); | |
retry_text.setCharacterSize(20); | |
sf::FloatRect rt_size = retry_text.getGlobalBounds(); | |
retry_text.setPosition(gview.getCenter().x - rt_size.width / 2.f, gview.getCenter().y - rt_size.height / 2.f); | |
sf::ConvexShape floor; | |
floor.setPointCount(4); | |
sf::RectangleShape hud_rect(sf::Vector2f(800, 150)); | |
hud_rect.setFillColor(sf::Color::Black); | |
hud_rect.setPosition(0, 450); | |
sf::Text hp, lz, tscore; | |
sf::RectangleShape hp_bar(sf::Vector2f(700, 25)), lz_bar(sf::Vector2f(700, 25)); | |
hp.setFont(font); | |
hp.setString("HP:"); | |
hp.setPosition(hud_rect.getPosition() + sf::Vector2f(5.f, 5.f)); | |
hp_bar.setPosition(hp.getPosition() + sf::Vector2f(hp.getGlobalBounds().width + 10, 0.f)); | |
hp_bar.setFillColor(sf::Color::Red); | |
lz.setFont(font); | |
lz.setString("LZ:"); | |
lz.setPosition(hp.getPosition() + sf::Vector2f(0.f, 30.f)); | |
lz_bar.setPosition(hp_bar.getPosition().x, lz.getPosition().y); | |
lz_bar.setFillColor(sf::Color::Blue); | |
tscore.setFont(font); | |
tscore.setString("Score:" + std::to_string(score)); | |
tscore.setPosition(hp.getPosition() + sf::Vector2f(0.f, 60.f)); | |
floor.setPoint(0, sf::Vector2f(0.f, 311.f)); | |
floor.setPoint(1, sf::Vector2f(800.f, 311.f)); | |
floor.setPoint(2, sf::Vector2f(800.f, 600.f)); | |
floor.setPoint(3, sf::Vector2f(0.f, 600.f)); | |
/*floor.setPoint(0, sf::Vector2f(300.f, 310.f)); | |
floor.setPoint(1, sf::Vector2f(500.f, 310.f)); | |
floor.setPoint(2, sf::Vector2f(1200.f, 600.f)); | |
floor.setPoint(3, sf::Vector2f(-400.f, 600.f)); | |
*///floor.setFillColor(sf::Color::Green); | |
floor.setTexture(&floor_tex); | |
floor.setOutlineColor(sf::Color::Black); | |
floor.setOutlineThickness(2); | |
sf::Color gray(25, 25, 25); | |
sf::ConvexShape ceiling; | |
ceiling.setPointCount(4); | |
ceiling.setPoint(0, sf::Vector2f(0.f, 0.f)); | |
ceiling.setPoint(1, sf::Vector2f(800.f, 0.f)); | |
ceiling.setPoint(2, sf::Vector2f(800.f, 269.f)); | |
ceiling.setPoint(3, sf::Vector2f(0.f, 269.f)); | |
ceiling.setFillColor(gray); | |
ceiling.setOutlineColor(sf::Color::Black); | |
ceiling.setOutlineThickness(2); | |
sf::ConvexShape wall_left; | |
wall_left.setPointCount(4); | |
wall_left.setPoint(0, sf::Vector2f(-400.f, -10.f)); | |
wall_left.setPoint(1, sf::Vector2f(300.f, 270.f)); | |
wall_left.setPoint(2, sf::Vector2f(300.f, 310.f)); | |
wall_left.setPoint(3, sf::Vector2f(-400.f, 600.f)); | |
wall_left.setFillColor(gray); | |
//floor.setTexture(&floor_tex); | |
wall_left.setOutlineColor(sf::Color::Black); | |
wall_left.setOutlineThickness(2); | |
sf::ConvexShape wall_right; | |
wall_right.setPointCount(4); | |
wall_right.setPoint(0, sf::Vector2f(500.f, 270.f)); | |
wall_right.setPoint(1, sf::Vector2f(1200.f,-10.f)); | |
wall_right.setPoint(2, sf::Vector2f(1200.f, 600.f)); | |
wall_right.setPoint(3, sf::Vector2f(500.f, 310.f)); | |
wall_right.setFillColor(gray); | |
//floor.setTexture(&floor_tex); | |
wall_right.setOutlineColor(sf::Color::Black); | |
wall_right.setOutlineThickness(2); | |
//std::cout << got_size.width << "\n"; | |
//enim_rect.setFillColor(sf::Color::Green); | |
Entity player{ | |
EntityType::PLAYER, | |
sf::Vector3f(0.f, 0.f, 5.f), | |
sf::Vector3f(0.f, 0.f, 0.f), | |
player_rect, | |
"Player1", | |
sf::Clock(), | |
sf::Clock(), | |
0, | |
10, | |
10, | |
EntityState::FRONT_WALK | |
}; | |
Entity * player_ref = &player; | |
float player_rot = 0.f; | |
sf::Vector2f winCenter = (sf::Vector2f)window.getSize() / 2.f; | |
float pcircle_rad = 250.f; | |
sf::CircleShape s(pcircle_rad); | |
window.setFramerateLimit(60); | |
s.setFillColor(sf::Color::Transparent); | |
s.setOutlineColor(sf::Color::White); | |
s.setOutlineThickness(1.0f); | |
sf::Clock deltaTimer, fpsTimer; | |
s.setPosition( | |
window.getSize().x / 2.f - pcircle_rad, | |
window.getSize().y / 2.f - pcircle_rad | |
); | |
while (window.isOpen()) | |
{ | |
sf::Time _ttime = deltaTimer.restart(); | |
float delta = _ttime.asSeconds(); | |
if (fpsTimer.getElapsedTime().asMilliseconds() > 1000) { | |
std::string fpsTitle = "FPS: " + std::to_string((int)(1 / delta)); | |
fpsTimer.restart(); | |
window.setTitle(fpsTitle); | |
} | |
sf::Event event; | |
while (window.pollEvent(event)) | |
{ | |
if (event.type == sf::Event::Closed) | |
window.close(); | |
} | |
window.clear(); | |
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { | |
crosshair_rect.move(-crosshair_speed * delta, 0.f); | |
} | |
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) { | |
crosshair_rect.move(crosshair_speed* delta, 0.f); | |
} | |
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) { | |
crosshair_rect.move(0.f, -crosshair_speed* delta); | |
} | |
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) { | |
crosshair_rect.move(0.f, crosshair_speed* delta); | |
} | |
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) { | |
shoot(); | |
} | |
crosshair_rect.rotate(50.f * delta); | |
pew_pew_rect.setPosition(crosshair_rect.getPosition()); | |
std::vector<Entity*> to_remove; | |
if (game_state == 1) { | |
if (phase == 0) { | |
Entity enemy{ | |
EntityType::ENEMY | EntityType::SKELETON, | |
sf::Vector3f(0.f, 0.f, 120.f), | |
sf::Vector3f(0.f, 0.f, 0.f), | |
enim_rect, | |
"Skelington", | |
sf::Clock(), | |
sf::Clock(), | |
0, | |
10, | |
3, | |
EntityState::FRONT_WALK | |
}; | |
Entity enemy2{ | |
EntityType::ENEMY | EntityType::SKELETON, | |
sf::Vector3f(20.f, 0.f, 200.f), | |
sf::Vector3f(0.f, 0.f, 0.f), | |
enim_rect, | |
"Enemy2", | |
sf::Clock(), | |
sf::Clock(), | |
0, | |
10, | |
10, | |
EntityState::FRONT_WALK | |
}; | |
Entity enemy3{ | |
EntityType::ENEMY | EntityType::SKELETON, | |
sf::Vector3f(-20.f, 0.f, 90.f), | |
sf::Vector3f(0.f, 0.f, 0.f), | |
enim_rect, | |
"Enemy3", | |
sf::Clock(), | |
sf::Clock(), | |
0, | |
10, | |
3, | |
EntityState::FRONT_WALK | |
}; | |
ents.push_back(&player); | |
ents.push_back(&enemy); | |
ents.push_back(&enemy2); | |
ents.push_back(&enemy3); | |
phase = 1; | |
} | |
else if (phase == 1) { | |
float loc_near = .0f, loc_far = .0f; | |
window.draw(floor); | |
window.draw(ceiling); | |
window.draw(wall_left); | |
window.draw(wall_right); | |
for (Entity * e : ents) { | |
bool draw = true; | |
int ent_type = e->type >> 4; | |
int ent_sub_type = e->type & 0x0F; | |
int64 elapsed = e->clock.getElapsedTime().asMilliseconds(); | |
//Player | |
if (ent_type == 0) | |
draw = false; | |
loc_near = player_ref->pos.z + near_view; | |
loc_far = player_ref->pos.z + far_view; | |
if (player_ref->health <= 0) { | |
player_dying = true; | |
game_state = 2; | |
} | |
//Enemy & Others | |
if (ent_type != 0) { | |
if (ent_type == 1) { | |
if (e->health > 0) { | |
if (e->state == EntityState::FRONT_WALK) { | |
if (e->pos.z > loc_near) { | |
e->pos.z -= 25.f * delta; | |
} | |
else { | |
// Melee | |
if (e->clock2.getElapsedTime().asMilliseconds() > 1500) { | |
e->clock2.restart(); | |
std::cout << "HP: " << player_ref->health << "\n"; | |
do_damage_screen(); | |
player_ref->health -= 1; | |
} | |
} | |
if (e->idx == 2) e->idx = 0; | |
} | |
} | |
else { | |
if (e->pos.z < loc_far) { | |
sf::Color tmpCol = e->rect.getFillColor(); | |
e->rect.setFillColor(tmpCol - sf::Color(0, 0, 0, 20)); | |
e->pos.z += 1; | |
} | |
else { to_remove.push_back(e); } | |
} | |
} | |
if (e->health <= 0 && e->state != EntityState::IDLE) { | |
score += e->total_health; | |
e->state = EntityState::IDLE; | |
} | |
float scaleX = lerp(.5f, 10.f, loc_near / e->pos.z); | |
//std::cout << "Near: " << loc_near << "\n" << "Far: " << loc_far << "\n"; | |
//std::cout << e->pos.z << "\n"; | |
e->rect.setScale(scaleX, scaleX); | |
if (scaleX < 0.f) draw = false; | |
sf::Vector2f artificial_pos( | |
e->pos.x + screen_center_x - (e->rect.getSize().x * scaleX / 2) + e->pos.x * scaleX, | |
e->pos.y + screen_center_y - (e->rect.getSize().y * scaleX / 2) + e->pos.y * scaleX); | |
e->pos += e->velocity; | |
e->rect.setPosition(artificial_pos); | |
/* | |
if (e->pos.z < loc_near) | |
draw = false;*/ | |
} | |
int tex_index = e->type | e->state; | |
if (draw) { | |
if (elapsed > texture_indicies[tex_index][2] && ent_sub_type != 0) { | |
if (texture_indicies[tex_index][1] > 0) { | |
//e->idx = (e->idx++ + texture_indicies[tex_index][0] % texture_indicies[tex_index][1]); | |
if (e->idx < texture_indicies[tex_index][0]) | |
e->idx = texture_indicies[tex_index][0]; | |
if (e->idx < texture_indicies[tex_index][1]) e->idx++; | |
else e->idx = texture_indicies[tex_index][0]; | |
} | |
else | |
e->idx = texture_indicies[tex_index][0]; | |
e->rect.setTexture(texture_bank[e->idx]); | |
e->clock.restart(); | |
} | |
window.draw(e->rect); | |
} | |
} | |
//window.draw(s); | |
sf::Color col = damage_screen.getFillColor(); | |
if (col.a > 0) { | |
window.draw(damage_screen); | |
col.a -= 5; | |
damage_screen.setFillColor(col); | |
} | |
if (dmg_flag) { | |
damage_screen.setFillColor(damage_red); | |
dmg_flag = false; | |
} | |
window.draw(hud_rect); | |
window.draw(hp); | |
hp_bar.setSize( | |
sf::Vector2f(lerp(0, 700, (float)player_ref->health / (float)player_ref->total_health), | |
hp_bar.getSize().y)); | |
window.draw(hp_bar); | |
window.draw(lz); | |
window.draw(lz_bar); | |
tscore.setString("Score:" + std::to_string(score)); | |
window.draw(tscore); | |
} | |
} | |
else if (game_state == 2) { | |
if (player_dying) { | |
if (phase == 0) { | |
sf::Color col = game_over_text.getFillColor(); | |
if (col.a < 255) { | |
col.a += 5; | |
game_over_text.setFillColor(col); | |
} | |
else phase = 1; | |
} | |
if (phase == 1) { | |
if (game_over_text.getPosition().y > window.getView().getSize().y * 0.4f) | |
game_over_text.move(0.f, -1.f); | |
else | |
phase = 2; | |
} | |
if (phase == 2) | |
window.draw(retry_text); | |
window.draw(game_over_text); | |
} | |
} | |
sf::Color col2 = pew_pew_rect.getFillColor(); | |
if (col2.a > 0) { | |
window.draw(pew_pew_rect); | |
col2 -= sf::Color(0, 0, 0, 10); | |
pew_pew_rect.setFillColor(col2); | |
} | |
if (shoot_flag && !shot) { | |
pew_pew_rect.setFillColor(pew_pew_color); | |
shoot_flag = false; | |
shot = true; | |
pew_limit_clock.restart(); | |
score--; | |
for (Entity* pew_target : ents) { | |
if (pew_target->type != 0) { | |
sf::Vector2f hc = crosshair_rect.getPosition(); | |
sf::FloatRect tg = pew_target->rect.getGlobalBounds(); | |
if (hc.x > tg.left && hc.x < tg.left + tg.width && | |
hc.y > tg.top && hc.y < tg.left + tg.height) { | |
//std::cout << pew_target->name << " was shot!\n"; | |
pew_target->pos.z += 5; | |
pew_target->health -= 1; | |
break; | |
} | |
} | |
} | |
} | |
if (pew_limit_clock.getElapsedTime().asMilliseconds() > 200) { | |
shot = false; | |
pew_limit_clock.restart(); | |
} | |
for (Entity *rem : to_remove) | |
ents.erase(std::remove(ents.begin(), ents.end(), rem), ents.end()); | |
ents.sort(render_order_sort); | |
window.draw(crosshair_rect); | |
window.display(); | |
} | |
return 0; | |
} | |
void do_damage_screen() { | |
dmg_flag = true; | |
} | |
void shoot() { | |
shoot_flag = true; | |
} | |
float lerp(float v1, float v2, float p) { | |
return v1 + (v2 - v1) * p; | |
} | |
bool render_order_sort(Entity * a, Entity * b) { | |
return a->pos.z > b->pos.z; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment