2
$\begingroup$

How should one go about implementing a script that will execute before the current scene loads? For example I am attempting to connect to a tcp/ip server in order to send and receive data between clients. The connection code will be run in a separate thread so not to block any other processes.

My main area of confusion at this point happens to be how to initiate the execution of this script at the start of the program.

$\endgroup$
  • $\begingroup$ This question seems to me not related to blender. You just need to run the script before you load the game, lets say (assuming you have loadScene.blend) 1) in your load scene make the connection and when you got the required data 2) load the mainGame.blend with a) "Game actuator" or b) load everyting with libLoad (asset.blend, world.blend, object.blend, player.blend, etc). $\endgroup$ – Strapicarus Oct 5 '17 at 14:27
  • $\begingroup$ @Strapicarus This is good information. One question though, where exactly is the entry point? For example in blender when I run the bge, where do I tell it to execute my script that uses libLoad? Do I attach this script to logic brick actuator? (apologies if I'm not explaining myself well. I think what I'm asking is pretty basic, I just haven't had to do it before) $\endgroup$ – nullReference Oct 5 '17 at 15:29
1
$\begingroup$

I use the next setup.

launcher.blend has a camera and a plane with a python controller that run my script launcher.py and the logic is always sensor > python controller > game actuator:

enter image description here

And the script check for files and...

from os.path import isfile, join
from scripts.settings import Settings
from scripts.functions import erro, install_path

class Launcher():
    """This class launch the game if no problem encountered."""
    def __init__(self, controller):
        """Assing game actuator file name and mode"""
        self.settings = Settings()
        self.gameActuator = controller.actuators['Game']
        if isfile(join(install_path, 'intro.blend')):
            self.gameActuator.fileName = str(join(install_path, 'intro.blend'))
            self.gameActuator.mode = 0
            self.main = self.initialize
        elif isfile(join(install_path, 'menu.blend')):
            erro(self, 'intro.blend file not found', 1)     
            self.gameActuator.fileName = str((join(install_path, 'main_menu.blend') if isfile(join(install_path(), 'main_menu.blend')) else join(install_path(), 'erro.blend') )) 
            self.gameActuator.mode = 0
            self.main = self.initialize
        else:
            erro(cls = self, msg = 'menu.blend file not found', level = 0)

    def initialize(self, controller):
        """Launch the game menu if settings are ok."""
        if self.settings.read_config_file():
            print('ready...')
            controller.activate(self.gameActuator)
            # at this point, bge should restart and load the new blend.
        else:
            self.settings.defaults_settings()
            if self.settings.read_config_file():
                print('ready...')
                controller.activate(self.gameActuator)
            else:
                erro(cls = self, msg = 'menu.blend file not found', level = 1)
                try:
                    controller.activate(self.gameActuator)
                except Exception as e:
                    erro(self, 'Error fatal!', 0)


def main(controller):
    if not "launcher" in controller.owner.getPropertyNames():
        controller.owner["launcher"] = Launcher(controller)
        return
    controller.owner["launcher"].main(controller)
$\endgroup$
  • $\begingroup$ The general setup is fine. I suggest some fine tuning: A) disable [True Level Triggering] to avoid running it again. B) avoid calling that "main" it serves no purpose. Better tell what it should do. Btw. you can use script mode too. In that case you just write the code (without defining functions). $\endgroup$ – Monster Oct 6 '17 at 5:46
  • $\begingroup$ This is a template that i use. and the main() does not do anything here but Doing without function i've notice that the scripts runs twice the first run! and some times that bother me, this way i control the things i want to runs once. Another thing is that i can control are the states without messing with logic brick states. And yeah i stick to it ;), Of course this script is 11 lines without all my extras xD. $\endgroup$ – Strapicarus Oct 6 '17 at 6:59
  • $\begingroup$ When using Always sensor without [True Level Triggering] the controller should never get triggered twice. Nevertheless the code should always check the sensors status (status.positive) unless you really do not care or you can guaranty the setup of the sensor. $\endgroup$ – Monster Oct 9 '17 at 3:53
  • $\begingroup$ I know the "main" comes from the templates. I suggest to see the function name as placeholder for a meaningful name. When you do it that way this name can tell the reader what the code is supposed to do on an higher level. The template does not know what you want to do so it has to use a generic name. This is pretty much the same as the first text block is named "Text" too. - just something to think about $\endgroup$ – Monster Oct 9 '17 at 3:58
  • $\begingroup$ Yeah Always sensor without [True Level Triggering] the controller should never get triggered twice, it happen to me and i check it (maybe) in versions 2.72 to 2.75 or 2.76, i don't really remember exactly, but i think it happens when importing some scripts. Another thing is the question itself, attempting to connect to a tcp/ip server in order to send and receive data, so it will need a script that run for the time needed because there is no tpc sensor to trigger the script so indeed need an always sensor with [True Level Triggering]. $\endgroup$ – Strapicarus Oct 9 '17 at 5:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.