Source

pygamekit / sensor.pxi

from libcpp cimport bool
from prerequisites cimport *

'''How to make a sensor:

cdef list my_callback_list = []

cdef class mySensor(Sensor):

    def __init__(self):
        self.init_sensor(my_callback_list)   # it adds itself when needed
        # add any other initialization
    
    def __nonzero__(self):
        return state_of_this_sensor

def evaluate_my_callbacks():
    cdef mySensor sensor
    for sensor in reversed(my_callback_list):  # remember sensors may remove themselves while iterating!!
        if sensor_state_just_changed:
            sensor.execute()
            
'''


cdef class Sensor:
    
    # This list contains all sensors that may be called.
    # The sensor will add itself when you link it.
    # Sensor subtypes must assign this.
    cdef list callback_list
    #cdef bool _im_in_list
    
    # This list contains callables (functions, controllers, actuators) to be called
    # when the sensor state changes.
    # TODO: change it to be a property so it adds itself (see link())
    cdef public list links
    
    cdef readonly GameObject owner
    
    cdef bool prevstate #used for some callbacks
    # TODO: do we need justActivated/justDeactivated/justChanged?
    
    # Time
    cdef readonly unsigned long int last_time

    cdef gkClock *timer
    
    def __init__(self):
        self.init_sensor([])
        
    def link(self, *actuators):
        if self not in self.callback_list:
            self.callback_list.append(self)
        self.links.extend(actuators)
        for a in actuators:
            if isinstance(a,Controller):
                a.sensors.append(self)
    
    def unlink(self, *actuators):
        self.links = list(set(self.links)-set(actuators))
        for a in actuators:
            if isinstance(a,Controller) and self in a.sensors:
                a.remove(self)
    
    def unlink_all(self):
        for c in self.links:
            if isinstance(c,Controller):
                c.sensors.remove(self)
        del(self.links[:])
        
    def with_links_of(self, sensor):
        self.link(sensor.links)
        return self

    cdef void _init(self):
        pass
    
    cdef void _set_owner(self, GameObject obj):
        self.owner = obj
    
    # Implementation methods
    cdef void init_sensor(self, callback_list):
        self.timer = new gkClock()
        self.callback_list = callback_list
        self.links = []

    cdef void execute(self) except *:
        if self.links:
            self.reset_time()
            for f in self.links:
                f(self)
        else:
            self.callback_list.pop(self.callback_list.index(self))
            
    cdef void reset_time(self):
        self.last_time = self.timer.getMilliseconds()
            
    property elapsed_time:
        def __get__(self):
            return self.timer.getMilliseconds() - self.last_time

    def __str__(self):
        if len(self.links):
            return "<Sensor connected to: %s>" % str(self[:])
        return "<Sensor>"

    def __repr__(self):
        if len(self.links):
            return "<Sensor connected to: %s>" % str(self[:])
        return "<Sensor>"
    


cdef list timer_callbacks = []

cdef class Timer(Sensor):
    
    cdef long endtime, relatime, pausedrem
    cdef bool triggered  # also True when stopped, so it's not evaluated
    
    def __init__(self, time=0):
        self.init_sensor(timer_callbacks)
        if time:
            self.start(time)
        
    def start(self, time):
        self.reset_time()
        self.relatime = time
        self.endtime = time+self.last_time
        self.triggered = False
        self.pausedrem = 0
        
    def restart(self):
        self.start(self.relatime)
        
    def stop(self):
        self.endtime = 0
        self.triggered = True
        self.pausedrem = 0
        
    def pause(self):
        if not self.triggered:
            self.pausedrem = self.endtime-self.timer.getMilliseconds()
        self.endtime=0
        self.triggered = True
        
    def resume(self):
        if self.pausedrem:
            self.endtime = self.timer.getMilliseconds() + self.pausedrem
        self.triggered = False
        self.pausedrem = 0
        
    property elapsed:
        def __get__(self):
            return self.relatime-(self.endtime-self.timer.getMilliseconds())
            
    property remaining:
        def __get__(self):
            return self.endtime-self.timer.getMilliseconds()
            
    property running:
        def __get__(self):
            return not self.triggered and self.endtime!=0
        
    property paused:
        def __get__(self):
            return self.pausedrem!=0
        
    property stopped:
        def __get__(self):
            return not self.triggered and self.endtime!=0 and self.pausedrem!=0
        
    def __nonzero__(self):
        return self.endtime!=0 and (self.triggered or self.endtime<=self.timer.getMilliseconds())
    
    def __str__(self):
        return "<Timer triggered at %i, current %i>" % (self.endtime,self.timer.getMilliseconds())

    def __repr__(self):
        return "<Timer triggered at %i, current %i>" % (self.endtime,self.timer.getMilliseconds())


cdef void evaluate_timer_callbacks():
    cdef Timer t
    for t in reversed(timer_callbacks):
        if not t.triggered and t.endtime<=t.timer.getMilliseconds():
            t.triggered = True
            t.execute()
    
    
    
    
    
        
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.