r-type  0.0.0
R-Type main
Loading...
Searching...
No Matches
playerControllerMulti.cpp
Go to the documentation of this file.
2#include "ECS/Component.hpp"
7
9{
10 auto [offsetX, offsetY] = utl::calculateHitboxOffsets(
12
14 registry.createEntity()
15 .with<ecs::Transform>("player_transform", x, y, 0.F)
16 .with<ecs::Velocity>("player_velocity", 0.F, 0.F)
17 .with<ecs::Rect>("player_rect", 0.F, 0.F, static_cast<int>(utl::GameConfig::Player::SPRITE_WIDTH),
19 .with<ecs::Scale>("player_scale", utl::GameConfig::Player::SCALE, utl::GameConfig::Player::SCALE)
20 .with<ecs::Texture>("player_texture", utl::Path::Texture::TEXTURE_PLAYER)
21 .with<ecs::Player>("player", true)
22 .with<ecs::Health>("player_health", 100.0f, 100.0f)
23 .with<ecs::BeamCharge>("beam_charge", 0.0f, utl::GameConfig::Beam::MAX_CHARGE)
24 .with<ecs::Hitbox>("player_hitbox", utl::GameConfig::Hitbox::PLAYER_RADIUS, offsetX, offsetY)
25 .build();
26 return m_playerEntity;
27}
28
30{
31 switch (event.type)
32 {
34 if (event.key == eng::Key::Up)
35 {
36 m_keysPressed[eng::Key::Up] = true;
37 }
38 if (event.key == eng::Key::Down)
39 {
40 m_keysPressed[eng::Key::Down] = true;
41 }
42 if (event.key == eng::Key::Left)
43 {
44 m_keysPressed[eng::Key::Left] = true;
45 }
46 if (event.key == eng::Key::Right)
47 {
48 m_keysPressed[eng::Key::Right] = true;
49 }
50 if (event.key == eng::Key::Space)
51 {
52 m_keysPressed[eng::Key::Space] = true;
53 }
54 break;
55
57 if (event.key == eng::Key::Up)
58 {
59 m_keysPressed[eng::Key::Up] = false;
60 }
61 if (event.key == eng::Key::Down)
62 {
63 m_keysPressed[eng::Key::Down] = false;
64 }
65 if (event.key == eng::Key::Left)
66 {
67 m_keysPressed[eng::Key::Left] = false;
68 }
69 if (event.key == eng::Key::Right)
70 {
71 m_keysPressed[eng::Key::Right] = false;
72 }
73 if (event.key == eng::Key::Space)
74 {
75 m_keysPressed[eng::Key::Space] = false;
76 }
77 break;
78
79 default:
80 break;
81 }
82
83 sendInputsIfChanged();
84}
85
87{
88 // Send inputs immediately for better responsiveness
89 // No throttling for shoot input
90
91 auto checkKey = [this](const eng::Key key) -> bool
92 {
93 auto it = m_keysPressed.find(key);
94 return it != m_keysPressed.end() && it->second;
95 };
96
97 const bool up = checkKey(eng::Key::Up);
98 const bool down = checkKey(eng::Key::Down);
99 const bool left = checkKey(eng::Key::Left);
100 const bool right = checkKey(eng::Key::Right);
101 const bool shoot = checkKey(eng::Key::Space);
102
103 sendInputToServer(up, down, left, right, shoot);
104}
105
106void gme::PlayerControllerMulti::sendInputToServer(bool up, bool down, bool left, bool right, bool shoot) const
107{
108 std::vector<std::uint8_t> inputData;
109 inputData.push_back(up ? 1 : 0);
110 inputData.push_back(down ? 1 : 0);
111 inputData.push_back(left ? 1 : 0);
112 inputData.push_back(right ? 1 : 0);
113 inputData.push_back(shoot ? 1 : 0);
114 // Create EventRecord
115 rnp::EventRecord eventRecord;
116 eventRecord.entityId = 0;
117 eventRecord.type = rnp::EventType::INPUT;
118 eventRecord.data = inputData;
119
120 // Serialize and send
121 std::vector<rnp::EventRecord> events;
122 events.push_back(eventRecord);
123
124 rnp::Serializer serializer;
125 serializer.serializeEntityEvents(events);
126
127 // Publish to event bus to send to server
128 m_eventBus.publish(utl::EventType::SEND_ENTITY_EVENT, serializer.getData(), m_componentId, utl::NETWORK_CLIENT);
129}
130
132{
133 const auto keyboardEntities = registry.getAll<ecs::KeyboardInput>();
134 ecs::Entity keyboardEntity = ecs::INVALID_ENTITY;
135 if (!keyboardEntities.empty())
136 {
137 keyboardEntity = keyboardEntities.begin()->first;
138 }
139 else
140 {
141 keyboardEntity = registry.createEntity().with<ecs::KeyboardInput>("keyboard_input").build();
142 }
143
144 if (auto *keyboardInput = registry.getComponent<ecs::KeyboardInput>(keyboardEntity))
145 {
146 auto checkKey = [this](const eng::Key key) -> bool
147 {
148 auto it = m_keysPressed.find(key);
149 return it != m_keysPressed.end() && it->second;
150 };
151
152 keyboardInput->space_pressed = checkKey(eng::Key::Space);
153 keyboardInput->up_pressed = checkKey(eng::Key::Up);
154 keyboardInput->down_pressed = checkKey(eng::Key::Down);
155 keyboardInput->left_pressed = checkKey(eng::Key::Left);
156 keyboardInput->right_pressed = checkKey(eng::Key::Right);
157 }
158
159 // Client-side prediction: Apply inputs immediately to local player
160 if (auto *transform = registry.getComponent<ecs::Transform>(m_playerEntity))
161 {
162 if (auto *velocity = registry.getComponent<ecs::Velocity>(m_playerEntity))
163 {
164 // Calculate velocity based on current key states
165 constexpr float SPEED = 500.0f;
166 velocity->x = 0.0f;
167 velocity->y = 0.0f;
168
169 auto checkKey = [this](const eng::Key key) -> bool
170 {
171 auto it = m_keysPressed.find(key);
172 return it != m_keysPressed.end() && it->second;
173 };
174
175 const bool up = checkKey(eng::Key::Up);
176 const bool down = checkKey(eng::Key::Down);
177 const bool left = checkKey(eng::Key::Left);
178 const bool right = checkKey(eng::Key::Right);
179
180 if (up)
181 {
182 velocity->y = -SPEED;
183 }
184 if (down)
185 {
186 velocity->y = SPEED;
187 }
188 if (left)
189 {
190 velocity->x = -SPEED;
191 }
192 if (right)
193 {
194 velocity->x = SPEED;
195 }
196
197 if (velocity->x != 0.0f && velocity->y != 0.0f)
198 {
199 velocity->x *= 0.707f;
200 velocity->y *= 0.707f;
201 }
202
203 transform->x += velocity->x * dt;
204 transform->y += velocity->y * dt;
205
206 transform->x = std::max(0.0f, std::min(1920.0f, transform->x));
207 transform->y = std::max(0.0f, std::min(1080.0f, transform->y));
208 }
209 }
210}
211
213{
214 auto it = m_keysPressed.find(eng::Key::Space);
215 return it != m_keysPressed.end() && it->second;
216}
This file contains the component definitions.
Configuration constants for the multiplayer game.
Utility functions for hitbox calculations.
Multiplayer player controller system for R-Type client.
This file contains the network protocol.
Network packet serializer for RNP protocol.
EntityBuilder & with(Args &&...args)
Definition Registry.hpp:40
Class for managing entities and their components.
Definition Registry.hpp:25
EntityBuilder createEntity()
Definition Registry.hpp:53
std::unordered_map< Entity, T > & getAll()
Definition Registry.hpp:77
T * getComponent(Entity e)
Definition Registry.hpp:71
bool isSpacePressed() const
Check if space bar is currently pressed.
void sendInputToServer(bool up, bool down, bool left, bool right, bool shoot) const
Send input command to server via event bus.
void sendInputsIfChanged()
Send input update if state has changed.
ecs::Entity m_playerEntity
Local player entity ID.
void handleInput(ecs::Registry &registry, const eng::Event &event)
Handle input events from the window.
ecs::Entity createPlayer(ecs::Registry &registry, float x, float y)
Create the local player entity.
void update(ecs::Registry &registry, float dt) override
Update the player controller system (called each frame)
Binary serializer for RNP protocol packets.
const std::vector< std::uint8_t > & getData() const
Get the serialized data.
void serializeEntityEvents(const std::vector< EventRecord > &events)
Serialize multiple EventRecords for ENTITY_EVENT packet.
std::uint32_t Entity
Definition Entity.hpp:13
constexpr Entity INVALID_ENTITY
Definition Entity.hpp:14
constexpr float MAX_CHARGE
constexpr float PLAYER_RADIUS
constexpr float SCALE
constexpr float SPRITE_HEIGHT
constexpr float SPRITE_WIDTH
constexpr auto TEXTURE_PLAYER
Definition Common.hpp:114
std::pair< float, float > calculateHitboxOffsets(const float spriteWidth, const float spriteHeight, const float scale)
Calculate hitbox offsets to center the hitbox on the sprite.
static constexpr std::uint32_t NETWORK_CLIENT
Definition Event.hpp:17
EventType type
Event record for ENTITY_EVENT packets (TLV format)
Definition Protocol.hpp:117
std::uint32_t entityId
Definition Protocol.hpp:119
std::vector< std::uint8_t > data
Definition Protocol.hpp:120