diff --git a/Aircraft.gd b/Aircraft.gd index 7b669ba..d952292 100644 --- a/Aircraft.gd +++ b/Aircraft.gd @@ -25,12 +25,17 @@ func drop(): box.apply_central_impulse(-transform.y * 500) box.rotation = rotation + rand_range(-PI / 2, PI / 2) var rnd = randf() - if rnd < 0.5: - box.setContent(1) - elif rnd < 0.9: - box.setContent(2) + if rnd > 0.8: + box.setContent(4) # health + elif rnd > 0.7: + box.setContent(3) # spring + elif rnd > 0.5: + box.setContent(2) # big + elif rnd > 0.2: + box.setContent(1) # small else: - box.setContent(3) + box.setContent(0) # shell + box.z_index = z_index - 1 box.collision_layer = 128 box.collision_mask = 128 diff --git a/Box.gd b/Box.gd index 58339ff..7e44ecb 100644 --- a/Box.gd +++ b/Box.gd @@ -2,7 +2,7 @@ extends RigidBody2D export (PackedScene) var Shell -enum Content { SHELL=0, SMALL_SHELLS=1, BIG_SHELL=2, SPRING=3 } +enum Content { SHELL=0, SMALL_SHELLS=1, BIG_SHELL=2, SPRING=3, HEALTH=4 } var content = null var targetScale = Vector2(1, 1) @@ -26,11 +26,16 @@ func _physics_process(delta): func setContent(content): $Sprite/Content.frame = content self.content = content + if content == Content.SHELL: + shells = 15 + elif content == Content.HEALTH: + $Sprite/Content.rotation = 0 + life = 30 func hit(damage, source): life -= damage if life < 0: - if content != Content.SPRING: + if content != Content.SPRING and content != Content.HEALTH: fire(source) queue_free() @@ -62,6 +67,8 @@ func _on_PickArea_body_entered(body): body.addBigShell() if content == Content.SMALL_SHELLS: body.addSmallShells() + if content == Content.HEALTH: + body.addLife(0.6) func _on_FallTimer_timeout(): z_index = 1 diff --git a/Box.tscn b/Box.tscn index af46da9..fe75339 100644 --- a/Box.tscn +++ b/Box.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=10 format=2] +[gd_scene load_steps=11 format=2] [ext_resource path="res://images/box.png" type="Texture" id=1] [ext_resource path="res://images/shell.png" type="Texture" id=2] @@ -7,16 +7,17 @@ [ext_resource path="res://images/big-shell.png" type="Texture" id=5] [ext_resource path="res://Box.gd" type="Script" id=6] [ext_resource path="res://Shell.tscn" type="PackedScene" id=7] +[ext_resource path="res://images/health.png" type="Texture" id=8] [sub_resource type="SpriteFrames" id=1] animations = [ { -"frames": [ ExtResource( 2 ), ExtResource( 3 ), ExtResource( 5 ), ExtResource( 4 ) ], +"frames": [ ExtResource( 2 ), ExtResource( 3 ), ExtResource( 5 ), ExtResource( 4 ), ExtResource( 8 ) ], "loop": true, "name": "default", "speed": 5.0 } ] -[sub_resource type="CapsuleShape2D" id=3] +[sub_resource type="CapsuleShape2D" id=2] radius = 10.7314 height = 44.8859 @@ -48,7 +49,7 @@ frames = SubResource( 1 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="PickArea"] scale = Vector2( 2.06014, -0.801646 ) -shape = SubResource( 3 ) +shape = SubResource( 2 ) [node name="FallTimer" type="Timer" parent="."] wait_time = 0.6 diff --git a/Field.gd b/Field.gd index 0dc2cad..4968357 100644 --- a/Field.gd +++ b/Field.gd @@ -6,40 +6,42 @@ signal tank_removed(tank) signal game_over var candidates +var state = [0,0,0] func _ready(): candidates = [ $Tank1, $Tank2, $Tank3 ] $Tank1.setOthers([$Tank2, $Tank3]) $Tank2.setOthers([$Tank1, $Tank3]) $Tank3.setOthers([$Tank2, $Tank1]) - $Tank1.robot = true - $Tank2.robot = true var winner = null func update(): if len(candidates) < 2: - if len(candidates) == 1: + if len(candidates) == 1 and not candidates[0].robot: winner = candidates[0] $Airfcrafts.stop() emit_signal("game_over") else: var zeroes=0 var maybeWinner = null + var humans=0 for c in candidates: - if c == null: + if c == null or c.robot: continue - if c.points == 0: + if c.points <= 0: zeroes += 1 else: maybeWinner = c - if zeroes > len(candidates) -1: + humans += 1 + if zeroes > humans-1: winner = maybeWinner $Airfcrafts.stop() emit_signal("game_over") func _on_Tank1_dead(): candidates.erase($Tank1) + state[0] = $Tank1.type emit_signal("tank_removed", 1) update() @@ -48,6 +50,7 @@ func _on_Tank1_zero(): func _on_Tank2_dead(): candidates.erase($Tank2) + state[1] = $Tank2.type emit_signal("tank_removed", 2) update() @@ -56,6 +59,7 @@ func _on_Tank2_zero(): func _on_Tank3_dead(): candidates.erase($Tank3) + state[2] = $Tank3.type emit_signal("tank_removed", 3) update() @@ -64,8 +68,7 @@ func _on_Tank3_zero(): func spawnAircraft(): var spawn_location - if randf() > 0.5: - + if randf() > 0.5: spawn_location = $Airfcrafts/UpperAircraftSpawner/PathFollow2D else: spawn_location = $Airfcrafts/LowerAircraftSpawner/PathFollow2D @@ -95,3 +98,27 @@ func _on_PathCalculation_paths_updated(paths): $Tank2.updatePaths(paths) if $Tank3 != null: $Tank3.updatePaths(paths) + +func getState(): + return [ + $Tank1.type if $Tank1 != null else state[0], + $Tank2.type if $Tank2 != null else state[1], + $Tank3.type if $Tank3 != null else state[2] + ] + +func setState(state): + $Tank1.setType(state[0]) + $Tank2.setType(state[1]) + $Tank3.setType(state[2]) + +func _on_Tank1_robot(): + state[0] = $Tank1.type + emit_signal("tank_removed", 1) + +func _on_Tank2_robot(): + state[1] = $Tank2.type + emit_signal("tank_removed", 2) + +func _on_Tank3_robot(): + state[2] = $Tank3.type + emit_signal("tank_removed", 3) diff --git a/Field.tscn b/Field.tscn index 320efce..f9b9dcc 100644 --- a/Field.tscn +++ b/Field.tscn @@ -85,7 +85,7 @@ position = Vector2( 1035.76, 300.097 ) shape = SubResource( 4 ) [node name="Airfcrafts" type="Timer" parent="."] -wait_time = 20.0 +wait_time = 14.0 autostart = true [node name="UpperAircraftSpawner" type="Path2D" parent="Airfcrafts"] @@ -102,9 +102,12 @@ position = Vector2( 736.224, 683.747 ) rotation = 3.13704 [connection signal="dead" from="Tank1" to="." method="_on_Tank1_dead"] +[connection signal="robot" from="Tank1" to="." method="_on_Tank1_robot"] [connection signal="zero" from="Tank1" to="." method="_on_Tank1_zero"] [connection signal="dead" from="Tank2" to="." method="_on_Tank2_dead"] +[connection signal="robot" from="Tank2" to="." method="_on_Tank2_robot"] [connection signal="zero" from="Tank2" to="." method="_on_Tank2_zero"] [connection signal="dead" from="Tank3" to="." method="_on_Tank3_dead"] +[connection signal="robot" from="Tank3" to="." method="_on_Tank3_robot"] [connection signal="zero" from="Tank3" to="." method="_on_Tank3_zero"] [connection signal="timeout" from="Airfcrafts" to="." method="_on_Airfcrafts_timeout"] diff --git a/Game.gd b/Game.gd index 9ce08a3..94cb42f 100644 --- a/Game.gd +++ b/Game.gd @@ -2,6 +2,7 @@ extends Node2D var gameOver = false var currentLevel +var clean = true func _ready(): var level = randi() % $Levels.get_children().size() @@ -13,25 +14,40 @@ func _ready(): $GameOver.hide() if not OS.has_touchscreen_ui_hint(): $Controls.queue_free() - + var save_game = File.new() + if save_game.file_exists("user://savegame.save"): + save_game.open("user://savegame.save", File.READ) + var data = parse_json(save_game.get_line()) + $Field.setState(data.players) + save_game.close() + func _process(delta): if Input.is_action_just_pressed("reset"): if gameOver: $Camera2D.make_current() $GameOver.hide() + save($Field.getState()) get_tree().reload_current_scene() func _on_Field_game_over(): + save($Field.getState()) $GameOver/Timer.start() if $Field.winner != null: $Field.winner.focus() +func save(state): + var save_game = File.new() + save_game.open("user://savegame.save", File.WRITE) + save_game.store_line(to_json({ "players": state})) + save_game.close() + func _on_Timer_timeout(): gameOver = true if $Field.winner == null: $GameOver.show() func _on_Field_tank_removed(tank): + clean = false if $Controls == null: return if(tank == 1): diff --git a/Game.tscn b/Game.tscn index 1aa5959..c98e65c 100644 --- a/Game.tscn +++ b/Game.tscn @@ -90,22 +90,24 @@ rocks = 0.9 [node name="Controls1" parent="Controls" instance=ExtResource( 4 )] modulate = Color( 0.635294, 0.588235, 0.0313726, 0.360784 ) -position = Vector2( 103.847, 46.9703 ) +position = Vector2( 103.847, 57.9703 ) rotation = 1.5708 player = 1 [node name="Controls2" parent="Controls" instance=ExtResource( 4 )] modulate = Color( 0.054902, 0.435294, 0.835294, 0.388235 ) -position = Vector2( 917.263, 533.288 ) +position = Vector2( 917.263, 537.288 ) rotation = -1.5708 player = 2 [node name="Controls3" parent="Controls" instance=ExtResource( 4 )] modulate = Color( 0.603922, 0.247059, 0.803922, 0.356863 ) -position = Vector2( 393.722, 496.634 ) +position = Vector2( 395.722, 496.634 ) player = 3 [node name="GameOver" type="Node2D" parent="."] +z_index = 156 +z_as_relative = false [node name="Label" type="Label" parent="GameOver"] margin_left = 205.407 @@ -113,7 +115,7 @@ margin_top = 237.133 margin_right = 797.406 margin_bottom = 357.133 custom_fonts/font = SubResource( 1 ) -text = "No Winner" +text = "Game Over" align = 1 valign = 1 __meta__ = { @@ -142,7 +144,6 @@ z_as_relative = false script = ExtResource( 6 ) [node name="PathUpdate" type="Timer" parent="ArtificialIntelligence/PathCalculation"] -wait_time = 0.5 [connection signal="ready" from="." to="ArtificialIntelligence/PathCalculation" method="_on_Game_ready"] [connection signal="game_over" from="Field" to="." method="_on_Field_game_over"] diff --git a/PathCalculation.gd b/PathCalculation.gd index 2bf6559..b1ac36a 100644 --- a/PathCalculation.gd +++ b/PathCalculation.gd @@ -5,7 +5,9 @@ const DEBUG_PATHS = false var rocks var triangles var ready = false +var blacklist var paths +var thread signal paths_updated(paths) @@ -19,6 +21,10 @@ func _on_Game_ready(): $PathUpdate.start() func _draw(): + if DEBUG_PATHS: + calculate() + +func calculate(ignore=null): if not ready: return if DEBUG_PATHS: @@ -28,7 +34,7 @@ func _draw(): draw_circle(to_local(c), 6, Color(1,0,0,0.5)) var threshold = 80 paths = [] - var blacklist = [] + blacklist = [] for t in triangles: var path = [] for i in range(0,3): @@ -43,7 +49,7 @@ func _draw(): path.append(center) if len(path) > 2: path.append(path[0]) - paths.append(path) + paths.append(path) for path in paths: var toRemove=[] for point in blacklist: @@ -51,7 +57,7 @@ func _draw(): if (point - path[i]).length() < 10: path.remove(i) if len(path) == 1: - path.remove(0) + path.remove(0) for path in paths: for i in range(len(path)-1, -1, -1): var n = 0 @@ -90,7 +96,6 @@ func triangulate(): for triple in triangleArray: triangles.append([allPoints[triple[0]], allPoints[triple[1]], allPoints[triple[2]]]) ready = true - update() func getCorners(): var node = get_parent().get_parent().get_node("Field/CollisionShape2D") @@ -104,3 +109,12 @@ func getCorners(): func _on_PathUpdate_timeout(): triangulate() + if DEBUG_PATHS: + update() + else: + thread = Thread.new() + thread.start(self, "calculate", null) + +func _exit_tree(): + if thread != null: + thread.wait_to_finish() diff --git a/Robot.gd b/Robot.gd index 805909c..2a57911 100644 --- a/Robot.gd +++ b/Robot.gd @@ -10,6 +10,7 @@ var currentPaths = [] var shooting = false var updating = 0 var started = false +var original func updatePaths(paths): self.paths = paths @@ -28,7 +29,13 @@ func _physics_process(delta): if weakref(other).get_ref() and not other.robot: start = start and not other.virgin started = start + if started and get_parent().robot: + get_parent().emit_signal("robot") + if get_parent().type == get_parent().Type.REMOVE and started: + get_parent().die(false) + return if get_parent().robot and started and get_parent().life > 0 and paths != null: + $Sprite.hide() if updating == 0: computeDestination() disperse = false @@ -67,7 +74,6 @@ func _physics_process(delta): updating += delta if updating > 0.5: updating = 0 - func computeDestination(): var threshold = 20 diff --git a/Shell.gd b/Shell.gd index 2a57c42..a8ce2a8 100644 --- a/Shell.gd +++ b/Shell.gd @@ -1,6 +1,6 @@ extends Area2D -const HIT_REWARD = 10 +const HIT_REWARD = 2 var speed = 480 var shell_force = 70 var damage = 11 diff --git a/Tank.gd b/Tank.gd index 364e393..3965f65 100644 --- a/Tank.gd +++ b/Tank.gd @@ -7,6 +7,7 @@ export (int) var player signal dead signal zero +signal robot const SMALL_ROTATE_RATIO = 0.2 const ROTATE_IMPULSE = 6000 @@ -16,7 +17,7 @@ const FIRE_SKEW = 40 const LOAD_TIME = 0.260 const SHOTS_PER_SEQUENCE = 3 const DAMAGE_RATIO = 1.4 -const DESTROY_REWARD = 20 +const DESTROY_REWARD = 15 const SHOW_OFF_IMPULSE = 100 const FULL_LIFE = Color(0.1, 0.7, 0.1) const HIGH_LIFE = Color(0.6, 0.7, 0.1) @@ -30,7 +31,7 @@ var life = MAX_LIFE var buttonDuration = 0 var loading = false var shot = 0 -var points = 50 +var points = 30 var lastDelta = 0 var focused = false var ready = false @@ -40,15 +41,22 @@ var bigShell = 0 var smallShells = 0 var robot = false var others = [] +var color + +enum Type { HUMAN, ROBOT, REMOVE } +var type = Type.HUMAN func _ready(): if player == 1: - $Sprite.modulate = Color(0.8, 0.6, 0) + color = Color(0.8, 0.6, 0) if player == 2: - $Sprite.modulate = Color(0, 0.6, 0.9) + color = Color(0, 0.6, 0.9) if player == 3: - $Sprite.modulate = Color(0.7, 0.4, 0.7) + color = Color(0.7, 0.4, 0.7) + $Sprite.modulate = color $InitTimer.start() + $Remove.hide() + $Robot/Sprite.hide() $Label.hide() $Life.hide() @@ -159,6 +167,10 @@ func showLife(): $Life.show() $Life/Fade.start() +func addLife(ratio): + life = min(MAX_LIFE, life + ratio*MAX_LIFE) + showLife() + func addPoints(delta): var newPoints = max(0, points+delta) lastDelta = points - newPoints @@ -233,12 +245,35 @@ func _on_InitTimer_timeout(): ready = true func _on_TankButton_pressed(): - if virgin: - die(false) + switchType() func _on_MouseButton_pressed(): + switchType() + +func setType(newType): + robot = false + if newType == 1: + type = Type.ROBOT + robot = true + $Robot/Sprite.show() + $Sprite.modulate = Color(0.2, 0.7, 0.3) + elif newType == 2: + $Sprite.modulate = color + type = Type.REMOVE + $Robot/Sprite.hide() + $Remove.show() + elif newType == 0: + type = Type.HUMAN + $Remove.hide() + +func switchType(): if virgin: - die(false) + if type == Type.HUMAN: + setType(Type.ROBOT) + elif type == Type.ROBOT: + setType(Type.REMOVE) + elif type == Type.REMOVE: + setType(Type.HUMAN) func updatePaths(paths): $Robot.updatePaths(paths) diff --git a/Tank.tscn b/Tank.tscn index bd83457..fb72566 100644 --- a/Tank.tscn +++ b/Tank.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=13 format=2] +[gd_scene load_steps=15 format=2] [ext_resource path="res://images/tank.png" type="Texture" id=1] [ext_resource path="res://Tank.gd" type="Script" id=2] @@ -9,6 +9,8 @@ [ext_resource path="res://fonts/Xolonium-Regular.ttf" type="DynamicFontData" id=7] [ext_resource path="res://Box.tscn" type="PackedScene" id=8] [ext_resource path="res://Robot.gd" type="Script" id=9] +[ext_resource path="res://images/robot.png" type="Texture" id=10] +[ext_resource path="res://images/remove.png" type="Texture" id=11] [sub_resource type="ParticlesMaterial" id=1] lifetime_randomness = 0.32 @@ -177,6 +179,15 @@ cast_to = Vector2( 0, 400 ) enabled = true cast_to = Vector2( 0, -1000 ) +[node name="Sprite" type="Sprite" parent="Robot"] +position = Vector2( 0, 4 ) +scale = Vector2( 0.063, 0.063 ) +texture = ExtResource( 10 ) + +[node name="Remove" type="Sprite" parent="."] +scale = Vector2( 0.063, 0.063 ) +texture = ExtResource( 11 ) + [connection signal="timeout" from="Muzzle/MuzzleFire/Timer" to="Muzzle/MuzzleFire/Timer" method="_on_Timer_timeout"] [connection signal="timeout" from="Muzzle/MuzzleFire/Timer" to="." method="_on_Timer_timeout"] [connection signal="timeout" from="LoadTimer" to="." method="_on_LoadTimer_timeout"] diff --git a/icon.png b/icon.png index 2e573b7..c3e9ef7 100644 Binary files a/icon.png and b/icon.png differ diff --git a/images/health.png b/images/health.png index e63e5e4..60ae70c 100644 Binary files a/images/health.png and b/images/health.png differ diff --git a/images/remove.png b/images/remove.png new file mode 100644 index 0000000..d78291d Binary files /dev/null and b/images/remove.png differ diff --git a/images/remove.png.import b/images/remove.png.import new file mode 100644 index 0000000..653af83 --- /dev/null +++ b/images/remove.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/remove.png-7e50080613bd475f813f05098c3fe7b2.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/remove.png" +dest_files=[ "res://.import/remove.png-7e50080613bd475f813f05098c3fe7b2.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/images/robot.png b/images/robot.png new file mode 100644 index 0000000..064aec6 Binary files /dev/null and b/images/robot.png differ diff --git a/images/robot.png.import b/images/robot.png.import new file mode 100644 index 0000000..09cc9ba --- /dev/null +++ b/images/robot.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/robot.png-89f84a23f2b400909818f389317963c2.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://images/robot.png" +dest_files=[ "res://.import/robot.png-89f84a23f2b400909818f389317963c2.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0