Resource centre for ZX Spectrum games
using Manic Miner and Jet Set Willy game engines
Archive of the
Manic Miner & Jet Set Willy Yahoo! Group
messages
|
|
||
|
|
Message: 6556
Author: andrewbroad
Date: 10/07/2009
Subject: Re: Harmless guardians / Patch to kill guardians
I have just cited Message 5816 in a post about Willy being able to kill guardians at
http://www.worldofspectrum.org/forums/showthread.php?t=24988
My idea is to replace the code that kills Willy when a guardian collides with him with some code to remove that guardian-instance from the current-room buffer (to make it disappear instantly), and from the primary room-record (to make it disappear permanently).
I don't fancy writing a MM/JSW game in which the player can kill guardians, because it kind of ruins the point of designing intricate, challenging MM/JSW rooms. But it would be cool to see it just as a variant of the original Jet Set Willy.
What would also be cool would be to see a Spectrum-conversion (or even a PC-remake) of _Horace in the Mystic Woods_ <http://www.worldofspectrum.org/forums/showthread.php?t=24818>: having just watched a video of the game on YouTube, it looks very Manic-Minerish, but you build up speed as you run (à la Super Mario Bros), and the faster you're running, the higher you can jump.
I wish I could write more about my MM/JSW plans now that Wimbledon is over, but I'm not sure what to do next on the MM/JSW front. I might start work on H* or start/resume another MM/JSW-editing project (as per the previews on my website), or perhaps this is a year to finally make serious inroads in my backlog of playing the MM/JSW games that were released since 2000. :o
--
Dr. Andrew Broad
http://tinyurl.com/andrewbroad-mmjsw
[Message 5816]
On 24th April 2006, I wrote:
>
> --------------------------------------
> Method A: The quick and dirty solution
> --------------------------------------
>
> The nastiest way to have harmless guardians in Jet Set Willy is...
>
> POKE 37050,58 (Hex 90BA: 3A)
>
> ...which modifies the following code...
>
> #90B8: LD A,#FF
> #90BA: LD (#85D1),A ; set 'airborne' status to 'dead' (#FF)
>
> ...as follows:
>
> #90BA: LD A,(#85D1) ; get 'airborne' status
>
> Guardians still collide (and are only drawn down to the point of
> collision), Fire-cells don't kill you, and if you fall too far, you
> just disappear and have to reset the game.
>
> -------------------------------------------
> Method B: Modify the sprite-drawing routine
> -------------------------------------------
>
> The following two POKEs, which must be used together, ...
>
> POKE 37982,0 (Hex 945E: 00)
> POKE 37994,0 (Hex 946A: 00)
>
> ...modify the sprite-drawing subroutine at #9456 to ignore
> collisions. This subroutine has the following preconditions...
>
> * C == 1 if collision is to be enabled, 0 if disabled;
> * DE == address of sprite to draw;
> * HL == address to draw it to.
>
> ...and the following postconditions...
>
> * Zero-flag == set (Z) if no collision occurred - the whole sprite
> was drawn;
> * Zero-flag == reset (NZ) if a collision occurred - the sprite was
> drawn only down to the point of collision.
>
> #9456: LD B,#10 ;;;; 16 pixel-rows to draw
> #9458: BIT 0,C ;;;;; (loop starts at #9458) test Bit 0 of C-register
> #945A: LD A,(DE) ;;; get pixel-row from sprite's left cell-column
> #945B: JR Z,#9461 ;; skip collision-detection if Bit 0 of C is 0
> #945D: AND (HL) ;;;; if any pixels collide
> #945E: RET NZ ;;;;;; then return with Zero-flag reset (collision!)
> #945F: LD A,(DE) ;;; get pixel-row from sprite's left cell-column
> #9460: OR (HL) ;;;;; merge sprite's pixels with what's already there
> #9461: LD (HL),A ;;; draw pixel-row (left cell-column)
> #9462: INC L ;;;;;;; move right by one cell-column
> #9463: INC DE ;;;;;; point to next pixel-row in sprite's right column
> #9464: BIT 0,C ;;;;; ditto re. sprite's right cell-column...
> #9466: LD A,(DE)
> #9467: JR Z,#946D
> #9469: AND (HL) ;;;; if any pixels collide
> #946A: RET NZ ;;;;;; then return with Zero-flag reset (collision!)
> #946B: LD A,(DE)
> #946C: OR (HL)
> #946D: LD (HL),A
> #946E: DEC L ;;;;;;; move left by one cell-column
> #946F: INC H ;;;;;;; move down by one cell-row
> #9470: INC DE ;;;;;; point to next pixel-row in sprite's left column
>> another>
> #9486: DJNZ #9458 ;; repeat until whole sprite drawn
> #9488: XOR A ;;;;;;; A:= 0 and set Zero-flag (Z)
> #9489: RET ;;;;;;;;; return with Zero-flag set (no collision)
>
> The above two POKEs replace the RET NZ instructions with NOPs, so
> if a collision does occur, it is ignored and the whole sprite is
> drawn. This means that if Willy walks into a guardian, their pixels
> are merged together.
>
> Note that this subroutine is called not only for guardians, but
> also for Maria (but not the toilet), Willy's extra lives, the
> objects on the Game Over screen, and the colour-code routine.
> So the above two POKEs allow Willy to walk through Maria as well as
> guardians.
>
> -------------------------------------------------------
> Method C: Modify calls to the sprite-drawing subroutine
> -------------------------------------------------------
>
> For guardians and Maria, the above subroutine is called with C == 1
> to enable collision-detection.
>
> So, to disable collision-detection for guardians, we can call it
> with C == 0 by using the following POKE...
>
> POKE 37392,0 (Hex 9210: 00)
>
> ...which modifies the following code...
>
> #920F: LD C,1 ;;;;;;;; enable collision-detection
> #9211: LD A,(IX+1) ;;; A:= animation-mask
> #9214: AND (IX+0) ;;;; bitwise-AND it with the current frame-number
> #9217: OR (IX+2) ;;;;; bitwise-OR that with the start-sprite
> #921A: AND %11100000 ; extract frame-number to be drawn
> #921C: LD E,A ;;;;;;;; this forms the low byte of the sprite-address
> #921D: LD D,(IX+5) ;;; D:= sprite-page (high byte of sprite-address)
> #9220: LD H,#82 ;;;;;; lookup-table at #8200: position -> address
> #9222: LD L,(IX+3) ;;; L:= guardian's row (in pixels*2)
> #9225: LD A,(IX+2) ;;; A:= start-sprite | cell-column
> #9228: AND %00011111 ; extract cell-column
> #922A: OR (HL) ;;;;;;; table lookup: (row, column) -> low byte
> #922B: INC HL ;;;;;;;; point to next byte in table
> #922C: LD H,(HL) ;;;;; table lookup: (row, column) -> high byte
> #922D: LD L,A ;;;;;;;; {HL == address to draw sprite}
> #922E: CALL #9456 ;;;; call sprite-drawing subroutine
>
> ...as follows:
>
> #920F: LD C,0 ;;;;;;;; disable collision-detection
>
> This differs from Method B in that:
>
> (a) it's only one POKE;
>
> (b) it doesn't disable collision-detection for Maria (that can be
> done by POKE 38242,0 (Hex 9562: 00));
>
> (c) each guardian-sprite overwrites everything in its 16x16-pixel
> square, rather than merging its pixels with what's there already.
> This means that each guardian is like a moving portal; thus
> stationary guardians can be combined with teleporters to simulate
> portals (which are permanently open, regardless of any items in the
> room).
