game_input_manager.cpp 12.7 KB
Newer Older
1
2
#include <glm/gtx/string_cast.hpp>

Elias Broschin's avatar
Elias Broschin committed
3
4
5
6
7
8
9
10
11
12
#include <gameplay/game_input_manager.h>
#include <core/engine.hpp>
#include <SDL.h>
#include <ecs/entity.hpp>
#include <physics/movement/movement_component.h>
#include <gameplay/game_play_system.h>
#include <gameplay/level_manager.h>
#include <input/input.hpp>
#include <rendering/staticmesh_component.hpp>
#include <rendering/camera_component.hpp>
Elias Broschin's avatar
Elias Broschin committed
13
#include <physics/collision/ray.h>
14
#include <physics/collision/sphere.h>
Elias Broschin's avatar
Elias Broschin committed
15
16
#include <physics/physics_system.h>
#include <graphics/graphics_system.hpp>
17
#include <audio/audio.hpp>
Elias Broschin's avatar
Elias Broschin committed
18
#include <rendering/rendering_system.hpp>
grunt92's avatar
grunt92 committed
19
#include <physics/collision/object_type_component.h>
20
#include <audio/AudioEventHandler.hpp>
21
#include <util/logger.hpp>
22
#include <gameplay/item/player_item_manager.h>
Elias Broschin's avatar
Elias Broschin committed
23
#include <physics/collision/collision_component.h>
Elias Broschin's avatar
Elias Broschin committed
24
25
26

namespace gdw {

27
28
	const float game_input_manager::maximum_movement_distance = 13.0f;

29
	game_input_manager::game_input_manager(engine& engine):engine_(engine) {
30
31
32
33
34
35
36
		auto& input = engine_.input();
		//input.addMapping("test");
		input.addMapping("move_left");
		input.addMapping("move_right");
		input.addMapping("place_item");
		input.addMapping("beam_normal");
		input.addMapping("beam_inverse");
Elias Broschin's avatar
Elias Broschin committed
37
38
39
40
41
42
43
	}

	game_input_manager::~game_input_manager() {

	}

	void game_input_manager::update(float dt) {
Elias Broschin's avatar
merged    
Elias Broschin committed
44
45
		handle_key_input(dt);
		handle_mouse_input(dt);
Elias Broschin's avatar
Elias Broschin committed
46
47
	}

Elias Broschin's avatar
Elias Broschin committed
48
49
50
51
	glm::vec3 game_input_manager::get_world_mouse_pos() {
		auto& input = engine_.input();
		auto& level_manager = engine_.game_play_system().level_manager();

52
53
		float x = (float(input.positionX())/engine_.graphics_system().width()) * 2.0f -1;
		float y = (float(input.positionY())/engine_.graphics_system().height()) * 2.0f -1;
Elias Broschin's avatar
Elias Broschin committed
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

		auto cam = level_manager.camera()->component<camera_component>();
		auto camera = level_manager.camera();
		auto mouse_pos = glm::vec2(x, -y);
		auto inv_proj_view = glm::inverse(cam->projection_view());
		auto world_pos_near = inv_proj_view * glm::vec4(mouse_pos,0.1f,1.f);
		auto world_pos_far = inv_proj_view * glm::vec4(mouse_pos,0.9f,1.f);
		world_pos_near /= world_pos_near.w;
		world_pos_far /= world_pos_far.w;

		auto ray_dir = world_pos_far - world_pos_near;

		auto final_pos = world_pos_near + ray_dir;
		auto& entity_manager = engine_.entity_manager();

		auto plane_normal = glm::vec3(0,1,0);	//Hardcoded ground plane

		//HNF
72
		float d = glm::dot(glm::vec3(0.f, 0.f, 0.f) - glm::vec3(world_pos_near), plane_normal) / glm::dot(glm::vec3(glm::normalize(-ray_dir)), plane_normal);
Elias Broschin's avatar
Elias Broschin committed
73
74
75
76

		return camera->position()-glm::vec3((glm::normalize(ray_dir))*d);
	}

Elias Broschin's avatar
merged    
Elias Broschin committed
77
	void game_input_manager::handle_key_input(float dt) {
Jerry's avatar
Jerry committed
78
		auto& level_manager = engine_.game_play_system().level_manager();
Elias Broschin's avatar
Elias Broschin committed
79
80
81
82
		auto player = level_manager.player();

		auto move = player->component<movement_component>();
		if(!move) return;
Jerry's avatar
Jerry committed
83
		auto& input = engine_.input();
Elias Broschin's avatar
Elias Broschin committed
84

Elias Broschin's avatar
Elias Broschin committed
85
86
		constexpr float rotation_speed = 7.f;
		constexpr float turn_rate_modifier = 4.5f;
87

88
		/*if (input.isPressed("test")){
89
			log << "input test pressed" << std::endl;
90
		}*/
91

92
93
94
95
		/*if (input.isDown("test")){
			log << "pos: x:" << input.positionX() << " y:" << input.positionY() << std::endl;
			//log << "input test down" << std::endl;
		}*/
96

97
		/*if (input.isReleased("test")){
98
			log << "input test released" << std::endl;
99
		}*/
100

101
		if (input.isDown("move_left") && player->position().x > -maximum_movement_distance) {
Elias Broschin's avatar
Elias Broschin committed
102
103
104
105
106
107
108
109
			auto orientation = player->rotation()*glm::vec3(0,0,1);
			auto diff = std::abs(orientation.x - (-1.f)) + std::abs(orientation.z - (0.f));
			auto clamped = glm::clamp(diff/turn_rate_modifier, 0.f, 1.f);

			move->add_force(glm::vec3(-level_manager.player_speed()*(1.f-clamped), 0.f,0.f));

			if((orientation.z >= 0.f && orientation.z <= -1.f) || (orientation.z >= -1.f && orientation.z <= 0.f)) {
				move->add_angular_force(glm::vec3(0.f, rotation_speed*(std::pow(diff, 1.4f)) , 0.f));
Elias Broschin's avatar
Elias Broschin committed
110
			} else
Elias Broschin's avatar
Elias Broschin committed
111
				move->add_angular_force(glm::vec3(0.f, -rotation_speed*(std::pow(diff, 1.4f)) , 0.f));
Elias Broschin's avatar
merged    
Elias Broschin committed
112
		}
Elias Broschin's avatar
Elias Broschin committed
113

114
		if (engine_.input().isDown("move_right") && player->position().x < maximum_movement_distance) {
Elias Broschin's avatar
Elias Broschin committed
115
116
117
118
119
120
121
122
			auto orientation = player->rotation()*glm::vec3(0,0,1);
			auto diff = std::abs(orientation.x - (1.f)) + std::abs(orientation.z - (0.f));
			auto clamped = glm::clamp(diff/turn_rate_modifier, 0.f, 1.f);

			move->add_force(glm::vec3(level_manager.player_speed()*(1.f-clamped), 0.f,0.f));

			if((orientation.z >= 0.f && orientation.z <= -1.f) || (orientation.z >= -1.f && orientation.z <= 0.f)) {
				move->add_angular_force(glm::vec3(0.f, -rotation_speed*(std::pow(diff, 1.4f)) , 0.f));
Elias Broschin's avatar
Elias Broschin committed
123
			} else
Elias Broschin's avatar
Elias Broschin committed
124
				move->add_angular_force(glm::vec3(0.f, rotation_speed*(std::pow(diff, 1.4f)) , 0.f));
Elias Broschin's avatar
Elias Broschin committed
125
		}
126
127

		// SET ITEM WITH SPACE KEY
128
		if (input.isDown("place_item")) {
Elias Broschin's avatar
Elias Broschin committed
129
			engine_.game_play_system().player_item_manager().place_item(get_world_mouse_pos());
130
		}
Elias Broschin's avatar
Elias Broschin committed
131
132
	}

Elias Broschin's avatar
merged    
Elias Broschin committed
133
	void game_input_manager::handle_mouse_input(float dt) {
Elias Broschin's avatar
Elias Broschin committed
134
135
		auto &input = engine_.input();
		auto &level_manager = engine_.game_play_system().level_manager();
Elias Broschin's avatar
Elias Broschin committed
136

Elias Broschin's avatar
Elias Broschin committed
137
138
139
140
		//MOUSEWHEEL
		if(input.mouseWheelY() < 0.f) {
			auto cam = engine_.game_play_system().level_manager().camera();
			cam->position(cam->position()+glm::vec3(0,1.f,1.f));
141
			level_manager.set_weapon(weapon_type::tractor_beam);
Elias Broschin's avatar
Elias Broschin committed
142
143
144
145
		}
		if(input.mouseWheelY() > 0.f) {
			auto cam = engine_.game_play_system().level_manager().camera();
			cam->position(cam->position()+glm::vec3(0,-1.f,-1.f));
146
			level_manager.set_weapon(weapon_type::portal_gun);
Elias Broschin's avatar
Elias Broschin committed
147
148
		}

149
		if(input.isPressed("beam_normal")) {
150
151
			engine_.audioEventHandler().trigger(AudioEventHandler::TRAKTORBEAM_REVERSE_ACTIVATED);
		}
152
		if(input.isReleased("beam_normal")) {
153
154
			engine_.audioEventHandler().trigger(AudioEventHandler::TRAKTORBEAM_REVERSE_DEACTIVATED);
		}
155
		if(input.isPressed("beam_inverse")) {
156
157
			engine_.audioEventHandler().trigger(AudioEventHandler::TRAKTORBEAM_ACTIVATED);
		}
Elias Broschin's avatar
Elias Broschin committed
158

159
		if(input.isReleased("beam_inverse")) {
Elias Broschin's avatar
Elias Broschin committed
160
			engine_.audioEventHandler().trigger(AudioEventHandler::TRAKTORBEAM_DEACTIVATED);
161
162
		}

Elias Broschin's avatar
Elias Broschin committed
163
		//LEFT && RIGHT CLICK
Elias Broschin's avatar
Elias Broschin committed
164
165
		switch(level_manager.weapon()) {
			case weapon_type::tractor_beam: {
166
				if(input.isDown("beam_normal") || input.isDown("beam_inverse")) {
Elias Broschin's avatar
Elias Broschin committed
167
168
169
					auto intersection_point = get_world_mouse_pos();

					auto cannon = level_manager.cannon();
170
171
172
173
174
175
176
					if (!cannon) {
						return;
					}
					auto cannon_pos = cannon->position();
					auto cannon_rotation = glm::toMat4(cannon->rotation());
					auto offset = glm::vec3(cannon_rotation * glm::vec4(0.f, 0.57352f, 1.3088f, 1.f));
					ray r(cannon_pos + offset, intersection_point);
Elias Broschin's avatar
Elias Broschin committed
177
178

					auto ray_unnormalized = glm::vec3(1.f);
179
					if (input.isDown("beam_normal")) {
Elias Broschin's avatar
Elias Broschin committed
180
181
182
183
184
185
186
187
188
						ray_unnormalized = r.source - r.destination;
					} else {
						ray_unnormalized = r.destination - r.source;
					}

					constexpr float max_ray_length = 40.f;
					auto ray_length_ = max_ray_length;
					bool asteroid_hit = false;
					float beam_velocity = 10.f;
Elias Broschin's avatar
stuff    
Elias Broschin committed
189
190
					auto remaining_length = 0.f;
					int portal_type = -1;	//-1 none, 0 blue, 1 yellow
Elias Broschin's avatar
Elias Broschin committed
191

Elias Broschin's avatar
stuff    
Elias Broschin committed
192
193

					process_beam_collision(r, ray_unnormalized, beam_velocity, ray_length_, asteroid_hit, portal_type, remaining_length);
Elias Broschin's avatar
Elias Broschin committed
194

195
					if (input.isDown("beam_normal")) {
Elias Broschin's avatar
Elias Broschin committed
196
						auto ray_length = (std::abs(ray_length_ - 0.f) < 0.001f)? glm::length(ray_unnormalized): ray_length_;
197
						render_ray(&r, offset, ray_length, 0.18f, false, glm::vec3(0.5f, 0.6f, 0.9f));
Elias Broschin's avatar
Elias Broschin committed
198
199
					} else {
						auto ray_length = (std::abs(ray_length_ - 0.f) < 0.001f)? glm::length(ray_unnormalized): ray_length_;
200
						render_ray(&r, offset, ray_length, 0.18f, true, glm::vec3(0.8f, 0.4f, 0.f));
Elias Broschin's avatar
Elias Broschin committed
201
					}
Elias Broschin's avatar
stuff    
Elias Broschin committed
202
//					do {
203
204
205
206
207
208
209
210
						switch(portal_type) {
							case 0: {
								auto yellow_portal = level_manager.yellow_portal();
								if(yellow_portal) {
									ray r2(yellow_portal->position(), yellow_portal->position()+(r.source - r.destination));
									portal_type = -1;
									ray_length_ = remaining_length;
									process_beam_collision(r2, ray_unnormalized, beam_velocity, ray_length_, asteroid_hit, portal_type, remaining_length);
211
									if (input.isDown("beam_normal")) {
212
										render_ray(&r2, offset, remaining_length, 0.18f, false, glm::vec3(0,0,1));
213
									} else {
214
										render_ray(&r2, offset, remaining_length, 0.18f, true, glm::vec3(1,0,0));
215
216
217
218
219
220
221
222
223
224
225
									}
								}
							break;
							}
							case 1: {
							auto blue_portal = level_manager.blue_portal();
							if(blue_portal) {
								ray r2(blue_portal->position(), blue_portal->position()+(r.source - r.destination));
								portal_type = -1;
								ray_length_ = remaining_length;
								process_beam_collision(r2, ray_unnormalized, beam_velocity, ray_length_, asteroid_hit, portal_type, remaining_length);
226
								if (input.isDown("beam_normal")) {
227
									render_ray(&r2, offset, remaining_length, 0.18f, false, glm::vec3(0,0,1));
228
								} else {
229
									render_ray(&r2, offset, remaining_length, 0.18f, true, glm::vec3(1,0,0));
230
231
232
233
234
235
								}
							}
							break;
							}
						default:{}
						}
Elias Broschin's avatar
stuff    
Elias Broschin committed
236
//					} while(portal_type > 0 || glm::length(remaining_length)<0.3f);
Elias Broschin's avatar
Elias Broschin committed
237
238
				}
				break;
239
			}
Elias Broschin's avatar
Elias Broschin committed
240
			case weapon_type::portal_gun: {
241
				if(input.isDown("beam_normal") || input.isDown("beam_inverse")) {
Elias Broschin's avatar
Elias Broschin committed
242
243
					auto intersection_point = get_world_mouse_pos();

244
					if(input.isDown("beam_normal"))
Elias Broschin's avatar
Elias Broschin committed
245
246
						level_manager.create_blue_portal(intersection_point);

247
					if(input.isDown("beam_inverse"))
Elias Broschin's avatar
Elias Broschin committed
248
249
250
						level_manager.create_yellow_portal(intersection_point);
				}
				break;
251
			}
Elias Broschin's avatar
Elias Broschin committed
252
		}
253
254
255
256
257
258
259
260
261
262

		auto cannon = level_manager.cannon();
		if (cannon) {
			const static auto cannon_dir = glm::vec3(0.f, 0.f, 1.f);
			auto ray_dir = get_world_mouse_pos() - cannon->position();
			auto alpha = glm::atan(ray_dir.x, ray_dir.z);
			auto beta = glm::atan(cannon_dir.x, cannon_dir.z);
			auto cannon_rotation = glm::angleAxis(alpha + beta, glm::vec3(0.f, 1.f, 0.f));
			cannon->rotation(cannon_rotation);
		}
Elias Broschin's avatar
Elias Broschin committed
263
264
	}

Elias Broschin's avatar
stuff    
Elias Broschin committed
265
	void game_input_manager::process_beam_collision(ray& r, glm::vec3 &ray_unnormalized, float &beam_velocity, float &ray_length_, bool &asteroid_hit, int &portal_type, float &remaining_ray_length) {
Elias Broschin's avatar
Elias Broschin committed
266
		auto collider = engine_.physics_system().checkCollisions<gdw::shape_type::ray>(&r);
Elias Broschin's avatar
stuff    
Elias Broschin committed
267
		//DONT DO THIS AT HOME
Elias Broschin's avatar
Elias Broschin committed
268
269
270
271
272
273
274
275

		//BEAM X ACCELERATOR
		for(auto &coll : collider) {
			auto c = engine_.entity_manager().resolve(coll);
			auto type_comp = c->component<object_type_component>();
			if(!type_comp) continue;

			if(type_comp->get_object_type() == "ACCELERATOR") {
276
277
				ray_length_ = asteroid_hit ? ray_length_ : ray_length_*1.5f;
				beam_velocity += 10.f;
Elias Broschin's avatar
Elias Broschin committed
278
279
280
			}
		}

281
282


Elias Broschin's avatar
stuff    
Elias Broschin committed
283
		//BEAM X ASTEROIDS
Elias Broschin's avatar
Elias Broschin committed
284
285
286
287
288
289
290
291
		for(auto &coll : collider) {
			auto c = engine_.entity_manager().resolve(coll);
			auto type_comp = c->component<object_type_component>();
			if(type_comp) {
				if(type_comp->get_object_type() == "ASTEROID") {
					ray_length_ = std::min(ray_length_, glm::length(c->position() - r.source));
					asteroid_hit = true;
				}
Elias Broschin's avatar
stuff    
Elias Broschin committed
292
293
294
			}
		}

295
296
		//BEAM X PORTAL
		for(auto &coll : collider) {
Elias Broschin's avatar
stuff    
Elias Broschin committed
297

298
			auto c = engine_.entity_manager().resolve(coll);
Elias Broschin's avatar
stuff    
Elias Broschin committed
299

300
301
			auto type_comp = c->component<object_type_component>();
			if(!type_comp) continue;
Elias Broschin's avatar
stuff    
Elias Broschin committed
302

303
304
			if(type_comp->get_object_type() == "BLUE_PORTAL") {
				if(glm::length(r.source - c->position()) > ray_length_) continue;
Elias Broschin's avatar
stuff    
Elias Broschin committed
305

306
307
308
309
310
				auto reduced_ray_length = std::min(ray_length_, glm::length(c->position() - r.source));
				remaining_ray_length = ray_length_ - reduced_ray_length;
				ray_length_ = reduced_ray_length;
				portal_type = 0;
			}
Elias Broschin's avatar
stuff    
Elias Broschin committed
311

312
313
			if(type_comp->get_object_type() == "YELLOW_PORTAL") {
				if(glm::length(r.source - c->position()) > ray_length_) continue;
Elias Broschin's avatar
stuff    
Elias Broschin committed
314

315
316
317
318
319
320
				auto reduced_ray_length = std::min(ray_length_, glm::length(c->position() - r.source));
				remaining_ray_length = ray_length_ - reduced_ray_length;
				ray_length_ = reduced_ray_length;
				portal_type = 1;
			}
		}
Elias Broschin's avatar
stuff    
Elias Broschin committed
321
322
323
324
325
326
327
328
329

		//BEAM X MOVINGS
		for(auto &coll : collider) {
			auto c = engine_.entity_manager().resolve(coll);
			auto move = c->component<movement_component>();

			auto type_comp = c->component<object_type_component>();
			if(type_comp->get_object_type() == "PLAYER") {
				continue;
Elias Broschin's avatar
Elias Broschin committed
330
331
332
333
334
335
336
337
			}

			if(glm::length(ray_unnormalized) < 0.01f) continue;
			auto attract_dir = glm::normalize(ray_unnormalized);
			if(move) {
				auto distance = glm::length(r.source - c->position());
				if(glm::length(r.source - c->position()) < ray_length_) {
					move->add_force((attract_dir * beam_velocity) / std::max(distance/20.f, 2.f));
338
					ray_length_ = std::min(ray_length_, glm::length(c->position() - r.source));
Elias Broschin's avatar
Elias Broschin committed
339
340
341
342
343
				}
			}
		}
	}

344
345
346
347
348
349
350
351
	void game_input_manager::render_ray(ray* r, const glm::vec3& offset, float length, float radius, bool invert, glm::vec3 color) {
		const static auto cannon_dir = glm::vec3(0.f, 0.f, 1.f);
		auto ray_dir = glm::normalize(r->destination - (r->source - offset));
		auto alpha = glm::atan(ray_dir.x, ray_dir.z);
		auto beta = glm::atan(cannon_dir.x, cannon_dir.z);
		auto cannon_rotation = glm::angleAxis(alpha + beta, glm::vec3(0.f, 1.f, 0.f));

		engine_.rendering_system().render_trakor_beam(r->source, cannon_rotation, length, radius, invert, color);
Elias Broschin's avatar
Elias Broschin committed
352
353
	}

Elias Broschin's avatar
Elias Broschin committed
354
} //Namespace gdw