Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
#include "Headers/PingPongScene.h"

#include "Core/Math/Headers/Transform.h"
#include "Core/Time/Headers/ApplicationTimer.h"
#include "Managers/Headers/SceneManager.h"
#include "Geometry/Material/Headers/Material.h"
#include "Geometry/Shapes/Headers/Predefined/Box3D.h"
#include "Geometry/Shapes/Headers/Predefined/Sphere3D.h"
#include "Rendering/Camera/Headers/FreeFlyCamera.h"

namespace Divide {

void PingPongScene::processGUI(const U64 deltaTime) {
    D64 FpsDisplay = Time::SecondsToMilliseconds(0.3);
    if (_guiTimers[0] >= FpsDisplay) {
        _GUI->modifyText(_ID("fpsDisplay"),
                         Util::StringFormat("FPS: %3.0f. FrameTime: %3.1f",
                                            Time::ApplicationTimer::instance().getFps(),
                                            Time::ApplicationTimer::instance().getFrameTime()));
        _guiTimers[0] = 0.0;
    }
    Scene::processGUI(deltaTime);
}

void PingPongScene::processTasks(const U64 deltaTime) {
    static vec2<F32> _sunAngle =
        vec2<F32>(0.0f, Angle::DegreesToRadians(45.0f));
    static bool direction = false;
    if (!direction) {
        _sunAngle.y += 0.005f;
        _sunAngle.x += 0.005f;
    } else {
        _sunAngle.y -= 0.005f;
        _sunAngle.x -= 0.005f;
    }

    if (_sunAngle.y <= Angle::DegreesToRadians(25) ||
        _sunAngle.y >= Angle::DegreesToRadians(70))
        direction = !direction;

    _sunvector =
        vec3<F32>(-cosf(_sunAngle.x) * sinf(_sunAngle.y), -cosf(_sunAngle.y),
                  -sinf(_sunAngle.x) * sinf(_sunAngle.y));

    _sun.lock()->get<PhysicsComponent>()->setPosition(_sunvector);
    _currentSky.lock()->getNode<Sky>()->setSunProperties(_sunvector,
                                                         _sun.lock()->getNode<Light>()->getDiffuseColor());

    Scene::processTasks(deltaTime);
}

void PingPongScene::resetGame() {
    _directionTowardsAdversary = true;
    _upwardsDirection = false;
    _touchedAdversaryTableHalf = false;
    _touchedOwnTableHalf = false;
    _lost = false;
    _sideDrift = 0;
    clearTasks();
    _ballSGN.lock()->get<PhysicsComponent>()->setPosition(vec3<F32>(0, 2, 2));
}

void PingPongScene::serveBall(I64 btnGUID) {
    _GUI->modifyText(_ID("insults"), "");
    resetGame();

    removeTask(getGUID());

    TaskHandle newGame(CreateTask(getGUID(),
                               DELEGATE_BIND(&PingPongScene::test, this,
                               std::placeholders::_1,
                               rand() % 5,
                               CallbackParam::TYPE_INTEGER)));
    newGame.startTask(Task::TaskPriority::HIGH);
    registerTask(newGame);
}

void PingPongScene::test(const std::atomic_bool& stopRequested, cdiggins::any a, CallbackParam b) {
    while (!stopRequested) {
        bool updated = false;
        stringImpl message;
        PhysicsComponent* ballTransform =
            _ballSGN.lock()->get<PhysicsComponent>();
        vec3<F32> ballPosition = ballTransform->getPosition();

        SceneGraphNode_ptr table(_sceneGraph.findNode("table").lock());
        SceneGraphNode_ptr net(_sceneGraph.findNode("net").lock());
        SceneGraphNode_ptr opponent(_sceneGraph.findNode("opponent").lock());
        SceneGraphNode_ptr paddle(_sceneGraph.findNode("paddle").lock());

        vec3<F32> paddlePosition =
            paddle->get<PhysicsComponent>()->getPosition();
        vec3<F32> opponentPosition =
            opponent->get<PhysicsComponent>()->getPosition();
        vec3<F32> tablePosition =
            table->get<PhysicsComponent>()->getPosition();

        // Is the ball coming towards us or towards the opponent?
        _directionTowardsAdversary ? ballPosition.z -= 0.11f : ballPosition.z +=
                                                               0.11f;
        // Up or down?
        _upwardsDirection ? ballPosition.y += 0.084f : ballPosition.y -= 0.084f;

        // Is the ball moving to the right or to the left?
        ballPosition.x += _sideDrift * 0.15f;
        if (opponentPosition.x != ballPosition.x)
            opponent->get<PhysicsComponent>()->translateX(
                ballPosition.x - opponentPosition.x);

        ballTransform->translate(ballPosition - ballTransform->getPosition());

        // Did we hit the table? Bounce then ...
        if (table->get<BoundsComponent>()
                 ->getBoundingBox().collision(_ballSGN.lock()->get<BoundsComponent>()
                                                             ->getBoundingBox()))
        {
            if (ballPosition.z > tablePosition.z) {
                _touchedOwnTableHalf = true;
                _touchedAdversaryTableHalf = false;
            } else {
                _touchedOwnTableHalf = false;
                _touchedAdversaryTableHalf = true;
            }
            _upwardsDirection = true;
        }
        // Kinetic  energy depletion
        if (ballPosition.y > 2.1f) _upwardsDirection = false;

        // Did we hit the paddle?
        if (_ballSGN.lock()->get<BoundsComponent>()->getBoundingBox().collision(paddle->get<BoundsComponent>()->getBoundingBox())) {
            _sideDrift = ballPosition.x - paddlePosition.x;
            // If we hit the ball with the upper margin of the paddle, add a slight
            // impuls to the ball
            if (ballPosition.y >= paddlePosition.y) ballPosition.z -= 0.12f;

            _directionTowardsAdversary = true;
        }

        if (ballPosition.y + 0.75f < table->get<BoundsComponent>()->getBoundingBox().getMax().y) {
            // If we hit the ball and it landed on the opponent's table half
            // Or if the opponent hit the ball and it landed on our table half
            if ((_touchedAdversaryTableHalf && _directionTowardsAdversary) ||
                (!_directionTowardsAdversary && !_touchedOwnTableHalf))
                _lost = false;
            else
                _lost = true;

            updated = true;
        }
        // Did we win or lose?
        if (ballPosition.z >= paddlePosition.z) {
            _lost = true;
            updated = true;
        }
        if (ballPosition.z <= opponentPosition.z) {
            _lost = false;
            updated = true;
        }

        if (_ballSGN.lock()->get<BoundsComponent>()->getBoundingBox().collision(net->get<BoundsComponent>()->getBoundingBox())) {
            if (_directionTowardsAdversary) {
                // Did we hit the net?
                _lost = true;
            } else {
                // Did the opponent hit the net?
                _lost = false;
            }
            updated = true;
        }

        // Did we hit the opponent? Then change ball direction ... BUT ...
        // Add a small chance that we win
        if (Random(30) != 2)
            if (_ballSGN.lock()->get<BoundsComponent>()
                               ->getBoundingBox().collision(opponent->get<BoundsComponent>()
                                                                    ->getBoundingBox())) {
                _sideDrift =
                    ballPosition.x -
                    opponent->get<PhysicsComponent>()->getPosition().x;
                _directionTowardsAdversary = false;
            }
        // Add a spin effect to the ball
        ballTransform->rotate(vec3<F32>(ballPosition.z, 1, 1));

        if (updated) {
            if (_lost) {
                message = "You lost!";
                _score--;

                if (b == CallbackParam::TYPE_INTEGER) {
                    I32 quote = a.constant_cast<I32>();
                    if (_score % 3 == 0)
                        _GUI->modifyText(_ID("insults"), _quotes[quote]);
                }
            } else {
                message = "You won!";
                _score++;
            }

            _GUI->modifyText(_ID("Score"), Util::StringFormat("Score: %d", _score));
            _GUI->modifyText(_ID("Message"), (char*)message.c_str());
            resetGame();
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(30));
    }
}

void PingPongScene::processInput(const U64 deltaTime) {
    if (_freeFly) {
        _wasInFreeFly = true;
        return;
    }
    if (_wasInFreeFly) {
        // Position the camera
        _paddleCam->setPitch(-90);
        _paddleCam->setYaw(0);
        _paddleCam->setRoll(0);
        _wasInFreeFly = false;
    }
    // Move FB = Forward/Back = up/down
    // Move LR = Left/Right
    static F32 paddleMovementDivisor = 10;
    // Camera controls
    if (state().angleLR() != SceneState::MoveDirection::NONE) {
        _paddleCam->rotateYaw(to_float(state().angleLR()));
    }
    if (state().angleUD() != SceneState::MoveDirection::NONE) {
        _paddleCam->rotatePitch(to_float(state().angleUD()));
    }

    SceneGraphNode_ptr paddle(_sceneGraph.findNode("paddle").lock());

    vec3<F32> pos = paddle->get<PhysicsComponent>()->getPosition();

    // Paddle movement is limited to the [-3,3] range except for Y-descent
    if (state().moveFB() != SceneState::MoveDirection::NONE) {
        if ((state().moveFB() == SceneState::MoveDirection::POSITIVE && pos.y >= 3) ||
            (state().moveFB() == SceneState::MoveDirection::NEGATIVE && pos.y <= 0.5f))
            return;
        paddle->get<PhysicsComponent>()->translateY(to_int(state().moveFB()) / paddleMovementDivisor);
    }

    if (state().moveLR() != SceneState::MoveDirection::NONE) {
        // Left/right movement is flipped for proper control
        if ((state().moveLR() == SceneState::MoveDirection::NEGATIVE && pos.x >= 3) ||
            (state().moveLR() == SceneState::MoveDirection::POSITIVE && pos.x <= -3))
            return;
        paddle->get<PhysicsComponent>()->translateX(to_int(state().moveLR()) / paddleMovementDivisor);
    }
}

bool PingPongScene::load(const stringImpl& name, GUI* const gui) {
    _freeFly = false;
    _wasInFreeFly = false;

    // Load scene resources
    bool loadState = SCENE_LOAD(name, gui, true, true);
    // Add a light
    _sun = addLight(LightType::DIRECTIONAL, _sceneGraph.getRoot());
    _currentSky = addSky();
    _freeFlyCam = &renderState().getCamera();
    _paddleCam = renderState().getCameraMgr().createCamera("paddleCam", Camera::CameraType::FREE_FLY);
    _paddleCam->fromCamera(*_freeFlyCam);
    // Position the camera
    // renderState().getCamera().setPitch(-90);
    _paddleCam->lockMovement(true);
    _paddleCam->setEye(vec3<F32>(0, 2.5f, 6.5f));
    _freeFlyCam->setEye(vec3<F32>(0, 2.5f, 6.5f));

    return loadState;
}

U16 PingPongScene::registerInputActions() {
    U16 actionID = Scene::registerInputActions();

    //ToDo: Move these to per-scene XML file
    PressReleaseActions actions;

    _input->actionList().registerInputAction(actionID, [this](InputParams param) {serveBall(-1);});
    actions._onReleaseAction = actionID;
    _input->addJoystickMapping(Input::Joystick::JOYSTICK_1, Input::JoystickElement(Input::JoystickElementType::BUTTON_PRESS, 0), actions);
    actionID++;

    _input->actionList().registerInputAction(actionID, [this](InputParams param) {
        _freeFly = !_freeFly;
        if (!_freeFly)
            renderState().getCameraMgr().pushActiveCamera(_paddleCam);
        else
            renderState().getCameraMgr().popActiveCamera();
    });
    actions._onReleaseAction = actionID;
    _input->addKeyMapping(Input::KeyCode::KC_L, actions);

    return actionID++;
}

bool PingPongScene::loadResources(bool continueOnErrors) {
    static const U32 lightMask = to_const_uint(SGNComponent::ComponentType::PHYSICS) |
                                 to_const_uint(SGNComponent::ComponentType::BOUNDS) |
                                 to_const_uint(SGNComponent::ComponentType::RENDERING);
    static const U32 normalMask = lightMask | 
                                  to_const_uint(SGNComponent::ComponentType::NAVIGATION);

    // Create a ball
    ResourceDescriptor minge("Ping Pong Ball");
    _ball = CreateResource<Sphere3D>(minge);
    _ball->setResolution(16);
    _ball->setRadius(0.1f);
    _ball->getMaterialTpl()->setDiffuse(vec4<F32>(0.4f, 0.4f, 0.4f, 1.0f));
    _ball->getMaterialTpl()->setShininess(36.8f);
    _ball->getMaterialTpl()->setSpecular(
        vec4<F32>(0.774597f, 0.774597f, 0.774597f, 1.0f));
    _ballSGN = _sceneGraph.getRoot().addNode(*_ball, normalMask, PhysicsGroup::GROUP_KINEMATIC, "PingPongBallSGN");
    _ballSGN.lock()->get<PhysicsComponent>()->translate(vec3<F32>(0, 2, 2));

    /*ResourceDescriptor tempLight("Light Omni");
    tempLight.setEnumValue(LIGHT_TYPE_POINT);
    Light* light = CreateResource<Light>(tempLight);
    _sceneGraph->getRoot()->addNode(*light, lightMask);
    light->setRange(30.0f);
    light->setCastShadows(false);
    light->setPosition(vec3<F32>(0, 6, 2));
    */
    const vec2<U16>& resolution = _GUI->getDisplayResolution();
    // Buttons and text labels
    _GUI->addButton(_ID("Serve"), "Serve",
                    vec2<I32>(to_int(resolution.width - 120),
                              to_int(resolution.height / 1.1f)),
                    vec2<U32>(100, 25), vec3<F32>(0.65f),
                    DELEGATE_BIND(&PingPongScene::serveBall, this, std::placeholders::_1));

    _GUI->addText(_ID("Score"),
                  vec2<I32>(to_int(resolution.width - 120),
                            to_int(resolution.height / 1.3f)),
                  Font::DIVIDE_DEFAULT,
                  vec4<U8>(255, 0, 0, 255),
                  Util::StringFormat("Score: %d", 0));

    _GUI->addText(_ID("Message"),
                  vec2<I32>(to_int(resolution.width - 120),
                            to_int(resolution.height / 1.5f)),
                  Font::DIVIDE_DEFAULT,
                  vec4<U8>(255, 0, 0, 255),
                  "");
    _GUI->addText(_ID("insults"),
                  vec2<I32>(resolution.width / 4,
                            resolution.height / 3),
                  Font::DIVIDE_DEFAULT,
                  vec4<U8>(0, 255, 0, 255),
                  "");
    _GUI->addText(_ID("fpsDisplay"),  // Unique ID
                  vec2<I32>(60, 60),  // Position
                  Font::DIVIDE_DEFAULT,  // Font
                  vec4<U8>(0, 50, 255, 255),// Color
                  Util::StringFormat("FPS: %d", 0));  // Text and arguments
    // Add some taunts
    _quotes.push_back("Ha ha ... even Odin's laughin'!");
    _quotes.push_back("If you're a ping-pong player, I'm Jimmy Page");
    _quotes.push_back(
        "Ooolee, ole ole ole, see the ball? ... It's past your end");
    _quotes.push_back(
        "You're lucky the room's empty. I'd be so ashamed otherwise if I were "
        "you");
    _quotes.push_back("It's not the hard. Even a monkey can do it.");

    _guiTimers.push_back(0.0);  // Fps
    _taskTimers.push_back(0.0);  // Light

    return true;
}

};

Commits for Divide-Framework/trunk/Source Code/Scenes/PingPongScene/PingPongScene.cpp

Diff revisions: vs.
Revision Author Commited Message
704 Diff Diff IonutCava picture IonutCava Thu 12 May, 2016 16:24:17 +0000

[IonutCava]
- More work on the DefaultScene:
— Automatically list each available scene as a button that will load the actual desired scene

703 Diff Diff IonutCava picture IonutCava Wed 11 May, 2016 15:44:57 +0000

[IonutCava]
- Finish XML-based control bindings:
— Allow per bind input params (key id, mouse button index, joystick control data, etc)
— Allow mouse binding (with up to 7 buttons)
— Allow up to 4 joysticks (for now) with 120+ button, POV, Axis, Slider and Vector binding support for each
- Change all hashes in code from U32 to size_t for compatibility with STL/Boost

699 Diff Diff IonutCava picture IonutCava Tue 10 May, 2016 16:16:57 +0000

[IonutCava]
- Initial key binding code with external XML support
— Allow separation of actions and keys
— Specify actions in code by id
— Specify action id for each Key state
— Allow key modifiers: Left/Right Alt, Left/Right Ctrl

- Initial default scene code

696 Diff Diff IonutCava picture IonutCava Mon 09 May, 2016 16:14:09 +0000

[IonutCava]
- More physics system preparation:
— Define specific px groups for nodes: static, kinematic, dynamic, ragdoll, etc

693 Diff Diff IonutCava picture IonutCava Thu 28 Apr, 2016 16:19:35 +0000

[IonutCava]
- Cleanup Time and Profiling code

687 Diff Diff IonutCava picture IonutCava Thu 21 Apr, 2016 20:44:41 +0000

[IonutCava]
- Fix stack overflow issue with SGN relationship cache invalidation
- Code cleanup

686 Diff Diff IonutCava picture IonutCava Thu 21 Apr, 2016 16:24:19 +0000

[IonutCava]
- Refactor the scene self-registering system to prevent linker related issues
- Add a SGNRelationshipCache class that can quickly verify if any 2 given nodes are related in any way
— This should speed up Octree updates by a lot

note: The template refactoring code has significantly slowed down performance for reasons yet unknown. Investigating.

680 Diff Diff IonutCava picture IonutCava Thu 14 Apr, 2016 16:15:38 +0000

[IonutCava]
- Added a mat2 class (untested)
- Added static asserts to matrices, vectors and quaternions to allow only arithmetic (sans bool) data types
- Added more vector unit tests
- Added unit tests for matrices
- D32 finally renamed to D64 as the VC++ compiler is considered as the reference compiler

670 Diff Diff IonutCava picture IonutCava Wed 06 Apr, 2016 16:21:35 +0000

[IonutCava]
- getInstance() renamed to instance() for simplicity (should really go away altogether, but that’s a different issue)
- some particle emitter threading updates

669 IonutCava picture IonutCava Mon 04 Apr, 2016 16:15:35 +0000

[IonutCava]
- Move Task creation calls to TaskPool.h
- Allow tasks to use any pool, but default behaviour is to use the Kernel’s main task pool
- Change image transparency check to use the task pool instead of OpenMP
— Perfect place for future parallel_for implementation
- Warning fixes
- Some method renaming for improved readability