Web Service Integration Samples¶
1. Earn Items by Answering Surveys¶
Code
# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
TextEditState textEditState;
bool received = false;
bool pushed = false;
while (System::Update())
{
Rect{ 40, 40, 480, 140 }.rounded(10).drawShadow(Vec2{ 2, 2 }, 12, 0).draw();
if (not received)
{
if (SimpleGUI::Button(U"Answer survey and get secret code", Vec2{ 60, 60 }, 440))
{
pushed = true;
System::LaunchBrowser(U"https://forms.gle/vyiwgwNFSvZPZ8fu5");
}
SimpleGUI::Headline(U"Enter code", Vec2{ 60, 118 }, unspecified, pushed);
SimpleGUI::TextBox(textEditState, Vec2{ 220, 120 }, 160, 8, pushed);
if (SimpleGUI::Button(U"Confirm", Vec2{ 400, 120 }, 60, pushed))
{
if (textEditState.text == U"123")
{
received = true;
Print << U"Item acquired.";
}
else
{
Print << U"Invalid code.";
}
}
}
else
{
SimpleGUI::Headline(U"Thank you for answering the survey.", Vec2{ 60, 90 });
}
}
}
2. Tweet Game Score¶
Code
# include <Siv3D.hpp>
void Main()
{
Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });
int32 score = 12345;
while (System::Update())
{
if (SimpleGUI::Button(U"Tweet score", Vec2{ 40, 40 }))
{
// Including hashtags and URLs helps spread the word.
const String text = U"I scored {} points in the game!\n#Test #Siv3D\nhttps://github.com/Siv3D/OpenSiv3D"_fmt(ThousandsSeparate(score));
// Open tweet posting screen
Twitter::OpenTweetWindow(text);
}
}
}
3. Chat¶
For how to integrate with Photon, see Tutorial 75. Multiplayer.
This is a sample for sending and receiving data between players who joined the created room.
Code
# include <Siv3D.hpp>
# include "Multiplayer_Photon.hpp"
# include "PHOTON_APP_ID.SECRET"
// User-defined type
struct MyData
{
String word;
Point pos;
// Define member function for serialization support
template <class Archive>
void SIV3D_SERIALIZE(Archive& archive)
{
archive(word, pos);
}
};
class MyNetwork : public Multiplayer_Photon
{
public:
static constexpr int32 MaxPlayers = 3;
using Multiplayer_Photon::Multiplayer_Photon;
private:
Array<LocalPlayer> m_localPlayers;
void connectReturn([[maybe_unused]] const int32 errorCode, const String& errorString, const String& region, [[maybe_unused]] const String& cluster) override
{
if (m_verbose)
{
Print << U"MyNetwork::connectReturn() [Process result of attempting to connect to server]";
}
if (errorCode)
{
if (m_verbose)
{
Print << U"[Server connection failed] " << errorString;
}
return;
}
if (m_verbose)
{
Print << U"[Server connection successful]";
Print << U"[region: {}]"_fmt(region);
Print << U"[Username: {}]"_fmt(getUserName());
Print << U"[User ID: {}]"_fmt(getUserID());
}
Scene::SetBackground(ColorF{ 0.4, 0.5, 0.6 });
}
void disconnectReturn() override
{
if (m_verbose)
{
Print << U"MyNetwork::disconnectReturn() [Called when disconnected from server]";
}
m_localPlayers.clear();
Scene::SetBackground(Palette::DefaultBackground);
}
void joinRandomRoomReturn([[maybe_unused]] const LocalPlayerID playerID, const int32 errorCode, const String& errorString) override
{
if (m_verbose)
{
Print << U"MyNetwork::joinRandomRoomReturn() [Process result of attempting to join existing random room]";
}
if (errorCode == NoRandomMatchFound)
{
const RoomName roomName = (getUserName() + U"'s room-" + ToHex(RandomUint32()));
if (m_verbose)
{
Print << U"[No available random room found]";
Print << U"[Creating new room " << roomName << U"]";
}
createRoom(roomName, MaxPlayers);
return;
}
else if (errorCode)
{
if (m_verbose)
{
Print << U"[Error joining existing random room] " << errorString;
}
return;
}
if (m_verbose)
{
Print << U"[Successfully joined existing random room]";
}
}
void createRoomReturn([[maybe_unused]] const LocalPlayerID playerID, const int32 errorCode, const String& errorString) override
{
if (m_verbose)
{
Print << U"MyNetwork::createRoomReturn() [Process result of creating new room]";
}
if (errorCode)
{
if (m_verbose)
{
Print << U"[Error creating new room] " << errorString;
}
return;
}
if (m_verbose)
{
Print << U"[Successfully created room " << getCurrentRoomName() << U"]";
}
}
void joinRoomEventAction(const LocalPlayer& newPlayer, [[maybe_unused]] const Array<LocalPlayerID>& playerIDs, const bool isSelf) override
{
if (m_verbose)
{
Print << U"MyNetwork::joinRoomEventAction() [Called when someone (including yourself) joins the current room]";
}
if (m_verbose)
{
Print << U"[{} (ID: {}) joined the room. Local ID: {}] {}"_fmt(newPlayer.userName, newPlayer.userID, newPlayer.localID, (isSelf ? U"(yourself)" : U""));
m_localPlayers = getLocalPlayers();
Print << U"Current room members of " << getCurrentRoomName();
for (const auto& player : m_localPlayers)
{
Print << U"- [{}] {} (id: {}) {}"_fmt(player.localID, player.userName, player.userID, player.isHost ? U"(host)" : U"");
}
}
}
void leaveRoomEventAction(const LocalPlayerID playerID, [[maybe_unused]] const bool isInactive) override
{
if (m_verbose)
{
Print << U"MyNetwork::joinRoomEventAction() [Called when someone leaves the room]";
}
if (m_verbose)
{
for (const auto& player : m_localPlayers)
{
if (player.localID == playerID)
{
Print << U"[{} (ID: {}, Local ID: {}) left the room]"_fmt(player.userName, player.userID, player.localID);
}
}
m_localPlayers = getLocalPlayers();
Print << U"Current room members of " << getCurrentRoomName();
for (const auto& player : m_localPlayers)
{
Print << U"- [{}] {} (ID: {}) {}"_fmt(player.localID, player.userName, player.userID, player.isHost ? U"(host)" : U"");
}
}
}
void leaveRoomReturn(int32 errorCode, const String& errorString) override
{
if (m_verbose)
{
Print << U"MyNetwork::leaveRoomReturn() [Called when leaving room]";
}
m_localPlayers.clear();
if (errorCode)
{
if (m_verbose)
{
Print << U"[Error leaving room] " << errorString;
}
return;
}
}
void customEventAction(const LocalPlayerID playerID, const uint8 eventCode, const int32 data) override
{
Print << U"<<< Received from [" << playerID << U"] eventCode: " << eventCode << U", data: int32(" << data << U")";
}
void customEventAction(const LocalPlayerID playerID, const uint8 eventCode, const String& data) override
{
Print << U"<<< Received from [" << playerID << U"] eventCode: " << eventCode << U", data: String(" << data << U")";
}
void customEventAction(const LocalPlayerID playerID, const uint8 eventCode, const Point& data) override
{
Print << U"<<< Received from [" << playerID << U"] eventCode: " << eventCode << U", data: Point" << data;
}
void customEventAction(const LocalPlayerID playerID, const uint8 eventCode, const Array<int32>& data) override
{
Print << U"<<< Received from [" << playerID << U"] eventCode: " << eventCode << U", data: Array<int32>" << data;
}
void customEventAction(const LocalPlayerID playerID, const uint8 eventCode, const Array<String>& data) override
{
Print << U"<<< Received from [" << playerID << U"] eventCode: " << eventCode << U", data: Array<String>" << data;
}
// Override function called when serialized data is received for customization
void customEventAction(const LocalPlayerID playerID, const uint8 eventCode, Deserializer<MemoryViewReader>& reader) override
{
if (eventCode == 123)
{
MyData mydata;
reader(mydata);
Print << U"<<< Received MyData(" << mydata.word << U", " << mydata.pos << U") from [" << playerID << U"]";
}
}
};
void Main()
{
Window::Resize(1280, 720);
const std::string secretAppID{ SIV3D_OBFUSCATE(PHOTON_APP_ID) };
MyNetwork network{ secretAppID, U"1.0", Verbose::Yes };
while (System::Update())
{
network.update();
const bool isActive = network.isActive();
const bool isInLobby = network.isInLobby();
const bool isInRoom = network.isInRoom();
if (SimpleGUI::Button(U"Connect", Vec2{ 1000, 20 }, 160, (not isActive)))
{
const String userName = U"Siv";
network.connect(userName);
}
if (SimpleGUI::Button(U"Disconnect", Vec2{ 1000, 60 }, 160, isActive))
{
network.disconnect();
}
if (SimpleGUI::Button(U"Join Room", Vec2{ 1000, 100 }, 160, isInLobby))
{
network.joinRandomRoom(MyNetwork::MaxPlayers);
}
if (SimpleGUI::Button(U"Leave Room", Vec2{ 1000, 140 }, 160, isInRoom))
{
network.leaveRoom();
}
if (SimpleGUI::Button(U"Send int32", Vec2{ 1000, 180 }, 200, isInRoom))
{
const int32 n = Random(0, 10000);
Print << U"Sending eventCode: 0, int32(" << n << U") >>>";
network.sendEvent(0, n);
}
if (SimpleGUI::Button(U"Send String", Vec2{ 1000, 220 }, 200, isInRoom))
{
const String s = Sample({ U"Hello!", U"Thank you!", U"Nice!" });
Print << U"Sending eventCode: 0, String(" << s << U") >>>";
network.sendEvent(0, s);
}
if (SimpleGUI::Button(U"Send Point", Vec2{ 1000, 260 }, 200, isInRoom))
{
const Point pos = RandomPoint(Scene::Rect());
Print << U"Sending eventCode: 0, Point" << pos << U" >>>";
network.sendEvent(0, pos);
}
if (SimpleGUI::Button(U"Send Array<int32>", Vec2{ 1000, 300 }, 200, isInRoom))
{
Array<int32> v(3);
for (auto& n : v)
{
n = Random(0, 1000);
}
Print << U"Sending eventCode: 0, Array<int32>" << v << U" >>>";
network.sendEvent(0, v);
}
if (SimpleGUI::Button(U"Send Array<String>", Vec2{ 1000, 340 }, 200, isInRoom))
{
Array<String> words(3);
for (auto& word : words)
{
word = Sample({ U"apple", U"bird", U"cat", U"dog" });
}
Print << U"Sending eventCode: 0, Array<String>" << words << U" >>>";
network.sendEvent(0, words);
}
// Button to send random MyData
if (SimpleGUI::Button(U"Send MyData", Vec2{ 1000, 380 }, 200, isInRoom))
{
MyData myData;
myData.word = Sample({ U"apple", U"bird", U"cat", U"dog" });
myData.pos = RandomPoint(Scene::Rect());
Print << U"Sending eventCode: 123, MyData(" << myData.word << U", " << myData.pos << U") >>>";
network.sendEvent(123, Serializer<MemoryWriter>{}(myData));
}
}
}