Jump to content
Jet Set Willy & Manic Miner Community

Ropes & Arrows


SymbolShift

Recommended Posts

1 hour ago, Norman Sword said:

Assuming you can draw the rope. Starting at the top we count the pixels drawn for the rope draw.  

If Not attached to the rope. Each cell drawn is tested for collision. if collision then willy is attached to the rope at that point. 

If attached to the rope. The cell that is assigned as the collision point (as above) is used as the x,y position to draw Willy - (slight shift adjustment needed in zx spectrum code)

To move on the rope the point of collision is moved up or down the rope 

To detach from the rope. A timer is set and Willy is cell aligned and exits from the rope.

Thanks again, that's good info. I might give the rope a go later on. I checked in an emulator, and the JSW rope is a lot more "flowing" than I remember (almost like a wind is blowing it as it swings), so I'm not terribly sure on how to reproduce that. Is there a simple breakdown on how the rope pixels are generated, to create that wind-flowing/swinging pattern?

Link to comment
Share on other sites

The rope is very simple in operation. Matthews code does its best to obscure that simplicity.

The rope data has offsets for x and y. - the data below is padded out to 256 bytes
 

rope_table_X:
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H01,&H01,&H01,&H01,&H01,&H01,&H01,&H01
DATA &H01,&H01,&H01,&H01,&H02,&H02,&H02,&H02
DATA &H02,&H02,&H02,&H02,&H02,&H02,&H02,&H02
DATA &H02,&H02,&H02,&H02,&H02,&H02,&H02,&H02
DATA &H02,&H02,&H01,&H02,&H02,&H01,&H01,&H02
DATA &H01,&H01,&H02,&H02,&H03,&H02,&H03,&H02
DATA &H03,&H03,&H03,&H03,&H03,&H03

;==================

DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00


' y-coordinate shift
rope_table_Y:
DATA &H06,&H06,&H06,&H06,&H06,&H06,&H06,&H06
DATA &H06,&H06,&H06,&H06,&H06,&H06,&H06,&H06
DATA &H06,&H06,&H06,&H06,&H06,&H06,&H06,&H06
DATA &H06,&H06,&H06,&H06,&H06,&H06,&H06,&H06
DATA &H06,&H06,&H06,&H06,&H06,&H06,&H06,&H06
DATA &H06,&H06,&H06,&H06,&H06,&H06,&H06,&H06
DATA &H04,&H06,&H06,&H04,&H06,&H04,&H06,&H04
DATA &H06,&H04,&H04,&H04,&H06,&H04,&H04,&H04
DATA &H04,&H04,&H04,&H04,&H04,&H04,&H04,&H04
DATA &H04,&H04,&H04,&H04,&H04,&H04,&H04,&H04
DATA &H04,&H04,&H04,&H04,&H04,&H04

;===========

DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00

simple logic for animation

A pointer is set as an offset into the data (as above)

The pointer has two other variables - side and step

The step is added to the offset.
 

if the offset is now 0 then reverse the step and reverse the side - simply negate the side and step.

if the offset is maximum the reverse the step- Simply negate the step

The above is the core logic for animation

--------------------------

To draw- start x=128; start y=0:
loop
draw point x,y
Take the offset into the above data - find the x entry - delta x-  and if side is 1 add delta x to x ; if side is -1 deduct delta x from x
Take the offset into the above data : find the y entry and add to the y

add 1 to the offset

loop for the length of the rope

the above will need adjustments, with the size of steps and length of rope etc =but will draw the rope.

 

 


 

Edited by Norman Sword
Link to comment
Share on other sites

OK. I'll try and explain as best I can how I've done it from a GMS2 perspective. I'm a hobbyist coder in games terms and a bit messy in all honesty, so apologies for inconsistent naming schemes.

I have a SPRITE defined for a single rope segment - in my version it's a 4x4 white square because I've done everything at 4x resolution in case I ever want to do an 'HD' version in future. eg. Willy's sprite is 64x64.

I have 2 OBJECTS defined - one I call a "RopeGenerator", and another which I call "RopeSpriteSegment". The RopeGenerator is the object which actually gets put into the room. The RopeSpriteSegment has no code in it, but has two Variable Definitions - "parent_instance" and "segment_id".

I've attached a very roughly commented extract from various GMS scripts shoved into a .txt file which drive the ropes / player in my remake. You'll probably have to work a fair few bits out yourself to relate it to your code, but it should give you a starting point and at least let you understand how the ropes are formed. When I saw how simple and elegantly Matthew Smith had done the rope I was really quite impressed.

EDIT: Sorry there are a few typos in the text file I've just seen - 32 vs 33 segments (yay off by one errors!) etc, but the gist is there.

RopeCode.txt

Edited by CPL
Link to comment
Share on other sites

Thanks to Norman and CPL for sharing this valuable information. I think I have enough to "give it a go", but will probably end up with a list of questions 😁 When you think about it, Matthew Smith was a clever bugger, working out all this stuff in the early 80's, in Z80 assembler, considering his age. Using tables to store the rope pattern makes total sense, rather than some complex maths formula. I always assumed it used a Sine wave algorithm to generate the swing. The GMS2 code snippets provided by CPL will be super helpful also. I am also a "hobbyist coder" and would never call myself a proper programmer, so I will excuse your messy code 😄

Edited by SymbolShift
Link to comment
Share on other sites

  • 2 weeks later...

After implementing my rope, I am still somewhat bewildered as to why Matthew Smith used the control system he used for climbing up/down the rope. The climbing logic used in JSW is...

Rope swinging left:
left key = climb down / right key = climb up

Rope swinging right:
left key = climb up / right key = climb down

Anyone I know who jumps on a rope for the first time is totally baffled on how to control Willy, as the climbing direction reverses when the swing direction changes. That said, after a while, you do eventually get used to it. I have coded the above method in my game (since it's true to JSW), but I did try a simplified version (left = up, right = down, no matter what swinging direction) and it seemed way more logical.

I wonder if there was a valid reason that Matthew Smith programmed it this way. Maybe there IS a reason? or maybe it's just a side-effect of lazy coding?

Would love to hear any thoughts on this.

Link to comment
Share on other sites

It does catch the un-initiated out !

I'd speculate it was done that way to make it harder to control him on a rope, as it seems easier to code it as a fixed method , at least from a players perspective.

I can see the logic in some ways if you think of it differently in that JSW does not have an up/down control so to reverse left/right for rope climbing/descending does make a bit of sense too.

Have you compared this to JSW2 or perhaps JSW on other platforms ? I can't recall immediately offhand if they differ and I don't have access at this moment to check for instance the BBC or CBM version out.

 

Link to comment
Share on other sites

1 hour ago, SymbolShift said:

After implementing my rope, I am still somewhat bewildered as to why Matthew Smith used the control system he used for climbing up/down the rope. The climbing logic used in JSW is...

Rope swinging left:
left key = climb down / right key = climb up

Rope swinging right:
left key = climb up / right key = climb down

Anyone I know who jumps on a rope for the first time is totally baffled on how to control Willy, as the climbing direction reverses when the swing direction changes. That said, after a while, you do eventually get used to it. I have coded the above method in my game (since it's true to JSW), but I did try a simplified version (left = up, right = down, no matter what swinging direction) and it seemed way more logical.

I wonder if there was a valid reason that Matthew Smith programmed it this way. Maybe there IS a reason? or maybe it's just a side-effect of lazy coding?

Would love to hear any thoughts on this.

It always seemed fairly intuitive to me for some reason, I don't know why. Maybe that was the same reason for MS?

Link to comment
Share on other sites

 

Taking the actual code used to control Willy on the rope . It took me all of 1 second to change the logic.

This original is deliberate and very logical in the manor of control. Walking up a stair you press against the stair, to move down a rope you press against the rope. Which to me is reverse logic, but still a consistant logic.

To modify to play as you mentioned is the lazy way of coding the movement and not the other way around. Note the ease of modification

Part of the rope swing


    LD A,(willy_dir)    ; #9375    ;#85D0  Pick up Willy's direction and movement flags from #85D0
    BIT 1,A         ; #9378    ;    Is Willy moving up or down the rope?
    JR Z,next_entity_draw    ; #937A    ;#93b3  If not, jump to consider the next entity

;CHANGE CODE FROM
;    RRCA            ; #937C    ;    XOR Willy's direction bit (0=facing right, 1=facing left) with the rope's direction bit
;;                ;;    ;    (0=swinging right to left, 1=swinging left to right)

;    XOR (IX+rope00)     ; #937D    ;
;    RLCA            ; #9380    ;
;    RLCA            ; #9381    ;    Now A=1 if Willy is facing the same direction as the rope is swinging (he will move down the rope),
;;                ;;    ;    or -1 otherwise (he will move up the rope)

; CHANGE CODE TO 
    RLCA           ; #937C
    NOP            ; #937D
    NOP            ; #937E
    NOP            ; #937F
    NOP            ; #9380
    NOP            ; #9381

 

;>> back to the normal logic

   AND #02         ; 9382    ;
    DEC A            ; 9384    ;

 

included is a file with the rope swinging in such a way. 

 

 

NOTE this file is so close to the original --- it might still have the attic bug --- I can not remember.

 

Addendum:-  easier is to just  zero out #937c, #937d, #937e, #937f, #9380.  -- five 0(zero) pokes.

jsw rope swing.tap

Edited by Norman Sword
Deleted excess code information.
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...

Important Information

By using this site, you agree to our Terms of Use.