From 31d586b386e9f0a758b6bb73e7bf4d116e9fd36d Mon Sep 17 00:00:00 2001 From: OddlyTimbot Date: Mon, 24 Mar 2025 21:02:52 -0400 Subject: [PATCH] level changing, autoloads, coins, player damage, characterstats --- .../assets/graphics/enemies/slime_green.png | Bin 0 -> 908 bytes .../graphics/enemies/slime_green.png.import | 34 ++ .../assets/graphics/pickups/coin.png | Bin 0 -> 500 bytes .../assets/graphics/pickups/coin.png.import | 34 ++ .../player/hurt/Player Hurt 48x48.png | Bin 0 -> 1448 bytes .../player/hurt/Player Hurt 48x48.png.import | 34 ++ februarygodotgame/project.godot | 4 + februarygodotgame/scenes/coin.tscn | 114 ++++ februarygodotgame/scenes/game.tscn | 24 +- februarygodotgame/scenes/level2.tscn | 2 +- februarygodotgame/scenes/level3.tscn | 499 ++++++++++++++++++ februarygodotgame/scenes/player.tscn | 42 +- februarygodotgame/scenes/slime.tscn | 60 +++ februarygodotgame/scripts/coin.gd | 7 + februarygodotgame/scripts/gamecontroller.gd | 71 ++- februarygodotgame/scripts/player.gd | 145 ++--- .../scripts/res/characterStats.gd | 8 + .../scripts/res/playerStats.tres | 11 + februarygodotgame/scripts/res/slimeStats.tres | 11 + februarygodotgame/scripts/scene_manager.gd | 38 +- februarygodotgame/scripts/slime.gd | 7 + 21 files changed, 1061 insertions(+), 84 deletions(-) create mode 100644 februarygodotgame/assets/graphics/enemies/slime_green.png create mode 100644 februarygodotgame/assets/graphics/enemies/slime_green.png.import create mode 100644 februarygodotgame/assets/graphics/pickups/coin.png create mode 100644 februarygodotgame/assets/graphics/pickups/coin.png.import create mode 100644 februarygodotgame/assets/graphics/player/hurt/Player Hurt 48x48.png create mode 100644 februarygodotgame/assets/graphics/player/hurt/Player Hurt 48x48.png.import create mode 100644 februarygodotgame/scenes/coin.tscn create mode 100644 februarygodotgame/scenes/level3.tscn create mode 100644 februarygodotgame/scenes/slime.tscn create mode 100644 februarygodotgame/scripts/coin.gd create mode 100644 februarygodotgame/scripts/res/characterStats.gd create mode 100644 februarygodotgame/scripts/res/playerStats.tres create mode 100644 februarygodotgame/scripts/res/slimeStats.tres create mode 100644 februarygodotgame/scripts/slime.gd diff --git a/februarygodotgame/assets/graphics/enemies/slime_green.png b/februarygodotgame/assets/graphics/enemies/slime_green.png new file mode 100644 index 0000000000000000000000000000000000000000..a21cb6fa253a2142be9bdad248238299dce6e695 GIT binary patch literal 908 zcmeAS@N?(olHy`uVBq!ia0vp^2|(<@!3HEb(?2AGr~;43Vg?3oVGw3ym^DX&fq~i1 z)5S5QV$Rz+)_J!b1lrmiqe6M+oJ(NX&NN4Phv|b`z4{NYP5+>JWrs--17qeTsRD5g z!(g=zZP^CRNrf+-+NH@KR$Td0s&mngVw3+xu0?EXcCBM}?K8i`C}Wk?V1NhZ=gNnL znwH6IezGFZ!~9a6?RHUyhPV4>Uu{?_FnfW>zS{qPKK*<4uVTZ$ce_63>1Q2~5psEW zx_|#J@#X97|9=sRdr@7gG^K>%S{q!=tk;zc{umA757CW^gF~?Y* zzL@Q4_FeSScBuyG05^_0b=8H-_E|RV`0{(oCG+JLF?=tr`x)+BFt>laYl`#E_4#US z^)8yV;ydQc)Lt=IzWv`O|NWa{=kBflzObA3)w^Aa^ZVqko^^cn|Ic5O3*}M*OaJxH zkT2-?mBRcbPJn+~%B^6jY(87p9(Mo#>Q7(h~rm&XFcnS2%Pu(#j4I<=R1EbeZ((y;O5o?wIy5Q|G$2J-k$H; z`tsE}e}z7FZ&xe&&T>;Ie$t&EuHB#RoL~6BudegQ(e6(xj^8Zaa&Il$W#4ySE~~5m zTfmt7%O>)U?6I5hEH)mc^Zy7i2AYE5_cS8+Pd zEL*XBwVBru|99M6hFkZ|y>aAN9DmO}@fM%8>yNRi-8VbG`yY1_&*gmzOfw=rUyaF+ zc6a>UWOJqT@=>+Yz0nhwE57CCn(*tmRI)?YzOxPXujg|0Ui|Qj8JN8oJYD@<);T3K F0RY5^vzq__ literal 0 HcmV?d00001 diff --git a/februarygodotgame/assets/graphics/enemies/slime_green.png.import b/februarygodotgame/assets/graphics/enemies/slime_green.png.import new file mode 100644 index 0000000..c6ce784 --- /dev/null +++ b/februarygodotgame/assets/graphics/enemies/slime_green.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://gm75hmen7j50" +path="res://.godot/imported/slime_green.png-5261ffd1254c816fe62b35227a9aa11d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/graphics/enemies/slime_green.png" +dest_files=["res://.godot/imported/slime_green.png-5261ffd1254c816fe62b35227a9aa11d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/februarygodotgame/assets/graphics/pickups/coin.png b/februarygodotgame/assets/graphics/pickups/coin.png new file mode 100644 index 0000000000000000000000000000000000000000..01ae33d70b398db7f1f7bcafe883a0a469805201 GIT binary patch literal 500 zcmV^r!6hi!Wct>kSmw76A*+mkqIDVjdDL!Rb}5E?Td;C@2y9S zHih2xK(yTWh+gXdrTqK8Uwx^_$MoI4V|67Hn26^Qp-rJ*c_3P5d_*tx|6%^yEznE& zeE6^KHvJ|vI7934d=L#ytZIR)9hxaN1Jm8sZ6_j{Yx1#nTWt!D2<;1?{VNX?M*l~R zzukKP+i+D+FAlB;7qkOXfaGA?&h>EX&+$Oxqgs>{d4C#zhd05hUS`kO@{&+Bb`?-H zKXwYn7Ms9B!`F}PQh%-o65r;4=uy!A4;g>*6iCRL!wF!o{9{X0YM%Mf@U=DvM2}Kx zY#A;!e+4Y{Qh#m^NPMe5dkcj0f5`ZIy8@JYG2kpkh}LrU76{dHI?&Z}2LKX(>v1MX z4k6>OaQ_N1p97frj@jdSpELonJ&y=&3jN9h(K6#Bda3^x^WUBW>`ee7IfzLSUk<|l qVg27u071wNc?u+CjZ6R`YyJS*Ofbr5QwY-l0000Px)Vo5|nRCt{2n@>y}RUF4ZkJerOE#kjMStQgHNr?OjDhY`uTxqn~MsGFI8%cX2 z#+wHZ-nkf)9-7#Lo=hNMy_gUWrUz6Ku)&lxmefL8tXe6HK*8r>dAl>i%(BbQ?!JNF zC)s3n-t6r6_vZI~zxQT#K@bE%5ClOG1VIo4K@bE%5ClOG1VIo4;mDxEKB3kcfQ3g} z+PS|g5mx|8h5nVH@&3Aq|r=_kK&wGEuT zmfemKQw=rs)TufE&aa%SkiuY`+5tYA+TfG-rd`JjoV~_c_tUEBm%q4lf25-N3dI?R zUkp~>2EDsErvcVCHeLJM9_;Qr_Ro850JOfDbbVj7&EV|#;VTb$bTgKVnw}Fa`j(3H%HIITHZHRh;MEc($q) z;h^LizHn7g?I6s=!@9VRFw`3-wCCUn zV_s{X2{^C8L2>M%6RMH%mPy82CPUG1@~|IF#(UKA)_k@zm$&A1JmA>6jzQJhk=b@8 z{@!-g=0Uxk?TjQR)aSs|g?8;7MNf|{Dp&-rnq5{cU`CP?%1^fg)m*>By^L;W;#alb zA!lTB4TdkY2O85gm8(gZr5l*ZT~pTRL4wxs)cg|^>Sl% zyOL6hCP;fe-GkqKW;U%dZ!vUqUso|=WvOI`t^i6YwATA70YG|N(-6z_cU{Mz@_we; zCNPX7C-&*E-2?`&cCYTYzg+TLs9VwRP9vKt2ALTAs_^YmNH4qtWvFB&RRA-pC*wUT zeruiht@UhMdRu3!fpej&lybdnU@D;e2JNpFeuh12+*sXqy#P*+Etbv1hpqqyGpa|K zw$UK~?u>m8Kr-FuXkDtboV<8V;MH!JO{H}IM6?a#tYT1}N>;J~47D#d1F-pfZZ#j@ zZ3Hq8&1@O%^NpfyqeJX|TF~7H>u?&uZD4yb*P?B7XrF;AMJPXoaAJ&LlK;{Cd}PW) z)RKShrw{h^Z4{D!Bsrn{Dw#1cWa5}j1>dj;i%^~etgkJ&gqq}!0w#%~mi&H1F$S-R z+eU|6CN8%LWZ>4FSbiKUbdha!@ z?QwYZo8uN4{ZRfGN}2+h void: + print("Coin collision") + coinCollectedSignal.emit(body, self) diff --git a/februarygodotgame/scripts/gamecontroller.gd b/februarygodotgame/scripts/gamecontroller.gd index 8719c49..ccd132e 100644 --- a/februarygodotgame/scripts/gamecontroller.gd +++ b/februarygodotgame/scripts/gamecontroller.gd @@ -3,12 +3,43 @@ class_name GameController extends Node2D # Game Data var totalCrates = 4 var cratesDestroyed = 0 +var coinsCollected =0 +var totalCoinsAvailable = 0 + +var enemies = 0 + +signal destroySignal(body) +signal levelCompleteSignal(level) +signal playerHurtSignal(healthRemaining) +#level info +var timer:= Timer.new() +var levels = ["res://scenes/game.tscn","res://scenes/level2.tscn","res://scenes/level3.tscn"] +var timers = [20,15,25] +var currentLevel = 0 +var countdown=0 + +var player:Resource +var slime:Resource # Called when the node enters the scene tree for the first time. func _ready() -> void: - pass # Replace with function body. - - + player = load("res://scripts/res/playerStats.tres") + slime = load("res://scripts/res/slimeStats.tres") + + countdown = timers[currentLevel] + add_child(timer) + timer.wait_time = 1 + timer.one_shot = false + timer.connect("timeout", secondCounter) + timer.start() +func reset(): + countdown = timers[currentLevel] + +func secondCounter(): + countdown -=1 + if countdown <=0: + print("YOU LOSE") + levelCompleteSignal.emit(levels[currentLevel]) # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: pass @@ -20,7 +51,7 @@ func _on_trigger_area_trigger(effect, body) -> void: "destroy": #write code to destroy if body is Crate: - %SceneManager.destroy(body) + destroySignal.emit(body) cratesDestroyed +=1 "powerup": if body is Player: @@ -30,10 +61,38 @@ func bulletHit(body): print("Gamecontroller knows bullet hit") if body is Crate: print("You hit a crate") - cratesDestroyed +=1 - %SceneManager.destroy(body) + totalCrates -=1 + destroySignal.emit(body) print("Crates Remaining :: "+str(totalCrates - cratesDestroyed)) + if totalCrates <=0: + print("You won!!!") + currentLevel +=1 + if currentLevel >= levels.size(): + currentLevel = 0 + levelCompleteSignal.emit(levels[currentLevel]) func numberOfCrates(value): totalCrates = value print("Game Controller knows crates "+str(totalCrates) ) +func numberOfCoins(value): + totalCoinsAvailable = value + +func coinCollected(body, coin): + print("GC knows coin collected") + if body is Player: + #increase coins collected count + coinsCollected +=1 + destroySignal.emit(coin) +func playerDamage(body, badguy): + if body is Player: + print("GC knows player taking damage") + print("Player health "+str(player.health)+" takes damage "+str(slime.meleeDamage)) + player.health -= slime.meleeDamage + if player.health > 0: + playerHurtSignal.emit(player.health) + else: + print("kill em") + + +func numberOfBadguys(value): + enemies = value diff --git a/februarygodotgame/scripts/player.gd b/februarygodotgame/scripts/player.gd index ff5986a..d617d35 100644 --- a/februarygodotgame/scripts/player.gd +++ b/februarygodotgame/scripts/player.gd @@ -17,77 +17,90 @@ var isJumping = false @onready var right_target: Node2D = $rightTarget @onready var left_target: Node2D = $leftTarget +var animPlaying = "idle" +var living = true func _physics_process(delta: float) -> void: - # Add the gravity. - if not is_on_floor(): - velocity += get_gravity() * delta - else: - isJumping = false - + if living and not animPlaying == "hurt": + # Add the gravity. + if not is_on_floor(): + velocity += get_gravity() * delta + else: + isJumping = false + - # Handle jump. - if Input.is_action_just_pressed("ui_accept") and is_on_floor(): - velocity.y = JUMP_VELOCITY - isJumping = true - playerGraphic.play("jump") + # Handle jump. + if Input.is_action_just_pressed("ui_accept") and is_on_floor(): + velocity.y = JUMP_VELOCITY + isJumping = true + playerGraphic.play("jump") + + # Get the input direction and handle the movement/deceleration. + # As good practice, you should replace UI actions with custom gameplay actions. + var direction := Input.get_axis("left", "right") + if Input.is_action_just_pressed("shove") && pushRightEnabled && faceLeft == false: + pushTarget.apply_central_impulse(Vector2(1,0) * PUSH_FORCE) + pushRightEnabled = false + if Input.is_action_just_pressed("shove") && pushLeftEnabled && faceLeft == true: + pushTarget.apply_central_impulse(Vector2(-1,0) * PUSH_FORCE) + pushLeftEnabled = false + # shoot attack + if Input.is_action_just_pressed("shoot"): + if faceLeft == false: + %SceneManager.makeBullet(right_target.global_transform, 700) + if faceLeft == true: + %SceneManager.makeBullet(left_target.global_transform, -700) - # Get the input direction and handle the movement/deceleration. - # As good practice, you should replace UI actions with custom gameplay actions. - var direction := Input.get_axis("left", "right") - if Input.is_action_just_pressed("shove") && pushRightEnabled && faceLeft == false: - pushTarget.apply_central_impulse(Vector2(1,0) * PUSH_FORCE) - pushRightEnabled = false - if Input.is_action_just_pressed("shove") && pushLeftEnabled && faceLeft == true: - pushTarget.apply_central_impulse(Vector2(-1,0) * PUSH_FORCE) - pushLeftEnabled = false - # shoot attack - if Input.is_action_just_pressed("shoot"): - if faceLeft == false: - %SceneManager.makeBullet(right_target.global_transform, 700) - if faceLeft == true: - %SceneManager.makeBullet(left_target.global_transform, -700) - - - if direction: - velocity.x = direction * SPEED - else: - velocity.x = move_toward(velocity.x, 0, SPEED) - if direction: - if not isJumping: - playerGraphic.play("run") - if direction ==0: - if not isJumping: - playerGraphic.play("idle") - - if direction <0: - faceLeft = true - playerGraphic.flip_h = true - if direction >0: - faceLeft = false - playerGraphic.flip_h = false + if direction: + velocity.x = direction * SPEED + else: + velocity.x = move_toward(velocity.x, 0, SPEED) + if direction: + if not isJumping: + playerGraphic.play("run") + if direction ==0: + if not isJumping: + playerGraphic.play("idle") + + if direction <0: + faceLeft = true + playerGraphic.flip_h = true + if direction >0: + faceLeft = false + playerGraphic.flip_h = false + - move_and_slide() - if right_cast.is_colliding(): - print("something on my right") - var collider = right_cast.get_collider() - if collider is Node: - if collider is RigidBody2D: - print("shove this crate") - #record that we can shove right - pushRightEnabled = true - #record what object to shove - pushTarget = collider - if left_cast.is_colliding(): - var collider = left_cast.get_collider() - if collider is Node: - if collider is RigidBody2D: - pushLeftEnabled = true - pushTarget = collider + move_and_slide() + if right_cast.is_colliding(): + print("something on my right") + var collider = right_cast.get_collider() + if collider is Node: + if collider is RigidBody2D: + print("shove this crate") + #record that we can shove right + pushRightEnabled = true + #record what object to shove + pushTarget = collider + if left_cast.is_colliding(): + var collider = left_cast.get_collider() + if collider is Node: + if collider is RigidBody2D: + pushLeftEnabled = true + pushTarget = collider + + for i in get_slide_collision_count(): + var c = get_slide_collision(i) + if c.get_collider() is RigidBody2D: + c.get_collider().apply_central_impulse(-c.get_normal() * 50) - for i in get_slide_collision_count(): - var c = get_slide_collision(i) - if c.get_collider() is RigidBody2D: - c.get_collider().apply_central_impulse(-c.get_normal() * 50) +func hurtPlayer(health): + print("Player takes damage, health remaining:: "+str(health)) + animPlaying = "hurt" + playerGraphic.play(animPlaying) + + +func _on_animation_finished() -> void: + if animPlaying=="hurt": + animPlaying=="idle" diff --git a/februarygodotgame/scripts/res/characterStats.gd b/februarygodotgame/scripts/res/characterStats.gd new file mode 100644 index 0000000..acfaff9 --- /dev/null +++ b/februarygodotgame/scripts/res/characterStats.gd @@ -0,0 +1,8 @@ +class_name CharacterStats extends Resource + +@export var max_health:int = 100 +@export var starting_health:int = 100 +@export var health:int = 100 + +@export var meleeDamage:int = 10 +@export var rangeDamage:int = 8 diff --git a/februarygodotgame/scripts/res/playerStats.tres b/februarygodotgame/scripts/res/playerStats.tres new file mode 100644 index 0000000..ec02cb1 --- /dev/null +++ b/februarygodotgame/scripts/res/playerStats.tres @@ -0,0 +1,11 @@ +[gd_resource type="Resource" script_class="CharacterStats" load_steps=2 format=3 uid="uid://bhxl0nmjr16wm"] + +[ext_resource type="Script" path="res://scripts/res/characterStats.gd" id="1_dc0h5"] + +[resource] +script = ExtResource("1_dc0h5") +max_health = 110 +starting_health = 110 +health = 110 +meleeDamage = 15 +rangeDamage = 6 diff --git a/februarygodotgame/scripts/res/slimeStats.tres b/februarygodotgame/scripts/res/slimeStats.tres new file mode 100644 index 0000000..b5464bf --- /dev/null +++ b/februarygodotgame/scripts/res/slimeStats.tres @@ -0,0 +1,11 @@ +[gd_resource type="Resource" script_class="CharacterStats" load_steps=2 format=3 uid="uid://bmwctbkvbp0en"] + +[ext_resource type="Script" path="res://scripts/res/characterStats.gd" id="1_ev6pb"] + +[resource] +script = ExtResource("1_ev6pb") +max_health = 50 +starting_health = 50 +health = 50 +meleeDamage = 30 +rangeDamage = 0 diff --git a/februarygodotgame/scripts/scene_manager.gd b/februarygodotgame/scripts/scene_manager.gd index 5229bd6..ca8d743 100644 --- a/februarygodotgame/scripts/scene_manager.gd +++ b/februarygodotgame/scripts/scene_manager.gd @@ -1,7 +1,10 @@ extends Node -@onready var gameController: GameController = $".." + @onready var crates: Node2D = $"../crates" @onready var triggers: Node2D = $"../triggers" +@onready var coins: Node2D = $"../coins" +@onready var badguys: Node2D = $"../badguys" +@onready var player: Player = $"../CharacterBody2D" var bulletsFiredTotal = 0 var bulletsMadeTotal = 0 @@ -33,7 +36,7 @@ func makeBullet(position, speed): func bulletHit(bullet, body): print("Tell the game controller a bullet hit something") - gameController.bulletHit(body) + Gamecontroller.bulletHit(body) bullet.setSpeed(0) bullet.position = Vector2(-100,-100) @@ -46,13 +49,40 @@ func buildLevel(): for obj in crates.get_children(): if obj is Crate: totalCrates +=1 - gameController.numberOfCrates(totalCrates) + Gamecontroller.numberOfCrates(totalCrates) + #how many coins? + var totalCoins = 0 + if coins: + for obj in coins.get_children(): + if obj is Coin: + totalCoins +=1 + obj.coinCollectedSignal.connect(Gamecontroller.coinCollected) + Gamecontroller.numberOfCoins(totalCoins) + #how many badguys? + var totalBadguys = 0 + if badguys: + for obj in badguys.get_children(): + if obj is Slime: + totalBadguys +=1 + obj.playerDamageSignal.connect(Gamecontroller.playerDamage) + Gamecontroller.numberOfBadguys(totalBadguys) #wire up the triggers for obj in triggers.get_children(): if obj is Trigger: # wire up to GC - obj.areaTrigger.connect(gameController._on_trigger_area_trigger) + obj.areaTrigger.connect(Gamecontroller._on_trigger_area_trigger) + + #listen to gamnecontroller + Gamecontroller.destroySignal.connect(destroy) + Gamecontroller.levelCompleteSignal.connect(loadLevel) + Gamecontroller.playerHurtSignal.connect(playerHurt) + +func loadLevel(level): + get_tree().change_scene_to_file(level) func _ready() -> void: buildLevel() + Gamecontroller.reset() +func playerHurt(health): + player.hurtPlayer(health) diff --git a/februarygodotgame/scripts/slime.gd b/februarygodotgame/scripts/slime.gd new file mode 100644 index 0000000..b9faa9c --- /dev/null +++ b/februarygodotgame/scripts/slime.gd @@ -0,0 +1,7 @@ +class_name Slime extends Area2D + +signal playerDamageSignal + +func _on_body_entered(body: Node2D) -> void: + print("Bad guy contact") + playerDamageSignal.emit(body, self)