From 898803a6221904fa218b959d7247ecec9c4a64b4 Mon Sep 17 00:00:00 2001 From: JayisonDevadas Date: Mon, 7 Jul 2025 21:03:25 -0400 Subject: [PATCH] player damage, player death, badguy dictionary, badguy damage, badguy death, user intererface, paler damage animation, player death animation --- .../Player/death/Player Death 64x64.png | Bin 0 -> 1584 bytes .../death/Player Death 64x64.png.import | 34 +++++ .../Player/hurt/Player Hurt 48x48.png | Bin 0 -> 1448 bytes .../Player/hurt/Player Hurt 48x48.png.import | 34 +++++ scenes/bullet.tscn | 2 + scenes/crate.tscn | 4 +- scenes/game.tscn | 16 ++- scenes/level2.tscn | 7 +- scenes/level3.tscn | 7 +- scenes/player.tscn | 118 +++++++++++++++++- scenes/slime.tscn | 38 +++++- scenes/ui.tscn | 50 ++++++++ scripts/bullet.gd | 7 ++ scripts/character_body_2d.gd | 23 +++- scripts/coin.gd | 1 - scripts/crate.gd | 1 + scripts/crate.gd.uid | 1 + scripts/gamecontroller.gd | 62 ++++++--- scripts/scene_manager.gd | 12 +- scripts/slime.gd | 18 ++- scripts/ui.gd | 17 +++ scripts/ui.gd.uid | 1 + 22 files changed, 412 insertions(+), 41 deletions(-) create mode 100644 assets/Graphics/Player/death/Player Death 64x64.png create mode 100644 assets/Graphics/Player/death/Player Death 64x64.png.import create mode 100644 assets/Graphics/Player/hurt/Player Hurt 48x48.png create mode 100644 assets/Graphics/Player/hurt/Player Hurt 48x48.png.import create mode 100644 scenes/ui.tscn create mode 100644 scripts/crate.gd create mode 100644 scripts/crate.gd.uid create mode 100644 scripts/ui.gd create mode 100644 scripts/ui.gd.uid diff --git a/assets/Graphics/Player/death/Player Death 64x64.png b/assets/Graphics/Player/death/Player Death 64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..2e6a1ae0514b237d754893f563c87ba5f95dc109 GIT binary patch literal 1584 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 void: pass @@ -10,3 +11,9 @@ func setSpeed(value): speed = value func _physics_process(delta: float) -> void: position += transform.x * speed * delta + + +func _on_area_entered(area): + print("bullet is hitting area") + if area is Slime: + bulletDamageSignal.emit(area,self) diff --git a/scripts/character_body_2d.gd b/scripts/character_body_2d.gd index cb2fb96..f33634e 100644 --- a/scripts/character_body_2d.gd +++ b/scripts/character_body_2d.gd @@ -14,12 +14,15 @@ const JUMP_VELOCITY = -400.0 enum FaceDirection{LEFT, RIGHT} var facing:FaceDirection = FaceDirection.RIGHT -enum State{IDLE, RUN, JUMP, FALLING} +enum State{IDLE, RUN, JUMP, FALLING, HURT, DEATH} var current_state:State = State.IDLE var pushTarget var pushEnable = false var direction var upJump = false + +signal deathAnimationCompleteSignal + func _physics_process(delta: float) -> void: #game loop handle_input() @@ -71,15 +74,15 @@ func handle_collisions(): c.get_collider().apply_central_impulse(-c.get_normal() * 100 ) if right_cast.is_colliding() && facing == FaceDirection.RIGHT: - print("right cast collision") + #print("right cast collision") # get the thing i am colliding with var collider = right_cast.get_collider() if collider is Node && collider is RigidBody2D: - print("i can shove this right") + #print("i can shove this right") pushTarget = collider pushEnable = true if left_cast.is_colliding() && facing == FaceDirection.LEFT: - print("left cast collision") + #print("left cast collision") var collider = left_cast.get_collider() if collider is Node && collider is RigidBody2D: print("i can shove this left") @@ -113,6 +116,10 @@ func update_animation(): player_graphic.play("Jump") State.FALLING: player_graphic.play("Falling") + State.HURT: + player_graphic.play("hurt") + State.DEATH: + player_graphic.play("death") func update_states(): match current_state: #idle when movment in x @@ -135,10 +142,16 @@ func _on_animation_finished() -> void: match current_state: State.JUMP: upJump = false - + State.HURT: + current_state = State.IDLE + State.DEATH: + deathAnimationCompleteSignal.emit() func playerTakesDamage(health): print("player sees remainting health"+str(health)) + current_state = State.HURT func playerDies(): print("player sees he ded.") + current_state = State.DEATH + diff --git a/scripts/coin.gd b/scripts/coin.gd index 12c3098..d028a35 100644 --- a/scripts/coin.gd +++ b/scripts/coin.gd @@ -13,5 +13,4 @@ func _process(delta: float) -> void: func _on_body_entered(body: Node2D) -> void: - print ("Coin sees collision") coinCollectedSignal.emit(body, self) diff --git a/scripts/crate.gd b/scripts/crate.gd new file mode 100644 index 0000000..7f42195 --- /dev/null +++ b/scripts/crate.gd @@ -0,0 +1 @@ +class_name Crate extends RigidBody2D diff --git a/scripts/crate.gd.uid b/scripts/crate.gd.uid new file mode 100644 index 0000000..b614247 --- /dev/null +++ b/scripts/crate.gd.uid @@ -0,0 +1 @@ +uid://cov5urwm68y3l diff --git a/scripts/gamecontroller.gd b/scripts/gamecontroller.gd index abb8c45..07b9acc 100644 --- a/scripts/gamecontroller.gd +++ b/scripts/gamecontroller.gd @@ -4,22 +4,27 @@ extends Node2D var totalCoinsAvailable = 0 var timer = Timer.new() -var timeAvailable = 30 +var timeAvailable var level="res://scenes/game.tscn" var levelTwo = "res://scenes/level2.tscn" var levels = ["res://scenes/game.tscn","res://scenes/level2.tscn","res://scenes/level3.tscn"] var timers = [30,20,15] var currentLevel = 0 +var startingCoins = 0 signal destroySignal(body) signal levelChangeSignal(level) signal playerTakeDamageSignal(health) signal playerDiesSignal - +signal bulletDamageEnemySignal(body) +signal countDownSignal(timeRemaining) +signal coinCountSignal(coinsRemaining, startingCoins) var player:Characterstats var enemy:Characterstats var playerHealth:int + +var enemiesDict = {} # Called when the node enters the scene tree for the first time. func _ready() -> void: player = load("res://scripts/rscs/playerstats.tres") @@ -36,13 +41,16 @@ func _ready() -> void: func secondCounter() -> void: timeAvailable -=1 + countDownSignal.emit(timeAvailable) if timeAvailable <= 0: print ("YOU LOSE") #get_tree().call_deferred("change_scene_to_file", levels[currentLevel]) levelChangeSignal.emit(levels[currentLevel]) #reload the current scene func reset() -> void: + startingCoins=0 timeAvailable = timers[currentLevel] + playerHealth = player.starting_health # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: @@ -61,25 +69,49 @@ func _on_areatrigger(effect, body) -> void: print("player health is now"+str(playerHealth)) func totalCoinCount(totalCoins): - + if startingCoins == 0: + startingCoins = totalCoins totalCoinsAvailable = totalCoins func coinCollected(body, coin): - - destroySignal.emit(coin) - totalCoinsAvailable -= 1 - if totalCoinsAvailable <=0: - print("YOU WIN") - currentLevel +=1 - if currentLevel >= levels.size(): - currentLevel =0 - - #get_tree().call_deferred("change_scene_to_file", levels[currentLevel]) - levelChangeSignal.emit(levels[currentLevel]) + if not body is Crate: + + destroySignal.emit(coin) + totalCoinsAvailable -= 1 + coinCountSignal.emit(totalCoinsAvailable, startingCoins) + if totalCoinsAvailable <=0: + print("YOU WIN") + currentLevel +=1 + if currentLevel >= levels.size(): + currentLevel =0 + + #get_tree().call_deferred("change_scene_to_file", levels[currentLevel]) + levelChangeSignal.emit(levels[currentLevel]) func playerAttacked(body, slime): print("GC knows player attacked") - playerHealth -= enemy.meleeDamage + playerHealth -= enemiesDict[slime].damage if playerHealth<=0: playerDiesSignal.emit() else: playerTakeDamageSignal.emit(playerHealth) +func playerDead(): + levelChangeSignal.emit(levels[currentLevel] ) + +func bulletDamage(area, bullet): + print("Gc Knows bullet hit something"+str(player.rangeDamage)) + print("GC Knows BG health is :"+str( enemiesDict[area].health)) + enemiesDict[area].health -= player.rangeDamage + if enemiesDict[area].health<=0: + destroySignal.emit(area) + enemiesDict.erase(area) + else: + bulletDamageEnemySignal.emit(area) +func addEnemyToLevel(slime): + var randHealth:int = randi() % 20 + var randDamage:int = randi() % 10 + var enemyStat = { + "health":enemy.starting_health+ randHealth, + "damage":enemy.meleeDamage + randDamage + + } + enemiesDict[slime]= enemyStat diff --git a/scripts/scene_manager.gd b/scripts/scene_manager.gd index 554fb5b..8602063 100644 --- a/scripts/scene_manager.gd +++ b/scripts/scene_manager.gd @@ -7,7 +7,8 @@ var totalAllowedBullets = 7 @onready var coins: Node2D = $"../Coins" @onready var enemies: Node2D = $"../Enemies" @onready var player: Player = $"../Player" - +@onready var ui = $"../CanvasLayer/Ui" + func _ready() -> void: Gamecontroller.reset() @@ -18,11 +19,19 @@ func _ready() -> void: for obj in enemies.get_children(): if obj is Slime: obj.playerDamageSignal.connect(Gamecontroller.playerAttacked) + Gamecontroller.addEnemyToLevel(obj) + Gamecontroller.bulletDamageEnemySignal.connect(obj.takeDamage) + updateCoins() Gamecontroller.destroySignal.connect(destroyItem) Gamecontroller.levelChangeSignal.connect(changeScene) Gamecontroller.playerTakeDamageSignal.connect(player.playerTakesDamage) + if ui: + Gamecontroller.playerTakeDamageSignal.connect(ui.healthUpdate) + Gamecontroller.countDownSignal.connect(ui.timerUpdate) + Gamecontroller.coinCountSignal.connect(ui.coinsUpdate) Gamecontroller.playerDiesSignal.connect(player.playerDies) + player.deathAnimationCompleteSignal.connect(Gamecontroller.playerDead) #call this anytimes the coins change func updateCoins() ->void: var coinCount = 0 @@ -43,6 +52,7 @@ func bulletFactory(): var mybullet if bulletArray.size() < totalAllowedBullets: mybullet = bullet.instantiate() + mybullet.bulletDamageSignal.connect(Gamecontroller.bulletDamage ) owner.add_child(mybullet) else: mybullet = bulletArray.pop_back() diff --git a/scripts/slime.gd b/scripts/slime.gd index 1ad6e31..ba8ffc2 100644 --- a/scripts/slime.gd +++ b/scripts/slime.gd @@ -5,6 +5,7 @@ class_name Slime extends Area2D @onready var left_down_cast: RayCast2D = $"slimeGraphic/Left DownCast" @onready var right_down_cast: RayCast2D = $"slimeGraphic/Right DownCast" + var speed:int = 100 var direction = 1 @@ -17,6 +18,7 @@ func _ready() -> void: # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: + if not right_down_cast.is_colliding(): direction = -1 slime_graphic.flip_h = true @@ -24,15 +26,21 @@ func _process(delta: float) -> void: direction = 1 slime_graphic.flip_h = false if right_side_cast.is_colliding(): - direction = -1 - slime_graphic.flip_h = true + if not right_side_cast.get_collider() is Player && not right_side_cast.get_collider() is Slime: + direction = -1 + slime_graphic.flip_h = true if left_side_cast.is_colliding(): - direction = 1 - slime_graphic.flip_h = false - position.x += direction * speed * delta + if not left_side_cast.get_collider() is Player && not left_side_cast.get_collider() is Slime: + direction = 1 + slime_graphic.flip_h = false + position.x += direction * speed * delta func _on_body_entered(body: Node2D) -> void: if body is Player: print("player attacked") playerDamageSignal.emit(body, self) +func takeDamage(body): + if body == self: + slime_graphic.play("hurt") + diff --git a/scripts/ui.gd b/scripts/ui.gd new file mode 100644 index 0000000..c95b1ae --- /dev/null +++ b/scripts/ui.gd @@ -0,0 +1,17 @@ +extends Control +@onready var health = $VBoxContainer/HBoxContainer/MarginContainer/Health +@onready var timer = $VBoxContainer/HBoxContainer/MarginContainer2/Timer +@onready var coins = $VBoxContainer/HBoxContainer/MarginContainer3/Coins + + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass +func healthUpdate(healthRemaining): + health.text = "Health: "+str(healthRemaining) + +func timerUpdate(timeRemaining): + timer.text= str(timeRemaining) +func coinsUpdate(coinsRemaining, startingCoins): + coins.text="coins: "+str(coinsRemaining)+"/"+str(startingCoins) + diff --git a/scripts/ui.gd.uid b/scripts/ui.gd.uid new file mode 100644 index 0000000..6a9a1b0 --- /dev/null +++ b/scripts/ui.gd.uid @@ -0,0 +1 @@ +uid://du5ut0qfft7le