Added win/lose conditions, lose animation. Clicking on revealed tile with correct number of flags reveals the surrounding unflagged tiles. Added completion timer. Probably other things I'm forgetting
This commit is contained in:
parent
34a254b12c
commit
32150473c6
9
minesweeper/scenes/Minefield.tscn1397283733.tmp
Normal file
9
minesweeper/scenes/Minefield.tscn1397283733.tmp
Normal file
@ -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)
|
9
minesweeper/scenes/Minefield.tscn1403038500.tmp
Normal file
9
minesweeper/scenes/Minefield.tscn1403038500.tmp
Normal file
@ -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)
|
@ -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
|
||||
|
@ -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)
|
||||
|
BIN
minesweeper/sprites/brokenFlag.png
Normal file
BIN
minesweeper/sprites/brokenFlag.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 265 B |
34
minesweeper/sprites/brokenFlag.png.import
Normal file
34
minesweeper/sprites/brokenFlag.png.import
Normal file
@ -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
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user