Rick

Members
  • Content count

    7,326
  • Joined

  • Last visited

  • Days Won

    103

Rick last won the day on May 19

Rick had the most liked content!

Community Reputation

1,282 Excellent

About Rick

  • Rank
    Advanced Member
  • Birthday 12/04/1979

Profile Information

  • Gender
    Male
  • Interests
    Family, golf, football, programming, games

Recent Profile Visitors

19,082 profile views
  • Josh

  1. This might actually be a good example for coroutines too. I'll see what it would look like with coroutines and post and see what you think. Whenever you are mananging a lot of state variables coroutines might be ale to help reduce those and make the code smaller and easier to read.
  2. Typewriter script example to show a usage of coroutines. Now of course you could do this without coroutines (you can do everything without coroutines), but coroutines tend to make longer, more sequence like code easier to write, read, and maintain given it manages state for you which means less state variables required to manage and less jumping around in code during the sequence to understand where you are in the sequence. https://drive.google.com/open?id=0B0eHAaVNOFUwQnA4MzY4UTEzUnM So as you can see it's up to the user to manage the coroutine. What would be pretty cool is to somehow mark a user defined script function as a coroutine function so we can just use coroutine.yield() inside of it automatically. When the function is then called by whatever, the engine would then need to wrap it in a coroutine, and store it in a list and then each frame resume into the coroutines that entity currently has running. This would make things more natural. For example if I had a character script with a custom function of Script:DoSequenceOfEvents(), inside that function all the sequence of events could be done, vs now we basically have to set a state and then manage that inside UpdateWorld(). This means UpdateWorld() needs to exist and always be called every frame even if we aren't doing DoSequenceOfEvents(), which most of the time we aren't. This would allow having a lot more scripts in a scene that can do things. When we were working on urWorld we had scripts attached to trees and then had a ton of trees, but we noticed we had to remove UpdateWorld() function from the scripts otherwise performance was horrible. This meant, of course, the trees had no meaningful functionality that could be done because today you need UpdateWorld() to do stuff. With coroutines this wouldn't be the case. Functions that actually do things over time could be created and they aren't ran until called and when finished they are dead and not called anymore. Coroutines give us sort of a dynamic UpdateWorld() that's only called when we need it instead of every frame which is a huge performance boost when you have a lot of stuff in your scene with scripts. Of course if you have to do something every frame then you still need UpdateWorld() but there are cases where you just need to do things over time on that object when called.
  3. You have 666 posts! Quick post again Thanks for sharing. I don't know if you're open to coding suggestions but the thing that instantly stood out to me is the level of indentation. Each indentation is like allocating memory on a stack in our minds. Code with less indentation tends to be easier to read and less error prone. A way to remove indentation, again if you care at all, is to negate and return early. Your PostRender() is a good example of that. 5 levels of indentation can be turned into basically none with: function Script:PostRender(context) if self.ShowGraphics == false then return end if self.enabled == false then return end if self.using == false then return end if self.useold == false then return end if self.completed == true then return end context:SetBlendMode(Blend.Alpha) window = Window:GetCurrent() local segment = Vec2(window:GetWidth() *.25,window:GetHeight() *.47) context:SetColor(0,0,0,0.5) context:DrawRect(segment.x, segment.y , window:GetWidth() - (segment.x*2),window:GetHeight() - (segment.y*2)) context:SetColor(1,1,1,0.5) context:DrawRect(segment.x+4, segment.y+4 , (window:GetWidth() - ((segment.x+4)*2))*(self:Percentage()*.01) , window:GetHeight() - ((segment.y+4)*2)) end UpdatePhysics is another good example. Checking for self.enabled is very common so negating and bailing out early helps readability. Again, just something that stood out. You can tell me to piss off if you aren't interested
  4. Did the new link above work?
  5. hmm wtf. I'll find another way to upload the project. Dropbox sucks these days as they seem like they changed so trying to see how I can upload something larger than 5MB on the forum as that's what I'm limited to. OK, try the link below. https://drive.google.com/open?id=0B0eHAaVNOFUwNklnVTZUQ1hpWTg
  6. Did a cross fading images project with coroutines. http://ge.tt/4W36hAk2
  7. I think the standard way across compilers is: for(auto i : list) { }
  8. I guess the question is what are the examples where you aren't iterating over the list each frame and even if you aren't is there harm in setting a deletion flag and deleting it when you do eventuslly iterate over the list. When we don't know the details of your data storage scenarios it makes it hard to give suggestions so we only give based on specific situations. There aren't that many game engine developers in the world either so most people don't run into your scenarios perhaps.
  9. We understand it, storing iterators just has potential for issue and disadvantages as you're saying and so it's generally avoided. In your example you are storing an entity in the world. I would assume you are looping over each entity each frame given that a script can be attached thst might have an UpdateWorld function that needs to be called each frame. Data management can be done 100 different ways to Sunday. You gave us one example so it's what we have to go from. You're also making a highly specialized piece of software, game engine. The business world where most of the code exists in the world, doesn't care about the small performance hit of erasing from a list with the data itself. So it's not that people don't "get it". I would also add that my understanding is that most game engines try to avoid dynamic creation and deletion when possible and favor object pooling for speed reasons which changes all of that.
  10. I think like the one guy mentioned you are already interating over the list at some point in your program (a main reason for why the list exists right), so when you want to delete an object in the list you set a flag of the object itself and at the one iteration point you check that flag and if it's set for deletion, you delete it there while you have the iterator handy. I think, while storing iterators is possible, it has its disadvantages and possible issues that you are seeing, and trying to work around those will more than likely cause more unforeseen issues.
  11. My first thought is don't. Can you give a scenario of the issue? I don't think generally you keep iterators around. They are generally just for iterating at that specific point. Are you trying to store iterators for later use? It's been some time since I've been in C++ but I don't recall needing to do that.
  12. Was messing around a little this evening. Here's a quick typewriter effect script. The biggest disadvantage to coroutine functions is that if there is an error we get no error message popup. The function just stops working. So you have to put a lot of print statements in usually to see where it's erroring out and I usually can just see why. I'm sure LE could capture the errors as I'm sure the language allows for it but might have to do something special on the interpreter side. function Script:Start() self.co = coroutine.create(Intro) self.text = "" end function Script:UpdateWorld() if coroutine.status(self.co) ~= "dead" then coroutine.resume(self.co, self) end end function Script:PostRender(context) context:SetBlendMode(Blend.Alpha) context:DrawText(self.text, 0, 0) context:SetBlendMode(Blend.Solid) end -- helper function to wait x ms function Wait(ms) local time = Time:GetCurrent() while Time:GetCurrent() < time + ms do coroutine.yield() end end -- helper function to give a typewriter effect where each letter in a string is printed at a give interval function Typewriter(script, fullText, delay) for i = 1, #fullText do local c = fullText:sub(i,i) script.text = script.text..c Wait(delay) end end -- below is the function that we run in the coroutine function Intro(script) script.text = "I'm about to do a typewriter effect. Hold on!" Wait(5000) script.text = "" Typewriter(script, "This is a test to see if this work! And it does!", 150) end
  13. Yeah I have a fade in and out function that makes this easy in a coroutine.