wip: reworking cards to use sprites and fixing up some stuff related to them
This commit is contained in:
parent
d1ef1d6f4f
commit
7cddb502b4
81
caching.gd
81
caching.gd
@ -9,37 +9,40 @@ var _emitted_done = 0
|
||||
signal fetch_start
|
||||
var _emitted_start = 0
|
||||
|
||||
|
||||
var _consts = preload("res://data/consts.gd")
|
||||
|
||||
|
||||
func _all_downloads_done() -> bool:
|
||||
return _emitted_done == _emitted_start
|
||||
|
||||
|
||||
func _setup_cache_in_mem():
|
||||
var file = FileAccess.open("user://bulk.json", FileAccess.READ)
|
||||
_bulk_data = JSON.parse_string(file.get_as_text())
|
||||
file.close()
|
||||
|
||||
|
||||
|
||||
func setup() -> Error:
|
||||
if !FileAccess.file_exists("user://bulk.json"):
|
||||
get_bulk_data(false)
|
||||
push_error("Bulk Data was not downloaded! Downloading now!")
|
||||
return FAILED
|
||||
|
||||
|
||||
if !_all_downloads_done():
|
||||
push_error("Not done downloading Bulk Data.")
|
||||
return FAILED
|
||||
|
||||
|
||||
_setup_cache_in_mem()
|
||||
return OK
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
_req_headers = PackedStringArray(["User-Agent: " + _consts.APP_NAME + "/" + _consts.APP_VERSION, "Accept: */*"])
|
||||
|
||||
_req_headers = PackedStringArray(
|
||||
["User-Agent: " + _consts.APP_NAME + "/" + _consts.APP_VERSION, "Accept: */*"]
|
||||
)
|
||||
|
||||
fetch_done.connect(_on_end_emit)
|
||||
fetch_start.connect(_on_start_emit)
|
||||
|
||||
|
||||
|
||||
func _on_start_emit() -> void:
|
||||
@ -49,20 +52,22 @@ func _on_start_emit() -> void:
|
||||
func _on_end_emit() -> void:
|
||||
_emitted_done += 1
|
||||
|
||||
|
||||
func has_emitted_all() -> bool:
|
||||
return _emitted_start == _emitted_done
|
||||
|
||||
|
||||
func _cache_error(err: String) -> String:
|
||||
return "CACHE::ERROR::" + err + "\n"
|
||||
|
||||
|
||||
|
||||
func _get_dict_from_file(filepath: String) -> Dictionary:
|
||||
var file = FileAccess.open(filepath, FileAccess.READ)
|
||||
var data = JSON.parse_string(file.get_as_text())
|
||||
|
||||
|
||||
return data
|
||||
|
||||
|
||||
## get_card_data_from_name
|
||||
##
|
||||
## _name: String [br]
|
||||
@ -88,108 +93,114 @@ func _get_card_data_from_bulk(field: String, search_query: String) -> Dictionary
|
||||
selected_entry = entry
|
||||
break
|
||||
continue
|
||||
|
||||
|
||||
if selected_entry == null:
|
||||
return {}
|
||||
|
||||
|
||||
if selected_entry["image_status"] != "missing":
|
||||
_fetch_card_img(selected_entry)
|
||||
|
||||
|
||||
var dir = DirAccess.open("user://")
|
||||
dir.make_dir_recursive("user://card_cache/" + selected_entry["id"] + "/")
|
||||
dir = null
|
||||
|
||||
var file = FileAccess.open("user://card_cache/" + selected_entry["id"] + "/card.json", FileAccess.WRITE)
|
||||
|
||||
var file = FileAccess.open(
|
||||
"user://card_cache/" + selected_entry["id"] + "/card.json", FileAccess.WRITE
|
||||
)
|
||||
file.store_line(JSON.stringify(selected_entry, "\t"))
|
||||
file.close()
|
||||
|
||||
|
||||
print("Card: " + selected_entry["name"] + "(" + selected_entry["id"] + ") found, and cached.")
|
||||
|
||||
|
||||
return selected_entry
|
||||
|
||||
|
||||
func _fetch_card_img(data: Dictionary) -> Error:
|
||||
fetch_start.emit()
|
||||
if FileAccess.file_exists("user://card_cache/" + data["id"] + "card.png"):
|
||||
return OK
|
||||
|
||||
|
||||
var httpr = HTTPRequest.new()
|
||||
add_child(httpr)
|
||||
|
||||
|
||||
var err = httpr.request((data["image_uris"])["png"], _req_headers)
|
||||
if err != OK:
|
||||
push_error(_cache_error("GET_REQUEST") + "An error occured in the Scryfall request.")
|
||||
return FAILED
|
||||
var resp = await httpr.request_completed
|
||||
|
||||
|
||||
var img = Image.new()
|
||||
err = img.load_png_from_buffer(resp[3])
|
||||
if err != OK:
|
||||
push_error(_cache_error("IMG_LOADING") + "Couldn't load the image.")
|
||||
return FAILED
|
||||
|
||||
|
||||
var dir = DirAccess.open("user://")
|
||||
dir.make_dir_recursive("user://card_cache/" + data["id"] + "/")
|
||||
dir = null
|
||||
|
||||
|
||||
img.save_png("user://card_cache/" + data["id"] + "/card.png")
|
||||
img = null
|
||||
|
||||
|
||||
fetch_done.emit()
|
||||
|
||||
|
||||
return OK
|
||||
|
||||
|
||||
func get_bulk_data(force: bool) -> Error:
|
||||
if FileAccess.file_exists("user://bulk.json"):
|
||||
if force:
|
||||
DirAccess.remove_absolute("user://bulk.json")
|
||||
else:
|
||||
return OK
|
||||
|
||||
|
||||
var httpr = HTTPRequest.new()
|
||||
add_child(httpr)
|
||||
|
||||
|
||||
var error = httpr.request("https://api.scryfall.com/bulk-data/unique-artwork", _req_headers)
|
||||
if error != OK:
|
||||
push_error(_cache_error("GET_REQUEST") + "An error occurred in the Scryfall request.")
|
||||
return FAILED
|
||||
|
||||
|
||||
var response = await httpr.request_completed
|
||||
if response[0] != HTTPRequest.RESULT_SUCCESS:
|
||||
push_error(_cache_error("GET_REQUEST") + "Failed to fetch card data from Scryfall")
|
||||
return FAILED
|
||||
|
||||
|
||||
var unprocessed_body = response[3].get_string_from_utf8()
|
||||
var card_content = JSON.parse_string(unprocessed_body)
|
||||
if card_content == null:
|
||||
push_error(_cache_error("PARSING") + "Failed to parse the Scryfall card results.")
|
||||
return FAILED
|
||||
|
||||
|
||||
|
||||
error = httpr.request(card_content["download_uri"], _req_headers)
|
||||
if error != OK:
|
||||
push_error(_cache_error("GET_REQUEST") + "An error occurred in the Scryfall request.")
|
||||
return FAILED
|
||||
|
||||
|
||||
response = await httpr.request_completed
|
||||
if response[0] != HTTPRequest.RESULT_SUCCESS:
|
||||
push_error(_cache_error("GET_REQUEST") + "Failed to fetch card data from Scryfall")
|
||||
return FAILED
|
||||
|
||||
|
||||
unprocessed_body = response[3].get_string_from_utf8()
|
||||
card_content = JSON.parse_string(unprocessed_body)
|
||||
if card_content == null:
|
||||
push_error(_cache_error("PARSING") + "Failed to parse the Scryfall card results.")
|
||||
return FAILED
|
||||
|
||||
|
||||
var data_cache = FileAccess.open("user://bulk.json", FileAccess.WRITE)
|
||||
data_cache.store_string(unprocessed_body)
|
||||
data_cache.close()
|
||||
|
||||
|
||||
fetch_done.emit()
|
||||
|
||||
|
||||
return OK
|
||||
|
||||
|
||||
func _notification(what):
|
||||
if what == NOTIFICATION_PREDELETE:
|
||||
if !_all_downloads_done():
|
||||
push_error("ERR::MEM::CACHE\nCache being deleted before all threads have finished processing!")
|
||||
push_error(
|
||||
"ERR::MEM::CACHE\nCache being deleted before all threads have finished processing!"
|
||||
)
|
||||
|
71
card.gd
71
card.gd
@ -5,12 +5,7 @@ extends TextureRect
|
||||
## Represents an instance of a card to be displayed on the tabletop.
|
||||
## Contains helper text for the text, the cards ID, and the image path.
|
||||
|
||||
enum pivot {
|
||||
ROTATE_0,
|
||||
ROTATE_90,
|
||||
ROTATE_180,
|
||||
ROTATE_270
|
||||
}
|
||||
enum pivot { ROTATE_0, ROTATE_90, ROTATE_180, ROTATE_270 }
|
||||
|
||||
var current_pivot = pivot.ROTATE_0
|
||||
|
||||
@ -19,14 +14,16 @@ var card_name: String
|
||||
var card_type: String
|
||||
var oracle_text: String
|
||||
|
||||
var is_dragging = false
|
||||
var is_pivot = false
|
||||
# Tween trackers for distinguishing which state the card is in.
|
||||
var is_focused = false # Is the card a focus?
|
||||
var is_dragging = false # Is the card currently being dragged?
|
||||
var is_travelling = false # Is the card moving to a location?
|
||||
var is_pivot = false # Is the card currently waiting to be tapped/untapped?
|
||||
|
||||
var delay = 5.0
|
||||
var mouse_offset: Vector2
|
||||
|
||||
|
||||
|
||||
func _pivot() -> int:
|
||||
var deg: int
|
||||
match current_pivot:
|
||||
@ -39,17 +36,29 @@ func _pivot() -> int:
|
||||
pivot.ROTATE_270:
|
||||
deg = 270
|
||||
return deg
|
||||
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if is_dragging == true:
|
||||
var tween = get_tree().create_tween()
|
||||
tween.tween_property(self, "position", get_global_mouse_position() - mouse_offset, delay * delta)
|
||||
if is_pivot == true:
|
||||
var tween = get_tree().create_tween()
|
||||
_tweening(delta)
|
||||
|
||||
|
||||
func _tweening(delta: float) -> void:
|
||||
var tween = get_tree().create_tween()
|
||||
|
||||
if is_focused:
|
||||
tween.tween_property(self, "scale", Vector2(1.05, 1.05), delta * delay)
|
||||
else:
|
||||
tween.tween_property(self, "scale", Vector2(1.0, 1.0), delta * delay)
|
||||
|
||||
if is_dragging:
|
||||
tween.tween_property(
|
||||
self, "position", get_global_mouse_position() - mouse_offset, delay * delta
|
||||
)
|
||||
|
||||
if is_pivot:
|
||||
tween.tween_property(self, "rotation_degrees", _pivot(), delta * delay)
|
||||
is_pivot = false
|
||||
|
||||
|
||||
|
||||
func _gui_input(event: InputEvent) -> void:
|
||||
if event is not InputEventMouseButton:
|
||||
@ -57,14 +66,30 @@ func _gui_input(event: InputEvent) -> void:
|
||||
match event.button_index:
|
||||
MOUSE_BUTTON_LEFT:
|
||||
if event.pressed:
|
||||
is_dragging = true
|
||||
is_dragging = true
|
||||
mouse_offset = get_global_mouse_position() - global_position
|
||||
else:
|
||||
is_dragging = false
|
||||
MOUSE_BUTTON_RIGHT:
|
||||
# TODO: Tooltip menu for right-button clicking on cards.
|
||||
pass
|
||||
|
||||
|
||||
|
||||
func _on_mouse_entered() -> void:
|
||||
is_focused = true
|
||||
|
||||
|
||||
func _on_mouse_exited() -> void:
|
||||
if not is_dragging:
|
||||
is_focused = false
|
||||
|
||||
|
||||
func travel_to(position: Vector2) -> Error:
|
||||
# TODO: Check whether position to travel to is within the confines of where this card can go.
|
||||
|
||||
return OK
|
||||
|
||||
|
||||
func _unhandled_key_input(event: InputEvent) -> void:
|
||||
if not event.is_action_pressed("default_action"):
|
||||
return
|
||||
@ -76,13 +101,14 @@ func _unhandled_key_input(event: InputEvent) -> void:
|
||||
is_pivot = true
|
||||
set_pivot_offset(size / 2)
|
||||
|
||||
|
||||
func _card_error(error_type: String) -> String:
|
||||
return "ERROR::CARD::%s::%s::%s::\n" % [card_id, card_name, error_type]
|
||||
|
||||
|
||||
func init(id: String) -> void:
|
||||
card_id = id
|
||||
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var load_status = _load_card()
|
||||
@ -91,7 +117,7 @@ func _ready() -> void:
|
||||
# if the card is not cached, perhaps a placeholder blank card can be used instead?
|
||||
# Setting that up can be put here later...
|
||||
push_error("Failed to load card.")
|
||||
|
||||
|
||||
set_pivot_offset(size / 2)
|
||||
|
||||
|
||||
@ -140,16 +166,11 @@ func _load_image() -> Error:
|
||||
push_error("%sCard on-board image failed to load correctly" % _card_error("IMAGE"))
|
||||
return FAILED
|
||||
|
||||
|
||||
# TODO: Get the size from the node or some constant variable.
|
||||
image.resize(int(size.x), int(size.y), Image.INTERPOLATE_LANCZOS)
|
||||
|
||||
|
||||
|
||||
var image_texture = ImageTexture.new()
|
||||
image_texture.set_image(image)
|
||||
|
||||
#expand_mode = TextureRect.EXPAND_FIT_WIDTH
|
||||
texture = image_texture
|
||||
|
||||
return OK
|
||||
|
12
card.tscn
12
card.tscn
@ -1,7 +1,9 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cah3mvdnom1xg"]
|
||||
[gd_scene load_steps=3 format=3 uid="uid://cah3mvdnom1xg"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b3yqd1qu7dyq" path="res://card.gd" id="1_kikvd"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kikvd"]
|
||||
|
||||
[node name="Card" type="TextureRect"]
|
||||
offset_left = 794.0
|
||||
offset_top = 79.0
|
||||
@ -9,3 +11,11 @@ offset_right = 919.0
|
||||
offset_bottom = 254.0
|
||||
mouse_default_cursor_shape = 2
|
||||
script = ExtResource("1_kikvd")
|
||||
|
||||
[node name="Area2D" type="Area2D" parent="."]
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
|
||||
shape = SubResource("RectangleShape2D_kikvd")
|
||||
|
||||
[connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"]
|
||||
[connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"]
|
||||
|
@ -6,6 +6,7 @@ var _decklist
|
||||
|
||||
var cards: String
|
||||
|
||||
|
||||
func _init(_cards: String) -> void:
|
||||
cards = _cards
|
||||
_decklist = Dictionary()
|
||||
@ -18,7 +19,7 @@ func _convert_mtgo_to_cache_lookup(decklist: String) -> Dictionary:
|
||||
var words = line.split(" ", false, 1)
|
||||
if words.size() != 2:
|
||||
continue
|
||||
|
||||
|
||||
_cards[words[1]] = words[0]
|
||||
return _cards
|
||||
|
||||
@ -37,7 +38,7 @@ func do_decklist_grab(decklist: String) -> void:
|
||||
for query in queries:
|
||||
var entry = cache.get_card_data_from_name(query)
|
||||
_decklist[entry["id"]] = queries[query]
|
||||
|
||||
|
||||
cache.fetch_done.connect(_do_free.bind(cache))
|
||||
|
||||
|
||||
|
15
hand.gd
Normal file
15
hand.gd
Normal file
@ -0,0 +1,15 @@
|
||||
extends StaticBody2D
|
||||
|
||||
var cards: Array[Node] = []
|
||||
|
||||
var _card_class = preload("res://card.tscn")
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
1
hand.gd.uid
Normal file
1
hand.gd.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://dvu4gdhqjejeo
|
@ -19,6 +19,7 @@ func _init(_decklist: Dictionary) -> void:
|
||||
for i in _num:
|
||||
lib_cards.push_back(card)
|
||||
|
||||
|
||||
func add_cards(cards: Array, top: bool) -> void:
|
||||
for card in cards:
|
||||
add_card(card, top)
|
||||
|
11
player.gd
11
player.gd
@ -7,18 +7,21 @@ var fields: Array[Node] = []
|
||||
|
||||
var decks: Array[Dictionary]
|
||||
|
||||
|
||||
func _load_decks():
|
||||
if !FileAccess.file_exists("user://decks.json"):
|
||||
return # no loaded decks
|
||||
return # no loaded decks
|
||||
|
||||
var file = FileAccess.open("user://decks.json", FileAccess.READ)
|
||||
decks = JSON.parse_string(file.get_as_text())
|
||||
file.close()
|
||||
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
# The first field in the array will be the player's own field.
|
||||
# Might be a better idea to have that in a seperate variable? idk
|
||||
|
||||
|
||||
var card = _card_class.instantiate()
|
||||
|
||||
# TODO: Currently working with an already-cached card with a known ID to load this.
|
||||
@ -26,7 +29,7 @@ func _ready() -> void:
|
||||
card.init("d3f10f07-7cfe-4a6f-8de6-373e367a731b")
|
||||
|
||||
add_child(card)
|
||||
|
||||
|
||||
#fields.append(field_scene.instantiate())
|
||||
#var colors: Array[Color] = [Color(1, 0, 1)]
|
||||
#fields[0].set_colors(colors)
|
||||
|
13
player.tscn
13
player.tscn
@ -1,12 +1,21 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://cx0vga81xwckh"]
|
||||
[gd_scene load_steps=5 format=3 uid="uid://cx0vga81xwckh"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://w2rqm1u7p7im" path="res://player.gd" id="1_4flbx"]
|
||||
[ext_resource type="Script" uid="uid://dvu4gdhqjejeo" path="res://hand.gd" id="2_i3pqv"]
|
||||
[ext_resource type="Script" uid="uid://bc51go8t8uvts" path="res://library.gd" id="2_onrkg"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_onrkg"]
|
||||
size = Vector2(1920, 200)
|
||||
|
||||
[node name="Player" type="Node2D"]
|
||||
script = ExtResource("1_4flbx")
|
||||
|
||||
[node name="Hand" type="Node2D" parent="."]
|
||||
[node name="Hand" type="StaticBody2D" parent="."]
|
||||
script = ExtResource("2_i3pqv")
|
||||
|
||||
[node name="CollisionArea" type="CollisionShape2D" parent="Hand"]
|
||||
position = Vector2(960, 980)
|
||||
shape = SubResource("RectangleShape2D_onrkg")
|
||||
|
||||
[node name="Library" type="Node2D" parent="."]
|
||||
script = ExtResource("2_onrkg")
|
||||
|
14
tabletop.gd
14
tabletop.gd
@ -4,17 +4,18 @@ var player_class = preload("res://player.gd")
|
||||
var deck_input = preload("res://deck_input.gd")
|
||||
var _caching = preload("res://caching.gd")
|
||||
|
||||
|
||||
var cards = "1 All That Glitters\n1 Ancestral Mask\n1 Angelic Destiny\n1 Arcane Signet\n1 Archon of Sun's Grace\n1 Austere Command\n1 Banishing Light\n1 Bear Umbra\n1 Blossoming Sands\n1 Canopy Vista\n1 Celestial Mantle\n1 Collective Resistance\n1 Command Tower\n1 Danitha Capashen, Paragon\n1 Danitha, New Benalia's Light\n1 Darksteel Mutation\n1 Daybreak Coronet\n1 Destiny Spinner\n1 Eidolon of Blossoms\n1 Eidolon of Countless Battles\n1 Ellivere of the Wild Court\n1 Enchantress's Presence\n1 Envoy of the Ancestors\n1 Ethereal Armor\n1 Fertile Ground\n13 Forest\n1 Frantic Strength\n1 Generous Gift\n1 Gilded Lotus\n1 Glittering Frost\n1 Grasp of Fate\n1 Gylwain, Casting Director\n1 Hall of Heliod's Generosity\n1 Heliod's Pilgrim\n1 Hidden Grotto\n1 Horrid Vigor\n1 Idyllic Tutor\n1 Jukai Naturalist\n1 Kenrith's Transformation\n1 Kor Spiritdancer\n1 Krosan Verge\n1 Light-Paws, Emperor's Voice\n1 Luminous Broodmoth\n1 Mantle of the Ancients\n1 Overgrowth\n1 Overprotect\n1 Pacifism\n14 Plains\n1 Rancor\n1 Retether\n1 Rogue's Passage\n1 Sage's Reverie\n1 Sanctum Weaver\n1 Selesnya Guildgate\n1 Setessan Champion\n1 Shalai, Voice of Plenty\n1 Snake Umbra\n1 Sol Ring\n1 Solemnity\n1 Songbirds' Blessing\n1 Starfield Mystic\n1 Swords to Plowshares\n1 Tanglespan Lookout\n1 Timber Paladin\n1 Timely Ward\n1 Tithe Takern1 Transcendent Envoy\n1 Twinblade Blessing\n1 Umbra Mystic\n1 Unfinished Business\n1 Utopia Sprawl\n1 Wild Growth\n1 Winds of Rath\n1 Yenna, Redtooth Regent\n1 Sythis, Harvest's Hand"
|
||||
|
||||
|
||||
func _bulk_callback(cache) -> void:
|
||||
cache.setup()
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
var cache = _caching.new()
|
||||
add_child(cache)
|
||||
|
||||
|
||||
if cache.setup() != OK:
|
||||
cache.fetch_done.connect(_bulk_callback.bind(cache))
|
||||
# TODO: Create 2-4 player instances as children of this tabletop node.
|
||||
@ -22,12 +23,11 @@ func _ready() -> void:
|
||||
var player = player_class.new()
|
||||
add_child(player)
|
||||
move_child(player, 0)
|
||||
|
||||
|
||||
cache.get_card_data_from_name("1996 World Champion")
|
||||
|
||||
var deck = deck_input.new(cards)
|
||||
add_child(deck)
|
||||
|
||||
|
||||
# var deck = deck_input.new(cards)
|
||||
# add_child(deck)
|
||||
|
||||
pass # Replace with function body.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user