/
main.cpp
176 lines (146 loc) · 5.45 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Network.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
// Do we want to showcase direct JNI/NDK interaction?
// Undefine this to get real cross-platform code.
// Uncomment this to try JNI access; this seems to be broken in latest NDKs
//#define USE_JNI
#if defined(USE_JNI)
// These headers are only needed for direct NDK/JDK interaction
#include <android/native_activity.h>
#include <jni.h>
// Since we want to get the native activity from SFML, we'll have to use an
// extra header here:
#include <SFML/System/NativeActivity.hpp>
// NDK/JNI sub example - call Java code from native code
int vibrate(sf::Time duration)
{
// First we'll need the native activity handle
ANativeActivity* activity = sf::getNativeActivity();
// Retrieve the JVM and JNI environment
JavaVM* vm = activity->vm;
JNIEnv* env = activity->env;
// First, attach this thread to the main thread
JavaVMAttachArgs attachargs;
attachargs.version = JNI_VERSION_1_6;
attachargs.name = "NativeThread";
attachargs.group = nullptr;
jint res = vm->AttachCurrentThread(&env, &attachargs);
if (res == JNI_ERR)
return EXIT_FAILURE;
// Retrieve class information
jclass natact = env->FindClass("android/app/NativeActivity");
jclass context = env->FindClass("android/content/Context");
// Get the value of a constant
jfieldID fid = env->GetStaticFieldID(context, "VIBRATOR_SERVICE", "Ljava/lang/String;");
jobject svcstr = env->GetStaticObjectField(context, fid);
// Get the method 'getSystemService' and call it
jmethodID getss = env->GetMethodID(natact, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
jobject vib_obj = env->CallObjectMethod(activity->clazz, getss, svcstr);
// Get the object's class and retrieve the member name
jclass vib_cls = env->GetObjectClass(vib_obj);
jmethodID vibrate = env->GetMethodID(vib_cls, "vibrate", "(J)V");
// Determine the timeframe
jlong length = duration.asMilliseconds();
// Bzzz!
env->CallVoidMethod(vib_obj, vibrate, length);
// Free references
env->DeleteLocalRef(vib_obj);
env->DeleteLocalRef(vib_cls);
env->DeleteLocalRef(svcstr);
env->DeleteLocalRef(context);
env->DeleteLocalRef(natact);
// Detach thread again
vm->DetachCurrentThread();
}
#endif
// This is the actual Android example. You don't have to write any platform
// specific code, unless you want to use things not directly exposed.
// ('vibrate()' in this example; undefine 'USE_JNI' above to disable it)
int main(int argc, char* argv[])
{
sf::VideoMode screen(sf::VideoMode::getDesktopMode());
sf::RenderWindow window(screen, "");
window.setFramerateLimit(30);
sf::Texture texture;
if (!texture.loadFromFile("image.png"))
return EXIT_FAILURE;
sf::Sprite image(texture);
image.setPosition(sf::Vector2f(screen.size) / 2.f);
image.setOrigin(sf::Vector2f(texture.getSize()) / 2.f);
sf::Font font;
if (!font.loadFromFile("tuffy.ttf"))
return EXIT_FAILURE;
sf::Text text(font, "Tap anywhere to move the logo.", 64);
text.setFillColor(sf::Color::Black);
text.setPosition({10, 10});
sf::View view = window.getDefaultView();
sf::Color background = sf::Color::White;
// We shouldn't try drawing to the screen while in background
// so we'll have to track that. You can do minor background
// work, but keep battery life in mind.
bool active = true;
while (window.isOpen())
{
while (const auto event = active ? window.pollEvent() : window.waitEvent())
{
if (event.is<sf::Event::Closed>())
{
window.close();
}
else if (const auto* keyPressed = event.getIf<sf::Event::KeyPressed>())
{
if (keyPressed->code == sf::Keyboard::Key::Escape)
window.close();
}
else if (const auto* resized = event.getIf<sf::Event::Resized>())
{
const auto size = sf::Vector2f(resized->size);
view.setSize(size);
view.setCenter(size / 2.f);
window.setView(view);
}
else if (event.is<sf::Event::FocusLost>())
{
background = sf::Color::Black;
}
else if (event.is<sf::Event::FocusGained>())
{
background = sf::Color::White;
}
// On Android MouseLeft/MouseEntered are (for now) triggered,
// whenever the app loses or gains focus.
else if (event.is<sf::Event::MouseLeft>())
{
active = false;
}
else if (event.is<sf::Event::MouseEntered>())
{
active = true;
}
else if (const auto* touchBegan = event.getIf<sf::Event::TouchBegan>())
{
if (touchBegan->finger == 0)
{
image.setPosition(sf::Vector2f(touchBegan->position));
#if defined(USE_JNI)
vibrate(sf::milliseconds(10));
#endif
}
}
}
if (active)
{
window.clear(background);
window.draw(image);
window.draw(text);
window.display();
}
else
{
sf::sleep(sf::milliseconds(100));
}
}
}