Skip to content

Commit e4dc8c0

Browse files
committed
added arrow to target cave
1 parent 0f655e4 commit e4dc8c0

File tree

12 files changed

+120
-12
lines changed

12 files changed

+120
-12
lines changed

src/caveexpress/client/CaveExpressClientMap.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#include "caveexpress/client/CaveExpressClientMap.h"
2+
#include "caveexpress/server/entities/Player.h"
23
#include "caveexpress/shared/CaveExpressEntityType.h"
34
#include "caveexpress/shared/CaveExpressCooldown.h"
45
#include "caveexpress/client/entities/ClientWindowTile.h"
56
#include "caveexpress/client/entities/ClientCaveTile.h"
67
#include "caveexpress/shared/network/messages/ProtocolMessages.h"
8+
#include "common/Math.h"
79
#include "common/ThemeType.h"
810
#include "common/vec2.h"
911
#include "particles/Bubble.h"
@@ -20,6 +22,8 @@
2022
#include "common/Log.h"
2123
#include "service/ServiceProvider.h"
2224
#include "common/DateUtil.h"
25+
#include "ui/nodes/UINodeSprite.h"
26+
#include "ui/windows/IUIMapWindow.h"
2327
#include <SDL.h>
2428
#include <SDL_image.h>
2529

@@ -63,6 +67,42 @@ void CaveExpressClientMap::renderWater (int x, int y) const
6367
}
6468
}
6569

70+
// _player arrow to cave
71+
void CaveExpressClientMap::renderArrow () const
72+
{
73+
ClientPlayer *player = getPlayer();
74+
if (!player)
75+
return;
76+
UINodeSpriteRot* arrow = UI::get().getNode<UINodeSpriteRot>(UI_WINDOW_MAP, UINODE_TARGET_ARROW);
77+
float ang = arrow->_angle;
78+
if (ang < 0.f)
79+
return;
80+
81+
float xdir = cosf(ang), ydir = -sinf(ang);
82+
83+
int x1, y1;
84+
player->getScreenPos(x1,y1);
85+
const vec2& s = player->getSize();
86+
y1 -= s.y / 2;
87+
const float d1 = 40.f, d2 = 90.f;
88+
int x2 = x1 + xdir * d2;
89+
int y2 = y1 + ydir * d2;
90+
x1 += xdir * d1;
91+
y1 += ydir * d1;
92+
_frontend->renderLine(x1, y1, x2, y2, colorGreen);
93+
94+
const float a = M_PI + M_PI / 6.f, d3 = 15.f;
95+
float xa = cosf(ang + a), ya = -sinf(ang + a);
96+
int x3 = x2 + xa * d3;
97+
int y3 = y2 + ya * d3;
98+
const float b = M_PI - M_PI / 6.f;
99+
_frontend->renderLine(x2, y2, x3, y3, colorGreen);
100+
float xb = cosf(ang + b), yb = -sinf(ang + b);
101+
int x4 = x2 + xb * d3;
102+
int y4 = y2 + yb * d3;
103+
_frontend->renderLine(x2, y2, x4, y4, colorGreen);
104+
}
105+
66106
bool CaveExpressClientMap::drop ()
67107
{
68108
if (isPause() || !isActive())
@@ -267,6 +307,7 @@ void CaveExpressClientMap::renderEnd (int x, int y) const
267307
if (_target)
268308
_frontend->renderTarget(_target);
269309
renderWater(x, y);
310+
renderArrow();
270311
}
271312

272313
int CaveExpressClientMap::renderCooldownDescription (uint32_t cooldownIndex, int x, int y, int w, int h) const

src/caveexpress/client/CaveExpressClientMap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class CaveExpressClientMap: public ClientMap {
1111
float _wind = 0.0f;
1212
mutable RenderTarget* _target = nullptr;
1313

14+
void renderArrow () const;
1415
void renderWater (int x, int y) const;
1516
SDL_Rect getWaterRect(int x, int y) const;
1617
void couldNotFindEntity (const std::string& prefix, uint16_t id) const override;

src/caveexpress/client/network/TargetCaveHandler.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@ class TargetCaveHandler: public ClientProtocolHandler<TargetCaveMessage> {
2020

2121
void execute(const TargetCaveMessage* msg) override
2222
{
23+
const float ang = msg->getAngle();
24+
UINodeSpriteRot* arrow = UI::get().getNode<UINodeSpriteRot>(UI_WINDOW_MAP, UINODE_TARGET_ARROW);
25+
arrow->_angle = ang;
26+
2327
const uint8_t caveNumber = msg->getCaveNumber();
28+
if (caveNumber >= 200) // from update
29+
return;
30+
2431
UINodeSprite* node = UI::get().getNode<UINodeSprite>(UI_WINDOW_MAP, UINODE_TARGETCAVEID);
2532
if (caveNumber == 0) {
2633
node->clearSprites();

src/caveexpress/client/ui/windows/UIMapWindow.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ void UIMapWindow::initHudNodes()
134134
_panel->add(pkgLeft);
135135

136136
add(_panel);
137+
138+
UINodeSpriteRot *arrow = new UINodeSpriteRot(_frontend, spriteHeight, spriteHeight);
139+
arrow->setId(UINODE_TARGET_ARROW);
140+
add(arrow);
137141
}
138142

139143
}

src/caveexpress/server/entities/Player.cpp

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "caveexpress/shared/CaveExpressCooldown.h"
1919
#include "caveexpress/shared/CaveExpressSoundType.h"
2020
#include "caveexpress/shared/constants/ConfigVars.h"
21+
#include <cmath>
2122

2223
namespace caveexpress {
2324

@@ -28,7 +29,8 @@ const float gravityScale = 0.3f;
2829
Player::Player (Map& map, ClientId clientId) :
2930
IEntity(EntityTypes::PLAYER, map), _touching(nullptr), _invulnerableTime(0u), _powerUpTime(0u), _collectedNPC(nullptr), _acceleration(b2Vec2_zero), _fingerAcceleration(
3031
false), _accelerateX(0), _accelerateY(0), _clientId(clientId), _lastAccelerate(0), _name(""), _lastFruitCollected(0), _hitpoints(
31-
0), _lives(0), _fruitsCollectedInARow(0), _revoluteJoint(nullptr), _crashReason(CRASH_NONE) {
32+
0), _lives(0), _fruitsCollectedInARow(0), _revoluteJoint(nullptr), _crashReason(CRASH_NONE)
33+
{
3234
_godMode = Config.getConfigVar(GOD_MODE);
3335
_maxHitPoints = Config.getConfigVar(MAX_HITPOINTS);
3436
_hitpoints = _maxHitPoints->getIntValue();
@@ -39,6 +41,8 @@ Player::Player (Map& map, ClientId clientId) :
3941
setAnimationType(Animations::ANIMATION_IDLE);
4042
setState(PlayerState::PLAYER_IDLE);
4143
memset(_collectedEntities, 0, sizeof(_collectedEntities));
44+
_targetCavePos.x = -1.f;
45+
_targetCavePos.y = -1.f;
4246
}
4347

4448
Player::~Player ()
@@ -154,6 +158,8 @@ void Player::update (uint32_t deltaTime)
154158
{
155159
IEntity::update(deltaTime);
156160

161+
sendTargetCaveAngle();
162+
157163
if (isCrashed()) {
158164
// before we crash, we should drop the stuff we are carrying
159165
drop();
@@ -462,7 +468,7 @@ bool Player::collect (CollectableEntity* entity)
462468
break;
463469
}
464470
if (EntityTypes::isStone(entityType)) {
465-
GameEvent.sendTargetCave(ClientIdToClientMask(_clientId), 100);
471+
GameEvent.sendTargetCave(ClientIdToClientMask(_clientId), 100, -1.f);
466472
Achievements::COLLECT_10_STONES.unlock();
467473
Achievements::COLLECT_100_STONES.unlock();
468474
}
@@ -481,7 +487,7 @@ void Player::drop ()
481487
if (EntityTypes::isStone(*entityType)) {
482488
Stone *entity = new Stone(_map, getPos().x, getPos().y, this);
483489
entity->createBody();
484-
GameEvent.sendTargetCave(ClientIdToClientMask(_clientId), 0);
490+
GameEvent.sendTargetCave(ClientIdToClientMask(_clientId), 0, -1.f);
485491
} else if (EntityTypes::isBomb(*entityType)) {
486492
Bomb *entity = new Bomb(_map, getPos().x, getPos().y, this);
487493
entity->createBody();
@@ -629,17 +635,43 @@ void Player::setPlatform (Platform* entity)
629635
npc->resetTriggerMovement();
630636
}
631637

632-
void Player::setCollectedNPC(NPCFriendly *npc) {
638+
static float GetAngle(float x, float y)
639+
{
640+
if (x == 0.f && y == 0.f)
641+
return 0.f;
642+
643+
if (y == 0.f)
644+
return (x < 0.f) ? M_PI : 0.f;
645+
else
646+
return (y < 0.f) ? atan2f(-y, x) : (2.f * M_PI - atan2f(y, x));
647+
}
648+
649+
void Player::sendTargetCaveAngle()
650+
{
651+
if (_collectedNPC == nullptr)
652+
return;
653+
if (_collectedNPC->getTargetCave() == nullptr)
654+
return;
655+
656+
_targetCavePos = _collectedNPC->getTargetCave()->getPos();
657+
const b2Vec2 dir = _targetCavePos - getPos();
658+
const float angle = GetAngle(dir.x, dir.y);
659+
660+
GameEvent.sendTargetCave(ClientIdToClientMask(_clientId), 200, angle);
661+
}
662+
663+
void Player::setCollectedNPC(NPCFriendly *npc)
664+
{
633665
// we can't collect a npc if we have collected something else
634666
if (npc && !isFree())
635667
return;
636668

637669
_collectedNPC = npc;
638670
if (npc != nullptr) {
639671
npc->setCollected();
640-
GameEvent.sendTargetCave(ClientIdToClientMask(_clientId), npc->getTargetCaveNumber());
672+
GameEvent.sendTargetCave(ClientIdToClientMask(_clientId), npc->getTargetCaveNumber(), -1.f);
641673
} else {
642-
GameEvent.sendTargetCave(ClientIdToClientMask(_clientId), 0);
674+
GameEvent.sendTargetCave(ClientIdToClientMask(_clientId), 0, -1.f);
643675
}
644676
}
645677

src/caveexpress/server/entities/Player.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class Player: public IEntity {
4646
uint32_t _powerUpTime;
4747

4848
NPCFriendly* _collectedNPC;
49+
b2Vec2 _targetCavePos;
4950

5051
b2Vec2 _acceleration;
5152

@@ -127,6 +128,7 @@ class Player: public IEntity {
127128
void createBody (const b2Vec2 &pos);
128129

129130
void setCollectedNPC(NPCFriendly *npc);
131+
void sendTargetCaveAngle();
130132
void reset ();
131133

132134
ClientId getClientId () const;

src/caveexpress/server/events/GameEventHandler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ void GameEventHandler::announceTargetCave(int clientMask, const NPCFriendly& npc
115115
_serviceProvider->getNetwork().sendToClients(clientMask, msg);
116116
}
117117

118-
void GameEventHandler::sendTargetCave(int clientMask, uint8_t number) const {
119-
const TargetCaveMessage msg(number);
118+
void GameEventHandler::sendTargetCave(int clientMask, uint8_t number, float angle) const {
119+
const TargetCaveMessage msg(number, angle);
120120
_serviceProvider->getNetwork().sendToClients(clientMask, msg);
121121
}
122122

src/caveexpress/server/events/GameEventHandler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class GameEventHandler: public NonCopyable {
6868
void announceTargetCave (int clientMask, const NPCFriendly& npc, int16_t delayMillis) const;
6969

7070
// inform the client about the target cave number the npc wants to get carried to
71-
void sendTargetCave (int clientMask, uint8_t number) const;
71+
void sendTargetCave (int clientMask, uint8_t number, float angle) const;
7272

7373
// inform the clients that the given entity changed its animation
7474
// used to e.g. change a npc animation to walking

src/caveexpress/shared/network/messages/TargetCaveMessage.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,35 @@ namespace caveexpress {
77
class TargetCaveMessage: public IProtocolMessage {
88
private:
99
uint8_t _targetCave; // 0 none, 100 stone
10+
float _angle; // arrow angle to target cave -1 if none
1011

1112
public:
12-
TargetCaveMessage(uint8_t targetCave) :
13-
IProtocolMessage(protocol::PROTO_TARGETCAVE), _targetCave(targetCave) {
13+
TargetCaveMessage(uint8_t targetCave, float angle) :
14+
IProtocolMessage(protocol::PROTO_TARGETCAVE), _targetCave(targetCave), _angle(angle) {
1415
}
1516

1617
PROTOCOL_CLASS_FACTORY(TargetCaveMessage);
1718
explicit TargetCaveMessage(ByteStream& input) :
18-
IProtocolMessage(protocol::PROTO_TARGETCAVE) {
19+
IProtocolMessage(protocol::PROTO_TARGETCAVE)
20+
{
1921
_targetCave = input.readByte();
22+
_angle = input.readFloat();
2023
}
2124

2225
void serialize(ByteStream& out) const override
2326
{
2427
out.addByte(_id);
2528
out.addByte(_targetCave);
29+
out.addFloat(_angle);
2630
}
2731

2832
inline uint8_t getCaveNumber() const {
2933
return _targetCave;
3034
}
35+
36+
inline float getAngle() const {
37+
return _angle;
38+
}
3139
};
3240

3341
}

src/modules/ui/nodes/UINodeSprite.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ UINodeSprite::UINodeSprite (IFrontend *frontend, int spriteWidth, int spriteHeig
99
0.0f), _movementSpeed(0.0f), _movementActive(false) {
1010
}
1111

12+
UINodeSpriteRot::UINodeSpriteRot (IFrontend *frontend, int spriteWidth, int spriteHeight)
13+
: UINodeSprite(frontend, spriteWidth, spriteHeight)
14+
{
15+
}
1216

1317
UINodeSprite::UINodeSprite (IFrontend *frontend, const EntityType& type, const Animation& animation, int spriteWidth, int spriteHeight) :
1418
UINode(frontend), _offset(0), _borderWidth(-1.0f), _borderHeight(-1.0f), _spriteWidth(

src/modules/ui/nodes/UINodeSprite.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ class UINodeSprite: public UINode {
4040
void update (uint32_t deltaTime) override;
4141
};
4242

43+
class UINodeSpriteRot: public UINodeSprite {
44+
public:
45+
float _angle = -1.f;
46+
47+
UINodeSpriteRot (IFrontend *frontend, int spriteWidth = -1, int spriteHeight = -1);
48+
};
49+
50+
4351
inline void UINodeSprite::addSprite (const SpritePtr& sprite)
4452
{
4553
_sprites.push_back(sprite);

src/modules/ui/windows/IUIMapWindow.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#define UINODE_SECONDS_REMAINING "seconds"
1010
#define UINODE_MAP "map"
1111
#define UINODE_TARGETCAVEID "targetcave"
12+
#define UINODE_TARGET_ARROW "target_arrow"
1213
#define UINODE_COLLECTED "collected"
1314
#define UINODE_TRANSFERS "transfers"
1415
#define UINODE_TRANSFERS_LEFT "transfers_left"

0 commit comments

Comments
 (0)