Bomberman Multiplayer
Authoritative multiplayer networking layer for Bomberman.
Loading...
Searching...
No Matches
MultiplayerLevelSceneInternal.h
Go to the documentation of this file.
1
6#ifndef BOMBERMAN_SCENES_MULTIPLAYERLEVELSCENEINTERNAL_H
7#define BOMBERMAN_SCENES_MULTIPLAYERLEVELSCENEINTERNAL_H
8
9#include <algorithm>
10#include <cmath>
11#include <cstdint>
12#include <memory>
13
14#include "Const.h"
15#include "Core/Animation.h"
16#include "Entities/Sprite.h"
17#include "Net/NetCommon.h"
19#include "Sim/SimConfig.h"
20#include "Sim/SpawnSlots.h"
21#include "Util/PlayerColors.h"
22
23namespace bomberman::multiplayer_level_scene_internal
24{
25 static_assert(!sim::kDefaultSpawnSlots.empty(), "Spawn slot table must not be empty");
26 static_assert(net::kMaxPlayers <= util::kPlayerColorCount,
27 "Player color table must cover all supported multiplayer player ids");
28
29 // ----- Shared Presentation Constants -----
30
31 inline constexpr int kMovementDeltaThresholdQ = 2;
32 inline constexpr int kNameTagOffsetPx = 6;
33 inline constexpr int kNameTagMinPointSize = 12;
34 inline constexpr int kNameTagMaxPointSize = 20;
35 inline constexpr uint32_t kGameplayDegradedThresholdMs = 2000;
36 inline constexpr int kGameplayStatusOffsetY = 12;
37 inline constexpr int kDebugHudOffsetX = 12;
38 inline constexpr int kDebugHudOffsetY = 12;
39 inline constexpr int kDebugHudPointSize = 12;
40 inline constexpr int kDebugHudLineGapPx = 4;
41 inline constexpr uint32_t kDebugHudRefreshIntervalMs = 250;
42 inline constexpr int kCenterBannerPointSize = 56;
43 inline constexpr int kCenterBannerDetailPointSize = 40;
44 inline constexpr int kCenterBannerLineGapPx = 10;
45 inline constexpr uint32_t kCenterBannerDurationTicks = static_cast<uint32_t>(sim::kTickRate);
46 inline constexpr uint32_t kLivePredictionLogIntervalMs = 1000;
47 inline constexpr uint32_t kSimulationTickMs = 1000u / static_cast<uint32_t>(sim::kTickRate);
48 inline constexpr uint32_t kPreStartReturnTimeoutMs = 7000;
49 inline constexpr uint32_t kPowerupBlinkIntervalMs = 140;
50 inline constexpr int kBombAnimationFrameCount = 4;
51 inline constexpr int kBombSparkAnimationFrameCount = 5;
52 inline constexpr int kBombSparkFrameSizePx = 32;
53 inline constexpr uint32_t kBombSparkAnimationIntervalMs = 50;
54 inline constexpr uint32_t kBombSparkLifetimeMs = 250;
55 inline constexpr uint32_t kPendingLocalBombPlacementLifetimeMs =
56 static_cast<uint32_t>((1000ull * sim::kDefaultBombFuseTicks) / sim::kTickRate);
57 inline constexpr int kBoostedBombExtraPx = 4;
58 inline constexpr int kExplosionAnimationStartFrame = 1;
59 inline constexpr int kExplosionAnimationFrameCount = 11;
60 inline constexpr uint32_t kExplosionLifetimeMs = 800;
61
65 [[nodiscard]]
66 constexpr uint16_t packCellKey(const uint8_t col, const uint8_t row)
67 {
68 return static_cast<uint16_t>((static_cast<uint16_t>(row) << 8u) | static_cast<uint16_t>(col));
69 }
70
74 inline void attachBombAnimation(const std::shared_ptr<Sprite>& bombSprite)
75 {
76 if (!bombSprite)
77 return;
78
79 auto animation = std::make_shared<Animation>();
80 for (int frame = 0; frame < kBombAnimationFrameCount; ++frame)
81 {
82 animation->addAnimationEntity(AnimationEntity(tileSize * frame, 0, tileSize, tileSize));
83 }
84
85 animation->setSprite(bombSprite.get());
86 bombSprite->addAnimation(animation);
87 animation->play();
88 }
89
93 inline void attachExplosionAnimation(const std::shared_ptr<Sprite>& explosionSprite)
94 {
95 if (!explosionSprite)
96 return;
97
98 auto animation = std::make_shared<Animation>();
99 for (int frame = 0; frame < kExplosionAnimationFrameCount; ++frame)
100 {
101 animation->addAnimationEntity(
102 AnimationEntity(tileSize * (kExplosionAnimationStartFrame + frame), 0, tileSize, tileSize));
103 }
104
105 animation->setSprite(explosionSprite.get());
106 explosionSprite->addAnimation(animation);
107 animation->play();
108 }
109
113 inline void attachBombSparkAnimation(const std::shared_ptr<Sprite>& bombSparkSprite)
114 {
115 if (!bombSparkSprite)
116 return;
117
118 auto animation = std::make_shared<Animation>();
119 animation->setAnimationInterval(kBombSparkAnimationIntervalMs);
120 for (int frame = 0; frame < kBombSparkAnimationFrameCount; ++frame)
121 {
122 animation->addAnimationEntity(AnimationEntity(kBombSparkFrameSizePx * frame,
123 0,
124 kBombSparkFrameSizePx,
125 kBombSparkFrameSizePx));
126 }
127
128 animation->setSprite(bombSparkSprite.get());
129 bombSparkSprite->addAnimation(animation);
130 animation->play();
131 }
132
133 [[nodiscard]]
134 inline bool snapshotEntryIsAlive(const net::MsgSnapshot::PlayerEntry& entry)
135 {
136 const auto flags = static_cast<uint8_t>(entry.flags);
137 return (flags & static_cast<uint8_t>(net::MsgSnapshot::PlayerEntry::EPlayerFlags::Alive)) != 0;
138 }
139
140 [[nodiscard]]
141 inline bool snapshotEntryInputLocked(const net::MsgSnapshot::PlayerEntry& entry)
142 {
143 const auto flags = static_cast<uint8_t>(entry.flags);
144 return (flags & static_cast<uint8_t>(net::MsgSnapshot::PlayerEntry::EPlayerFlags::InputLocked)) != 0;
145 }
146
147 [[nodiscard]]
148 inline bool snapshotEntryInvulnerable(const net::MsgSnapshot::PlayerEntry& entry)
149 {
150 const auto flags = static_cast<uint8_t>(entry.flags);
151 return (flags & static_cast<uint8_t>(net::MsgSnapshot::PlayerEntry::EPlayerFlags::Invulnerable)) != 0;
152 }
153
154 [[nodiscard]]
155 inline bool snapshotEntryBombRangeBoost(const net::MsgSnapshot::PlayerEntry& entry)
156 {
157 const auto flags = static_cast<uint8_t>(entry.flags);
158 return (flags & static_cast<uint8_t>(net::MsgSnapshot::PlayerEntry::EPlayerFlags::BombRangeBoost)) != 0;
159 }
160
161 [[nodiscard]]
162 inline bool snapshotEntryMaxBombsBoost(const net::MsgSnapshot::PlayerEntry& entry)
163 {
164 const auto flags = static_cast<uint8_t>(entry.flags);
165 return (flags & static_cast<uint8_t>(net::MsgSnapshot::PlayerEntry::EPlayerFlags::MaxBombsBoost)) != 0;
166 }
167
168 [[nodiscard]]
169 inline bool snapshotEntrySpeedBoost(const net::MsgSnapshot::PlayerEntry& entry)
170 {
171 const auto flags = static_cast<uint8_t>(entry.flags);
172 return (flags & static_cast<uint8_t>(net::MsgSnapshot::PlayerEntry::EPlayerFlags::SpeedBoost)) != 0;
173 }
174
178 [[nodiscard]]
179 inline MovementDirection inferDirectionFromDelta(const int dxQ,
180 const int dyQ,
181 const MovementDirection fallback)
182 {
183 const int absDx = std::abs(dxQ);
184 const int absDy = std::abs(dyQ);
185
186 if (absDx < kMovementDeltaThresholdQ && absDy < kMovementDeltaThresholdQ)
187 return fallback;
188
189 if (absDx >= absDy)
190 return dxQ >= 0 ? MovementDirection::Right : MovementDirection::Left;
191
192 return dyQ >= 0 ? MovementDirection::Down : MovementDirection::Up;
193 }
194
198 [[nodiscard]]
199 inline int computeTagPointSize(const int scaledTileSize)
200 {
201 return std::clamp(scaledTileSize / 3, kNameTagMinPointSize, kNameTagMaxPointSize);
202 }
203
207 [[nodiscard]]
208 inline MovementDirection inferDirectionFromButtons(const uint8_t buttons)
209 {
210 const int8_t moveX = net::buttonsToMoveX(buttons);
211 const int8_t moveY = net::buttonsToMoveY(buttons);
212
213 if (moveX == 0 && moveY == 0)
214 return MovementDirection::None;
215
216 if (moveX != 0)
217 return moveX > 0 ? MovementDirection::Right : MovementDirection::Left;
218
219 return moveY > 0 ? MovementDirection::Down : MovementDirection::Up;
220 }
221} // namespace bomberman::multiplayer_level_scene_internal
222
223#endif // BOMBERMAN_SCENES_MULTIPLAYERLEVELSCENEINTERNAL_H
Game-world configuration constants.
constexpr unsigned int tileSize
Source sprite size in pixels (not scaled render size).
Definition Const.h:45
void attachBombAnimation(const std::shared_ptr< Sprite > &bombSprite)
Attach the looping bomb animation.
Definition MultiplayerLevelSceneInternal.h:74
void attachExplosionAnimation(const std::shared_ptr< Sprite > &explosionSprite)
Attach the explosion animation.
Definition MultiplayerLevelSceneInternal.h:93
constexpr uint32_t kGameplayDegradedThresholdMs
Silence window before gameplay is marked degraded.
Definition MultiplayerLevelSceneInternal.h:35
constexpr uint32_t kPendingLocalBombPlacementLifetimeMs
Lifetime of a pending local bomb reservation.
Definition MultiplayerLevelSceneInternal.h:55
MovementDirection inferDirectionFromDelta(const int dxQ, const int dyQ, const MovementDirection fallback)
Infer visible facing from position delta.
Definition MultiplayerLevelSceneInternal.h:179
int computeTagPointSize(const int scaledTileSize)
Derive a readable player-tag size from the current tile size.
Definition MultiplayerLevelSceneInternal.h:199
void attachBombSparkAnimation(const std::shared_ptr< Sprite > &bombSparkSprite)
Attach the short local bomb spark animation.
Definition MultiplayerLevelSceneInternal.h:113
MovementDirection inferDirectionFromButtons(const uint8_t buttons)
Infer facing directly from queued input buttons.
Definition MultiplayerLevelSceneInternal.h:208
constexpr uint16_t packCellKey(const uint8_t col, const uint8_t row)
Pack a tile coordinate into one map key.
Definition MultiplayerLevelSceneInternal.h:66
Multiplayer gameplay scene interface.
Shared client/server wire contract for the multiplayer protocol.
Shared simulation tuning constants used by client and server gameplay code.
Shared default multiplayer spawn slots.
constexpr int8_t buttonsToMoveY(uint8_t buttons)
Derives vertical movement {-1, 0, 1} from a button bitmask.
Definition NetCommon.h:90
constexpr int8_t buttonsToMoveX(uint8_t buttons)
Derives horizontal movement {-1, 0, 1} from a button bitmask.
Definition NetCommon.h:81
constexpr uint8_t kMaxPlayers
Maximum supported player count in a game instance.
Definition NetCommon.h:54
constexpr uint32_t kDefaultBombFuseTicks
Default authoritative bomb fuse in simulation ticks.
Definition SimConfig.h:23
constexpr std::array< SpawnSlotCell, 4 > kDefaultSpawnSlots
Default player-id keyed spawn slots for the current arena layout.
Definition SpawnSlots.h:36
constexpr int16_t kTickRate
Simulation tick rate in Hz.
Definition SimConfig.h:14
Animation part for clipping.
Definition Animation.h:14
EPlayerFlags flags
Player alive status and other state flags.
Definition NetCommon.h:705
@ Alive
Player is alive if set, dead if unset.
@ MaxBombsBoost
Player currently has the max-bombs boost active.
@ BombRangeBoost
Player currently has the bomb-range boost active.
@ SpeedBoost
Player currently has the speed boost active.
@ InputLocked
Player input/movement is server-locked if set.