2025-05-13 11:16:02 -04:00
|
|
|
class_name Minefield extends Node2D
|
|
|
|
|
|
|
|
static var instance: Minefield
|
|
|
|
|
2025-05-13 14:49:17 -04:00
|
|
|
@onready var tilePrefab: PackedScene = preload("res://scenes/Tile.tscn")
|
2025-05-13 11:16:02 -04:00
|
|
|
@onready var cam: Camera2D = $Camera2D
|
|
|
|
|
|
|
|
@export var width: int = 10
|
|
|
|
@export var height: int = 10
|
|
|
|
@export var mineCount: int = 10
|
2025-05-13 22:29:20 -04:00
|
|
|
@export var startingSafeZone: int = 2
|
2025-05-13 11:16:02 -04:00
|
|
|
|
2025-05-13 14:49:17 -04:00
|
|
|
var tiles: Array[Tile]
|
2025-05-14 11:32:36 -04:00
|
|
|
var mines: Array[Tile]
|
|
|
|
var falseFlags: Array[Tile]
|
2025-05-13 11:16:02 -04:00
|
|
|
var spriteWidth: int = 16
|
|
|
|
var fieldInitialized: bool = false
|
2025-05-14 11:32:36 -04:00
|
|
|
var gameRunning: bool = true
|
|
|
|
var revealed: int = 0
|
|
|
|
var winCondition: int
|
|
|
|
var timer: int
|
2025-05-13 11:16:02 -04:00
|
|
|
|
|
|
|
func _enter_tree() -> void:
|
|
|
|
if (instance == null || is_instance_valid(instance)): instance = self
|
|
|
|
else: queue_free()
|
|
|
|
|
|
|
|
func _ready() -> void:
|
|
|
|
var scale: float = 1
|
2025-05-14 11:32:36 -04:00
|
|
|
winCondition = (width * height) - mineCount
|
2025-05-13 11:16:02 -04:00
|
|
|
for x: int in range(width):
|
|
|
|
for y: int in range(height):
|
2025-05-13 14:49:17 -04:00
|
|
|
var tile: Tile = tilePrefab.instantiate()
|
|
|
|
tile.coord = Vector2i(x, y)
|
|
|
|
tile.position = Vector2(spriteWidth * x - (spriteWidth * (width / 2)) + (spriteWidth / 2),
|
2025-05-13 11:16:02 -04:00
|
|
|
spriteWidth * y - (spriteWidth * (height / 2)) + (spriteWidth / 2))
|
2025-05-13 14:49:17 -04:00
|
|
|
add_child(tile)
|
|
|
|
tiles.append(tile)
|
2025-05-13 11:16:02 -04:00
|
|
|
|
|
|
|
func initField(coord: Vector2i) -> void:
|
2025-05-13 14:49:17 -04:00
|
|
|
fieldInitialized = true
|
|
|
|
var pickPool: Array[Tile] = tiles.duplicate()
|
2025-05-13 11:16:02 -04:00
|
|
|
for i: int in range(mineCount):
|
2025-05-13 14:49:17 -04:00
|
|
|
var pick: Tile = pickPool.pick_random()
|
2025-05-13 11:16:02 -04:00
|
|
|
while (true):
|
2025-05-13 14:49:17 -04:00
|
|
|
pickPool.erase(pick)
|
2025-05-13 22:29:20 -04:00
|
|
|
if (abs(coord - pick.coord) >= Vector2i(startingSafeZone, startingSafeZone)):
|
2025-05-13 14:49:17 -04:00
|
|
|
pick.type = Tile.TileTypes.MINE
|
2025-05-14 11:32:36 -04:00
|
|
|
mines.append(pick)
|
2025-05-13 14:49:17 -04:00
|
|
|
break
|
|
|
|
pick = pickPool.pick_random()
|
|
|
|
for tile: Tile in tiles:
|
|
|
|
tile.evaluateType()
|
2025-05-14 11:32:36 -04:00
|
|
|
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")
|
2025-05-13 14:49:17 -04:00
|
|
|
|
|
|
|
func getTile(coord: Vector2i) -> Tile:
|
2025-05-13 11:16:02 -04:00
|
|
|
if (coord.x < 0 || coord.y < 0 || coord.x >= width || coord.y >= width): return null
|
2025-05-13 14:49:17 -04:00
|
|
|
return tiles[(coord.x * height) + coord.y]
|