nimcity.nim 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import sdl2
  2. import sdl2/ttf
  3. # import sdl2/private/keycodes
  4. from ./pong/cons import nil
  5. import ./pong/pong
  6. import ./pong/tmpl
  7. import ./pong/font
  8. type
  9. App {.requiresInit.}= object
  10. window:WindowPtr
  11. renderer:RendererPtr
  12. font:Font
  13. isRun = true
  14. game:Pong
  15. dt: float32=0
  16. event:Event
  17. proc NewApp():App=
  18. if_SDL_fail(not sdl2.init(INIT_VIDEO or INIT_TIMER or INIT_EVENTS)):
  19. "NewApp(): SDL2 initialization failed"
  20. let window = createWindow(
  21. title = "PingPong",
  22. x = SDL_WINDOWPOS_CENTERED,
  23. y = SDL_WINDOWPOS_CENTERED,
  24. w = cons.WindowWidth,
  25. h = cons.WindowHeight,
  26. flags = SDL_WINDOW_SHOWN
  27. )
  28. if_SDL_fail(window.isNil, "NewApp(): window could not be created")
  29. let renderer = createRenderer(
  30. window = window,
  31. index = -1,
  32. flags = Renderer_Accelerated or Renderer_PresentVsync or Renderer_TargetTexture
  33. )
  34. if_SDL_fail(renderer.isNil, "NewApp(): renderer could not be created")
  35. if_SDL_fail(not ttfInit()): "NewApp(): SDL_TTF initialization failed"
  36. let font0 = ttf.openFont("./assets/UbuntuMono-R.ttf", cons.TextHeight)
  37. if_SDL_fail(font0.isNil, "NewApp(): font could not be created")
  38. let font=NewFont(font0, renderer)
  39. let game = NewPong(font, renderer)
  40. let sf=App(
  41. window:window,
  42. renderer:renderer,
  43. font:font,
  44. game:game,
  45. event:defaultEvent,
  46. )
  47. return sf
  48. var
  49. keyUp, keyDown:bool
  50. proc loop(sf:var App){.inline.}=
  51. case sf.event.kind
  52. of QuitEvent:
  53. sf.isRun = false
  54. of KeyDown:
  55. # game.sdlInput[event.key.keysym.scancode.toInput] = true
  56. # game.sdlInput[event.key.keysym.scancode.toInput] = false
  57. # Теперь безопасно проверяем конкретные клавиши
  58. case sf.event.key.keysym.scancode
  59. of SDL_SCANCODE_UP:
  60. keyUp=true
  61. of SDL_SCANCODE_DOWN:
  62. keyDown=true
  63. else:
  64. discard
  65. of KeyUp:
  66. # Останавливаем движение, когда стрелки отпущены
  67. case sf.event.key.keysym.scancode
  68. of SDL_SCANCODE_UP:
  69. keyUp=false
  70. of SDL_SCANCODE_DOWN:
  71. keyDown=false
  72. else:
  73. discard
  74. else:
  75. discard
  76. proc run(sf:var App)=
  77. defer: sdl2.quit()
  78. defer: sf.window.destroy()
  79. defer: sf.renderer.destroy()
  80. defer: ttfQuit()
  81. var
  82. lastTime = getTicks() # Время на предыдущем кадре
  83. fpsTimer = getTicks() # Таймер для обновления счетчика FPS
  84. frameCount = 0 # Счетчик отрисованных кадров
  85. fps = 0 # Итоговый FPS для вывода
  86. while sf.isRun:
  87. # 1. Считаем время между кадрами (в миллисекундах)
  88. let currentTime = getTicks()
  89. # Переводим в секунды (разделив на 1000), чтобы использовать как dt
  90. sf.dt = (currentTime - lastTime).float / 1000.0
  91. lastTime = currentTime
  92. # 2. Считаем FPS (обновляем раз в секунду, чтобы текст не мерцал)
  93. inc frameCount
  94. if currentTime - fpsTimer >= 1000:
  95. fps = frameCount
  96. frameCount = 0
  97. fpsTimer = currentTime
  98. # Выводим FPS напрямую в заголовок окна для теста
  99. sf.window.setTitle(("Pong Game | FPS: " & $fps).cstring)
  100. sf.event = defaultEvent
  101. while pollEvent(sf.event):
  102. sf.loop()
  103. if keyUp:
  104. sf.game.keyUp(sf.dt)
  105. elif keyDown:
  106. sf.game.keyDown(sf.dt)
  107. else:
  108. sf.game.stopHuman()
  109. sf.game.update(sf.dt)
  110. let
  111. txtFps="FPS: " & $fps
  112. color:Color=(r:255,g:255,b:0,a:255)
  113. sf.game.draw()
  114. sf.font.text(txtFps, 50, 50, color)
  115. sf.renderer.present()
  116. proc main =
  117. var app=NewApp()
  118. app.run()
  119. main()