├── README.md ├── BloodSplatter.gd ├── BloodSplatter.tscn ├── LICENSE ├── NewFPS-MeleeTut.gd └── NewFPS-MeleeTut.tscn /README.md: -------------------------------------------------------------------------------- 1 | # godot-melee-weapons 2 | How to make melee weapons in Godot game engine 3 | -------------------------------------------------------------------------------- /BloodSplatter.gd: -------------------------------------------------------------------------------- 1 | extends Spatial 2 | 3 | onready var particles = $Particles 4 | 5 | func _ready(): 6 | particles.emitting = true 7 | 8 | func _process(delta): 9 | if not particles.emitting: 10 | queue_free() 11 | -------------------------------------------------------------------------------- /BloodSplatter.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://scripts/BloodSplatter.gd" type="Script" id=1] 4 | 5 | [sub_resource type="ParticlesMaterial" id=1] 6 | emission_shape = 1 7 | emission_sphere_radius = 0.5 8 | direction = Vector3( 0, 1, 0 ) 9 | spread = 180.0 10 | flatness = 0.66 11 | gravity = Vector3( 0, -20, 0 ) 12 | initial_velocity = 3.0 13 | scale = 0.2 14 | 15 | [sub_resource type="SpatialMaterial" id=2] 16 | flags_unshaded = true 17 | params_billboard_mode = 3 18 | particles_anim_h_frames = 1 19 | particles_anim_v_frames = 1 20 | particles_anim_loop = false 21 | albedo_color = Color( 1, 0, 0, 1 ) 22 | 23 | [sub_resource type="QuadMesh" id=3] 24 | material = SubResource( 2 ) 25 | 26 | [node name="BloodSplatter" type="Spatial"] 27 | script = ExtResource( 1 ) 28 | 29 | [node name="Particles" type="Particles" parent="."] 30 | emitting = false 31 | amount = 40 32 | lifetime = 0.5 33 | one_shot = true 34 | process_material = SubResource( 1 ) 35 | draw_pass_1 = SubResource( 3 ) 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Garbaj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NewFPS-MeleeTut.gd: -------------------------------------------------------------------------------- 1 | extends KinematicBody 2 | 3 | var melee_damage = 50 4 | 5 | var speed = 10 6 | var h_acceleration = 6 7 | var air_acceleration = 1 8 | var normal_acceleration = 6 9 | var gravity = 20 10 | var jump = 10 11 | var full_contact = false 12 | 13 | var mouse_sensitivity = 0.03 14 | 15 | var direction = Vector3() 16 | var h_velocity = Vector3() 17 | var movement = Vector3() 18 | var gravity_vec = Vector3() 19 | var extra = Vector3() 20 | onready var head = $Head 21 | onready var ground_check = $GroundCheck 22 | 23 | onready var melee_anim = $AnimationPlayer 24 | onready var hitbox = $Head/Camera/Hitbox 25 | onready var blood_splatter = preload("res://assets/BloodSplatter.tscn") 26 | 27 | func _ready(): 28 | pass 29 | 30 | func _input(event): 31 | if event is InputEventMouseMotion: 32 | rotate_y(deg2rad(-event.relative.x * mouse_sensitivity)) 33 | head.rotate_x(deg2rad(-event.relative.y * mouse_sensitivity)) 34 | head.rotation.x = clamp(head.rotation.x, deg2rad(-89), deg2rad(89)) 35 | 36 | func melee(): 37 | if Input.is_action_just_pressed("fire"): 38 | if not melee_anim.is_playing(): 39 | melee_anim.play("Attack") 40 | melee_anim.queue("Return") 41 | if melee_anim.current_animation == "Attack": 42 | for body in hitbox.get_overlapping_bodies(): 43 | if body.is_in_group("Enemy"): 44 | var b = blood_splatter.instance() 45 | b.global_transform.origin = body.global_transform.origin 46 | get_tree().get_root().add_child(b) 47 | body.health -= melee_damage 48 | 49 | func _physics_process(delta): 50 | 51 | melee() 52 | 53 | direction = Vector3() 54 | 55 | full_contact = ground_check.is_colliding() 56 | 57 | if not is_on_floor(): 58 | gravity_vec += Vector3.DOWN * gravity * delta 59 | h_acceleration = air_acceleration 60 | elif is_on_floor() and full_contact: 61 | gravity_vec = -get_floor_normal() * gravity 62 | h_acceleration = normal_acceleration 63 | else: 64 | gravity_vec = -get_floor_normal() 65 | h_acceleration = normal_acceleration 66 | 67 | if Input.is_action_just_pressed("jump") and (is_on_floor() or ground_check.is_colliding()): 68 | gravity_vec = Vector3.UP * jump 69 | 70 | if Input.is_action_pressed("move_forward"): 71 | direction -= transform.basis.z 72 | elif Input.is_action_pressed("move_backward"): 73 | direction += transform.basis.z 74 | if Input.is_action_pressed("move_left"): 75 | direction -= transform.basis.x 76 | elif Input.is_action_pressed("move_right"): 77 | direction += transform.basis.x 78 | 79 | direction = direction.normalized() 80 | h_velocity = h_velocity.linear_interpolate(direction * speed, h_acceleration * delta) 81 | movement.z = h_velocity.z + gravity_vec.z + extra.z 82 | movement.x = h_velocity.x + gravity_vec.x 83 | movement.y = gravity_vec.y 84 | 85 | move_and_slide(movement, Vector3.UP) 86 | 87 | 88 | -------------------------------------------------------------------------------- /NewFPS-MeleeTut.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=13 format=2] 2 | 3 | [ext_resource path="res://scripts/NewFPS-MeleeTut.gd" type="Script" id=1] 4 | [ext_resource path="res://assets/generic.material" type="Material" id=4] 5 | 6 | [sub_resource type="CapsuleMesh" id=1] 7 | material = ExtResource( 4 ) 8 | mid_height = 3.0 9 | 10 | [sub_resource type="CapsuleShape" id=2] 11 | height = 3.0 12 | 13 | [sub_resource type="CylinderShape" id=3] 14 | 15 | [sub_resource type="BoxShape" id=4] 16 | extents = Vector3( 1, 1, 2 ) 17 | 18 | [sub_resource type="SpatialMaterial" id=5] 19 | albedo_color = Color( 0.968627, 0.670588, 0.160784, 1 ) 20 | 21 | [sub_resource type="CubeMesh" id=6] 22 | material = SubResource( 5 ) 23 | size = Vector3( 0.1, 2, 0.1 ) 24 | 25 | [sub_resource type="SpatialMaterial" id=7] 26 | albedo_color = Color( 0.117647, 0.117647, 0.117647, 1 ) 27 | 28 | [sub_resource type="CubeMesh" id=8] 29 | material = SubResource( 7 ) 30 | size = Vector3( 0.4, 0.4, 0.8 ) 31 | 32 | [sub_resource type="Animation" id=9] 33 | resource_name = "Attack" 34 | length = 0.02 35 | step = 0.02 36 | tracks/0/type = "value" 37 | tracks/0/path = NodePath("Head/Camera/MeleeWeapon:rotation_degrees") 38 | tracks/0/interp = 2 39 | tracks/0/loop_wrap = true 40 | tracks/0/imported = false 41 | tracks/0/enabled = true 42 | tracks/0/keys = { 43 | "times": PoolRealArray( 0, 0.02 ), 44 | "transitions": PoolRealArray( 1, 1 ), 45 | "update": 0, 46 | "values": [ Vector3( 0, 0, 0 ), Vector3( -70, 0, 0 ) ] 47 | } 48 | 49 | [sub_resource type="Animation" id=10] 50 | resource_name = "Return" 51 | length = 0.1 52 | tracks/0/type = "value" 53 | tracks/0/path = NodePath("Head/Camera/MeleeWeapon:rotation_degrees") 54 | tracks/0/interp = 2 55 | tracks/0/loop_wrap = true 56 | tracks/0/imported = false 57 | tracks/0/enabled = true 58 | tracks/0/keys = { 59 | "times": PoolRealArray( 0, 0.1 ), 60 | "transitions": PoolRealArray( 1, 1 ), 61 | "update": 0, 62 | "values": [ Vector3( -70, 0, 0 ), Vector3( 0, 0, 0 ) ] 63 | } 64 | 65 | [node name="NewFPS-MeleeTut" type="KinematicBody"] 66 | script = ExtResource( 1 ) 67 | 68 | [node name="MeshInstance" type="MeshInstance" parent="."] 69 | transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, 0, 0 ) 70 | visible = false 71 | cast_shadow = 0 72 | mesh = SubResource( 1 ) 73 | material/0 = null 74 | 75 | [node name="CollisionShape" type="CollisionShape" parent="."] 76 | transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, 0, 0 ) 77 | shape = SubResource( 2 ) 78 | 79 | [node name="Foot" type="CollisionShape" parent="."] 80 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.5, 0 ) 81 | shape = SubResource( 3 ) 82 | 83 | [node name="Head" type="Spatial" parent="."] 84 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.25, 0 ) 85 | 86 | [node name="Camera" type="Camera" parent="Head"] 87 | 88 | [node name="Hitbox" type="Area" parent="Head/Camera"] 89 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -3 ) 90 | 91 | [node name="CollisionShape" type="CollisionShape" parent="Head/Camera/Hitbox"] 92 | shape = SubResource( 4 ) 93 | 94 | [node name="MeleeWeapon" type="Spatial" parent="Head/Camera"] 95 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.812, -1.572, -1.538 ) 96 | 97 | [node name="MeshInstance" type="MeshInstance" parent="Head/Camera/MeleeWeapon"] 98 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.75, 0 ) 99 | mesh = SubResource( 6 ) 100 | material/0 = null 101 | 102 | [node name="MeshInstance" type="MeshInstance" parent="Head/Camera/MeleeWeapon/MeshInstance"] 103 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.75, 0 ) 104 | mesh = SubResource( 8 ) 105 | material/0 = null 106 | 107 | [node name="GroundCheck" type="RayCast" parent="."] 108 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2, 0 ) 109 | enabled = true 110 | cast_to = Vector3( 0, -1.5, 0 ) 111 | 112 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 113 | anims/Attack = SubResource( 9 ) 114 | anims/Return = SubResource( 10 ) 115 | --------------------------------------------------------------------------------