{"action":"created","issue":{"url":"https://api.github.com/repos/libgdx/libgdx/issues/3516","labels_url":"https://api.github.com/repos/libgdx/libgdx/issues/3516/labels{/name}","comments_url":"https://api.github.com/repos/libgdx/libgdx/issues/3516/comments","events_url":"https://api.github.com/repos/libgdx/libgdx/issues/3516/events","html_url":"https://github.com/libgdx/libgdx/issues/3516","id":113793932,"number":3516,"title":"ParticleEffect isComplete is true on continuous effects if delayTimer >= delay after update","user":{"login":"Xkynar","id":8341832,"avatar_url":"https://avatars.githubusercontent.com/u/8341832?v=3","gravatar_id":"","url":"https://api.github.com/users/Xkynar","html_url":"https://github.com/Xkynar","followers_url":"https://api.github.com/users/Xkynar/followers","following_url":"https://api.github.com/users/Xkynar/following{/other_user}","gists_url":"https://api.github.com/users/Xkynar/gists{/gist_id}","starred_url":"https://api.github.com/users/Xkynar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Xkynar/subscriptions","organizations_url":"https://api.github.com/users/Xkynar/orgs","repos_url":"https://api.github.com/users/Xkynar/repos","events_url":"https://api.github.com/users/Xkynar/events{/privacy}","received_events_url":"https://api.github.com/users/Xkynar/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-10-28T11:04:01Z","updated_at":"2015-10-30T20:13:07Z","closed_at":null,"body":"Lets take into case a continuous ParticleEffect with a single emitter. This is ParticleEffect's \"isComplete\" method:\r\n\r\npublic boolean isComplete () {\r\n\t\tfor (int i = 0, n = emitters.size; i < n; i++) {\r\n\t\t\tParticleEmitter emitter = emitters.get(i);\r\n\t\t\tif (!emitter.isComplete()) return false;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\nThis means that it depends on the emitter's completion. This is ParticleEmitter's \"isComplete\":\r\n\r\npublic boolean isComplete () {\r\n\t\tif (delayTimer < delay) return false;\r\n\t\treturn durationTimer >= duration && activeCount == 0;\r\n\t}\r\n\r\nIt depends mostly on delayTimer, and if we check the update method of ParticleEmitters:\r\n\r\nif (delayTimer < delay) {\r\n\t\t\tdelayTimer += deltaMillis;\r\n\t\t} else { ... }\r\n\r\nAnd this is the way you say we should update particles:\r\n\r\nfor (int i = effects.size - 1; i >= 0; i--) {\r\n    PooledEffect effect = effects.get(i);\r\n    effect.draw(batch, delta);\r\n    if (effect.isComplete()) {\r\n        effect.free();\r\n        effects.removeIndex(i);\r\n    }\r\n}\r\n\r\nWhat can and will happen (it happened to me) is that, after the update, in the random case in which \"delayTimer += deltaMillis;\" will be greater or equal than delay, isComplete will return true, even if the effect is continuous, and if we free/remove all particles which are complete just like in the cycle above, we will end up removing random continuous effects that should not be removed.\r\n"},"comment":{"url":"https://api.github.com/repos/libgdx/libgdx/issues/comments/152640916","html_url":"https://github.com/libgdx/libgdx/issues/3516#issuecomment-152640916","issue_url":"https://api.github.com/repos/libgdx/libgdx/issues/3516","id":152640916,"user":{"login":"Xkynar","id":8341832,"avatar_url":"https://avatars.githubusercontent.com/u/8341832?v=3","gravatar_id":"","url":"https://api.github.com/users/Xkynar","html_url":"https://github.com/Xkynar","followers_url":"https://api.github.com/users/Xkynar/followers","following_url":"https://api.github.com/users/Xkynar/following{/other_user}","gists_url":"https://api.github.com/users/Xkynar/gists{/gist_id}","starred_url":"https://api.github.com/users/Xkynar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Xkynar/subscriptions","organizations_url":"https://api.github.com/users/Xkynar/orgs","repos_url":"https://api.github.com/users/Xkynar/repos","events_url":"https://api.github.com/users/Xkynar/events{/privacy}","received_events_url":"https://api.github.com/users/Xkynar/received_events","type":"User","site_admin":false},"created_at":"2015-10-30T20:13:07Z","updated_at":"2015-10-30T20:13:07Z","body":"The fix is very simple, an emitter should take into account its \"complete\" flag when asked if it is complete..\r\n\r\npublic boolean isComplete () {\r\n//ADD THIS\r\nif(continuous) return false;\r\n\r\nif (delayTimer < delay) return false;\r\nreturn durationTimer >= duration && activeCount == 0;\r\n}\r\n\r\nA continuous emitter should never be complete. It is a simple check, much safer than just checking for the delay timers.\r\n\r\nAs for the reproduction of the bug, as I said, it only happens in the particular case in which you are removing the \"complete\" particleeffects after their update. the \"isComplete\" check is flawed, and if durationTimer ends up being >= than duration after the update, isComplete will return true before the next update cycle has a chance to reset \"delayTimer\" (because of the effect's continous flag).\r\n\r\nIn my case, i had a permanent effect in my game and it just disappeared randomly, after some time.\r\nWhen i made a proper isComplete check, taking into account the emitters' continous flag manually, it was ok, but that should really be unecessary, since isComplete should NEVER return true on a continuous effect."}}