From 3e3067733805c7a3910d7a67d260dfdfff771c9c Mon Sep 17 00:00:00 2001 From: Canopteks <thomas.duhamel@protonmail.com> Date: Sun, 23 Feb 2020 23:42:10 +0100 Subject: [PATCH] moving hitboxes and feedbacks on serv and clients --- client/autoloads/gamestate.gd | 14 ++-- client/entities/characters/player.gd | 7 +- client/entities/characters/player.tscn | 1 + client/levels/lobby/lobby.gd | 4 +- client/levels/test/game.gd | 13 +++- client/project.godot | 10 +++ server/autoloads/gamestate.gd | 2 +- server/entities/characters/player.gd | 99 ++++++++++++++++++++++++-- server/entities/characters/player.tscn | 45 +++++++++++- server/levels/test/bloc/bloc.tscn | 1 + server/levels/test/game.gd | 4 +- server/levels/test/game.tscn | 2 - server/project.godot | 5 ++ 13 files changed, 180 insertions(+), 27 deletions(-) diff --git a/client/autoloads/gamestate.gd b/client/autoloads/gamestate.gd index 2d65ccd..86ce275 100644 --- a/client/autoloads/gamestate.gd +++ b/client/autoloads/gamestate.gd @@ -11,11 +11,11 @@ signal server_disconnected func joinServer(ip, port): # Create the network client - var peer_join = NetworkedMultiplayerENet.new() + var peer_join:NetworkedMultiplayerENet = NetworkedMultiplayerENet.new() peer_join.create_client(ip, int(port)) get_tree().set_network_peer(peer_join) - print("Trying to join the server ", ip, ":", port) + print("Trying to join the server ", ip, ":", port, " with id: ", get_tree().get_network_unique_id()) puppet func registerPlayer(id): @@ -37,8 +37,8 @@ puppet func startGame(): get_node("/root/lobby").hide() - var game = preload("res://levels/test/game.tscn").instance() - var player_scene = preload("res://entities/characters/player.tscn") + var game:Node = preload("res://levels/test/game.tscn").instance() + var player_scene:PackedScene = preload("res://entities/characters/player.tscn") get_tree().get_root().add_child(game) # TODO: check (and perhaps) the scene changing functionality @@ -47,16 +47,16 @@ puppet func startGame(): #Next evey player will spa every other player including the server's own client! Try to move this to server only var i = 1 for peer_id in players: - var player = player_scene.instance() + var player:Node = player_scene.instance() player.set_name(str(peer_id)) get_node(GAMEPATH).add_child(player) - var spawnPosition = get_node("/root/game/spawnCollection/spawn"+str(i)).get_translation() + var spawnPosition:Vector3 = get_node("/root/game/spawnCollection/spawn"+str(i)).get_translation() player.translate(spawnPosition) i+=1 - var playerArrow = preload("res://entities/characters/playerArrow.tscn").instance() + var playerArrow:Node = preload("res://entities/characters/playerArrow.tscn").instance() get_node(GAMEPATH+str(get_tree().get_network_unique_id())).add_child(playerArrow) \ No newline at end of file diff --git a/client/entities/characters/player.gd b/client/entities/characters/player.gd index b1de2aa..71c73b5 100644 --- a/client/entities/characters/player.gd +++ b/client/entities/characters/player.gd @@ -1,5 +1,8 @@ extends KinematicBody # Update the player's position based on the position computed by the remote scene on the server -puppet func getRemoteMovement(position): - self.set_translation(position) \ No newline at end of file +puppet func getRemoteMovement(position:Vector3): + self.set_translation(position) + +puppet func hurt(damages:int): + print("You suffered a hit and lost "+str(damages)+" HPs !") \ No newline at end of file diff --git a/client/entities/characters/player.tscn b/client/entities/characters/player.tscn index 27fb14f..1d62a17 100644 --- a/client/entities/characters/player.tscn +++ b/client/entities/characters/player.tscn @@ -6,6 +6,7 @@ script = ExtResource( 1 ) [node name="Model" type="Spatial" parent="."] +editor/display_folded = true [node name="CSGBox" type="CSGBox" parent="Model"] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.513621, 0 ) diff --git a/client/levels/lobby/lobby.gd b/client/levels/lobby/lobby.gd index 0603a64..3c453e0 100644 --- a/client/levels/lobby/lobby.gd +++ b/client/levels/lobby/lobby.gd @@ -10,13 +10,13 @@ func _ready(): func _on_joinButton_pressed(): # Get and check the Ip - var ip = get_node("menu/ipLineEdit").text + var ip:String = get_node("menu/ipLineEdit").text if not ip.is_valid_ip_address(): get_node("menu/errorLabel").text = "Invalid IPv4 address!" return # Get and check the port - var port = get_node("menu/portLineEdit").text + var port:String = get_node("menu/portLineEdit").text if port == "": get_node("menu/errorLabel").text = "Invalid port!" return diff --git a/client/levels/test/game.gd b/client/levels/test/game.gd index 4209e3a..fbe0ce8 100644 --- a/client/levels/test/game.gd +++ b/client/levels/test/game.gd @@ -1,14 +1,19 @@ extends Node +# Movements var movementInput:int = 0 var jumpInput:bool = false var sprintInput:bool = false +# Attacks +enum {NONE=0, PRIMARY=1, SECONDARY=2} + func _physics_process(delta): getPlayerInput() func getPlayerInput(): movementInput = 0 + var attackStateInput:int = NONE if Input.is_action_pressed("movementLeft"): movementInput -= 1 @@ -24,6 +29,12 @@ func getPlayerInput(): sprintInput = true else: sprintInput = false + + if Input.is_action_pressed("primaryAttack"): + attackStateInput = PRIMARY + + elif Input.is_action_pressed("secondaryAttack"): + attackStateInput = SECONDARY # Sent without safety resend - rpc_unreliable_id(1, "sendPlayerInputs", movementInput, sprintInput, jumpInput) \ No newline at end of file + rpc_unreliable_id(1, "sendPlayerInputs", movementInput, sprintInput, jumpInput, attackStateInput) \ No newline at end of file diff --git a/client/project.godot b/client/project.godot index 8048c79..936fcb6 100644 --- a/client/project.godot +++ b/client/project.godot @@ -48,6 +48,16 @@ movementSprint={ "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777237,"unicode":0,"echo":false,"script":null) ] } +primaryAttack={ +"deadzone": 0.5, +"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null) + ] +} +secondaryAttack={ +"deadzone": 0.5, +"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":2,"pressed":false,"doubleclick":false,"script":null) + ] +} [rendering] diff --git a/server/autoloads/gamestate.gd b/server/autoloads/gamestate.gd index d28868e..af0a0e0 100644 --- a/server/autoloads/gamestate.gd +++ b/server/autoloads/gamestate.gd @@ -3,7 +3,7 @@ extends Node const GAMEPATH = "/root/game/" const PORT = 10001 -const MAX_CLIENTS = 1 +const MAX_CLIENTS = 2 var players = {} diff --git a/server/entities/characters/player.gd b/server/entities/characters/player.gd index 81c4de8..88004aa 100644 --- a/server/entities/characters/player.gd +++ b/server/entities/characters/player.gd @@ -1,5 +1,12 @@ extends KinematicBody +onready var ownId = self.name + +######## MOVEMENT AND POSITION VARS ######## + +# The side faced by the player +var orientation:int = 1 + # Speed values const MAX_SPEED:float = 8.0 const MAX_SPRINT_SPEED:float = 12.0 @@ -23,19 +30,39 @@ var vel:Vector3 = Vector3() # move_and_slide need that const FLOOR_NORMAL:Vector3 = Vector3(0,1,0) +######### ATTACKS VARS ######## + +# l2r +var isAttacking:bool = false +# attack type +enum {NONE=0, PRIMARY=1, SECONDARY=2} +# attacks related nodes +onready var attackTimer:Tween = $attackTween +onready var primaryHitArea:Area = $primaryHitArea +onready var secondaryHitArea:Area = $secondaryHitArea + +######## FUNCTIONS ######## # called by the engine func _physics_process(delta): processMovement(delta) - broadcastMovement(delta) + broadcastMovement() # Called from the game script to update the vars -func getPlayerInputs(movementInput, sprintInput, jumpInput): +func getPlayerInputs(movementInput, sprintInput, jumpInput, attackTypeInput): motion = movementInput + orientation = movementInput if movementInput!=0 else orientation isSprinting = sprintInput isJumping = jumpInput + if !isAttacking && attackTypeInput: + processAttack(attackTypeInput) func processMovement(delta): + if orientation == 1: + set_rotation_degrees(Vector3(0,0,0)) + else: + set_rotation_degrees(Vector3(0,180,0)) + if self.is_on_floor(): if isJumping: vel.y = JUMP_SPEED @@ -44,7 +71,7 @@ func processMovement(delta): vel.y += delta * GRAVITY # Speed of the player - var target = Vector3(motion, 0, 0) + var target:Vector3 = Vector3(motion, 0, 0) if isSprinting: target *= MAX_SPRINT_SPEED @@ -52,7 +79,7 @@ func processMovement(delta): target *= MAX_SPEED # Acceleration of the player if he is moving horizontally - var accel + var accel:float var hvel:Vector3 = Vector3(vel.x,0,0) if target.dot(hvel)>0: if isSprinting: @@ -68,6 +95,64 @@ func processMovement(delta): # Update the velocity after the collisions (physical engine ftw) vel = self.move_and_slide(vel, FLOOR_NORMAL) -func broadcastMovement(delta): - # Send the position of the player - rpc("getRemoteMovement", self.get_translation()) \ No newline at end of file +# Send the position of the player +func broadcastMovement(): + rpc("getRemoteMovement", self.get_translation()) + +# Check and trigger the type of attack requested +func processAttack(attackType): + isAttacking = true + match attackType: + PRIMARY: + primaryAttack() + SECONDARY: + secondaryAttack() + +func primaryAttack(): + primaryHitArea.set_monitoring(true) + primaryHitArea.set_visible(true) + var duration:float = 0.6 + var distance:float = 1.2 + + attackTimer.interpolate_property(primaryHitArea, "translation:x", 0, distance, duration, Tween.TRANS_BACK, Tween.EASE_IN) + attackTimer.start() + yield(attackTimer, "tween_completed") + + primaryHitArea.set_monitoring(false) + primaryHitArea.set_visible(false) + isAttacking = false + +func secondaryAttack(): + secondaryHitArea.set_monitoring(true) + secondaryHitArea.set_visible(true) + var duration:float = 0.3 + var distance:float = 1.2 + + attackTimer.interpolate_property(secondaryHitArea, "translation:x", 0, distance, duration, Tween.TRANS_BACK, Tween.EASE_IN) + attackTimer.start() + yield(attackTimer, "tween_completed") + + secondaryHitArea.set_monitoring(false) + secondaryHitArea.set_visible(false) + isAttacking = false + +func hurt(damages): + rpc_id(int(ownId), "hurt", str(damages)); + +######## SIGNALS ######## + +# Primary hit has landed on something +func _on_primaryHitArea_body_entered(body): + if body.name==ownId: + return + + print("body named "+body.name+" hit: primary") + body.hurt(30) + +# Secondary hit has landed on something +func _on_secondaryHitArea_body_entered(body): + if body.name==ownId: + return + + print("body named "+body.name+" hit: secondary") + diff --git a/server/entities/characters/player.tscn b/server/entities/characters/player.tscn index f8eba0f..e734fd8 100644 --- a/server/entities/characters/player.tscn +++ b/server/entities/characters/player.tscn @@ -1,13 +1,16 @@ -[gd_scene load_steps=3 format=2] +[gd_scene load_steps=4 format=2] [ext_resource path="res://entities/characters/player.gd" type="Script" id=1] - - [sub_resource type="BoxShape" id=1] extents = Vector3( 0.175, 0.275, 0.7 ) +[sub_resource type="BoxShape" id=2] +extents = Vector3( 0.544245, 0.192381, 0.312851 ) + [node name="Player" type="KinematicBody"] +collision_layer = 2 +collision_mask = 3 script = ExtResource( 1 ) [node name="Body_CollisionShape" type="CollisionShape" parent="."] @@ -26,3 +29,39 @@ depth = 0.684 transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.17856, 0 ) radius = 0.2 radial_segments = 24 + +[node name="primaryHitArea" type="Area" parent="."] +visible = false +monitoring = false +collision_layer = 0 +collision_mask = 2 + +[node name="primaryHitCol" type="CollisionShape" parent="primaryHitArea"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.420072, 0.815, 0 ) +shape = SubResource( 2 ) + +[node name="primaryHitCSG" type="CSGBox" parent="primaryHitArea"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.419673, 0.815, 0 ) +width = 1.09437 +height = 0.400067 +depth = 0.618424 + +[node name="secondaryHitArea" type="Area" parent="."] +visible = false +monitoring = false +collision_layer = 0 +collision_mask = 2 + +[node name="secondaryHitCol" type="CollisionShape" parent="secondaryHitArea"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.42, 0.2, 0 ) +shape = SubResource( 2 ) + +[node name="secondaryHitCSG" type="CSGBox" parent="secondaryHitArea"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.42, 0.2, 0 ) +width = 1.09437 +height = 0.400067 +depth = 0.618424 + +[node name="attackTween" type="Tween" parent="."] +[connection signal="body_entered" from="primaryHitArea" to="." method="_on_primaryHitArea_body_entered"] +[connection signal="body_entered" from="secondaryHitArea" to="." method="_on_secondaryHitArea_body_entered"] diff --git a/server/levels/test/bloc/bloc.tscn b/server/levels/test/bloc/bloc.tscn index 6d021e8..af80b4d 100644 --- a/server/levels/test/bloc/bloc.tscn +++ b/server/levels/test/bloc/bloc.tscn @@ -12,6 +12,7 @@ mesh = SubResource( 1 ) material/0 = null [node name="StaticBody" type="StaticBody" parent="MeshInstance"] +collision_mask = 2 [node name="CollisionShape" type="CollisionShape" parent="MeshInstance/StaticBody"] shape = SubResource( 2 ) diff --git a/server/levels/test/game.gd b/server/levels/test/game.gd index 6eb3b6b..0703762 100644 --- a/server/levels/test/game.gd +++ b/server/levels/test/game.gd @@ -1,7 +1,7 @@ extends Node -master func sendPlayerInputs(movementInput, jumpInput, sprintInput): +master func sendPlayerInputs(movementInput, jumpInput, sprintInput, attackStateInput): # Get the input from a client and send it to the matchig remote player var senderId = get_tree().get_rpc_sender_id() - gamestate.get_node("/root/game/"+str(senderId)).getPlayerInputs(movementInput, jumpInput, sprintInput) \ No newline at end of file + gamestate.get_node("/root/game/"+str(senderId)).getPlayerInputs(movementInput, jumpInput, sprintInput, attackStateInput) \ No newline at end of file diff --git a/server/levels/test/game.tscn b/server/levels/test/game.tscn index 6eff247..59b44e0 100644 --- a/server/levels/test/game.tscn +++ b/server/levels/test/game.tscn @@ -3,8 +3,6 @@ [ext_resource path="res://levels/test/game.gd" type="Script" id=1] [ext_resource path="res://levels/test/bloc/bloc.tscn" type="PackedScene" id=2] - - [node name="game" type="Spatial"] script = ExtResource( 1 ) diff --git a/server/project.godot b/server/project.godot index 73c0570..29dcf55 100644 --- a/server/project.godot +++ b/server/project.godot @@ -23,6 +23,11 @@ config/icon="res://icon.png" gamestate="*res://autoloads/gamestate.gd" +[layer_names] + +3d_physics/layer_1="environment" +3d_physics/layer_2="players" + [rendering] environment/default_environment="res://default_env.tres" -- GitLab