Post new topic    
Metal Slime
Send private message
Jumping (down a ledge) 
 PostThu Jul 07, 2016 1:18 am
Send private message Reply with quote
Hello,

I have a script for jumping down a ledge, but it's not behaving. The attached image shows the path I want the player to follow during this scripted movement.
Here are my scripts:

Code:

script, jump, direction, distance, begin
   suspend hero walls
   walk hero (me, direction, distance) #move (distance) tile in (direction)
     set hero Z (me, +2)     #Frame 1
   wait(distance)
   set hero Z (me, +4)     #Frame 2
   wait(distance)
   set hero Z (me, +6)     #Frame 3
   wait(distance)
   set hero Z (me, +4)     #Frame 4
   wait(distance)
   set hero Z (me, +2)     #Frame 5
   wait(distance)
   resume hero walls
end


That is the script that will be called for jumps, here is the actual plotscript:

Code:
plotscript, abseil, begin
   suspend player
   suspend obstruction
   suspend NPCs
   jump (down, 2)
   wait for hero (me)
   walk hero (me, left, 3)
   wait for hero (me)
   walk hero (me, down, 1)
   wait for hero (me)
   jump (down, 2)
   wait for hero (me)
   walk hero (me, left, 2)
   wait for hero (me)
   jump (left, 2)
   wait for hero (me)
   resume player
   resume obstruction
   resume NPCs
end


The problem is the "set hero z" commands don't seem to be functioning correctly. If I have them set to minus (-) the hero's Z position instead of (+), the script works fine but it looks weird as the player seems to "duck" instead of jump, but with (+) Z commands the player's Z position isn't changed, he just walks through the ledges as normal.

Also, assuming I get this working properly, should I be resetting the hero's Z position at the end of the script?

Many regards.
vvight.wordpress.com
Metal King Slime
Send private message
 
 PostThu Jul 07, 2016 5:10 am
Send private message Reply with quote
HSpeak does not recognise +2 to mean 2. Instead it interprets "set hero Z (me, +2)" to mean "set hero Z (me+2)" with the unspecified Z argument defaulting to 0. Get rid of the +'s. In future I may make HSpeak stricter about disallowing stray commas in certain contexts. And yes, you need to put a "set hero Z (me, 0)" at the end of the script.

Aside from that, only changing the hero's Z coordinate every 2 ticks instead of every tick is going to make the animation less smooth than it could be. Although I can see you did that to make the script simpler and more flexible. Also, I'm always going to have to complain about non-parabolic (non-physical) jump arcs, it's a pet peeve. You're using a triangular rather than parabolic arc, although over just a few ticks there's not much difference. Worse, the script is written for jumping over a two tile wide gap instead of jumping one tile south and dropping by 20 pixels. Doing a physically correct parabolic arc is tricky, it looks something like this (took me a while to get this right), and think it looks much nicer:

Code:
# Move one tile in any direction, while also falling 1 tile
script, jump down, who, direction, begin
  suspend hero walls
  variable(vz, i, old speed)
  old speed := get hero speed(who)
  if (direction == south) then (
    set hero speed(who, 4)
    walk hero(who, south, 2)
  ) else (
    set hero speed(who, 2)
    walk hero(who, south, 1)
    walk hero(who, direction, 1)
  )
  # This line is optional, comment it out to make the camera move in a straight line
  camera follows slice(lookup slice(sl:walkabout sprite component, get hero slice(who)))
  vz := 3
  for (i, 1, 10) do (
    # The +2 here is to make the total Z movement add to 0
    set hero Z(who, hero Z(who) + vz + 2)
    vz -= 1
    wait
  )
  set hero Z(who, 0)
  camera follows hero(who)
  set hero speed(who, old speed)
  resume hero walls
end


Comment the line marked optional to change the camera movement; see which way you prefer.
Metal Slime
Send private message
 
 PostThu Jul 07, 2016 11:22 am
Send private message Reply with quote
Thankyou for the detailed response.

With your advice, I got my script working and it looks ... fine. But I then tried the one that you kindly provided and it looks much nicer and "realistic".
If I were to reuse the script in the future, what kind of changes would I have to make for other kinds of jumps? For example, if I wanted the hero to jump 3 spaces across a gap without dropping, or jumping down a ledge more than 2 spaces?

I really must thank you for the exemplary help. '

Regards.
vvight.wordpress.com
Metal King Slime
Send private message
 
 PostSat Jul 09, 2016 2:54 pm
Send private message Reply with quote
Well, unfortunately generalising it isn't that easy (especially if you commented out that 'camera follows slice' line), but I can try it tomorrow. If you just want to jump across a gap without dropping, there's already a script you can use here. I think it even uses the same strength of gravity, so should look fine together with the script I posted
Metal Slime
Send private message
 
 PostSun Jul 10, 2016 5:37 am
Send private message Reply with quote
Thanks, with the script you have provided I'll work to figure something out, and post if I have issues.

Regards.
vvight.wordpress.com
Metal King Slime
Send private message
 
 PostSun Jul 10, 2016 11:02 am
Send private message Reply with quote
Well, I really got carried away and rewrote the script to do any jump one could want, up, down, level, diagonal, any distance, and you can adjust the constants like the strength of gravity without completely breaking it. So now I can point people at this in the future. There's also some animation code in there, which might need adjusting for the way you're drawn your walkabouts.

Code:

define constant(1, gravity)

# Make a hero jump a certain number of tiles in the X, Y and Z directions,
# possibly diagonally.
# 'z tiles' is the amount to travel upwards (negative for downwards),
# e.g. -1 to fall to a platform that's one tile lower,
# 0 for a jump between two level platforms, 2 to gain 2 tiles height, etc.
script, jump hero, who, x tiles, y tiles, z tiles = 0, begin

  # How hard do we have to jump upwards? This part might need some adjusting,
  # and if 'initial vz' isn't large enough when jumping upwards, the hero will get
  # jerked to the destination
  variable(initial vz)
  if (z tiles < 0) then (initial vz := 4)  # Just hop over the edge (assuming we don't jump far)
  else if (z tiles == 0) then (initial vz := 6)  # Jumping straight
  else (initial vz := 6 + z tiles * 2)  # Jumping upwards

  # First calculate ahead of time how long it's going to take to jump
  # Keep dropping until we've fallen to the desired z value on the way down (vz is negative)
  variable(ticks, z, vz)
  vz := initial vz
  while (vz >= 0 || z > z tiles * 20) do (
    z += vz
    vz -= gravity
    ticks += 1
  )

  # Move in an arc using puthero
  camera follows slice (lookup slice(sl:walkabout sprite component, get hero slice(who)))
  variable(startx, starty, i)
  startx := hero X (who)
  starty := hero Y (who)
  vz := initial vz
  # Skip one tick: the last frame is when we realign, not inside the for loop
  for (i, 1, ticks -- 1) do (
    put hero (who, 20 * start x + 20 * x tiles * i / ticks, 20 * start y + 20 * y tiles * i / ticks)
    set hero Z (who, hero Z (who) + vz)
    vz -= gravity
    # For no walking animation during the jump, comment this line:
    if (i < 5) then (set hero frame (who, (i/2, mod, 2)))
    wait
  )

  # Realign the hero, converting Z displacement to Y position
  set hero position (who, start x + x tiles, start y + y tiles -- z tiles)
  set hero Z (who, 0)
  set hero frame (who, 1)   # Ideally, change this to the 'standing' instead of 'stepping' walk frame
  camera follows hero (who)
end


Here's a convenient script to test it:

Code:


plotscript, onkeypress test jump, begin
  if (keyval(key:1) > 1) then (
    do a jump(1, 0)
  ) else if (keyval(key:2) > 1) then (
    do a jump(2, 0)
  ) else if (keyval(key:3) > 1) then (
    do a jump(3, 0)
  ) else if (keyval(key:d) > 1) then (
    do a jump(1, -1) # down
  ) else if (keyval(key:p) > 1) then (
    do a jump(1, -3) # plummet
  ) else if (keyval(key:u) > 1) then (
    do a jump(1, 1) # up
  )
end

script, do a jump, distance, z, begin
  switch (hero direction(me)) do (
    case(south) jump hero(me, 0, distance, z)
    case(north) jump hero(me, 0, -1*distance, z)
    case(east)  jump hero(me, distance, 0, z)
    case(west)  jump hero(me, -1*distance, 0, z)
  )
end
Metal Slime
Send private message
 
 PostWed Jul 13, 2016 6:36 am
Send private message Reply with quote
Oh my, this is fantastic. I'm not much of a coder so I'm going to go through it carefully and figure out what exactly is happening. I can't thank you enough!
vvight.wordpress.com
Metal King Slime
Send private message
 
 PostWed Jul 13, 2016 11:20 am
Send private message Reply with quote
I probably should comment/clean it up a little more, and give it a proper page on the wiki.

Of course, normally, you should at least suspend/resume player at the beginning/end of the script, but I skipped that because the script you're calling from already has it.

The game I was testing with has the hero drawn with legs apart on the first frame in each direction, and is standing in the second frame, in which case the jump looks quite nice. The
Display posts from previous: