Shop OBEX P1 Docs P2 Docs Learn Events
HYDRA Pacman demo code question. — Parallax Forums

HYDRA Pacman demo code question.

CoolguyCoolguy Posts: 26
edited 2007-11-02 02:03 in Propeller 1
I've a question on the below code. This is from HYDRA book page 538. It is reference to pacman_tile_demo_002.spin. What is this code do?

tile_map2[noparse][[/noparse]ghost_tx + ghost_ty << 4]

I don't understand what is it do?

Below is the whole PUB

PUB Start
' This is the first entry point the system will see when the PChip starts,
' execution ALWAYS starts on the first PUB in the source code for
' the top level file
' star the game pad driver
game_pad.start
' initialize all vars
ghost_tx· := 4··················· ' set tile location of ghost to center of screen
ghost_ty· := 6··················· ' about (4,6)
ghost_dir := GHOST_TILE_LEFT····· ' start ghost out with eyes to left
······················
' set up tile and sprite engine data before starting it, so no ugly startup
' points ptrs to actual memory storage for tile engine
tile_map_base_ptr_parm······· := @tile_map2
tile_bitmaps_base_ptr_parm··· := @tile_bitmaps
tile_palettes_base_ptr_parm·· := @palette_map
' these control the sprite engine, all 0 for now, no sprites
tile_map_sprite_cntrl_parm··· := $00_00 ' 0 sprites, tile map set to 0=16 tiles wide, 1=32 tiles, 2=64 tiles, etc.
tile_sprite_tbl_base_ptr_parm := 0
tile_status_bits_parm········ := 0
' launch a COG with ASM video driver
gfx.start(@tile_map_base_ptr_parm)
' enter main event loop...
repeat while 1
·
· ' main even loop code here...
· ' draw the ghost tile by overwriting the screen tile word destructively, both
· ' the palette index and the tile index
· ' note the add of "ghost_dir", this modifies the tiles, so we can see the ghost
· ' turn right, left, up, down as he moves.

· ' test if player is trying to move ghost, if so write a blank tile at current location
· ' overwriting tile index and palette
· ' then move ghost
· if (game_pad.button(NES0_RIGHT))
··· ' clear tile
··· tile_map2[noparse][[/noparse]ghost_tx + ghost_ty << 4] := $02_00·
··· ' move ghost
··· ghost_tx++
··· ' set eye direction, which affects tile selected during rendering.
··· ghost_dir := GHOST_TILE_RIGHT

· if (game_pad.button(NES0_LEFT))
··· ' clear tile
··· tile_map2[noparse][[/noparse]ghost_tx + ghost_ty << 4] := $02_00·
··· ' move ghost
··· ghost_tx--
··· ' set eye direction, which affects tile selected during rendering.
··· ghost_dir := GHOST_TILE_LEFT
· if (game_pad.button(NES0_UP))
··· ' clear tile
··· tile_map2[noparse][[/noparse]ghost_tx + ghost_ty << 4] := $02_00·
··· ' move ghost
··· ghost_ty--
··· ' set eye direction, which affects tile selected during rendering.
··· ghost_dir := GHOST_TILE_UP

· if (game_pad.button(NES0_DOWN))
··· ' clear tile
··· tile_map2[noparse][[/noparse]ghost_tx + ghost_ty << 4] := $02_00·
··· ' move ghost
··· ghost_ty++
··· ' set eye direction, which affects tile selected during rendering.
··· ghost_dir := GHOST_TILE_DOWN
· ' bounds check ghost, keep it on screen, use SPIN operators for bounds testing
· ghost_tx <#= 9 ' if (ghost_tx > 9) then ghost_tx = 9
· ghost_tx #>= 0 ' if (ghost_tx < 0) then ghost_tx = 0·
· ghost_ty <#= 11 ' if (ghost_ty > 11) then ghost_tx = 11
· ghost_ty #>= 0· ' if (ghost_ty < 0) then ghost_ty = 0·
· ' draw ghost down
· tile_map2[noparse][[/noparse]ghost_tx + ghost_ty << 4] := $02_04 + ghost_dir
· ' delay a moment, otherwise everything will blur!
· repeat 20_000
···
· ' return back to repeat main event loop...
' parent COG will terminate now...if it gets to this point

Comments

  • CardboardGuruCardboardGuru Posts: 443
    edited 2007-11-01 02:30
    Hi Coolguy,

    Spin doesn't have 2 dimensional arrays, so you have to use a one dimensional array. You have to multiply the y coordinate by the width of the array. In this case the width must be 16. So you'd do this:

    tile_map2[noparse][[/noparse]ghost_tx + ghost_ty*16]

    However, a trick of doing a multiply by 16 quickly is to shift a value 4 binary places to the left.

    00000001 binary = 1 in decimal.
    00010000 binary = 16 in decimal.

    In spin << is the left shift operator. So

    tile_map2[noparse][[/noparse]ghost_tx + ghost_ty << 4] is the same as tile_map2[noparse][[/noparse]ghost_tx + ghost_ty*16], but possibly a little faster.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Help to build the Propeller wiki - propeller.wikispaces.com
    Prop Room Robotics - my web store for Roomba spare parts in the UK
  • CoolguyCoolguy Posts: 26
    edited 2007-11-01 08:06
    CardboardGuru,

    WOW! I understand this.

    tile_map2[noparse][[/noparse]ghost_tx + ghost_ty*16]

    But the rotate left trick just throw me off. Thanks now.

    Coolguy
  • AndreLAndreL Posts: 1,004
    edited 2007-11-02 02:03
    In general, I REALLY try to make the code as straightforward as possible and not be cryptic or clever. But, since the propeller has no multiply when multiplying by a power of 2, I can't help myself from using shifts. Also, you can multiply any number with this technique, but at some point a general multiply will be faster, but say you wanted x * 50?

    50 = 32 + 16 + 2, thus x*(50) = x*(32+16+2) = 32*x + 16*x + 2*x = x << 5 + x << 4 + x << 1

    So on a microprocessor with no multiply that at least has a shift operator, or better yet a barrell roll operator you can do the multiply in 3 instructions basically.

    Now in spin, this may work against you since its so slow compared to asm, the act of running the three different shift adds might be slower then just saying x*50, since once the i-code finally gets to the multiply its going to be pretty quick, but you can always try this technique and for exact powers of 2 its definitely faster, but if you have to do two lines of code, the overhead of the spin interpreter might kill the amount of actual "work" you save with the trick...

    Andre'
Sign In or Register to comment.