Jump to content
IGNORED

Moving a sprite through a Maze, Extended Basic


LASooner

Recommended Posts

I'm having trouble wrapping my brain around how to constrain player controlled and CPU controlled sprites through a maze. for the CPU controlled, I originally tried trigger spots, where the monster determines where it is and whether it's coincident with an intersection, then randomly select which direction to go by adjusting sprite velocity. The problem with this is the time it takes to scan through all possible intersections, and act upon it, the coincident detection has usually past. And my monsters just keep moving in that one direction. The player controlled, I can easily keep the player sprite within the confines of the screen, I'm using CALL LOCATE to position the player, and I can set minimum and maximum constraints for the screen, I have then determined where the vertical pathways are and only limit up and down motion through those avenues. But I don't know how to determine when a wall blocks that vertical path. I want to keep all this position polling to a minimum as it affects the animation of the characters because it has to be done during the game loop.

 

I don't see anyway to detect collision with a specific character which would be the easiest way, since the path is all CHR$(32)

 

I was just wondering how others may have tackled the task of moving player and CPU controlled sprites through a maze without clipping through walls using extended basic?

 

My intent is to compress this as I'm using XB256, so RXB is not really an option.

 

 

Link to comment
Share on other sites

So if X and Y are the dot values given by CALL POSITION, I would use A=INT(X/8) :: B=INT(Y/8) :: CALL GCHAR (A,B,Z)

 

Am I correct that Z would give me the character value under the SPRITE?

 

Sorry if these question sound newbie, programming isn't my strong suit.

 

Actually the formula would be: A=INT(X/8)+1 (and the same for Y) since sprite locations between 1 and 7 would return, i.e. INT(7/8) is 0, and tile rows and columns are 1-based.

 

In your example Z would contain the ASCII value of the tile (character) at row A, col B. See pg. 88 of the XB manual (available in PDF form from many places, see the sticky thread at the top of the forum).

 

However, be careful with HCHAR and GCHAR, the parameters are "row, col", and row is the same as the y-axis when thinking about the screen in terms of an X,Y grid. The parameters for sprites are also called "dot-row" and "dot-col", so at least it is consistent. To keep your brain straight, you might want to switch to using R and C instead of Y and X. Actually, the example in the XB manual for CALL POSITION uses an example with X,Y and shows them written in "Y, X" order:

 

CALL POSITION(#1,Y,X)
XT=INT(X/8)+1::YT=INT(Y/8)+1
CALL GCHAR(YT,XT,T)

or save the intermediate variables:

CALL GCHAR(INT(Y/8)+1,INT(X/8)+1,T)

Also, if you are in XB and expect to have the 32K expansion, it *might* be faster to keep your maze in an array instead of using GCHAR:

 

DIM MAZE(30,20)

T=MAZE(INT(X/8)+1,INT(Y/8)+1)

You would load your maze into the array and draw it to the screen once during setup. Then your array is the in memory model of your maze and you use it to know where you can move, etc. What is on the screen is just a reflection of what is in the maze. But the XB gurus will have to chime-in to tell us if this would be faster.

 

Notice in this case that your array is in X,Y format, so you use X,Y instead of Y,X as you would for GCHAR.

 

I would also recommend you keep the "path" part of your maze as a single full tile, and also make the walls a full tile. This will make your wall collision much easier and faster.

 

As for moving, I know auto-sprite motion is nice and all, but you risk having your sprites move right through the walls if you are not careful in the way you set up the motion. You might try a typical game-loop first, using CALL LOCATE to move the sprites, to see if you get satisfactory results. A game-loop goes something like this:

 

while ( user doesn't exit )
  check for user input
  run AI
  move user
  move enemies
  resolve collisions
  update/draw graphics
  play sounds
end while

Although it seems complicated, each step is usually only a few lines of code (that's all the time you have in an environment like XB). For example, your "check for user input" step would be CALL KEY, the "run AI" step is the simple steps your computer player makes to decide how to move. The "move user" step would just be calculating the player's *new* X,Y position (this is a very important distinction) based on the keyboard input.

 

It is the "resolve collisions" step that your original question was concerned with. At this point you would check if the *new* position is in bounds of a maze path, or if it hit a maze wall. If there was a hit, you simply don't update the player's position. If the move is legal then you set the player's real position to the new position calculated previously. Then you draw/update the sprite positions.

 

This might all go something like:

 

SPEED=2
DIM MAZE(30,20)

// generate maze in MAZE

// draw maze on screen

WHILE game_running

  // user input, note to have the player keep moving when a direction key
  // is released, remove the "ELSE DY=0" and "ELSE DX=0" parts.
  CALL KEY ...

  IF quit or dead or whatever THEN ...

  IF up THEN DY=-SPEED
  ELSE IF down THEN DY=SPEED
  ELSE DY=0

  IF left THEN DX=-SPEED
  ELSE IF right THEN DX=SPEED
  ELSE DX=0

  // run AI, none yet.

  // move user, PX,PY is the current player location
  NX=PX+DX :: DY=PY+DY

  // resolve collisions
  IF MAZE(INT(NX/8)+1,INT(NY/8)+1)=32 THEN PX=NX :: PY=NY

  // update graphics
  CALL LOCATE(#1,PY,PX)

  // play sounds, maybe if the player hit a wall then make
  // a bump sound.
  IF PX<>NX THEN CALL SOUND(bump)

END WHILE

An alternate resolve collisions if using CALL GCHAR:

  // resolve collisions
  CALL GCHAR(INT(NY/8)+1,INT(NX/8)+1,T)
  IF T=32 THEN PX=NX :: PY=NY

Of course this is part pseudo code and part XB, so you will have to sort out the syntax bits to make it all work.

 

Here are a few examples. I like to use W,A,S,D instead of the TI "arrows", and Q is for quit.

 

 

 

Avoid the edge of the screen:

100 REM >>> GAMELOOP <<<
110 CALL CLEAR
120 X=16::Y=12
130 DX=0::DY=0
140 C=64:=32::E=42
150 CALL HCHAR(Y,X,C)
160 REM >>> GAME LOOP
170 REM >>> CHECK USER INPUT W,A,S,D,OR Q
180 CALL KEY(0,K,S)::IF S=0 THEN 250
190 IF K=81 THEN EXIT_GAME:
200 IF K=87 THEN DX=0::DY=-1::GOTO 250
210 IF K=83 THEN DX=0::DY=1::GOTO 250
220 IF K=65 THEN DX=-1::DY=0::GOTO 250
230 IF K=68 THEN DX=1::DY=0
240 REM >>> MOVE PLAYER
250 NX=X+DX::NY=Y+DY
260 REM >>> AI
270 REM >>> MOVE ENEMIES
280 REM >>> RESOLVE COLLISIONS
290 IF NX < 1 OR NX > 32 OR NY < 1 OR NY > 24 THEN 380
300 REM >>> DRAW GRAPHICS
310 CALL HCHAR(Y,X,D)
320 X=NX::Y=NY
330 CALL HCHAR(Y,X,C)
340 REM >>> PLAY SOUNDS
350 REM >>> END GAME LOOP
360 GOTO 170
370 REM >>> BLOW UP
380 CALL HCHAR(Y,X,E)
390 DISPLAY AT(12,14):"BOOM"
400 FOR I=1 TO 500::NEXT I
410 GOTO 110
420 END

 

 

 

 

 

Uses a sprite, avoid the edge of the screen.

100 REM >>> SPRITE GAMELOOP <<<
110 CALL CLEAR
120 X=128::Y=96
130 DX=0::DY=0::SP=2
140 C=64::E=42
150 CALL SPRITE(#1,C,2,Y,X)
160 REM >>> GAME LOOP
170 REM >>> CHECK USER INPUT W,A,S,D, OR Q
180 CALL KEY(0,K,S)::IF S=0 THEN 250
190 IF K=81 THEN 420
200 IF K=87 THEN DX=0::DY=-SP::GOTO 250
210 IF K=83 THEN DX=0::DY=SP::GOTO 250
220 IF K=65 THEN DX=-SP::DY=0::GOTO 250
230 IF K=68 THEN DX=SP::DY=0
240 REM >>> MOVE PLAYER
250 NX=X+DX::NY=Y+DY
260 REM >>> AI
270 REM >>> MOVE ENEMIES
280 REM >>> RESOLVE COLLISIONS
290 IF NX < 8 OR X > 248 OR Y < 8 OR Y > 184 THEN 370
300 X=NX::Y=NY
310 REM >>> DRAW GRAPHICS
320 CALL LOCATE(#1,Y,X)
330 REM >>> PLAY SOUNDS
340 REM >>> END GAME LOOP
350 GOTO 170
360 REM >>> BLOW UP
370 CALL PATTERN(#1,E)
380 DISPLAY AT(12,14):"BOOM"
390 FOR I=1 TO 500::NEXT I
400 GOTO 110
410 REM >>> END GAMELOOP
420 END

 

 

 

 

 

Uses a sprite, avoid the #

100 REM >>> SPRITE GAMELOOP <<<
110 DIM M(30,22)
120 CALL CLEAR
130 X=128::Y=96
140 DX=0::DY=0::SP=2
150 C=64::E=42::W=35
160 REM >>> BORDER
170 FOR TX=1 TO 30
180 M(TX,1)=W::CALL HCHAR(1,TX,W)
190 M(TX,22)=W::CALL HCHAR(22,TX,W)
200 NEXT TX
210 FOR TY=1 TO 22
220 M(1,TY)=W::CALL HCHAR(TY,1,W)
230 M(30,TY)=W::CALL HCHAR(TY,30,W)
240 NEXT TY
250 REM >>> GENERATE PLAYFIELD
260 FOR TY=2 TO 21
270 FOR TX=2 TO 29::M(TX,TY)=0::NEXT TX
280 TX=INT(RND*28)+2
290 M(TX,TY)=W::CALL HCHAR(TY,TX,W)
300 NEXT TY
310 REM INITIAL PLAYER LOCATION
320 M(INT(X/8)+1,INT(Y/8)+1)=0
330 CALL SPRITE(#1,C,5,Y,X)
340 REM >>> GAME LOOP
350 REM >>> CHECK USER INPUT W,A,S,D, OR Q
360 CALL KEY(0,K,S)::IF S=0 THEN 430
370 IF K=81 THEN 610
380 IF K=87 THEN DX=0::DY=-SP::GOTO 430
390 IF K=83 THEN DX=0::DY=SP::GOTO 430
400 IF K=65 THEN DX=-SP::DY=0::GOTO 430
410 IF K=68 THEN DX=SP::DY=0
420 REM >>> MOVE PLAYER
430 NX=X+DX::NY=Y+DY
440 REM >>> AI
450 REM >>> MOVE ENEMIES
460 REM >>> RESOLVE COLLISIONS
470 IF M(INT(NX/8)+1,INT(NY/8)+1)=W THEN 550
480 X=NX::Y=NY
490 REM >>> DRAW GRAPHICS
500 CALL LOCATE(#1,Y,X)
510 REM >>> PLAY SOUNDS
520 REM >>> END GAME LOOP
530 GOTO 350
540 REM >>> BLOW UP
550 CALL PATTERN(#1,E)
560 DISPLAY AT(12,14):"BOOM"
570 FOR I=1 TO 500::NEXT I
580 CALL LOCATE(#1,192,1)
590 GOTO 120
600 REM >>> END GAMELOOP
610 END

 

 

  • Like 2
Link to comment
Share on other sites

I should mention that I'm using MAGNIFY (3), so the pathways are 2 chars wide. I am having some success, with using GCHAR, I have one for each corner of the sprite. I figured out the need to have it be (X/8)+1 earlier this evening so some brain cells are still kicking. If the character next to sprite is 32 in any direction, I only allow input in those directions. It's getting there. I will move the monsters away from auto motion and use LOCATE as well. But I'm not worrying about those guys yet.

 

I'm a 3D Artist for my day job, so interpolating X and Y is hard wired in my brain.

Edited by LASooner
  • Like 1
Link to comment
Share on other sites

In my limited experience the automatic sprites in XB are fun to mess around with but difficult to manage due to the slow speed of XB -- the main BIG issue.

 

It's like trying to fly a drone with a really slow radio control scheme. By the time you tell the damn thing to turn around it has already flown out of range.

 

Compiling XB fixes most of the speed issues and significantly helps to cleanly manage auto-spites. Still, it's not perfect. Just pretty good. I'd say the 20X+ speed improvement with Compiled BASIC results in GOOD auto-sprite management, not GREAT.

 

The final step is programming in Assembly where you have the speed to accurately manage automatic sprites but may not really need them. Ironic?

Edited by Airshack
Link to comment
Share on other sites

LOCATE is your best option for moving a CPU-controlled sprite through a maze. You can look at "Dark Maze", my short program, as an example of a moving sprite enemy.

 

In general, for XB programming, it's pretty hard to have more than a single CPU controlled enemy. Using compiled XB helps a bit, but you still have the challenge of timing things.

 

You have the opposite problem in assembly. You have to make certain that sprites move at intervals that are actually visible to the user. Generally speaking, there is no excuse there for poor controls short of intensive CPU work, like Parsec with the horizontal scrolling. (TI Invaders annoys me with how your cannon is sluggish to respond to sudden changes in direction.)

  • Like 1
Link to comment
Share on other sites

LOCATE is your best option for moving a CPU-controlled sprite through a maze. You can look at "Dark Maze", my short program, as an example of a moving sprite enemy.

 

In general, for XB programming, it's pretty hard to have more than a single CPU controlled enemy. Using compiled XB helps a bit, but you still have the challenge of timing things.

 

You have the opposite problem in assembly. You have to make certain that sprites move at intervals that are actually visible to the user. Generally speaking, there is no excuse there for poor controls short of intensive CPU work, like Parsec with the horizontal scrolling. (TI Invaders annoys me with how your cannon is sluggish to respond to sudden changes in direction.)

I think Invaders is written in GPL and they did not put the SCAN loop in the main loop for checking key input from user.

 

Thus why you get lag in changing direction, it appears they instead called SCAN when not updating the screen.

  • Like 1
Link to comment
Share on other sites

I think Invaders is written in GPL and they did not put the SCAN loop in the main loop for checking key input from user.

 

Thus why you get lag in changing direction, it appears they instead called SCAN when not updating the screen.

 

Yep, that makes sense. It's a bad game design. Given that most of the old TI games were written by college-level CS students, it's not surprising.

  • Like 1
Link to comment
Share on other sites

I've tried to write an example code to help with the maze game and sprite, and hit on a problem myself. But in doing so, help with this might help you to make your maze game. Note that I've used only small sprite, magnification 1.

 

! TREASURE HOUSE EXAMPLE GAME
! NO PROBLEM WITH LEFT OR RIGHT, BUT A PROBLEM OCCURS IN UP AND DOWN MOVEMENT, WHY??
! DEFINE THE GRAPHICS
10 CALL CHAR(104,"080808FF808080FF") ! WALLS (CHAR)
20 CALL CHAR(96,"1819FFBC3C3C6446") ! THE PLAYER (SPRITE)
25 CALL CHAR(112,"00001C2236363E00") ! TREASURE (CHAR)
! DO THE COLOURS
30 CALL CLEAR::CALL COLOR(10,5,16,11,4,1)::CALL SCREEN(2)
! RESET THE SCORE
35 SCORE=0
! PLAN THE HOUSE LAYOUT
40 CALL HCHAR(1,1,104,32)::CALL HCHAR(24,1,104,32)::CALL VCHAR(1,1,104,24)::CALL VCHAR(1,32,104,24)
50 FOR Q=3 TO 22 STEP 2::CALL HCHAR(Q,3,104,28)::NEXT Q
60 FOR Q=3 TO 30 STEP 3::CALL HCHAR(22,Q,104)::NEXT Q
! PLACE THE TREASURE CHARS
70 CALL HCHAR(2,2,112)::CALL HCHAR(2,31,112)::CALL HCHAR(23,2,112)::CALL HCHAR(23,31,112)
! GIVE THE PLAYER X AND Y COORDS AND TELL COMPUTER THAT TREASURE=0
80 MX=136 :: MY=128 :: TR=0
! PLACE THE PLAYER SPRITE
90 CALL SPRITE(#1,96,16,MX,MY)
! NOTE THE JOYSTICK COMMAND WORKS OPPOSITE WITH X AND Y. I KNOW, RIGHT?!
100 CALL JOYST(1,JY,JX)
110 IF JY=-4 THEN 210
120 IF JY=4 THEN 220
130 IF JX=4 THEN 230
140 IF JX=-4 THEN 240
150 goto 100
210 ! MOVE LEFT
211 MY=MY-8::GOSUB 1100::GOTO 90
220 ! MOVE RIGHT
221 MY=MY+8::GOSUB 1200::GOTO 90
230 ! MOVE UP
231 MX=MX-8::GOSUB 1300::GOTO 90
240 ! MOVE DOWN
241 MX=MX+8::GOSUB 1400::GOTO 90
1100 ! CHECK FOR LEFT
1102 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX,CY-1,CH)
1104 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MY=MY+8::GOTO 90
1106 GOTO 90
1200 ! CHECK FOR RIGHT
1202 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX,CY+1,CH)
1204 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MY=MY-8::GOTO 90
1206 GOTO 90
1300 ! CHECK FOR UP
1302 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX-1,CY,CH)
1304 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MX=MX-8::GOTO 90
1306 GOTO 90
1400 ! CHECK FOR DOWN
1402 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX+1,CY,CH)
1404 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MX=MX+8::GOTO 90
1406 GOTO 90
2000 ! GOT TREASURE
2010 CALL SOUND(200,1360,1)::TR=TR+1::IF TR=4 THEN 3000 ELSE 90
3000 ! GOT ALL TREASURE
3010 FOR Q=220 TO 880 STEP 64::CALL SOUND(128,Q,1)::NEXT Q::DISPLAY AT(24,1)ERASE ALL:"GOT ALL THE TREASURE!"::STOP
  • Like 1
Link to comment
Share on other sites

 

1100 ! CHECK FOR LEFT
1102 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX,CY-1,CH)
1104 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MY=MY+8::GOTO 90
1106 GOTO 90
1200 ! CHECK FOR RIGHT
1202 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX,CY+1,CH)
1204 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MY=MY-8::GOTO 90
1206 GOTO 90
1300 ! CHECK FOR UP
1302 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX-1,CY,CH)
1304 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MX=MX-8::GOTO 90
1306 GOTO 90
1400 ! CHECK FOR DOWN
1402 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX+1,CY,CH)
1404 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MX=MX+8::GOTO 90
1406 GOTO 90

 

 

 

That is basically what I'm doing as well, it's not as clean for a 16x16 sprite since I'm doing only 4 checks, I'm going to try adding 4 more and see if that slows it down too much

 

 

*- GCHAR position point

 

#- Sprite

 

What I'm currently doing

 * 
 ## 
*##*
  *

With these 4 checks it works perfectly when colliding with obstacles to the right and down, but left and up causes the character to get stuck, so I've had to include checks to see if the character has gone too far to the left, or too high up and reset their position to the next closest pathway

 

So I'm going to try doing 2 checks on each side.

 **
*##*
*##*
 **

Which I suspect will yield better collision,without having to check the character's position, but not sure at what cost performance wise doing 8 GCHARs per input loop.

 

 

 

Thanks for all the input guys, I appreciate it!

Edited by LASooner
  • Like 1
Link to comment
Share on other sites

Years ago, I wrote a simple two-player tank game. I used CALL COINC, but at any decent sprite speed, XB failed to detect if a cannon shot scored or the two tanks collided, let alone hit any static obstacles. So I just made it into an out of control free for all. Too bad, 'cause I had great graphics and sound for when a tank blew up!

-Ed

  • Like 2
Link to comment
Share on other sites

Well , performance-wise, if you're compiling the game, just remember take into consideration the heavier the hit on performance your routines are, the lesser the number you'll want in your CALL LINK("DELAY",XX) number ... Just as an example, Eric in Monsterland has around 3 to 4 sprites moving around on screen with programmed movements (not automotion all the time) and I use something like CALL LINK("DELAY",80) ... that is done on every screen update. I think you'll want probably 40 or so. See how it goes. As for the up and down I don't know I'm as stuck as you are on that one

Link to comment
Share on other sites

 

I've tried to write an example code to help with the maze game and sprite, and hit on a problem myself. But in doing so, help with this might help you to make your maze game. Note that I've used only small sprite, magnification 1.

 

! TREASURE HOUSE EXAMPLE GAME
! NO PROBLEM WITH LEFT OR RIGHT, BUT A PROBLEM OCCURS IN UP AND DOWN MOVEMENT, WHY??
! DEFINE THE GRAPHICS
10 CALL CHAR(104,"080808FF808080FF") ! WALLS (CHAR)
20 CALL CHAR(96,"1819FFBC3C3C6446") ! THE PLAYER (SPRITE)
25 CALL CHAR(112,"00001C2236363E00") ! TREASURE (CHAR)
! DO THE COLOURS
30 CALL CLEAR::CALL COLOR(10,5,16,11,4,1)::CALL SCREEN(2)
! RESET THE SCORE
35 S! PLAN THE HOUSE LAYOUT
40 CALL HCHAR(1,1,104,32)::CALL HCHAR(24,1,104,32)::CALL VCHAR(1,1,104,24)::CALL VCHAR(1,32,104,24)
50 FOR Q=3 TO 22 STEP 2::CALL HCHAR(Q,3,104,28)::NEXT Q
60 FOR Q=3 TO 30 STEP 3::CALL HCHAR(22,Q,104)::NEXT Q
! PLACE THE TREASURE CHARS
70 CALL HCHAR(2,2,112)::CALL HCHAR(2,31,112)::CALL HCHAR(23,2,112)::CALL HCHAR(23,31,112)
! GIVE THE PLAYER X AND Y COORDS AND TELL COMPUTER THAT TREASURE=0
80 MX=136 :: MY=128 :: TR=0
! PLACE THE PLAYER SPRITE
90 CALL SPRITE(#1,96,16,MX,MY)
! NOTE THE JOYSTICK COMMAND WORKS OPPOSITE WITH X AND Y. I KNOW, RIGHT?!
100 CALL JOYST(1,JY,JX)
110 IF JY=-4 THEN 210
120 IF JY=4 THEN 220
130 IF JX=4 THEN 230
140 IF JX=-4 THEN 240
150 goto 100
210 ! MOVE LEFT
211 MY=MY-8::GOSUB 1100::GOTO 90
220 ! MOVE RIGHT
221 MY=MY+8::GOSUB 1200::GOTO 90
230 ! MOVE UP
231 MX=MX-8::GOSUB 1300::GOTO 90
240 ! MOVE DOWN
241 MX=MX+8::GOSUB 1400::GOTO 90
1100 ! CHECK FOR LEFT
1102 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX,CY-1,CH)
1104 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MY=MY+8::GOTO 90
1106 GOTO 90
1200 ! CHECK FOR RIGHT
1202 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX,CY+1,CH)
1204 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MY=MY-8::GOTO 90
1206 GOTO 90
1300 ! CHECK FOR UP
1302 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX-1,CY,CH)
1304 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MX=MX-8::GOTO 90
1306 GOTO 90
1400 ! CHECK FOR DOWN
1402 CALL POSITION(#1,PX,PY)::CX=INT(PX/8)+1::CY=INT(PY/8)+1::CALL GCHAR(CX+1,CY,CH)
1404 IF CH=112 THEN 2000 ELSE IF CH=104 THEN MX=MX+8::GOTO 90
1406 GOTO 90
2000 ! GOT TREASURE
2010 CALL SOUND(200,1360,1)::TR=TR+1::IF TR=4 THEN 3000 ELSE 90
3000 ! GOT ALL TREASURE
3010 FOR Q=220 TO 880 STEP 64::CALL SOUND(128,Q,1)::NEXT Q::DISPLAY AT(24,1)ERASE ALL:"GOT ALL THE TREASURE!"::STOP

 

RXB has better versions of this XB code for CALL HCHAR and CALL VCHAR

40 CALL HCHAR(1,1,104,32)::CALL HCHAR(24,1,104,32)::CALL VCHAR(1,1,104,24)::CALL VCHAR(1,32,104,24) ! XB
40 CALL HCHAR(1,1,104,32,24,1,104,32)::CALL VCHAR(1,1,104,24,1,32,104,24) ! RXB

70 CALL HCHAR(2,2,112)::CALL HCHAR(2,31,112)::CALL HCHAR(23,2,112)::CALL HCHAR(23,31,112) ! XB
70 CALL HCHAR(2,2,112,1,2,31,112,1,23,2,112,1,23,31,112) ! RXB

  • Like 1
Link to comment
Share on other sites

I've tried to write an example code to help with the maze game and sprite, and hit on a problem myself. But in doing so, help with this might help you to make your maze game. Note that I've used only small sprite, magnification 1.

 

! TREASURE HOUSE EXAMPLE GAME
...

 

This is only a quick and minor rewrite. I've moved focus from the sprite pixel position to it's row and column position. It makes it easier to evaluate a new position (in this case). Directions are handled in one go instead of splitting the logic into four. Also removing the treasure once you get one.

 

This is of course not a solution for moving a sprite at different speeds (other than 8 pixels per move).

 

 

 

! TREASURE HOUSE EXAMPLE GAME
 
! DO THE COLOURS
10 CALL CLEAR::CALL COLOR(10,5,16,11,4,1)::CALL SCREEN(2)
 
! DEFINE THE GRAPHICS

20 CALL CHAR(104,"080808FF808080FF") ! WALLS (CHAR)
25 CALL CHAR(96,"1819FFBC3C3C6446") ! THE PLAYER (SPRITE)
30 CALL CHAR(112,"00001C2236363E00") ! TREASURE (CHAR)
 
! PLAN THE HOUSE LAYOUT 
40 CALL HCHAR(24,1,104,64)::CALL VCHAR(1,32,104,48)
50 FOR Q=3 TO 22 STEP 2::CALL HCHAR(Q,3,104,28)::NEXT Q
60 FOR Q=3 TO 30 STEP 3::CALL HCHAR(22,Q,104)::NEXT Q
 
! PLACE THE TREASURE CHARS
70 CALL HCHAR(2,2,112)::CALL HCHAR(2,31,112)::CALL HCHAR(23,2,112)::CALL HCHAR(23,31,112)
 
! GIVE THE PLAYER COORDS
80 C=19 :: R=18
 
! PLACE THE PLAYER SPRITE
90 CALL SPRITE(#1,96,16,(R-1)*8+1,(C-1)*8+1)
 
! READ JOYSTICK
100 CALL JOYST(1,X,Y)::if x=0 and y=0 then 100
! find new position
110 rn=r-y/4::cn=c+x/4::call gchar(rn,cn,g)
! CHECK FOR WALL
120 if g=104 then 100
! MOVE OKAY
130 r=rn::c=cn
! CHECK FOR TREASURE
140 if g=112 then 2000 else 90
 
2000 ! GOT TREASURE
2010 call hchar(r,c,32)::CALL SOUND(200,1360,1)::TR=TR+1::IF TR=4 THEN 3000 ELSE 90
 
3000 ! GOT ALL TREASURE
3010 FOR Q=220 TO 880 STEP 64::CALL SOUND(128,Q,1)::NEXT Q::DISPLAY AT(24,1)ERASE ALL:"GOT ALL THE TREASURE!"::STOP
 

 

 

  • Like 1
Link to comment
Share on other sites

Excellent, sometimes99er. Thankyou. This is something I've always become stuck with! Probably help me with that platformer I need to make and I hope helps LASooner with his game too. :)

 

Thanks. Yep, I hope this may at least bring another perspective (rather than confusion) to the challenge of the topic. Changing focus (from pixel to chars) is not something one has to do, just in this case I think it makes for less code overall. Handling the movement in one go, instead of splitting it up, is universal, even though optimizing XB may indeed lead to "splitting" code.

 

Nice little and cute game that could be taken to the next level. :thumbsup:

  • Like 1
Link to comment
Share on other sites

So after adding 4 more points of character detection, he moves the maze pretty good, the only areas where he's having trouble is the ends of the walls, but I put IF/THEN statements in the movement subroutines to handle those positions and it's working fairly well. If the character gets really close to the wall he's moving slower but not stopping, and I'm not opposed to this behavior as it simulates wall scraping a bit, so I may just leave it. Most importantly adding the extra detection passes hasn't made that much of a speed hit compared to just 4. I took Mathew180's suggestion of removing the interim variable.

 

I use TIdBit so this is my detection pass

_MOVERETURN:


	_COLMAP:	CALL GCHAR(INT(MY/8)+1,INT(MX/8)+1,MZ1)
					IF MZ1=32 THEN GOSUB _LEFT
					IF MZ1=16 THEN GOSUB _LEFT
					IF MZ1=17 THEN GOSUB _LEFT
					IF MZ1=18 THEN GOSUB _LEFT
					IF MZ1=19 THEN GOSUB _LEFT
					IF MX>33 AND MY>33 THEN _COLMAP1
						FOR A=36 TO 45
							IF MZ1=A THEN GOSUB _WEBLEFT
						NEXT A
			
	_COLMAP1:	CALL GCHAR(INT(MY/8)+2,INT(MX/8)+1,MZ2)	
					IF MZ2=32 THEN GOSUB _LEFT
					IF MZ2=16 THEN GOSUB _LEFT
					IF MZ2=17 THEN GOSUB _LEFT
					IF MZ2=18 THEN GOSUB _LEFT
					IF MZ2=19 THEN GOSUB _LEFT
					IF MX>33 AND MY>33 THEN _COLMAP2
						FOR A=36 TO 45
							IF MZ2=A THEN GOSUB _WEBLEFT
						NEXT A	
			
	
	_COLMAP2:	CALL GCHAR(INT(MY/8)+1,INT(MX/8)+3,MZ3)
					IF MZ3=32 THEN GOSUB _RIGHT
					IF MZ3=16 THEN GOSUB _RIGHT
					IF MZ3=17 THEN GOSUB _RIGHT
					IF MZ3=18 THEN GOSUB _RIGHT
					IF MZ3=19 THEN GOSUB _RIGHT
					IF MX>33 AND MY>33 THEN _COLMAP3
						FOR A=36 TO 45
							IF MZ3=A THEN GOSUB _WEBRIGHT
						NEXT A
						
	_COLMAP3:	CALL GCHAR(INT(MY/8)+2,INT(MX/8)+3,MZ4)
					IF MZ4=32 THEN GOSUB _RIGHT
					IF MZ4=16 THEN GOSUB _RIGHT
					IF MZ4=17 THEN GOSUB _RIGHT
					IF MZ4=18 THEN GOSUB _RIGHT
					IF MZ4=19 THEN GOSUB _RIGHT
					IF MX>33 AND MY>33 THEN _COLMAP4
						FOR A=36 TO 45
							IF MZ4=A THEN GOSUB _WEBRIGHT
						NEXT A
		
	_COLMAP4:	CALL GCHAR(INT(MY/8)+1,INT(MX/8)+1,MZ5)
					IF MZ5=32 THEN GOSUB _UP		
					IF MZ5=16 THEN GOSUB _UP
					IF MZ5=17 THEN GOSUB _UP
					IF MZ5=18 THEN GOSUB _UP
					IF MZ5=19 THEN GOSUB _UP
					IF MX>33 AND MY>33 THEN _COLMAP5
						FOR A=36 TO 45
							IF MZ5=A THEN GOSUB _WEBUP
						NEXT A
						
	_COLMAP5:	CALL GCHAR(INT(MY/8)+1,INT(MX/8)+2,MZ6)
					IF MZ6=32 THEN GOSUB _UP		
					IF MZ6=16 THEN GOSUB _UP
					IF MZ6=17 THEN GOSUB _UP
					IF MZ6=18 THEN GOSUB _UP
					IF MZ6=19 THEN GOSUB _UP
					IF MX>33 AND MY>33 THEN _COLMAP6
						FOR A=36 TO 45
							IF MZ6=A THEN GOSUB _WEBUP
						NEXT A					
										
	_COLMAP6: 	CALL GCHAR(INT(MY/8)+3,INT(MX/8)+1,MZ7)
					IF MZ7=32 THEN GOSUB _DOWN
					IF MZ7=16 THEN GOSUB _DOWN
					IF MZ7=17 THEN GOSUB _DOWN
					IF MZ7=18 THEN GOSUB _DOWN
					IF MZ7=19 THEN GOSUB _DOWN
					IF MX>33 AND MY>33 THEN _COLMAP7
						FOR A=36 TO 45
							IF MZ7=A THEN GOSUB _WEBDOWN
						NEXT A
	
	_COLMAP7: 	CALL GCHAR(INT(MY/8)+3,INT(MX/8)+2,MZ8)
					IF MZ8=32 THEN GOSUB _DOWN
					IF MZ8=16 THEN GOSUB _DOWN
					IF MZ8=17 THEN GOSUB _DOWN
					IF MZ8=18 THEN GOSUB _DOWN
					IF MZ8=19 THEN GOSUB _DOWN
					IF MX>33 AND MY>33 THEN _LIMITS
						FOR A=36 TO 45
							IF MZ8=A THEN GOSUB _WEBDOWN
						NEXT A


Edited by LASooner
Link to comment
Share on other sites

Time to take the wraps off what I've been farting around with. Here's my test, I have the player moving through the maze, Robot, Bats and Spider randomly moving through the maze, and I can pick up the gun and add bullets. I've only been working on this since last week. It is running CPU Overdrive because it's not compiled yet. But this is all very encouraging.

 

 

I felt like Night Stalker was good choice, Bomb Squad was a little too ambitious at this time. It only has 1 map, always 4 enemies, so basically once I get the base game working, getting to the finish seems more achievable. With tools like XB256, Magellan and TIdBit, it sure removes the barrier to entry.

 

 

The next challenge will be shooting and hit detection. But I'll probably clean up the player sticking to walls as much as I can. Thanks again everyone for the help!

  • Like 9
Link to comment
Share on other sites

That's fantastic. You may need to be mindful of >4 sprites per line. In my head, that's always the biggest challenge, especially when you consider bullets, although perhaps you can use character animations for those. If you do that, then you could just prevent the 2 bats from ever crossing paths. Then you're done.

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...