Author Topic: Need some help with player movement..  (Read 6672 times)

0 Members and 1 Guest are viewing this topic.

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Need some help with player movement..
« on: October 09, 2019, 01:28:34 pm »
I have a tile based game I'm playing around with, but am having some issues getting the player to move correctly.
The tiles and character are 32pix square.

Player can move in the 4 main directions.

There is a slight (.1 sec) delay before the character starts to move, that way the player can look in a direction without moving in that direction right away.

the character moves by pixels (so moves 32 pixels per tile)

the character finishes moving even if direction key is no longer pressed, so if the player is halfway through a tile the animation needs to finish them into the next tile before stopping.

I can manage the delay and direction but when(IF) the character starts moving they don't stop until the array errors out. I've tried using TIMERs, I've try using flags, its just not working for me. Can't shut down the whole execution to move the player cause there are other NPCs that need to be able to move in time with the player. so this has to happen 'in flow' EX;
Code: [Select]
Do
 control routine...
 if player moving then do frame of movement...
 if NPCs are moving then move NPCs a frame of movement....
 do other house keeping....
 build screen....
 display screen...
 delay...
Loop until quit
and execution needs to be constant.

I can get it to move by whole tiles, I just can't get the 32pixel walk to work. and I'm at my wits end with this. I really need help with the mechanics of that part, the controls, graphics, and final movement I can get, it is just that 1 phase that is not working.

Bplus, [banned user], Steve, you guys have any ideas?
Granted after becoming radioactive I only have a half-life!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Need some help with player movement..
« Reply #1 on: October 09, 2019, 01:50:49 pm »
Hi Cobalt. Is very hard to say, what is wrong without real source code. If your character step is 32 pixels, try use something as this:

Code: QB64: [Select]
  1. character_position = 160
  2.  
  3. DO UNTIL i$ = CHR$(27)
  4.     i$ = INKEY$
  5.     IF i$ = "a" THEN char_step = 1
  6.     IF i$ = "z" THEN char_step = -1
  7.     IF i$ = "" THEN char_step = 0
  8.  
  9.     IF LEN(i$) THEN
  10.         FOR move = 1 TO 32 'character size = 32 pixels
  11.             character_position = character_position + char_step
  12.             CLS
  13.             LINE (character_position, 100)-(character_position + 32, 132), , B
  14.             _DELAY .01
  15.         NEXT
  16.         i$ = ""
  17.     END IF
  18.  
  19.  
  20.     LINE (character_position, 100)-(character_position + 32, 132), , B
  21.  

OR maybe, if character start moving, then limit graphic shift with DO UNTIL move MOD 32 = 0 condition after first pixel increase or decrease.
« Last Edit: October 09, 2019, 02:01:22 pm by Petr »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Need some help with player movement..
« Reply #2 on: October 09, 2019, 01:53:34 pm »
Hi Cobalt,

I think I would set a target x, y for character movement to reach, when the character was within a limit of that target (using distance formula) I would snap the character image into the tile. You could even have code to check that character IS closing in on target and alert you if it weren't or just snap it in then.
« Last Edit: October 09, 2019, 02:02:07 pm by bplus »

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Need some help with player movement..
« Reply #3 on: October 09, 2019, 05:59:21 pm »
Hi Cobalt. Is very hard to say, what is wrong without real source code. If your character step is 32 pixels, try use something as this:

If you think the source would help, good luck!


my last incarnation of failure, attempting to use a TIMER to control the movement.
« Last Edit: October 15, 2019, 01:13:53 pm by Cobalt »
Granted after becoming radioactive I only have a half-life!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Need some help with player movement..
« Reply #4 on: October 10, 2019, 05:38:25 am »
Hi Cobalt, thank you, i try it.  Which IDE version you use? Unknown statement _SETBIT found on line 436.
« Last Edit: October 10, 2019, 05:42:22 am by Petr »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Need some help with player movement..
« Reply #5 on: October 10, 2019, 08:02:20 am »
I commented on rows that use the command above. I'm confused by your colission function. I have never seen a similar example of using SELECT CASE. Are you really sure that the function returns the expected results? I prefer to use a two-dimensional array for this type of detection.

Code: QB64: [Select]
  1. FOR T = 1 TO 34
  2.     result = 0
  3.     SELECT CASE T
  4.         CASE 1, 2, 3, 5, 6, 19 TO 23, 27, 30, 32, 33, 34
  5.             result = 1
  6.     END SELECT
  7.     PRINT "Value for T:"; T; "Result:"; result
  8.     SLEEP
  9.  

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Need some help with player movement..
« Reply #6 on: October 10, 2019, 08:07:13 am »
Hi Cobalt
I confirm the experience of Petr if I load your code into QB64.

about the issue please answer to these questions:
Quote
when(IF) the character starts moving they don't stop until the array errors out.
1. the sprite array for animation uses an index used also for the other events of the game ?

Quote
Can't shut down the whole execution to move the player cause there are other NPCs that need to be able to move in time with the player. so this has to happen 'in flow' E
2. Do NPCs use player's moves to do their move?


Quote
the character finishes moving even if direction key is no longer pressed, so if the player is halfway through a tile the animation needs to finish them into the next tile before stopping.
3. do you like to end move when character gains the end of the tile where it is now?


Quote
Do
 control routine...
 if player moving then do frame of movement...
 if NPCs are moving then move NPCs a frame of movement....
 do other house keeping....
 build screen....
 display screen...
 delay...
Loop until quit
4. How does control_routine pass the Inputs/commands to this general engine_Loop?


Here a clear semplification of example posted by Petr
Code: QB64: [Select]
  1. character_position = 160
  2. TileLimit = 30
  3. DO UNTIL i$ = CHR$(27)
  4.     i$ = INKEY$
  5.     IF i$ = "a" THEN char_step = 1
  6.     IF i$ = "z" THEN char_step = -1
  7.     IF i$ = "" THEN char_step = 0
  8.  
  9.     IF LEN(i$) THEN
  10.         FOR move = 1 TO 32 'character size = 32 pixels
  11.             ' stopping if it reaches the limit of movement (border of tale or other kind of limit)
  12.             IF character_position + char_step <> TileLimit THEN character_position = character_position + char_step
  13.             CLS
  14.             LINE (TileLimit, 0)-(TileLimit, 300), 14
  15.             LINE (character_position, 100)-(character_position + 32, 132), , B
  16.             _DELAY .01
  17.         NEXT
  18.         i$ = ""
  19.     END IF
  20.  
  21.     LINE (TileLimit, 0)-(TileLimit, 300), 14
  22.     LINE (character_position, 100)-(character_position + 32, 132), , B
  23.  
  24.  
Programming isn't difficult, only it's  consuming time and coffee

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Need some help with player movement..
« Reply #7 on: October 10, 2019, 08:17:34 am »
Thank you, TempodiBasic. Better outputs are, if you replace on row 19  I$ = ""  to _KEYCLEAR  for case, if is key still pressed.

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Need some help with player movement..
« Reply #8 on: October 10, 2019, 10:39:44 am »
Hi Cobalt, thank you, i try it.  Which IDE version you use? Unknown statement _SETBIT found on line 436.

this version:
https://www.qb64.org/forum/index.php?topic=1664.msg108951#msg108951

I commented on rows that use the command above. I'm confused by your colission function. I have never seen a similar example of using SELECT CASE. Are you really sure that the function returns the expected results? I prefer to use a two-dimensional array for this type of detection.
see lines 286-289, that is all debugging and represents those 4 '0's along the right hand of the screen. if the bottom number turns -1 its found a collision. Which uses an array(PLACE(27,45,45)) and checks which sprite is displayed for 'walkable' and 'not walkable'.

Hi Cobalt
I confirm the experience of Petr if I load your code into QB64.

about the issue please answer to these questions:
1. the sprite array for animation uses an index used also for the other events of the game ?
there are, simply enough, only 2 frames for each direction and the TIMER(T(0)) simply toggles the Frame%% value. It has no other barring on the program.
When I referred to 'animation' I was referring to the movement from one tile to another.

2. Do NPCs use player's moves to do their move?
They will use a mirror of the same routine. Just with the NPCs data set. With random chance to change direction and\or move.

3. do you like to end move when character gains the end of the tile where it is now?
Unless the player still has the key pressed (_KEYDOWN) for the current direction of movement then it needs to keep moving 'smoothly' without a jitter each time the player finishes onto a tile.

4. How does control_routine pass the Inputs/commands to this general engine_Loop?
In this incarnation of failure, it simply sets the direction the player is facing then turns on a TIMER. Which runs the MOVE_PLAYER routine. Which sets the Moving flag. I have used the Controls routine to return a flag value to have the routine move_player called from the main loop too, again failure.



What I am seeking help with is a way to finish a move onto the next tile when the player may stop pressing the direction key after starting the move. All my bag-o-tricks have failed so far.


Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Need some help with player movement..
« Reply #9 on: October 10, 2019, 11:36:46 am »
As you can see, the player acquires the target position no matter what speed it is going...

Code: QB64: [Select]
  1. _TITLE "Aquiring Target Positions" 'for Colbalt 2019-10-10 B+
  2. CONST xmax = 800, ymax = 600
  3. SCREEN _NEWIMAGE(xmax, ymax, 32)
  4. _SCREENMOVE 300, 40
  5. TYPE xyType
  6.     x AS INTEGER
  7.     y AS INTEGER
  8.     hit AS INTEGER
  9. DIM SHARED targets(1 TO 100) AS xyType
  10. FOR i = 1 TO 100
  11.     targets(i).x = RND * xmax \ 1
  12.     targets(i).y = RND * ymax \ 1
  13. DIM SHARED px, py, target, dwell
  14. px = 400: py = 300: target = 1: dx = 5: dy = 5
  15. WHILE _KEYDOWN(27) = 0
  16.     update
  17.     IF dwell THEN
  18.         dwell = dwell - 1
  19.     ELSE
  20.         curDist = dist(px, py, targets(target).x, targets(target).y)
  21.         IF dist(px + dx, py, targets(target).x, targets(target).y) < curDist THEN
  22.             px = px + dx
  23.         ELSEIF dist(px - dx, py, targets(target).x, targets(target).y) < curDist THEN
  24.             px = px - dx
  25.         ELSEIF dist(px, py + dy, targets(target).x, targets(target).y) < curDist THEN
  26.             py = py + dy
  27.         ELSEIF dist(px, py - dy, targets(target).x, targets(target).y) < curDist THEN
  28.             py = py - dy
  29.         ELSE
  30.             'must be as close as we cane be so be there!
  31.             px = targets(target).x: py = targets(target).y: dwell = 20
  32.             'record the achievement
  33.             targets(target).hit = -1
  34.             'set next target
  35.             target = target + 1: dx = dx + 1: dy = dy + 1
  36.             IF target > 100 THEN update: PRINT "All Targets Hit!": END
  37.         END IF
  38.     END IF
  39.     _DISPLAY
  40.     _LIMIT 30
  41.  
  42. FUNCTION dist (x, y, x1, y1)
  43.     dist = ((x - x1) ^ 2 + (y - y1) ^ 2) ^ .5
  44.  
  45. SUB drawTarget (x, y)
  46.     FOR i = 0 TO 7
  47.         IF (i \ 1) MOD 2 THEN CIRCLE (x, y), i, &HFFFFFFFF ELSE CIRCLE (x, y), i, &HFFFF0000
  48.     NEXT
  49.  
  50. SUB update
  51.     CLS
  52.     FOR i = 1 TO 100
  53.         IF targets(i).hit = 0 THEN
  54.             IF i <> target THEN
  55.                 CIRCLE (targets(i).x, targets(i).y), 8, &HFFFFFF00
  56.             ELSE
  57.                 drawTarget targets(i).x, targets(i).y
  58.             END IF
  59.         END IF
  60.     NEXT
  61.     IF dwell THEN CIRCLE (targets(target - 1).x, targets(target - 1).y), 6, &HFFFFFF00
  62.     LINE (px - 3, py - 3)-STEP(6, 6), &HFF0000FF, BF
  63.  

I added a dwell whenever a target has been hit.

Modified again to show that the square player image is precisely located correctly in place.
« Last Edit: October 10, 2019, 12:22:00 pm by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Need some help with player movement..
« Reply #10 on: October 10, 2019, 01:35:11 pm »
Hi Cobalt

so _SETBIT is one of your innovations for QB64
and I am fear that we must wait just some time before we can go on trying your code after downloading the new version of QB64 from github that has into it your innovations!

or in the while you can post a workaround for now until the gap is not covered.

Quote
syntax _SETBIT(VariableToset, parameter?%)

_SETBIT sets the high/low bit (or nibble) of a variable following the action activated by parameter?%

Parameter?% can have these values ?-?-?-?  or this range of values min??-max??

PS
looking at your static code (without possibility to run it for now)
this is my feedback

Code: QB64: [Select]
  1.  SUB Move_Player ()
  2.     IF P(0).Map >= 0 THEN X%% = P(0).MapX: Y%% = P(0).MapY ELSE X%% = P(0).WorldX: Y%% = P(0).WorldY
  3.     SELECT CASE P(Who%%).Facing
  4.         CASE DOWN
  5.             BEEP
  6.             IF Collision(0, X%%, Y%% + 1) = FALSE THEN
  7.                 G.Moving = TRUE
  8.                 P(0).MoveY = P(0).MoveY + 1   '<--- here you increase position of character on the world
  9.                 IF P(0).MoveY >= 32 THEN   ' <--- here only if character has done 32 pixel steps you stop movement of character
  10.                                  ' ^
  11.                                  ' | so here  you must add the Flag to control the movement of your character following your will
  12.                                  ' | with for example an ...OR FlagStop%% THEN
  13.                     G.Moving = FALSE: TIMER(T(1)) OFF
  14.                     IF P(0).Map >= 0 THEN
  15.                         P(0).MapY = P(0).MapY + 1
  16.                         P(0).MoveY = 0       ' if you like you can move this line where is ***
  17.                     ELSE
  18.                         P(0).WorldY = P(0).WorldY + 1
  19.                         P(0).MoveY = 0       ' if you like you can move this line where is ***
  20.                     END IF
  21.                     Check_Location 0
  22.                 END IF
  23.                 '***
  24.             ELSE
  25.                 'play collision sound
  26.                 Check_Location 0
  27.             END IF
  28.     END SELECT
  29. [code]
  30.  
  31.  
« Last Edit: October 10, 2019, 02:11:16 pm by TempodiBasic »
Programming isn't difficult, only it's  consuming time and coffee

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Need some help with player movement..
« Reply #11 on: October 10, 2019, 09:07:20 pm »
As you can see, the player acquires the target position no matter what speed it is going...
I added a dwell whenever a target has been hit.
Modified again to show that the square player image is precisely located correctly in place.

that may be a little outside the scope of this game,

without actually playing its hard to get the feel for the movement, but that is about how it should look.
Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Need some help with player movement..
« Reply #12 on: October 10, 2019, 10:07:44 pm »
So the player doesn't move inside the screen, the world moves around the player.

Code: QB64: [Select]
  1. _TITLE "Walking between cells" 'for Colbalt 2019-10-10 B+
  2. ' the map moves around the player in the center
  3.  
  4. CONST xmax = 801, ymax = 641
  5. SCREEN _NEWIMAGE(xmax, ymax, 32)
  6. _SCREENMOVE 300, 40
  7. DIM SHARED mCols, mRows
  8. mCols = 12: mRows = 10
  9. DIM SHARED map(1 TO mCols, 1 TO mRows) AS INTEGER
  10.  
  11. FOR i = 1 TO 12 'landmarks
  12.     rx = INT(RND * mCols) + 1: ry = INT(RND * mRows) + 1
  13.     map(rx, ry) = INT(RND * 4) + 1
  14.     PRINT rx, ry, map(rx, ry)
  15.  
  16. pr = 10: pc = 12: xoff = 0: yoff = 0
  17. WHILE _KEYDOWN(27) = 0
  18.     IF txoff = 0 AND tyoff = 0 THEN 'we have finished moving and can take another keypress
  19.         kh& = _KEYHIT
  20.         SELECT CASE kh&
  21.             CASE 18432 'up
  22.                 IF pr - 1 >= 1 THEN
  23.                     IF map(pc, pr - 1) = 0 THEN pr = pr - 1: txoff = 0: dx = 0: tyoff = 33: dy = 1
  24.                 END IF
  25.             CASE 19712 'right
  26.                 IF pc + 1 <= mCols THEN 'make sure not past the array limit
  27.                     IF map(pc + 1, pr) = 0 THEN pc = pc + 1: txoff = -33: dx = -1: tyoff = 0: dy = 0
  28.                 END IF
  29.             CASE 20480 'down
  30.                 IF pr + 1 <= mRows THEN
  31.                     IF map(pc, pr + 1) = 0 THEN pr = pr + 1: txoff = 0: dx = 0: tyoff = -33: dy = -1
  32.                 END IF
  33.             CASE 19200 'left
  34.                 IF pc - 1 >= 1 THEN
  35.                     IF map(pc - 1, pr) = 0 THEN pc = pc - 1: txoff = 33: dx = 1: tyoff = 0: dy = 0
  36.                 END IF
  37.         END SELECT
  38.         _KEYCLEAR
  39.     END IF
  40.     txoff = txoff - dx: tyoff = tyoff - dy
  41.     IF txoff = 0 THEN dx = 0
  42.     IF tyoff = 0 THEN dy = 0
  43.     xoff = xoff + dx: yoff = yoff + dy
  44.     drawMap xoff, yoff
  45.     _DISPLAY
  46.     _LIMIT 30
  47.  
  48. SUB drawMap (xOff, yOff) 'x and y offset = 0
  49.     CLS
  50.     FOR y = 1 TO mRows
  51.         FOR x = 1 TO mCols
  52.             SELECT CASE map(x, y)
  53.                 CASE 0: LINE (xOff + x * 32, yOff + y * 32)-STEP(32, 32), &HFF006000, BF
  54.                 CASE 1: LINE (xOff + x * 32, yOff + y * 32)-STEP(32, 32), &HFF773300, BF
  55.                 CASE 2: LINE (xOff + x * 32, yOff + y * 32)-STEP(32, 32), &HFF884422, BF
  56.                 CASE 3: LINE (xOff + x * 32, yOff + y * 32)-STEP(32, 32), &HFF336600, BF
  57.                 CASE 4: LINE (xOff + x * 32, yOff + y * 32)-STEP(32, 32), &HFF006644, BF
  58.             END SELECT
  59.         NEXT
  60.     NEXT
  61.     LINE (12 * 32, 10 * 32)-STEP(32, 32), &HFFFFFFFF, BF
  62.  

Dang RND * 4 \ 1 + 1 Does not give me integers from 1 to 4, it gives me integers 1 to 5?

Colbalt, without _KEYCLEAR the player (white box) walks in first arrow direction until border or obstacle, maybe the same problem you were having?
« Last Edit: October 11, 2019, 09:30:02 am by bplus »

FellippeHeitor

  • Guest
Re: Need some help with player movement..
« Reply #13 on: October 11, 2019, 12:06:30 am »
World moving around player example, something in there may be of use: https://www.qb64.org/forum/index.php?topic=93.msg501#msg501

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Need some help with player movement..
« Reply #14 on: October 11, 2019, 07:28:48 am »
Hi Fellippe
I have forgotten your platform demo!

Thanks so I have played it again... Cool and fine parallax perspective!
  [ You are not allowed to view this attachment ]  
  [ You are not allowed to view this attachment ]  


@Cobalt
about
Quote
Quote from: TempodiBasic on Yesterday at 08:07:13 AM
4. How does control_routine pass the Inputs/commands to this general engine_Loop?
In this incarnation of failure, it simply sets the direction the player is facing then turns on a TIMER. Which runs the MOVE_PLAYER routine. Which sets the Moving flag. I have used the Controls routine to return a flag value to have the routine move_player called from the main loop too, again failure.

LOL yesterday I have tried to mod Petr's example using a TIMER (ON TIMER ...., TIMER ON, TIMER OFF, TIMER FREE) and so I have loosen my mind and meself into TIMER dimension.... :-)
 The use of a timer brings some collateral side effects!
The first that I found is how syncronize I/O and timer events.
Programming isn't difficult, only it's  consuming time and coffee