Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

Directional Key Inputs Moving Gui Icon ?

Asked by
x_Tso 48
4 years ago

Hi! In my never ending quest to ask literally every possible question you can think of on this site, I'm working on a revamp to a revamp of my game, which essentially turns my game into a turn-based bullet board game. To make this as easy as possible, I've chosen to use guis to represent the board, the bullets, and the player. I felt this would be the best way to do this, however, I am open to switching to a part-based bullet, board, and player representation if my current gui-representation won't yield the results I'm looking for.

The current way this works is when the enemy is given a turn, the board will appear on screen, along with your player icon (for placeholder's sake it's just a 14x14 frame.) During the enemy's turn, you will have to avoid their attacks by moving this 14x14 frame via your standard w, a, s, and d keys. Just like you would your regular player character.

The action on the board would be pretty similar to Just Shapes and Beats, minus the rhythm element of that game.

Currently I'm working on the free movement of your 14x14 icon. Press w to go up, a to go left, s to go down, d to go right. You can hold one of these keys to keep a constant speed in that direction until you let go. Hold multiple keys to combine their directions into a diagonal direction. This is literally standard moving-a-player-in-every-single-game type stuff.

So, here's how I detect the player holding a single key. In this case, this detects the player has held the "w" key, and proceeds to move them up.

local uiservice = game:GetService("UserInputService")

local holdingWKey = false

uiservice.InputBegan:Connect(function(inputObject) 
    if inputObject.KeyCode == Enum.KeyCode.W then
        holdingWKey = true
        while holdingWKey do
        --this is where the icon movement magic happens!
        end
    end
end)

uiservice.InputEnded:Connect(function(inputObject)
    if inputObject.KeyCode == Enum.KeyCode.W then
        holdingWKey = false
    end
end)

This snippet of code is the same for the other 3 main directional keys. The only difference is a variable with a different name to match the key you're holding, and some slightly different movement code (that only moves it in a different direction.)

That piece of code is not my problem. I've tested it where the "while holdingWKey do" part just prints a random string to test it's responsiveness and reliability (since those are essential for how hard some of these enemies are gonna be.) It's responsive. It's reliable. It detects when I'm holding and it detects it good.

If there's a more efficient way of detecting holding keys, I am also open to change that, but keep in mind, that's not my problem area.

My problem area is the icon movement magic.

Currently I'm using a recycled method from a game I previously worked on 3 months ago (according to my post history at least), which was literally just a ROBLOX port of Just Shapes and Beats, or it was meant to be one. I scrapped it.

The player icon moved like this:

script.Parent.Background.PlayerIcon.Position = script.Parent.Background.PlayerIcon.Position + UDim2.new(0, 0, -5, 0)

So, it moves the icon 5 pixels up on the board every time the loop runs past that piece of code. The issue is that it's moving 5 pixels at a time. 5 pixels at a time is somewhat noticeable if you're not paying attention, but very noticeable when you are. If I lower the pixel increment so it maybe runs, say, 2 pixels per loop, it looks smoother, but the icon moves much, much slower. That's obvious, because it's running the loop at the same speed yet moving it less per loop. So, with this method, I am running on picking one of two options:

Do I want the icon to move in a fluid, smooth manner? or Do I want the icon to move fast, allowing for more speedy gameplay?

Picking one of the two is like those "pick 2 on the triangle." Obviously I want both. But, with this current method, I'm not able to use both. I have to sacrifice one element and obviously it hurts to watch my icon move fast, yet choppily, or, rather, smoothly yet painstakingly slow.

There is a game which I believe pulls off this kind of idea using a part-based board, icon, and bullets, but kind of covers the same essential idea (except it doesn't use guis.) That game would be badtime.tiff by magic277.

Here's a link to a gameplay video of the hardest difficulty (which can help show what kind of speed and precision is necessary (there will be enemies harder than the level the player plays in the video if that helps.))

https://www.youtube.com/watch?v=sWolBiI8C44

I linked a video because the game is now set to private.

So, of course, I'm trying to do that essentially, but with guis instead of parts. Again, if necessary, I will think of a system that uses parts.

My other idea would be tweening, but from what I am aware, you can't tween specifically on a single axis (x or y), and overriding tweens every time a loop runs would definitely not work visually. Plus, the player would be a little slippery, possibly not stopping exactly when you let go of a specific key.

So, what can I do?

0
Please be patient I'm slow and stupid with LUA. x_Tso 48 — 4y

1 answer

Log in to vote
0
Answered by 4 years ago
Edited 4 years ago

A method that seemed to achieve what you're going for, whereby it's smooth and as fast or slow as you need it to be is to run IsKeyDown checks on W, A, S, and D every frame like so:

local userInputService = game:GetService("UserInputService")
local player = script.Parent    -- the GUI object the player moves

local movementData = {
    [Enum.KeyCode.W] = UDim2.new(0, 0, 0, -5),
    [Enum.KeyCode.S] = UDim2.new(0, 0, 0, 5),
    [Enum.KeyCode.A] = UDim2.new(0, -5, 0, 0),
    [Enum.KeyCode.D] = UDim2.new(0, 5, 0, 0)    
}

local function update()
    for key, direction in pairs(movementData) do
        if userInputService:IsKeyDown(key) then
            player.Position = player.Position + direction
        end
    end
end

game:GetService("RunService").Stepped:Connect(update)

The work at hand here isn't involved at all so you can probably see what's going on, but essentially every frame (RunService.Stepped), the table 'movementData' is iterated through to detect which key(s) are being held down, and a UDim2 value is added to the GUI object position depending on the results of that (as you were doing before). I've started at offsets of 5 pixels, but this can be bumped up to 10, 20, 30, whatever; it runs smooth regardless.

0
works beautifully! seems I was on the right track by adding onto the position of the icon using UDim2, but not quite. thanks for the help! x_Tso 48 — 4y
Ad

Answer this question