Jump to content
IGNORED

Making platformers in XB


Retrospect

Recommended Posts

Hi everyone. I'm wanting to make a third game in the "Eric" series, there's Castle Conquer, Eric in Monsterland (soon) and after that, "Eric goes to Egypt" ... now, I want Eric to be able to jump up to another platform instead of him being always fastened to the floor except when he jumps.

 

Let's assume, Eric's pixel position is set to 135 .. so Variable MX = 135

 

There's a platform for him to jump onto - it's set at say position 112 (character position 14 for the tiles) ... how would I work it so that it checks whether there's anything for him to jump onto, during the jump routine?

 

My jump routines are fairly simple, they are literally

 

MA= eric's character

LEV = whatever screen he's on

 

 

10 LEV=1

 

IF player jumps then goto 4100

 

2110 CALL SPRITE(#1,MA,16,MX,MY,#2 whatever monsters are here ) :: RETURN

2120 stuff for screen 2

2130 stuff for screen 3

 

4100 MA=64::FOR L=1 TO 3 :: MX=MX-4 :: MY=MY+3 :: GOSUB 8000 :: NEXT L

4110 FOR L=1 TO 2 :: MX=MX-3 :: MY=MY+3 :: GOSUB 8000 :: NEXT L

4120 FOR L=1 TO 2 :: MX=MX-2 :: MY=MY+1 :: GOSUB 8000 :: NEXT L::MA=68

4130 FOR L=1 TO 2 :: MX=MX+2 :: MY=MY+1 :: GOSUB 8000 :: NEXT L

4140 FOR L=1 TO 2 :: MX=MX+3:: MY=MY+3 :: GOSUB 8000 :: NEXT L

4150 FOR L=1 TO 3 :: MX=MX+4 :: MY=MY+3 :: GOSUB 8000 :: NEXT L::MA=60

 

8000 CALL COINC(ALL,C) :: IF C=-1 THEN 9000

8010 GOSUB 8100 :: CALL LINK("DELAY",80) :: RETURN

 

8100 ON LEV GOSUB 2110,2120,2130 and so on

8110 CALL LINK("SCPXLF",184,4,1)::CALL LINK("SCPXLF",200,4,1) (this does the water scroll, it's always active whether water is there or not in order to maintain a steady speed and not go up n down all over the place )

 

 

.... what would I do to check if there's a platform anywhere? This sort of code would have to be entirely re-written? Any help would be great if I can understand it. :)

 

  • Like 2
Link to comment
Share on other sites

I used to code jumps using a fixed table of y offsets, so that every time the sprite moves one pixel in x it gets the movement in y from the next entry of the table. The jump finishes when the last entry is reached. This is the table from Jet Set Willy:

 

JMPTBL BYTE -4,-4,-3,-3,-2,-2,-1,-1,0,0,1,1,2,2,3,3,4,4

 

Recently I have started coding jumps using velocities and accelerations instead. Say you have two variables for the Y direction: VY (velocity) and AY (acceleration). For the X direction you only need the velocity VX since you usually don't accelerate during a jump. Now a jump can simply be coded something like this:

VX=1               (or -1, depending on the direction of movement)
AY=0.05            (a small downwards acceleration)
VY=-4.0            (a relatively high upwards velocity)
FOR I=1 to 100     (adjust duration to fit)
  MX=MX+VX
  VY=VY+AY
  MY=MY+VY
  display sprite at (MX,MY)
  check collision with platforms
NEXT I

The central movement code is not limited to jumps, but can also be used for both straight movement and falling. You probably only need these lines once in your central loop. When you move the joystick left or right you set VX. When you jump you set AY and VY. When you detect you're in open space you set AY. If you move into something horizontally you reset VX. If you jump into something with your head you reset VY. And so on...

 

To check collision with platforms, you need a routine to get the character at pixel position (X,Y). I rarely used XB, but I think you need to divide X and Y by 8 and use GCHAR?

 

When you move upwards (jump) you need to check the character above the head. and possibly the one next to it as well. When you move left or right you need to check one or two character to the left or right. When you fall or stand you need to check characters beneath the feet.

 

During falling (when VY > 0), if you detect a character beneath the feet you will probably want round off the sprite Y position to the integer multiple of 8 above it, to prevent sinking into the platform. If afraid I don't remember how to do that in XB, but it something like MY = MY - (MY MOD 8 ) where MOD is the remainder after a division.

  • Like 5
Link to comment
Share on other sites

If you lay out your screen characters carefully, you can use CALL GCHAR to detect if the ground is solid or not. For example, put all the solid characters above 95, and all open space or background characters at 95 or below. In Magellan, you can use shift-click to swap two character tiles, so rearranging them above or below a certain number is pretty easy. Then to detect solid ground you would use:

CALL GCHAR(INT((MY+16)/8)+1, INT((MX+4)/8)+1, C)
IF C > 95 THEN  (solid ground detected below)

The INT((MY+16)/8)+1 converts the sprite Y coordinate 16 pixels down to the screen row, and INT((MX+4)/8)+1 converts the sprite X coordinate 4 pixels to the right (centered under the sprite) to the screen column. You would need to do the test during the downward path of the jump, and also check for space after moving left or right so the player will fall after walking off the edge of the platform.

 

I haven't tested this, and it's been a while since I've done any basic programming, but I use the same concept for an assembly game I'm working on.

  • Like 3
Link to comment
Share on other sites

Regarding acceleration on the jumps - it's also perfectly okay to use integer values, which I believe will work better on the compiler. I usually use a gravity (acceleration Y) of '1' and then tweak the initial upwards velocity to get the desired arc. It does result in a very natural looking jump.

 

Catching the ground on the downward arc can be fiddly - make sure you check before you draw the sprite to avoid him popping into the ground then back out. Also you will want to cap the maximum positive acceleration - otherwise a long fall will result in velocities that are large enough to make detecting a platform or the ground difficult. (Just think of it as terminal velocity ;) ). Again, I don't have hard and fast rules for those, I just tweak values till I like what I see.

 

When you detect ground, you can then snap to the calculated row by multiplying by 8 and adding 1 (for the sprite offset).

 

I don't think XB has a MOD function, but it's faster to round with INT anyway. SCREENY = INT(SPRITEY/8) - be aware that SPRITEY of 0 is actually the second row on the screen, so this could be off by 1. Usually that's not a problem and in XB the speed is worth it, but since you're compiling you could adjust for it. A quick and dirty program to show how it lines up (and so you can adjust the code to get the exact match you want):

 

 

 
100 PI2=PI*2
110 CALL CLEAR
120 CALL MAGNIFY(2)
130 REM MANUALLY MOVE A SPRITE IN A CIRCLE
140 CALL SPRITE(#1,ASC("Y"),2,193,1)
150 FOR AN=0 TO PI2 STEP PI2/360
160 SPX=COS(AN)*64+128
170 SPY=SIN(AN)*64+96
180 CALL LOCATE(#1,SPY,SPX)
190 REM GET THE SPRITE POSITION AND PUT A CHARACTER UNDER IT
200 IF SCR=0 THEN 220
210 CALL HCHAR(SCR,SCC,32,3)
220 CALL POSITION(#1,INR,INC)
230 SCR=INT((INR+23)/8)
240 SCC=INT(INC/8)
250 REM SPRITE IS 2 CHARS WIDE, MEANS IT WILL OFTEN STRADDLE 3 CHARS
260 CALL HCHAR(SCR,SCC,ASC("#"),3)
270 NEXT AN
280 GOTO 150
  • Like 4
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...