Author Topic: Blocking the way of a character  (Read 3016 times)

0 Members and 1 Guest are viewing this topic.

Offline Prithak

  • Newbie
  • Posts: 56
  • Life itself is a Programming Language!
    • View Profile
    • My Programming Language
Blocking the way of a character
« on: January 23, 2019, 07:01:57 am »
Here, I have a character which has (x,y) co-ordinates and I also have a box in the co-ordinates (Let's assume, (100,100) and (200,200))

Now, I have to make the character not enter the box (block it from entering)

What should I do?

Here's what I came up with:

Code: QB64: [Select]
  1. FUNCTION detect(x,y,x1,y1,x2,y2) 'This is the detection function for just rectangles
  2.     IF x >= x1 AND x <= x2 AND y >= y1 AND y <= y2 THEN
  3.         detect = -1
  4.     END IF
  5. SUB block (x, y, x1, y1, x2, y2) 'The block sub
  6.     IF detect(x, y, x1, y1, x2, y1) THEN
  7.         y = y - 20
  8.     ELSEIF detect(x, y, x1, y2, x2, y2) THEN
  9.         y = y + 5
  10.     ELSEIF detect(x, y, x1, y1, x1, y2) THEN
  11.         x = x - 20
  12.     ELSEIF detect(x, y, x2, y1, x2, y2) THEN
  13.         x = x + 20
  14.     END IF
  15.  

But still, it isn't properly working... What is a viable solution to this?
CLS
IF computer$ = "ON" THEN
me$ = "Happy!"
ELSE
me$ = "Time To Draw!"
END IF
END

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Blocking the way of a character
« Reply #1 on: January 23, 2019, 10:18:41 am »
One method I often use is Flags. If your map is a array(I would image so) you could have a flag for each array space called Occupied%% (or type defined Occupied as _byte) and if there is something in that space or some reason you(or a NPC) could not walk in that space you set the flag, Occupied%%, to TRUE (-1) then in the movement routine you check if that map square is walkable ore not by checking the flag.
Simple Example of checking
Code: QB64: [Select]
  1. If NOT Map(x,y).Occupied  then
  2. 'allow movement to that square
  3. 'block movement to that square
  4.  

or if you didn't want to have a UDT for you map array you could have a second array Occupied(100,100) AS _BYTE
and just change the initial IF
Code: QB64: [Select]
  1. If NOT Occupied(x,y) then
  2.  
rest would be the same.

personally I like assigning a TYPE to my map array to allow for more control options but this is a simple way I have found to block out whole map squares from movement.
Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Blocking the way of a character
« Reply #2 on: January 23, 2019, 11:42:18 am »
Hi Prithak,

Your character is likely to also take the shape of a box, such that you will need to prevent overlap of two boxes. Johnno has supplied us with a simple collision detection code for two boxes that I fixed up for a reusable routine.

Here is a demo of using that collision detection to prevent the box at the mouse position from entering the forbidden white box in center of screen:
Code: QB64: [Select]
  1. _TITLE "Block mouse box entry to another box" ' demo for Prithak by B+ 2019-01-23
  2. ' from Collision of Rectangular Images started by Johnno mod b+ 2018-06-10"
  3. ' 2018-06-10 mod by B+ change for x, y, w, h of images
  4. ' by readjusting all the variables and use STEP for box drawing
  5. ' Generalize the specific gosub routine from this one app so can reuse IN ANY APP using sprites / tiles / images
  6.  
  7. SCREEN _NEWIMAGE(800, 600, 32) '<<< something more standard center is 400, 300
  8.  
  9. ' sprites / tiles / images are typically referred to by their left top corner ie X, Y  and their width and height
  10.  
  11. 'lets do the height and width first of the  forbidden box
  12. box1Width = 400 '<<< mod add this instead of above
  13. box1Height = 100 '<<< mod add this instead of above
  14.  
  15. 'now center the forbidden box
  16. box1Left = 400 - box1Width / 2 'same as box1X
  17. box1Top = 300 - box1Height / 2 'same as box1Y
  18.  
  19. 'the box for the character at the mouse pointer
  20. mouseboxWidth = 50 '<<< mod add these constants
  21. mouseboxHeight = 40 '<<< mod add these constants
  22.  
  23.     k$ = INKEY$
  24.     COLOR _RGB32(255, 255, 255), _RGB32(0, 0, 0)
  25.     CLS
  26.  
  27.     'box of forbidden entry
  28.     LINE (box1Left, box1Top)-STEP(box1Width, box1Height), _RGB32(255, 255, 255), BF
  29.     COLOR _RGB32(0, 0, 0), _RGB32(255, 255, 255)
  30.     _PRINTSTRING (box1Left + 120, box1Top + 45), "Forbidden to Enter Box"
  31.  
  32.     WHILE _MOUSEINPUT: WEND '<<< this is all the loop needed for mouse input
  33.     mouseboxX = _MOUSEX - mouseboxWidth / 2
  34.     mouseboxY = _MOUSEY - mouseboxHeight / 2
  35.  
  36.     IF collision%(box1Left, box1Top, box1Width, box1Height, mouseboxX, mouseboxY, mouseboxWidth, mouseboxHeight) = 1 THEN
  37.         mouseboxX = oldMouseBoxX: mouseboxY = oldMouseBoxY
  38.     ELSE
  39.         oldMouseBoxX = mouseboxX: oldMouseBoxY = mouseboxY
  40.     END IF
  41.  
  42.     'draw character at mouse box
  43.     LINE (mouseboxX, mouseboxY)-STEP(mouseboxWidth, mouseboxHeight), _RGB32(255, 128, 0), BF '<<< use step with width and height
  44.  
  45.     _DISPLAY
  46.     _LIMIT 50 '<<< save the fan
  47. LOOP UNTIL k$ = CHR$(27)
  48.  
  49. 'very handy function to detect if 2 boxes will overlap, given their top left corner and width and height, Thanks Johnno
  50. FUNCTION collision% (b1x, b1y, b1w, b1h, b2x, b2y, b2w, b2h)
  51.     ' yes a type smaller than integer might be used
  52.     ' x, y represent the box left most x and top most y
  53.     ' w, h represent the box width and height which is the usual way sprites / tiles / images are described
  54.     ' such that boxbottom = by + bh
  55.     '        and boxright = bx + bw
  56.     'so the specific gosub above is gerealized to a function procedure here!
  57.     IF (b1y + b1h < b2y) OR (b1y > b2y + b2h) OR (b1x > b2x + b2w) OR (b1x + b1w < b2x) THEN
  58.         collision% = 0
  59.     ELSE
  60.         collision% = 1
  61.     END IF
  62.  
  63.  
« Last Edit: January 23, 2019, 11:49:22 am by bplus »

Offline Prithak

  • Newbie
  • Posts: 56
  • Life itself is a Programming Language!
    • View Profile
    • My Programming Language
Re: Blocking the way of a character
« Reply #3 on: January 23, 2019, 09:46:15 pm »
Hi Prithak,

Your character is likely to also take the shape of a box, such that you will need to prevent overlap of two boxes. Johnno has supplied us with a simple collision detection code for two boxes that I fixed up for a reusable routine.

Here is a demo of using that collision detection to prevent the box at the mouse position from entering the forbidden white box in center of screen:
Code: QB64: [Select]
  1. _TITLE "Block mouse box entry to another box" ' demo for Prithak by B+ 2019-01-23
  2. ' from Collision of Rectangular Images started by Johnno mod b+ 2018-06-10"
  3. ' 2018-06-10 mod by B+ change for x, y, w, h of images
  4. ' by readjusting all the variables and use STEP for box drawing
  5. ' Generalize the specific gosub routine from this one app so can reuse IN ANY APP using sprites / tiles / images
  6.  
  7. SCREEN _NEWIMAGE(800, 600, 32) '<<< something more standard center is 400, 300
  8.  
  9. ' sprites / tiles / images are typically referred to by their left top corner ie X, Y  and their width and height
  10.  
  11. 'lets do the height and width first of the  forbidden box
  12. box1Width = 400 '<<< mod add this instead of above
  13. box1Height = 100 '<<< mod add this instead of above
  14.  
  15. 'now center the forbidden box
  16. box1Left = 400 - box1Width / 2 'same as box1X
  17. box1Top = 300 - box1Height / 2 'same as box1Y
  18.  
  19. 'the box for the character at the mouse pointer
  20. mouseboxWidth = 50 '<<< mod add these constants
  21. mouseboxHeight = 40 '<<< mod add these constants
  22.  
  23.     k$ = INKEY$
  24.     COLOR _RGB32(255, 255, 255), _RGB32(0, 0, 0)
  25.     CLS
  26.  
  27.     'box of forbidden entry
  28.     LINE (box1Left, box1Top)-STEP(box1Width, box1Height), _RGB32(255, 255, 255), BF
  29.     COLOR _RGB32(0, 0, 0), _RGB32(255, 255, 255)
  30.     _PRINTSTRING (box1Left + 120, box1Top + 45), "Forbidden to Enter Box"
  31.  
  32.     WHILE _MOUSEINPUT: WEND '<<< this is all the loop needed for mouse input
  33.     mouseboxX = _MOUSEX - mouseboxWidth / 2
  34.     mouseboxY = _MOUSEY - mouseboxHeight / 2
  35.  
  36.     IF collision%(box1Left, box1Top, box1Width, box1Height, mouseboxX, mouseboxY, mouseboxWidth, mouseboxHeight) = 1 THEN
  37.         mouseboxX = oldMouseBoxX: mouseboxY = oldMouseBoxY
  38.     ELSE
  39.         oldMouseBoxX = mouseboxX: oldMouseBoxY = mouseboxY
  40.     END IF
  41.  
  42.     'draw character at mouse box
  43.     LINE (mouseboxX, mouseboxY)-STEP(mouseboxWidth, mouseboxHeight), _RGB32(255, 128, 0), BF '<<< use step with width and height
  44.  
  45.     _DISPLAY
  46.     _LIMIT 50 '<<< save the fan
  47. LOOP UNTIL k$ = CHR$(27)
  48.  
  49. 'very handy function to detect if 2 boxes will overlap, given their top left corner and width and height, Thanks Johnno
  50. FUNCTION collision% (b1x, b1y, b1w, b1h, b2x, b2y, b2w, b2h)
  51.     ' yes a type smaller than integer might be used
  52.     ' x, y represent the box left most x and top most y
  53.     ' w, h represent the box width and height which is the usual way sprites / tiles / images are described
  54.     ' such that boxbottom = by + bh
  55.     '        and boxright = bx + bw
  56.     'so the specific gosub above is gerealized to a function procedure here!
  57.     IF (b1y + b1h < b2y) OR (b1y > b2y + b2h) OR (b1x > b2x + b2w) OR (b1x + b1w < b2x) THEN
  58.         collision% = 0
  59.     ELSE
  60.         collision% = 1
  61.     END IF
  62.  
  63.  
Thank you bplus but my code worked out. I made my character a circle and it's radius to 10. Somehow, it worked out.... But I still think I should use this function tho...
CLS
IF computer$ = "ON" THEN
me$ = "Happy!"
ELSE
me$ = "Time To Draw!"
END IF
END