]> git.tdb.fi Git - libs/game.git/blob - examples/bassteroids/source/playercontroller.cpp
b90992ed6239b191645476f48414e63ec7785b3e
[libs/game.git] / examples / bassteroids / source / playercontroller.cpp
1 #include "playercontroller.h"
2 #include <msp/game/root.h>
3 #include <msp/game/stage.h>
4 #include "controls.h"
5
6 using namespace std;
7 using namespace Msp;
8
9 PlayerController::PlayerController(Game::Stage &s):
10         System(s),
11         player_setup{ .physical={ .body={ .mass=1, .moment_of_inertia=0.8f }, .collider={ .type=ColliderType::CIRCLE, .radius=0.8f }},
12                 .mesh={ .object_name="Bass guitar.object" },
13                 .speed=12.0f, .turn_rate=4.71f },
14         bullet_setup{ .physical={ .body={ .mass=0.05f, .moment_of_inertia=0.04f }, .collider={ .type=ColliderType::CIRCLE, .radius=0.2f }},
15                 .hittable={ .damaging=true, .hits={ .max_hits=1 }, .damage={ .amount=1, .type=0 }},
16                 .mesh={ .object_name="Quaver.object" }}
17 {
18         declare_dependency<Game::Transform>(READ_OLD);
19         declare_dependency<RigidBody>(UPDATE);
20 }
21
22 void PlayerController::set_controls(Controls *c)
23 {
24         controls = c;
25         if(!player_ship)
26                 player_ship = Game::Owned<Ship>(stage.get_root(), player_setup);
27 }
28
29 void PlayerController::tick(Time::TimeDelta dt)
30 {
31         if(!controls)
32                 return;
33
34         float dt_secs = dt/Time::sec;
35
36         const Ship::Setup &setup = player_ship->get_setup();
37         float thrust = setup.speed*setup.speed;
38         float torque = setup.turn_rate*setup.turn_rate;
39
40         Game::Handle<Game::Transform> transform = player_ship->get_transform();
41         LinAl::Vector<float, 2> fwd_dir = normalize(transform->get_world_matrix().column(0).slice<2>(0));
42         Game::Handle<RigidBody> body = player_ship->get_body();
43
44         body->add_force(fwd_dir*(controls->forward.get_value()*thrust));
45         const LinAl::Vector<float, 2> &velocity = body->get_velocity();
46         float speed = velocity.norm();
47         if(speed>1e-5)
48                 body->add_force(velocity*-min(speed+setup.speed/speed, 1.0f/dt_secs));
49
50         body->add_torque(controls->turn_left.get_value()*torque);
51         Geometry::Angle<float> angular_vel = body->get_angular_velocity();
52         Geometry::Angle<float> angular_speed = abs(angular_vel);
53         if(abs(angular_speed.radians())>1e-5)
54                 body->add_torque(angular_vel.radians()*-min(angular_speed.radians()+setup.turn_rate/angular_speed.radians(), 1.0f/dt_secs));
55
56         if(controls->fire.was_pressed())
57                 defer([this]{ fire(); });
58
59         controls->reset_edges();
60 }
61
62 void PlayerController::deferred_tick()
63 {
64         System::deferred_tick();
65         erase_if(bullets, [](Game::Handle<Bullet> b){ return !b->get_hitpoints()->is_alive(); });
66 }
67
68 void PlayerController::fire()
69 {
70         Game::Handle<Game::Transform> player_tf = player_ship->get_transform();
71         Game::Handle<RigidBody> player_body = player_ship->get_body();
72
73         Game::TransformValues tv;
74         tv.position = (player_tf->get_world_matrix()*LinAl::Vector<float, 4>(2.0f, 0.0f, 0.0f, 1.0f)).slice<3>(0);
75         tv.rotation = player_tf->get_rotation()*Geometry::Quaternion<float>::rotation(Geometry::Angle<float>::from_degrees(10), LinAl::Vector<float, 3>(0.0f, 0.0f, 1.0f));
76         bullets.emplace_back(stage.get_root(), bullet_setup, tv);
77         Game::Handle<Bullet> bullet = bullets.back();
78         Game::Handle<RigidBody> bullet_body = bullet->get_body();
79         bullet_body->set_velocity(player_body->get_velocity()+(player_tf->get_world_matrix()*LinAl::Vector<float, 4>(20.0f, 0.0f, 0.0f, 0.0f)).slice<2>(0));
80 }