import sdl2 import sdl2/ttf # import sdl2/private/keycodes from ./pong/cons import nil import ./pong/pong import ./pong/tmpl import ./pong/font type App {.requiresInit.}= object window:WindowPtr renderer:RendererPtr font:Font isRun = true game:Pong dt: float32=0 event:Event proc NewApp():App= if_SDL_fail(not sdl2.init(INIT_VIDEO or INIT_TIMER or INIT_EVENTS)): "NewApp(): SDL2 initialization failed" let window = createWindow( title = "PingPong", x = SDL_WINDOWPOS_CENTERED, y = SDL_WINDOWPOS_CENTERED, w = cons.WindowWidth, h = cons.WindowHeight, flags = SDL_WINDOW_SHOWN ) if_SDL_fail(window.isNil, "NewApp(): window could not be created") let renderer = createRenderer( window = window, index = -1, flags = Renderer_Accelerated or Renderer_PresentVsync or Renderer_TargetTexture ) if_SDL_fail(renderer.isNil, "NewApp(): renderer could not be created") if_SDL_fail(not ttfInit()): "NewApp(): SDL_TTF initialization failed" let font0 = ttf.openFont("./assets/UbuntuMono-R.ttf", cons.TextHeight) if_SDL_fail(font0.isNil, "NewApp(): font could not be created") let font=NewFont(font0, renderer) let game = NewPong(font, renderer) let sf=App( window:window, renderer:renderer, font:font, game:game, event:defaultEvent, ) return sf var keyUp, keyDown:bool proc loop(sf:var App){.inline.}= case sf.event.kind of QuitEvent: sf.isRun = false of KeyDown: # game.sdlInput[event.key.keysym.scancode.toInput] = true # game.sdlInput[event.key.keysym.scancode.toInput] = false # Теперь безопасно проверяем конкретные клавиши case sf.event.key.keysym.scancode of SDL_SCANCODE_UP: keyUp=true of SDL_SCANCODE_DOWN: keyDown=true else: discard of KeyUp: # Останавливаем движение, когда стрелки отпущены case sf.event.key.keysym.scancode of SDL_SCANCODE_UP: keyUp=false of SDL_SCANCODE_DOWN: keyDown=false else: discard else: discard proc run(sf:var App)= defer: sdl2.quit() defer: sf.window.destroy() defer: sf.renderer.destroy() defer: ttfQuit() var lastTime = getTicks() # Время на предыдущем кадре fpsTimer = getTicks() # Таймер для обновления счетчика FPS frameCount = 0 # Счетчик отрисованных кадров fps = 0 # Итоговый FPS для вывода while sf.isRun: # 1. Считаем время между кадрами (в миллисекундах) let currentTime = getTicks() # Переводим в секунды (разделив на 1000), чтобы использовать как dt sf.dt = (currentTime - lastTime).float / 1000.0 lastTime = currentTime # 2. Считаем FPS (обновляем раз в секунду, чтобы текст не мерцал) inc frameCount if currentTime - fpsTimer >= 1000: fps = frameCount frameCount = 0 fpsTimer = currentTime # Выводим FPS напрямую в заголовок окна для теста sf.window.setTitle(("Pong Game | FPS: " & $fps).cstring) sf.event = defaultEvent while pollEvent(sf.event): sf.loop() if keyUp: sf.game.keyUp(sf.dt) elif keyDown: sf.game.keyDown(sf.dt) else: sf.game.stopHuman() sf.game.update(sf.dt) let txtFps="FPS: " & $fps color:Color=(r:255,g:255,b:0,a:255) sf.game.draw() sf.font.text(txtFps, 50, 50, color) sf.renderer.present() proc main = var app=NewApp() app.run() main()