Moving the Hero with "set slice velocity x()"

Ask and answer questions about making games and related topics. Unrelated topics go in that other forum.

Moderators: marionline, SDHawk

Post Reply
User avatar
kylekrack
Liquid Metal Slime
Posts: 1242
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Moving the Hero with "set slice velocity x()"

Post by kylekrack »

Since the slice returned by "get hero slice()" cannot be manually repositioned, is there another slice, such as the "sl:walkabout slice component" child of the hero slice that can be moved? I'd like to see if I can get some movement done easily with the set slice velocity commands, but would like to hold onto some nifty info, like hero direction.

I didn't know if setting velocity counted as repositioning a slice, so I tried it anyway, on both the hero slice and its walkabout sprite component, and got an invalid slice id error. It was unsurprising, but I'm still unsure where to go from here.

Alternatively, I could just create an entirely new slice and make the camera follow it, but I don't have a full plan on how to execute that.
My pronouns are they/them
Ps. I love my wife
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

If you got an invalid slice handle error then you must have called something with the wrong arguments.

I checked and found that the Y position of the walkabout sprite component can't be overridden, as it is set every frame to the foot offset. And the camera isn't centered on it anyway (again, there's special behaviour for the foot offset).

I think you're going to need to move around a separate slice.
User avatar
kylekrack
Liquid Metal Slime
Posts: 1242
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

Sounds good. I started on that anyway because I still wanted to be working on it instead of just giving up.

I have run into a few problems with manipulating a loaded hero sprite (I will be using hero sprites instead of walkabouts in a sidescroller manner). I think I misunderstand what setting the velocity of a slice actually does. Basically, moving left and right works fine, no problems. I have a script setup similar to Baby Bob, wherein a keypress handler sets variables "want left" and "want right" and the main game loop responds accordingly. This works fine at the *edges* of the screen (x pixel values 0-320, where the game window ends), but once the sprite moves beyond that, the velocity accelerates indefinitely, until it reaches the other side of the map, at which point it slows back to normal speed.

The whole movement script is posted below. It's not fully polished, I still need to fix wall conditions. Those don't work at all yet, but I'm pretty sure they won't with the approach I'm using. What's happening in a nutshell is 'xv' is a global variable that represents the player's x velocity. The script "walk override(dir)" sets 'xv' based on direction and wall conditions (in theory), and then sets the slice's x velocity to 'xv'.

Of course, if I'm doing something entirely wrong, that would be good to know. Otherwise, I'd like to use the slice velocity scripts, because I have never used them for anything successfully before and they seem so useful. I just don't understand the weird acceleration bug.

Code: Select all

global variable, begin
    0,game is running
    1,paused
    2,want left
    3,want right
    4,xv
    5,player
end

define constant(5,walkv)
define constant(10,runv)

plotscript, new game, begin
    suspend player
    
    create hero sprite
    main game loop
end

script, create hero sprite, begin
    player := load hero sprite(1)
    camera follows slice(player)
    put sprite(player,hero x(0) * 20,(hero y(0) -- 1) * 20)
end

script, main game loop, begin
    
    game is running := true
    
    while(game is running) do, begin
        
        
        # Movement
        if(want left) then(walk override(left))
        else if(want right) then(walk override(right))
        else(set slice velocity x(player,0))
        
        # Check Walls
        if(check wall(left) || check wall(right)) then(
            xv := 0)
        
        # Pause Game Conditions
        if(current textbox >= 0
        || top menu == true
        )
        then(paused := true)
        else(wait, paused := false)
        
        if(get slice velocity x(player) ==  0) then(
            xv := 0)
        
        want left := false
        want right := false
        
        # Wait
        wait
    end
end

plotscript, keypress handler, begin
  if(paused == false) then(
    if(key is pressed(key:left)) then(
        want left := true)
    if(key is pressed(key:right)) then(
        want right := true)
    if(key is pressed(key:z)) then(
        activate center item)
    if(key is pressed(key:esc) || key is pressed(key:filtered alt)) then(
        open menu(0))
  )
end

script, walk override, dir, begin
    variable(sl)
    sl := get moving slice
    
    if(dir == left) then(
        if(check wall) then(
            xv := 0)
        else(    
            xv := walkv -- (walkv * 2))
    )
    else(
        if(check wall) then(
            xv := 0)
        else(    
            xv := walkv)
    )
    
    set slice velocity x(player,xv)
    
    
end

script, check wall, dir, begin
    variable(x,y)
    x := slice x(player)
    y := slice y(player)
    
    if(dir == left) then(
        if(read pass block((x/20) -- 1, y)) then(
            return(true)
        )
    )
    else(
        if(read pass block((x/20) + 1, y)) then(
            return(true)
        )
    )
end
My pronouns are they/them
Ps. I love my wife
User avatar
Bob the Hamster
Lord of the Slimes
Posts: 7660
Joined: Tue Oct 16, 2007 2:34 pm
Location: Hamster Republic (Ontario Enclave)
Contact:

Post by Bob the Hamster »

If you are making a sidescroller, you probably should not be using the built-in slice velocity at all.

Your are probably better off tracking your velocity in your xv variable, and then adding it to the slice x once per tick

set slice x(player, slice x(player) + xv)

The built-in velocity feature was intended for animations, and I don't know if anybody has ever successfully used it for a sidescroller or not.
User avatar
kylekrack
Liquid Metal Slime
Posts: 1242
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

Will do! Thank you for the answer. It was an experiment, if anything. It seemed like it would remove an extra step from the process, but it looks like I was definitely wrong about that. I may be back with more questions.
My pronouns are they/them
Ps. I love my wife
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

The reason why using slice velocity commands doesn't save you any work is that for wall checking you need to calculate where the hero sprite is going to be (trying to move to) anyway. You probably haven't realised that yet because your current wall checking code is tile based rather than pixel based. Basically, you only need to check for a wall when you actually cross the edge of a tile. Baby Bob should be a good reference.

I also notice you have "if(check wall(left) || check wall(right)) then(xv := 0)" in the main loop and the same logic in "walk override". There shouldn't be a need to duplicate it.

Also, writing "top menu == true" is incorrect. topmenu returns a menu handle, or 0 (false) if none is open. "not(top menu == false)" is not the same thing as "top menu == true"! I believe you can implement pausing as a while loop if you want ("while (menu or text open) do (want left := false , want right := false, wait)"), but do you need to be careful: I think this should be put at the top of the main loop. Or just use a "paused" global like you're using, that's fine too. But you need to suspend all the game logic, not just player input, unless the player is the only thing that moves and there's no gravity.
User avatar
kylekrack
Liquid Metal Slime
Posts: 1242
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

I started working on a pixel based wall check that I am now realizing is whack. Fixing the movement first should fix that along. The wall check in the main loop was actually a debugging attempt to see if wall checks would work in any condition (it wasn't). I shouldn't have left it there.

Thank you for the pointers. I will fix the pausing functions, including the menu check. Also, I notice you say top menu returns 0 if no menu is open. Shouldn't it return -1 for no menu open, considering menu 0 is the main menu? In this case, should "if(top menu >= 0)" work, or would it have to simply be greater than 0?
My pronouns are they/them
Ps. I love my wife
TMC
Metal King Slime
Posts: 4308
Joined: Sun Apr 10, 2011 9:19 am

Post by TMC »

No, "top menu" returns a menu handle not a menu ID. Afterall it's possible to show a menu not defined in Custom. You can't make any assumptions about whether handles are positive or negative (in future, they will no longer even be numbers except in the 'false' case).
User avatar
kylekrack
Liquid Metal Slime
Posts: 1242
Joined: Mon Jun 16, 2014 8:58 am
Location: USA
Contact:

Post by kylekrack »

Gotcha. I'll have to be more careful dealing with menus in the future. Thanks for the explanations!
My pronouns are they/them
Ps. I love my wife
Post Reply