void Game::shutdown() { // Call user finalization. if (_state != UNINITIALIZED) { GP_ASSERT(_animationController); GP_ASSERT(_audioController); GP_ASSERT(_physicsController); GP_ASSERT(_aiController); Platform::signalShutdown(); // Call user finalize finalize(); // Call script finalize if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, finalize)); // Destroy script target so no more script events are fired SAFE_DELETE(_scriptTarget); // Shutdown scripting system first so that any objects allocated in script are released before our subsystems are released _scriptController->finalize(); unsigned int gamepadCount = Gamepad::getGamepadCount(); for (unsigned int i = 0; i < gamepadCount; i++) { Gamepad* gamepad = Gamepad::getGamepad(i, false); SAFE_DELETE(gamepad); } _animationController->finalize(); SAFE_DELETE(_animationController); _audioController->finalize(); SAFE_DELETE(_audioController); _physicsController->finalize(); SAFE_DELETE(_physicsController); _aiController->finalize(); SAFE_DELETE(_aiController); ControlFactory::finalize(); Theme::finalize(); // Note: we do not clean up the script controller here // because users can call Game::exit() from a script. SAFE_DELETE(_audioListener); FrameBuffer::finalize(); RenderState::finalize(); SAFE_DELETE(_properties); _state = UNINITIALIZED; } }
bool Game::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelta) { if (mouseEvent(evt, x, y, wheelDelta)) return true; if (_scriptTarget) return _scriptTarget->fireScriptEvent<bool>(GP_GET_SCRIPT_EVENT(GameScriptTarget, mouseEvent), evt, x, y, wheelDelta); return false; }
void Game::resizeEventInternal(unsigned int width, unsigned int height) { // Update the width and height of the game if (_width != width || _height != height) { _width = width; _height = height; resizeEvent(width, height); if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, resizeEvent), width, height); } }
void Transform::transformChanged() { if (_listeners) { for (std::list<TransformListener>::iterator itr = _listeners->begin(); itr != _listeners->end(); ++itr) { TransformListener& l = *itr; GP_ASSERT(l.listener); l.listener->transformChanged(this, l.cookie); } } fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(Transform, transformChanged), dynamic_cast<void*>(this)); }
void Game::updateOnce() { GP_ASSERT(_animationController); GP_ASSERT(_audioController); GP_ASSERT(_physicsController); GP_ASSERT(_aiController); // Update Time. static double lastFrameTime = getGameTime(); double frameTime = getGameTime(); float elapsedTime = (frameTime - lastFrameTime); lastFrameTime = frameTime; // Update the internal controllers. _animationController->update(elapsedTime); _physicsController->update(elapsedTime); _aiController->update(elapsedTime); _audioController->update(elapsedTime); if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, update), elapsedTime); }
void AnimationClip::onBegin() { this->addRef(); // Initialize animation to play. setClipStateBit(CLIP_IS_STARTED_BIT); if (_speed >= 0) { _elapsedTime = (Game::getGameTime() - _timeStarted) * _speed; if (_listeners) *_listenerItr = _listeners->begin(); } else { _elapsedTime = _activeDuration + (Game::getGameTime() - _timeStarted) * _speed; if (_listeners) *_listenerItr = _listeners->end(); } // Notify begin listeners if any. if (_beginListeners) { std::vector<Listener*>::iterator listener = _beginListeners->begin(); while (listener != _beginListeners->end()) { GP_ASSERT(*listener); (*listener)->animationEvent(this, Listener::BEGIN); listener++; } } // Fire script begin event fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(AnimationClip, clipBegin), this); this->release(); }
void AnimationClip::onEnd() { this->addRef(); _blendWeight = 1.0f; resetClipStateBit(CLIP_ALL_BITS); // Notify end listeners if any. if (_endListeners) { std::vector<Listener*>::iterator listener = _endListeners->begin(); while (listener != _endListeners->end()) { GP_ASSERT(*listener); (*listener)->animationEvent(this, Listener::END); listener++; } } // Fire script end event fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(AnimationClip, clipEnd), this); this->release(); }
void Game::gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad) { gamepadEvent(evt, gamepad); if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, gamepadEvent), evt, gamepad); }
void Game::gestureDropEventInternal(int x, int y) { gestureDropEvent(x, y); if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, gestureDropEvent), x, y); }
void Game::gestureLongTapEventInternal(int x, int y, float duration) { gestureLongTapEvent(x, y, duration); if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, gestureLongTapevent), x, y, duration); }
void Game::gesturePinchEventInternal(int x, int y, float scale) { gesturePinchEvent(x, y, scale); if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, gesturePinchEvent), x, y, scale); }
void Game::gestureSwipeEventInternal(int x, int y, int direction) { gestureSwipeEvent(x, y, direction); if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, gestureSwipeEvent), x, y, direction); }
void Game::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex) { touchEvent(evt, x, y, contactIndex); if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, touchEvent), evt, x, y, contactIndex); }
void Game::keyEventInternal(Keyboard::KeyEvent evt, int key) { keyEvent(evt, key); if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, keyEvent), evt, key); }
void Game::frame() { if (!_initialized) { // Perform lazy first time initialization initialize(); if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, initialize)); _initialized = true; // Fire first game resize event Platform::resizeEventInternal(_width, _height); } static double lastFrameTime = Game::getGameTime(); double frameTime = getGameTime(); // Fire time events to scheduled TimeListeners fireTimeEvents(frameTime); if (_state == Game::RUNNING) { GP_ASSERT(_animationController); GP_ASSERT(_audioController); GP_ASSERT(_physicsController); GP_ASSERT(_aiController); // Update Time. float elapsedTime = (frameTime - lastFrameTime); lastFrameTime = frameTime; // Update the scheduled and running animations. _animationController->update(elapsedTime); // Update the physics. _physicsController->update(elapsedTime); // Update AI. _aiController->update(elapsedTime); // Update gamepads. Gamepad::updateInternal(elapsedTime); // Application Update. update(elapsedTime); // Update forms. Form::updateInternal(elapsedTime); // Run script update. if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, update), elapsedTime); // Audio Rendering. _audioController->update(elapsedTime); // Graphics Rendering. render(elapsedTime); // Run script render. if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, render), elapsedTime); // Update FPS. ++_frameCount; if ((Game::getGameTime() - _frameLastFPS) >= 1000) { _frameRate = _frameCount; _frameCount = 0; _frameLastFPS = getGameTime(); } } else if (_state == Game::PAUSED) { // Update gamepads. Gamepad::updateInternal(0); // Application Update. update(0); // Update forms. Form::updateInternal(0); // Script update. if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, update), 0); // Graphics Rendering. render(0); // Script render. if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, render), 0); } }
bool AnimationClip::update(float elapsedTime) { if (isClipStateBitSet(CLIP_IS_PAUSED_BIT)) { return false; } if (isClipStateBitSet(CLIP_IS_MARKED_FOR_REMOVAL_BIT)) { // If the marked for removal bit is set, it means stop() was called on the AnimationClip at some point // after the last update call. Reset the flag, and return true so the AnimationClip is removed from the // running clips on the AnimationController. onEnd(); return true; } if (!isClipStateBitSet(CLIP_IS_STARTED_BIT)) { // Clip is just starting onBegin(); } else { // Clip was already running _elapsedTime += elapsedTime * _speed; if (_repeatCount == REPEAT_INDEFINITE && _elapsedTime <= 0) { // Elapsed time is moving backwards, so wrap it back around the end when it falls below zero _elapsedTime = _activeDuration + _elapsedTime; // TODO: account for _loopBlendTime } } // Current time within a loop of the clip float currentTime = 0.0f; // Check to see if clip is complete. if (_repeatCount != REPEAT_INDEFINITE && ((_speed >= 0.0f && _elapsedTime >= _activeDuration) || (_speed <= 0.0f && _elapsedTime <= 0.0f))) { // We finished our active duration (including repeats), so clamp to our end value. resetClipStateBit(CLIP_IS_STARTED_BIT); // Ensure we end off at the endpoints of our clip (-speed==0, +speed==_duration) currentTime = _speed < 0.0f ? 0.0f : _duration; } else { // If _duration == 0, we have a "pose". Just set currentTime to 0. if (_duration == 0) { currentTime = 0.0f; } else { // Animation is running normally. currentTime = fmodf(_elapsedTime, _duration + _loopBlendTime); } } // Notify any listeners of Animation events. if (_listeners) { GP_ASSERT(_listenerItr); if (_speed >= 0.0f) { while (*_listenerItr != _listeners->end() && _elapsedTime >= (long) (**_listenerItr)->_eventTime) { GP_ASSERT(_listenerItr); GP_ASSERT(**_listenerItr); GP_ASSERT((**_listenerItr)->_listener); (**_listenerItr)->_listener->animationEvent(this, Listener::TIME); ++(*_listenerItr); } } else { while (*_listenerItr != _listeners->begin() && _elapsedTime <= (long) (**_listenerItr)->_eventTime) { GP_ASSERT(_listenerItr); GP_ASSERT(**_listenerItr); GP_ASSERT((**_listenerItr)->_listener); (**_listenerItr)->_listener->animationEvent(this, Listener::TIME); --(*_listenerItr); } } } // Fire script update event fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(AnimationClip, clipUpdate), this, _elapsedTime); // Add back in start time, and divide by the total animation's duration to get the actual percentage complete GP_ASSERT(_animation); // Compute percentage complete for the current loop (prevent a divide by zero if _duration==0). // Note that we don't use (currentTime/(_duration+_loopBlendTime)). That's because we want a // % value that is outside the 0-1 range for loop smoothing/blending purposes. float percentComplete = _duration == 0 ? 1 : currentTime / (float)_duration; if (_loopBlendTime == 0.0f) percentComplete = MATH_CLAMP(percentComplete, 0.0f, 1.0f); // If we're cross fading, compute blend weights if (isClipStateBitSet(CLIP_IS_FADING_OUT_BIT)) { GP_ASSERT(_crossFadeToClip); GP_ASSERT(_crossFadeOutDuration > 0); if (isClipStateBitSet(CLIP_IS_FADING_OUT_STARTED_BIT)) // Calculate elapsed time since the fade out begin. { GP_ASSERT(_crossFadeToClip); _crossFadeOutElapsed = (Game::getGameTime() - _crossFadeToClip->_timeStarted) * fabs(_speed); resetClipStateBit(CLIP_IS_FADING_OUT_STARTED_BIT); } else { // continue tracking elapsed time. _crossFadeOutElapsed += elapsedTime * fabs(_speed); } if (_crossFadeOutElapsed < _crossFadeOutDuration) { // Calculate this clip's blend weight. float tempBlendWeight = ((float)_crossFadeOutDuration - _crossFadeOutElapsed) / (float)_crossFadeOutDuration; // If this clip is fading in, adjust the crossfade clip's weight to be a percentage of your current blend weight if (isClipStateBitSet(CLIP_IS_FADING_IN_BIT)) { _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight) * _blendWeight; _blendWeight -= _crossFadeToClip->_blendWeight; } else { // Just set the blend weight. _crossFadeToClip->_blendWeight = (1.0f - tempBlendWeight); _blendWeight = tempBlendWeight; } } else { // Fade is done. _crossFadeToClip->_blendWeight = 1.0f; _blendWeight = 0.0f; resetClipStateBit(CLIP_IS_STARTED_BIT); resetClipStateBit(CLIP_IS_FADING_OUT_BIT); _crossFadeToClip->resetClipStateBit(CLIP_IS_FADING_IN_BIT); SAFE_RELEASE(_crossFadeToClip); } } // Evaluate this clip. Animation::Channel* channel = NULL; AnimationValue* value = NULL; AnimationTarget* target = NULL; size_t channelCount = _animation->_channels.size(); float percentageStart = (float)_startTime / (float)_animation->_duration; float percentageEnd = (float)_endTime / (float)_animation->_duration; float percentageBlend = (float)_loopBlendTime / (float)_animation->_duration; for (size_t i = 0; i < channelCount; i++) { channel = _animation->_channels[i]; GP_ASSERT(channel); target = channel->_target; GP_ASSERT(target); value = _values[i]; GP_ASSERT(value); // Evaluate the point on Curve GP_ASSERT(channel->getCurve()); channel->getCurve()->evaluate(percentComplete, percentageStart, percentageEnd, percentageBlend, value->_value); // Set the animation value on the target property. target->setAnimationPropertyValue(channel->_propertyId, value, _blendWeight); } // When ended. Probably should move to it's own method so we can call it when the clip is ended early. if (isClipStateBitSet(CLIP_IS_MARKED_FOR_REMOVAL_BIT) || !isClipStateBitSet(CLIP_IS_STARTED_BIT)) { onEnd(); return true; } return false; }