1 #include <GL/glew.h>
2 
3 #include "blackHole.h"
4 #include "pathPlanner.h"
5 #include "main.h"
6 #include <SFML/OpenGL.hpp>
7 
8 #include "scriptInterface.h"
9 #include "glObjects.h"
10 #include "shaderRegistry.h"
11 
12 
13 #if FEATURE_3D_RENDERING
14 struct VertexAndTexCoords
15 {
16     sf::Vector3f vertex;
17     sf::Vector2f texcoords;
18 };
19 #endif
20 
21 /// A blackhole has a 5km radius where it pulls in all near objects. At the center of the black hole everything gets a lot of damage.
22 /// Which will lead to the eventual destruction of said object.
REGISTER_SCRIPT_SUBCLASS(BlackHole,SpaceObject)23 REGISTER_SCRIPT_SUBCLASS(BlackHole, SpaceObject)
24 {
25 }
26 
27 REGISTER_MULTIPLAYER_CLASS(BlackHole, "BlackHole");
BlackHole()28 BlackHole::BlackHole()
29 : SpaceObject(5000, "BlackHole")
30 {
31     update_delta = 0.0;
32     PathPlannerManager::getInstance()->addAvoidObject(this, 7000);
33     setRadarSignatureInfo(0.9, 0, 0);
34 }
35 
update(float delta)36 void BlackHole::update(float delta)
37 {
38     update_delta = delta;
39 }
40 
41 #if FEATURE_3D_RENDERING
draw3DTransparent()42 void BlackHole::draw3DTransparent()
43 {
44     static std::array<VertexAndTexCoords, 4> quad{
45         sf::Vector3f(), {0.f, 1.f},
46         sf::Vector3f(), {1.f, 1.f},
47         sf::Vector3f(), {1.f, 0.f},
48         sf::Vector3f(), {0.f, 0.f}
49     };
50 
51     glBindTexture(GL_TEXTURE_2D, textureManager.getTexture("blackHole3d.png")->getNativeHandle());
52     ShaderRegistry::ScopedShader shader(ShaderRegistry::Shaders::Billboard);
53 
54     glUniform4f(shader.get().uniform(ShaderRegistry::Uniforms::Color), 1.f, 1.f, 1.f, 5000.f);
55     gl::ScopedVertexAttribArray positions(shader.get().attribute(ShaderRegistry::Attributes::Position));
56     gl::ScopedVertexAttribArray texcoords(shader.get().attribute(ShaderRegistry::Attributes::Texcoords));
57 
58     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
59 
60     glVertexAttribPointer(positions.get(), 3, GL_FLOAT, GL_FALSE, sizeof(VertexAndTexCoords), (GLvoid*)quad.data());
61     glVertexAttribPointer(texcoords.get(), 2, GL_FLOAT, GL_FALSE, sizeof(VertexAndTexCoords), (GLvoid*)((char*)quad.data() + sizeof(sf::Vector3f)));
62 
63     std::initializer_list<uint8_t> indices = { 0, 2, 1, 0, 3, 2 };
64     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, std::begin(indices));
65     glBlendFunc(GL_ONE, GL_ONE);
66 }
67 #endif
68 
drawOnRadar(sf::RenderTarget & window,sf::Vector2f position,float scale,float rotation,bool long_range)69 void BlackHole::drawOnRadar(sf::RenderTarget& window, sf::Vector2f position, float scale, float rotation, bool long_range)
70 {
71     sf::Sprite object_sprite;
72     textureManager.setTexture(object_sprite, "blackHole.png");
73     object_sprite.setRotation(getRotation());
74     object_sprite.setPosition(position);
75     float size = getRadius() * scale / object_sprite.getTextureRect().width * 2;
76     object_sprite.setScale(size, size);
77     object_sprite.setColor(sf::Color(64, 64, 255));
78     window.draw(object_sprite);
79     object_sprite.setColor(sf::Color(0, 0, 0));
80     window.draw(object_sprite);
81 }
82 
collide(Collisionable * target,float collision_force)83 void BlackHole::collide(Collisionable* target, float collision_force)
84 {
85     if (update_delta == 0.0)
86         return;
87 
88     P<SpaceObject> obj = P<Collisionable>(target);
89     if (!obj) return;
90     if (!obj->hasWeight()) { return; } // the object is not affected by gravitation
91 
92     sf::Vector2f diff = getPosition() - target->getPosition();
93     float distance = sf::length(diff);
94     float force = (getRadius() * getRadius() * 50.0f) / (distance * distance);
95     DamageInfo info(NULL, DT_Kinetic, getPosition());
96     if (force > 10000.0)
97     {
98         force = 10000.0;
99         if (isServer())
100         {
101             obj->takeDamage(100000.0, info); //try to destroy the object by inflicting a huge amount of damage
102             if (target)
103             {
104                 target->destroy();
105                 return;
106             }
107         }
108     }
109     if (force > 100.0 && isServer())
110     {
111         obj->takeDamage(force * update_delta / 10.0f, info);
112     }
113     if (!obj) {return;}
114     obj->setPosition(obj->getPosition() + diff / distance * update_delta * force);
115 }
116