Game Design - How do you control your enemies, actors and vehicles?

I was just wondering how everyone handles controlling their agents in game design.

I have looked into unity, and ue4, and they seem to have a input controller built in but it was kind of a black box.

I built my own from scratch and I was wondering how far it was from ‘Standard’ in the industry

(drag and drop actors, enemy / player / vehicles are all extensions of the same script)

easily extended, non branching etc.

what are your thoughts?
how can I improve this?

how does it compare to your own solutions?
(does it look easy enough to use?)

I intend to make a generic keybinding screen next -(to generate the keybind dictionaries)

what is missing?

is there anything you see that would be more efficient?

Standard? I highly doubt that most game mechanics have an ‘industry standard’ implementation to them in the same vein you see with certain things in 3D applications. The closest you get to a standard is movement with WASD to free up the right hand, but most standards apply to the game creation software itself as mechanics might need to be customized on a per-game basis.

Also, I would be very careful about mentioning your projects in General Discussion (again), this thread can work if it was just talking about game mechanics in general and whether there’s a standard way, rather than discussing their implementation in a specific game project that happens to belong to the thread owner.

Moved from “General Forums > Blender and CG Discussions” to “Game Engine > Game Engine Support and Discussion”

@BPR, if you continue to post threads in the wrong forum, the moderation team will be forced to start deleting them.

@BPR, if you continue to post threads in the wrong forum, the moderation team will be forced to start deleting them.

I don’t want just bge peoples opinion

Better to post in a non Blender forum then (e.g GameDev.net)

With regards to easy to use, I think you could benefit from some code refactoring and separation of concerns. Generally speaking, several levels of indentation, or large branches, or long functions shout “refactor me!”. See this link for more. http://stackoverflow.com/a/611322/1215241

Though it’s tempting to try and unify control schemes, it’s hard to abstract this problem any further. Vehicles often don’t have the same control requirements as other interactive entities.

I’m quite interested in state-driven animation, but that’s just one approach of many (including procedural animation).

I also suggest defining some common interface / practice principles to object interactions. For example, when an object becomes detached from another, are there systems that need to be informed? Who can execute the “detach” code? It’s generally good to decide these relationships in advance.

I personally don’t like using Game Object properties for system data, because it’s easily modified and doesn’t convey any sense of ownership. Classes, as one approach, allow the suggestion of private state. Another approach is a system-specific data dictionary.

TLDR on the video.

how are you living in the blender text editor and still have your mind on straight!? for me the undo feature decimates anything i do in there at first glance. NOTEPAD FTW!

i use almost 100% python via classes and modules. the only logic bricks i have are one time python controllers which call a class, then init adds the coded object, assigns the class to a “RUN” property, and does some magic. the added objects, if needed, have an Always-Python pointing to a small module which calls a RUN() function from the class instance stored in the property.

while still in need of better inheritance structures, it works wonderfully efficient. im highly considering posting a flavor on github once the inheritance is better and the weapons system is more fine tuned. its not the most advanced thing ever, since im taking it slow, learning and refactoring as i go.

as far as standards go, in my research, the closest thing to “standard” is genre, FPS, RPG, MMO, etc. even UI isnt all that standard. if there was such a standard, sloppy poorly coded games just might be a thing of the past.

Good to see you thinking about design BPR. but welcome to the world of software, where therealmost certainly isn’t a ‘best’ way for many many things

One of the things I have standardised is how I do GUI’s: I set up a HTML-like events model, with callbacks and event mimicking those present in Javascript (eg an onmousedown event that has a mouseEvent with the various attributes pass into it). I’ve found it to be very robust for quickly building simple interfaces and being capable of handling complex ones. Currently the library I wrote that does this I did while working for a company, so I can’t release the code for it, but I plan to develop a similar system in my free time as it is so powerful. I’ve also learned a lot from the first attempt.
I’m pretty happy with how I do GUI’s. I built a file browser in just an hour or two, I’ve done scrollable lists of things etc.

I’m also getting better at designing interfaces between objects, but I think that’s just because I plan things out more than I used to.

These days this is how I approach things:
The place you should stop abstracting, is where it leaves the simplest and most maintainable code for you to implement.
I often find half-way through constructing an object that I’ve placed an abstraction layer slightly funny, and have to re-think about it for a while. This is particularly relevant to when it comes to designing interfaces for lots of similar objects. At some level, a ‘human’ character and a ‘vehicle’ are similar, and thus should have similar interfaces. The problem is where, and that depends on their intended use. In one project, I placed my AI at exactly the same abstraction level as the interface to the human player - and then found it was awkward to access needed functionality (eg raycasts). But it did make writing the AI easy, you just thought about how you responded, and what buttons you pressed, and the AI could do exactly that. I really don’t think there is an ideal solution.

The thing that makes the most difference? The pad of graph paper sitting on my desk. Informal UML diagrams and scribbled out class templates are great.

Yeah, these days I’m nearly 100% python, and create all my game-objects as part of a python-object constructor. The only issue is when you need to integrate it with physics detection or raycasts - because then you get a game object and have to find the associated python objects. Anyone have a solution for that?

Depends how you create your objects. In nearly all cases, just store a reference to the Python class instance in the object properties. Unless you’re using the mutation trick, in which case, the KX_GameObject returned by any BGE API is already that class instance.

The way you presented the thread made it look like another plug for the BGE and your projects. Not only that, but it also made the thread look like a Q&A question regarding the development of Manic Macks more than a general discussion about game development.

If you want to create a general discussion on game mechanics, refer to the world of game development in general. You can also talk about the ideas you have had, but only refer to them in a general sense without posting WIP videos of you working on your projects.

thats nice ace :smiley:

ok so I was able to abstract a bit further, and at the same time expand the functionality


import bge
cont = bge.logic.getCurrentController()
own = cont.owner
from mathutils import Vector


if 'Armature' not in own:
    for child in own.children:
        if 'ArmaTag' in child:
            own['Armature']=child


if own['Run']>=1:
    own['Run']-=1
G = cont.sensors['Collision']




    


def Animate(Data):
    print('calling anim')
    anim = Data[0]
    start = Data[1]  
    end = Data[2]
    rate = Data[3]
    mode = Data[4]
    chan = Data[5]
    s = str(chan)+"_frame"
    
    frame = own['Armature'][s]
    
    if mode=="Loop":
        f = own['Armature'][s]+rate
        if f>end:
            f= f-end
        if f< start:
            f = end-f
        if len(Data)==6:    
            own['Armature'].playAction(anim, f, f, chan, 0, 0, 0, 0.0, 0, 0.0, 0)
        else:
            own['Armature'].playAction(anim, f, f, chan, 0, Data[6], 0, 0.0, 0, 0.0, 0)
                
        own['Armature'][s]=f      
    
def idle(point):
    print('calling idle')
    if G.positive:
        own.localLinearVelocity*=.1
        
        
      
def Rot(point):
    print(point[0])
    
    local = point[0]-own.worldPosition
    local = own.worldOrientation.inverted()*local
    own['D']=str(local)
    #print('set')
    if local.x>0:
        own.applyRotation([0,0,(local.y/8)],1)
        if local.y>.05:
            own.applyRotation((0,0,.01),1)
        elif local.y<.05:
            own.applyRotation((0,0,-.01),1)    
    else:
        own.applyRotation([0,0,(local.y/18)],1)
        if local.y>.05:
            own.applyRotation((0,0,.05),1)
        elif local.y<.05:
            own.applyRotation((0,0,-.05),1)    
            
        
        
def Move(point):
    if G.positive:
        v2 = own.getVectTo(point[0])
        
        local = point[0]-own.worldPosition
        local = own.worldOrientation.inverted()*local
        if local.x>0 and (abs(local.y)-abs(local.x))<0:
            
            if own.localLinearVelocity.x<5:
                own.applyForce((50,0,0),1)
            own.localLinearVelocity.y*=.5    
            
     


Pos = own.worldPosition




Movement_Dict = {}
Movement_Dict.update({str(['UP']):[ [Move,[Pos+Vector([0,-1,0])] ],[Rot,[Pos+Vector([0,-1,0])]],[Animate,['walk',0,23,own.localLinearVelocity.x*.1,"Loop",0] ] ] })
Movement_Dict.update({str(['UP', 'LEFT']):[ [Move,[Pos+Vector([1,-1,0])] ],[Rot,[Pos+Vector([1,-1,0])]],[Animate,['walk',0,23,own.localLinearVelocity.x*.1,"Loop",0] ] ] })
Movement_Dict.update({str(['LEFT', 'DOWN']):[ [Move,[Pos+Vector([1,1,0])] ],[Rot,[Pos+Vector([1,1,0])]],[Animate,['walk',0,23,own.localLinearVelocity.x*.1,"Loop",0] ] ] })
Movement_Dict.update({str(['DOWN']):[ [Move,[Pos+Vector([0,1,0])]],[Rot,[Pos+Vector([0,1,0])]],[Animate,['walk',0,23,own.localLinearVelocity.x*.1,"Loop",0] ] ] })
Movement_Dict.update({str(['DOWN', 'RIGHT']):[ [Move,[Pos+Vector([-1,1,0])]],[Rot,[Pos+Vector([-1,1,0])]],[Animate,['walk',0,23,own.localLinearVelocity.x*.1,"Loop",0] ] ] })
Movement_Dict.update({str(['LEFT']):[ [Move,[Pos+Vector([1,0,0])] ],[Rot,[Pos+Vector([1,0,0])]],[Animate,['walk',0,23,own.localLinearVelocity.x*.1,"Loop",0] ] ] })
Movement_Dict.update({str(['RIGHT']):[ [Move,[Pos+Vector([-1,0,0])] ],[Rot,[Pos+Vector([-1,0,0])]],[Animate,['walk',0,23,own.localLinearVelocity.x*.1,"Loop",0] ] ] })
Movement_Dict.update({str(['UP', 'RIGHT']):[ [Move,[Pos+Vector([-1,-1,0])] ],[Rot,[Pos+Vector([-1,-1,0])]],[Animate,['walk',0,23,own.localLinearVelocity.x*.1,"Loop",0] ] ] })
Movement_Dict.update({str([]):[ [idle,[]] ]})
def main():


    


    own['D']=own['Move']
    


    if str(own['Move']) in Movement_Dict:
        command = Movement_Dict[str(own['Move'])]
        for part in command:
            function = part[0]
            function(part[1])
        if len(own['Move'])>0:
            cont.deactivate(cont.actuators['Idle']) 
        else:
            cont.activate(cont.actuators['Idle'])       
        own['Move']=[]




main()



now instead of directly calling 1 function for each state, a list of functions is called.
next up is building GOAP and adding goals to pop the GOAP to the functions to be able to be called
(Timer(timeEnd,Time), Point(Vector or agent), AnyKey(‘PUNCH’))

For controlling, I pass a virtual joystick to my NPCs and use code to press the buttons on the virtual joystick. A funny result of this is that if I switch from a virtual joystick to a real one, I can control my NPCs.

For enemy behaviour I use behaviour trees.

Same thing here, but I pass actrstrip arguments directly like navigate, or attack, directly in hostile player actors.

Agent[‘ActStrip’] = [ [‘Navigate’, Target], [‘Attack’, Target] ]

( however now these states (actrstrips) will be lists of stuff to do each frame, and goals soon)
Also since the systems are split to more functions, I can stay DRY.

I do not even use code. I use messages to decouple device input (keyboard sensor, Joystick sensor, Mouse button sensor) from the requested operation.

The drawback is that the processing is always one frame behind:

frame t+0: input + mapping to a message [mapper]
frame t+1: message detection + operation

There are many benefits:

  • This works very well and fully integrate into the logic bricks.
  • No need to use complicated Python code (or Python code at all).
  • You can have as many mappers (which convert input to message) as you want.
  • It is easy to share the same mapper within different scenes.
  • You can dynamically exchange or modify mappers.
  • You can provide them as pre-sets to be shared within many different games (e.g. WASD-mapper)
  • You can easily create your own custom mapper with any complexity you like.
  • You can exchange the control on the fly (e.g. switching between characters, switching from character walking to vehicle driving)
  • You do not need to build your assets around input (keyboard sensor) but around messages.
  • Games using logic bricks are simple to migrate (replace the keyboard sensor with a message sensor).