aboutsummaryrefslogtreecommitdiff
path: root/source/30-game/Player.cpp
blob: 34c454968da78b35f361abd1312784c8af618d97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "Player.hpp"

#include "AppConfig.hpp"
#include "CommonVertexIndex.hpp"
#include "ScopeGuard.hpp"
#include "Utils.hpp"

#include <cstdio>
#include <cstdlib>

// Keep the same number as # of fields in `struct {}` in PlayerKeyBinds
constexpr int kPlayerKeyBindCount = 4;

// Here be dragons: this treats consecutive fiels as an array, technically UB
std::span<int> PlayerKeyBinds::GetKeyArray() {
	return { &keyLeft, kPlayerKeyBindCount };
}
std::span<bool> PlayerKeyBinds::GetKeyStatusArray() {
	return { &pressedLeft, kPlayerKeyBindCount };
}

Player::Player(GameWorld* world, int id)
	: GameObject(KD_Player, world)
	, mId{ id } {
	renderObject.SetMaterial(gDefaultMaterial.Get());
	renderObject.SetFormat(gVformatStandard.Get(), Tags::IT_16Bit);
	renderObject.RebuildIfNecessary();
}

void Player::Awaken() {
	LoadFromFile();
}

void Player::Resleep() {
	SaveToFile();
}

void Player::Update() {
	using namespace Tags;

	if (keybinds.pressedLeft) {
	}
	if (keybinds.pressedRight) {
	}

	// TODO jump controller

	// TODO attack controller

	// TODO set default sprite to get rid of this check
	if (sprite.GetDefinition()) {
		int prevFrame = sprite.GetFrame();
		sprite.PlayFrame();
		int currFrame = sprite.GetFrame();
		if (prevFrame != currFrame) {
			uint16_t indices[6];
			Index_U16::Assign(indices, 0);
			renderObject.GetIndexBuffer()->Upload((const std::byte*)indices, IT_16Bit, std::size(indices));

			Vertex_PTC vertices[4];
			Vertex_PTC::Assign(vertices, Rect<float>{ GetPos(), sprite.GetDefinition()->GetBoundingBox() });
			Vertex_PTC::Assign(vertices, 0.0f);
			Vertex_PTC::Assign(vertices, RgbaColor(255, 255, 255));
			Vertex_PTC::Assign(vertices, sprite.GetFrameSubregion());
			renderObject.GetVertexBufferBindings().bindings[0]->Upload((const std::byte*)vertices, sizeof(vertices));
		}
	}
}

Material* Player::GetMaterial() const {
	return renderObject.GetMaterial();
}

void Player::SetMaterial(Material* material) {
	renderObject.SetMaterial(material);
	renderObject.RebuildIfNecessary();
}

std::span<const RenderObject> Player::GetRenderObjects() const {
	return { &renderObject, 1 };
}

void Player::HandleKeyInput(int key, int action) {
	bool pressed;
	if (action == GLFW_PRESS) {
		pressed = true;
	} else if (action == GLFW_REPEAT) {
		return;
	} else /* action == GLFW_RELEASE */ {
		pressed = false;
	}

	for (int i = 0; i < kPlayerKeyBindCount; ++i) {
		int kbKey = keybinds.GetKeyArray()[i];
		bool& kbStatus = keybinds.GetKeyStatusArray()[i];

		if (kbKey == key) {
			kbStatus = pressed;
			break;
		}
	}
}

#pragma push_macro("PLAYERKEYBINDS_DO_IO")
#undef PLAYERKEYBINDS_DO_IO
#define PLAYERKEYBINDS_DO_IO(function, fieldPrefix)              \
	function(file, "left=%d\n", fieldPrefix keybinds.keyLeft);   \
	function(file, "right=%d\n", fieldPrefix keybinds.keyRight); \
	function(file, "jump=%d\n", fieldPrefix keybinds.keyJump);   \
	function(file, "attack=%d\n", fieldPrefix keybinds.keyAttack);

static FILE* OpenPlayerConfigFile(Player* player, Utils::IoMode mode) {
	char path[2048];
	snprintf(path, sizeof(path), "%s/player%d.txt", AppConfig::dataDir.c_str(), player->GetId());

	return Utils::OpenCstdioFile(path, mode);
}

bool Player::LoadFromFile() {
	auto file = OpenPlayerConfigFile(this, Utils::Read);
	if (!file) return false;
	DEFER { fclose(file); };

	// TODO input validation
	PLAYERKEYBINDS_DO_IO(fscanf, &);

	return true;
}

bool Player::SaveToFile() {
	auto file = OpenPlayerConfigFile(this, Utils::WriteTruncate);
	if (!file) return false;
	DEFER { fclose(file); };

	PLAYERKEYBINDS_DO_IO(fprintf, );

	return true;
}
#pragma pop_macro("PLAYERKEYBINDS_DO_IO")