mirror of
https://github.com/minetest-mods/throwing.git
synced 2025-01-09 09:40:26 +01:00
New physics
This commit is contained in:
parent
bd4d040c4e
commit
0dd44bb30c
26
README.md
26
README.md
@ -13,10 +13,14 @@ Mods based on this API:
|
|||||||
|
|
||||||
The settings are the following:
|
The settings are the following:
|
||||||
```
|
```
|
||||||
# Movement parameters
|
# Trajectory parameters
|
||||||
throwing.velocity_factor = 19
|
|
||||||
throwing.horizontal_acceleration_factor = -3
|
|
||||||
throwing.vertical_acceleration = -10
|
throwing.vertical_acceleration = -10
|
||||||
|
throwing.realistic_trajectory = false
|
||||||
|
throwing.frictional_coefficient = -.5
|
||||||
|
|
||||||
|
# How the initial velocity of arrows is computed: simple, strength, or momentum
|
||||||
|
throwing.velocity_mode = strength
|
||||||
|
throwing.velocity_factor = 19
|
||||||
|
|
||||||
# Whether to allow placing an arrow as a node
|
# Whether to allow placing an arrow as a node
|
||||||
throwing.allow_arrow_placing = false
|
throwing.allow_arrow_placing = false
|
||||||
@ -28,6 +32,22 @@ throwing.bow_cooldown = 0.2
|
|||||||
throwing.toolranks = true
|
throwing.toolranks = true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Trajectory parameters
|
||||||
|
|
||||||
|
By default, the trajectory of the arrow is a simple parabola. You can set the vertical acceleration (acceleration of gravity) using `throwing.vertical_acceleration`.
|
||||||
|
|
||||||
|
If you want a more realistic trajectory that uses a first-order modelling of air friction, you can set `throwing.realistic_trajectory` to true. In this mode, `throwing.frictional_coefficient` indicates the ratio between the friction force on the arrow and its velocity. It should be negative. The acceleration of the arrow is subsequently determined by dividing the force by the "mass" of the arrow, the reference mass of 1 being the mass of a simple steel arrow. Generally, the frictional coefficient should be quite small; a value of -1 will already drastically shorten the range of the arrow. The default is -0.5.
|
||||||
|
|
||||||
|
### Initial velocity computation
|
||||||
|
|
||||||
|
The mod provides three modes to compute the initial speed of an arrow: simple, strength or strengthmass.
|
||||||
|
|
||||||
|
In simple mode, the initial velocity of the arrow is always the same. The `throwing.velocity_factor` contains the value of this velocity.
|
||||||
|
|
||||||
|
In strength mode (the default), the initial velocity of the arrow only depends on the bow that is used---the more expensive the bow, the faster the arrow. The arrow strength is multiplied by the velocity factor to compute the speed of the arrow, an arrow strength of 1 is about the strength of the steel bow in `throwing_arrows`.
|
||||||
|
|
||||||
|
Finally, momentum mode is the most realistic. It computes the velocity of the arrow based on the bow strength, as in the strength mode, and on the mass of the arrow: the heavier the arrow, the slower it will be shot. It is called the momentum mode because, in this mode, the strength of a bow indicates the initial momentum of the arrow rather than its initial speed.
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
There are two available functions in the mod API:
|
There are two available functions in the mod API:
|
||||||
|
52
init.lua
52
init.lua
@ -28,6 +28,22 @@ function throwing.spawn_arrow_entity(pos, arrow, player)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function apply_realistic_acceleration(obj, mass)
|
||||||
|
if not minetest.settings:get_bool("throwing.realistic_trajectory", false) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local vertical_acceleration = tonumber(minetest.settings:get("throwing.vertical_acceleration")) or -10
|
||||||
|
local friction_coef = tonumber(minetest.settings:get("throwing.frictional_coefficient")) or -3
|
||||||
|
|
||||||
|
local velocity = obj:get_velocity()
|
||||||
|
obj:set_acceleration({
|
||||||
|
x = friction_coef * velocity.x / mass,
|
||||||
|
y = friction_coef * velocity.y / mass + vertical_acceleration,
|
||||||
|
z = friction_coef * velocity.z / mass
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
local function shoot_arrow(def, toolranks_data, player, bow_index, throw_itself, new_stack)
|
local function shoot_arrow(def, toolranks_data, player, bow_index, throw_itself, new_stack)
|
||||||
local inventory = player:get_inventory()
|
local inventory = player:get_inventory()
|
||||||
local arrow_index
|
local arrow_index
|
||||||
@ -65,14 +81,29 @@ local function shoot_arrow(def, toolranks_data, player, bow_index, throw_itself,
|
|||||||
end
|
end
|
||||||
|
|
||||||
local dir = player:get_look_dir()
|
local dir = player:get_look_dir()
|
||||||
local velocity_factor = tonumber(minetest.settings:get("throwing.velocity_factor")) or 19
|
|
||||||
local horizontal_acceleration_factor = tonumber(minetest.settings:get("throwing.horizontal_acceleration_factor")) or -3
|
|
||||||
local vertical_acceleration = tonumber(minetest.settings:get("throwing.vertical_acceleration")) or -10
|
local vertical_acceleration = tonumber(minetest.settings:get("throwing.vertical_acceleration")) or -10
|
||||||
|
local velocity_factor = tonumber(minetest.settings:get("throwing.velocity_factor")) or 19
|
||||||
|
local velocity_mode = minetest.settings:get("throwing.velocity_mode") or "strength"
|
||||||
|
|
||||||
obj:set_velocity({x=dir.x*velocity_factor, y=dir.y*velocity_factor, z=dir.z*velocity_factor})
|
local velocity
|
||||||
obj:set_acceleration({x=dir.x*horizontal_acceleration_factor, y=vertical_acceleration, z=dir.z*horizontal_acceleration_factor})
|
if velocity_mode == "simple" then
|
||||||
|
velocity = velocity_factor
|
||||||
|
elseif velocity_mode == "momentum" then
|
||||||
|
velocity = def.strength * velocity_factor / luaentity.mass
|
||||||
|
else
|
||||||
|
velocity = def.strength * velocity_factor
|
||||||
|
end
|
||||||
|
|
||||||
|
obj:set_velocity({
|
||||||
|
x = dir.x * velocity,
|
||||||
|
y = dir.y * velocity,
|
||||||
|
z = dir.z * velocity
|
||||||
|
})
|
||||||
|
obj:set_acceleration({x = 0, y = vertical_acceleration, z = 0})
|
||||||
obj:set_yaw(player:get_look_horizontal()-math.pi/2)
|
obj:set_yaw(player:get_look_horizontal()-math.pi/2)
|
||||||
|
|
||||||
|
apply_realistic_acceleration(obj, luaentity.mass)
|
||||||
|
|
||||||
if luaentity.on_throw_sound ~= "" then
|
if luaentity.on_throw_sound ~= "" then
|
||||||
minetest.sound_play(luaentity.on_throw_sound or "throwing_sound", {pos=playerpos, gain = 0.5})
|
minetest.sound_play(luaentity.on_throw_sound or "throwing_sound", {pos=playerpos, gain = 0.5})
|
||||||
end
|
end
|
||||||
@ -224,6 +255,8 @@ function throwing.arrow_step(self, dtime)
|
|||||||
wielded_light.update_light_by_item(self.item, self.object:get_pos())
|
wielded_light.update_light_by_item(self.item, self.object:get_pos())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
apply_realistic_acceleration(self.object, self.mass) -- Physics: air friction
|
||||||
|
|
||||||
self.last_pos = pos -- Used by the build arrow
|
self.last_pos = pos -- Used by the build arrow
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -256,6 +289,7 @@ function throwing.register_arrow(name, def)
|
|||||||
if not def.groups.dig_immediate then
|
if not def.groups.dig_immediate then
|
||||||
def.groups.dig_immediate = 3
|
def.groups.dig_immediate = 3
|
||||||
end
|
end
|
||||||
|
|
||||||
def.inventory_image = def.tiles[1]
|
def.inventory_image = def.tiles[1]
|
||||||
def.on_place = function(itemstack, placer, pointed_thing)
|
def.on_place = function(itemstack, placer, pointed_thing)
|
||||||
if minetest.settings:get_bool("throwing.allow_arrow_placing") and pointed_thing.above then
|
if minetest.settings:get_bool("throwing.allow_arrow_placing") and pointed_thing.above then
|
||||||
@ -313,6 +347,7 @@ function throwing.register_arrow(name, def)
|
|||||||
on_hit_fails = def.on_hit_fails,
|
on_hit_fails = def.on_hit_fails,
|
||||||
on_step = throwing.arrow_step,
|
on_step = throwing.arrow_step,
|
||||||
item = name,
|
item = name,
|
||||||
|
mass = def.mass or 1,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -322,6 +357,7 @@ function throwing.register_bow(name, def)
|
|||||||
local enable_toolranks = use_toolranks and not def.no_toolranks
|
local enable_toolranks = use_toolranks and not def.no_toolranks
|
||||||
|
|
||||||
def.name = name
|
def.name = name
|
||||||
|
|
||||||
if not def.allow_shot then
|
if not def.allow_shot then
|
||||||
def.allow_shot = function(player, itemstack, index)
|
def.allow_shot = function(player, itemstack, index)
|
||||||
if index >= player:get_inventory():get_size("main") and not def.throw_itself then
|
if index >= player:get_inventory():get_size("main") and not def.throw_itself then
|
||||||
@ -330,9 +366,15 @@ function throwing.register_bow(name, def)
|
|||||||
return throwing.is_arrow(itemstack) or def.throw_itself
|
return throwing.is_arrow(itemstack) or def.throw_itself
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if not def.inventory_image then
|
if not def.inventory_image then
|
||||||
def.inventory_image = def.texture
|
def.inventory_image = def.texture
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not def.strength then
|
||||||
|
def.strength = 20
|
||||||
|
end
|
||||||
|
|
||||||
def.on_use = function(itemstack, user, pointed_thing)
|
def.on_use = function(itemstack, user, pointed_thing)
|
||||||
-- Cooldown
|
-- Cooldown
|
||||||
local meta = itemstack:get_meta()
|
local meta = itemstack:get_meta()
|
||||||
@ -397,9 +439,11 @@ function throwing.register_bow(name, def)
|
|||||||
end)
|
end)
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
if enable_toolranks then
|
if enable_toolranks then
|
||||||
def.original_description = def.original_description or def.description
|
def.original_description = def.original_description or def.description
|
||||||
def.description = toolranks.create_description(def.description, 0, 1)
|
def.description = toolranks.create_description(def.description, 0, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_tool(name, def)
|
minetest.register_tool(name, def)
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user