Author Topic: CatChum for CP/M  (Read 4593 times)

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

FellippeHeitor

  • Guest
CatChum for CP/M
« on: July 19, 2017, 06:09:38 am »
This is the idea:


Screenshot attached.

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(52, 24, 0)
  2.  
  3. _TITLE "CatChum for CP/M"
  4.  
  5. COLOR 2 'for a phosphor look
  6.  
  7.  
  8. CONST true = -1, false = NOT true
  9. CONST powerPelletMAX = 7 'duration of the power pellet effects
  10.  
  11. TYPE new_DOT
  12.     x AS INTEGER
  13.     y AS INTEGER
  14.     state AS _BYTE '0 = taken; 1 = dot; 2 = power pellet
  15.  
  16. DIM SHARED dot(1 TO 201) AS new_DOT
  17. DIM SHARED mapData(1 TO 23) AS STRING
  18. DIM SHARED PacMan AS new_DOT
  19. DIM SHARED ghost(1 TO 4) AS new_DOT
  20. DIM SHARED direction AS _BYTE, nextDirection AS _BYTE
  21. DIM SHARED endGame AS _BYTE, lastMove!
  22. DIM SHARED score AS LONG, powerPelletTimer AS SINGLE
  23.  
  24.     setupMap
  25.     setupDots
  26.     endGame = false
  27.     direction = 1
  28.     lastMove! = 0
  29.  
  30.     DO
  31.         CLS
  32.         processInput
  33.         movePacMan
  34.         detectColision
  35.  
  36.         drawLabyrinth
  37.         IF NOT _KEYDOWN(100306) THEN drawItems
  38.  
  39.         _PRINTSTRING (1, 24), STR$(score)
  40.         _DISPLAY
  41.         _LIMIT 30
  42.     LOOP UNTIL endGame
  43.  
  44. SUB detectColision
  45.     FOR i = 1 TO UBOUND(dot)
  46.         IF dot(i).x = PacMan.x AND dot(i).y = PacMan.y THEN
  47.             SELECT CASE dot(i).state
  48.                 CASE 1
  49.                     'dot
  50.                     score = score + 10
  51.                     dot(i).state = 0
  52.                 CASE 2
  53.                     'power pellet
  54.                     score = score + 20
  55.                     dot(i).state = 0
  56.                     powerPelletTimer = TIMER
  57.             END SELECT
  58.         END IF
  59.     NEXT
  60.  
  61. SUB movePacMan
  62.     STATIC didMove AS _BYTE
  63.  
  64.     DIM refreshRate!
  65.  
  66.     IF direction = 1 OR direction = 3 THEN refreshRate! = .1
  67.     IF direction = 2 OR direction = 4 THEN refreshRate! = .12
  68.  
  69.     IF TIMER - lastMove! < refreshRate! THEN EXIT SUB
  70.  
  71.     IF didMove = false AND lastMove! > 0 THEN direction = 0
  72.  
  73.     lastMove! = TIMER
  74.  
  75.     'same axis changes are immediately applied
  76.     SELECT CASE nextDirection
  77.         CASE 1, 3
  78.             IF direction = 1 OR direction = 3 THEN direction = nextDirection: nextDirection = 0
  79.         CASE 2, 4
  80.             IF direction = 2 OR direction = 4 THEN direction = nextDirection: nextDirection = 0
  81.     END SELECT
  82.  
  83.     IF direction = 0 THEN direction = nextDirection
  84.  
  85.     DIM prevDirection AS _BYTE
  86.  
  87.     IF nextDirection THEN
  88.         prevDirection = direction
  89.         direction = nextDirection
  90.     END IF
  91.  
  92.     didMove = false
  93.     DIM i AS INTEGER
  94.     FOR i = 1 TO 2
  95.         SELECT CASE direction
  96.             CASE 1 'left
  97.                 IF PacMan.x > 1 THEN
  98.                     IF ASC(mapData(PacMan.y), PacMan.x - 1) = 32 THEN
  99.                         PacMan.x = PacMan.x - 1
  100.                         didMove = true
  101.                         EXIT FOR
  102.                     ELSE
  103.                         IF prevDirection THEN
  104.                             nextDirection = direction
  105.                             direction = prevDirection
  106.                         END IF
  107.                     END IF
  108.                 ELSE 'warp
  109.                     PacMan.x = LEN(mapData(1))
  110.                     didMove = true
  111.                 END IF
  112.             CASE 2 'up
  113.                 IF PacMan.y > 1 THEN
  114.                     IF ASC(mapData(PacMan.y - 1), PacMan.x) = 32 THEN
  115.                         PacMan.y = PacMan.y - 1
  116.                         didMove = true
  117.                         EXIT FOR
  118.                     ELSE
  119.                         IF prevDirection THEN
  120.                             nextDirection = direction
  121.                             direction = prevDirection
  122.                         END IF
  123.                     END IF
  124.                 ELSE 'warp
  125.                     PacMan.y = 23
  126.                     didMove = true
  127.                 END IF
  128.             CASE 3 'right
  129.                 IF PacMan.x < LEN(mapData(1)) THEN
  130.                     IF ASC(mapData(PacMan.y), PacMan.x + 1) = 32 THEN
  131.                         PacMan.x = PacMan.x + 1
  132.                         didMove = true
  133.                         EXIT FOR
  134.                     ELSE
  135.                         IF prevDirection THEN
  136.                             nextDirection = direction
  137.                             direction = prevDirection
  138.                         END IF
  139.                     END IF
  140.                 ELSE 'warp
  141.                     PacMan.x = 1
  142.                     didMove = true
  143.                 END IF
  144.             CASE 4 'down
  145.                 IF PacMan.y < 23 THEN
  146.                     IF ASC(mapData(PacMan.y + 1), PacMan.x) = 32 THEN
  147.                         PacMan.y = PacMan.y + 1
  148.                         didMove = true
  149.                         EXIT FOR
  150.                     ELSE
  151.                         IF prevDirection THEN
  152.                             nextDirection = direction
  153.                             direction = prevDirection
  154.                         END IF
  155.                     END IF
  156.                 ELSE 'warp
  157.                     PacMan.y = 1
  158.                     didMove = true
  159.                 END IF
  160.         END SELECT
  161.     NEXT
  162.  
  163. SUB processInput
  164.     DIM k AS LONG
  165.  
  166.     k = _KEYHIT
  167.     IF k = 27 THEN endGame = true
  168.  
  169.     IF _KEYDOWN(19200) THEN nextDirection = 1
  170.     IF _KEYDOWN(18432) THEN nextDirection = 2
  171.     IF _KEYDOWN(19712) THEN nextDirection = 3
  172.     IF _KEYDOWN(20480) THEN nextDirection = 4
  173.  
  174. SUB setupMap
  175.     DIM i AS INTEGER
  176.  
  177.     RESTORE
  178.     FOR i = 1 TO 23
  179.         READ mapData(i)
  180.     NEXT
  181.  
  182. SUB setupDots
  183.     DIM i AS INTEGER
  184.  
  185.     FOR i = 1 TO 23
  186.         DIM c AS INTEGER, thisDot AS INTEGER, thisGhost AS INTEGER
  187.  
  188.         FOR c = 1 TO LEN(mapData(i))
  189.             SELECT CASE ASC(mapData(i), c)
  190.                 CASE 46
  191.                     'dot
  192.                     ASC(mapData(i), c) = 32
  193.                     thisDot = thisDot + 1
  194.                     dot(thisDot).x = c
  195.                     dot(thisDot).y = i
  196.                     dot(thisDot).state = 1
  197.                 CASE 111
  198.                     'power pellet
  199.                     ASC(mapData(i), c) = 32
  200.                     thisDot = thisDot + 1
  201.                     dot(thisDot).x = c
  202.                     dot(thisDot).y = i
  203.                     dot(thisDot).state = 2
  204.                 CASE 65
  205.                     'ghost
  206.                     ASC(mapData(i), c) = 32
  207.                     thisGhost = thisGhost + 1
  208.                     ghost(thisGhost).x = c
  209.                     ghost(thisGhost).y = i
  210.                     ghost(thisGhost).state = true
  211.                 CASE 67
  212.                     'PacMan
  213.                     ASC(mapData(i), c) = 32
  214.                     PacMan.x = c
  215.                     PacMan.y = i
  216.                 CASE 35
  217.                     'wall separator
  218.                     ASC(mapData(i), c) = 0
  219.             END SELECT
  220.         NEXT
  221.     NEXT
  222.  
  223. SUB drawLabyrinth
  224.     DIM i AS INTEGER
  225.  
  226.     FOR i = 1 TO 23
  227.         _PRINTSTRING (3, i), mapData(i)
  228.     NEXT
  229.  
  230. SUB drawItems
  231.     DIM i AS INTEGER, c$
  232.  
  233.     FOR i = 1 TO UBOUND(dot)
  234.         c$ = " "
  235.         IF dot(i).state = 1 THEN c$ = "."
  236.         IF dot(i).state = 2 THEN c$ = "o"
  237.         _PRINTSTRING (2 + dot(i).x, dot(i).y), c$
  238.     NEXT
  239.  
  240.     SELECT CASE direction
  241.         CASE 0
  242.             PacManChar$ = "C"
  243.         CASE 1, 3 'left or right
  244.             IF PacMan.x MOD 2 = 0 THEN PacManChar$ = "C" ELSE PacManChar$ = "c"
  245.         CASE 2, 4 'up or down
  246.             IF PacMan.y MOD 2 <> 0 THEN PacManChar$ = "C" ELSE PacManChar$ = "c"
  247.     END SELECT
  248.  
  249.     _PRINTSTRING (2 + PacMan.x, PacMan.y), PacManChar$
  250.  
  251.     IF TIMER - powerPelletTimer < powerPelletMAX THEN ghostChar$ = "m" ELSE ghostChar$ = "A"
  252.  
  253.     FOR i = 1 TO UBOUND(ghost)
  254.         _PRINTSTRING (2 + ghost(i).x, ghost(i).y), ghostChar$
  255.     NEXT
  256.  
  257. 'Map data
  258. DATA "+-------------------+# #+# #+-------------------+"
  259. DATA "|#. . . . . . . . . . .#|#. . . . . . . . . . .#|"
  260. DATA "|#.#+-----+#.#+-----+#.#|#.#+-----+#.#+-----+#.#|"
  261. DATA "|#o#|     |#.#|     |#.#|#.#|     |#.#|     |#o#|"
  262. DATA "|#.#+-----+#.#+-----+#.#|#.#+-----+#.#+-----+#.#|"
  263. DATA "|#. . . . . . . . . . .#|#. . . . . . . . . . .#|"
  264. DATA "|#.#-------#.#|#.#------+------#.#|#.#-------#.#|"
  265. DATA "|#. . . . . .#|#. . . .#|#. . . .#|#. . . . . .#|"
  266. DATA "+---------+#.#------+# #|# #+-----+#.#+---------+"
  267. DATA "          |#.#|#                 #|#.#|          "
  268. DATA "----------+#.#|# #+-----#-----+# #|#.#+----------"
  269. DATA "            .    #|  A A A A  |#    .            "
  270. DATA "----------+#.#|# #+-----#-----+# #|#.#+----------"
  271. DATA "          |#.#|#                 #|#.#|          "
  272. DATA "+---------+#.#|# #------+------# #|#.#+---------+"
  273. DATA "|#. . . . . . . . . . .#|#. . . . . . . . . . .#|"
  274. DATA "|#.#------+#.#-------#.#|#.#-------#.#+------#.#|"
  275. DATA "|#o . . .#|#. . . . . . C . . . . . .#|#. . . o#|"
  276. DATA "+------#.#|#.#|# #-------------# #|#.#|#.#------+"
  277. DATA "|#. . . . . .#|#. . . . . . . . .#|#. . . . . .#|"
  278. DATA "|#.#----------+------#.#|#.#------+----------#.#|"
  279. DATA "|#. . . . . . . . . . .#|#. . . . . . . . . . .#|"
  280. DATA "+-------------------+# #+# #+-------------------+"
  281.  

I'll be posting the progress here as I go.
« Last Edit: July 19, 2017, 06:12:08 am by FellippeHeitor »

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
Re: CatChum for CP/M
« Reply #1 on: July 19, 2017, 09:43:21 am »
Nice! I like it! :)
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials

Offline keybone

  • Forum Regular
  • Posts: 116
  • My name a Nursultan Tulyakbay.
Re: CatChum for CP/M
« Reply #2 on: July 19, 2017, 12:16:31 pm »
Wow, CP/M. Now thats oldschool. :)
« Last Edit: July 19, 2017, 01:28:13 pm by keybone »
I am from a Kazakhstan, we follow the hawk.

Offline Aureal

  • Newbie
  • Posts: 17
  • memes
Re: CatChum for CP/M
« Reply #3 on: July 19, 2017, 09:47:14 pm »
I like it a lot!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
Re: CatChum for CP/M
« Reply #4 on: July 20, 2017, 10:55:48 am »
Hi, nice game!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: CatChum for CP/M
« Reply #5 on: July 21, 2017, 11:08:47 am »
If you're looking to reproduce authentic style Pacman gameplay, you might want to take a look at this link: http://gameinternals.com/post/2072558330/understanding-pac-man-ghost-behavior

That does the best job of any write up which I've ever seen, explaining how the Ghost AI behaves and operates in Pacman.  It might be of some use to you.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

FellippeHeitor

  • Guest
Re: CatChum for CP/M
« Reply #6 on: July 21, 2017, 12:24:32 pm »
Thanks for sharing the link, Steve!

I'd looked at that article before, and it kinda slowed me down, as I figured it'd be harder than just chasing Pacman. This updated version in the attachment has ghosts doing just that, chasing Pacman blindly.

Maybe I'll get to it when I'm on vacation again.

PS: Hit "m" for a more "modern" look, as in the screenshot.

PS2: Ghosts are harmless for now.
« Last Edit: July 21, 2017, 12:28:34 pm by FellippeHeitor »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
Re: CatChum for CP/M
« Reply #7 on: July 22, 2017, 03:22:48 am »
Hi Fellippe, on line 139 - its new command _CONTINUE ? My IDE write syntax error for this, i comment this line and then it start. I like new graphic after m press.

FellippeHeitor

  • Guest
Re: CatChum for CP/M
« Reply #8 on: July 22, 2017, 10:04:01 am »
Hi Petr.

Yes, _CONTINUE is a new QB64 statement introduced in build 20170628/55. It works exactly like its C counterpart:

Quote
The continue statement in C programming works somewhat like the break statement. Instead of forcing termination, it forces the next iteration of the loop to take place, skipping any code in between.
From https://www.tutorialspoint.com/cprogramming/c_continue_statement.htm

It's a shortcut to a goto, and if you look in the C++ output, that's exactly what it does. Take the code below:

Code: QB64: [Select]
  1. FOR i = 1 to 10
  2.     IF i = 5 THEN GOTO skip
  3.     PRINT i;
  4.     skip:

You can write the same using _CONTINUE as follows:
Code: QB64: [Select]
  1. FOR i = 1 to 10
  2.     IF i = 5 THEN _CONTINUE
  3.     PRINT i;

Both will output:
Quote
1 2 3 4 6 7 8 9 10

You can also use _CONTINUE in DO/LOOP and WHILE/WEND blocks, with the same purpose of skipping to the end of the block without exiting it.

Marked as best answer by on April 03, 2024, 05:11:05 pm

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
Re: CatChum for CP/M
« Reply #9 on: July 22, 2017, 01:25:11 pm »
  • Undo Best Answer
  • Hi FellippeHeitor, thank you for your clear explanation. So it's time to upgrade my IDE ...