Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - dajan

Pages: [1] 2 3
1
Programs / Re: Coin Race!
« on: August 16, 2020, 07:00:43 am »
Nice game SierraKen, a bit easy to win, though. Challenging AI would make the code much longer. Maybe you could try something simple, like storing unpicked coin counts in rows/columns in array and turning the AI car into the one with the highest value on its way direction.

2
Programs / Re: Checkers with Mouse
« on: February 04, 2020, 05:24:37 pm »
Well, you can allways start with programming the difficulty level "I'm too young to lose", where the computer just makes random legal moves, unless it has a chance to jump over your stone. That I would be able to beat at least :o)  Good luck.

3
Programs / Re: Checkers with Mouse
« on: February 04, 2020, 03:00:44 am »
Nice one, bplus. How can I play against computer?

4
Programs / Re: Triangle Dissection
« on: January 31, 2020, 03:37:49 am »
Sorry for doble post.

5
Programs / Re: Triangle Dissection
« on: January 31, 2020, 03:34:23 am »
bplus, i suspect that is a very cool looking proof of some geometric rule, I don't have a clue about.

6
Programs / Re: Convert mouse input to DRAW
« on: January 25, 2020, 04:28:30 pm »
bplus, yeah thanks.
the maxpoints=100 and iterations=30 works about how I would expect.

7
I have done some improvements to this simple chasing game in the version 2.2 of it:

- graphics polished slightly
- added energy indicator on player
- increased the player boost speed to 5 times of the normal speed (much more fun)
- AI chooses a victim to chase more carefuly now. Unless being in low energy/panic mode, it chooses to eliminate the player closest to the victory. Therefore, it is really hard to win the match to zero. Analog gamepad is strongly recommended for the best control experience.

Code: QB64: [Select]
  1. '--------constants----------------------------------------------------------------------------------------------------------------------------------
  2. CONST MENU_BUILDSTR = "2.2.20.01.01"
  3. CONST RES_X = 1280 'screen horizontal resolution, set to -1 to match the dsektop
  4. CONST RES_Y = 720 'screen vertical resolution, set to -1 to match the dsektop
  5. CONST FPS = 100 'set target frames per seconds to 100 for proper physicss speed
  6. CONST DEBUGMODE = 0 'initial state of debug mode
  7. CONST FULLSCREENMODE = 0 'set 1 for fullscreen on startup, other value to window mode
  8. CONST RES_X_TARG = 1920 'world target horizontal resolution
  9. CONST RES_Y_TARG = 1080 'world target vertical resolution
  10. CONST MAX_COL = 247 'max. color number to use of 255
  11. CONST PLAYER_COUNT_INI = 3 'Initial players count
  12. CONST POCET_GUL_INI = 20 'Initial non player balls count
  13. CONST PLAYER_COUNT_MAX = 32 'Maximum players count
  14. CONST PLAYER_NET_MAX = 8 'Max. number of network players
  15. CONST PLAYER_NET_MIN = 2 'First network control enabled player
  16. CONST POCET_GUL_MAX = 32 'Maximum balls count
  17. CONST STRAT_COUNT_MAX = 20 'Maximum players strategies
  18. CONST PLAY_BALL_R = 20 'Players ball size
  19. CONST V_MAX = 300 / FPS 'Max player ball velocity
  20. CONST ACC_X = 10 / FPS 'Balls acceleration X
  21. CONST ACC_Y = 10 / FPS 'Balls accelereation Y
  22. CONST FRICTION = 0.998 'Space fricition coeffifcient
  23. CONST ENERGY_ALL_MIN = 500 'min.starting energy of all players together
  24. CONST ENERGY_PLAYER_MIN = 50 'min. player's starting energy
  25. CONST ENERGY_PLAYER_MAX = 150 'max. player's starting energy
  26. CONST ENERGY_DEC = 5 / FPS 'ball energy decrement
  27. CONST REACTIME_AVG_NORMAL = 0 * FPS 'Average AI reaction time in sec*FPS
  28. CONST CHYBASMERU_NORMAL = 0.0 'Improper reaction rate
  29. CONST PRIESTOR_MIN = PLAY_BALL_R + 100
  30. CONST DELAY_ROUNDSTART = 8 'delay in seconds after round end to accept resume
  31. CONST DELAY_MATCHEND = 20 'delay in seconds after match end to accept resume
  32. CONST FREEZE_TIME = 1.0 * FPS 'player freeze time after getting tag in seconds
  33. CONST SCORE_POS_X = 50 'Score horizontal draw position
  34. CONST SCORE_DELTA_Y = 13 'Score draw - vertictal offset from screen top
  35. CONST SCORE_DELTA_X = 350 'Score draw - players score horizontal offset
  36. CONST SCORE_NAME_LEN = 120 'Score draw - horizontal space for player name
  37. CONST BOOST_V_KOEF = 3.0 'boost factor of extra maximum speed
  38. CONST BOOST_TRVANIE = 1 * FPS 'boost duration
  39. CONST BOOST_TIME = 1 * FPS 'min time between boosts in sec*fps
  40. CONST MENUCURSOR_COLOR = 15 'Menu cursor color
  41. CONST MENUITEM_COLOR = 7 'Menu cursor color
  42. CONST MENU_PLAYERS_COUNT = 8 'Number of players in menu
  43. CONST FONT_W = 8 'Font width in pixels
  44. CONST FONT_H = 16 'Font height in pixels
  45. CONST GAMESTICK_DEADZONE = 0.05 'gamepad stick axis maximum value considered as zero
  46. CONST CPU_CONTROLID = PLAYER_NET_MAX + 1 'CPU controller id
  47. CONST HOSTIP_DEFAULT = "" '"localhost" '
  48. CONST HOSTPORT_DEFAULT = 7432
  49. CONST GETITEM_SYNC = "SNC" 'network trasfer item code
  50. CONST GETITEM_STAV = "SNS" 'network trasfer item code
  51. CONST GETITEM_BAL = "SNB" 'network trasfer item code
  52. CONST GETITEM_PBAL = "SNP" 'network trasfer item code
  53. CONST GETITEM_KLAV = "SNK" 'network trasfer item code
  54. CONST GETITEM_HRAC = "SNH" 'network trasfer item code
  55. CONST GETITEM_MESG = "SNM" 'network trasfer item code
  56. CONST GETITEM_STAT = "SNT" 'network trasfer item code
  57. CONST NET_TIMEOUT_LIMIT = 10 'timeout to disconnect in seconds
  58. CONST NET_TIMEOUT_SYNC = 0.01 'timeout to get synced in seconds
  59. CONST MSG_COUNT_MAX = 20 'max. messages displayed
  60. CONST MSG_LEN_MAX = 80 'max. length of message
  61. CONST MSG_DUR_STD = 20 'message standard duration in seconds
  62. CONST MSG_COL = 7 'message standard color
  63. CONST UPDATE_PER_BAL = 0.1 'all balls network update period in seconds
  64. CONST UPDATE_PER_PLBAL = 0.04 'player balls network update period in seconds
  65. CONST UPDATE_PER_HRAC = 0.1 'players network update period in seconds
  66. CONST UPDATE_PER_STAV = 0.04 'world state network update period in seconds
  67. CONST AUTOSTART_SEC_MAX = 180 'max game autostart time
  68.  
  69. '--------type definitions----------------------------------------------------------------------------------------------------------------------------
  70. TYPE vektor 'general 2D vector type
  71.     x AS SINGLE
  72.     y AS SINGLE
  73.  
  74. TYPE tstav 'game world state type  (cca 100B)
  75.     minx AS INTEGER 'world - minimum x position
  76.     maxx AS INTEGER 'world - maximum x position
  77.     miny AS INTEGER 'world - minimum y position
  78.     maxy AS INTEGER 'world - maximum y position
  79.     vmax AS SINGLE 'maximum unboosted ball velocity
  80.     maxcol AS INTEGER 'world - maximum of colors
  81.     pocetgulzvoleny AS INTEGER 'number of balls desired
  82.     pocetgul AS INTEGER 'number of balls actual
  83.     pocetgulx AS INTEGER 'number of balls in bottom row
  84.     pocetguly AS INTEGER 'number of balls in left column
  85.     pocethracov AS INTEGER 'number of players
  86.     energy_allmin AS SINGLE 'all players starting energy sum
  87.     energy_playermin AS SINGLE 'minimum starting energy of player
  88.     energy_playermax AS SINGLE 'maximum starting energy of player
  89.     energy_player_start AS SINGLE 'player's starting energy
  90.     energydec AS SINGLE 'energy decrease unit
  91.     baljeto AS INTEGER 'actual tagged ball idx
  92.     balbudeto AS INTEGER 'successor tagged ball idx
  93.     vitaz AS INTEGER 'winner player idx
  94.     koniec_kola AS _BYTE 'end of round flag (0=no end, 1=end of round, 2=end fo round and match)
  95.     odpor AS SINGLE 'space friction
  96.     massallowed AS _BYTE 'calculate balls with different masses
  97.     pauza AS _BYTE 'game pause flag (0 or 1)
  98.     gameplay AS _BYTE 'state of session: 0=menu, 1=gameplay
  99.     fps AS SINGLE 'fps target set
  100.     zacinabal AS INTEGER 'initially tagged ball idx
  101.     boostallowed AS _BYTE 'player boost mode allowed (0 or 1)
  102.     syncstr AS STRING * 3 'net synchronisation string code
  103.     synctime AS DOUBLE 'net synchronisation time stamp
  104.     AIallowed AS _BYTE 'AI players in netgame allowed=1
  105.     autostart_set AS INTEGER 'game autostart setting in seconds; 0=off
  106.     autostart_timeleft AS SINGLE 'actual time to autostart the game in seconds
  107.     winscore AS _BYTE 'score to win a match
  108.  
  109. TYPE gula 'ball  type  (cca 90B)
  110.     i AS INTEGER 'balls id
  111.     x AS SINGLE 'balls y position
  112.     y AS SINGLE 'balls y position
  113.     r AS SINGLE 'radius
  114.     m AS SINGLE 'mass
  115.     v AS vektor 'velocity
  116.     vi AS vektor 'desired velocity
  117.     a AS vektor 'acceleration
  118.     col AS INTEGER 'balls color
  119.     riadena AS INTEGER 'is actually player controllable (0 or 1)
  120.     complayer AS INTEGER 'is computer player's ball (0 or 1)
  121.     protivnik AS INTEGER 'actual ball's enemy ball id
  122.     strat AS INTEGER 'balls behaviour strategy id
  123.     energia AS SINGLE 'players energy
  124.     freezedtime AS INTEGER 'actual time to unfreeze players control
  125.     smer_odchyl AS SINGLE 'actual deviance from intended direction in radians
  126.     klucka_time AS INTEGER 'actual time to start doging
  127.     klucka_uhol AS SINGLE 'actual dodge angle
  128.     klucka_trvanie AS INTEGER 'actual dodge duration
  129.     klucka_pocet AS INTEGER 'actual dodge count
  130.     boost_time AS INTEGER 'actual time to boost allowed again
  131.     boost_trvanie AS INTEGER 'actual time to end boost
  132.     reactdrop_time AS INTEGER 'actual time to start reaction drop in frames
  133.     reactdrop_dur AS INTEGER 'actual time to stop reaction drop in frames
  134.     boostintended AS INTEGER 'intention to boost or not (1, 0)
  135.     syncstr AS STRING * 3 'net synchronisation string code
  136.     synctime AS DOUBLE 'net synchronisation time stamp
  137.     hrac AS INTEGER 'ball player's id
  138.  
  139. TYPE tstrat 'balls behaviour strategy type
  140.     okraj AS INTEGER 'distance from screen border to turn
  141.     okraj_rot AS SINGLE 'distance from screen border to turn
  142.     chybasmeru AS SINGLE 'percentage of deviance from desired direction -- not used currently
  143.     react_lag AS INTEGER 'average reaction time in frames
  144.     klucka_avgtm AS SINGLE 'average time between dodging in fps +-50%
  145.     klucka_uhol AS SINGLE 'average dodge angle
  146.     klucka_trvanie AS INTEGER 'average dodge time +-50%
  147.     klucka_pocet AS INTEGER 'average dodge count
  148.     klucka_uholodch AS SINGLE 'dodge angle deviation percentage
  149.     detekcia_sin AS SINGLE 'sinus of frontal enemy detection angle
  150.     detekcia_vzdfull AS SINGLE 'distance of frontal enemy full detection
  151.     detekcia_vzdmin AS SINGLE 'distance of frontal enemy minimum detection
  152.     detekcia_rot AS SINGLE 'amount of rotation on enemy detection in radians
  153.     reactdrop_per AS INTEGER 'average reaction drop period in frames
  154.     reactdrop_dur AS INTEGER 'average reaction drop duration in frames
  155.     boost_rate AS SINGLE 'inclination to use boost in percent
  156.     boost_dist AS SINGLE 'enemy distance activating boost deciding
  157.     boost_chasesin AS SINGLE 'max. sinus of enemy to player velocity angle to apply chasing boost
  158.     mate_cosenmax AS SINGLE 'max. cosinus of (player-enemy vector to player velocity) to rotate to mate
  159.     mate_rot AS SINGLE 'amount of unit rotation towards nearest mate in rad per frame
  160.     mate_en_distmin AS SINGLE 'min. distance from enemy to apply rotation towards mate
  161.     mate_distmin AS SINGLE 'min. distance from mate to apply rotation towards mate
  162.     adrenalin_rate AS SINGLE 'percentage of reaction time improved in adrenalin mode
  163.     adrenalin_energy AS SINGLE 'energy level precentage starting adrenalin mode
  164.  
  165. TYPE thrac 'player type
  166.     i AS INTEGER 'player index number
  167.     meno AS STRING * 10 'players name
  168.     skore AS _BYTE 'players score
  169.     klavesy AS _BYTE 'players control keys set index
  170.     bal AS INTEGER 'player driven ball idx
  171.     col AS INTEGER 'player's choosed color
  172.     clientid AS _BYTE 'index of hosted client, 0 if local player
  173.     isready AS _BYTE '1=player is ready for game start
  174.     syncstr AS STRING * 3
  175.     synctime AS DOUBLE
  176.  
  177. TYPE tklavesy 'players controller type
  178.     id AS INTEGER 'controllers id
  179.     devid AS INTEGER 'controllers device id  (0=unused)
  180.     typ AS _BYTE 'type of controller (0=unused, 1=keyboard, 2=mouse reserved, 3=gamepad, 4=AI, 5=network, 6=empty)
  181.     nazov AS STRING * 25 'game controllers name
  182.     up AS LONG 'key code for up
  183.     down AS LONG 'keyp code for down
  184.     right AS LONG 'key code for right
  185.     left AS LONG 'key code for left
  186.     shoota AS LONG 'keyborad key code or gamepad button id
  187.     shootb AS LONG 'keyborad key code or gamepad button id
  188.     xaxis AS _BYTE 'gamepad analog x-asis id
  189.     yaxis AS _BYTE 'gamepad analog y-asis id
  190.     dxaxis AS _BYTE 'gamepad digital x-asis id
  191.     dyaxis AS _BYTE 'gamepad digital y-asis id
  192.     isup AS _BYTE 'controllers actual state for up
  193.     isdown AS _BYTE 'controllers actual state for down
  194.     isright AS _BYTE 'controllers actual state for right
  195.     isleft AS _BYTE 'controllers actual state for left
  196.     isshoota AS _BYTE 'controllers actual state for fire 1
  197.     isshootb AS _BYTE 'controllers actual state for fire 2
  198.     gvektor AS vektor 'controllers actual x and y axis state
  199.     buttonstate AS LONG 'all gamepads buttons cumulative state value
  200.     buttonstatechanged AS _BYTE '0 if no button state change, 1 if any button state changed
  201.     buttonstatetimer AS INTEGER
  202.     syncstr AS STRING * 3 'net synchronisation string code
  203.     synctime AS DOUBLE 'net synchronisation time stamp
  204.  
  205. TYPE tmenu
  206.     title AS STRING * 10 'menu title use for nothing
  207.     items_count AS INTEGER 'menu items count
  208.     item_active AS INTEGER 'active item index
  209.     item_height AS INTEGER 'menu item height in pixels
  210.     cursor_col AS INTEGER 'menu cursor color
  211.     cursor_xpos AS INTEGER 'x position of cursors left side
  212.     cursor_out AS INTEGER 'cursor bar outset
  213.     ypos AS INTEGER 'y position of cursor
  214.     cursor_width AS INTEGER 'cursor width in pixels
  215.     menucode AS INTEGER 'stores code of selected action upon active menuitem
  216.     playercode AS INTEGER 'stores  player id of active menuitem
  217.  
  218. TYPE tmessage
  219.     clientid AS INTEGER 'client origin of message
  220.     text AS STRING * MSG_LEN_MAX 'message text
  221.     time_start AS DOUBLE 'message time
  222.     time_dur AS SINGLE 'message duration
  223.     col AS INTEGER 'message color
  224.     distribute AS INTEGER 'message dsitribution status 1=distribute
  225.     syncstr AS STRING * 3 'net synchronisation string code
  226.     synctime AS DOUBLE 'net synchronisation time stamp
  227.  
  228. TYPE tgamesession 'my game session properties
  229.     maxx AS INTEGER 'my screen x resolution
  230.     maxy AS INTEGER 'my screen y resolution
  231.     isnetgame AS _BYTE 'network game flag; 1=network, 0=local
  232.     hosth AS INTEGER 'my host handle
  233.     clienth AS INTEGER 'my client handle
  234.     clientid AS INTEGER 'my client's id registered at host
  235.     host_ip AS STRING * 100 'host's ip to connect as a client
  236.     host_port AS LONG 'host's port to connect as a client
  237.     get_item AS STRING * 3 'actual item to get from host
  238.     get_time AS DOUBLE 'time of last succesfull reading from host
  239.     get_isdesync AS INTEGER 'net transfer is desynced=1
  240.     fpsactual AS SINGLE 'fps achieved
  241.     fpscoef AS SINGLE 'fps actual/target
  242.     tstart AS DOUBLE 'timer start time
  243.     tend AS DOUBLE 'timer end time
  244.     pocetgamepadov AS INTEGER 'number of gamepads detected
  245.     pocetkontrolerov AS INTEGER 'number of game controllers
  246.     start AS INTEGER 'start game flag (0 or 1)
  247.     exituj AS INTEGER 'exit game flag (0 or 1)
  248.     printdebug AS INTEGER 'debug mode flag (0 or 1)
  249.     msgcount AS INTEGER 'total number of actual messages
  250.     msgwrite AS INTEGER 'message write mode=1
  251.     newmsg AS INTEGER 'is new messages to distribute flag
  252.     msgtext AS STRING * MSG_LEN_MAX 'message text being actually written
  253.     autostart_time AS SINGLE 'local host time of game autostart
  254.     timer_pballs AS SINGLE 'local time of last player balls update from host
  255.     sync_stats AS _BYTE 'send statistics to clients flag
  256.     show_stats AS _BYTE 'display match statistics
  257.  
  258. TYPE tclient 'hosted client type
  259.     conn AS INTEGER 'connection handle of hosted client
  260.     ip AS STRING * 100 'ip of hosted client
  261.     get_item AS STRING * 3 'next item to get from client
  262.     get_time AS DOUBLE 'time of last succesfull reading from client
  263.     get_isdesync AS INTEGER 'net desynchronisation flag host cannot get from client
  264.     isdesynced AS _BYTE 'client side is desynced - cannot get from host
  265.     spectating AS _BYTE 'client player control enabled
  266.  
  267. TYPE tsyncvar
  268.     syncstr AS STRING * 3 'sync string code
  269.     synctime AS DOUBLE 'net synchronisation time stamp
  270.     itemstr AS STRING * 3 'code of the next item to get
  271.     isdesync AS _BYTE '1=the other side is desynced
  272.     clientid AS INTEGER 'client id
  273.  
  274. '-----global variables-------------------------------------------------------------------------------------------------------------------------------
  275. REDIM SHARED bal(1 TO POCET_GUL_MAX + PLAYER_COUNT_MAX) AS gula 'balls
  276. DIM SHARED klav(1 TO PLAYER_COUNT_MAX) AS tklavesy 'keyboard control sets
  277. DIM SHARED stav AS tstav 'game world state
  278. DIM SHARED strat(1 TO STRAT_COUNT_MAX) AS tstrat 'computer players strategies
  279. DIM SHARED hrac(1 TO PLAYER_COUNT_MAX) AS thrac 'players balls
  280. DIM SHARED sync AS tsyncvar 'net sync variable
  281. DIM SHARED stats(1 TO PLAYER_NET_MAX + 1, 1 TO PLAYER_NET_MAX) AS INTEGER 'players game statistics
  282.  
  283. REDIM SHARED ibal(1 TO POCET_GUL_MAX) AS gula 'nonplayer balls transfer array
  284. REDIM SHARED ipbal(1 TO PLAYER_NET_MAX) AS gula 'players balls transfer array
  285. DIM SHARED iklav(1 TO PLAYER_COUNT_MAX) AS tklavesy 'keyboard control sets transfer array
  286. DIM SHARED istav AS tstav 'game world state transfer array
  287. DIM SHARED ihrac(1 TO PLAYER_NET_MAX) AS thrac 'players balls transfer array
  288. DIM SHARED isync AS tsyncvar 'net sync variable transfer array
  289. DIM SHARED istats(1 TO PLAYER_NET_MAX + 1, 1 TO PLAYER_NET_MAX) AS INTEGER 'players game statistics transfer
  290.  
  291. DIM SHARED client(1 TO 8) AS tclient
  292. DIM SHARED menu AS tmenu
  293. DIM SHARED game AS tgamesession
  294. DIM SHARED msg(1 TO MSG_COUNT_MAX) AS tmessage
  295.  
  296. '----main program------------------------------------------------------------------------------------------------------------------------------------
  297. SetGlobalParameters
  298. SetUpControllers
  299. IF game.pocetgamepadov > 0 THEN hrac(1).klavesy = game.pocetkontrolerov 'set gamepad as default controller for player1
  300.  
  301. SCREEN _NEWIMAGE(game.maxx, game.maxy, 256), , ,
  302. IF FULLSCREENMODE = 1 THEN _FULLSCREEN
  303. AddMessage "Welcome in the Tag game.", MSG_COL, 5, 0
  304. AddMessage "To display/hide match statistics press 'c' while gameplay.", MSG_COL, 8, 0
  305. AddMessage "Default TCP port for the network game is 7432. ", MSG_COL, 11, 0
  306.  
  307.     '--------Main menu begin---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  308.     REDIM SHARED ibal(1 TO POCET_GUL_MAX) AS gula 'nonplayer balls transfer array
  309.     REDIM SHARED ipbal(1 TO PLAYER_NET_MAX) AS gula 'players balls transfer array
  310.     DIM playerst(1 TO 8) AS STRING * 30
  311.     DIM hoststat AS STRING * 50
  312.     DIM joinstat AS STRING * 50
  313.     DIM autostart AS STRING
  314.     DIM AIplayers AS STRING
  315.     DIM newenergy AS STRING * 3
  316.  
  317.     stav.gameplay = 0
  318.     vys = FONT_H
  319.     sir = FONT_W
  320.     menu.items_count = 27
  321.  
  322.     DO
  323.         WINDOW (0, 0)-(game.maxx, game.maxy)
  324.         IF game.hosth <> 0 THEN hoststat = "host started" ELSE hoststat = ""
  325.         IF game.clienth <> 0 AND game.clientid = 0 THEN joinstat = "joining game...   "
  326.         IF game.clienth <> 0 AND game.clientid <> 0 THEN joinstat = "connected to         " + LEFT$(game.host_ip, 30)
  327.         IF game.clienth = 0 AND game.clientid = 0 THEN joinstat = ""
  328.         ReadyPlayersCount = 0
  329.         FOR i = 1 TO 8
  330.             playerst(i) = ""
  331.             IF game.isnetgame = 1 THEN
  332.                 IF hrac(i).clientid > 0 THEN playerst(i) = "  state: connected" ELSE playerst(i) = "  state: "
  333.                 IF klav(hrac(i).klavesy).typ <= 3 THEN playerst(i) = "  state: local player"
  334.                 IF hrac(i).isready = 1 AND hrac(i).clientid > 0 THEN playerst(i) = RTRIM$(playerst(i)) + " / ready!": ReadyPlayersCount = ReadyPlayersCount + 1
  335.             END IF
  336.         NEXT i
  337.  
  338.         IF stav.autostart_set = 0 THEN
  339.             autostart = "Off"
  340.         ELSE
  341.             HumanPlayers = HumanPlayersCount
  342.             IF game.autostart_time - stav.autostart_set > TIMER THEN game.autostart_time = game.autostart_time - 86399
  343.             IF (game.isnetgame = 0 OR (game.isnetgame = 1 AND game.hosth <> 0)) THEN stav.autostart_timeleft = game.autostart_time - TIMER
  344.             IF (game.isnetgame = 0 OR (game.isnetgame = 1 AND game.hosth <> 0)) AND game.autostart_time <= TIMER THEN
  345.                 IF stav.AIallowed = 1 OR (stav.AIallowed = 0 AND HumanPlayers >= 2) THEN
  346.                     game.start = 1
  347.                 ELSE
  348.                     game.autostart_time = TIMER + stav.autostart_set
  349.                 END IF
  350.             END IF
  351.             IF game.isnetgame = 1 AND game.hosth <> 0 AND ReadyPlayersCount = HumanPlayers AND ((stav.AIallowed = 1 AND HumanPlayers >= 1) OR (stav.AIallowed = 0 AND HumanPlayers >= 2)) THEN game.start = 1
  352.             autostart = LTRIM$(STR$(stav.autostart_set)) + " sec               " + LTRIM$(STR$(INT(stav.autostart_timeleft))) + " left"
  353.         END IF
  354.  
  355.         IF stav.AIallowed = 1 THEN AIplayers = "Yes" ELSE AIplayers = "No"
  356.  
  357.         CLS 1
  358.         DisplayMessages
  359.         PrintMenuItem -2, menu, 0, 0, 0, "Tag! v.2", 0, 0, -3, 13
  360.         PrintMenuItem -1, menu, 0, 0, 0, "created in QuickBasic64 by Daniel Janec (2019) build " + MENU_BUILDSTR, 0, 0, -2, 20
  361.         PrintMenuItem 1, menu, 6, 0, 0, "Play <Space>", 0, 0, 0, MENUITEM_COLOR
  362.         PrintMenuItem 2, menu, 1, 0, 0, "Refresh gamepads detected: " + STR$(game.pocetgamepadov), 0, 0, 0, MENUITEM_COLOR
  363.         PrintMenuItem 3, menu, 2, 1, 1, hrac(1).meno + " controls: " + klav(hrac(1).klavesy).nazov + RTRIM$(playerst(1)), 150, -10 * sir, 1, hrac(1).col
  364.         PrintMenuItem 4, menu, 3, 1, 1, "              color:" + STR$(hrac(1).col), 150, -10 * sir, 1, hrac(1).col
  365.         PrintMenuItem 5, menu, 2, 2, 1, hrac(2).meno + " controls: " + klav(hrac(2).klavesy).nazov + RTRIM$(playerst(2)), 150, -10 * sir, 1, hrac(2).col
  366.         PrintMenuItem 6, menu, 3, 2, 1, "              color:" + STR$(hrac(2).col), 150, -10 * sir, 1, hrac(2).col
  367.         PrintMenuItem 7, menu, 2, 3, 1, hrac(3).meno + " controls: " + klav(hrac(3).klavesy).nazov + RTRIM$(playerst(3)), 150, -10 * sir, 1, hrac(3).col
  368.         PrintMenuItem 8, menu, 3, 3, 1, "              color:" + STR$(hrac(3).col), 150, -10 * sir, 1, hrac(3).col
  369.         PrintMenuItem 9, menu, 2, 4, 1, hrac(4).meno + " controls: " + klav(hrac(4).klavesy).nazov + RTRIM$(playerst(4)), 150, -10 * sir, 1, hrac(4).col
  370.         PrintMenuItem 10, menu, 3, 4, 1, "              color:" + STR$(hrac(4).col), 150, -10 * sir, 1, hrac(4).col
  371.         PrintMenuItem 11, menu, 2, 5, 1, hrac(5).meno + " controls: " + klav(hrac(5).klavesy).nazov + RTRIM$(playerst(5)), 150, -10 * sir, 1, hrac(5).col
  372.         PrintMenuItem 12, menu, 3, 5, 1, "              color:" + STR$(hrac(5).col), 150, -10 * sir, 1, hrac(5).col
  373.         PrintMenuItem 13, menu, 2, 6, 1, hrac(6).meno + " controls: " + klav(hrac(6).klavesy).nazov + RTRIM$(playerst(6)), 150, -10 * sir, 1, hrac(6).col
  374.         PrintMenuItem 14, menu, 3, 6, 1, "              color:" + STR$(hrac(6).col), 150, -10 * sir, 1, hrac(6).col
  375.         PrintMenuItem 15, menu, 2, 7, 1, hrac(7).meno + " controls: " + klav(hrac(7).klavesy).nazov + RTRIM$(playerst(7)), 150, -10 * sir, 1, hrac(7).col
  376.         PrintMenuItem 16, menu, 3, 7, 1, "              color:" + STR$(hrac(7).col), 150, -10 * sir, 1, hrac(7).col
  377.         PrintMenuItem 17, menu, 2, 8, 1, hrac(8).meno + " controls: " + klav(hrac(8).klavesy).nazov + RTRIM$(playerst(8)), 150, -10 * sir, 1, hrac(8).col
  378.         PrintMenuItem 18, menu, 3, 8, 1, "              color:" + STR$(hrac(8).col), 150, -10 * sir, 1, hrac(8).col
  379.         PrintMenuItem 19, menu, 8, 0, 1, "Player starting energy: " + LTRIM$(STR$(stav.energy_player_start)), 100, -10 * sir, 2, MENUITEM_COLOR
  380.         PrintMenuItem 20, menu, 4, 0, 1, "     Number of players: " + LTRIM$(STR$(stav.pocethracov)), 100, -10 * sir, 2, MENUITEM_COLOR
  381.         PrintMenuItem 21, menu, 12, 0, 1, "   CPU players allowed: " + AIplayers, 100, -10 * sir, 2, MENUITEM_COLOR
  382.         PrintMenuItem 22, menu, 5, 0, 1, "           Balls count: " + LTRIM$(STR$(stav.pocetgulzvoleny)), 100, -10 * sir, 2, MENUITEM_COLOR
  383.         PrintMenuItem 23, menu, 13, 0, 1, "   Match winning score: " + LTRIM$(STR$(stav.winscore)), 100, -10 * sir, 2, MENUITEM_COLOR
  384.         PrintMenuItem 24, menu, 11, 0, 1, "        Game autostart: " + autostart, 100, -10 * sir, 2, MENUITEM_COLOR
  385.         PrintMenuItem 25, menu, 9, 0, 0, "             Host game: " + hoststat, 100, -10 * sir, 2, MENUITEM_COLOR
  386.         PrintMenuItem 26, menu, 10, 0, 0, "             Join game: " + joinstat, 100, -10 * sir, 2, MENUITEM_COLOR
  387.         PrintMenuItem 27, menu, 7, 0, 0, "Exit <Esc>", 0, 0, 2, MENUITEM_COLOR
  388.         PrintMenuCursor menu
  389.  
  390.         k = _KEYHIT 'read menu action
  391.         IF game.msgwrite = 1 AND game.isnetgame = 1 THEN WriteMessage k: k = 0
  392.         IF game.msgwrite = 0 AND game.isnetgame = 1 THEN WriteMessage -1
  393.  
  394.         '---debug code begin---------------------------------------------
  395.         IF k = 98 THEN game.printdebug = -(game.printdebug = 0)
  396.         IF game.printdebug = 1 THEN DebugScreen k 'print debug info on screen
  397.         '---debug code end-----------------------------------------------
  398.  
  399.         FOR i = 1 TO game.pocetkontrolerov
  400.             IF klav(i).typ = 3 THEN
  401.                 ReadGamepad klav(i)
  402.                 IF klav(i).buttonstatechanged THEN
  403.                     IF klav(i).isshoota THEN k = 13: klav(i).isshoota = 0
  404.                     IF klav(i).isup THEN k = 18432: klav(i).isup = 0
  405.                     IF klav(i).isdown THEN k = 20480: klav(i).isdown = 0
  406.                     IF klav(i).isright THEN k = 19712: klav(i).isright = 0
  407.                     IF klav(i).isleft THEN k = 19200: klav(i).isleft = 0
  408.                 END IF
  409.             END IF
  410.         NEXT i
  411.  
  412.         SELECT CASE k 'perform menu choice
  413.             CASE 18432 'up
  414.                 IF menu.item_active > 1 THEN menu.item_active = menu.item_active - 1
  415.             CASE 20480 'down
  416.                 IF menu.item_active < menu.items_count THEN menu.item_active = menu.item_active + 1
  417.             CASE 19200 'left
  418.                 SELECT CASE menu.menucode
  419.                     CASE 2 'players controller
  420.                         i = menu.playercode
  421.                         hrac(i).klavesy = hrac(i).klavesy - 1
  422.                         IF hrac(i).klavesy < PLAYER_NET_MAX + 1 THEN hrac(i).klavesy = PLAYER_NET_MAX + 1
  423.                     CASE 3 'players color
  424.                         i = menu.playercode
  425.                         hrac(i).col = hrac(i).col - 1
  426.                         IF hrac(i).col < 1 THEN hrac(i).col = stav.maxcol
  427.                     CASE 4 'players count
  428.                         IF stav.pocethracov > 2 THEN
  429.                             stav.pocethracov = stav.pocethracov - 1
  430.                         END IF
  431.                     CASE 5 'balls count
  432.                         IF stav.pocetgulzvoleny > 0 THEN
  433.                             stav.pocetgulzvoleny = stav.pocetgulzvoleny - 1
  434.                         END IF
  435.                     CASE 8 'starting energy
  436.                         IF stav.energy_player_start > 10 THEN
  437.                             stav.energy_player_start = stav.energy_player_start - 1
  438.                         END IF
  439.                     CASE 11 'game autostart
  440.                         IF stav.autostart_set > 0 THEN
  441.                             stav.autostart_set = stav.autostart_set - 10
  442.                             game.autostart_time = TIMER + stav.autostart_set
  443.                         END IF
  444.                     CASE 12 'CPU players allowed
  445.                         stav.AIallowed = 0
  446.                     CASE 13 'Winning score
  447.                         IF stav.winscore > 1 THEN stav.winscore = stav.winscore - 1
  448.                 END SELECT
  449.             CASE 19712 'right
  450.                 SELECT CASE menu.menucode
  451.                     CASE 2 'players controller
  452.                         i = menu.playercode
  453.                         hrac(i).klavesy = hrac(i).klavesy + 1
  454.                         IF hrac(i).klavesy > game.pocetkontrolerov THEN hrac(i).klavesy = game.pocetkontrolerov
  455.                     CASE 3 'players color
  456.                         i = menu.playercode
  457.                         hrac(i).col = hrac(i).col + 1
  458.                         IF hrac(i).col > stav.maxcol THEN hrac(i).col = 1
  459.                     CASE 4 'players count
  460.                         IF stav.pocethracov < PLAYER_COUNT_MAX THEN
  461.                             stav.pocethracov = stav.pocethracov + 1
  462.                         END IF
  463.                     CASE 5 'balls count
  464.                         IF stav.pocetgulzvoleny < POCET_GUL_MAX THEN
  465.                             stav.pocetgulzvoleny = stav.pocetgulzvoleny + 1
  466.                         END IF
  467.                     CASE 8 'starting energy
  468.                         IF stav.energy_player_start < ENERGY_PLAYER_MAX THEN
  469.                             stav.energy_player_start = stav.energy_player_start + 1
  470.                         END IF
  471.                     CASE 11 'game autostart
  472.                         IF stav.autostart_set < AUTOSTART_SEC_MAX THEN
  473.                             stav.autostart_set = stav.autostart_set + 10
  474.                             game.autostart_time = TIMER + stav.autostart_set
  475.                         END IF
  476.                     CASE 12 'CPU players allowed
  477.                         stav.AIallowed = 1
  478.                     CASE 13 'Winning score
  479.                         IF stav.winscore < 99 THEN stav.winscore = stav.winscore + 1
  480.                 END SELECT
  481.             CASE 13 'enter
  482.                 SELECT CASE menu.menucode
  483.                     CASE 1
  484.                         SetUpControllers
  485.                     CASE 8 'starting energy
  486.                         newenergy = LTRIM$(STR$(stav.energy_player_start))
  487.                         newenergy = InputText$(newenergy, menu.cursor_xpos + 2 * sir, menu.ypos + (menu.item_active - 1) * menu.item_height, MENUITEM_COLOR, 48, "<Type starting energy>", 0, 1)
  488.                         IF LEFT$(newenergy$, 1) <> CHR$(27) AND LEN(RTRIM$(newenergy$)) > 0 THEN
  489.                             energyval = VAL(newenergy)
  490.                             IF energyval < 10 THEN energyval = 10
  491.                             IF energyval > ENERGY_PLAYER_MAX THEN energyval = ENERGY_PLAYER_MAX
  492.                             stav.energy_player_start = energyval
  493.                         END IF
  494.                     CASE 2 'set new name
  495.                         novemeno$ = InputText$(hrac(menu.playercode).meno, menu.cursor_xpos + 2 * sir, menu.ypos + (menu.item_active - 1) * menu.item_height, hrac(menu.playercode).col, 14, "<Type name>", 0, 0)
  496.                         IF novemeno$ <> CHR$(27) AND LEN(novemeno$) > 0 THEN hrac(menu.playercode).meno = novemeno$
  497.                     CASE 9 'host game
  498.                         HostGame
  499.                     CASE 10 'join game
  500.                         IF game.clienth = 0 THEN
  501.                             gethostip$ = InputText$(game.host_ip, menu.cursor_xpos + 2 * sir, menu.ypos + (menu.item_active - 1) * menu.item_height, MENUITEM_COLOR, LEN(game.host_ip), "<Type IP address or host name>", 1, 0)
  502.                             IF gethostip$ <> CHR$(27) THEN game.host_ip = gethostip$
  503.                             IF gethostip$ <> CHR$(27) AND LEN(RTRIM$(game.host_ip)) > 0 THEN JoinGame
  504.                         ELSE
  505.                             ResetNetGame
  506.                         END IF
  507.                     CASE 6 'start game
  508.                         IF game.clientid > 0 THEN hrac(game.clientid).isready = 1 - hrac(game.clientid).isready
  509.                         IF (game.isnetgame = 0 OR (game.isnetgame = 1 AND game.hosth <> 0)) AND (stav.AIallowed = 1 OR (stav.AIallowed = 0 AND HumanPlayersCount >= 2)) THEN game.start = 1
  510.                     CASE 7 'exit game
  511.                         game.exituj = 1
  512.                 END SELECT
  513.             CASE 116 'messaage write mode on
  514.                 IF game.isnetgame = 1 THEN
  515.                     game.msgwrite = 1
  516.                     k = 0
  517.                 END IF
  518.             CASE 32 'start game
  519.                 IF game.clientid > 0 THEN hrac(game.clientid).isready = 1 - hrac(game.clientid).isready
  520.                 IF (game.isnetgame = 0 OR (game.isnetgame = 1 AND game.hosth <> 0)) AND (stav.AIallowed = 1 OR (stav.AIallowed = 0 AND HumanPlayersCount >= 2)) THEN game.start = 1
  521.             CASE 27 'exit game
  522.                 game.exituj = 1
  523.         END SELECT
  524.  
  525.         FOR i = 1 TO PLAYER_COUNT_MAX 'set AI controller type for computer players
  526.             IF game.isnetgame = 1 AND game.clienth <> 0 AND game.clientid <> 0 AND klav(hrac(i).klavesy).typ = 4 THEN hrac(i).klavesy = hrac(i).klavesy + 1 'change AI controler on client to keyboard
  527.             IF (game.isnetgame = 0 OR (game.isnetgame = 1 AND game.hosth <> 0)) AND klav(hrac(i).klavesy).typ = 4 THEN 'on host or singleplayer change AI controlled ball
  528.                 bal(hrac(i).bal).complayer = 1
  529.             ELSE
  530.                 bal(hrac(i).bal).complayer = 0
  531.             END IF
  532.         NEXT i
  533.  
  534.         IF game.isnetgame AND stav.pocethracov > PLAYER_NET_MAX THEN stav.pocethracov = PLAYER_NET_MAX
  535.         IF menu.menucode = 4 AND (k = 19712 OR k = 19200) THEN 'after changing players count
  536.             stav.energy_player_start = INT(stav.energy_allmin / stav.pocethracov) 'calculate  players energy
  537.             IF stav.energy_player_start < stav.energy_playermin THEN stav.energy_player_start = stav.energy_playermin
  538.             IF stav.energy_player_start > stav.energy_playermax THEN stav.energy_player_start = stav.energy_playermax
  539.         END IF
  540.  
  541.         IF game.isnetgame = 1 AND game.clienth <> 0 AND game.clientid > 0 AND stav.gameplay = 1 THEN game.start = 1
  542.         IF game.isnetgame = 1 THEN SyncNetGameData
  543.         _DISPLAY
  544.         _LIMIT stav.fps
  545.  
  546.     LOOP UNTIL game.start = 1 OR game.exituj = 1
  547.     game.start = 0
  548.     IF game.clientid > 0 THEN hrac(game.clientid).isready = 0
  549.     '--------end of main menu---------------------------------------------------------------------------------------------------------------------------------------------------------------------
  550.  
  551.     '----------------------------------new game start-------------------------------------------------------------------------------------------------
  552.     WINDOW (0, 0)-(stav.maxx, stav.maxy)
  553.     IF game.exituj <> 1 THEN 'new game starts here
  554.         '----------------------------------set the world on the new game start-------------------------------
  555.         IF game.hosth <> 0 THEN AddMessage "The match has been started by the host. Whoever scores" + RTRIM$(STR$(stav.winscore)) + " times wins.", MSG_COL, MSG_DUR_STD, 1
  556.  
  557.         FOR i = 1 TO PLAYER_NET_MAX
  558.             FOR j = 1 TO PLAYER_NET_MAX
  559.                 stats(i, j) = 0
  560.             NEXT j
  561.         NEXT i
  562.  
  563.         stav.gameplay = 1
  564.         stav.pocetgul = stav.pocetgulzvoleny + stav.pocethracov
  565.         stav.pocetgulx = MATHROUND(SQR(4 / 3 * stav.pocetgul))
  566.         IF stav.pocetgulx < stav.pocethracov THEN stav.pocetgulx = stav.pocethracov
  567.         stav.pocetguly = _CEIL(stav.pocetgul / stav.pocetgulx)
  568.  
  569.         IF stav.pocethracov < 2 THEN stav.pocethracov = 2
  570.         FOR i = 1 TO stav.pocethracov
  571.             hrac(i).skore = 0
  572.         NEXT i
  573.  
  574.         FOR n = 1 TO stav.pocethracov: bal(n).syncstr = GETITEM_PBAL: bal(n).synctime = 0: NEXT n
  575.         FOR n = stav.pocethracov + 1 TO UBOUND(bal): bal(n).syncstr = GETITEM_BAL: bal(n).synctime = 0: NEXT n
  576.  
  577.         stav.zacinabal = hrac(INT(RND * stav.pocethracov + 1)).bal
  578.  
  579.         DO 'new round starts here
  580.             '-------------------------------set the world on the new round start---------------------------
  581.             stav.koniec_kola = 0
  582.             stav.pauza = 0
  583.             stav.vitaz = 0
  584.             game.exituj = 0
  585.             stav.baljeto = 0
  586.  
  587.             IF game.isnetgame = 1 AND game.hosth <> 0 THEN 'engage new spectating players
  588.                 FOR i = 2 TO stav.pocethracov
  589.                     IF client(i).spectating = 1 THEN
  590.                         hrac(i).skore = 0
  591.                         bal(hrac(i).bal).hrac = i
  592.                         bal(hrac(i).bal).complayer = 0
  593.                         bal(hrac(i).bal).riadena = 1
  594.                         client(i).spectating = 0
  595.                         bal(i).vi.x = 0: bal(i).vi.y = 0
  596.                         FOR j = 1 TO PLAYER_NET_MAX
  597.                             stats(i, j) = 0
  598.                             stats(j, i) = 0
  599.                         NEXT j
  600.                     END IF
  601.                 NEXT i
  602.             END IF
  603.  
  604.             RANDOMIZE TIMER
  605.             coloffset = 104 + INT(RND * 10)
  606.             colcoef = (1 + INT(RND * (246 - coloffset))) / stav.pocetgulx
  607.             FOR i = 1 TO stav.pocetguly + 1 'set all balls
  608.                 FOR j = 1 TO stav.pocetgulx
  609.                     n = (i - 1) * stav.pocetgulx + j:
  610.                     IF n <= stav.pocetgul THEN
  611.                         ry = 20 + RND * INT(((stav.maxy - 100) / (stav.pocetguly + 1) - 25) / 2)
  612.                         rx = 10 + RND * INT(((stav.maxx - 100) / (stav.pocetgulx + 1) - 25) / 2)
  613.                         bcol = coloffset + j * colcoef
  614.                         bal(n).i = n
  615.                         bal(n).col = bcol
  616.                         bal(n).x = 100 + j * INT((stav.maxx - 100) / (stav.pocetgulx + 1))
  617.                         bal(n).y = 100 + i * INT((stav.maxy - 100) / (stav.pocetguly + 1))
  618.                         bal(n).r = rx * -(rx < ry) + ry * -(ry < rx)
  619.                         bal(n).m = 4 / 4 * pi * bal(n).r ^ 2
  620.                         bal(n).v.x = -10 / FPS: bal(n).v.y = -30 / FPS
  621.                         bal(n).a.x = ACC_X * stav.maxx / RES_X_TARG
  622.                         bal(n).a.y = ACC_Y * stav.maxx / RES_X_TARG
  623.                         bal(n).vi.x = -(bal(n).complayer = 1) * RND * stav.vmax - stav.vmax / 2
  624.                         bal(n).vi.y = -(bal(n).complayer = 1) * RND * stav.vmax - stav.vmax / 2
  625.                         bal(n).riadena = 0
  626.                         bal(n).energia = stav.energy_player_start
  627.                         bal(n).freezedtime = 0: bal(n).klucka_time = 0: bal(n).klucka_pocet = 0
  628.                         bal(n).klucka_trvanie = 0: bal(n).klucka_uhol = 0
  629.                         bal(n).boost_time = 0: bal(n).boost_trvanie = 0
  630.                         bal(n).synctime = 0
  631.                     END IF
  632.                 NEXT j
  633.             NEXT i
  634.  
  635.             '---set players balls default atributtes--------------------------------------------------------
  636.             FOR i = 1 TO stav.pocethracov
  637.                 hrac(i).bal = i
  638.                 bal(hrac(i).bal).hrac = i
  639.                 bal(hrac(i).bal).riadena = 1
  640.                 IF stav.AIallowed = 0 AND klav(hrac(i).klavesy).typ = 4 THEN
  641.                     bal(hrac(i).bal).energia = 0
  642.                     bal(hrac(i).bal).riadena = 0
  643.                 ELSE
  644.                     bal(hrac(i).bal).r = PLAY_BALL_R * stav.maxx / RES_X_TARG
  645.                     bal(hrac(i).bal).m = 4 / 4 * pi * PLAY_BALL_R ^ 2 / 2 'Players have only half density
  646.                     bal(hrac(i).bal).col = hrac(i).col
  647.                     bal(hrac(i).bal).strat = 3
  648.                 END IF
  649.             NEXT i
  650.  
  651.             '---decide initially tagged player-------------------------------------------------------------
  652.             zacinalNaposledyBal = stav.zacinabal
  653.             stav.balbudeto = stav.zacinabal
  654.             DO
  655.                 stav.zacinabal = stav.zacinabal + 1
  656.                 IF stav.zacinabal > stav.pocetgulx THEN stav.zacinabal = 1
  657.             LOOP UNTIL bal(stav.zacinabal).riadena = 1
  658.             stav.baljeto = stav.zacinabal
  659.  
  660.             FOR b = 1 TO stav.pocethracov
  661.                 bal(hrac(b).bal).protivnik = stav.baljeto * -(hrac(b).bal <> stav.baljeto)
  662.             NEXT b
  663.             bal(stav.zacinabal).protivnik = zacinalNaposledyBal
  664.  
  665.             '----------------------------------game action loop--------------------------------------------
  666.             DO
  667.                 game.tstart = TIMER(.001)
  668.                 _LIMIT stav.fps
  669.                 CLS 1
  670.                 k = _KEYHIT
  671.                 IF k = 116 AND game.clientid > 0 AND game.msgwrite = 0 THEN game.msgwrite = 1: k = 0 'message writing mode
  672.                 IF game.msgwrite = 1 THEN WriteMessage k: k = 0
  673.                 IF NOT (game.isnetgame = 1 AND game.clienth <> 0) AND (k = 112 OR k = 102) THEN stav.pauza = 1 - stav.pauza
  674.  
  675.                 DrawScore 'Draw players score on screen
  676.                 DisplayMessages 'Draw messages
  677.  
  678.                 '---debug code begin---------------------------------------------
  679.                 IF k = 98 THEN game.printdebug = -(game.printdebug = 0)
  680.                 IF game.printdebug = 1 THEN DebugScreen k 'display debug info on screen
  681.                 '---debug code end-----------------------------------------------
  682.  
  683.                 IF k = 99 THEN game.show_stats = -(game.show_stats = 0)
  684.                 IF game.show_stats = 1 THEN DisplayStatistics 'display match statistics
  685.  
  686.                 IF stav.pauza = 0 THEN
  687.                     FOR i = 1 TO stav.pocethracov
  688.                         ResolvePlayerControl bal(hrac(i).bal), klav(hrac(i).klavesy) 'resolve players control
  689.                         IF bal(hrac(i).bal).riadena = 1 THEN
  690.                             CalculatePlayerState bal(hrac(i).bal) 'calculate player status
  691.                         END IF
  692.                     NEXT i
  693.  
  694.                     FOR n = 1 TO stav.pocetgul
  695.                         PerformMovement bal(n) 'do ball movement
  696.                     NEXT n
  697.  
  698.                     FOR i = 1 TO stav.pocetgul
  699.                         FOR j = i + 1 TO stav.pocetgul
  700.                             BounceTest bal(i), bal(j) 'Test balls bounce
  701.                         NEXT j
  702.                     NEXT i
  703.                 ELSE
  704.                     PauseGame
  705.                 END IF
  706.  
  707.                 IF game.isnetgame = 1 THEN SyncNetGameData
  708.  
  709.                 FOR n = 1 TO stav.pocetgul
  710.                     DrawBall bal(n) 'draw ball
  711.                 NEXT n
  712.  
  713.                 IF stav.vitaz <> 0 THEN DrawWinScreen
  714.  
  715.                 IF NOT (game.isnetgame = 1 AND game.clienth <> 0) AND (k = 102) THEN stav.pauza = 1
  716.                 IF k = 27 AND game.isnetgame = 1 THEN AddMessage "To quit network game press 't' and type '/q'", MSG_COL, MSG_DUR_STD, 0: k = 0
  717.                 IF k = 27 AND game.isnetgame = 0 THEN stav.koniec_kola = 2
  718.  
  719.                 _DISPLAY 'Turn video page over
  720.                 game.tend = TIMER(.001)
  721.                 CalculateFps
  722.             LOOP UNTIL stav.koniec_kola >= 1
  723.             '---------------------------end of game action loop---------------------------------------------
  724.  
  725.             IF stav.vitaz <> 0 THEN k = 0
  726.             anyHumanPlayer = HumanPlayersCount
  727.             resumegame = 0
  728.             DO 'wait for resume if not net game
  729.                 _LIMIT stav.fps
  730.                 IF k = 27 AND game.hosth = 0 THEN stav.koniec_kola = 2
  731.                 FOR i = 1 TO stav.pocethracov
  732.                     IF klav(hrac(i).klavesy).typ = 3 THEN ReadGamepad klav(hrac(i).klavesy)
  733.                     IF klav(hrac(i).klavesy).isshoota THEN resumegame = 1
  734.                     IF klav(hrac(i).klavesy).isshootb THEN stav.koniec_kola = 2
  735.                     IF klav(hrac(i).klavesy).typ = 1 THEN IF _KEYDOWN(klav(hrac(i).klavesy).shoota) THEN resumegame = 1
  736.                 NEXT i
  737.                 k = _KEYHIT
  738.             LOOP UNTIL (resumegame = 1) OR (anyHumanPlayer = 0) OR (stav.koniec_kola = 2) OR (game.isnetgame = 1)
  739.             '---------------------------end of round-----------------------------------------------------------
  740.         LOOP UNTIL stav.koniec_kola = 2 OR (stav.AIallowed = 0 AND anyHumanPlayer < 2)
  741.         IF (stav.AIallowed = 0 AND anyHumanPlayer < 2) THEN AddMessage "Match was ended for less than 2 players left", MSG_COL, MSG_DUR_STD, 0
  742.     END IF
  743.     '---------------------------end of game------------------------------------------------------------
  744.     game.autostart_time = TIMER + stav.autostart_set
  745. LOOP UNTIL game.exituj = 1
  746. CLS 1
  747. '---------------------------end of program------------------------------------------------------------
  748.  
  749. '////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  750. '----------------------------------------------------------------------------------------------------------------------------------------------------
  751. SUB DrawWinScreen
  752.     DIM statstab(1 TO PLAYER_NET_MAX) AS STRING
  753.     IF stav.vitaz > 0 THEN
  754.         IF hrac(stav.vitaz).skore >= stav.winscore THEN windelay = DELAY_MATCHEND ELSE windelay = DELAY_ROUNDSTART
  755.         IF game.autostart_time - windelay > TIMER THEN game.autostart_time = game.autostart_time - 86399
  756.         IF (game.autostart_time <= TIMER) AND (game.isnetgame = 0 OR game.hosth <> 0) THEN
  757.             stav.koniec_kola = 1 'end of round
  758.             IF hrac(stav.vitaz).skore >= stav.winscore THEN stav.koniec_kola = 2 'end of match either
  759.         END IF
  760.         IF (game.isnetgame = 0 OR game.hosth <> 0) THEN stav.autostart_timeleft = game.autostart_time - TIMER
  761.         IF INT(stav.autostart_timeleft) >= 0 THEN timeleft$ = "  (" + LTRIM$(STR$(INT(stav.autostart_timeleft))) + ")" ELSE timeleft$ = ""
  762.         IF hrac(stav.vitaz).skore < stav.winscore THEN
  763.             winstr1$ = "....and the winner of this round is... " + RTRIM$(hrac(stav.vitaz).meno) + timeleft$
  764.             winstr2$ = "Press <fire> for the next round"
  765.         ELSE
  766.             winstr1$ = "...>>> " + RTRIM$(hrac(stav.vitaz).meno) + " <<<.... scores " + LTRIM$(STR$(stav.winscore)) + " and becomes the MATCH WINNER!" + timeleft$
  767.             winstr2$ = "Press <fire> to return to the menu"
  768.             DisplayStatistics
  769.         END IF
  770.         COLOR bal(hrac(stav.vitaz).bal).col
  771.         _PRINTSTRING ((game.maxx - LEN(winstr1$) * 10) / 2, (game.maxy - 50) / 2), winstr1$
  772.         IF stav.koniec_kola > 0 THEN _PRINTSTRING ((game.maxx - LEN(winstr2$) * 10) / 2, (game.maxy - 50) / 2 + 50), winstr2$
  773.     END IF
  774.  
  775. '----------------------------------------------------------------------------------------------------------------------------------------------------
  776. SUB DisplayStatistics
  777.     IF stav.pocethracov <= PLAYER_NET_MAX THEN playercount = stav.pocethracov ELSE playercount = PLAYER_NET_MAX
  778.     row = INT((game.maxy - (playercount + 4) * _FONTHEIGHT) / _FONTHEIGHT)
  779.     col = INT((game.maxx - ((playercount + 2) * 11 * _FONTWIDTH)) / 2 / _FONTWIDTH)
  780.     IF row < 1 THEN row = 1
  781.     IF col < 1 THEN col = 1
  782.     COLOR MSG_COL
  783.     LOCATE row, col
  784.     PRINT "Match statistics - tags given by player"
  785.     LOCATE row + 1, col
  786.     PRINT STRING$((playercount + 2) * 11, "-"),
  787.     LOCATE row + 2, col
  788.     PRINT "Player"
  789.     FOR i = 1 TO playercount
  790.         COLOR hrac(i).col
  791.         LOCATE row + 2, col + i * 11
  792.         PRINT RTRIM$(hrac(i).meno)
  793.     NEXT i
  794.     COLOR MSG_COL
  795.     LOCATE row + 2, col + i * 11
  796.     PRINT "Tags given"
  797.     FOR i = 1 TO playercount
  798.         tagsum = 0
  799.         LOCATE row + 2 + i, col
  800.         COLOR hrac(i).col
  801.         PRINT RTRIM$(hrac(i).meno)
  802.         FOR j = 1 TO playercount
  803.             LOCATE row + 2 + i, col + j * 11
  804.             IF stats(i, j) > 0 THEN PRINT STR$(stats(i, j))
  805.             tagsum = tagsum + stats(i, j)
  806.         NEXT j
  807.         LOCATE row + 2 + i, col + j * 11
  808.         PRINT STR$(tagsum)
  809.     NEXT i
  810.  
  811. '----------------------------------------------------------------------------------------------------------------------------------------------------
  812. FUNCTION HumanPlayersCount 'set pre-game parameters
  813.     HumanPlayersCount = 0
  814.     FOR i = 1 TO stav.pocethracov
  815.         IF bal(hrac(i).bal).complayer = 0 THEN HumanPlayersCount = HumanPlayersCount + 1
  816.     NEXT i
  817.  
  818. '----------------------------------------------------------------------------------------------------------------------------------------------------
  819. SUB SetGlobalParameters 'set pre-game parameters
  820.     '-------------------------------set game session parameters----------------------------------------------------------------------------------------
  821.     game.fpsactual = FPS
  822.     game.isnetgame = 0
  823.     game.clienth = 0
  824.     game.clientid = 0
  825.     game.hosth = 0
  826.     game.host_port = HOSTPORT_DEFAULT
  827.     game.host_ip = HOSTIP_DEFAULT
  828.     game.printdebug = DEBUGMODE
  829.     game.exituj = 0
  830.     game.start = 0
  831.     game.newmsg = 0
  832.     IF RES_X = -1 THEN game.maxx = _DESKTOPWIDTH ELSE game.maxx = RES_X
  833.     IF RES_Y = -1 THEN game.maxy = _DESKTOPHEIGHT ELSE game.maxy = RES_Y
  834.     game.msgcount = 0
  835.     game.msgwrite = 0
  836.     game.msgtext = ""
  837.     game.show_stats = 0
  838.     sync.syncstr = GETITEM_SYNC
  839.     sync.synctime = 0
  840.  
  841.     '-------------------------------set game world parameters----------------------------------------------------------------------------------------
  842.     pi = _PI
  843.     stav.syncstr = GETITEM_STAV
  844.     stav.synctime = 0
  845.     stav.pauza = 0
  846.     stav.gameplay = 0
  847.     stav.fps = FPS
  848.     stav.pocethracov = PLAYER_COUNT_INI
  849.     stav.pocetgulzvoleny = POCET_GUL_INI
  850.     stav.pocetgul = POCET_GUL_INI
  851.     stav.energy_allmin = ENERGY_ALL_MIN
  852.     stav.energy_playermin = ENERGY_PLAYER_MIN
  853.     stav.energy_playermax = ENERGY_PLAYER_MAX
  854.     stav.energydec = ENERGY_DEC
  855.     stav.odpor = FRICTION
  856.     stav.minx = 0
  857.     stav.miny = 0
  858.     stav.maxx = RES_X_TARG
  859.     stav.maxy = RES_Y_TARG
  860.     stav.vmax = V_MAX * stav.maxx / RES_X_TARG
  861.     stav.maxcol = MAX_COL
  862.     stav.boostallowed = 1
  863.     stav.massallowed = 0 'sticky balls problem if mass allowed unsolved yet
  864.     stav.autostart_set = 0
  865.     game.autostart_time = 0
  866.     stav.AIallowed = 1
  867.     stav.winscore = 3
  868.     stav.energy_player_start = (stav.energy_allmin / stav.pocethracov) 'calculate  players energy
  869.     IF stav.energy_player_start < stav.energy_playermin THEN stav.energy_player_start = stav.energy_playermin
  870.     IF stav.energy_player_start > stav.energy_playermax THEN stav.energy_player_start = stav.energy_playermax
  871.  
  872.     stats(PLAYER_NET_MAX + 1, 1) = ASC(GETITEM_STAT, 1)
  873.     stats(PLAYER_NET_MAX + 1, 2) = ASC(GETITEM_STAT, 2)
  874.     stats(PLAYER_NET_MAX + 1, 3) = ASC(GETITEM_STAT, 3)
  875.  
  876.     '-------------------------------set game controllers---------------------------------------------------------------------------------------------
  877.     FOR i = 1 TO UBOUND(klav) 'set all the other game controllers as unused, few reserved for net players
  878.         IF i <= PLAYER_NET_MAX THEN
  879.             klav(i).typ = 5
  880.             klav(i).nazov = "NetControl" + LTRIM$(STR$(i))
  881.         ELSE
  882.             klav(i).typ = 0
  883.         END IF
  884.         klav(i).devid = 0
  885.         klav(i).syncstr = GETITEM_KLAV
  886.         klav(i).synctime = 0
  887.     NEXT i
  888.  
  889.     'set default controllers
  890.     kid = PLAYER_NET_MAX + 1 'CPU void controller
  891.     klav(kid).id = kid: klav(kid).devid = 1: klav(kid).nazov = "<CPU>": klav(kid).typ = 4
  892.  
  893.     kid = PLAYER_NET_MAX + 2 'keyboard set 1 controller
  894.     klav(kid).id = kid: klav(kid).devid = 1: klav(kid).nazov = "<Arrow keys + LShift>": klav(kid).typ = 1
  895.     klav(kid).up = 18432: klav(kid).down = 20480: klav(kid).left = 19200: klav(kid).right = 19712
  896.     klav(kid).shoota = 100304: klav(kid).shootb = 100306
  897.  
  898.     kid = PLAYER_NET_MAX + 3 'keyboard set 2 controller
  899.     klav(kid).id = kid: klav(kid).devid = 1: klav(kid).nazov = "<W,A,S,D + RShift>": klav(kid).typ = 1
  900.     klav(kid).up = 119: klav(kid).down = 115: klav(kid).left = 97: klav(kid).right = 100
  901.     klav(kid).shoota = 100303: klav(kid).shootb = 100305
  902.  
  903.     kid = PLAYER_NET_MAX + 4 'keyboard set 3 controller
  904.     klav(kid).id = kid: klav(kid).devid = 1: klav(kid).nazov = "<I,J,K,L + Enter>": klav(kid).typ = 1
  905.     klav(kid).up = 105: klav(kid).down = 107: klav(kid).left = 106: klav(kid).right = 108
  906.     klav(kid).shoota = 13: klav(kid).shootb = 21248
  907.  
  908.     '-------------------------------set players------------------------------------------------------------------------------------------------------
  909.     FOR i = 1 TO UBOUND(hrac) 'initial setting for all players
  910.         hrac(i).bal = i
  911.         hrac(i).meno = "Player" + LTRIM$(STR$(i))
  912.         hrac(i).skore = 0
  913.         hrac(i).klavesy = CPU_CONTROLID
  914.         hrac(i).col = 32 + i * 3
  915.         hrac(i).clientid = 0
  916.         bal(hrac(i).bal).complayer = 1
  917.         hrac(i).syncstr = GETITEM_HRAC
  918.         hrac(i).synctime = 0
  919.     NEXT i
  920.  
  921.     'personalize some players initially
  922.     bal(hrac(1).bal).complayer = 0
  923.     hrac(1).klavesy = PLAYER_NET_MAX + 2
  924.     hrac(1).meno = "Chuck"
  925.     hrac(2).meno = "Arnold"
  926.     hrac(3).meno = "Jean"
  927.     hrac(4).meno = "Bruce"
  928.     hrac(5).meno = "Dolph"
  929.     hrac(6).meno = "Sylvester"
  930.     hrac(7).meno = "Jet"
  931.     hrac(8).meno = "Dwayne"
  932.  
  933.     '-------------------------------set behaviour strategies------------------------------------------------------------------------------------------
  934.     'some void strategy
  935.     strat(1).okraj = PRIESTOR_MIN:
  936.     strat(1).okraj_rot = 0.1
  937.     strat(1).chybasmeru = 0.00:
  938.     strat(1).klucka_avgtm = 1 * FPS: strat(1).klucka_pocet = 5
  939.     strat(1).klucka_trvanie = 0.25 * FPS: strat(1).klucka_uhol = pi / 2: strat(1).klucka_uholodch = 0.2
  940.     strat(1).detekcia_sin = SIN(pi / 4): strat(1).detekcia_vzdfull = 500: strat(1).detekcia_vzdmin = 1000: strat(1).detekcia_rot = 0.5
  941.     strat(1).boost_dist = 200
  942.     strat(1).boost_chasesin = SIN(pi / 8)
  943.     strat(1).mate_cosenmax = -0.8 'cos(140/180*pi)
  944.     strat(1).mate_rot = 0.1 ' 3*pi /FPS
  945.     strat(1).mate_en_distmin = 5 * PLAY_BALL_R
  946.     strat(1).mate_distmin = 4 * PLAY_BALL_R
  947.  
  948.     'non dodging strategy
  949.     strat(2).okraj = PRIESTOR_MIN + 10
  950.     strat(2).okraj_rot = 0.1
  951.     strat(2).chybasmeru = 0.00
  952.     strat(2).reactdrop_per = 0 * FPS
  953.     strat(2).reactdrop_dur = 0 * FPS
  954.     strat(2).klucka_avgtm = 10 * FPS
  955.     strat(2).klucka_pocet = 0
  956.     strat(2).klucka_trvanie = 0 * FPS
  957.     strat(2).klucka_uhol = 0 * pi / 3
  958.     strat(2).klucka_uholodch = 0.2
  959.     strat(2).detekcia_sin = SIN(pi / 6)
  960.     strat(2).detekcia_vzdfull = 500
  961.     strat(2).detekcia_vzdmin = 1000
  962.     strat(2).detekcia_rot = 0.5
  963.     strat(2).boost_dist = 200
  964.     strat(2).boost_chasesin = SIN(pi / 8)
  965.     strat(2).mate_cosenmax = -0.8 'cos(140/180*pi)
  966.     strat(2).mate_rot = 0.1 ' 3*pi /FPS
  967.     strat(2).mate_en_distmin = 5 * PLAY_BALL_R
  968.     strat(2).mate_distmin = 4 * PLAY_BALL_R
  969.  
  970.     'dodging strategy - currently used for all AI players
  971.     strat(3).okraj = PRIESTOR_MIN + 10
  972.     strat(3).okraj_rot = 0.1
  973.     strat(3).chybasmeru = 0.30
  974.     strat(3).reactdrop_per = 0.8 * FPS
  975.     strat(3).reactdrop_dur = 0.4 * FPS
  976.     strat(3).klucka_avgtm = 5 * FPS
  977.     strat(3).klucka_pocet = 3
  978.     strat(3).klucka_trvanie = 2 * FPS
  979.     strat(3).klucka_uhol = pi * 2 / 3
  980.     strat(3).klucka_uholodch = 0.2
  981.     strat(3).detekcia_sin = SIN(pi / 6)
  982.     strat(3).detekcia_vzdfull = 300
  983.     strat(3).detekcia_vzdmin = 1500
  984.     strat(3).detekcia_rot = 0.5 '10 * pi / FPS
  985.     strat(3).boost_dist = 200
  986.     strat(3).boost_chasesin = SIN(pi / 8)
  987.     strat(3).mate_cosenmax = -0.8 'cos(140/180*pi)
  988.     strat(3).mate_rot = 0.1 ' 3*pi /FPS
  989.     strat(3).mate_en_distmin = 8 * PLAY_BALL_R
  990.     strat(3).mate_distmin = 4 * PLAY_BALL_R
  991.     strat(3).adrenalin_rate = 0.90
  992.     strat(3).adrenalin_energy = 0.30
  993.  
  994.     '-------------------------------set main menu-----------------------------------------------------------------------------------------------------
  995.     menu.item_active = 1
  996.     menu.items_count = 22
  997.     menu.cursor_col = 15
  998.     menu.cursor_width = 400
  999.     menu.item_height = FONT_H + 4
  1000.     menu.cursor_xpos = INT((game.maxx - menu.cursor_width) / 2)
  1001.     menu.ypos = INT((game.maxy - menu.items_count * menu.item_height) / 2)
  1002.     menu.cursor_out = 5
  1003.     '-------------------------------set balls---------------------------------------------------------------------------------------------------------
  1004.     FOR n = 1 TO stav.pocethracov: bal(n).syncstr = GETITEM_PBAL: bal(n).synctime = 0: NEXT n
  1005.     FOR n = stav.pocethracov + 1 TO UBOUND(bal): bal(n).syncstr = GETITEM_BAL: bal(n).synctime = 0: NEXT n
  1006.  
  1007. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1008. SUB WriteMessage (k AS INTEGER)
  1009.     DIM tmptext AS STRING
  1010.     IF game.clientid > 0 THEN
  1011.         msginput_x = 10
  1012.         msginput_y = RES_Y - 20
  1013.  
  1014.         tmptext = LEFT$(game.msgtext, LEN(RTRIM$(game.msgtext)) - 1)
  1015.         IF k >= 32 AND k <= 126 AND LEN(tmptext) < MSG_LEN_MAX THEN tmptext = tmptext + CHR$(k)
  1016.         IF k = 8 AND LEN(tmptext) > 0 THEN tmptext = LEFT$(tmptext, LEN(tmptext) - 1)
  1017.         IF k = 27 THEN game.msgwrite = 0
  1018.  
  1019.         COLOR MSG_COL
  1020.         _PRINTSTRING (msginput_x, msginput_y), "Type message>>  " + tmptext
  1021.         IF k = -1 AND game.msgwrite = 0 THEN _PRINTSTRING (msginput_x, msginput_y), "Press 't' to writte text message to other players" + tmptext
  1022.  
  1023.  
  1024.         IF k = 13 THEN
  1025.             IF LEFT$(tmptext, 1) = "/" THEN
  1026.                 AddMessage tmptext, MSG_COL, MSG_DUR_STD, 0
  1027.             ELSE
  1028.                 AddMessage RTRIM$(hrac(game.clientid).meno) + "> " + tmptext, hrac(game.clientid).col, MSG_DUR_STD, 1
  1029.             END IF
  1030.             game.msgtext = CHR$(92)
  1031.             game.msgwrite = 0
  1032.         ELSE
  1033.             game.msgtext = tmptext + CHR$(92)
  1034.         END IF
  1035.     END IF
  1036.  
  1037. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1038. SUB SetUpControllers 'detect gamepads and set them as game controllers
  1039.     DIM klav_volne AS INTEGER, devices AS INTEGER
  1040.     DIM dev AS STRING
  1041.  
  1042.     FOR i = 1 TO UBOUND(klav) 'dispose all gamepad constrollers
  1043.         IF klav(i).typ = 3 THEN
  1044.             klav(i).typ = 0
  1045.             klav(i).devid = 0
  1046.         END IF
  1047.     NEXT i
  1048.     klav_volne = 1
  1049.     game.pocetgamepadov = 0
  1050.     DO
  1051.         klav_volne = klav_volne + 1
  1052.     LOOP UNTIL klav(klav_volne).typ = 0 OR klav_volne = UBOUND(klav)
  1053.     klav_used = klav_volne - 1
  1054.     devices = _DEVICES 'must be read prior to other device functions usage
  1055.     FOR i = 1 TO devices
  1056.         dev = _DEVICE$(i)
  1057.         IF INSTR(dev, "[CONTROLLER]") > 0 AND INSTR(dev, "[AXIS]") > 0 AND klav_volne <= UBOUND(klav) THEN 'set new controller if gamepad
  1058.             klav(klav_volne).id = klav_volne
  1059.             klav(klav_volne).devid = i
  1060.             klav(klav_volne).typ = 3
  1061.             klav(klav_volne).nazov = "<Gamepad" + LTRIM$(STR$(klav_volne - klav_used)) + ">"
  1062.             klav(klav_volne).xaxis = 1
  1063.             klav(klav_volne).yaxis = 2
  1064.             klav(klav_volne).dxaxis = _LASTAXIS(i) - 1
  1065.             klav(klav_volne).dyaxis = _LASTAXIS(i)
  1066.             klav(klav_volne).shoota = 1
  1067.             klav(klav_volne).shootb = 8
  1068.             klav_volne = klav_volne + 1
  1069.             game.pocetgamepadov = game.pocetgamepadov + 1
  1070.         END IF
  1071.     NEXT i
  1072.     game.pocetkontrolerov = klav_volne - 1
  1073.  
  1074. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1075. SUB MainMenuScreen 'perform choises in main menu
  1076.  
  1077. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1078. SUB SyncNetGameData
  1079.     DIM i AS INTEGER, isync AS tsyncvar, clklav AS tklavesy, clhrac AS thrac, imsg AS tmessage
  1080.     DIM sync_stav AS INTEGER, sync_pbal AS INTEGER, sync_bal AS INTEGER, sync_hrac AS INTEGER
  1081.     IF game.isnetgame = 1 THEN
  1082.         '--------------------------host side---------------------------------------------------------------------------------------------------------
  1083.         IF game.hosth <> 0 THEN 'sync host data
  1084.             FOR i = PLAYER_NET_MIN TO PLAYER_NET_MAX 'for each client try to connect
  1085.                 IF client(i).conn = 0 AND i <= stav.pocethracov THEN
  1086.                     client(i).conn = _OPENCONNECTION(game.hosth) 'try to open connection if not open
  1087.                     client(i).get_item = GETITEM_SYNC
  1088.                     client(i).get_isdesync = 0
  1089.                     client(i).get_time = TIMER(.001)
  1090.                     IF client(i).conn <> 0 THEN 'if connection opened
  1091.                         client(i).ip = _CONNECTIONADDRESS(client(i).conn)
  1092.                         PLAY "MBL64O2CEG>C"
  1093.                         IF stav.gameplay = 1 THEN
  1094.                             client(i).spectating = 1
  1095.                             game.sync_stats = 1
  1096.                             msgtext$ = " joins the game from the next round"
  1097.                         ELSE
  1098.                             client(i).spectating = 0
  1099.                             msgtext$ = " has joined the game"
  1100.                         END IF
  1101.                         AddMessage "Player " + RTRIM$(hrac(i).meno) + msgtext$, MSG_COL, MSG_DUR_STD, 1
  1102.                     END IF
  1103.                 END IF
  1104.                 IF (TIMER(.001) - client(i).get_time) > NET_TIMEOUT_LIMIT AND client(i).conn <> 0 THEN CloseClientConn (i)
  1105.             NEXT i
  1106.             FOR i = PLAYER_NET_MIN TO PLAYER_NET_MAX 'sync data with each client
  1107.                 sync.clientid = i
  1108.                 IF client(i).conn <> 0 THEN
  1109.                     DO
  1110.                         IF client(i).get_isdesync = 1 THEN 'flush acquired data if desynced
  1111.                             GET #client(i).conn, , flush$
  1112.                             client(i).get_isdesync = 0
  1113.                             client(i).get_item = GETITEM_SYNC
  1114.                         END IF
  1115.  
  1116.                         IF client(i).get_item = GETITEM_SYNC THEN 'first get sync info on what item to get next
  1117.                             GET #client(i).conn, , isync
  1118.                             IF NOT EOF(client(i).conn) THEN
  1119.                                 IF isync.syncstr = GETITEM_SYNC THEN
  1120.                                     client(i).get_item = isync.itemstr
  1121.                                     client(i).get_time = TIMER(.001)
  1122.                                     client(i).isdesynced = isync.isdesync
  1123.                                 ELSE
  1124.                                     client(i).get_isdesync = 1
  1125.                                 END IF
  1126.                             END IF
  1127.                         END IF
  1128.  
  1129.                         IF client(i).get_item = GETITEM_KLAV THEN 'get controller state from client
  1130.                             GET #client(i).conn, , clklav
  1131.                             IF NOT EOF(client(i).conn) THEN
  1132.                                 IF clklav.syncstr = GETITEM_KLAV THEN
  1133.                                     klav(hrac(i).klavesy).isup = clklav.isup
  1134.                                     klav(hrac(i).klavesy).isdown = clklav.isdown
  1135.                                     klav(hrac(i).klavesy).isright = clklav.isright
  1136.                                     klav(hrac(i).klavesy).isleft = clklav.isleft
  1137.                                     klav(hrac(i).klavesy).isshoota = clklav.isshoota
  1138.                                     klav(hrac(i).klavesy).isshootb = clklav.isshootb
  1139.                                     klav(hrac(i).klavesy).gvektor = clklav.gvektor
  1140.                                     client(i).get_time = TIMER(.001)
  1141.                                 ELSE
  1142.                                     client(i).get_isdesync = 1
  1143.                                 END IF
  1144.                                 client(i).get_item = GETITEM_SYNC
  1145.                             END IF
  1146.                         END IF
  1147.  
  1148.                         IF client(i).get_item = GETITEM_HRAC THEN 'get client's player
  1149.                             GET #client(i).conn, , clhrac
  1150.                             IF NOT EOF(client(i).conn) THEN
  1151.                                 IF clhrac.syncstr = GETITEM_HRAC THEN
  1152.                                     clhrac.skore = hrac(i).skore 'keep players socre
  1153.                                     hrac(i) = clhrac 'get player data from client
  1154.                                     hrac(i).klavesy = i 'set player net controlled
  1155.                                     hrac(i).clientid = i 'set player's clientid
  1156.                                     client(i).get_time = TIMER(.001)
  1157.                                 ELSE
  1158.                                     client(i).get_isdesync = 1
  1159.                                 END IF
  1160.                                 client(i).get_item = GETITEM_SYNC
  1161.                             END IF
  1162.                         END IF
  1163.  
  1164.                         IF client(i).get_item = GETITEM_MESG THEN 'get message from client
  1165.                             GET #client(i).conn, , imsg
  1166.                             IF NOT EOF(client(i).conn) THEN
  1167.                                 IF imsg.syncstr = GETITEM_MESG THEN
  1168.                                     AddMessage imsg.text, imsg.col, imsg.time_dur, 1
  1169.                                     msg(game.msgcount).clientid = imsg.clientid
  1170.                                     client(i).get_time = TIMER(.001)
  1171.                                 ELSE
  1172.                                     client(i).get_isdesync = 1
  1173.                                 END IF
  1174.                                 client(i).get_item = GETITEM_SYNC
  1175.                             END IF
  1176.                         END IF
  1177.  
  1178.                     LOOP UNTIL EOF(client(i).conn)
  1179.                 END IF
  1180.             NEXT i
  1181.  
  1182.             IF TIMER(.001) - stav.synctime > UPDATE_PER_STAV THEN 'check if update time
  1183.                 sync_stav = 1
  1184.             ELSE sync_stav = 0
  1185.             END IF
  1186.             IF TIMER(.001) - bal(1).synctime > UPDATE_PER_PLBAL THEN
  1187.                 FOR j = 1 TO stav.pocethracov: ipbal(j) = bal(j): NEXT j 'fill transfer array
  1188.                 sync_pbal = 1
  1189.             ELSE sync_pbal = 0
  1190.             END IF
  1191.             IF TIMER(.001) - bal(stav.pocethracov + 1).synctime > UPDATE_PER_BAL THEN
  1192.                 FOR j = 1 TO stav.pocetgulzvoleny: ibal(j) = bal(j + stav.pocethracov): NEXT j 'fill transfer array
  1193.                 sync_bal = 1
  1194.             ELSE sync_bal = 0
  1195.             END IF
  1196.             IF TIMER(.001) - hrac(1).synctime > UPDATE_PER_HRAC THEN
  1197.                 sync_hrac = 1
  1198.             ELSE sync_hrac = 0
  1199.             END IF
  1200.  
  1201.             FOR i = PLAYER_NET_MIN TO PLAYER_NET_MAX 'send host data to each client
  1202.                 IF client(i).conn <> 0 THEN
  1203.                     sync.clientid = i
  1204.  
  1205.                     IF client(i).isdesynced = 1 THEN 'send sync var if client desynced
  1206.                         sync.synctime = TIMER(.001)
  1207.                         sync.itemstr = GETITEM_SYNC
  1208.                         PUT #client(i).conn, , sync
  1209.                         'PRINT "Resyncing client "; i 'TEMP DEBUG line
  1210.                     END IF
  1211.  
  1212.                     IF sync_stav = 1 AND client(i).isdesynced = 0 THEN 'send world state
  1213.                         sync.synctime = TIMER(.001)
  1214.                         sync.itemstr = GETITEM_STAV
  1215.                         PUT #client(i).conn, , sync
  1216.                         stav.synctime = TIMER(.001)
  1217.                         PUT #client(i).conn, , stav
  1218.                     END IF
  1219.  
  1220.                     IF sync_pbal = 1 AND client(i).isdesynced = 0 THEN 'send player balls
  1221.                         sync.synctime = TIMER(.001):
  1222.                         sync.itemstr = GETITEM_PBAL
  1223.                         PUT #client(i).conn, , sync
  1224.                         bal(1).synctime = TIMER(.001)
  1225.                         PUT #client(i).conn, , ipbal()
  1226.                     END IF
  1227.  
  1228.                     IF sync_bal = 1 AND client(i).isdesynced = 0 THEN 'send nonplayer balls
  1229.                         sync.synctime = TIMER(.001)
  1230.                         sync.itemstr = GETITEM_BAL
  1231.                         bal(stav.pocethracov + 1).synctime = TIMER(.001)
  1232.                         PUT #client(i).conn, , sync
  1233.                         PUT #client(i).conn, , ibal()
  1234.                     END IF
  1235.  
  1236.                     IF sync_hrac = 1 AND client(i).isdesynced = 0 THEN 'IF stav.gameplay = 0 OR stav.vitaz <> 0 THEN 'send players
  1237.                         FOR j = 1 TO PLAYER_NET_MAX: ihrac(j) = hrac(j): NEXT j 'fill transfer array
  1238.                         sync.itemstr = GETITEM_HRAC
  1239.                         sync.synctime = TIMER(.001)
  1240.                         PUT #client(i).conn, , sync
  1241.                         hrac(1).synctime = TIMER(.001)
  1242.                         PUT #client(i).conn, , ihrac()
  1243.                     END IF
  1244.  
  1245.                     IF game.sync_stats = 1 AND client(i).isdesynced = 0 THEN 'send match statistics
  1246.                         sync.itemstr = GETITEM_STAT
  1247.                         sync.synctime = TIMER(.001)
  1248.                         PUT #client(i).conn, , sync
  1249.                         PUT #client(i).conn, , stats()
  1250.                     END IF
  1251.  
  1252.                     IF game.newmsg = 1 AND client(i).isdesynced = 0 THEN 'send new messages
  1253.                         FOR j = 1 TO game.msgcount
  1254.                             IF msg(j).distribute = 1 AND msg(j).clientid <> i THEN
  1255.                                 sync.itemstr = GETITEM_MESG:
  1256.                                 sync.synctime = TIMER(.001):
  1257.                                 PUT #client(i).conn, , sync
  1258.                                 msg(j).synctime = TIMER(.001):
  1259.                                 PUT #client(i).conn, , msg(j)
  1260.                             END IF
  1261.                         NEXT j
  1262.                     END IF
  1263.  
  1264.                 END IF
  1265.             NEXT i
  1266.             game.sync_stats = 0 'clear send statistics flag
  1267.             game.newmsg = 0 'clear messages distributed flags
  1268.             FOR j = 1 TO game.msgcount
  1269.                 msg(j).distribute = 0
  1270.             NEXT j
  1271.         END IF
  1272.  
  1273.         '-------------------client side-------------------------------------------------------------------------------
  1274.         IF game.clienth <> 0 THEN 'client getting data from host
  1275.             DO
  1276.                 IF game.get_isdesync = 1 THEN 'flush acquired data if desynced
  1277.                     'PRINT "Resyncing... "; game.get_item 'TEMP debug line
  1278.                     DO
  1279.                         GET #game.clienth, , isync
  1280.                     LOOP UNTIL (NOT EOF(game.clienth) AND isync.syncstr = GETITEM_SYNC) OR (TIMER(.001) - game.get_time) > NET_TIMEOUT_SYNC
  1281.  
  1282.                     'GET #game.clienth, , flush$
  1283.  
  1284.                     IF NOT EOF(game.clienth) AND isync.syncstr = GETITEM_SYNC THEN
  1285.                         'PRINT "==================RESYNCED================ "; game.get_item; "-"; isync.itemstr 'TEMP debug line
  1286.                         game.get_item = isync.itemstr
  1287.                         game.get_isdesync = 0
  1288.                     ELSE
  1289.                         'PRINT "Desynced!!!!!!!!!!!!! "; game.get_item 'TEMP debug line
  1290.                     END IF
  1291.                 END IF
  1292.  
  1293.                 IF game.get_item = GETITEM_SYNC THEN 'first get sync info on what item to get next
  1294.                     GET #game.clienth, , isync
  1295.                     IF NOT EOF(game.clienth) THEN
  1296.                         IF isync.syncstr = GETITEM_SYNC THEN
  1297.                             game.clientid = isync.clientid
  1298.                             game.get_item = isync.itemstr
  1299.                             game.get_time = TIMER(.001)
  1300.                             'PRINT "Synced"; isync.itemstr 'TEMP debug line
  1301.                         ELSE
  1302.                             game.get_isdesync = 1
  1303.                         END IF
  1304.                     END IF
  1305.                 END IF
  1306.  
  1307.                 IF game.get_item = GETITEM_STAV THEN 'get world state
  1308.                     GET #game.clienth, , istav
  1309.                     IF NOT EOF(game.clienth) THEN
  1310.                         IF istav.syncstr = GETITEM_STAV THEN
  1311.                             IF istav.synctime > stav.synctime THEN
  1312.                                 stav = istav
  1313.                             END IF
  1314.                             'PRINT "Synced"; isync.itemstr 'TEMP debug line
  1315.                         ELSE
  1316.                             game.get_isdesync = 1
  1317.                         END IF
  1318.                         game.get_item = GETITEM_SYNC
  1319.                     END IF
  1320.                 END IF
  1321.  
  1322.                 IF game.get_item = GETITEM_PBAL THEN 'get player balls data
  1323.                     GET #game.clienth, , ipbal()
  1324.                     IF NOT EOF(game.clienth) THEN
  1325.                         IF (ipbal(1).syncstr = GETITEM_PBAL) THEN
  1326.                             IF (ipbal(1).synctime > bal(1).synctime) THEN 'AND (TIMER(.001) - game.timer_pballs) < (ipbal(1).synctime - bal(1).synctime + 0.05) THEN
  1327.                                 FOR i = 1 TO stav.pocethracov
  1328.                                     bal(i) = ipbal(i)
  1329.                                 NEXT i
  1330.                             END IF
  1331.                             game.timer_pballs = TIMER(.001)
  1332.                             'PRINT "Synced"; isync.itemstr 'TEMP debug line
  1333.                         ELSE
  1334.                             game.get_isdesync = 1
  1335.                         END IF
  1336.                         game.get_item = GETITEM_SYNC
  1337.                     END IF
  1338.                 END IF
  1339.  
  1340.                 IF game.get_item = GETITEM_BAL THEN 'get nonplayer balls data
  1341.                     GET #game.clienth, , ibal()
  1342.                     IF NOT EOF(game.clienth) THEN
  1343.                         IF (ibal(1).syncstr = GETITEM_BAL) THEN
  1344.                             IF (ibal(1).synctime > bal(stav.pocethracov + 1).synctime) THEN
  1345.                                 FOR i = 1 TO stav.pocetgulzvoleny
  1346.                                     bal(stav.pocethracov + i) = ibal(i)
  1347.                                 NEXT i
  1348.                             END IF
  1349.                             'PRINT "Synced"; isync.itemstr 'TEMP debug line
  1350.                         ELSE
  1351.                             game.get_isdesync = 1
  1352.                         END IF
  1353.                         game.get_item = GETITEM_SYNC
  1354.                     END IF
  1355.                 END IF
  1356.  
  1357.                 IF game.get_item = GETITEM_MESG THEN 'get message
  1358.                     GET #game.clienth, , imsg
  1359.                     IF NOT EOF(game.clienth) THEN
  1360.                         IF (imsg.syncstr = GETITEM_MESG) THEN
  1361.                             AddMessage imsg.text, imsg.col, imsg.time_dur, 0
  1362.                             'PRINT "Synced"; isync.itemstr 'TEMP debug line
  1363.                         ELSE
  1364.                             game.get_isdesync = 1
  1365.                         END IF
  1366.                         game.get_item = GETITEM_SYNC
  1367.                     END IF
  1368.                 END IF
  1369.  
  1370.                 IF game.get_item = GETITEM_HRAC THEN 'get players data
  1371.                     GET #game.clienth, , ihrac()
  1372.                     IF NOT EOF(game.clienth) THEN
  1373.                         IF ihrac(1).syncstr = GETITEM_HRAC THEN
  1374.                             IF ihrac(1).synctime > hrac(1).synctime THEN
  1375.                                 FOR i = 1 TO PLAYER_NET_MAX
  1376.                                     IF i <> game.clientid AND game.clientid > 0 THEN 'if another client's player
  1377.                                         hrac(i) = ihrac(i) 'get player data from host
  1378.                                         hrac(i).klavesy = i 'set player net controlled
  1379.                                     ELSE 'if my client player
  1380.                                         hrac(i).skore = ihrac(i).skore
  1381.                                         hrac(i).bal = ihrac(i).bal
  1382.                                         hrac(i).clientid = ihrac(i).clientid
  1383.                                     END IF
  1384.                                 NEXT i
  1385.                             END IF
  1386.                             'PRINT "Synced"; isync.itemstr 'TEMP debug line
  1387.                         ELSE
  1388.                             game.get_isdesync = 1
  1389.                         END IF
  1390.                         game.get_item = GETITEM_SYNC
  1391.                     END IF
  1392.                 END IF
  1393.  
  1394.                 IF game.get_item = GETITEM_STAT THEN 'get match statistics
  1395.                     GET #game.clienth, , istats()
  1396.                     IF NOT EOF(game.clienth) THEN
  1397.                         IF (istats(PLAYER_NET_MAX + 1, 1) + istats(PLAYER_NET_MAX + 1, 2) + istats(PLAYER_NET_MAX + 1, 3)) = (ASC(GETITEM_STAT, 1) + ASC(GETITEM_STAT, 2) + ASC(GETITEM_STAT, 3)) THEN
  1398.                             FOR i = 1 TO UBOUND(stats, 1)
  1399.                                 FOR j = 1 TO UBOUND(stats, 2)
  1400.                                     stats(i, j) = istats(i, j)
  1401.                                 NEXT j
  1402.                             NEXT i
  1403.                             game.sync_stats = 0
  1404.                             'PRINT "Synced"; isync.itemstr 'TEMP debug line
  1405.                         ELSE
  1406.                             game.get_isdesync = 1
  1407.                         END IF
  1408.                         game.get_item = GETITEM_SYNC
  1409.                     END IF
  1410.                 END IF
  1411.  
  1412.             LOOP UNTIL EOF(game.clienth)
  1413.  
  1414.             IF game.clientid > 0 THEN 'send clients data to host
  1415.                 sync.synctime = TIMER(.001)
  1416.  
  1417.                 'IF stav.gameplay = 1 THEN 'send client controller to host
  1418.                 sync.itemstr = GETITEM_KLAV
  1419.                 sync.synctime = TIMER(.001)
  1420.                 sync.isdesync = game.get_isdesync
  1421.                 PUT #game.clienth, , sync
  1422.                 PUT #game.clienth, , klav(hrac(game.clientid).klavesy)
  1423.                 'END IF
  1424.  
  1425.                 'IF stav.gameplay = 0 THEN 'send client player to host
  1426.                 sync.itemstr = GETITEM_HRAC
  1427.                 sync.synctime = TIMER(.001)
  1428.                 PUT #game.clienth, , sync
  1429.                 PUT #game.clienth, , hrac(game.clientid)
  1430.                 'END IF
  1431.  
  1432.                 IF game.newmsg = 1 AND game.msgcount > 0 THEN 'send client player to host
  1433.                     IF msg(game.msgcount).distribute = 1 THEN
  1434.                         sync.itemstr = GETITEM_MESG
  1435.                         sync.synctime = TIMER(.001)
  1436.                         PUT #game.clienth, , sync
  1437.                         PUT #game.clienth, , msg(game.msgcount)
  1438.                         msg(game.msgcount).distribute = 0
  1439.                     END IF
  1440.                     game.newmsg = 0
  1441.                 END IF
  1442.             END IF
  1443.  
  1444.             IF (TIMER(.001) - game.get_time) > NET_TIMEOUT_LIMIT THEN ResetNetGame
  1445.         END IF
  1446.     END IF
  1447.  
  1448. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1449. SUB CloseClientConn (clidx AS INTEGER)
  1450.     IF client(clidx).conn <> 0 THEN
  1451.         CLOSE client(clidx).conn
  1452.         client(clidx).conn = 0
  1453.     END IF
  1454.     hrac(clidx).clientid = 0
  1455.     hrac(clidx).klavesy = CPU_CONTROLID
  1456.     hrac(clidx).isready = 0
  1457.     bal(hrac(clidx).bal).complayer = 1
  1458.     IF stav.AIallowed = 0 AND klav(hrac(clidx).klavesy).typ = 4 THEN
  1459.         bal(hrac(clidx).bal).energia = 0
  1460.         CalculatePlayerState bal(hrac(clidx).bal)
  1461.     END IF
  1462.     AddMessage "Player " + RTRIM$(hrac(clidx).meno) + " was disconnected", MSG_COL, MSG_DUR_STD, 1
  1463.  
  1464. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1465. SUB ResetNetGame
  1466.     IF game.clienth <> 0 THEN 'try to close client connection
  1467.         CLOSE game.clienth
  1468.         game.clienth = 0
  1469.         game.clientid = 0
  1470.         stav.autostart_set = 0
  1471.         AddMessage "You have been disconnected from the host", MSG_COL, MSG_DUR_STD, 0
  1472.     END IF
  1473.     IF game.hosth <> 0 THEN 'try to close host service
  1474.         CLOSE game.hosth
  1475.         game.hosth = 0
  1476.         game.clientid = 0
  1477.         hrac(1).clientid = 0
  1478.         AddMessage "Game hosting ended", MSG_COL, MSG_DUR_STD, 0
  1479.     END IF
  1480.     game.isnetgame = 0
  1481.     FOR i = 1 TO PLAYER_COUNT_MAX
  1482.         hrac(i).clientid = 0
  1483.         IF (klav(hrac(i).klavesy).typ = 5) OR (i > PLAYER_NET_MAX AND klav(hrac(i).klavesy).typ <> 4) THEN
  1484.             hrac(i).klavesy = CPU_CONTROLID
  1485.             bal(hrac(i).bal).complayer = 1
  1486.         END IF
  1487.     NEXT i
  1488.  
  1489. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1490. SUB HostGame
  1491.     IF game.clienth <> 0 THEN ResetNetGame
  1492.     IF game.hosth = 0 THEN
  1493.         game.hosth = _OPENHOST("TCP/IP:" + STR$(game.host_port))
  1494.         IF game.hosth <> 0 THEN
  1495.             game.isnetgame = 1
  1496.             game.clientid = 1
  1497.             hrac(1).clientid = 1
  1498.             AddMessage "Game hosting started", MSG_COL, MSG_DUR_STD, 0
  1499.         ELSE
  1500.             game.isnetgame = 0
  1501.         END IF
  1502.     ELSE
  1503.         ResetNetGame
  1504.     END IF
  1505.  
  1506. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1507. SUB JoinGame
  1508.     IF game.hosth <> 0 THEN ResetNetGame
  1509.     IF game.clienth = 0 THEN
  1510.         AddMessage "Connecting to" + RTRIM$(STR$(game.host_port)) + ":" + RTRIM$(game.host_ip) + "...", MSG_COL, MSG_DUR_STD, 0
  1511.         DisplayMessages
  1512.         _DISPLAY
  1513.         game.clienth = _OPENCLIENT("TCP/IP:" + STR$(game.host_port) + ":" + RTRIM$(game.host_ip))
  1514.         IF game.clienth <> 0 THEN
  1515.             game.isnetgame = 1
  1516.             game.get_item = GETITEM_SYNC
  1517.             game.get_isdesync = 0
  1518.             game.get_time = TIMER(.001)
  1519.             game.timer_pballs = TIMER(.001)
  1520.             AddMessage "Connection opened, joining the game...", MSG_COL, MSG_DUR_STD, 0
  1521.         ELSE
  1522.             game.isnetgame = 0
  1523.         END IF
  1524.     ELSE
  1525.         CLOSE game.clienth
  1526.         ResetNetGame
  1527.     END IF
  1528.  
  1529. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1530. FUNCTION InputText$ (meno AS STRING, xpos AS INTEGER, ypos AS INTEGER, col AS INTEGER, inputwidth AS _BYTE, hint AS STRING, initval AS _BYTE, digitonly AS _BYTE) 'get text input from keyboard input
  1531.     clrstr$ = ""
  1532.     tmpstr$ = ""
  1533.     IF initval = 1 THEN res$ = RTRIM$(meno) ELSE res$ = ""
  1534.     FOR i = 1 TO inputwidth: clrstr$ = clrstr$ + " ": NEXT i
  1535.     COLOR col
  1536.     DO
  1537.         DO
  1538.             _LIMIT FPS
  1539.             k = _KEYHIT
  1540.         LOOP UNTIL k <> 0
  1541.         IF ((digitonly = 0 AND k >= 33 AND k <= 126) OR (digitonly = 1 AND k >= 48 AND k <= 57)) AND LEN(res$) < LEN(meno) THEN res$ = res$ + CHR$(k)
  1542.         IF k = 8 AND LEN(res$) > 0 THEN res$ = LEFT$(res$, LEN(res$) - 1)
  1543.         IF res$ = "" THEN tmpstr$ = hint ELSE tmpstr$ = res$
  1544.         _PRINTSTRING (xpos, ypos), clrstr$
  1545.         _PRINTSTRING (xpos, ypos), tmpstr$
  1546.         _DISPLAY
  1547.     LOOP UNTIL k = 13 OR k = 27
  1548.     IF k = 13 THEN InputText$ = res$
  1549.     IF k = 27 THEN InputText$ = CHR$(27)
  1550.  
  1551. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1552. SUB PrintMenuItem (id AS INTEGER, amenu AS tmenu, menucode AS INTEGER, playercode AS INTEGER, rollable AS INTEGER, s AS STRING, fixedwidth AS INTEGER, deltax AS INTEGER, lineoff AS INTEGER, col AS INTEGER) 'print horizontaly centered text at line y
  1553.     slen = LEN(RTRIM$(s)) * FONT_W
  1554.     IF fixedwidth > 0 THEN slen = fixedwidth
  1555.     px = INT((game.maxx - slen) / 2) + deltax
  1556.     py = amenu.ypos + (id - 1) * amenu.item_height
  1557.     COLOR col
  1558.     _PRINTSTRING (px, py), s
  1559.     IF id = amenu.item_active THEN
  1560.         IF rollable = 1 THEN
  1561.             COLOR amenu.cursor_col
  1562.             _PRINTSTRING (amenu.cursor_xpos - 10 - FONT_W, py), "<"
  1563.             _PRINTSTRING (amenu.cursor_xpos + amenu.cursor_width + 10, py), ">"
  1564.         END IF
  1565.         amenu.menucode = menucode
  1566.         amenu.playercode = playercode
  1567.     END IF
  1568. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1569. SUB PrintMenuCursor (amenu AS tmenu) 'print menu cursor
  1570.     py = amenu.ypos + (amenu.item_active - 1) * amenu.item_height
  1571.     COLOR amenu.cursor_col
  1572.     LINE (amenu.cursor_xpos - amenu.cursor_out, game.maxy - (py - amenu.cursor_out))-(amenu.cursor_xpos + amenu.cursor_out + amenu.cursor_width, game.maxy - (py + FONT_H) - amenu.cursor_out), amenu.cursor_col, B
  1573.  
  1574. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1575. SUB PauseGame 'pause gameplay
  1576.     winstr$ = "-> Game paused <-"
  1577.     COLOR MSG_COL
  1578.     _PRINTSTRING ((game.maxx - LEN(winstr$) * 10) / 2, (game.maxy - 50) / 2), winstr$
  1579.  
  1580. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1581. SUB DrawBall (baln AS gula) 'draw ball
  1582.     CONST BSEGM = 10
  1583.     koef = (10 + 90 * game.printdebug) * FPS / 100
  1584.     bcol = baln.col
  1585.     IF baln.freezedtime > 0 THEN bcol = 27
  1586.     IF baln.riadena = 1 THEN
  1587.         CIRCLE (baln.x, baln.y), baln.r - 1, baln.col
  1588.         CIRCLE (baln.x, baln.y), baln.r + 1, baln.col
  1589.         FOR i = 1 TO BSEGM
  1590.             CIRCLE (baln.x, baln.y), i * (baln.r / 2 - 2) / BSEGM, bcol, 0, baln.energia / stav.energy_player_start * _PI * 2
  1591.         NEXT i
  1592.         LINE (baln.x, baln.y)-(baln.x + baln.v.x * koef, baln.y + baln.v.y * koef), baln.col 'draw actual velocity
  1593.         IF game.printdebug = 1 THEN LINE (baln.x, baln.y)-(baln.x + baln.vi.x * koef, baln.y + baln.vi.y * koef), bal(baln.protivnik).col 'draw intended velocity
  1594.     END IF
  1595.     IF baln.i = stav.baljeto THEN
  1596.         CIRCLE (baln.x, baln.y), baln.r * 2 / 3, 15
  1597.     END IF
  1598.     IF baln.i > stav.pocethracov THEN
  1599.         reflectfrom = ATN((1.25 * stav.maxy - baln.y) / (1.25 * stav.maxx - baln.x))
  1600.         CIRCLE (baln.x, baln.y), baln.r - 5, 28, reflectfrom, reflectfrom + _PI / 8
  1601.         CIRCLE (baln.x, baln.y), baln.r - 5, 28, reflectfrom + _PI / 8 + _PI / 32, reflectfrom + _PI / 4
  1602.         CIRCLE (baln.x, baln.y), baln.r - 10, 28, reflectfrom, reflectfrom + _PI / 8
  1603.         CIRCLE (baln.x, baln.y), baln.r - 10, 28, reflectfrom + _PI / 8 + _PI / 32, reflectfrom + _PI / 4
  1604.     END IF
  1605.  
  1606.     CIRCLE (baln.x, baln.y), baln.r, baln.col
  1607.  
  1608. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1609. SUB DrawScore 'Draw player score
  1610.     WINDOW (0, 0)-(game.maxx, game.maxy)
  1611.     FOR i = 1 TO stav.pocethracov
  1612.         scxl = SCORE_DELTA_X * -(game.maxx >= 4 * SCORE_DELTA_X) + game.maxx / 4 * -(game.maxx < 4 * SCORE_DELTA_X)
  1613.         dx = (game.maxx - 4 * scxl) / 2
  1614.         scx = dx + scxl * ((i - 4 * INT((i - 1) / 4)) - 1)
  1615.         scty = SCORE_DELTA_Y + 15 * INT((i - 1) / 4)
  1616.         scly = game.maxy - SCORE_DELTA_Y - 15 * INT((i - 1) / 4)
  1617.         COLOR bal(hrac(i).bal).col
  1618.         _PRINTSTRING (scx + (LEN(hrac(i).meno) - LEN(RTRIM$(hrac(i).meno))) * 8, scty - 10), RTRIM$(hrac(i).meno) + " -" + STR$(hrac(i).skore)
  1619.         LINE (scx + SCORE_NAME_LEN, scly)-(scx + SCORE_NAME_LEN + bal(hrac(i).bal).energia, scly + 7), bal(hrac(i).bal).col, BF
  1620.         IF bal(hrac(i).bal).energia <= 0 THEN
  1621.             _PRINTSTRING (scx + SCORE_NAME_LEN, scty - 10), "OUT"
  1622.         END IF
  1623.     NEXT i
  1624.     WINDOW (0, 0)-(stav.maxx, stav.maxy)
  1625.  
  1626. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1627. SUB CalculatePlayerState (baln AS gula) 'calculate players states
  1628.     DIM od AS SINGLE
  1629.     '-----------------------energy decreasing-------------------------------------
  1630.     IF baln.freezedtime > 0 THEN
  1631.         baln.freezedtime = baln.freezedtime - 1
  1632.     ELSE
  1633.         baln.energia = baln.energia - (stav.energydec * -(stav.baljeto = baln.i)) * game.fpscoef
  1634.     END IF
  1635.     IF baln.energia <= 0 THEN
  1636.         baln.riadena = 0
  1637.         pocetriadenych = 0
  1638.         FOR i = 1 TO stav.pocethracov
  1639.             IF bal(hrac(i).bal).riadena = 1 THEN
  1640.                 pocetriadenych = pocetriadenych + 1
  1641.                 priebeznyvitaz = i
  1642.             END IF
  1643.         NEXT i
  1644.         IF pocetriadenych > 1 THEN
  1645.             stav.baljeto = stav.balbudeto
  1646.             stav.balbudeto = nearestPlayer(bal(stav.baljeto), 0, 0)
  1647.             FOR i = 1 TO stav.pocetgulx
  1648.                 IF bal(i).i <> stav.baljeto AND bal(i).riadena = 1 THEN bal(i).protivnik = stav.baljeto
  1649.             NEXT i
  1650.         END IF
  1651.         IF pocetriadenych = 1 THEN
  1652.             stav.vitaz = priebeznyvitaz
  1653.             hrac(stav.vitaz).skore = hrac(stav.vitaz).skore + 1
  1654.             IF hrac(stav.vitaz).skore >= stav.winscore THEN game.autostart_time = TIMER + DELAY_MATCHEND ELSE game.autostart_time = TIMER + DELAY_ROUNDSTART
  1655.             DrawScore
  1656.         END IF
  1657.     END IF
  1658.     '-----------------------dodging time-----------------------------------------
  1659.     IF baln.klucka_time = 0 AND baln.klucka_trvanie = 0 AND baln.klucka_pocet = 0 THEN
  1660.         baln.klucka_time = INT(RND * strat(baln.strat).klucka_avgtm + strat(baln.strat).klucka_avgtm / 2) / game.fpscoef
  1661.         baln.klucka_pocet = strat(baln.strat).klucka_pocet
  1662.     END IF
  1663.     IF baln.klucka_time > 0 THEN
  1664.         baln.klucka_time = baln.klucka_time - 1
  1665.     END IF
  1666.     IF baln.klucka_time = 0 AND baln.klucka_trvanie > 0 THEN
  1667.         baln.klucka_trvanie = baln.klucka_trvanie - 1
  1668.     END IF
  1669.     IF baln.klucka_time = 0 AND baln.klucka_trvanie = 0 AND baln.klucka_pocet > 0 THEN
  1670.         baln.klucka_pocet = baln.klucka_pocet - 1
  1671.         baln.klucka_trvanie = INT(RND * strat(baln.strat).klucka_trvanie + strat(baln.strat).klucka_trvanie / 2) / game.fpscoef
  1672.         baln.klucka_uhol = RND * strat(baln.strat).klucka_uhol * (2 * strat(baln.strat).klucka_uholodch) + strat(baln.strat).klucka_uhol * (1 - strat(baln.strat).klucka_uholodch) * (3 - INT(RND * 2 + 1) * 2)
  1673.     END IF
  1674.     '-----------------------choose nearest enemy if tagged-----------------------
  1675.     IF stav.baljeto = baln.i THEN
  1676.         novyprotivnik = nearestPlayer(baln, 0, -(baln.energia > (stav.energy_player_start * strat(baln.strat).adrenalin_energy)))
  1677.         IF novyprotivnik <> 0 THEN baln.protivnik = novyprotivnik
  1678.         stav.balbudeto = nearestPlayer(baln, 0, 0)
  1679.     END IF
  1680.     '-----------------------boosting time----------------------------------------
  1681.     IF baln.boost_time > 0 AND baln.boost_trvanie = 0 THEN baln.boost_time = baln.boost_time - 1
  1682.     IF baln.boost_trvanie > 0 THEN baln.boost_trvanie = baln.boost_trvanie - 1
  1683.  
  1684.     '-----------------------reaction drop time-----------------------------------
  1685.     IF baln.reactdrop_time > 0 THEN baln.reactdrop_time = baln.reactdrop_time - 1
  1686.     IF baln.reactdrop_time <= 0 AND baln.reactdrop_dur > 0 THEN baln.reactdrop_dur = baln.reactdrop_dur - 1
  1687.     IF baln.reactdrop_time <= 0 AND baln.reactdrop_dur <= 0 THEN
  1688.         IF baln.energia < (stav.energy_player_start * strat(baln.strat).adrenalin_energy) THEN reactkoef = (1 - strat(baln.strat).adrenalin_rate) ELSE reactkoef = 1
  1689.         baln.reactdrop_time = INT((RND * strat(baln.strat).reactdrop_per * reactkoef + strat(baln.strat).reactdrop_per * reactkoef / 2) / game.fpscoef)
  1690.         baln.reactdrop_dur = INT((RND * strat(baln.strat).reactdrop_dur * reactkoef + strat(baln.strat).reactdrop_dur * reactkoef / 2) / game.fpscoef)
  1691.         baln.smer_odchyl = (RND * strat(baln.strat).chybasmeru - strat(baln.strat).chybasmeru / 2) * pi 'apply random radian deviance from intended direction
  1692.     END IF
  1693.  
  1694. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1695. FUNCTION nearestPlayer (baln AS gula, mateonly AS _BYTE, weighted AS _BYTE) 'returns nearest opponent idx
  1696.     CONST NEAREST_WEIGHTCOEF = 10.0 'coeficient for energy inclusion into weight
  1697.     DIM weight, vzd, vzdakt, vzdakt_winner AS SINGLE
  1698.     DIM nearest_winner AS INTEGER
  1699.     vzdakt = 0
  1700.     nearestPlayer = 0
  1701.     vzdakt_winner = 0
  1702.     nearest_winner = 0
  1703.     FOR i = 1 TO stav.pocetgulx
  1704.         IF bal(i).i <> baln.i AND bal(i).riadena = 1 AND (mateonly = 1 IMP i <> stav.baljeto) THEN
  1705.             weight = weighted * (stav.energy_player_start - bal(i).energia) * NEAREST_WEIGHTCOEF
  1706.             vzd = SQR((baln.x - bal(i).x) ^ 2 + (baln.y - bal(i).y) ^ 2) + weight
  1707.             IF nearestPlayer = 0 OR vzd < vzdakt THEN
  1708.                 nearestPlayer = i
  1709.                 vzdakt = vzd
  1710.             END IF
  1711.             IF hrac(bal(i).hrac).skore = stav.winscore - 1 AND (vzd < vzdakt_winner OR nearest_winner = 0) THEN
  1712.                 nearest_winner = i
  1713.                 vzdakt_winner = vzd
  1714.             END IF
  1715.         END IF
  1716.     NEXT i
  1717.     IF weighted = 1 AND nearest_winner > 0 THEN nearestPlayer = nearest_winner
  1718.  
  1719. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1720. SUB GenerateAIControl (baln AS gula) 'Decide computer player's control keys hits
  1721.     DIM dd AS SINGLE, vid AS SINGLE, vd AS SINGLE, eid AS SINGLE, vnd AS SINGLE, ved AS SINGLE, did AS SINGLE, thit AS SINGLE
  1722.     DIM rot_klucka AS SINGLE, rot_border AS SINGLE, rot_enemy AS SINGLE, rot_mate AS SINGLE
  1723.     DIM siner AS SINGLE, coser AS SINGLE, sineri AS SINGLE, coseri AS SINGLE
  1724.     DIM sinevr AS SINGLE, cosevr AS SINGLE, sinmt AS SINGLE, cosnmt AS SINGLE
  1725.     DIM okrajrot AS SINGLE, enemy_dist_factor AS SINGLE, smerdookraju AS INTEGER, nearmate AS INTEGER
  1726.     DIM d AS vektor, vi AS vektor, ei AS vektor, ve AS vektor, di AS vektor, dm AS vektor
  1727.  
  1728.     vi = baln.vi 'player's intended speed vector copy
  1729.     vid = SQR(vi.x ^ 2 + vi.y ^ 2)
  1730.     vi.x = vi.x / vid * stav.vmax
  1731.     vi.y = vi.y / vid * stav.vmax
  1732.     vd = SQR(baln.v.x ^ 2 + baln.v.y ^ 2)
  1733.     ve = bal(baln.protivnik).v 'enemy speed vector copy
  1734.     ved = SQR(ve.x ^ 2 + ve.y ^ 2)
  1735.  
  1736.     d.x = bal(baln.protivnik).x - baln.x 'player to enemy postition vector
  1737.     d.y = bal(baln.protivnik).y - baln.y
  1738.     dd = SQR(d.x ^ 2 + d.y ^ 2)
  1739.     coser = (d.x * baln.v.x + d.y * baln.v.y) / (dd * vd)
  1740.     siner = (d.x * baln.v.y - d.y * baln.v.x) / (dd * vd)
  1741.     cosevr = (ve.x * baln.v.x + ve.y * baln.v.y) / (ved * vd)
  1742.     sinevr = (ve.x * baln.v.y - ve.y * baln.v.x) / (ved * vd)
  1743.  
  1744.     '!EXPERIMENTAL CODE! - try more exact enemy future position vector, but  does not work so well as used approximation
  1745.     'di.x = d.x + ve.x * d.x / ((((d.x / dd) + (ve.x / ved)) * stav.vmax) - ve.x) 'new intended direction to enemy
  1746.     'di.y = d.y + ve.y * d.y / ((((d.y / dd) + (ve.y / ved)) * stav.vmax) - ve.y) 'new intended direction to enemy
  1747.     '!EXPERIMENTAL CODE! end
  1748.  
  1749.     di.x = d.x + ve.x * dd / vd * ABS(siner) 'player to enemy approximate future position vector, future enemy position more relevant when enemy closer
  1750.     di.y = d.y + ve.y * dd / vd * ABS(siner)
  1751.     did = SQR(di.x ^ 2 + di.y ^ 2)
  1752.     coseri = (di.x * baln.v.x + di.y * baln.v.y) / (did * vd)
  1753.     sineri = (di.x * baln.v.y - di.y * baln.v.x) / (did * vd)
  1754.  
  1755.     rot_enemy = 0 'rotation away from enemy in rad
  1756.     rot_border = 0 'rotation away from border in rad
  1757.     rot_mate = 0 'rotation towards nearest mate in rad
  1758.     rot_odchyl = 0 'baln.smer_odchyl * -(baln.reactdrop_dur = 1) 'apply direction error if react time
  1759.     smerdookraju = 0 'is players direction to border
  1760.  
  1761.     IF NOT (stav.baljeto = baln.i) THEN 'decide flee action
  1762.         enemy_dist_factor = 1 * -(dd <= strat(baln.strat).detekcia_vzdfull) + (1 - (dd - strat(baln.strat).detekcia_vzdfull) / _
  1763.           (strat(baln.strat).detekcia_vzdmin - strat(baln.strat).detekcia_vzdfull)) * -(dd > strat(baln.strat).detekcia_vzdfull AND dd <= strat(baln.strat).detekcia_vzdmin)' factor=1 if enemy distance within treshold, then decreasing
  1764.  
  1765.         IF enemy_dist_factor > 0 THEN 'if enemy in detection distance, rotate away
  1766.             rot_enemy = -(coseri > 0) * -(ABS(sineri) <= strat(baln.strat).detekcia_sin) * (-(sineri > 0) + (sineri < 0)) * strat(baln.strat).detekcia_rot * enemy_dist_factor * game.fpscoef
  1767.  
  1768.             '!EXPERIMENTAL CODE! - try better rotation from enemy
  1769.             'strat(baln.strat).detekcia_rot = 10 * pi / FPS 'TEMPORARY MODIFICATION
  1770.             'cosevi = (di.x * vi.x + di.y * vi.y) / (did * vid)
  1771.             'sinevi = (di.x * vi.y - di.y * vi.x) / (did * vid)
  1772.             'cosvvi = (v.x * vi.x + v.y * vi.y) / (vd * vid)
  1773.             'sinvvi = (v.x * vi.y - v.y * vi.x) / (vd * vid)
  1774.             'IF (coseri > 0) AND (ABS(sineri) <= strat(baln.strat).detekcia_sin) THEN
  1775.             '    rot_dir = -(sineri > 0) + (sineri < 0)
  1776.             '    IF NOT ((cosevi > 0 AND (ABS(sinevi) <= strat(baln.strat).detekcia_sin)) AND NOT (rot_dir = (-(sinevi > 0) + (sinevi < 0)))) THEN
  1777.             '        rot_enemy = rot_dir * strat(baln.strat).detekcia_rot * enemy_dist_factor * game.fpscoef
  1778.             '    END IF
  1779.             'END IF
  1780.             '!EXPERIMENTAL CODE! end
  1781.  
  1782.         END IF
  1783.  
  1784.         okrajrot = strat(baln.strat).okraj_rot 'border unit rotation in rad
  1785.         IF baln.x < strat(baln.strat).okraj AND vi.x < 0 THEN
  1786.             rot_border = (okrajrot * (vi.y >= 0) + okrajrot * -(vi.y < 0)) '* (1 - enemy_dist_factor)
  1787.             smerdookraju = 1
  1788.         END IF
  1789.         IF baln.x > stav.maxx - strat(baln.strat).okraj AND vi.x > 0 THEN
  1790.             rot_border = (okrajrot * -(vi.y >= 0) + okrajrot * (vi.y < 0)) '* (1 - enemy_dist_factor)
  1791.             smerdookraju = 1
  1792.         END IF
  1793.         IF baln.y < strat(baln.strat).okraj AND vi.y < 0 THEN
  1794.             rot_border = (okrajrot * (vi.x >= 0) + okrajrot * (vi.x < 0)) '* (1 - enemy_dist_factor)
  1795.             smerdookraju = 1
  1796.         END IF
  1797.         IF baln.y > stav.maxy - strat(baln.strat).okraj AND vi.y > 0 THEN
  1798.             rot_border = (okrajrot * (vi.x >= 0) + okrajrot * -(vi.x < 0)) '* (1 - enemy_dist_factor)
  1799.             smerdookraju = 1
  1800.         END IF
  1801.     END IF
  1802.  
  1803.     rot_klucka = baln.klucka_uhol * -(baln.klucka_time = 0) * -(baln.klucka_trvanie = 1) * -(stav.baljeto <> baln.i) * _
  1804.       (dd > strat(baln.strat).mate_distmin OR (coseri < 0 AND sineri >= 0 AND baln.klucka_uhol > 0 AND baln.klucka_uhol < pi) OR (coseri < 0 AND sineri <= 0 AND baln.klucka_uhol < 0 AND baln.klucka_uhol > -pi)) 'apply dodge if dodging time - TEMPORARY DISABLED!!!
  1805.  
  1806.  
  1807.     IF baln.i = bal(stav.baljeto).protivnik THEN 'if ball being chased
  1808.         nearmate = nearestPlayer(baln, 1, -(baln.energia > (stav.energy_player_start * strat(baln.strat).adrenalin_energy)))
  1809.         IF nearmate > 0 THEN
  1810.             dm.x = bal(nearmate).x - baln.x
  1811.             dm.y = bal(nearmate).y - baln.y
  1812.             dmd = SQR(dm.x ^ 2 + dm.y ^ 2)
  1813.             cosnm = (dm.x * baln.v.x + dm.y * baln.v.y) / (dmd * vd)
  1814.             sinnm = (dm.x * baln.v.y - dm.y * baln.v.x) / (dmd * vd)
  1815.             IF (rot_border = 0) AND (dmd > strat(baln.strat).mate_distmin) AND (((coseri < strat(baln.strat).mate_cosenmax) AND (dd < strat(baln.strat).mate_en_distmin)) OR ((coseri < 0) AND (dd > strat(baln.strat).mate_en_distmin))) THEN
  1816.                 rot_mate = ((sinnm > 0) * strat(baln.strat).mate_rot * game.fpscoef - (sinnm <= 0) * strat(baln.strat).mate_rot * game.fpscoef) 'rotate towards mate
  1817.             END IF
  1818.         END IF
  1819.     END IF
  1820.  
  1821.     RotateVector vi, rot_border + rot_klucka + rot_odchyl + rot_enemy + rot_mate 'aplly all calculated rotations to intended velocity
  1822.  
  1823.     IF stav.baljeto = baln.i THEN 'chasing direction intended
  1824.         IF baln.reactdrop_time > 0 THEN 'if time is up for reaction
  1825.             baln.boostintended = -(-(coser > 0) AND -(cosevr > 0) AND -(ABS(sinevr) < strat(baln.strat).boost_chasesin) AND baln.boost_time = 0 AND smerdookraju = 0)
  1826.             baln.vi.x = stav.vmax * di.x / did
  1827.             baln.vi.y = stav.vmax * di.y / did
  1828.         END IF
  1829.     ELSE 'flee direction intended
  1830.         baln.boostintended = -(-(coser < 0) AND baln.boost_time = 0 AND dd < (RND * strat(baln.strat).boost_dist + 2 * PLAY_BALL_R) AND smerdookraju = 0)
  1831.         baln.vi.x = vi.x
  1832.         baln.vi.y = vi.y
  1833.     END IF
  1834.  
  1835. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1836. SUB ReadGamepad (klavn AS tklavesy) 'read state of gamepad
  1837.     di = _DEVICEINPUT(klavn.devid)
  1838.     IF klavn.typ = 3 THEN
  1839.         klavn.gvektor.x = _AXIS(klavn.xaxis)
  1840.         klavn.gvektor.y = -_AXIS(klavn.yaxis)
  1841.         klavn.isshoota = _BUTTON(klavn.shoota)
  1842.         klavn.isshootb = _BUTTON(klavn.shootb)
  1843.         klavn.isup = (_AXIS(klavn.dyaxis) = -1)
  1844.         klavn.isdown = (_AXIS(klavn.dyaxis) = 1)
  1845.         klavn.isleft = (_AXIS(klavn.dxaxis) = -1)
  1846.         klavn.isright = (_AXIS(klavn.dxaxis) = 1)
  1847.         IF klavn.gvektor.x > 0.5 THEN klavn.isright = -1
  1848.         IF klavn.gvektor.x < -0.5 THEN klavn.isleft = -1
  1849.         IF klavn.gvektor.y > 0.5 THEN klavn.isup = -1
  1850.         IF klavn.gvektor.y < -0.5 THEN klavn.isdown = -1
  1851.  
  1852.         IF klavn.buttonstate <> (klavn.isshoota + klavn.isshootb * 2 + klavn.isup * 4 + klavn.isdown * 8 + klavn.isright * 16 + klavn.isleft * 32) THEN
  1853.             klavn.buttonstatechanged = -1
  1854.             klavn.buttonstatetimer = 50
  1855.         ELSE
  1856.             klavn.buttonstatechanged = 0
  1857.         END IF
  1858.         klavn.buttonstate = (klavn.isshoota + klavn.isshootb * 2 + klavn.isup * 4 + klavn.isdown * 8 + klavn.isright * 16 + klavn.isleft * 32)
  1859.     END IF
  1860.     IF klavn.buttonstatetimer > 0 THEN klavn.buttonstatetimer = klavn.buttonstatetimer - 1
  1861.     IF klavn.buttonstatetimer = 0 THEN klavn.buttonstatechanged = -1
  1862.  
  1863. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1864. SUB ResolvePlayerControl (baln AS gula, klavn AS tklavesy) 'perform players control keys actions
  1865.     DIM vn AS vektor, gvector AS vektor
  1866.  
  1867.     IF baln.complayer = 0 THEN 'read human player controls
  1868.         IF klavn.typ = 1 THEN 'read keyboard control
  1869.             klavn.isright = _KEYDOWN(klavn.right)
  1870.             klavn.isleft = _KEYDOWN(klavn.left)
  1871.             klavn.isdown = _KEYDOWN(klavn.down)
  1872.             klavn.isup = _KEYDOWN(klavn.up)
  1873.             klavn.isshoota = _KEYDOWN(klavn.shoota)
  1874.             klavn.isshootb = _KEYDOWN(klavn.shootb)
  1875.             baln.vi.x = baln.v.x
  1876.             baln.vi.y = baln.v.y
  1877.         END IF
  1878.  
  1879.         IF klavn.typ = 3 THEN 'read gamepad control
  1880.             baln.vi.x = 0
  1881.             baln.vi.y = 0
  1882.             ReadGamepad klavn
  1883.             baln.vi.x = klavn.gvektor.x * stav.vmax
  1884.             baln.vi.y = klavn.gvektor.y * stav.vmax
  1885.             IF ABS(klavn.gvektor.x) > GAMESTICK_DEADZONE OR ABS(klavn.gvektor.y) > GAMESTICK_DEADZONE THEN
  1886.                 klavn.isright = (baln.v.x < baln.vi.x) 'set control keys status for desired direction
  1887.                 klavn.isleft = (baln.v.x > baln.vi.x)
  1888.                 klavn.isup = (baln.v.y < baln.vi.y)
  1889.                 klavn.isdown = (baln.v.y > baln.vi.y)
  1890.             END IF
  1891.             IF klavn.isshootb AND game.isnetgame = 0 THEN stav.koniec_kola = 2
  1892.         END IF
  1893.  
  1894.         IF klavn.typ = 5 AND game.isnetgame = 1 THEN
  1895.             IF game.clienth <> 0 THEN ' reset network controller state on client
  1896.                 klavn.isright = (baln.v.x < baln.vi.x) 'set control keys status for desired direction
  1897.                 klavn.isleft = (baln.v.x > baln.vi.x)
  1898.                 klavn.isup = (baln.v.y < baln.vi.y)
  1899.                 klavn.isdown = (baln.v.y > baln.vi.y)
  1900.                 'klavn.isright = 0
  1901.                 'klavn.isleft = 0
  1902.                 'klavn.isup = 0
  1903.                 'klavn.isdown = 0
  1904.                 klavn.isshoota = 0
  1905.             END IF
  1906.             baln.vi.x = baln.v.x
  1907.             baln.vi.y = baln.v.y
  1908.         END IF
  1909.  
  1910.     ELSE 'get controls of computer player
  1911.         IF baln.riadena = 1 THEN GenerateAIControl baln
  1912.         klavn.isright = (baln.v.x < baln.vi.x) 'set control keys status for desired direction
  1913.         klavn.isleft = (baln.v.x > baln.vi.x)
  1914.         klavn.isup = (baln.v.y < baln.vi.y)
  1915.         klavn.isdown = (baln.v.y > baln.vi.y)
  1916.         klavn.isshoota = -baln.boostintended
  1917.     END IF
  1918.  
  1919.     IF baln.freezedtime <= 0 AND baln.riadena = 1 THEN 'apply acquired controls to player movement
  1920.         vn.x = baln.v.x
  1921.         vn.y = baln.v.y
  1922.  
  1923.         game.fpscoef = stav.fps / game.fpsactual
  1924.         IF klavn.isright THEN vn.x = vn.x + baln.a.x * game.fpscoef 'accelerate player according to control keys states
  1925.         IF klavn.isleft THEN vn.x = vn.x - baln.a.x * game.fpscoef
  1926.         IF klavn.isdown THEN vn.y = vn.y - baln.a.y * game.fpscoef
  1927.         IF klavn.isup THEN vn.y = vn.y + baln.a.x * game.fpscoef
  1928.         IF klavn.isshoota AND baln.boost_time = 0 AND stav.boostallowed = 1 THEN 'set boost state
  1929.             baln.boost_trvanie = BOOST_TRVANIE / game.fpscoef
  1930.             baln.boost_time = BOOST_TIME / game.fpscoef
  1931.         END IF
  1932.         vnd = SQR(vn.x ^ 2 + vn.y ^ 2) 'limit actual velocity to max. velocity
  1933.         IF vnd > stav.vmax THEN
  1934.             vn.x = vn.x * stav.vmax / vnd
  1935.             vn.y = vn.y * stav.vmax / vnd
  1936.         END IF
  1937.  
  1938.         IF baln.boost_trvanie > 0 THEN 'add some extra speed if boosted
  1939.             vn.x = vn.x + stav.vmax * BOOST_V_KOEF * (baln.boost_trvanie / BOOST_TRVANIE) * game.fpscoef * vn.x / vnd
  1940.             vn.y = vn.y + stav.vmax * BOOST_V_KOEF * (baln.boost_trvanie / BOOST_TRVANIE) * game.fpscoef * vn.y / vnd
  1941.         END IF
  1942.  
  1943.         baln.v.x = vn.x 'apply controler modified velocity
  1944.         baln.v.y = vn.y
  1945.     END IF
  1946.  
  1947. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1948. SUB PerformMovement (baln AS gula) 'Calculate ball movement
  1949.     baln.x = baln.x + baln.v.x * game.fpscoef
  1950.     baln.y = baln.y + baln.v.y * game.fpscoef
  1951.     baln.v.x = baln.v.x * stav.odpor ^ game.fpscoef
  1952.     baln.v.y = baln.v.y * stav.odpor ^ game.fpscoef
  1953.     IF (baln.x + baln.r > stav.maxx) THEN
  1954.         baln.v.x = -baln.v.x
  1955.         baln.x = stav.maxx - baln.r
  1956.     END IF
  1957.     IF (baln.x - baln.r < stav.minx) THEN
  1958.         baln.v.x = -baln.v.x
  1959.         baln.x = stav.minx + baln.r
  1960.     END IF
  1961.     IF (baln.y + baln.r > stav.maxy) THEN
  1962.         baln.v.y = -baln.v.y
  1963.         baln.y = stav.maxy - baln.r
  1964.     END IF
  1965.     IF (baln.y - baln.r < stav.miny) THEN
  1966.         baln.v.y = -baln.v.y
  1967.         baln.y = stav.miny + baln.r
  1968.     END IF
  1969.  
  1970. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1971. SUB BounceTest (bala AS gula, balb AS gula) 'Balls bounce test
  1972.     IF (bala.x - balb.x) * (bala.x - balb.x) + (bala.y - balb.y) * (bala.y - balb.y) <= (bala.r + balb.r + 0) * (bala.r + balb.r + 0) THEN
  1973.         PerformBounce bala, balb
  1974.         IF bala.riadena AND balb.riadena AND bala.freezedtime <= 0 AND balb.freezedtime <= 0 AND (stav.baljeto = bala.i OR stav.baljeto = balb.i) THEN 'balb.col = bal(bala.protivnik).col
  1975.             newjeto = bala.i * -(stav.baljeto <> bala.i) + balb.i * -(stav.baljeto <> balb.i)
  1976.             IF stav.baljeto <= PLAYER_NET_MAX AND newjeto <= PLAYER_NET_MAX AND (game.isnetgame = 0 OR game.hosth <> 0) THEN
  1977.                 stats(stav.baljeto, newjeto) = stats(stav.baljeto, newjeto) + 1
  1978.                 game.sync_stats = 1
  1979.             END IF
  1980.             stav.baljeto = newjeto
  1981.             bala.freezedtime = -(stav.baljeto = bala.i) * FREEZE_TIME / game.fpscoef
  1982.             balb.freezedtime = -(stav.baljeto = balb.i) * FREEZE_TIME / game.fpscoef
  1983.             bala.protivnik = balb.i
  1984.             balb.protivnik = bala.i
  1985.             FOR i = 1 TO stav.pocetgulx
  1986.                 IF bal(i).i <> stav.baljeto AND bal(i).riadena = 1 THEN bal(i).protivnik = bal(stav.baljeto).i
  1987.             NEXT i
  1988.         END IF
  1989.     END IF
  1990.  
  1991. '----------------------------------------------------------------------------------------------------------------------------------------------------
  1992. SUB PerformBounce (bala AS gula, balb AS gula) 'Calculate balls bounce
  1993.     DIM dx AS SINGLE, dy AS SINGLE, d AS SINGLE
  1994.     DIM l AS SINGLE, l1 AS SINGLE, l2 AS SINGLE
  1995.     DIM k AS SINGLE, k1 AS SINGLE, k2 AS SINGLE
  1996.     DIM m AS SINGLE, m1 AS SINGLE, m2 AS SINGLE
  1997.     DIM n AS SINGLE, n1 AS SINGLE, n2 AS SINGLE
  1998.     DIM cosa AS SINGLE, cosb AS SINGLE, p AS SINGLE
  1999.     DIM ma AS SINGLE, mb AS SINGLE
  2000.  
  2001.     IF stav.massallowed = 1 THEN
  2002.         ma = bala.m
  2003.         mb = balb.m
  2004.     ELSE
  2005.         ma = 1
  2006.         mb = 1
  2007.     END IF
  2008.  
  2009.     dx = balb.x - bala.x
  2010.     dy = balb.y - bala.y
  2011.     d = SQR(dx ^ 2 + dy ^ 2)
  2012.  
  2013.     p = bala.r + balb.r - d 'Move overlapping balls away from each other
  2014.     IF p >= 0 THEN
  2015.         bala.x = bala.x - dx * p / d / 2 * 2
  2016.         bala.y = bala.y - dy * p / d / 2 * 2
  2017.         balb.x = balb.x + dx * p / d / 2 * 2
  2018.         balb.y = balb.y + dy * p / d / 2 * 2
  2019.  
  2020.         dx = balb.x - bala.x
  2021.         dy = balb.y - bala.y
  2022.         d = SQR(dx ^ 2 + dy ^ 2)
  2023.     END IF
  2024.  
  2025.     cosa = dy / d
  2026.     cosb = -cosa
  2027.  
  2028.     l = (dx * bala.v.x * ma + dy * bala.v.y * ma) / d
  2029.     l2 = l * cosa
  2030.     k = (dy * bala.v.x * ma - dx * bala.v.y * ma) / d
  2031.     k1 = k * cosa
  2032.     l1 = bala.v.x * ma - k1
  2033.     k2 = bala.v.y * ma - l2
  2034.  
  2035.     n = (-dx * balb.v.x * mb - dy * balb.v.y * mb) / d
  2036.     n2 = n * cosb
  2037.     m = (-dy * balb.v.x * mb + dx * balb.v.y * mb) / d
  2038.     m1 = m * cosb
  2039.     n1 = balb.v.x * mb - m1
  2040.     m2 = balb.v.y * mb - n2
  2041.  
  2042.     bala.v.x = (k1 + n1) / ma
  2043.     bala.v.y = (k2 + n2) / ma
  2044.     balb.v.x = (m1 + l1) / mb
  2045.     balb.v.y = (m2 + l2) / mb
  2046.  
  2047. '----------------------------------------------------------------------------------------------------------------------------------------------------
  2048. FUNCTION MATHROUND (n)
  2049.     MATHROUND = FIX(n + 0.5 * SGN(n))
  2050.  
  2051. '----------------------------------------------------------------------------------------------------------------------------------------------------
  2052. SUB RotateVector (vn AS vektor, b AS SINGLE)
  2053.     DIM vt AS vektor
  2054.     sinb = SIN(b): cosb = COS(b)
  2055.     vt.x = vn.x * cosb - vn.y * sinb
  2056.     vt.y = vn.y * cosb + vn.x * sinb
  2057.     vn = vt
  2058.  
  2059. '----------------------------------------------------------------------------------------------------------------------------------------------------
  2060. SUB CalculateFps 'calculate actual fps coeficient for correct timig
  2061.     IF game.tend = game.tstart THEN
  2062.         game.fpsactual = stav.fps
  2063.     ELSE
  2064.         game.fpsactual = ((1 / (game.tend - game.tstart)) * 1 + game.fpsactual * 99) / 100
  2065.     END IF
  2066.     game.tstart = game.tend
  2067.     game.fpscoef = stav.fps / game.fpsactual
  2068.  
  2069. '----------------------------------------------------------------------------------------------------------------------------------------------------
  2070. SUB DisplayMessages
  2071.     IF game.msgcount > 0 THEN 'refresh messages validity
  2072.         FOR i = 1 TO game.msgcount
  2073.             IF ((TIMER(.001) - msg(i).time_start) > msg(i).time_dur) AND msg(i).time_dur > 0 THEN DeleteMessage (i)
  2074.         NEXT i
  2075.     END IF
  2076.     LOCATE 3, 1
  2077.     IF game.msgcount > 0 THEN 'print messages
  2078.         FOR i = 1 TO game.msgcount
  2079.             COLOR msg(i).col
  2080.             PRINT RTRIM$(msg(i).text)
  2081.         NEXT i
  2082.     END IF
  2083.  
  2084. '----------------------------------------------------------------------------------------------------------------------------------------------------
  2085. SUB AddMessage (mtext AS STRING, mcol AS INTEGER, mdur AS SINGLE, mdist AS INTEGER)
  2086.     IF LEFT$(mtext, 1) = "/" THEN
  2087.         TextCommand mtext
  2088.     ELSE
  2089.         IF mdur <> 0 THEN
  2090.             IF game.msgcount >= MSG_COUNT_MAX THEN DeleteMessage (1) 'delete last message if full
  2091.             game.msgcount = game.msgcount + 1
  2092.             msg(game.msgcount).clientid = game.clientid
  2093.             msg(game.msgcount).text = mtext
  2094.             msg(game.msgcount).col = mcol
  2095.             msg(game.msgcount).time_dur = mdur
  2096.             msg(game.msgcount).time_start = TIMER(.001)
  2097.             msg(game.msgcount).syncstr = "SNM"
  2098.             msg(game.msgcount).synctime = 0
  2099.             msg(game.msgcount).distribute = mdist
  2100.             IF mdist = 1 THEN game.newmsg = 1
  2101.         END IF
  2102.     END IF
  2103.  
  2104. '----------------------------------------------------------------------------------------------------------------------------------------------------
  2105. SUB DeleteMessage (mid AS INTEGER)
  2106.     IF mid < game.msgcount AND mid > 0 THEN
  2107.         FOR i = mid TO game.msgcount - 1
  2108.             msg(i) = msg(i + 1)
  2109.         NEXT i
  2110.     END IF
  2111.     game.msgcount = game.msgcount - 1
  2112.  
  2113. '----------------------------------------------------------------------------------------------------------------------------------------------------
  2114. SUB TextCommand (ctext AS STRING)
  2115.     SELECT CASE LEFT$(RTRIM$(ctext), 2)
  2116.         CASE "/q" 'end network game
  2117.             IF game.hosth <> 0 AND stav.gameplay = 1 THEN
  2118.                 stav.koniec_kola = 2
  2119.                 AddMessage "The match has been ended by the host", MSG_COL, MSG_DUR_STD, 1
  2120.             END IF
  2121.             IF game.clienth <> 0 AND stav.gameplay = 1 THEN
  2122.                 stav.koniec_kola = 2
  2123.                 ResetNetGame
  2124.             END IF
  2125.         CASE "/d" 'disconnet client clidx
  2126.             clidx = VAL(MID$(RTRIM$(ctext), 3, LEN(RTRIM$(ctext)) - 2))
  2127.             IF game.hosth <> 0 AND clidx > 1 AND clidx <= PLAYER_NET_MAX THEN
  2128.                 IF client(clidx).conn <> 0 THEN
  2129.                     CloseClientConn clidx
  2130.                     AddMessage "Player " + RTRIM$(hrac(clidx).meno) + " was disconnected by host", MSG_COL, MSG_DUR_STD, 1
  2131.                 END IF
  2132.             END IF
  2133.     END SELECT
  2134.  
  2135. '----------------------------------------------------------------------------------------------------------------------------------------------------
  2136. SUB DebugScreen (K AS INTEGER) 'print debyg information on screen in runtime
  2137.     COLOR 7
  2138.     LOCATE INT((stav.pocethracov - 0.5) / 4) + 2, 1
  2139.     PRINT "FPS:   "; game.fpsactual
  2140.  
  2141.     IF K = 101 THEN stav.energydec = -(stav.energydec = 0) * ENERGY_DEC
  2142.     IF K = 113 THEN
  2143.         bal(hrac(2).bal).strat = bal(hrac(2).bal).strat + 1
  2144.         IF bal(hrac(2).bal).strat > UBOUND(strat) THEN
  2145.             bal(hrac(2).bal).strat = 1
  2146.         END IF
  2147.     END IF
  2148.     COLOR 13
  2149.     PRINT "hrac(n)..isleft   "; klav(hrac(1).klavesy).isleft; klav(hrac(2).klavesy).isleft; klav(hrac(3).klavesy).isleft; klav(hrac(4).klavesy).isleft
  2150.     PRINT "hrac(n)..isright  "; klav(hrac(1).klavesy).isright; klav(hrac(2).klavesy).isright; klav(hrac(3).klavesy).isright; klav(hrac(4).klavesy).isright
  2151.     PRINT "hrac(n)..isdown   "; klav(hrac(1).klavesy).isdown; klav(hrac(2).klavesy).isdown; klav(hrac(3).klavesy).isdown; klav(hrac(4).klavesy).isdown
  2152.     PRINT "hrac(n)..isup     "; klav(hrac(1).klavesy).isup; klav(hrac(2).klavesy).isup; klav(hrac(3).klavesy).isup; klav(hrac(4).klavesy).isup
  2153.     PRINT "bal(2).vi        "; bal(hrac(2).bal).vi.x; bal(hrac(2).bal).vi.y
  2154.     PRINT "bal(3).vi        "; bal(hrac(3).bal).vi.x; bal(hrac(3).bal).vi.y
  2155.     PRINT "bal(4).vi        "; bal(hrac(4).bal).vi.x; bal(hrac(4).bal).vi.y
  2156.     PRINT "bal(2).strat     "; bal(2).strat
  2157.     PRINT "bal(2).klucka_time    "; bal(hrac(2).bal).klucka_time
  2158.     PRINT "bal(2).klucka_pocet   "; bal(hrac(2).bal).klucka_pocet
  2159.     PRINT "bal(2).klucka_trvanie "; bal(hrac(2).bal).klucka_trvanie
  2160.     PRINT "bal(2).klucka_uhol    "; bal(hrac(2).bal).klucka_uhol
  2161.     PRINT "bal(n).protivnik      "; bal(1).protivnik; bal(2).protivnik; bal(3).protivnik
  2162.     PRINT "bal(n).complayer      "; bal(1).protivnik; bal(2).protivnik; bal(3).protivnik
  2163.     PRINT "stav.baljeto          "; stav.baljeto
  2164.     PRINT "stav.koniec_kola      "; stav.koniec_kola
  2165.     PRINT "nearestPlayer(1)      "; nearestPlayer(bal(1), 0, 1)
  2166.     PRINT "bal(n).reactdrop_time _dur "; bal(2).reactdrop_time; bal(2).reactdrop_dur
  2167.     PRINT "bal(1).v              "; bal(1).v.x; bal(1).v.y
  2168.     PRINT "bal(1).a              "; bal(1).a.x; bal(1).a.y
  2169.     PRINT "bal(2).boostintended  "; bal(2).boostintended
  2170.     PRINT "bal(2).boost_time     "; bal(1).boost_time
  2171.     PRINT "bal(2).boost_trvanie  "; bal(1).boost_trvanie
  2172.     PRINT "bal(n).hrac           "; bal(1).hrac; bal(2).hrac; bal(3).hrac; bal(4).hrac
  2173.     PRINT "bal(1).syncstr        "; bal(1).syncstr
  2174.     PRINT "game.autostart_time   "; game.autostart_time
  2175.     PRINT "stav.autostart_set    "; stav.autostart_set
  2176.     PRINT "TIMER                 "; TIMER
  2177.     PRINT "client(n).conn"; client(1).conn; client(2).conn; client(3).conn; client(4).conn
  2178.     PRINT "hrac(n).klavesy"; hrac(1).klavesy; hrac(2).klavesy; hrac(3).klavesy; hrac(4).klavesy; hrac(10).klavesy
  2179.     PRINT "klav(hrac(n)klavesy).typ"; klav(hrac(1).klavesy).typ; klav(hrac(2).klavesy).typ; klav(hrac(3).klavesy).typ; klav(hrac(4).klavesy).typ; klav(hrac(10).klavesy).typ
  2180.     PRINT "game.sync_stats         "; game.sync_stats
  2181.  
  2182. '----------------------------------------------------------------------------------------------------------------------------------------------------
  2183.  
  2184.  


Game description:
The aim is simple - do not allow to get tagged. Tagged player loses energy. If you get tagged, tag someone else as quickly as possible. When you are out of energy, you are out of the game round. Win 3 rounds to win the whole match.

Network game:
Host player chooses "Host game" from the main menu. Other players launch the game on their computers,  choose "Join game" from main menu and input the IP address (or URL) of the computer with the host game running.
Player 1 is allways assigned to the host. Other players can be joined client players, other local players on host computer or AI players.

Control keys during the match:
P - pause the game
B - enter debug mode
E - enable/disable energy decreasing (only in debug mode)
<Esc> - quit the game (only if not in network game mode)
T - write text message to other players (only while hosting or joining a network session)
T/q - quit the game (only if hosting or joining a network session)
T/d2 - disconnect player 2 from session (only if hosting a network session)

8
Programs / Re: Convert mouse input to DRAW
« on: January 25, 2020, 03:04:55 pm »
...so here is the test code for Toolbox SUB Smooth testing with single mouse clicks

bplus, that was exactly what i meant, but why doesn't your code smooth the curve? Or it does just very slightly and very close to the points itself? Here's  smoothed 4 point curve that is more like rectange. Also, can I make lines thin in your demo?

STxAxTIC, you are right, when I move the mouse very quickly, the points are further from each other and smoothenes is more obvious then. But I was curious about the same as bplus, how would it curve a few separately clicked points.

9
Programs / Re: Convert mouse input to DRAW
« on: January 25, 2020, 01:05:22 pm »
There's not much difference between unsmoothed and smoothed curve, when your mouse move scans so many points. If I was allowed only click a few points, then the additional smoothing would stand out much more. Anyway, inspiring, thanks.

10
Programs / Re: Ectoplasm
« on: January 21, 2020, 12:13:34 pm »
@bplus, thanks for clarification, I'm not going to pretend I understood :o) anyway, the RND part tells me, there wouldn't be any regular pattern repeating.

11
Programs / Re: One page clock
« on: January 21, 2020, 05:49:18 am »
@bplus, awesome plasma, like the 3D shader effect a lot. Does the pattern repeat after a while, or it is completley random/fractaloid? I don't know a lot about this kind of math.

12
Programs / Re: DrawFrame - animation sub using DRAW
« on: January 21, 2020, 04:59:08 am »
what do you mean in specific?

TempodiBasic, bingo! Of course TA works with decimals, thanks a lot for pointing that out.  I tried and gave up, but now I realize I have probbably tried with such small numbers, that I have been feeding TA parameter with exponential number format and the DRAW went crazy.
I have fix that now, and the tree limbs swinging is WAY smoother, it is especially noticable in slow motion speeds.

And as a bonus, here's a new short clip with dog, I'll be teaching him new tricks, eventually:

Code: QB64: [Select]
  1.  
  2. '----------------------------------------------------------------------------------------------------------------------------------------------------
  3. ' The Tree string
  4. '----------------------------------------------------------------------------------------------------------------------------------------------------
  5. leaf1$ = "Q1:17;* (V30 K11:17;17.5 S1%;!40% K11:17.5;19 S!40%;50% V-90 K12 V-10;10 U50 V-800U20 V30U20 V30U20 V20U40 V20U40 V20U50 V100U50 V20U40 V20U40 V20U20 V30U20 V30U20 V-800 K12 U50;47 V180 K12 V10;-10 V90 V-30 S100%)"
  6. smallimb2$ = "Q2:7;* (V-90 K22:7;14 S1%;100% U100 K23:40;44 BM+0,+0;-4000,-100 K12:22;22.2# Q1 K23 BM+0,+0;+4000,+100 K22 S1%;100% U200 K23:47;49 BM+0,+0;-4000,-100 K12:22.1;22.3# Q1 K23 BM+0,+0;+4000,+100 K22 S1%;100% U100 V90 U10 V90 V-90 K23:49;51 BM+0,+0;-4000,-100 K12:22.2;22.4# Q1 K23 BM+0,+0;+4000,+100 K22 S1%;100% V90 U200 V-60 K23:49.5;51.5 BM+0,+0;-4000,-100 K12:22.3;22.5# Q1 K23 BM+0,+0;+4000,+100 K22 S1%;100% V60 U200 V-90 S100%)"
  7. biglimb3$ = "Q3:4;* (V-88 K31:4.0;11 S1%;100% U250 K32:25;25.4# V30;50 Q2 K32 V-30;-50 K31 S1%;100% U200 V88 K33:25.1;25.5# V-35;-15 Q2 K33 V35;15 V88 K34:25.2;25.6# V-40;-20 Q2 K34 V40;20 K31 S1%;100% U450 V92 V-180 S100%)"
  8. trunk4$ = "Q4 (K41:0;10 S1%;100% U500 K42:28.9;29.3# V30;40 Q3 K42 V-30;-40 K41 S1%;100% U400 V88 K43:29;29.4# V0;5 Q3 K43 V0;-5 V88 K41 S1%;100% U200 K44:29.1;29.5# V-30;-20 Q3 K44 V30;20 K41 S1%;100% M+0,+0;-10,-10 K45:17;17.6 M+0,+0;-25,-20 U700 V92 V92 S100%)"
  9. cloud5$ = "Q51:17; (Q5*8(U30-V30) S150% V200 Q5*6 S130% V230 Q5*6 S120% V210 Q5*8 S160% V220 Q5*6 S160% V235 Q5*6) S2"
  10. clip$ = "S2 BM1200,1000" + leaf1$ + smallimb2$ + biglimb3$ + "K1:0;10#C35;52 L400 K101:24.9;25.3# M-3,-0;+3,+0 " + trunk4$ + " K101 M+3,+0;-3,-0 M910,1000 L400 K102:17;23 BM2500,50;1400,100 TA90 K51:0;0.3# S2;2.05 " + cloud5$ + " TA0 K103:20;30 BM0,0 BM-800,+100;+500,+300 TA90 K51:0;0.3# S3;3.05 Q51"
  11.  
  12. '----------------------------------------------------------------------------------------------------------------------------------------------------
  13. ' Examples of clip strings
  14. '----------------------------------------------------------------------------------------------------------------------------------------------------
  15. 'clip$ = "BM500,300 Q1*12( U20 V30 )" '1 circle
  16. 'clip$ = "B M500,300 Q2*6( BU100 Q1*12( U20 V30 ) BD100 V60 )" '6 circles queued in round
  17. 'clip$ = "B M500,300 K1:0;3# V0;360 Q2*6( BU50 Q1*12( U10 V30 ) BD50 V60 )" '6 circles queued in round rotating
  18. 'clip$ = "B M500,300 K1:0;3* V0;360 Q2*6( K2:0;2# BU50;200 Q1*12( U10 V30 ) BD50;200 V60 )" '6 circles queued in round rotating and swingigng towards centre
  19. 'clip$ = "B M500,300 K2:0;2# K1:0;3* V0;360 Q2*6( K2_2:+0.2;+0.2# BU50;200 Q1*12( U10 V30 ) BD50;200 V60 )" '6 circles queued in round rotating and swingigng towards centre in different phase
  20. 'clip$ = "B M500,300 K2:0;1# K1:0;3* V0;360 Q2*6( K2_2:+0.2;+0.2# BU50;200 S100%;300% Q1*12( U10 V30 ) S100% BD50;200 V60 )" '6 circles queued in round rotating and swingigng towards centre in different phase changing size
  21.  
  22. '----------------------------------------------------------------------------------------------------------------------------------------------------
  23. ' The Dog string
  24. '----------------------------------------------------------------------------------------------------------------------------------------------------
  25. ' Q0 - dog positioning
  26. ' Q2 - dog walking
  27. ' Q3 - dog head shape, Q31 - head running
  28. ' Q4 - dog ear shape, Q41 - ear running
  29. ' Q5 - dog tail shape, Q51 - tail running
  30. ' Q7 - dog foot shape, Q71 - foot running
  31.  
  32. clip$ = "S2 BM1900,518 L3500 Q0*(K0:0;10 BM1800,400;300,400 TA0)  Q7*(L40 D20 R40 U20)  Q71*(BM+20,+180 K71_71:-0.5;-0.5* K72_71:+0;-0.5# K71 V0;360 BD40 V360;0 K72 V-10;30 Q7) K41:0;0.25#"+_
  33.         "Q4*(L40M+20,-40M+20,40) Q41*(K41_41:+0.05;+0.05# V-35;15 Q4 V35;-15) " + _
  34.         "Q5*(R50 U40 L50 D40) Q51*(K51:0;0.25#  V10;30 BM+100,-40 Q5)" + _
  35.         "Q3*(BM-20,-110 L200D120R200U120 BM-70,+30 R20D20L20U20 BM-120,-20 R30D30L30U30)  Q31*(K32:4;4.5 V0;50 K33_32:+3;+2.8 V!0;-50 K32 BM+0,0;-50,20 K33 BM+0,0;+50,-20 K31:0;0.25# BD-20;10 Q3 BM+140,-30 Q41 BR60 Q41) "+ _
  36.         "Q2(Q0 K21:-0.125;0.125# BU0;40 D150R250U150L250 BM+200,+70 Q51 K71:0;1* Q0 Q71 Q0 Q71 Q0BM+250,0 Q71 Q0BM+250,+0 Q71 Q0 Q31)"
  37.  
  38. '----------------------------------------------------------------------------------------------------------------------------------------------------
  39. SCREEN _NEWIMAGE(1920, 1080, 256)
  40.  
  41. DrawPlayer clip$, 0, 60, 30, _WIDTH / 1920, 1
  42.  
  43. '----------------------------------------------------------------------------------------------------------------------------------------------------
  44. 'Player demonstration
  45. '----------------------------------------------------------------------------------------------------------------------------------------------------
  46. SUB DrawPlayer (movie$, playfromtime, playtotime, fps, size, speed)
  47.     t = playfromtime * fps
  48.     dir = 1
  49.     DO
  50.         CLS
  51.         _PRINTSTRING (0, 5), "size:" + STR$(RoundDec(size, 2)) + "   speed:" + STR$(dir * speed) + "x  time:" + STR$(RoundDec(t / fps * speed, 2))
  52.         DrawFrame movie$, t / fps * speed, size
  53.         IF k = 32 THEN SLEEP: k = _KEYHIT: k = _KEYHIT
  54.         IF k = 20480 AND speed > 0.1 THEN speed = speed / 2: t = t * 2
  55.         IF k = 18432 AND speed < 100 THEN speed = speed * 2: t = t / 2
  56.         IF k = 19200 THEN t = t - 2 * fps
  57.         IF k = 19712 THEN t = t + 2 * fps
  58.         IF k = 43 THEN size = size + 0.01
  59.         IF k = 45 THEN size = size - 0.01
  60.         IF k = 114 THEN dir = -dir
  61.         t = t + dir
  62.         IF size > 10 THEN size = 10
  63.         IF size < 0.01 THEN size = 0.01
  64.         IF t > playtotime * fps / speed THEN t = playtotime * fps / speed
  65.         IF t < 0 THEN t = 0
  66.         k = _KEYHIT
  67.         _DISPLAY
  68.         _LIMIT fps
  69.     LOOP UNTIL _KEYDOWN(27)
  70.  
  71. '----------------------------------------------------------------------------------------------------------------------------------------------------
  72. 'Sub & Function definitions
  73. '----------------------------------------------------------------------------------------------------------------------------------------------------
  74. SUB DrawFrame (SrcStrOrig AS STRING, frametime AS SINGLE, size AS SINGLE)
  75.  
  76.     CONST CMD_LEN_MAX = 1000 'max. command sequence length definable using statement Q()
  77.  
  78.     TYPE TKFset 'Key frame set type
  79.         id AS INTEGER
  80.         defined AS _BYTE
  81.         timestart AS SINGLE
  82.         timeend AS SINGLE
  83.         repeat AS STRING * 1
  84.         repeatcount AS INTEGER
  85.     END TYPE
  86.  
  87.     TYPE TCmdSeq 'Command Sequence
  88.         id AS INTEGER
  89.         CmdStr AS STRING * CMD_LEN_MAX
  90.         defined AS _BYTE
  91.         startpos AS LONG
  92.         endpos AS LONG
  93.         timestart AS SINGLE
  94.         timeend AS SINGLE
  95.         repeatcount AS INTEGER
  96.     END TYPE
  97.  
  98.     TYPE TDrawState 'global Draw state
  99.         SrcLen AS LONG 'Source string length
  100.         SrcPos AS LONG 'Source string last read char position
  101.         ActKFSetIdx AS INTEGER 'KFset index applied to actual statement if KF enabled
  102.         ActTA AS SINGLE 'Actual parameter value of previous TA statement (in degrees)
  103.         ActS AS SINGLE 'Actual parameter value of previous "S" statement usage
  104.         ErrDsc AS STRING * 50 'Error description
  105.     END TYPE
  106.  
  107.     DIM KFset(0 TO 999) AS TKFset
  108.     DIM CmdSeq(0 TO 99) AS TCmdSeq
  109.     DIM DS AS TDrawState
  110.     DIM char AS STRING * 1
  111.     DIM prevchar AS STRING * 1
  112.     DIM TrgStr AS STRING
  113.     DIM c$, code$, label$, x1$, y1$, x2$, y2$, sgnx1$, sgny1$, rep$, repcnt$, par$, exclfrom$, exclto$, csstart$, percx1$, percx2$
  114.     DIM x AS SINGLE, y AS SINGLE, x1 AS SINGLE, y1 AS SINGLE, x2 AS SINGLE, y2 AS SINGLE, kid AS INTEGER, csid AS INTEGER
  115.     DIM readstate AS _BYTE
  116.     DIM stat$, ParseStatement$ ' Actual statement being read from source draw string
  117.     DIM SrcStr AS STRING
  118.  
  119.     SrcStr = SrcStrOrig
  120.     TrgStr = ""
  121.     stat$ = ""
  122.     prevchar = ""
  123.     SrcStr = SrcStr + "&"
  124.     DS.SrcLen = LEN(SrcStr)
  125.     DS.SrcPos = 0
  126.     DS.ActKFSetIdx = 0
  127.     DS.ActTA = 0
  128.     DS.ActS = 4
  129.  
  130.     DO 'read statement
  131.         DS.SrcPos = DS.SrcPos + 1
  132.         char = MID$(SrcStr, DS.SrcPos, 1)
  133.         IF (ASC(char) >= 64 AND ASC(char) <= 90 AND NOT (char = "A" AND prevchar = "T")) OR char = "&" THEN
  134.             '-------------------------------------------Parser begin-----------------------------------------------------------
  135.             stat$ = stat$ + "&"
  136.             ParseStatement$ = ""
  137.             readstate = 0
  138.             KFenabled = 0
  139.             omitstate = 0
  140.             par$ = "": code$ = "": label$ = "": x1$ = "": y1$ = "": x2$ = "": y2$ = "": sgnx1$ = "": sgny1$ = "": sgnx2$ = ""
  141.             rep$ = "": repcnt$ = "": par$ = "": exclfrom$ = "": exclto$ = "": csstart$ = "": percx1$ = "": percx2$ = "": rel$ = "": krel$ = ""
  142.             x = 0: y = 0: x1 = 0: y1 = 0: x2 = 0: y2 = 0: kid = 0: csid = 0
  143.  
  144.             FOR i = 1 TO LEN(stat$)
  145.                 c$ = MID$(stat$, i, 1)
  146.                 SELECT CASE readstate
  147.                     CASE 0:
  148.                         SELECT CASE c$
  149.                             CASE "A" TO "Z":
  150.                                 code$ = code$ + c$
  151.                             CASE "_":
  152.                                 label$ = par$: par$ = "": rel$ = c$: readstate = 11
  153.                             CASE ":":
  154.                                 label$ = par$: par$ = "": readstate = 1
  155.                             CASE ",":
  156.                                 x1$ = par$: par$ = "": readstate = 2
  157.                             CASE ";":
  158.                                 x1$ = par$: par$ = "": readstate = 3
  159.                                 KFenabled = 1
  160.                             CASE "!":
  161.                                 exclfrom$ = c$
  162.                             CASE "+", "-":
  163.                                 par$ = par$ + c$
  164.                                 sgnx1$ = c$
  165.                             CASE "0" TO "9", ".":
  166.                                 par$ = par$ + c$
  167.                             CASE "%":
  168.                                 percx1$ = percx1$ + c$
  169.                             CASE "*":
  170.                                 label$ = par$: par$ = "": rep$ = c$: readstate = 5
  171.                             CASE "(":
  172.                                 label$ = par$: csstart$ = c$: readstate = 10
  173.                             CASE "&", ")":
  174.                                 x1$ = par$: par$ = "": readstate = 10
  175.                             CASE ELSE: readstate = 99
  176.                         END SELECT
  177.                     CASE 11:
  178.                         SELECT CASE c$
  179.                             CASE "0" TO "9":
  180.                                 par$ = par$ + c$
  181.                             CASE ":":
  182.                                 krel$ = par$: par$ = "": readstate = 1
  183.                             CASE ELSE: readstate = 99
  184.                         END SELECT
  185.                     CASE 1:
  186.                         SELECT CASE c$
  187.                             CASE ",":
  188.                                 x1$ = par$: par$ = "": readstate = 2
  189.                             CASE ";":
  190.                                 x1$ = par$: par$ = "": readstate = 3
  191.                                 KFenabled = 1
  192.                             CASE "!":
  193.                                 exclfrom$ = c$
  194.                             CASE "+", "-":
  195.                                 par$ = par$ + c$
  196.                                 sgnx1$ = c$
  197.                             CASE "0" TO "9", ".":
  198.                                 par$ = par$ + c$
  199.                             CASE "%":
  200.                                 percx1$ = percx1$ + c$
  201.                             CASE "(":
  202.                                 x1$ = par$: csstart$ = c$: readstate = 10
  203.                             CASE "&", ")":
  204.                                 x1$ = par$: par$ = "": readstate = 10
  205.                             CASE ELSE: readstate = 99
  206.                         END SELECT
  207.                     CASE 2:
  208.                         SELECT CASE c$
  209.                             CASE ";":
  210.                                 y1$ = par$: par$ = "": readstate = 3
  211.                                 KFenabled = 1
  212.                             CASE "+", "-":
  213.                                 par$ = par$ + c$
  214.                                 sgny1$ = c$
  215.                             CASE "0" TO "9", ".":
  216.                                 par$ = par$ + c$
  217.                             CASE "&", ")":
  218.                                 y1$ = par$: par$ = "": readstate = 10
  219.                             CASE ELSE: readstate = 99
  220.                         END SELECT
  221.                     CASE 3:
  222.                         SELECT CASE c$
  223.                             CASE ",":
  224.                                 x2$ = par$: par$ = "": readstate = 4
  225.                             CASE "#":
  226.                                 x2$ = par$: par$ = "": rep$ = c$: readstate = 5
  227.                             CASE "*":
  228.                                 x2$ = par$: par$ = "": rep$ = c$: readstate = 5
  229.                             CASE "!":
  230.                                 exclto$ = c$
  231.                             CASE "+", "-":
  232.                                 par$ = par$ + c$
  233.                                 sgnx2$ = c$
  234.                             CASE "0" TO "9", ".":
  235.                                 par$ = par$ + c$
  236.                             CASE "%":
  237.                                 percx2$ = percx2$ + c$
  238.                             CASE "(":
  239.                                 x2$ = par$: csstart$ = c$: readstate = 10
  240.                             CASE "&", ")":
  241.                                 x2$ = par$: par$ = "": readstate = 10
  242.                             CASE ELSE: readstate = 99
  243.                         END SELECT
  244.                     CASE 4:
  245.                         SELECT CASE c$
  246.                             CASE "#":
  247.                                 y2$ = par$: par$ = "": rep$ = c$: readstate = 5
  248.                             CASE "*":
  249.                                 y2$ = par$: par$ = "": rep$ = c$: readstate = 5
  250.                             CASE "0" TO "9", "+", "-", ".":
  251.                                 par$ = par$ + c$
  252.                             CASE "&", ")":
  253.                                 y2$ = par$: par$ = "": readstate = 10
  254.                             CASE ELSE: readstate = 99
  255.                         END SELECT
  256.                     CASE 5:
  257.                         SELECT CASE c$
  258.                             CASE "0" TO "9", "+", "-", ".":
  259.                                 par$ = par$ + c$
  260.                             CASE "(":
  261.                                 repcnt$ = par$: par$ = "": csstart$ = c$: readstate = 10
  262.                             CASE "&", ")":
  263.                                 repcnt$ = par$: par$ = "": readstate = 10
  264.                             CASE ELSE: readstate = 99
  265.                         END SELECT
  266.                 END SELECT
  267.             NEXT i
  268.  
  269.             IF readstate = 99 THEN DS.ErrDsc = "Error in statement: " + LEFT$(stat$, LEN(stat$) - 1) ELSE DS.ErrDsc = ""
  270.             IF code$ = "K" THEN
  271.                 IF x2$ <> "" THEN ' defining KFset
  272.                     tsdelta = 0: tedelta = 0
  273.                     kid = VAL(label$)
  274.                     KFset(kid).id = kid
  275.                     KFset(kid).defined = 1
  276.                     IF krel$ <> "" THEN
  277.                         krel = VAL(krel$)
  278.                         IF sgnx1$ <> "" THEN tsdelta = KFset(krel).timestart
  279.                         IF sgnx2$ <> "" THEN tedelta = KFset(krel).timeend
  280.                     END IF
  281.                     KFset(kid).timestart = VAL(x1$) + tsdelta
  282.                     KFset(kid).timeend = VAL(x2$) + tedelta
  283.                     KFset(kid).repeat = rep$
  284.                     KFset(kid).repeatcount = VAL(repcnt$)
  285.                     DS.ActKFSetIdx = kid
  286.                 ELSE ' referencing KFset
  287.                     IF label$ = "" AND x1$ <> "" THEN label$ = x1$
  288.                     kid = VAL(label$)
  289.                     DS.ActKFSetIdx = kid
  290.                 END IF
  291.  
  292.             ELSEIF code$ = "Q" THEN
  293.                 IF x1$ <> "" OR x2$ <> "" AND label$ <> "" THEN
  294.                     csid = VAL(label$)
  295.                     CmdSeq(csid).timestart = VAL(x1$)
  296.                     CmdSeq(csid).timeend = VAL(x2$)
  297.                 END IF
  298.                 IF label$ = "" AND x1$ <> "" AND x2$ = "" THEN label$ = x1$
  299.                 csid = VAL(label$)
  300.                 CmdSeq(csid).id = csid
  301.                 IF repcnt$ <> "" THEN CmdSeq(csid).repeatcount = VAL(repcnt$)
  302.  
  303.                 ipos = 0
  304.                 IF csstart$ = "(" THEN ' defining command sequence
  305.                     parcnt = 1: c$ = ""
  306.                     DO ' Find corresponding right parenthes in the source string
  307.                         ipos = ipos + 1
  308.                         c$ = MID$(SrcStr$, DS.SrcPos + ipos, 1)
  309.                         IF c$ = "(" THEN parcnt = parcnt + 1
  310.                         IF c$ = ")" THEN parcnt = parcnt - 1
  311.                     LOOP UNTIL (c$ = ")" AND parcnt = 0) OR DS.SrcPos + ipos >= DS.SrcLen OR ipos >= CMD_LEN_MAX
  312.                     IF (c$ = ")" AND parcnt = 0) THEN
  313.                         CmdSeq(csid).CmdStr = MID$(SrcStr, DS.SrcPos, ipos)
  314.                         CmdSeq(csid).defined = 1
  315.                     ELSE
  316.                         CmdSeq(csid).defined = 0
  317.                     END IF
  318.                 ELSE 'Referencing command sequence
  319.                 END IF
  320.  
  321.                 IF CmdSeq(csid).defined = 1 THEN 'modify source string if command sequence defined
  322.                     IF CmdSeq(csid).repeatcount > 0 THEN
  323.                         rpt = CmdSeq(csid).repeatcount
  324.                     ELSEIF rep$ = "*" THEN
  325.                         rpt = 0
  326.                     ELSE
  327.                         rpt = 1
  328.                     END IF
  329.                     IF CmdSeq(csid).timeend <> 0 AND (frametime < CmdSeq(csid).timestart OR frametime > CmdSeq(csid).timeend) THEN rpt = 0
  330.                     IF frametime < CmdSeq(csid).timestart THEN rpt = 0
  331.                     cmdrpt$ = ""
  332.                     FOR i = 1 TO rpt: cmdrpt$ = cmdrpt$ + RTRIM$(CmdSeq(csid).CmdStr): NEXT i
  333.                     SrcStr = RTRIM$(cmdrpt$) + RIGHT$(SrcStr, DS.SrcLen - DS.SrcPos - ipos + 1)
  334.                     DS.SrcLen = LEN(SrcStr)
  335.                     DS.SrcPos = 0
  336.                     char = ""
  337.                 END IF
  338.  
  339.             ELSE 'do for other graphics statements
  340.                 x1 = VAL(x1$): y1 = VAL(y1$): x2 = VAL(x2$): y2 = VAL(y2$)
  341.                 kid = DS.ActKFSetIdx
  342.                 IF KFenabled = 1 AND KFset(kid).defined = 1 THEN 'change parameters if statement is keyframed
  343.                     fk = (frametime - KFset(kid).timestart) / (KFset(kid).timeend - KFset(kid).timestart)
  344.                     IF (frametime >= KFset(kid).timestart AND frametime <= KFset(kid).timeend) THEN
  345.                         IF x1$ <> "" THEN x1 = x1 + (x2 - x1) * fk
  346.                         IF y1$ <> "" THEN y1 = y1 + (y2 - y1) * fk
  347.                     ELSEIF (frametime > KFset(kid).timeend AND exclto$ <> "!") THEN
  348.                         period = INT((frametime - KFset(kid).timestart) / (KFset(kid).timeend - KFset(kid).timestart))
  349.                         IF (KFset(kid).repeat = "*" OR KFset(kid).repeat = "#") AND (period < KFset(kid).repeatcount OR KFset(kid).repeatcount = 0) THEN
  350.                             IF KFset(kid).repeat = "#" AND period MOD 2 = 1 THEN
  351.                                 fk = (KFset(kid).timeend - frametime + period * (KFset(kid).timeend - KFset(kid).timestart)) / (KFset(kid).timeend - KFset(kid).timestart)
  352.                             ELSE
  353.                                 fk = (frametime - KFset(kid).timestart - period * (KFset(kid).timeend - KFset(kid).timestart)) / (KFset(kid).timeend - KFset(kid).timestart)
  354.                             END IF
  355.                             IF x1$ <> "" THEN x1 = x1 + (x2 - x1) * fk
  356.                             IF y1$ <> "" THEN y1 = y1 + (y2 - y1) * fk
  357.                         ELSE
  358.                             IF KFset(kid).repeat = "#" AND KFset(kid).repeatcount MOD 2 = 0 THEN
  359.                                 IF x1$ <> "" THEN x1 = x1
  360.                                 IF y1$ <> "" THEN y1 = y1
  361.                             ELSE
  362.                                 IF x1$ <> "" THEN x1 = x2
  363.                                 IF y1$ <> "" THEN y1 = y2
  364.                             END IF
  365.                         END IF
  366.                     ELSEIF (frametime < KFset(kid).timestart AND exclfrom$ <> "!") THEN
  367.                         omitstate = 0
  368.                     ELSE
  369.                         omitstate = 1
  370.                     END IF
  371.                 END IF
  372.                 IF omitstate = 0 THEN
  373.                     SELECT CASE code$
  374.                         CASE "T", "TA":
  375.                             x1 = RoundDec(x1, 6)
  376.                             DS.ActTA = x1
  377.                             IF (DS.ActTA > 360) OR (DS.ActTA < -360) THEN DS.ActTA = DS.ActTA + (DS.ActTA > 0) * 360
  378.                         CASE "V":
  379.                             DS.ActTA = DS.ActTA + RoundDec(x1, 6)
  380.                             IF (DS.ActTA > 360) OR (DS.ActTA < -360) THEN DS.ActTA = DS.ActTA + (DS.ActTA > 0) * 360
  381.                             code$ = "TA"
  382.                             x1 = RoundDec(DS.ActTA, 6)
  383.                         CASE "C":
  384.                             x1 = _ROUND(x1)
  385.                         CASE "M", "D", "E", "F", "G", "H", "L", "R", "U":
  386.                             x1 = RoundDec(x1 * size, 4)
  387.                             y1 = RoundDec(y1 * size, 4)
  388.                         CASE "S":
  389.                             IF percx1$ <> "" OR percx2$ <> "" THEN
  390.                                 x1 = RoundDec(x1 * DS.ActS / 100, 5)
  391.                                 IF x1 > 8 THEN x1 = 8
  392.                             ELSE
  393.                                 DS.ActS = x1
  394.                             END IF
  395.                     END SELECT
  396.                     IF sgnx1$ <> "" AND x1 < 0 THEN sgnx1$ = ""
  397.                     IF sgnx1$ <> "" AND x1 > 0 THEN sgnx1$ = "+"
  398.                     IF sgny1$ <> "" AND y1 < 0 THEN sgny1$ = ""
  399.                     IF sgny1$ <> "" AND y1 > 0 THEN sgny1$ = "+"
  400.                     ParseStatement$ = code$
  401.                     IF x1$ <> "" THEN
  402.                         ParseStatement$ = ParseStatement$ + sgnx1$ + LTRIM$(STR$(x1))
  403.                         IF y1$ <> "" THEN ParseStatement$ = ParseStatement$ + "," + sgny1$ + LTRIM$(STR$(y1))
  404.                     END IF
  405.                 ELSE
  406.                     ParseStatement$ = ""
  407.                 END IF
  408.             END IF
  409.  
  410.             ''---DEBUG BEGIN-----------
  411.             'IF CmdSeq(csid).defined = 1 THEN cmd$ = RTRIM$(CmdSeq(csid).CmdStr) ELSE cmd$ = ""
  412.             'PRINT
  413.             'PRINT stat$ + " > ", , code$ + "/" + label$ + "/" + x1$ + "/" + y1$ + "/" + x2$ + "/" + y2$ + "/" + exclfrom$ + "/" + exclto$ + "/" + rep$ + "/" + repcnt$
  414.             'PRINT "TrgStr: "; TrgStr
  415.             'PRINT "SrcStr: "; SrcStr
  416.             'PRINT "cmd$: ", cmd$
  417.             'PRINT "DS.Srcpos", DS.SrcPos
  418.             'PRINT "ParseStatement$: ", ParseStatement$
  419.             'IF stat$ = "Q1*(&" OR stat$ = "Q1(&" THEN stopable = 1
  420.             'IF stopable THEN
  421.             '    DO
  422.             '    LOOP UNTIL _KEYHIT = 32
  423.             'END IF
  424.             ''---DEBUG END-------------
  425.  
  426.             '-------------------------------------------Parser end-----------------------------------------------------------
  427.             TrgStr = TrgStr + ParseStatement$
  428.             IF LTRIM$(DS.ErrDsc) <> "" THEN PRINT RTRIM$(DS.ErrDsc) + " at position:" + STR$(DS.SrcPos - LEN(stat$))
  429.             stat$ = ""
  430.         END IF
  431.         IF char <> " " THEN
  432.             stat$ = stat$ + char
  433.         END IF
  434.         prevchar = char
  435.     LOOP WHILE DS.SrcPos < DS.SrcLen
  436.  
  437.     DRAW TrgStr
  438.  
  439.     'PRINT SrcStr '---DEBUG code----
  440.     'PRINT TrgStr '---DEBUG code----
  441.  
  442. '----------------------------------------------------------------------------------------------------------------------------------------------------
  443. FUNCTION RoundDec (x AS SINGLE, n AS INTEGER)
  444.     RoundDec = _ROUND(x * 10 ^ n) / (10 ^ n)
  445.  
  446. '----------------------------------------------------------------------------------------------------------------------------------------------------
  447.  

13
Programs / Re: DrawFrame - animation sub using DRAW
« on: January 20, 2020, 01:14:02 pm »
@bplus: I see you actualy even did not use the original DRAW there, instead you invented completely new language and treated all graphics by yourself. That is quite an advantage over using DRAW, where some limitations I cannot bypass - e.g.  I can't turn the direction in decimals (TA10.25 doesn't work), which makes turning large object choppy.

@FellippeHeitor> Yes, the "come up with a way" part seems to be critical here :o) The more I'm trying to animate some compoud objects (like with more movable parts relative to each other), the more it reminds of a solving a puzzle in a simplistic language, trying to trick it's limitations, while each solution found is unique and cannot be generalized. So I'm rather skeptical at the moment, waiting for enlightment.

14
Programs / Re: One page clock
« on: January 19, 2020, 01:57:17 pm »
Wow, that looks almost like CRT display grain simulation.

15
Programs / Re: DrawFrame - animation sub using DRAW
« on: January 19, 2020, 12:03:21 pm »
@FellippeHeitor: thanks man, glad to hear that.

@Dimster: That is actualy pretty interesting idea, to add the third dimension to DRAW graphical statement M and also add 2 new directional statements to U, D, L, R for forward and backward direction.  Then the DRAW sub would get the camera position as parameter in addition. Two problems with that anyway: it would be hell of a drawing to create something reasonable = long and comlicated string. Also, the demo clip included in the code above alone completely devastates one CPU core (mainly due to extensive use of strings operations), I could not imagine how would the 3D DRAW manage.

@TempodiBasic: actually, it was my intention, to squeeze the whole movie into one, shortest string possible. This 60 sec. demo clip has 1251 characters (without spaces), it is possible to 7zip it to 661 bytes. And yes, it also came to my mind to build a graphuic GUI, where you could build the string with mouse and keyboard. Long strings are fairly CPU intensive, however, so it is more suitable to use it as single object animation tool in some kind of minigames. I will put an example here some time soon, cause I 'm having an idea yet.

Pages: [1] 2 3