diff --git a/minesweeper/scenes/Minefield.tscn1397283733.tmp b/minesweeper/scenes/Minefield.tscn1397283733.tmp new file mode 100644 index 0000000..f14de50 --- /dev/null +++ b/minesweeper/scenes/Minefield.tscn1397283733.tmp @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=3 uid="uid://b8ewc3373b0t2"] + +[ext_resource type="Script" uid="uid://du63nf81skbpt" path="res://scripts/Minefield.gd" id="1_rm6t6"] + +[node name="Minefield" type="Node2D"] +script = ExtResource("1_rm6t6") + +[node name="Camera2D" type="Camera2D" parent="."] +zoom = Vector2(4, 4) diff --git a/minesweeper/scenes/Minefield.tscn1403038500.tmp b/minesweeper/scenes/Minefield.tscn1403038500.tmp new file mode 100644 index 0000000..f14de50 --- /dev/null +++ b/minesweeper/scenes/Minefield.tscn1403038500.tmp @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=3 uid="uid://b8ewc3373b0t2"] + +[ext_resource type="Script" uid="uid://du63nf81skbpt" path="res://scripts/Minefield.gd" id="1_rm6t6"] + +[node name="Minefield" type="Node2D"] +script = ExtResource("1_rm6t6") + +[node name="Camera2D" type="Camera2D" parent="."] +zoom = Vector2(4, 4) diff --git a/minesweeper/scripts/Minefield.gd b/minesweeper/scripts/Minefield.gd index 1142963..c965648 100644 --- a/minesweeper/scripts/Minefield.gd +++ b/minesweeper/scripts/Minefield.gd @@ -11,8 +11,14 @@ static var instance: Minefield @export var startingSafeZone: int = 2 var tiles: Array[Tile] +var mines: Array[Tile] +var falseFlags: Array[Tile] var spriteWidth: int = 16 var fieldInitialized: bool = false +var gameRunning: bool = true +var revealed: int = 0 +var winCondition: int +var timer: int func _enter_tree() -> void: if (instance == null || is_instance_valid(instance)): instance = self @@ -20,6 +26,7 @@ func _enter_tree() -> void: func _ready() -> void: var scale: float = 1 + winCondition = (width * height) - mineCount for x: int in range(width): for y: int in range(height): var tile: Tile = tilePrefab.instantiate() @@ -38,10 +45,29 @@ func initField(coord: Vector2i) -> void: pickPool.erase(pick) if (abs(coord - pick.coord) >= Vector2i(startingSafeZone, startingSafeZone)): pick.type = Tile.TileTypes.MINE + mines.append(pick) break pick = pickPool.pick_random() for tile: Tile in tiles: tile.evaluateType() + timer = Time.get_ticks_msec() + +func lose() -> void: + gameRunning = false + for mine: Tile in mines: + await get_tree().create_timer(randf_range(0.01, 0.25)).timeout + mine.reveal() + for flag: Tile in falseFlags: + await get_tree().create_timer(randf_range(0.01, 0.1)).timeout + flag.breakFlag() + +func tilesRevealed(count: int) -> void: + revealed += count + if (revealed == winCondition): + gameRunning = false + var completionTime: int = Time.get_ticks_msec() - timer + var humanTime: float = float(completionTime) / 1000 + print("You win.\nCompleted in " + str(humanTime) + " seconds") func getTile(coord: Vector2i) -> Tile: if (coord.x < 0 || coord.y < 0 || coord.x >= width || coord.y >= width): return null diff --git a/minesweeper/scripts/Tile.gd b/minesweeper/scripts/Tile.gd index c5eef18..c5c9446 100644 --- a/minesweeper/scripts/Tile.gd +++ b/minesweeper/scripts/Tile.gd @@ -4,6 +4,7 @@ class_name Tile extends Node2D @onready var cover: CompressedTexture2D = preload("res://sprites/cover.png") @onready var mine: CompressedTexture2D = preload("res://sprites/mine.png") @onready var flag: CompressedTexture2D = preload("res://sprites/flag.png") +@onready var brokenFlag: CompressedTexture2D = preload("res://sprites/brokenFlag.png") @onready var nums: Array[CompressedTexture2D] = [ preload("res://sprites/1.png"), preload("res://sprites/2.png"), @@ -36,44 +37,63 @@ var coord: Vector2i var revealed: bool = false var flagged: bool = false -func evaluateType() -> void: - if (type == TileTypes.MINE): return - var count: int = 0 +func getNeighbors() -> Array[Tile]: + var results: Array[Tile] for x: int in range(-1, 2): for y: int in range(-1, 2): if (x == 0 && y == 0): continue var tile: Tile = Minefield.instance.getTile(coord + Vector2i(x, y)) if (tile == null): continue - if (tile.type == TileTypes.MINE): count += 1 + results.append(tile) + return results + +func evaluateType() -> void: + if (type == TileTypes.MINE): return + var count: int = 0 + for tile: Tile in getNeighbors(): + if (tile.type == TileTypes.MINE): count += 1 type = count as TileTypes -func reveal() -> void: - if (revealed): return +func reveal() -> int: + if (revealed || Minefield.instance.gameRunning && flagged): return 0 revealed = true + var count: int = 1 layer1.texture = backplate match type: TileTypes.EMPTY: layer2.texture = null - for x: int in range(-1, 2): - for y: int in range(-1, 2): - if (x == 0 && y == 0): continue - var tile: Tile = Minefield.instance.getTile(coord + Vector2i(x, y)) - if (tile == null): continue - tile.reveal() + for tile: Tile in getNeighbors(): count += tile.reveal() TileTypes.MINE: layer2.texture = mine + if (Minefield.instance.gameRunning): Minefield.instance.lose() _: layer2.texture = nums[type as int - 1] + return count + +func breakFlag() -> void: + layer2.texture = brokenFlag func _on_area_2d_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void: + if (!Minefield.instance.gameRunning): return if (event.is_released()): - if (event.is_action_released("reveal") && !flagged): + if (event.is_action_released("reveal") && revealed): + var count: int = 0 + var neighbors: Array[Tile] = getNeighbors() + for tile: Tile in neighbors: + if (tile.flagged): count += 1 + if (count == type as int): + count = 0 + for tile: Tile in neighbors: count += tile.reveal() + Minefield.instance.tilesRevealed(count) + elif (event.is_action_released("reveal") && !flagged): if (!Minefield.instance.fieldInitialized): Minefield.instance.initField(coord) - reveal() + Minefield.instance.tilesRevealed(reveal()) elif (event.is_action_released("flag") && !revealed): flagged = !flagged if (flagged): layer2.texture = flag + if (type != TileTypes.MINE): Minefield.instance.falseFlags.append(self) else: layer2.texture = null + if (type != TileTypes.MINE): Minefield.instance.falseFlags.erase(self) diff --git a/minesweeper/sprites/brokenFlag.png b/minesweeper/sprites/brokenFlag.png new file mode 100644 index 0000000..b0dd66d Binary files /dev/null and b/minesweeper/sprites/brokenFlag.png differ diff --git a/minesweeper/sprites/brokenFlag.png.import b/minesweeper/sprites/brokenFlag.png.import new file mode 100644 index 0000000..2f76d04 --- /dev/null +++ b/minesweeper/sprites/brokenFlag.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d353xpjsitdct" +path="res://.godot/imported/brokenFlag.png-785bad89b513c2a3f4b8d504b0f83440.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://sprites/brokenFlag.png" +dest_files=["res://.godot/imported/brokenFlag.png-785bad89b513c2a3f4b8d504b0f83440.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/minesweeper/sprites/minsweeperSprites.xcf b/minesweeper/sprites/minsweeperSprites.xcf index 90a89e8..b3b6cda 100644 Binary files a/minesweeper/sprites/minsweeperSprites.xcf and b/minesweeper/sprites/minsweeperSprites.xcf differ