Godot Version
godot-4
Question
I’m working on an fps game and need a way to switch weapons, currently my number key switching works, but I’m struggling to get the mousewheel to work. like most games, I have my weapons stored in an array, and when you mousewheel up, the weapon selected goes up, and vice versa, looping around to the opposite end when you reach either extreme of the array.
currently I have 3 weapons in my array, and cycling through them with the mouse wheel goes 0 → 2 → 1 → 0, instead of 0 → 1 → 2 → 0
I have no earthly idea why this is, please help.
I don’t have moving down through the array set up yet because moving up is so broken, but if someone knows how to do that, that would be appreciated as well.
func _input(event):
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
if curWeapon >= Weapons.size() - 1:
curWeapon = 0
else:
curWeapon = curWeapon + 1
_switch_weapon()
func _switch_weapon():
var i = 0
for gun in Weapons:
if i == curWeapon:
gun.visible = true
else:
gun.visible = false
i += 1```
for further context, I added more placeholder wepons to the area to see what happened(5 in total), and the pattern switched to 0 → 2 → 4 → 1 → 3 → 0,
so somewhere in my code, I’m adding 2 instead of one, but I don’t know why
Scrolling trough the weapons would make it easier for the player. Good idea.
First of all, the comparison made in the for loop in _switch_weapon
is disconnected from the for loop itself. You are looping over Weapons, but comparing the i variable to curWeapon and not picking a gun from the array. In this case, we can’t be sure the guns are in the same order as you’re expecting it to be. Since you are not picking an index from the weapons array, it could be a different gun then it should be.
How are you determining the pattern? Are you printing out the curWeapon variable?
The addition of 2 instead of 1 may be because two mouse scroll wheel inputs are detected. The mouse wheel can be finicky sometimes. Have you checked that this happens?
it would appear that the double mousewheel input is the issue, is there a way to fix this?
I just discovered the mouse wheel problems happens to me too…
First thing came in my mind to solve it is to create a boolean to check if we can scroll the mouse. I’ll call it can_scroll. It’s initialized to true.
When we check that
event.button_index == MOUSE_BUTTON_WHEEL_UP
we check
if can_scroll
and if it’s true, we can do our things and, after that, we can write something like:
var timer = Timer.new()
self.add_child(timer)
timer.oneshot= true
timer.timeout.connect(func():
can_scroll = true
timer.queue_free()
)
timer.start(0.001)
This gives us a delay of 1ms between each call to mouse wheel. I just tested and it seems to work.
Also, this is not about the question but you can try modular arithmetic for weapon index. That is, you could increase the index with something like:
curWeapon = (curWeapon + 1) % Weapons.size()
While to decrease it you could write something like:
curWeapon = (curWeapon - 1 + Weapons.size()) % Weapons.size()
I ended up changing the input to
“if event.button_index == MOUSE_BUTTON_WHEEL_UP && event.pressed == true:”
which looks like this in context:
func _input(event):
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_WHEEL_UP && event.pressed == true:
if curWeapon >= Weapons.size() - 1:
curWeapon = 0
else:
curWeapon = curWeapon + 1
mouseTimeSet = true
_switch_weapon()
```
for anyone looking for a full implementation of this concept, here’s my code, it should be reasonably plug and play
this would be placed on a node with all of the weapons parented to it. weapons is an array[node3d] that I .append() all the weapons into at the start of the game using a for loop and get children.
func _input(event):
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_WHEEL_UP && event.pressed == true:
if curWeapon >= Weapons.size() - 1:
curWeapon = 0
else:
curWeapon = curWeapon + 1
_switch_weapon()
if event.button_index == MOUSE_BUTTON_WHEEL_DOWN && event.pressed == true:
if curWeapon <= 0:
curWeapon = Weapons.size() - 1
else:
curWeapon = curWeapon - 1
_switch_weapon()
func _switch_weapon():
var i = 0
for gun in Weapons:
if i == curWeapon:
gun.visible = true
else:
gun.visible = false
i += 1
text.bbcode_text = "[wave amp=50.0 freq=5.0 connected=1]"+str(curWeapon)+"[/wave]"