Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 04 Jul 2003
Online Last Active Today, 12:09 AM

#5286093 Event-Listener with Lua and C++

Posted by JTippetts on 09 April 2016 - 11:05 PM

For an interesting take on how one project has integrated Lua and C++, I suggest you take a look at Urho3D. Urho3D provides a component-based framework with event passing, and provides a structure such that a component can be added to an object that wraps a Lua object. The component handles the sending and receiving of events, and the Lua script code can subscribe to listen for events or send events as needed. It's quite an elegant system, but the underpinnings of it is a little complex. The github repo is here, you can navigate to the Source/Urho3D/LuaScript folder to get a peek at how scripting is done.

As an example from my own game, I have a Lua class called FloatingCombatText. This is a class implemented in Lua, which subscribes to listen for certain events, such as Damage Taken, Low Life, etc... events that happen to an object during the course of combat. In response to the events it is listening for, it will create floating combat text objects and queue them to a list, and these objects are then displayed as numbers or alerts animating above the entity's head. Simply by adding this script object component to any combat-enabled object, that object then will display floating combat text. A truncated version of the FloatingCombatText code:

function FloatingCombatText:Start()
	self:SubscribeToEvent("AlertAll", "FloatingCombatText:HandleAlert")
	self:SubscribeToEvent("Update", "FloatingCombatText:HandleUpdate")
	self:SubscribeToEvent(self.node, "AddResources", "FloatingCombatText:HandleAddResources")
	self:SubscribeToEvent(self.node, "SpendResources", "FloatingCombatText:HandleSpendResources")
	self:SubscribeToEvent(self.node, "DamageTaken", "FloatingCombatText:HandleDamageTaken")
	self:SubscribeToEvent(self.node, "HealingTaken", "FloatingCombatText:HandleHealingTaken")
	self:SubscribeToEvent(self.node, "LifeLow", "FloatingCombatText:HandleLifeLow")
	self:SubscribeToEvent(self.node, "PrepareToDie", "FloatingCombatText:HandlePrepareToDie")

function FloatingCombatText:HandleLifeLow(eventType, eventData)
	self.list:push_back({text="Life low!!", color={r=1,g=0,b=0}})

function FloatingCombatText:HandlePrepareToDie(eventType, eventData)
	self.list:push_back({text="Dying!!!", color={r=1,g=1,b=0}})

function FloatingCombatText:HandleDamageTaken(eventType, eventData)
	local total=eventData["total"]:Get()
	if total>0 then
		self.list:push_back({text=tostring(total), color={r=1,g=0.15, b=0.15}})

function FloatingCombatText:HandleHealingTaken(eventType, eventData)
	local total=eventData["healing"]:Get()
	if total>0 then
		self.list:push_back({text=tostring(total), color={r=0.15,g=0.15, b=1}})
The Urho3D framework provides ScriptObject as a base 'class' from which all script classes inherit. The Start method is called when the object is created, and it subscribes to the various events from its owning node (to distinguish from events originating with another node.)

The Urho3D framework provides the ability to work with Lua how you see fit. You can write the majority of your game in C++, implementing only certain scriptable components in Lua, or you can implement the entirety of your game code in Lua, using the bound API to implement scriptable components as well as base game logic.

Sorry for the pimping post, it's just that I really do look at Urho3D as an interesting and elegant way in which Lua can be bound to your framework, going beyond the simple call-for-call API binding you typically see.

#5285681 Game frameworks and engines that aren't Unity, Cryengine, or UE4?

Posted by JTippetts on 07 April 2016 - 06:53 PM

Urho3d is written in c++, has bindings for Lua and AngelScript, supports D3d11 and GL, provides 2d, 3d, gui, bullet physics, networking, sound, names path finding with crowds, etc.


Wow, this is amazing. Also found Atomic Game Engine which is a fork of it. Not sure which I want to use. Probably just stick with Urho, but the fact the site hasn't been updated in awhile is a bit concerning.
Now I need to brush up on my C++...

Urho3D is under active development. Last commit was three hours ago. The site doesn't get update a whole lot, but there is much activity in the repo itself.

#5285523 RPG effect resolution flow.

Posted by JTippetts on 06 April 2016 - 08:30 PM

Using events for this kind of thing can work, you just need to be careful about going too deeply into it. Work from a few key events, and for the in-between stuff work locally.

For example, an object receives an Apply Damage event. This event may originate outside the entity (from another mob, from a trap, etc) or from within the entity (from a Damage over Time tick or other debuff, etc...) This event should hold all the information the entity needs to know: damage amount, damage type, etc. Once this event is received, the entity would put out a call (a broadcast event of some sort) letting anyone who is interested know that an Apply Damage event has been received by the entity and, if they are interested in responding, call back with their response. Then the entity sits and waits for all of the interested parties to register their interest in responding. The reactions need to be categorized according to specified rules, and applied according to the specified order. After all reactions are processed, the entity would then send an event, say Take Damage. This event would have the processed, modified and repackaged damage data, and would be sent to the entity itself. Any interested parties can respond to this event (floating combat text to show damage numbers above the head, combat log to show combat results as text, vital stats to reduce life and potentially trigger additional life-related events).

This event->broadcast for reactions->response event structure allows for decent flexibility. As an example:

An environment hazard generates a hit for 16 Fire damage against a player character. The hazard sends the Event "ApplyDamage -16 Fire Enviro" to the player.

The player's damage handling component receives this event, and sends out a call for responses, by passing on the event with additional tagging data if needed.

The entity receives the responses:

1) Fire Shield (local buff spell) wants to absorb 4 Fire damage.
2) Fire Resistance (local character stat) wants to mitigate 12% of Fire damage
3) Immolation Aura (area debuff) wants to increase Fire damage taken by 20%
4) Firewatcher (NPC AI mobile unit, faction-tied to player) wants to extinguish the source of the flames to protect its master

In this case, the responses that involve numerical adjustment of the incoming damage value are applied in an order proper to the game ruleset; ie, apply +/- X% adjustments first, then apply +/- hard value adjustments after. Additional responses don't necessarily need to be sent as reply events; ie, the Firewatcher can simply initiate its Extinguish Fires AI routine in response to the broadcast event.

After all of the numeric adjustments are applied, a TakeDamage event with the final adjusted total is packaged up and sent locally to the entity. At this point, any local components can listen for this event to respond appropriately. The CombatLogger component will write a message to the log ("Player takes X fire damage."), the FloatingCombatText component will read the event and respond by scrolling a number above the unit's head. The VitalStats component will reduce Life by the specified amount, and potentially trigger the sending of LifeLow or LifeDepleted events as needed.

#5285177 Game frameworks and engines that aren't Unity, Cryengine, or UE4?

Posted by JTippetts on 04 April 2016 - 11:02 PM

Urho3d is written in c++, has bindings for Lua and AngelScript, supports D3d11 and GL, provides 2d, 3d, gui, bullet physics, networking, sound, names path finding with crowds, etc.


#5284661 Isometric art projected on 3D shapes

Posted by JTippetts on 01 April 2016 - 03:35 PM

If you're choosing to use this particular abstraction (renders projected onto impostor geometry), you're probably going to be doing it for 2 main reasons: Z buffering and lighting. There are other benefits, to be sure, but these are the big ones. The Z buffering gets past some of the interesting sprite draw-order problems that have been highlighted over 30 years of isometric games, and the lighting just makes it look juicy.

But for both of these, you really want to have geometry that fits the rendered sprite that is projected on it. Cubes can work for many elements, as long as those elements are essentially cubic in nature. Since you are still going to try to avoid cases of intersection or clipping between objects, the occasional weird cube-like clipping artifact won't be too bad. But a mismatch between the rendered object and its impostor geometry is going to be very noticeable once you toss dynamic lighting into the mix.

So, no, there's really no one size fits all solution for impostor geometry. For this reason, I'd say that if you are looking for a paradigm to reduce your workload, this isn't it. Just go with a standard 2D sprite stacking approach instead, and deal with the edge cases as best you can. This technique ends up actually being more work, because after you have finished the intricate modeling of your rendered objects, you still have to perform modeling to obtain a good-fit impostor to stick in on. That second step can be skipped in a traditional 2D, at the cost of all the tradeoffs you have to make.

If you are willing to accept some lighting quirks, though, you can settle for cubes or portions of cubes for everything. It'll show up in lighting, but maybe you can finesse it so it's not that bad.

#5284525 Isometric art projected on 3D shapes

Posted by JTippetts on 31 March 2016 - 02:04 PM

Yes, it's mostly for lighting. Cubes typically work well enough for z buffering, unless the shape is concave. They don't light very well, though.

#5284379 Isometric art projected on 3D shapes

Posted by JTippetts on 30 March 2016 - 05:55 PM

Pretty much, yes. Also, you can cram more detail into the scene without drastically increasing the face count. And because the scene is handled as a 3D scene, you can take advantage of all the usual 3D tricks: frustum culling, occlusion culling, render batching, etc... To increase performance, and shader tricks such as normal mapping to increase render quality.

#5284374 Isometric art projected on 3D shapes

Posted by JTippetts on 30 March 2016 - 05:40 PM

Here is another shot of a wall piece.


You can see that the wall model is UV mapped to 'snip' out the rendered texture. Now, here is a shot with another wall piece tiled in adjacent to that one:


The rendered wall pieces are constructed such that they present a repeating tile pattern, so that when wall pieces are placed on a grid adjacent to each other, the rendered patterns form a seamless image. By placing different wall pieces, entire dungeons can be built.

#5284369 Isometric art projected on 3D shapes

Posted by JTippetts on 30 March 2016 - 05:27 PM

I reckon they would use geometry that matches the rendered geometry as closely as possible, not limiting themselves just to cubes. Here is an example from one of my own projects:


You can see that the geometry that is actually being rendered is much simpler than the geometry used to construct the rendered tiles of the wall and floor. It's a single plane, in the case of the floor.

I've learned that the most important thing is that you match the silhouette of the rendered geometry as close as you can. If you look at The spherical newell cap on the wall to the left in that screenshot, you can see a small crescent of white. That is caused by part of the wall background being projected by mistake onto the sphere, and receiving lighting from the sphere portion rather than from the more dimly-lit top of the wall. Adjustments to the silhouette of the impostor geometry can help to mitigate that sort of thing.

#5283948 Is death to intense for kid players (<13 years old)

Posted by JTippetts on 28 March 2016 - 05:00 PM

Kids can cope. If their parents have been doing their jobs, then kids of 12 or 13 should already know about death.

#5283854 Why does it look so beautiful and how could I make it in-game?

Posted by JTippetts on 28 March 2016 - 09:12 AM

If all voxels have the same geometry(cube) and AO doesn't depend on lighting, wouldn't it be possible to bake AO for a single voxel and reuse it for all? E.g. bake normal edge AO and 90 degree angle AO and just somehow calculate where to put it. Might be some more edge cases, but idea stays the same. This way we could get high quality AO without sacrificing performance.

The issue with this is that AO depends on a cube's surroundings. Now, I reckon you could pre-calculate the AO for all the possible surroundings patterns. Say, if your occlusion rays extend no more than 5 cubes away, you could pre-calculate the AO for a given cube using all possible 11x11x11 neighborhood patterns and attempt to build a look-up table. But the larger your AO neighborhood becomes, the more difficult this becomes.

#5283650 Help with game error log

Posted by JTippetts on 26 March 2016 - 07:54 PM

Seems like a problem for Blizzard technical support.

#5282018 Why does it look so beautiful and how could I make it in-game?

Posted by JTippetts on 19 March 2016 - 10:27 AM

It's also possible to bake AO to vertex colors, rather than requiring a dedicated full-scene texture. For example, see this journal post by eppo. It does require some care and consideration when constructing your meshes, taking care to add more vertex detail to areas where AO shading is likely to be prominent, in order to more accurately confine the shading to the proper regions.

In cases where your vertex color defines the color of the voxel, then you would bake the AO term to the alpha channel, then use the alpha channel in a mix or blend operation to blend with shadow color.

#5274461 Looking for an engine for a 2d action RPG.

Posted by JTippetts on 05 February 2016 - 10:07 AM

What makes you say that?

Going through the list:
1. Unity is a 3d engine, not 2d. You can fake 2d in it, if you're doing a sidescroller, but that's still faking it *and* this isn't a sidescroller.
2. Using sprites for *everything* in Unity is just not going to happen. And I do mean *everything*. I gave two links on what we're trying to make it look like, more or less. We'd lose Unity about the point we made a sprite and tried to tell it that's the floor.

I don't think you really understand the difference between 3D and 2D. Hint: in this day and age, they're the same. You're going to use the exact same techniques (drawing quads mapped with textures) to draw a sprite as you would to draw, say, a 3D clump of grass. It's just textures and geometry, the only difference being spatial placement. 2D usually places all of the geometry on a single plane, and uses draw order to sort. If there is a 3D engine out there that CAN'T support this kind of thing, I'd be surprised.

3. Real-time combat, at least, it can do. In fact, I reckon it'd be a lot harder to do turn-based combat in Unity than real-time.
4. Now, I didn't spend much time in Unity last time I tried game development (I never got a team together, and moved to Unreal while I was waiting), but I couldn't find one person who could tell me how to give an object multiple hitboxes. And funny,I just got off Steam where I was trying an FPS made in Unity. Oddly, they didn't have headshots, a nearly universal FPS trope. Kinda makes me think multiple hitboxes is impossible in Unity, or at the very least is so hard to do that the devs of that game couldn't figure it out.
5. This might not be impossible, but the entire system would need to be completely built from the ground up in Unity. There isn't even a basic framework present for the existence of stats. In fact, there's no framework available for any RPG mechanics. Or the mechanics of any other genre, really. That isn't a problem if you're making a simplistic mobile "game" that barely has any mechanics, but for a REAL game, you'll want a more specialized engine.

You do realize that you're going to have to do a lot of the work yourself, right? Engines are not intended to be specific solutions for any one person's particular needs. So, yes, you'll probably have to build your particular system from the ground up if you use Unity. Same if you use Unreal, or CryEngine, or any other out of the box engine. They're built for the general case, not the specific. I strongly suspect you're not going to have much luck finding a pre-made solution that ticks every checkbox on your list, and you'll end up having to build your own solution.

#5273708 Rpg Inventory gui

Posted by JTippetts on 01 February 2016 - 12:36 PM

Diablo 2, path of exile, etc..., the inventory placement isn't very 'smart'. It probably isn't going to, by default, pack the items most efficiently. Especially since the player controls the order in which they are placed, and the optimal would require rearranging previously placed items. You can make the assumption that players are going to have to perform some manual inventory shuffling; that's actually a (small) part of the genre. It presents them a small optimization problem they need to tackle as part of their decision making. Can I fit more stuff? Do I need to portal back to town now? With that in mind, it's quite simple to just start at the top left corner and work your way down the column. Test to see if the item can fit right there (ie, are there enough empty squares to the right and below it to fit the item?). A brute force test is sufficient. If no spot is found, start at the top of the next column and work downward. If you reach the last column, and find no space for it, you play the annoying "I have no room" voice effect and drop the thing back on the ground.


This simple method should work well enough.  It will result in, for example, a 2x3 piece of armor being placed preferably in the top 3 rows of the inventory, and if a 2x2 helmet is picked up, it will end up in the 2 rows beneath it (if empty). 1x1 objects will 'fill in' the empty spaces from left to right. Are there better ways? Maybe. Doesn't matter. IMO, you can meet player expectations by simply emulating the games that came before.