def __init__(self, start, end, duration): self.start = start self.end = end self.__diff_x = end[0]-start[0] self.__diff_y = end[1]-start[1] self.duration = duration self.freq = float(sdl2.SDL_GetPerformanceFrequency())
def run(self, screen, draw_func, update_func, fps=DEFAULT_FPS): self._screen = screen self._running = True self._fps = fps self._frame_time_ms = 1000 / fps event = sdl2.SDL_Event() time_accumulator_ms = 0 old_time = sdl2.SDL_GetPerformanceCounter() timer_resolution = sdl2.SDL_GetPerformanceFrequency() / 1000 # ms while self._running: while sdl2.SDL_PollEvent(ctypes.byref(event)) != 0: if event.type == sdl2.SDL_QUIT: self._running = False # Adjust the loop speed based on the time passed current_time = sdl2.SDL_GetPerformanceCounter() delta_time_ms = (current_time - old_time) / timer_resolution time_accumulator_ms += delta_time_ms while time_accumulator_ms > self._frame_time_ms: update_func(delta_time_ms) time_accumulator_ms -= self._frame_time_ms old_time = current_time # Update the screen screen.begin_update() draw_func(screen) screen.end_update() self.stop()
def getTime(): return sdl2.SDL_GetPerformanceCounter( ) * 1.0 / sdl2.SDL_GetPerformanceFrequency()
def run(self): prompt = CommandPrompt(self) print(">>> ", end='', flush=True) event = sdl2.SDL_Event() toc = 0 tic_toc_freq = sdl2.SDL_GetPerformanceFrequency() period = 1 excess = 0 remaining_cycles = 0 input_line = [] if self.has_sdl_audio: sdl2.SDL_PauseAudioDevice(self.audio_dev, 0) cpu_clock_rate = self.atari.color_clock_rate / 3 reasons = [Atari2600.StoppingReason.FRAME_DONE] current_input = self.input_stream[self.atari.frame_number] new_input = copy.deepcopy(current_input) while not self.done: # Timing. tic = toc toc = sdl2.timer.SDL_GetPerformanceCounter() elapsed = (toc - tic) / tic_toc_freq if elapsed > 1: # Too slow: reset counters. This may be caused by the program being # resumed or initialized. tic = toc elapsed = 0 elif elapsed < 1 / self.max_fps: # Too fast: throttle the simulation. This may be caused by # VSYNC is not working, for instance because the game window is hidden. sdl2.SDL_Delay(int(1000 * (1 / self.max_fps - elapsed))) toc = sdl2.timer.SDL_GetPerformanceCounter() elapsed = (toc - tic) / tic_toc_freq period = 0.95 * period + 0.05 * elapsed # Parse the SDL events. while sdl2.SDL_PollEvent(ctypes.byref(event)) != 0: if event.type == sdl2.SDL_QUIT: self.done = True elif (event.type == sdl2.SDL_KEYUP or event.type == sdl2.SDL_KEYDOWN) and event.key.repeat == 0: if event.type == sdl2.SDL_KEYDOWN: if (event.key.keysym.sym == sdl2.SDLK_EQUALS or event.key.keysym.sym == sdl2.SDLK_KP_PLUS): self.speed = min(5., self.speed + 0.25) print(f"Speed increased to {self.speed}") continue elif event.key.keysym.sym == sdl2.SDLK_0: self.speed = 1. print(f"Speed reset to {self.speed}") continue elif event.key.keysym.sym == sdl2.SDLK_MINUS: self.speed = max(0., self.speed - 0.25) print(f"Speed decreased to {self.speed}") continue if self.switches_interface.update(event.key, new_input): continue if new_input.peripheral_type == Input.Type.JOYSTICK: if self.joysticks_interface.update( event.key, new_input): continue elif new_input.peripheral_type == Input.Type.PADDLE: if self.paddles_interface.update(event.key, new_input): continue elif event.type == sdl2.SDL_WINDOWEVENT: if event.window.event == sdl2.SDL_WINDOWEVENT_RESIZED: pass elif (event.type == sdl2.SDL_JOYDEVICEADDED or event.type == sdl2.SDL_CONTROLLERDEVICEADDED): self.joysticks_interface.associate_sdl_joystick( event.cdevice.which, verbose=self.verbosity > 0) elif (event.type == sdl2.SDL_JOYDEVICEREMOVED or event.type == sdl2.SDL_CONTROLLERDEVICEREMOVED): self.joysticks_interface.disassociate_sdl_device( event.cdevice.which) elif (event.type == sdl2.SDL_JOYAXISMOTION or event.type == sdl2.SDL_JOYHATMOTION or event.type == sdl2.SDL_JOYBUTTONUP or event.type == sdl2.SDL_JOYBUTTONDOWN): if new_input.peripheral_type == Input.Type.JOYSTICK: if self.joysticks_interface.update_sdl_joystick( event, new_input): continue elif new_input.peripheral_type == Input.Type.PADDLE: if self.paddles_interface.update_sdl_joystick( event, new_input): continue # Parse the console events. if os.name == 'nt': pass else: dr, _, _ = select.select([sys.stdin], [], [], 0.0) if sys.stdin in dr: input_line = sys.stdin.read(1024) prompt.onecmd(input_line) print(">>> ", end='', flush=True) # Simulate an amount of CPU cycles equivalent to the real time elapsed. # Limit this to roughly two video frames. if not self.paused: remaining_cycles += cpu_clock_rate * elapsed * self.speed remaining_cycles = int( min(remaining_cycles, cpu_clock_rate * 2 / 60)) while remaining_cycles > 0: # At the beginning of each new frame, adjust the input stream. if Atari2600.StoppingReason.FRAME_DONE in reasons: if new_input.peripheral_type == Input.Type.PADDLE: self.paddles_interface.integrate(new_input) # Feed the *current* input to the console. if new_input != current_input: self.input_stream[self.atari.frame_number] = new_input current_input = self.input_stream[self.atari.frame_number] self.atari.set_panel(current_input.panel) if current_input.peripheral_type == Input.Type.JOYSTICK: for k in range(2): self.atari.set_joystick( k, current_input.peripheral[k]) elif current_input.peripheral_type == Input.Type.PADDLE: for k in range(4): self.atari.set_paddle(k, current_input.peripheral[k]) new_input = copy.deepcopy(current_input) # Simulate. reasons, remaining_cycles = self.atari.cycle( remaining_cycles) # Copy the screen content to the video texture. frame = self.atari.get_last_frame() pixels = ctypes.c_void_p() pitch = ctypes.c_int() sdl2.SDL_LockTexture(self.texture, None, ctypes.byref(pixels), ctypes.byref(pitch)) ctypes.memmove(pixels, bytes(frame), frame.width * frame.height * 4) sdl2.SDL_UnlockTexture(self.texture) sdl2.SDL_SetRenderTarget(self.renderer, self.texture) # Render the video texture. bounds = [0, frame.height - 1] sdl2.SDL_SetRenderDrawColor(self.renderer, 0, 0, 0, 0xff) sdl2.SDL_RenderClear(self.renderer) w = ctypes.c_int() h = ctypes.c_int() sdl2.SDL_GetWindowSize(self.screen, w, h) scale = min(w.value / (frame.width * self.aspect), h.value / (bounds[1] - bounds[0] + 1)) w_ = int(frame.width * self.aspect * scale) h_ = int((bounds[1] - bounds[0] + 1) * scale) dh_ = int(bounds[0] * scale) r = sdl2.SDL_Rect((int(w.value) - w_) // 2, (int(h.value) - h_) // 2 - dh_, w_, h_) sdl2.SDL_RenderCopy(self.renderer, self.texture, None, r) sdl2.SDL_RenderPresent(self.renderer) if self.has_sdl_audio: sdl2.SDL_PauseAudioDevice(self.audio_dev, 1)
def stamperChildFunction(qTo, qFrom, windowSize=[200, 200], windowPosition=[0, 0], windowColor=[255, 255, 255], doBorder=True): import sdl2 import sdl2.ext import sys import time try: import appnope appnope.nope() except: pass sdl2.SDL_Init(sdl2.SDL_INIT_TIMER) timeFreq = 1.0 / sdl2.SDL_GetPerformanceFrequency() sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) if doBorder: flags = sdl2.SDL_WINDOW_SHOWN else: flags = sdl2.SDL_WINDOW_BORDERLESS | sdl2.SDL_WINDOW_SHOWN window = sdl2.ext.Window("pyStamper", size=windowSize, position=windowPosition, flags=flags) windowID = sdl2.SDL_GetWindowID(window.window) windowSurf = sdl2.SDL_GetWindowSurface(window.window) red = sdl2.pixels.SDL_Color(r=255, g=0, b=0, a=255) green = sdl2.pixels.SDL_Color(r=0, g=255, b=0, a=255) black = sdl2.pixels.SDL_Color(r=0, g=0, b=0, a=255) white = sdl2.pixels.SDL_Color(r=255, g=255, b=255, a=255) if doBorder: sdl2.ext.fill(windowSurf.contents, green) else: sdl2.ext.fill( windowSurf.contents, sdl2.pixels.SDL_Color(r=windowColor[0], g=windowColor[1], b=windowColor[2], a=255)) window.refresh() for i in range(10): sdl2.SDL_PumpEvents() #to show the windows sdl2.SDL_Init( sdl2.SDL_INIT_JOYSTICK) #uncomment if you want joystick input sdl2.SDL_JoystickOpen(0) #uncomment if you want joystick input lostFocus = True lostColors = [red, black, red, white] lastRefreshTime = time.time() while True: if lostFocus and doBorder: if time.time() > (lastRefreshTime + (2.0 / 60)): sdl2.ext.fill(windowSurf.contents, lostColors[0]) window.refresh() lostColors.append(lostColors.pop(0)) lastRefreshTime = time.time() sdl2.SDL_PumpEvents() if not qTo.empty(): message = qTo.get() if message == 'quit': sys.exit() elif message == 'raise': sdl2.SDL_RaiseWindow(window.window) for event in sdl2.ext.get_events(): if event.type == sdl2.SDL_WINDOWEVENT: if event.window.windowID == windowID: if (event.window.event == sdl2.SDL_WINDOWEVENT_CLOSE): qFrom.put({ 'type': 'key', 'time': event.window.timestamp * timeFreq, 'value': 'escape' }) sys.exit() elif event.window.event == sdl2.SDL_WINDOWEVENT_FOCUS_LOST: lostFocus = True elif event.window.event == sdl2.SDL_WINDOWEVENT_FOCUS_GAINED: lostFocus = False if doBorder: sdl2.ext.fill(windowSurf.contents, green) window.refresh() else: message = {} if event.type == sdl2.SDL_KEYDOWN: message['type'] = 'key' message['time'] = event.key.timestamp * timeFreq message['value'] = sdl2.SDL_GetKeyName( event.key.keysym.sym).lower() message['keysym'] = event.key.keysym qFrom.put(message) elif event.type == sdl2.SDL_JOYAXISMOTION: message['type'] = 'axis' message['axis'] = event.jaxis.axis message['time'] = event.jaxis.timestamp * timeFreq message['value'] = event.jaxis.value qFrom.put(message) elif event.type == sdl2.SDL_JOYBUTTONDOWN: message['type'] = 'button' message['time'] = event.jbutton.timestamp * timeFreq message['value'] = event.jbutton.button qFrom.put(message)