• Content count

  • Joined

  • Last visited

Community Reputation

396 Neutral

About tookie

  • Rank
  1. Yes, it´s all ready to go in the code I posted Thanks, all my doubts are cleared up now
  2. So, a very basic game loop for a 2D game, like this one, is all I need? no sprite interpolation at all? unless I use a physics engine like Box2D? (and add a lot of rigid bodies to the world), or make an online game, right? I guess the only "physics" I'll use is sprite movement: pos += vel * dt
  3. My character has a jetpack, so I want to throw some fire particles when the character is flying (the particles must follow the sprite movement), that's why I asked... but yes, it sounds like a waste of time, I'll see may I need it for the particles integration?... about fixed timestep, I thought it was mandatory for every game :/ ... for some reason, I don't like the Sleep() call you see on most game programming tutorials Ok, thanks!
  4. I should check user input in the inner loop.. ok... but how about system events? like close window, lost focus, etc? Another questions: 1) if I add a particle system, should I use the rendering interpolation technique on every particle, every frame? Let's say I treat each particle as a sprite (I didn't designed my particle system yet) 2) Is 30 updates per sec good enough for a little 2D tilemap based game? Too much? (I'm not using any physics engine like Box2D) 3) If I let the player enable/disable Vsync, should I change anything about the game updates? or it only affects rendering?
  5. I see... now I get it :)   Ok, I may add multiplayer for my game in the future, so I will keep using the interpolation method Thanks!
  6. Hello After reading the famous article Fix your timestep, I'm trying to implement 2D sprite interpolation in my engine This is my sprite state struct // Sprite state for the interpolation struct SpriteState { Vec2 position; float angle; };  My interpolation functions // Return an interpolated position between previous and current state // Scalar inline auto calcInterpolation(float previous, float current, float alpha) -> float { return current * alpha + previous * (1.0f - alpha); } // Vectors inline auto calcInterpolation(const Vec2& previous, const Vec2& current, float alpha) -> Vec2 { return { current * alpha + previous * (1.0f - alpha) }; }  My Sprite class looks like this class Sprite { public: // ctor Sprite(const Texture2D& texture, const AABB<int>& rect, const AnimationState& animState = {}); /// just to test void useInterpolation(bool active = true); /// just to test void setPosition(const Vec2& pos); void setRotation(float angle); void update(float dt); void render(QuadRenderer& quadRenderer, float alpha); private: /// just to test bool m_usingInterpolation = true; /// just to test // Sprite states for the interpolation // (position and rotation) SpriteState m_currState, m_prevState; // Other transformations Transformations m_transform; // Animation state for this sprite AnimationState m_animState; // Sprite coordinates from the Texture Atlas AABB<int> m_spriteRect; // Normalized texture coordinates AABB<float> m_uvCoords; // Texture data const Texture2D& m_texture; // Sprite color Color m_color; };  Sprite update and render functions void Sprite::update(float dt) { m_prevState = m_currState; /// TODO: if animated, handle animation } void Sprite::render(QuadRenderer& quadRenderer, float alpha) { SpriteState state; /// just to test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if (m_usingInterpolation) { // Handle interpolation state.position = calcInterpolation(m_prevState.position, m_currState.position, alpha); state.angle = calcInterpolation(m_prevState.angle, m_currState.angle, alpha); } else { // If not using interpolation, just take the current state state = m_currState; } /// just to test !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Update matrix m_transform.updateMatrix(state); // Create a rectangle with the sprite dimensions, // starting from the origin of the coordinate system AABB<float> aabb = { 0.0f, 0.0f, static_cast<float>(m_spriteRect.width), static_cast<float>(m_spriteRect.height) }; // Add this sprite to the renderer quadRenderer.transformQuad(aabb, m_uvCoords, m_transform.getMatrix(), m_texture, m_color); } Transformation code // Update the internal matrix void Transformations::updateMatrix(const SpriteState& state) { // Baking a matrix // float angle = math::degToRad(-state.angle); float cosine = static_cast<float>(std::cos(angle)); float sine = static_cast<float>(std::sin(angle)); float sxc = m_scale.x * cosine; float syc = m_scale.y * cosine; float sxs = m_scale.x * sine; float sys = m_scale.y * sine; float tx = -m_origin.x * sxc - m_origin.y * sys + state.position.x; float ty = m_origin.x * sxs - m_origin.y * syc + state.position.y; m_matrix = { sxc, sys, tx, -sxs, syc, ty, 0.0f, 0.0f, 1.0f }; }  And this is my game loop code const int updateFPS = 30; const float dt = 1.0f / updateFPS; float accumulator = 0.0f; Uint32 currentTime = SDL_GetTicks(); // Main Loop bool close = false; while(!close) { // Process system events SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: close = true; break; case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_LEFT) { sprite1.moveH(-spriteVel * dt); sprite2.moveH(-spriteVel * dt); } if (event.key.keysym.sym == SDLK_RIGHT) { sprite1.moveH(spriteVel * dt); sprite2.moveH(spriteVel * dt); } default: break; } } // events // update // Get frame time in seconds const Uint32 newTime = SDL_GetTicks(); float frameTime = static_cast<float>(newTime - currentTime) / 1000.0f; // Avoid "Spiral of death" // (That is what happens when your physics simulation // cannot keep up with the steps it’s asked to take) frameTime = std::min(frameTime, 0.25f); currentTime = newTime; accumulator += frameTime; // Logic update while (accumulator >= dt) { sprite1.update(dt); sprite2.update(dt); accumulator -= dt; } // render float alpha = accumulator / dt; quadRenderer.begin(); sprite1.render(quadRenderer, alpha); sprite2.render(quadRenderer, alpha); quadRenderer.end(); swapBuffers(); }  Quad renderer is my sprite batcher. It works fine I'm creating two sprites to test this code, I activated interpolation in the first one, to see the difference Sprite sprite1(playerAtlas, { 0, 0, 64, 64 }); sprite1.setOrigin({ 32.0f, 63.0f }); sprite1.setPosition({ 512.0f, 384.0f }); sprite1.useInterpolation(true); Sprite sprite2(playerAtlas, { 0, 0, 64, 64 }); sprite2.setOrigin({ 32.0f, 63.0f }); sprite2.setPosition({ 512.0f, 318.0f }); sprite2.useInterpolation(false);  Now, the questions I have: 1) Is it ok to get the time as unsigned integers, or should I use something like std::chrono? SDL2 only returns time as Uint32 2) Why the author of the article is using this hardcoded number? if ( frameTime > 0.25 ) 3) Is my system events handling code in the right place? or should it be inside the while (accumulator >= dt) code? 4) Why I dont see any difference at all between the two sprites? the one using the interpolation method and the other one Thanks for reading... any tips for improving my code will be welcome
  7. Vulkan 101 Tutorial

    NULL macro, in the year 2016? really?
  8. Make a Particle Explosion Effect

  9. DIY 2D Vector Physics

    Great article! It would be nice if you can add the C++ code I always had problems with the minimal separation vector in my SAT implementations :(
  10. "it is also possible to iterate over the generated enums" Great! Best library feature EVER! Also, this can be a good solution to share enums with Lua