Author Topic: Simple Puzzle Game  (Read 3570 times)

0 Members and 1 Guest are viewing this topic.

Offline MasterGy

  • Seasoned Forum Regular
  • Posts: 327
  • people lie, math never lies
    • View Profile
Simple Puzzle Game
« on: November 17, 2020, 03:14:46 pm »
Hi !
Although I’ve been thinking about a jigsaw puzzle for a long time where parts of the picture are tossed apart and put together, I really liked Bplus’s tangram game and that gave me the inspiration to get started.
I don’t want to give the game a very ornate surface, just that the plot itself is in a cycle. Selectable snow resolution, selectable random speed, launch, program splits, people put together, and starts all over again. The point I am interested in, however, is how to connect things with things, it is no longer so interesting. There is still room for improvement, but you can already try it.
Enter the path to any image in SETTING pic (0) and launch!
When it's done, I'll unload it all at once.




Code: QB64: [Select]
  1. ' ---------------------- SETTINGS --------------------------------------------------------------------------------------------------------------------------
  2. 'bg_file$ = "background2.jpg" 'background picture jpg  ,if bg_file$="" then be a grey background
  3. pic(0) = _LOADIMAGE("puzzle.jpg", 32) 'picture puzzle
  4. puzzle_x = 3
  5. puzzle_y = 3
  6. monx = 800 'resolution X
  7. monrat = 0 'monitor ratio 0=16:9 1=4:3
  8. shuffling_speed_auto = .01
  9.  
  10. '------------------------ ADVANCED SETTING
  11. monpuzzle = 70 'percentage size max puzzle weight in the window
  12. inwindow = 28 'percentage size for windows, auto reposition if tile is over
  13. shuffling_speed = 30
  14. shuffling_rand1 = .5
  15. shuffling_rand2 = .1
  16. shuffling_cycle = 80
  17. puzzle_r = 45 'element rotation scale 90/x
  18. puzzle_b = 4 'black underborder under tiles
  19. puzzle_s = 10 'sens to joint in pixel
  20.  
  21.  
  22. '------------------------------------------------------------------------------------------------------------------------------------------------------------
  23.  
  24.  
  25. 'creating blackunder border
  26.  
  27.  
  28. RANDOMIZE TIMER: puzzle_s2 = puzzle_s ^ 2 'omitting the SQR required for distance measurement ;)
  29. pic(1) = _NEWIMAGE(10, 10, 32): _DEST pic(1): CLS: IF monrat THEN mony = INT(monx / 4 * 3) ELSE mony = INT(monx / 16 * 9)
  30. IF _FILEEXISTS(bg_file$) AND bg_file$ <> "" THEN bg = _LOADIMAGE(bg_file$, 32) ELSE bg = _NEWIMAGE(10, 10, 32): _DEST bg: CLS , _RGB32(30, 30, 30)
  31. mon = _NEWIMAGE(monx, mony, 32): SCREEN mon: _DEST mon: _SOURCE bg: _PUTIMAGE
  32. lwindow_x1 = monx * inwindow / 100: lwindow_x2 = monx - lwindow_x1: lwindow_y1 = mony * inwindow / 100: lwindow_y2 = mony - lwindow_y1
  33.  
  34.  
  35. 'calculating tiles size - ideal placement depending on whether the image is portrait or landscape
  36. psx = INT(monx * monpuzzle / 100): psy = INT(psx / _WIDTH(pic(0)) * _HEIGHT(pic(0))): ptx = psx / puzzle_x / 2: pty = psy / puzzle_y / 2
  37. IF psy > mony * monpuzzle / 100 THEN psy = INT(mony * monpuzzle / 100): psx = INT(psy / _HEIGHT(pic(0)) * _WIDTH(pic(0)))
  38. psxppx = psx / puzzle_x: psyppy = psy / puzzle_y: CONST pip180 = 3.14159265 / 180: wx = (monx - psx) / 2: wy = (mony - psy) / 2: REDIM mp(999, 12), dmp(19999, 12)
  39.  
  40. 'shuffle variations
  41. shc = 3
  42. sh(0, 0) = 2: sh(0, 1) = 2
  43. sh(1, 0) = 3: sh(1, 1) = 3
  44. sh(2, 0) = 4: sh(2, 1) = 4
  45. FOR t = 0 TO shc - 1: sh$(t) = "Shuffle " + LTRIM$(STR$(sh(t, 0))) + "x" + LTRIM$(STR$(sh(t, 0))): sh(t, 2) = 2: sh(t, 3) = 5 + t * 2: sh(t, 4) = (sh(t, 2) - 1) * 8
  46. sh(t, 5) = sh(t, 4) + LEN(sh$(t)) * 8: sh(t, 6) = (sh(t, 3) - 1) * 16: NEXT t
  47.  
  48.  
  49.  
  50. 'creating tiles
  51. tiles = puzzle_x * puzzle_y
  52. REDIM tiles(tiles - 1, 14), posx(puzzle_x, puzzle_y): atiles = 0: FOR ax = 0 TO puzzle_x - 1: FOR ay = 0 TO puzzle_y - 1
  53.         tiles(atiles, 0) = _WIDTH(pic(0)) / puzzle_x * ax 'puzzle picture x1
  54.         tiles(atiles, 1) = _HEIGHT(pic(0)) / puzzle_y * ay 'puzzle picture y1
  55.         tiles(atiles, 2) = _WIDTH(pic(0)) / puzzle_x * (ax + 1) 'puzzle picture x2
  56.         tiles(atiles, 3) = _HEIGHT(pic(0)) / puzzle_y * (ay + 1) 'puzzle picture y2
  57.         tiles(atiles, 4) = ax 'coordinate in puzzle X
  58.         tiles(atiles, 5) = ay 'coordinate in puzzle Y
  59.         tiles(atiles, 6) = atiles 'melyik area-ba ?
  60. posx(ax, ay) = atiles: atiles = atiles + 1: NEXT ay, ax
  61.  
  62. 'tiles neighbor finding
  63. FOR atiles = 0 TO tiles - 1: FOR t3 = 0 TO 3
  64.         t1 = SGN(t3 AND 1): t2 = SGN(t3 AND 2): ax = (t1 * 2 - 1) * t2 + tiles(atiles, 4): ay = (t1 * 2 - 1) * (t2 XOR 1) + tiles(atiles, 5)
  65.         IF (ax < 0 OR ax > puzzle_x - 1) OR (ay < 0 OR ay > puzzle_y - 1) THEN tiles(atiles, 7 + t3) = -1 ELSE tiles(atiles, 7 + t3) = posx(ax, ay)
  66. NEXT t3, atiles
  67.  
  68.  
  69. REDIM join(tiles - 1, tiles - 1, 7) 'create array to joint analyzing
  70.  
  71. 'create areas position on display and mouse rotation points
  72. REDIM area_posinfo(tiles - 1, 15)
  73. FOR atiles = 0 TO tiles - 1: avx = 0: avy = 0: av = 0 'the geometric mean of the area, if any tiles in it
  74.     FOR atiles2 = 0 TO tiles - 1: IF tiles(atiles2, 6) = atiles THEN av = av + 1: avx = avx + tiles(atiles2, 4): avy = avy + tiles(atiles2, 5)
  75.     NEXT atiles2
  76.     IF av THEN
  77.         forg = 200
  78.         area_posinfo(atiles, 0) = avx / av + .5 'X coordinate puzzle rotating point
  79.         area_posinfo(atiles, 1) = avy / av + .5 'X coordinate puzzle rotating point
  80.         area_posinfo(atiles, 2) = (monx - psx) / 2 '+ psx / puzzle_x * area_posinfo(atiles, 0) 'X coordinate in monitor
  81.         area_posinfo(atiles, 3) = (mony - psy) / 2 '+ psy / puzzle_y * area_posinfo(atiles, 1) 'Y coordinate in monitor
  82.         area_posinfo(atiles, 4) = forg * RND(1) - forg / 2 'ROTATE scale in monitor
  83.         area_posinfo(atiles, 5) = atiles 'draw order
  84.         area_posinfo(atiles, 6) = sh_rand_m * sh_rand_v 'X shuffling vector
  85.         area_posinfo(atiles, 7) = sh_rand_m * sh_rand_v 'Y shuffling vector
  86.         area_posinfo(atiles, 8) = sh_rand_m * sh_rand_v 'rotating shuffling angle
  87.         area_posinfo(atiles, 9) = 0 'command X over limit
  88.         area_posinfo(atiles, 10) = 0 'command Y over limit
  89.  
  90.     ELSE
  91.         area_posinfo(atiles, 5) = -1 'draw order = no ,because missing in area
  92.     END IF
  93. NEXT atiles
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107. _DEST mon: _SOURCE bg
  108. DO: _LIMIT 40: mw = 0: WHILE _MOUSEINPUT: mw = mw + _MOUSEWHEEL: WEND: mousey = _MOUSEY: mousex = _MOUSEX: mb1 = _MOUSEBUTTON(1)
  109.     bill$ = INKEY$
  110.     IF bill$ = " " THEN shuffling_timer = shuffling_cycle
  111.  
  112.     'shuffling operation
  113.     shuffling = shuffling_timer > 0: shuffling_timer = shuffling_timer - 1: IF shuffling_timer < 0 THEN shuffling_timer = 0
  114.     shuffling_speed_act = SIN(3.1415 / shuffling_cycle * shuffling_timer) * shuffling_speed
  115.     IF shuffling = 0 THEN shuffling_speed_act = shuffling_speed_auto: shuffling = 1: GOSUB shuffling: shuffling = 0
  116.     GOSUB shuffling
  117.  
  118.  
  119.  
  120.     'MOUSE1 POSITION
  121.     IF mb1 = 0 AND moving THEN moving = 0
  122.     IF moving = 0 AND mb1 AND act_area <> -1 THEN
  123.         moving_tile = act_area: moving = 1: smovex = mousex: smovey = mousey: sareax = area_posinfo(moving_tile, 2): sareay = area_posinfo(moving_tile, 3)
  124.         GOSUB to_underground
  125.     END IF
  126.     IF moving THEN area_posinfo(moving_tile, 2) = mousex - smovex + sareax: area_posinfo(moving_tile, 3) = mousey - smovey + sareay
  127.  
  128.     'MOUSE ROTAITION (wheel)
  129.     IF act_area <> -1 THEN area_posinfo(act_area, 4) = area_posinfo(act_area, 4) - mw * 4: IF mw THEN GOSUB to_underground: mw_act = 1
  130.  
  131.     DO: recalc = 0: GOSUB drawing: GOSUB joining: LOOP WHILE recalc
  132.     GOSUB auto_inwindow
  133.  
  134.  
  135. 'drawing and mouse-commands sensitive
  136. drawing: damp = 0: act_area = -1: act_tile = -1: _PUTIMAGE: FOR area_order = 0 TO tiles - 1: 'area scanning of order
  137.     FOR area = 0 TO tiles - 1: IF area_posinfo(area, 5) = area_order THEN EXIT FOR
  138.     NEXT area 'find next area or find empty area
  139.  
  140.     IF area < tiles AND area <> -1 THEN 'if area is not empty
  141.         amp = 0
  142.         FOR atiles = 0 TO tiles - 1 'work actual tile
  143.  
  144.             'rotating to draw
  145.             px(0) = psxppx * (tiles(atiles, 4)): py(0) = psyppy * (tiles(atiles, 5)): px(1) = psxppx * (tiles(atiles, 4) + 1): py(1) = py(0)
  146.             px(2) = px(0): py(2) = psyppy * (tiles(atiles, 5) + 1): px(3) = px(1): py(3) = py(2): angle = 90 / puzzle_r * area_posinfo(area, 4) * pip180
  147.  
  148.             'where i to draw tile
  149.             rotp_x = psxppx * area_posinfo(area, 0): rotp_y = psyppy * area_posinfo(area, 1)
  150.             FOR t = 0 TO 3: oldx = px(t) - rotp_x: oldy = py(t) - rotp_y
  151.                 x = (oldx * COS(angle)) + (oldy * SIN(angle)): y = (oldy * COS(angle)) - (oldx * SIN(angle))
  152.                 px(t) = x + rotp_x + area_posinfo(area, 2): py(t) = y + rotp_y + area_posinfo(area, 3)
  153.                 join(area, atiles, t * 2) = px(t): join(area, atiles, t * 2 + 1) = py(t) 'possible or non-existent tiles drawing position
  154.             NEXT t
  155.  
  156.             IF tiles(atiles, 6) = area THEN
  157.  
  158.                 'which area (tile in area)  under mouse ?
  159.                 oldx = (px(0) + px(1) + px(2) + px(3)) / 4 - mousex: oldy = (py(0) + py(1) + py(2) + py(3)) / 4 - mousey
  160.                 x = (oldx * COS(-angle)) + (oldy * SIN(-angle)): y = (oldy * COS(-angle)) - (oldx * SIN(-angle))
  161.                 IF (-ptx < x AND ptx > x) AND (-pty < y AND pty > y) THEN act_area = area: act_tile = atiles
  162.  
  163.                 'title part of it all
  164.                 qx0 = tiles(atiles, 0): qy0 = tiles(atiles, 1): qx1 = tiles(atiles, 2): qy1 = qy0
  165.                 qx2 = tiles(atiles, 0): qy2 = tiles(atiles, 3): qx3 = tiles(atiles, 2): qy3 = qy2
  166.  
  167.                 'draw black border under tile
  168.                 IF puzzle_b > 0 THEN
  169.                     FOR t = 1 TO puzzle_b - 1
  170.                         mp(amp, 0) = 0: mp(amp, 1) = 0: mp(amp, 2) = 9: mp(amp, 3) = 0: mp(amp, 4) = 0: mp(amp, 5) = 9: mp(amp, 6) = 1: mp(amp, 7) = px(0) + t
  171.                         mp(amp, 8) = py(0) + t: mp(amp, 9) = px(1) + t: mp(amp, 10) = py(1) + t: mp(amp, 11) = px(2) + t: mp(amp, 12) = py(2) + t: amp = amp + 1
  172.                         mp(amp, 0) = 9: mp(amp, 1) = 9: mp(amp, 2) = 9: mp(amp, 3) = 0: mp(amp, 4) = 0: mp(amp, 5) = 9: mp(amp, 6) = 1: mp(amp, 7) = px(3) + t
  173.                         mp(amp, 8) = py(3) + t: mp(amp, 9) = px(1) + t: mp(amp, 10) = py(1) + t: mp(amp, 11) = px(2) + t: mp(amp, 12) = py(2) + t: amp = amp + 1
  174.                     NEXT t
  175.                 END IF
  176.  
  177.                 'draw tile
  178.                 mp(amp, 0) = qx0: mp(amp, 1) = qy0: mp(amp, 2) = qx1: mp(amp, 3) = qy1: mp(amp, 4) = qx2: mp(amp, 5) = qy2: mp(amp, 6) = 0: mp(amp, 7) = px(0)
  179.                 mp(amp, 8) = py(0): mp(amp, 9) = px(1): mp(amp, 10) = py(1): mp(amp, 11) = px(2): mp(amp, 12) = py(2): amp = amp + 1: mp(amp, 0) = qx3
  180.                 mp(amp, 1) = qy3: mp(amp, 2) = qx1: mp(amp, 3) = qy1: mp(amp, 4) = qx2: mp(amp, 5) = qy2: mp(amp, 6) = 0: mp(amp, 7) = px(3): mp(amp, 8) = py(3)
  181.                 mp(amp, 9) = px(1): mp(amp, 10) = py(1): mp(amp, 11) = px(2): mp(amp, 12) = py(2): amp = amp + 1
  182.             END IF
  183.         NEXT atiles
  184.  
  185.         'write the correct order to dmp array (direct maptriangle commands)
  186.         IF amp > 0 THEN
  187.             FOR t4 = 1 TO 0 STEP -1: FOR t2 = 0 TO amp - 1: IF mp(t2, 6) = t4 THEN FOR t3 = 0 TO 12: dmp(damp, t3) = mp(t2, t3): NEXT t3: damp = damp + 1
  188.             NEXT t2, t4
  189.         END IF
  190.     END IF
  191. NEXT area_order
  192.  
  193.  
  194.  
  195.  
  196. 'direct draw _maptriangle using dmp array
  197. FOR t = 0 TO damp - 1
  198.     _MAPTRIANGLE (dmp(t, 0), dmp(t, 1))-(dmp(t, 2), dmp(t, 3))-(dmp(t, 4), dmp(t, 5)), pic(dmp(t, 6)) TO(dmp(t, 7), dmp(t, 8))-(dmp(t, 9), dmp(t, 10))-(dmp(t, 11), dmp(t, 12)), mon, _SMOOTH
  199.  
  200. 'calculating elements
  201. actual_elements = 0: FOR t = 0 TO tiles - 1: actual_elements = (ABS(area_posinfo(t, 5) <> -1)) + actual_elements: NEXT t
  202. COLOR _RGB32(200, 200, 200)
  203. completed100 = actual_elements = 1: LOCATE 1, 1: COLOR , 0: PRINT "SIMPLE PUZZLE GAME  -  Completed:"; INT((tiles - actual_elements) / (tiles - 1) * 100); "%"
  204.  
  205.  
  206. 'writing to display shuffle variations if completed is 100%
  207. sh_act = -1: IF completed100 THEN
  208.     FOR t = 0 TO shc - 1: IF (sh(t, 4) < mousex AND sh(t, 5) > mousex) AND (sh(t, 6) < mousey AND (sh(t, 6) + 16) > mousey) THEN
  209.     sh_act = t: COLOR _RGB32(255, 255, 255): ELSE COLOR _RGB32(100, 100, 100): END IF: LOCATE sh(t, 3), sh(t, 2): PRINT sh$(t): NEXT t
  210.  
  211. to_underground: IF act_area = -1 THEN RETURN
  212. fto = area_posinfo(act_area, 5): FOR atiles = 0 TO tiles - 1: IF area_posinfo(atiles, 5) > fto THEN area_posinfo(atiles, 5) = area_posinfo(atiles, 5) - 1
  213. NEXT atiles: area_posinfo(act_area, 5) = tiles - 1: RETURN
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220. joining: 'a1 area will be what we're looking at, a2 area will be overwritten if it's okay
  221. IF shuffling THEN RETURN
  222. FOR a1area = 0 TO tiles - 1: IF area_posinfo(a1area, 5) = -1 THEN _CONTINUE
  223.     FOR a2area = a1area TO tiles - 1: IF area_posinfo(a2area, 5) = -1 OR a1area = a2area THEN _CONTINUE
  224.         FOR a1tiles = 0 TO tiles - 1: IF tiles(a1tiles, 6) <> a1area THEN _CONTINUE
  225.  
  226.             p_ok = 0: FOR t = 0 TO 3
  227.                 disx = join(a1area, a1tiles, t * 2) - join(a2area, a1tiles, t * 2): disy = join(a1area, a1tiles, t * 2 + 1) - join(a2area, a1tiles, t * 2 + 1)
  228.             p_ok = p_ok + ABS(SGN((disx * disx + disy * disy) < puzzle_s2)): NEXT t: IF p_ok <> 4 THEN _CONTINUE
  229.  
  230.             'itt egyezset talalt area1 es area2 kozott, meghozza a a1tiles kockaban
  231.             'a kerdes az, hogy ha osszekapcsoljuk a ket teruletet, lesz-e olyan meglevo kocka, akinek nincs szomszedja ?
  232.  
  233.             'found a match here between area1 and area2 in the a1tiles tile. the question is whether if we connect the two areas,
  234.             'will there be an existing cube that has no neighbor
  235.  
  236.             FOR a2tiles = 0 TO tiles - 1: IF tiles(a2tiles, 6) <> a1area AND tiles(a2tiles, 6) <> a2area THEN _CONTINUE
  237.                 a3area_isok = 0: FOR t2 = 0 TO 3: a3tiles = tiles(a2tiles, 7 + t2)
  238.                     IF a3tiles <> -1 THEN a3area_isok = ABS(tiles(a3tiles, 6) = a1area OR tiles(a3tiles, 6) = a2area) OR a3area_isok
  239.                 NEXT t2: IF a3area_isok = 0 THEN EXIT FOR
  240.             NEXT a2tiles
  241.  
  242.             IF a3area_isok THEN 'joint is ok, areas concatenation
  243.                 FOR t = 0 TO tiles - 1: IF tiles(t, 6) = a1area THEN tiles(t, 6) = a2area
  244.                 NEXT t: GOSUB tile_to_center: recalc = 1: RETURN
  245.             END IF
  246.  
  247. NEXT a1tiles, a2area, a1area: RETURN
  248.  
  249.  
  250. tile_to_center: FOR atiles = 0 TO tiles - 1: avx = 0: avy = 0: av = 0
  251.     FOR atiles2 = 0 TO tiles - 1: IF tiles(atiles2, 6) = atiles THEN av = av + 1: avx = avx + tiles(atiles2, 4): avy = avy + tiles(atiles2, 5)
  252.     NEXT atiles2
  253.     IF av THEN
  254.         area_posinfo(atiles, 0) = avx / av + .5: area_posinfo(atiles, 1) = avy / av + .5 'X-Y coordinate puzzle rotating point (to mouse rotation)
  255.     ELSE
  256.         area_posinfo(atiles, 5) = -1 'empty area
  257.     END IF
  258. NEXT atiles: RETURN
  259.  
  260. auto_inwindow: 'does not allow the area to exit the screen too much'
  261. 'IF shuffling THEN RETURN
  262. FOR area = 0 TO tiles - 1: IF area_posinfo(area, 5) = -1 THEN _CONTINUE
  263.     minx = 9999999999: maxx = -minx: miny = minx: maxy = maxx
  264.     FOR atiles = 0 TO tiles - 1: IF tiles(atiles, 6) <> area THEN _CONTINUE
  265.         FOR t = 0 TO 7
  266.             IF t AND 1 THEN
  267.                 IF join(area, atiles, t) > maxy THEN maxy = join(area, atiles, t)
  268.                 IF join(area, atiles, t) < miny THEN miny = join(area, atiles, t)
  269.             ELSE
  270.                 IF join(area, atiles, t) > maxx THEN maxx = join(area, atiles, t)
  271.                 IF join(area, atiles, t) < minx THEN minx = join(area, atiles, t)
  272.             END IF
  273.     NEXT t: NEXT atiles
  274.     movex = (lwindow_x1 - maxx) * ABS(maxx < lwindow_x1) + (lwindow_x2 - minx) * ABS(minx > lwindow_x2)
  275.     movey = (lwindow_y1 - maxy) * ABS(maxy < lwindow_y1) + (lwindow_y2 - miny) * ABS(miny > lwindow_y2)
  276.     area_posinfo(area, 2) = area_posinfo(area, 2) + movex: area_posinfo(area, 3) = area_posinfo(area, 3) + movey
  277. area_posinfo(area, 9) = ABS(movex): area_posinfo(area, 10) = ABS(movey): NEXT area: RETURN
  278.  
  279.  
  280. shuffling: IF shuffling = 0 THEN RETURN
  281. FOR area = 0 TO tiles - 1: IF area_posinfo(area, 5) = -1 THEN _CONTINUE
  282.     area_posinfo(area, 2) = area_posinfo(area, 2) + area_posinfo(area, 6) * shuffling_speed_act
  283.     area_posinfo(area, 3) = area_posinfo(area, 3) + area_posinfo(area, 7) * shuffling_speed_act
  284.     area_posinfo(area, 4) = area_posinfo(area, 4) + area_posinfo(area, 8) * shuffling_speed_act
  285.     IF area_posinfo(area, 9) THEN area_posinfo(area, 6) = -SGN(area_posinfo(area, 6)) * sh_rand_m: area_posinfo(area, 8) = sh_rand_v * sh_rand_m
  286.     IF area_posinfo(area, 10) THEN area_posinfo(area, 7) = -SGN(area_posinfo(area, 7)) * sh_rand_m: area_posinfo(area, 8) = sh_rand_v * sh_rand_m
  287. NEXT area: RETURN
  288.  
  289.  
  290.  
  291.  
  292. FUNCTION sh_rand_m: sh_rand_m = .5 + .5 * RND(1): END FUNCTION
  293. FUNCTION sh_rand_v: sh_rand_v = INT(2 * RND(1)) * 2 - 1: END FUNCTION
  294.  
  295.  
  296.  

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Simple Puzzle Game
« Reply #1 on: November 17, 2020, 03:27:53 pm »
That. Is. Freaking. Cool
Shuwatch!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Simple Puzzle Game
« Reply #2 on: November 17, 2020, 04:12:49 pm »
+1 Cool!

Curious how the pieces drift if you let them alone for a bit.

Offline Kiara87

  • Forum Regular
  • Posts: 164
    • View Profile
Re: Simple Puzzle Game
« Reply #3 on: November 17, 2020, 04:34:27 pm »
thanks great program
se avessi solo un'ora per salvare il mondo, passerei 55 minuti per definire bene il problema e 5 a trovare la soluzione

Offline MasterGy

  • Seasoned Forum Regular
  • Posts: 327
  • people lie, math never lies
    • View Profile
Re: Simple Puzzle Game
« Reply #4 on: November 17, 2020, 04:39:18 pm »
BLUS,

Hu, I can't simply answer that. Set theory-like.
There is the TILES array, he stores data one by one, which only applies to 1 small piece cut. The location of the original image and which AREA it belongs to.
From here, where is this little piece on the screen, the AREA array gives the answer.
The area array records where he is on the screen, what rotation, and where from the rotation point. This just needs to be insulted.
Imagine 1 picture. At the very beginning, you specify that you are cutting toward 4x4, for example. This means 16 frames and also that the frame can be in 16 different places. these places are called AREA.
Initially, each AREA has 1 frame.
In practice, you envisioned AREAs by drawing a 4x4 table on 16 transparent foils. You place the frames in the transparencies as you wish. You just have to pay attention to one thing! 1 frame can only be on 1 film! When you rotate or move on the screen, overlapping layers sometimes show a match. If you look through them, one of the frames meets the other, puzzle_s - distance. If this deviation is less than this, the following occurs:
You have 2 pieces of film, which if you hold each other properly and look through it, you will see that the cube on one layer is adjacent to the cube on the other cube. then you discard one layer and copy the contents of the previous layer onto the other, then put that layer back among the others. It became 1 film less.
The answer to your question is: I move the transparencies, just don’t go off the screen!

Offline MasterGy

  • Seasoned Forum Regular
  • Posts: 327
  • people lie, math never lies
    • View Profile
Re: Simple Puzzle Game
« Reply #5 on: November 22, 2020, 10:55:39 am »

Hi !
I finished the puzzle. I put in everything I wanted. Adjustable division, movement, rotation. Right mouse button helps you find where to paste the tile. You can have fun with it pretty well. Just enter a picture at the beginning and get started.

(just one note: I wanted to use SHIFT and CTRL instead of 1 and 2, which I read with _KEYDOWN. I didn't do that because (maybe) the SHIFT and CTRL values are due to the mouse commands. sometimes they got false values .don't know why)





Code: QB64: [Select]
  1. '------------------- you have nothing else to do, give me a picture! ------------------------------------------------------------------------------------------
  2. pic(0) = _LOADIMAGE("puzzle.jpg", 32) 'picture puzzle
  3.  
  4.  
  5. ' ---------------------- SETTINGS --------------------------------------------------------------------------------------------------------------------------
  6. monx = 1200 'resolution X
  7. monrat = 0 'monitor ratio 0=16:9 1=4:3
  8. moving_speed(0) = 7 'TILE move speed start value
  9. rotating_speed(0) = 6 'TILE rotation speed start value
  10. st_rotating = 1 'rotation start value
  11. rotating_moving_chance = 20 'during the game the chance is 1:x to change direction or rotation of the TILE
  12. tile_ratiomax = 1.4 'the ratio of the larger and smaller sides of TILE should not be greater than this (filter out very rectangular tiles)
  13. bg_file$ = "" 'background picture jpg  ,if bg_file$="" then be a grey background
  14.  
  15.  
  16. '------------------------ ADVANCED SETTING
  17. monpuzzle = 70 'percentage size max puzzle weight in the window
  18. inwindow = 28 'percentage size for windows, auto reposition if tile is over
  19. shuffling_cycle = 100 'the mixing is so many cycles long  90 is ok
  20. puzzle_r = 720 '1 rotation scale = 360/puzzle_rnnecessary rotation possibilities (faster rotation)
  21. puzzle_b = 8 'thickness of tile over black background
  22. puzzle_s_ratio = .6 'two matching tile encounter detection sensitivity multiplier (real sensitivity is proportional to tile size)
  23. together_speed = 6 'fast tile speed when unification
  24. together_speed_slow = 1 'slow tile speed when unification
  25. dislimit = 2 'what the minimum deviation (pixel,angle) should change when unification ?
  26. keyviewy = 3: keyviewx = 2 'start location draw to setup text
  27. DIM col_act AS _INTEGER64, col_inact AS _INTEGER64: col_act = _RGB32(255, 255, 255): col_inact = _RGB32(100, 100, 100) 'setup text active/inactive colors
  28. moving_speed(1) = 20 'TILE move speed when shuffling
  29. rotating_speed(1) = 20 'TILE rotation speed when shuffling
  30.  
  31.  
  32. '------------------------- SETTING CONSTANT VALUES -----------------------------------------------------------------------------------------------------------------
  33. 'creating blackunder border
  34. RANDOMIZE TIMER: pic(1) = _NEWIMAGE(10, 10, 32): _DEST pic(1): CLS: pic(2) = _NEWIMAGE(10, 10, 32): _DEST pic(2): CLS , _RGB(255, 0, 0)
  35. IF monrat THEN mony = INT(monx / 4 * 3) ELSE mony = INT(monx / 16 * 9)
  36. IF _FILEEXISTS(bg_file$) AND bg_file$ <> "" THEN bg = _LOADIMAGE(bg_file$, 32) ELSE bg = _NEWIMAGE(10, 10, 32): _DEST bg: CLS , _RGB32(30, 30, 30)
  37. mon = _NEWIMAGE(monx, mony, 32): SCREEN mon: _FULLSCREEN _SQUAREPIXELS , _SMOOTH: _DEST mon: _SOURCE bg: _PUTIMAGE
  38. lwindow_x1 = monx * inwindow / 100: lwindow_x2 = monx - lwindow_x1: lwindow_y1 = mony * inwindow / 100: lwindow_y2 = mony - lwindow_y1
  39. CONST pip180 = 3.14159265 / 180: en$(1) = "enable": en$(0) = "disable"
  40. 'calculating tiles size - ideal placement depending on whether the image is portrait or landscape
  41. psx = INT(monx * monpuzzle / 100): psy = INT(psx / _WIDTH(pic(0)) * _HEIGHT(pic(0)))
  42. IF psy > mony * monpuzzle / 100 THEN psy = INT(mony * monpuzzle / 100): psx = INT(psy / _HEIGHT(pic(0)) * _WIDTH(pic(0)))
  43.  
  44. 'parcelling / shuffle variations creation searching
  45. shc_max = 20: shc = 0: DIM sh(shc_max - 1, 7), sh$(shc_max - 1): FOR shy = 1 TO 20: FOR shx = 1 TO 20: IF shy = 1 AND shx = 1 THEN _CONTINUE
  46.         tile_size_x = _WIDTH(pic(0)) / shx: tile_size_y = _HEIGHT(pic(0)) / shy: ratio = tile_size_y / tile_size_x
  47.         IF tile_size_x > tile_size_y THEN ratio = 1 / ratio
  48.         IF (ratio <= tile_ratiomax) AND shc < shc_max THEN sh(shc, 1) = shx: sh(shc, 0) = shy: sh(shc, 7) = shy * shx: shc = shc + 1
  49. NEXT shx, shy
  50. FOR t1 = 0 TO shc - 1: FOR t2 = 0 TO shc - 1: IF sh(t2, 7) > sh(t1, 7) THEN SWAP sh(t2, 7), sh(t1, 7): SWAP sh(t2, 7), sh(t1, 7): SWAP sh(t2, 7), sh(t1, 7)
  51. NEXT t2, t1
  52. FOR t = 0 TO shc - 1: sh$(t) = "Start " + LTRIM$(STR$(sh(t, 0))) + "x" + LTRIM$(STR$(sh(t, 1))) + "=" + LTRIM$(STR$(sh(t, 7))): sh(t, 2) = 2: sh(t, 3) = 12 + t * 1
  53. sh(t, 4) = (sh(t, 2) - 1) * 8: sh(t, 5) = sh(t, 4) + LEN(sh$(t)) * 8: sh(t, 6) = (sh(t, 3) - 1) * 16: NEXT t
  54.  
  55. 'initial values to get to the cycle on which to choose
  56. start_area_x_s = monx * .55 - psx / 2: start_area_y_s = mony / 2 - psy / 2: start_area_rotate_s = 360 / puzzle_r * 0: puzzle_x = 2: puzzle_y = 2: first_start = 1
  57. start_area_x = start_area_x_s: start_area_y = start_area_y_s: start_area_rotate = start_area_rotate_s
  58.  
  59. '-----------------------   henceforth no defining values should be used ------------------no constant values -------------------------------------------------
  60. restart_point: 'this is the restart point to which you can return at any time by division without collision
  61. tiles = puzzle_x * puzzle_y: psxppx = psx / puzzle_x: psyppy = psy / puzzle_y: ptx = psx / puzzle_x / 2: pty = psy / puzzle_y / 2
  62. REDIM mp(999, 12), dmp(19999, 12), px(3), py(3), tiles(tiles - 1, 14), posx(puzzle_x, puzzle_y), join(tiles - 1, tiles - 1, 7), area_posinfo(tiles - 1, 15)
  63.  
  64. 'hit sensitivity tile -proportional value
  65. st1 = 2: ss1 = 80 'For 2 tile, 80 sensitivity is ergonomic
  66. st2 = 40: ss2 = 60 'For 40 tile, 50 sensitivity is ergonomic
  67. puzzle_s2 = (((tiles - st1) / ((st2 - st1) / (ss2 - ss1)) + ss1) * puzzle_s_ratio) ^ 2
  68.  
  69. 'creating tiles
  70. atiles = 0: FOR ax = 0 TO puzzle_x - 1: FOR ay = 0 TO puzzle_y - 1
  71.         tiles(atiles, 0) = _WIDTH(pic(0)) / puzzle_x * ax: tiles(atiles, 1) = _HEIGHT(pic(0)) / puzzle_y * ay 'original picture tile coordinates
  72.         tiles(atiles, 2) = _WIDTH(pic(0)) / puzzle_x * (ax + 1): tiles(atiles, 3) = _HEIGHT(pic(0)) / puzzle_y * (ay + 1)
  73.         tiles(atiles, 4) = ax 'coordinate in puzzle X
  74.         tiles(atiles, 5) = ay 'coordinate in puzzle Y
  75.         tiles(atiles, 6) = atiles 'melyik area-ba ?
  76.         IF first_start THEN tiles(atiles, 6) = 0
  77. posx(ax, ay) = atiles: atiles = atiles + 1: NEXT ay, ax
  78.  
  79. 'tiles neighbor finding
  80. FOR atiles = 0 TO tiles - 1: FOR t3 = 0 TO 3
  81.         t1 = SGN(t3 AND 1): t2 = SGN(t3 AND 2): ax = (t1 * 2 - 1) * t2 + tiles(atiles, 4): ay = (t1 * 2 - 1) * (t2 XOR 1) + tiles(atiles, 5)
  82.         IF (ax < 0 OR ax > puzzle_x - 1) OR (ay < 0 OR ay > puzzle_y - 1) THEN tiles(atiles, 7 + t3) = -1 ELSE tiles(atiles, 7 + t3) = posx(ax, ay)
  83. NEXT t3, atiles
  84.  
  85. 'create areas position on display and mouse rotation points
  86. IF first_start THEN
  87.     area_posinfo(0, 0) = puzzle_x / 2: area_posinfo(0, 1) = puzzle_y / 2: area_posinfo(0, 2) = start_area_x: area_posinfo(0, 3) = start_area_y
  88.     area_posinfo(0, 4) = start_area_rotate: area_posinfo(0, 5) = 0: area_posinfo(0, 6) = sh_rand_m * sh_rand_v: area_posinfo(0, 7) = sh_rand_m * sh_rand_v
  89.     area_posinfo(0, 8) = sh_rand_m * sh_rand_v: area_posinfo(0, 9) = 0: area_posinfo(0, 10) = 0: FOR t = 1 TO tiles - 1: area_posinfo(t, 5) = -1: NEXT t
  90.     FOR atiles = 0 TO tiles - 1: avx = 0: avy = 0: av = 0 'the geometric mean of the area, if any tiles in it
  91.         FOR atiles2 = 0 TO tiles - 1: IF tiles(atiles2, 6) = atiles THEN av = av + 1: avx = avx + tiles(atiles2, 4): avy = avy + tiles(atiles2, 5)
  92.             NEXT atiles2: IF av THEN
  93.             area_posinfo(atiles, 0) = avx / av + .5 'X coordinate puzzle rotating point
  94.             area_posinfo(atiles, 1) = avy / av + .5 'X coordinate puzzle rotating point
  95.             area_posinfo(atiles, 2) = start_area_x '(monx - psx) / 2 '+ psx / puzzle_x * area_posinfo(atiles, 0) 'X coordinate in monitor
  96.             area_posinfo(atiles, 3) = start_area_y '(mony - psy) / 2 '+ psy / puzzle_y * area_posinfo(atiles, 1) 'Y coordinate in monitor
  97.             area_posinfo(atiles, 4) = start_area_rotate '0 'ROTATE scale in monitor
  98.             area_posinfo(atiles, 5) = atiles 'draw order
  99.             area_posinfo(atiles, 6) = sh_rand_m * sh_rand_v 'X shuffling vector
  100.             area_posinfo(atiles, 7) = sh_rand_m * sh_rand_v 'Y shuffling vector
  101.             area_posinfo(atiles, 8) = sh_rand_m * sh_rand_v 'rotating shuffling angle
  102.             area_posinfo(atiles, 9) = 0 'command X over limit
  103.             area_posinfo(atiles, 10) = 0 'command Y over limit
  104.         ELSE area_posinfo(atiles, 5) = -1 'draw order = no ,because missing in area
  105. END IF: NEXT atiles: END IF
  106.  
  107. _DEST mon: _SOURCE bg: theend = 0: shuffling_timer = shuffling_cycle * (first_start XOR 1): first_start = 0
  108.  
  109.  
  110. '---------------- BOSS CYCLE ---------------------------------------------------------------------------------------------------------------------------
  111.  
  112. DO: _LIMIT 40: mw = 0: WHILE _MOUSEINPUT: mw = mw + _MOUSEWHEEL: WEND: mousey = _MOUSEY: mousex = _MOUSEX: mb1 = _MOUSEBUTTON(1): mb2 = _MOUSEBUTTON(2)
  113.  
  114.     'keyboard and mouse commands
  115.     mb1_click = mb1 AND mb1 <> mb1_old: mb2_click = mb2 AND mb2 <> mb2_old
  116.     ikey$ = LCASE$(INKEY$): st_rotating = st_rotating XOR ABS((keyview_act = 0 AND (mb1_click OR mb2_click)) OR ikey$ = "r")
  117.     theend = (mb1 AND keyview_act = 5) OR theend OR ikey$ = "n": IF (mb1 AND keyview_act = 6) OR ikey$ = CHR$(27) THEN SYSTEM
  118.  
  119.     shift_ok = _KEYDOWN(49) OR (mb1 AND keyview_act = 3) 'ikey$ = "1" '(mb1 AND keyview_act = 3) OR (_KEYDOWN(100304) OR _KEYDOWN(100303))
  120.     ctrl_ok = _KEYDOWN(50) OR (mb1 AND keyview_act = 4) 'ikey$ = "2" '(mb1 AND keyview_act = 4) OR (_KEYDOWN(100306) OR _KEYDOWN(100305))
  121.     only1 = ctrl_ok: together = ABS(shift_ok OR ctrl_ok OR theend) AND (actual_elements > 1)
  122.     rotating_speed(0) = rotating_speed(0) - ABS(keyview_act = 2) * (mw + mb1_click - mb2_click) - (ikey$ = "*") + (ikey$ = "/")
  123.     moving_speed(0) = moving_speed(0) - ABS(keyview_act = 1) * (mw + mb1_click - mb2_click) - (ikey$ = "+") + (ikey$ = "-")
  124.     rotating_speed(0) = (ABS(rotating_speed(0) < 0) XOR 1) * rotating_speed(0): moving_speed(0) = (ABS(moving_speed(0) < 0) XOR 1) * moving_speed(0)
  125.     mb1_old = mb1: mb2_old = mb2
  126.  
  127.     'shuffling operation
  128.     shuffling = ABS(shuffling_timer > 0): shuffling_timer = (shuffling_timer - 1) * shuffling: shuffling_speed_act = SIN(3.1415 / shuffling_cycle * shuffling_timer)
  129.     shuffle_m = (moving_speed(1) * shuffling_speed_act * shuffling) + moving_speed(0) / 4 * (shuffling XOR 1)
  130.     shuffle_r = (rotating_speed(1) * shuffling_speed_act * shuffling) + rotating_speed(0) / 10 * (shuffling XOR 1): GOSUB shuffling
  131.  
  132.     'MOUSE1 POSITION
  133.     moving = moving * (ABS(mb1 = 0 AND moving) XOR 1)
  134.     IF moving = 0 AND mb1 AND act_area <> -1 THEN
  135.         moving_tile = act_area: moving = 1: smovex = mousex: smovey = mousey: sareax = area_posinfo(moving_tile, 2): sareay = area_posinfo(moving_tile, 3)
  136.         GOSUB to_underground
  137.     END IF
  138.     IF moving THEN area_posinfo(moving_tile, 2) = mousex - smovex + sareax: area_posinfo(moving_tile, 3) = mousey - smovey + sareay
  139.  
  140.     'MOUSE ROTAITION (wheel)
  141.     IF act_area <> -1 THEN area_posinfo(act_area, 4) = area_posinfo(act_area, 4) - mw * (360 / puzzle_r) * 32: IF mw THEN GOSUB to_underground: mw_act = 1
  142.  
  143.     GOSUB together: DO: recalc = 0: GOSUB drawing: GOSUB joining: LOOP WHILE recalc: GOSUB auto_inwindow 'calculations to new positions
  144.  
  145.     IF sh_act <> -1 AND mb1 THEN 'if complete 100% and choice a new variation
  146.         puzzle_x = sh(sh_act, 1): puzzle_y = sh(sh_act, 0): sh_act = -1: area = 0: DO UNTIL area_posinfo(area, 5) <> -1: area = area + 1: LOOP
  147.         start_area_x = area_posinfo(area, 2): start_area_y = area_posinfo(area, 3): start_area_rotate = area_posinfo(area, 4): GOTO restart_point
  148.     END IF
  149.  
  150.     'AREA-ROTATION NORMALIZE
  151.     FOR area = 0 TO tiles - 1: IF area_posinfo(area, 5) = -1 THEN _CONTINUE
  152.         DO WHILE area_posinfo(area, 4) > puzzle_r - 1: area_posinfo(area, 4) = area_posinfo(area, 4) - puzzle_r: LOOP
  153.         DO WHILE area_posinfo(area, 4) < 0: area_posinfo(area, 4) = area_posinfo(area, 4) + puzzle_r: LOOP
  154.     NEXT area
  155.  
  156.  
  157. 'drawing and mouse-commands sensitive
  158. drawing: und_flash = ABS(TIMER * 3 - INT(TIMER * 3) > .5): help_flash = help_flash XOR 1
  159. damp = 0: act_area = -1: act_tile = -1: _PUTIMAGE: FOR area_order = 0 TO tiles - 1: 'area scanning of order
  160.     FOR area = 0 TO tiles - 1: IF area_posinfo(area, 5) = area_order THEN EXIT FOR
  161.     NEXT area 'find next area or find empty area
  162.  
  163.     IF area < tiles AND area <> -1 THEN 'if area is not empty
  164.         amp = 0: FOR atiles = 0 TO tiles - 1 'work actual tile
  165.  
  166.             'rotating to draw
  167.             px(0) = psxppx * (tiles(atiles, 4)): py(0) = psyppy * (tiles(atiles, 5)): px(1) = psxppx * (tiles(atiles, 4) + 1): py(1) = py(0)
  168.             px(2) = px(0): py(2) = psyppy * (tiles(atiles, 5) + 1): px(3) = px(1): py(3) = py(2)
  169.             angle = 360 / puzzle_r * INT(area_posinfo(area, 4)) * pip180 * st_rotating
  170.  
  171.             'where i to draw tile
  172.             rotp_x = psxppx * area_posinfo(area, 0): rotp_y = psyppy * area_posinfo(area, 1)
  173.             FOR t = 0 TO 3: oldx = px(t) - rotp_x: oldy = py(t) - rotp_y
  174.                 x = (oldx * COS(angle)) + (oldy * SIN(angle)): y = (oldy * COS(angle)) - (oldx * SIN(angle))
  175.                 px(t) = x + rotp_x + area_posinfo(area, 2): py(t) = y + rotp_y + area_posinfo(area, 3)
  176.                 join(area, atiles, t * 2) = px(t): join(area, atiles, t * 2 + 1) = py(t) 'possible or non-existent tiles drawing position
  177.             NEXT t
  178.  
  179.             'current TILE drawing assessment
  180.             'the question is whether the act_tile_old is included in the current AREA of eppen.
  181.             'if not, there is a chance that you will need to flash in the case of MOUSE2.
  182.             'if we put ACT_TILE_OLD in the current area, would you have a neighbor in the corresponding AREA? if so, flash it
  183.             atiles_st = -1: IF tiles(atiles, 6) = area THEN '-1 tile nem kell mutatni,0 actual tile ,1 help neighbor tile
  184.                 atiles_st = 0: atiles_d = atiles: GOSUB draw2 'tile az aktualis kirajzolando
  185.             ELSE: IF tiles(atiles, 6) <> area AND mb2 AND act_tile_old = atiles THEN
  186.                     FOR a_n = 0 TO 3: anei = tiles(act_tile_old, 7 + a_n): IF anei <> -1 THEN
  187.                             act_ne = tiles(anei, 6): IF act_ne = area THEN atiles_st = 1: atiles_d = atiles: GOSUB draw2: EXIT FOR
  188.             END IF: NEXT a_n: END IF: END IF
  189.  
  190.         NEXT atiles
  191.  
  192.         'write the correct order to dmp array (direct maptriangle commands)
  193.         IF amp > 0 THEN
  194.             FOR t4 = 1 TO 0 STEP -1: FOR t2 = 0 TO amp - 1: IF mp(t2, 6) = t4 THEN FOR t3 = 0 TO 12: dmp(damp, t3) = mp(t2, t3): NEXT t3: damp = damp + 1
  195.         NEXT t2, t4: END IF
  196.  
  197.     END IF
  198. NEXT area_order: act_area_old = act_area: act_tile_old = act_tile
  199.  
  200.  
  201. 'direct draw _maptriangle using dmp array
  202. FOR t = 0 TO damp - 1: _MAPTRIANGLE (dmp(t, 0), dmp(t, 1))-(dmp(t, 2), dmp(t, 3))-(dmp(t, 4), dmp(t, 5)), pic(dmp(t, 6)) TO(dmp(t, 7), dmp(t, 8))-(dmp(t, 9), dmp(t, 10))-(dmp(t, 11), dmp(t, 12)), mon, _SMOOTH: NEXT t
  203.  
  204. 'calculating elements
  205. actual_elements = 0: FOR t = 0 TO tiles - 1: actual_elements = (ABS(area_posinfo(t, 5) <> -1)) + actual_elements: NEXT t
  206.  
  207.  
  208. 'any text and setup view and registration command
  209. COLOR _RGB32(200, 200, 200): LOCATE 1, 1: COLOR , 0: PRINT "SIMPLE PUZZLE GAME  -  Completed:"; INT((tiles - actual_elements) / (tiles - 1) * 100); "%"
  210. setup_minx = (keyviewx + setupminlen - 1) * 8: setup_active = ((mousex < 10 OR setup_active) AND (setup_minx > mousex)) OR actual_elements = 1
  211. IF setup_active OR fcalc = 0 THEN
  212.     keyviewc = 7: fcalc = 1
  213.     keyview$(0) = "-  R  - rotating (" + en$(st_rotating) + ")": keyview$(1) = "- +,- - moving speed (" + STR$(INT(moving_speed(0))) + ")"
  214.     keyview$(2) = "- *,/ - rotating speed (" + STR$(INT(rotating_speed(0))) + ")": keyview$(3) = "-  1  - Together1 command (" + en$(ABS(shift_ok)) + ")"
  215.     keyview$(4) = "-  2  - Together2 command (" + en$(ABS(ctrl_ok)) + ")": keyview$(5) = "-  N  - New Game": keyview$(6) = "- ESC - Exit"
  216.     keyview_act = -1: setupminlen = 0: FOR t = 0 TO keyviewc - 1: IF setupminlen < LEN(keyview$(t)) THEN setupminlen = LEN(keyview$(t))
  217.         x1 = (keyviewx - 1) * 8: x2 = x1 + LEN(keyview$(t)) * 8: y1 = (keyviewy - 1 + t) * 16: y2 = y1 + 16
  218.         IF mousex > x1 AND mousex < x2 AND mousey > y1 AND mousey < y2 THEN keyview_act = t: COLOR col_act ELSE COLOR col_inact
  219.     LOCATE keyviewy + t, keyviewx: PRINT keyview$(t): NEXT t: ELSE: LOCATE keyviewy, keyviewx: COLOR col_act: PRINT "<- SETUP OPEN": LOCATE keyviewy + 2, keyviewx
  220. COLOR col_inact: PRINT "Right mouse button helps you where to put it": END IF
  221.  
  222. 'writing to display shuffle variations if only 1 area active  = completed is 100%
  223. sh_act = -1: IF actual_elements = 1 THEN
  224.     FOR t = 0 TO shc - 1: IF (sh(t, 4) < mousex AND sh(t, 5) > mousex) AND (sh(t, 6) < mousey AND (sh(t, 6) + 16) > mousey) THEN
  225.     sh_act = t: COLOR col_act: ELSE COLOR col_inact: END IF: LOCATE sh(t, 3), sh(t, 2): PRINT sh$(t): NEXT t
  226.     IF sh_act <> -1 THEN 'draw grid to picture
  227.         area = 0: DO UNTIL area_posinfo(area, 5) <> -1: area = area + 1: LOOP: gx0 = join(area, 0, 0): gy0 = join(area, 0, 1): gx1 = join(area, puzzle_y - 1, 4)
  228.         gy1 = join(area, puzzle_y - 1, 5): gx2 = join(area, tiles - puzzle_y, 2): gy2 = join(area, tiles - puzzle_y, 3): gx3 = join(area, tiles - 1, 6)
  229.         gy3 = join(area, tiles - 1, 7): COLOR _RGB32(255, 255, 255)
  230.         FOR t = 1 TO sh(sh_act, 0) - 1: x1 = gx0 + (gx1 - gx0) / (sh(sh_act, 0)) * t: y1 = gy0 + (gy1 - gy0) / (sh(sh_act, 0)) * t
  231.         x2 = gx2 + (gx3 - gx2) / (sh(sh_act, 0)) * t: y2 = gy2 + (gy3 - gy2) / (sh(sh_act, 0)) * t: LINE (x1, y1)-(x2, y2): NEXT t
  232.         FOR t = 1 TO sh(sh_act, 1) - 1: x1 = gx0 + (gx2 - gx0) / (sh(sh_act, 1)) * t: y1 = gy0 + (gy2 - gy0) / (sh(sh_act, 1)) * t
  233.         x2 = gx1 + (gx3 - gx1) / (sh(sh_act, 1)) * t: y2 = gy1 + (gy3 - gy1) / (sh(sh_act, 1)) * t: LINE (x1, y1)-(x2, y2): NEXT t
  234.     END IF
  235.  
  236. to_underground: IF together THEN RETURN
  237. to_underground_fromtogether: IF act_area = -1 THEN RETURN
  238. fto = area_posinfo(act_area, 5): FOR atiles = 0 TO tiles - 1: IF area_posinfo(atiles, 5) > fto THEN area_posinfo(atiles, 5) = area_posinfo(atiles, 5) - 1
  239. NEXT atiles: area_posinfo(act_area, 5) = tiles - 1: RETURN
  240.  
  241. joining: 'a1 area will be what we're looking at, a2 area will be overwritten if it's okay
  242. IF shuffling THEN RETURN
  243. FOR a1area = 0 TO tiles - 1: IF area_posinfo(a1area, 5) = -1 THEN _CONTINUE
  244.     FOR a2area = a1area TO tiles - 1: IF area_posinfo(a2area, 5) = -1 OR a1area = a2area THEN _CONTINUE
  245.         FOR a1tiles = 0 TO tiles - 1: IF tiles(a1tiles, 6) <> a1area THEN _CONTINUE
  246.             p_ok = 0: FOR t = 0 TO 3
  247.                 disx = join(a1area, a1tiles, t * 2) - join(a2area, a1tiles, t * 2): disy = join(a1area, a1tiles, t * 2 + 1) - join(a2area, a1tiles, t * 2 + 1)
  248.             p_ok = p_ok + ABS(SGN((disx * disx + disy * disy) < puzzle_s2 * (1 + together * 1.5))): NEXT t: IF p_ok <> 4 THEN _CONTINUE
  249.             'found a match here between area1 and area2 in the a1tiles tile.
  250.             REDIM analy(puzzle_x - 1, puzzle_y - 1) AS _UNSIGNED _BYTE 'put out the imaginary picture to analy
  251.             FOR a2tiles = 0 TO tiles - 1: analy(tiles(a2tiles, 4), tiles(a2tiles, 5)) = ABS(tiles(a2tiles, 6) = a1area OR tiles(a2tiles, 6) = a2area): NEXT a2tiles
  252.             tile_sum = 0: FOR anax = 0 TO puzzle_x - 1: FOR anay = 0 TO puzzle_y - 1: IF analy(anax, anay) THEN tile_sum = tile_sum + 1: sax = anax: say = anay
  253.                     NEXT anay, anax: analy(sax, say) = 2: discovery = 1: DO: discovery_old = discovery: FOR anax = 0 TO puzzle_x - 1: FOR anay = 0 TO puzzle_y - 1
  254.                         IF analy(anax, anay) <> 2 THEN _CONTINUE
  255.                         FOR t = 0 TO 3: t1 = SGN(t AND 1): t2 = SGN(t AND 2): prex = (t1 * 2 - 1) * t2 + anax: prey = (t1 * 2 - 1) * (t2 XOR 1) + anay
  256.                             IF (prex < 0 OR prex > puzzle_x - 1) OR (prey < 0 OR prey > puzzle_y - 1) THEN _CONTINUE
  257.                             IF analy(prex, prey) = 1 THEN analy(prex, prey) = 2: discovery = discovery + 1
  258.                 NEXT t, anay, anax: LOOP UNTIL discovery = discovery_old: IF discovery = tile_sum THEN
  259.                 FOR t = 0 TO tiles - 1: IF tiles(t, 6) = a1area THEN tiles(t, 6) = a2area
  260.                 NEXT t: GOSUB tile_to_center: recalc = 1: RETURN
  261. END IF: NEXT a1tiles, a2area, a1area: RETURN
  262.  
  263.  
  264.  
  265. tile_to_center:
  266. FOR atiles = 0 TO tiles - 1: avx = 0: avy = 0: av = 0
  267.     FOR atiles2 = 0 TO tiles - 1: IF tiles(atiles2, 6) = atiles THEN av = av + 1: avx = avx + tiles(atiles2, 4): avy = avy + tiles(atiles2, 5)
  268.         NEXT atiles2: IF av THEN
  269.         area_posinfo(atiles, 0) = avx / av + .5: area_posinfo(atiles, 1) = avy / av + .5 'X-Y coordinate puzzle rotating point (to mouse rotation)
  270.     ELSE area_posinfo(atiles, 5) = -1 'empty area
  271. END IF: NEXT atiles: RETURN
  272.  
  273. auto_inwindow: 'does not allow the area to exit the screen too much'
  274. IF together THEN RETURN
  275. FOR area = 0 TO tiles - 1: IF area_posinfo(area, 5) = -1 THEN _CONTINUE
  276.     minx = 9999999999: maxx = -minx: miny = minx: maxy = maxx
  277.     FOR atiles = 0 TO tiles - 1: IF tiles(atiles, 6) <> area THEN _CONTINUE
  278.         FOR t = 0 TO 7
  279.             IF t AND 1 THEN
  280.                 IF join(area, atiles, t) > maxy THEN maxy = join(area, atiles, t)
  281.                 IF join(area, atiles, t) < miny THEN miny = join(area, atiles, t)
  282.             ELSE
  283.                 IF join(area, atiles, t) > maxx THEN maxx = join(area, atiles, t)
  284.                 IF join(area, atiles, t) < minx THEN minx = join(area, atiles, t)
  285.             END IF
  286.     NEXT t: NEXT atiles: movex = (lwindow_x1 - maxx) * ABS(maxx < lwindow_x1) + (lwindow_x2 - minx) * ABS(minx > lwindow_x2)
  287.     movey = (lwindow_y1 - maxy) * ABS(maxy < lwindow_y1) + (lwindow_y2 - miny) * ABS(miny > lwindow_y2)
  288.     area_posinfo(area, 2) = area_posinfo(area, 2) + movex: area_posinfo(area, 3) = area_posinfo(area, 3) + movey
  289. area_posinfo(area, 9) = ABS(movex): area_posinfo(area, 10) = ABS(movey): NEXT area: RETURN
  290.  
  291.  
  292. shuffling: IF together THEN RETURN
  293. FOR area = 0 TO tiles - 1: IF area_posinfo(area, 5) = -1 THEN _CONTINUE
  294.     DO: shok = 1: area_posinfo(area, 2) = area_posinfo(area, 2) + area_posinfo(area, 6) * shuffle_m
  295.         area_posinfo(area, 3) = area_posinfo(area, 3) + area_posinfo(area, 7) * shuffle_m
  296.         area_posinfo(area, 4) = area_posinfo(area, 4) + area_posinfo(area, 8) * shuffle_r * (1 / 360 * puzzle_r)
  297.  
  298.         rand = (INT(rotating_moving_chance * RND(1)) = 1) AND shuffling = 0: IF rand THEN area_posinfo(area, 8) = -area_posinfo(area, 8)
  299.         IF area_posinfo(area, 9) OR rand THEN area_posinfo(area, 6) = -SGN(area_posinfo(area, 6)) * sh_rand_m: area_posinfo(area, 8) = sh_rand_v * sh_rand_m: shok = 0
  300.         IF area_posinfo(area, 10) OR rand THEN area_posinfo(area, 7) = -SGN(area_posinfo(area, 7)) * sh_rand_m: area_posinfo(area, 8) = sh_rand_v * sh_rand_m: shok = 0
  301.  
  302.  
  303.  
  304.  
  305.  
  306. area_posinfo(area, 9) = 0: area_posinfo(area, 10) = 0: LOOP WHILE shok = 0: NEXT area: RETURN
  307.  
  308.  
  309. together: IF together = 0 THEN RETURN 'tiles unification
  310. IF only1 AND only1_area = -1 THEN DO: only1_area = INT(tiles * RND(1)): LOOP WHILE area_posinfo(only1_area, 5) = -1
  311. IF only1 THEN area = only1_area - 1 ELSE area = -1
  312. DO: area = area + 1: IF area = tiles THEN EXIT DO
  313.     IF area_posinfo(area, 5) = -1 THEN only1_area = -1: _CONTINUE
  314.     difx = start_area_x_s - area_posinfo(area, 2): dify = start_area_y_s - area_posinfo(area, 3)
  315.     rotdif1 = (start_area_rotate_s - area_posinfo(area, 4)): rotdif2 = (start_area_rotate_s - (area_posinfo(area, 4) + puzzle_r))
  316.     rotdif3 = (start_area_rotate_s - (area_posinfo(area, 4) - puzzle_r))
  317.     IF ABS(rotdif1) < ABS(rotdif2) THEN rotdif = rotdif1 ELSE rotdif = rotdif2
  318.     IF ABS(rotdif3) < ABS(rotdif) THEN rotdif = rotdif3
  319.     IF only1 THEN
  320.         IF (rotdif < dislimit) AND ABS(difx) < dislimit AND ABS(dify) < dislimit THEN
  321.             area_posinfo(area, 2) = start_area_x_s: area_posinfo(area, 3) = start_area_y_s: area_posinfo(area, 4) = start_area_rotate_s: only1_area = -1: EXIT DO
  322.         END IF
  323.         IF ABS(rotdif) < dislimit AND ABS(difx) < dislimit AND ABS(dify) < dislimit THEN speed = together_speed_slow ELSE speed = together_speed
  324.     ELSE
  325.         speed = together_speed_slow
  326.     END IF
  327.     area_posinfo(area, 4) = (area_posinfo(area, 4) + (rotdif * (1 / 360 * puzzle_r) / 20 * speed)): area_posinfo(area, 2) = area_posinfo(area, 2) + difx / 10 * speed
  328.     area_posinfo(area, 3) = area_posinfo(area, 3) + dify / 10 * speed: IF only1 THEN EXIT DO
  329.  
  330.  
  331. draw2:
  332. IF atiles_st <> -1 THEN
  333.  
  334.     'which area (tile in area)  under mouse ?
  335.     oldx = (px(0) + px(1) + px(2) + px(3)) / 4 - mousex: oldy = (py(0) + py(1) + py(2) + py(3)) / 4 - mousey
  336.     x = (oldx * COS(-angle)) + (oldy * SIN(-angle)): y = (oldy * COS(-angle)) - (oldx * SIN(-angle))
  337.     IF (-ptx < x AND ptx > x) AND (-pty < y AND pty > y) AND atiles_st = 0 THEN act_area = area: act_tile = atiles
  338.  
  339.     'title part of it all
  340.     qx0 = tiles(atiles_d, 0): qy0 = tiles(atiles_d, 1): qx1 = tiles(atiles_d, 2): qy1 = qy0
  341.     qx2 = tiles(atiles_d, 0): qy2 = tiles(atiles_d, 3): qx3 = tiles(atiles_d, 2): qy3 = qy2
  342.  
  343.     'draw black border under tile
  344.     draw_actual_border = ((area = act_area_old AND und_flash) XOR 1) AND atiles_st = 0 AND puzzle_b > 0: draw_actual = atiles_st = 0 OR atiles_st = help_flash
  345.     IF draw_actual_border THEN 'draw border
  346.         FOR t = 1 TO puzzle_b - 1
  347.             mp(amp, 0) = 0: mp(amp, 1) = 0: mp(amp, 2) = 9: mp(amp, 3) = 0: mp(amp, 4) = 0: mp(amp, 5) = 9: mp(amp, 6) = 1: mp(amp, 7) = px(0) + t
  348.             mp(amp, 8) = py(0) + t: mp(amp, 9) = px(1) + t: mp(amp, 10) = py(1) + t: mp(amp, 11) = px(2) + t: mp(amp, 12) = py(2) + t: amp = amp + 1
  349.             mp(amp, 0) = 9: mp(amp, 1) = 9: mp(amp, 2) = 9: mp(amp, 3) = 0: mp(amp, 4) = 0: mp(amp, 5) = 9: mp(amp, 6) = 1: mp(amp, 7) = px(3) + t
  350.             mp(amp, 8) = py(3) + t: mp(amp, 9) = px(1) + t: mp(amp, 10) = py(1) + t: mp(amp, 11) = px(2) + t: mp(amp, 12) = py(2) + t: amp = amp + 1
  351.         NEXT t
  352.     END IF
  353.     'draw tile
  354.     IF draw_actual THEN
  355.         mp(amp, 0) = qx0: mp(amp, 1) = qy0: mp(amp, 2) = qx1: mp(amp, 3) = qy1: mp(amp, 4) = qx2: mp(amp, 5) = qy2: mp(amp, 6) = 0: mp(amp, 7) = px(0)
  356.         mp(amp, 8) = py(0): mp(amp, 9) = px(1): mp(amp, 10) = py(1): mp(amp, 11) = px(2): mp(amp, 12) = py(2): amp = amp + 1: mp(amp, 0) = qx3
  357.         mp(amp, 1) = qy3: mp(amp, 2) = qx1: mp(amp, 3) = qy1: mp(amp, 4) = qx2: mp(amp, 5) = qy2: mp(amp, 6) = 0: mp(amp, 7) = px(3): mp(amp, 8) = py(3)
  358.         mp(amp, 9) = px(1): mp(amp, 10) = py(1): mp(amp, 11) = px(2): mp(amp, 12) = py(2): amp = amp + 1
  359.     END IF
  360.  
  361. FUNCTION sh_rand_m: sh_rand_m = .5 + .5 * RND(1): END FUNCTION: FUNCTION sh_rand_v: sh_rand_v = INT(2 * RND(1)) * 2 - 1: END FUNCTION
  362. 'SIMPLE PUZZLE GAME BY MASTERGY, 2020
  363.  
  364.  
  365.  
  366.  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Simple Puzzle Game
« Reply #6 on: November 22, 2020, 12:15:09 pm »
That is really fine app you put together MasterGy! The menu is easy to use and pieces pop together very easily!
I like that I can stop rotations and moving, too old for rolly coaster rides ;-))

  [ You are not allowed to view this attachment ]