Jump to content

Turbo Game Engine (Leadwerks 5) beta updated

Josh

276 views

A new beta is available. In this build I cleaned up a lot of internal stuff. I removed some parts of the engine that I want to redesign in order to clean up the source.

JSON material files loaded from MDL files are now supported.

Added ActiveWindow() command. if the game window is not the foreground window this will return null.

The Steamworks and all dependent classes are temporarily removed. There's a lot of stuff in there I don't intend to use in the future like all the Workshop functions, and I want to reintegrate it one piece at a time in a neater fashion. The good features like P2P networking will definitely be included in the future.

File IO finished

The file read and write commands are now 100% using global functions and internally using Unicode strings. You can still call functions with a regular std::string but internally it will just convert it to a wide string. The zip file read support is removed temporarily so I can rethink its design.

Key and mouse event binding

Since I am consciously making the decision to design the new engine for intermediate and expert users instead of beginners, it occurred to me that the MouseHit and KeyHit functions are flawed, since they rely on a global state and will cause problems if two pieces of code check for the same key or button. So I removed them and came up with this system:

self:BindKey(KEY_E,self.Interact)
self:BindKey(KEY_SPACE,self.Jump)
self:BindMouseButton(MOUSE_LEFT,self.Throw)

This works exactly as you would expect, by calling the entity script function when the key or mouse button is pressed. Naturally a key release event would also be useful. Perhaps a BindKeyRelease() function is the best way to do this? The KeyDown() / MouseDown() functions are still available, since they do not have the problems the Hit() commands do. The same technique will work with C++ actors though it is not yet implemented.

This is undoubtedly more complicated than a simple MouseHit() command but it is better for people as their code gets more complex. Instead of hurting the experience for advanced users, I am going to force beginners to adjust to the correct way of doing things.

This design is not final. I think there are other ways programmers might want to bind events. I would like to hear your ideas. I am willing to create a more complicated system if it means it is more useful. This is a big change in my idea of good design.

  • Like 2


7 Comments


Recommended Comments

They are methods. Not strings, but the Lua method itself.

Share this comment


Link to comment

The way you bind those events, in my opinion, is how the GUI events should work as well.

self.btnExit:BindEvent(ON_CLICK, self, self.btnExit_OnClick) or self.btnExit.onClick:Bind(self, self.btnExit)

Normally you have to pass the script itself as well so you can pass it as the first parameter tot he function so we can define it like

function Script:btnExit_OnClick()

end

 

and use self inside of the function to refer to the script itself as 'self' is hidden 1st parameter to the function

Share this comment


Link to comment

@Rick Yeah, it seems like the next logical step is general event binding:

self:BindEvent(EVENT_MOUSE_DOWN, self.OnClick)

However, binding to an event is different from binding a key or button. The OnClick method would get called when any mouse button was clicked, so you would need to check the button ID in the OnClick function:

function Script:OnClick(event)
	if event.data == MOUSE_LEFT then
		...
	end
end

And then user-created events would probably be the next step:

function Script:Start()
	EVENT_DEATH = AllocateEventID()
	self:BindEvent(EVENT_DEATH, self.OnDeath)
end

function Script:TakeDamage(damage)
	self.health = self.health - damage
	if self.health <= 0 then
		EmitEvent(EVENT_DEATH)
	end
end

I can't really think of a way in which user events would be useful. It seems like it just complicates the code for no reason. I am curious to see what you think.

  • Like 1

Share this comment


Link to comment
7 hours ago, Josh said:

I can't really think of a way in which user events would be useful. It seems like it just complicates the code for no reason. I am curious to see what you think.

I hope that even if events were implemented, we were still left with at least the basic Down function we have now.  It's great to have options but often simpler is better.

Share this comment


Link to comment
9 hours ago, Josh said:

I can't really think of a way in which user events would be useful. It seems like it just complicates the code for no reason. I am curious to see what you think.

I think user events are very useful in this kind of subscribe/publish style because it allows for other scripts to know about whatever gameplay event you want without the script needing a reference to another script or entity. Cross script communication via events in my view is the best way to communicate. Allow the EmitEvent() to take a second parameter which is the value that will be passed to the subscribed functions. Since it's lua you only need 1 parameter and it can be a table that the person emitting the event fills out and if you are catching an event you have to just know the structure of said event parameter (a reasonable request).

This would make using 3rd party scripts that emit events easier I think.

Let's think about when we create enemy instances on the fly (not via the editor) and we need them to know about certain things the player is doing. How do we do that today? The enemy script either needs to get a hold of an instance of the player or the player get a hold of instances of the enemies so they can communicate. How they do that isn't very efficient or wise because it either means you're storing a global variable of the player so the enemies can get it (globals bad and error prone) or the player script is looping over every enemy to get a reference of them but enemies could be loading all the time so this doesn't work well. With the event system you can screw all that noise and just have the enemy script bind to a certain event that the player will emit. This way neither need a reference to each other to talk. 


So in summary user events gives us a way to have cross script communication without needing references of scripts/entities.

 

2 hours ago, gamecreator said:

I hope that even if events were implemented, we were still left with at least the basic Down function we have now.  It's great to have options but often simpler is better.

I agree with this. Events work well for cross script communication and UI stuff, but gameplay stuff like picking objects work best with these inline procedural functions. Both are needed.

Share this comment


Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Blog Entries

    • By Josh in Josh's Dev Blog 5
      You might have seen this graphic comparing the size of the world in different games. I've played Fuel, and never reached the end of the world in that game. You can drive for a very long time on those roads.

      We want to use the new engine for realistic simulations of air and ground movements. At normal cruising altitude of a commercial airliner, the pilot has a view range of about 400 kilometers. The image below shows that area (800 x 800 km). You can see the areas of the biggest games ever fit neatly into the corner of just our visible area.

      The gray space above is not the total world size, it is just the area you can see at once from high altitude. The total world size is about 50 times bigger.
      This is what I am working on now.
    • By Josh in Josh's Dev Blog 26
      Gamers have always been fascinated with the idea of endless areas to roam.  It seems we are always artificially constrained within a small area to play in, and the possibility of an entire world outside those bounds is tantalizing.  The game FUEL captured this idea by presenting the player with an enormous world that took hours to drive across:
      In the past, I always implemented terrain with one big heightmap texture, which had a fixed size like 1024x1024, 2048x2048, etc.  However, our vegetation system, featured in the book Game Engine Gems 3, required a different approach.  There was far too many instances of grass, trees, and rocks to store them all in memory, and I wanted to do something really radical.  The solution was to create an algorithm that could instantly calculate all the vegetation instances in a given area.  The algorithm would always produce the same result, but the actual data would never be saved, it was just retrieved in the area where you needed it, when you needed it.  So with a few modifications, our vegetation system is already set up to generate infinite instances far into the distance.

      However, terrain is problematic.  Just because an area is too far away to see doesn't mean it should stop existing.  If we don't store the terrain in memory then how do we prevent far away objects from falling into the ground?  I don't like the idea of disabling far away physics because it makes things very complex for the end user.  There are definitely some tricks we can add like not updating far away AI agents, but I want everything to just work by default, to the best of my ability.
      It was during the development of the vegetation system that I realized the MISSING PIECE to this puzzle.  The secret is in the way collision works with vegetation.  When any object moves all the collidable vegetation instances around it are retrieved and collision is performed on this fetched data.  We can do the exact same thing with terrain   Imagine a log rolling across the terrain.  We could use an algorithm to generate all the triangles it potentially could collide with, like in the image below.

      You can probably imagine how it would be easy to lay out an infinite grid of flat squares around the player, wherever he is standing in the world.

      What if we only save heightmap data for the squares the user modifies in the editor?  They can't possibly modify the entire universe, so let's just save their changes and make the default terrain flat.  It won't be very interesting, but it will work, right?
      What if instead of being flat by default, there was a function we had that would procedurally calculate the terrain height at any point?  The input would be the XZ position in the world and the output would be a heightmap value.

      If we used this, then we would have an entire procedurally generated terrain combined with parts that the developer modifies by hand with the terrain tools.  Only the hand-modified parts would have to be saved to a series of files that could be named "mapname_x_x.patch", i.e. "magickingdom_54_72.patch".  These patches could be loaded from disk as needed, and deleted from memory when no longer in use.
      The real magic would be in developing an algorithm that could quickly generate a height value given an XZ position.  A random seed could be introduced to allow us to create an endless variety of procedural landscapes to explore.  Perhaps a large brush could even be used to assign characteristics to an entire region like "mountainy", "plains", etc.
      The possibilities of what we can do in Leadwerks Engine 5 are intriguing.  Granted I don't have all the answers right now, but implementing a system like this would be a major step forward that unlocks an enormous world to explore.  What do you think?

    • By Haydenmango in Snowboarding Development Blog 6
      So I've been researching snowboarding lately to get an idea of what animations and mechanics I need to create for my game.  I have learned lots of interesting things since I've only seen snow once or twice in my entire life and have never even tried snowboarding or any other board sports (skateboarding, surfing, etc.) for that matter.
       
      Snowboarding tricks are quite interesting as they are mostly derived from skateboarding.  Snowboarding tricks pay homage to their equivalent skating tricks by sharing many concepts and names.  For example basic grabs in snowboarding share the same concepts and names as skateboarding: indy, mute, method, stalefish, nosegrab, and tailgrab.  Something interesting to note is in snowboarding you can grab Tindy or Tailfish but this is considered poor form since these grabs can't be done on a skateboard (due to the board not being attached to the skaters feet) and grabbing these areas is generally something a novice snowboarder does when failing or "half-assing" a normal grab.  Check out this diagram to see how grabs work -
       
       
      So, after reading lots of text descriptions for tricks I was still confused by what all these terms meant and how they were actually applied.  So my next step was to look up these tricks actually being done and I found some really cool videos showing off how to do various tricks.  This video in particular is the best reference material I've found as it contains nearly every trick back to back with labeled names and some tweaks -
       
      Sadly my rigged model doesn't handle leg animations with the snowboard that well so I can't animate as many tricks as I want to.  Regardless there will still be around 15 total grab/air tricks in the game.  Now it's time for me to stop procrastinating and start animating!  
×
×
  • Create New...