Compare commits

...

5 Commits

Author SHA1 Message Date
9cf1956770
impl camera 2024-02-24 23:26:54 -05:00
162fc09baa
impl field 2024-02-24 23:26:28 -05:00
91d06311db
basic player 2024-02-24 23:26:24 -05:00
a42c93ff6b
basic player 2024-02-24 23:25:32 -05:00
5d2158fcaf
Asset Loader 2024-02-24 23:25:07 -05:00
12 changed files with 412 additions and 0 deletions

6
.gitignore vendored
View File

@ -1,2 +1,8 @@
.DS_Store
# Godot 4+ specific ignores
.godot/
export_presets.cfg
/AuthKey_VSYTQ75GZQ.p8

70
AssetLoaders/Enums.gd Normal file
View File

@ -0,0 +1,70 @@
class_name Enums
enum TileID {
TileVoid = 0,
TileBlank = 1,
TileHome = 2,
TileBattle = 3,
TileDraw = 4,
TileBonus = 5,
TileDrop = 6,
TileWarp = 7,
TileDrawx2 = 8,
TileBonusx2 = 9,
TileDropx2 = 10,
TileFlatWall = 11,
TileVoid2 = 12, # i'm not sure why there's 8 voids, or if they're even used
TileVoid3 = 13,
TileVoid4 = 14,
TileVoid5 = 15,
TileVoid6 = 16,
TileVoid7 = 17,
TileDeck = 18,
TileVoid8 = 19,
TileBattlex2 = 20,
TileMove = 21,
TileMovex2 = 22,
TileWarpMove = 23,
TileWarpMovex2 = 24,
TileIce = 25,
TileSnow = 26,
TileHeal = 27,
TileHealx2 = 28,
TileEvent = 29, # OJEdit says "Event (Blank Tile)"
TileUnknown = 30,
TileCoopBoss = 31,
TileDamage = 32,
TileDamagex2 = 33
}
static func get_tile_texture(id: int):
match id:
0: return ""
1: return "mass_common0.dat"
2: return "mass_check0.dat"
3: return "mass_encount0.dat"
4: return "mass_draw0.dat"
5: return "mass_bonus0.dat"
6: return "mass_drop0.dat"
7: return "mass_warp0.dat"
8: return "mass_drawL2.dat"
9: return "mass_bonusL2.dat"
10: return "mass_dropL2.dat"
11: return "mass_common0.dat"
12, 13, 14, 15, 16, 17: return ""
18: return "mass_editordeck.dat"
19: return ""
20: return "mass_encountL2.dat"
21: return "mass_move0.dat"
22: return "mass_moveL2.dat"
23: return "mass_warpmove0.dat"
24: return "mass_warpmoveL2.dat"
25: return "mass_snow0.dat"
26: return "mass_snow0.dat"
27: return "mass_heal0.dat"
28: return "mass_healL2.dat"
29: return "mass_common0.dat"
30: return "mass_common0.dat"
31: return "mass_boss.dat"
32: return "mass_damage.dat"
33: return "mass_damageL2.dat"

View File

@ -0,0 +1,99 @@
class_name PakAssetLoader
static var key = "a8Yb5$IpVobR,1Xph!k(#!B9h$V[o[r-I'x.37Q%E;lt2wGgk)hNF_p_!mF?Ds54.*8ErbCK,30".to_utf8_buffer()
#loads a file from a .pak file.
static func load_file(path: String):
var split = path.split(".pak/")
var pak = split[0]
var filename = split[1]
var zip_reader = ZIPReader.new()
var err = zip_reader.open(pak + ".pak")
if err != OK:
report_errors(err, pak + ".pak")
zip_reader.close()
var bytes = zip_reader.read_file(filename)
zip_reader.close()
if bytes.size() == 0:
report_errors(ERR_FILE_NOT_FOUND, filename)
if filename.ends_with(".dat"):
var magic = bytes[0]+bytes[1]+bytes[2]+bytes[3]
if magic == 0x25 + 0x7C + 0x0A + 0x42: #XOR'ed DDS file
unXOR(bytes)
magic = bytes[0]+bytes[1]+bytes[2]+bytes[3]
if magic == 0x44 + 0x44 + 0x53 + 0x20: #DDS file
var header = bytes.slice(0, 0x80)
bytes = bytes.slice(0x80)
var height = header[0xc] + (header[0xd] * 256)
var width = header[0x10] + (header[0x11] * 256)
var format = header[0x54]+header[0x55]+header[0x56]+header[0x57]
if format == 0:
fix_BGRA(bytes)
var img = Image.create_from_data(width, height, false, Image.FORMAT_RGBA8, bytes)
return ImageTexture.create_from_image(img)
elif format == 0x44 + 0x58 + 0x54 + 0x35:
var img = Image.create_from_data(width, height, false, Image.FORMAT_DXT5, bytes)
return ImageTexture.create_from_image(img)
else:
report_errors(ERR_FILE_UNRECOGNIZED, filename)
return
else:
report_errors(ERR_FILE_UNRECOGNIZED, filename)
return
elif filename.ends_with(".ogg"):
var magic = bytes[0]+bytes[1]+bytes[2]+bytes[3]
if magic == 0x4F + 0x67 + 0x67 + 0x53:
var stream = AudioStreamOggVorbis.load_from_buffer(bytes)
stream.loop = true
stream.loop_offset = get_loop_off(filename)
return stream
else:
report_errors(ERR_FILE_UNRECOGNIZED, filename)
elif filename.ends_with(".fld"):
return bytes
static func fix_BGRA(bytes: PackedByteArray):
for i in range(0, bytes.size(), 4):
var tmp = bytes[i]
bytes[i] = bytes[i+2]
bytes[i+2] = tmp
static func unXOR(bytes: PackedByteArray):
for i in range(bytes.size()):
bytes[i] ^= key[i % key.size()]
static func get_loop_off(filename: String):
match filename:
"bgm/0.ogg":
return 1.72
"bgm/1.ogg":
return 2
static func report_errors(err: int, filepath):
# See: https://docs.godotengine.org/en/latest/classes/class_@globalscope.html#enum-globalscope-error
var result_hash = {
ERR_FILE_NOT_FOUND: "File: not found",
ERR_FILE_BAD_DRIVE: "File: Bad drive error",
ERR_FILE_BAD_PATH: "File: Bad path error.",
ERR_FILE_NO_PERMISSION: "File: No permission error.",
ERR_FILE_ALREADY_IN_USE: "File: Already in use error.",
ERR_FILE_CANT_OPEN: "File: Can't open error.",
ERR_FILE_CANT_WRITE: "File: Can't write error.",
ERR_FILE_CANT_READ: "File: Can't read error.",
ERR_FILE_UNRECOGNIZED: "File: Unrecognized error.",
ERR_FILE_CORRUPT: "File: Corrupt error.",
ERR_FILE_MISSING_DEPENDENCIES: "File: Missing dependencies error.",
ERR_FILE_EOF: "File: End of file (EOF) error."
}
if err in result_hash:
print("Error: ", result_hash[err], " ", filepath)
else:
print("Unknown error with file ", filepath, " error code: ", err)

53
Field/field.gd Normal file
View File

@ -0,0 +1,53 @@
extends Node2D
var width: int
var height: int
var tiles: Array = []
var x = 1
var homes
var next_home
func _init():
var bytes = PakAssetLoader.load_file("user://data/fields.pak/field_practice.fld")
create_from_buffer(bytes)
# Called when the node enters the scene tree for the first time.
func _ready():
homes = tiles.filter(is_home)
$Player.position = homes[0].position
next_home = homes[1].position
homes = [homes[0], homes[1], homes[3], homes[2]]
pass
func is_home(tile):
return tile.id == Enums.TileID.TileHome
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
if $Player.position != next_home:
$Player.position = $Player.position.move_toward(next_home, 4)
else:
x += 1
next_home = homes[x % 4].position
pass
func create_from_buffer(bytes: PackedByteArray):
var num_tiles = bytes.size() / 8
# all boards are square
height = int(sqrt(num_tiles))
width = int(sqrt(num_tiles))
var j = 0;
for i in range(0, num_tiles):
var tile = load("res://Field/tile.tscn").instantiate()
tile.id = bytes.decode_u32(i * 8)
var exit_bits = bytes.decode_u8((i * 8) + 4)
add_child.call_deferred(tile)
tile.position = Vector2(((i % width) * 158) + 64, (j * 158) + 64)
tiles.append(tile)
if i % height == height - 1:
j += 1
#print(bytes)
pass

11
Field/field.tscn Normal file
View File

@ -0,0 +1,11 @@
[gd_scene load_steps=4 format=3 uid="uid://qipfodwbk1gf"]
[ext_resource type="Script" path="res://Field/field.gd" id="1_6uvjw"]
[ext_resource type="PackedScene" uid="uid://sp3iv6cxuerm" path="res://player.tscn" id="2_oi7aa"]
[ext_resource type="Script" path="res://Player/player.gd" id="3_vsc2e"]
[node name="Field" type="Node2D"]
script = ExtResource("1_6uvjw")
[node name="Player" parent="." instance=ExtResource("2_oi7aa")]
script = ExtResource("3_vsc2e")

26
Field/tile.gd Normal file
View File

@ -0,0 +1,26 @@
extends Node2D
var id: Enums.TileID
var enter: Array
var exit: Array
# Called when the node enters the scene tree for the first time.
func _ready():
var tex = Enums.get_tile_texture(id)
if tex != "":
$Sprite2D.texture = PakAssetLoader.load_file("user://data/field.pak/" + tex)
$Base.texture = PakAssetLoader.load_file("user://data/field.pak/mass_base0.dat")
# if id == Enums.TileID.TileIce:
# var layer = Sprite2D.new()
# var snow = Enums.get_tile_texture(Enums.TileID.TileSnow)
# layer.texture = PakAssetLoader.load_file("user://data/field.pak/" + snow)
# layer.flip_v = true
# print($Sprite2D.z_index)
# $Sprite2D.add_child(layer)
# layer.show_behind_parent = true
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

14
Field/tile.tscn Normal file
View File

@ -0,0 +1,14 @@
[gd_scene load_steps=2 format=3 uid="uid://b8vsmp8c1wqv6"]
[ext_resource type="Script" path="res://Field/tile.gd" id="1_kltr3"]
[node name="Tile" type="Node2D"]
script = ExtResource("1_kltr3")
[node name="Base" type="Sprite2D" parent="."]
scale = Vector2(1.45, 1.45)
flip_v = true
[node name="Sprite2D" type="Sprite2D" parent="."]
scale = Vector2(1.2, 1.2)
flip_v = true

View File

@ -0,0 +1,42 @@
extends Camera2D
class_name PanningCamera2D
@export var MIN_ZOOM: float = 0.5
@export var MAX_ZOOM: float = 3.0
@export var ZOOM_RATE: float = 8.0
@export var ZOOM_INCREMENT: float = 0.1
var target_zoom: float = 1.0
var reset_pos: Vector2 = Vector2(0.0, 0.0)
func _physics_process(delta: float) -> void:
zoom = lerp(zoom, target_zoom * Vector2.ONE, ZOOM_RATE * delta)
set_physics_process(not is_equal_approx(zoom.x, target_zoom))
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseButton:
if event.is_pressed():
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
zoom_in()
if event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
zoom_out()
if event is InputEventMouseMotion:
if event.button_mask == MOUSE_BUTTON_MASK_LEFT:
position -= event.relative / zoom
if event is InputEventKey:
if event.keycode == KEY_SPACE:
target_zoom = 1.0
zoom = Vector2(1.0, 1.0)
position = reset_pos
func zoom_in() -> void:
target_zoom = max(target_zoom - ZOOM_INCREMENT, MIN_ZOOM)
set_physics_process(true)
func zoom_out() -> void:
target_zoom = min(target_zoom + ZOOM_INCREMENT, MAX_ZOOM)
set_physics_process(true)

24
Player/player.gd Normal file
View File

@ -0,0 +1,24 @@
extends Node2D
var yvel = 1
var yoff = 0
# Called when the node enters the scene tree for the first time.
func _ready():
$Sprite2D.texture = PakAssetLoader.load_file("user://data/units.pak/tomomo_00_00.dat")
$Sprite2D.position = get_global_transform().origin
$Sprite2D.position.y -= 128
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
var pos = get_global_transform().origin
pos.y += -128 + yoff
yvel -= 1
if yvel < -9:
yvel = 9
pos.y += yvel
yoff += yvel
$Sprite2D.position = pos

13
Player/player.tscn Normal file
View File

@ -0,0 +1,13 @@
[gd_scene load_steps=2 format=3 uid="uid://dtm0201qhcn4d"]
[ext_resource type="Script" path="res://player.gd" id="1_6ggpr"]
[node name="Player" type="Node2D"]
z_index = 1
script = ExtResource("1_6ggpr")
metadata/_edit_group_ = true
[node name="Sprite2D" type="Sprite2D" parent="."]
top_level = true
z_index = 2
position = Vector2(2.08165e-12, -128)

16
main.tscn Normal file
View File

@ -0,0 +1,16 @@
[gd_scene load_steps=3 format=3 uid="uid://djirenq1psstj"]
[ext_resource type="Script" path="res://PanningCamera/PanningCamera2D.gd" id="1_vtapg"]
[ext_resource type="PackedScene" uid="uid://qipfodwbk1gf" path="res://Field/field.tscn" id="1_y0qkv"]
[node name="Main" type="Node2D"]
[node name="Camera2D" type="Camera2D" parent="."]
script = ExtResource("1_vtapg")
MIN_ZOOM = null
MAX_ZOOM = null
ZOOM_RATE = 5.0
[node name="Field" parent="." instance=ExtResource("1_y0qkv")]
rotation = 0.523599
skew = 0.523599

38
player.tscn Normal file
View File

@ -0,0 +1,38 @@
[gd_scene load_steps=2 format=3 uid="uid://sp3iv6cxuerm"]
[sub_resource type="GDScript" id="GDScript_hd04s"]
script/source = "extends Node2D
var yvel = 1
var yoff = 0
# Called when the node enters the scene tree for the first time.
func _ready():
$Sprite2D.texture = PakAssetLoader.load_file(\"user://data/units.pak/tomomo_00_00.dat\")
$Sprite2D.position = get_global_transform().origin
$Sprite2D.position.y -= 128
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
var pos = get_global_transform().origin
pos.y += -128 + yoff
yvel -= 1
if yvel < -9:
yvel = 9
pos.y += yvel
yoff += yvel
$Sprite2D.position = pos
"
[node name="Player" type="Node2D"]
z_index = 1
script = SubResource("GDScript_hd04s")
metadata/_edit_group_ = true
[node name="Sprite2D" type="Sprite2D" parent="."]
top_level = true
z_index = 2
position = Vector2(2.08165e-12, -128)