Working shared linear integrator, visualized on client
This commit is contained in:
parent
972ab12c64
commit
f85469dad4
8 changed files with 127 additions and 52 deletions
|
|
@ -4,14 +4,61 @@ var nakama_client: NakamaClient
|
||||||
var nakama_session: NakamaSession
|
var nakama_session: NakamaSession
|
||||||
var nakama_socket: NakamaSocket
|
var nakama_socket: NakamaSocket
|
||||||
|
|
||||||
|
const SERVER_WIDTH = 90.0
|
||||||
|
const SERVER_HEIGHT = 160.0
|
||||||
|
|
||||||
|
var predicted_tick = 0
|
||||||
|
var delta_counter = 0
|
||||||
|
var lerp_factor := 0.0
|
||||||
|
var bullets = []
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
print("Attempting auth.")
|
print("Attempting auth.")
|
||||||
await attempt_auth()
|
await attempt_auth()
|
||||||
print("Attempting to create debug match.")
|
print("Attempting to create debug match.")
|
||||||
await create_and_join_debug_match()
|
await create_and_join_debug_match()
|
||||||
|
nakama_socket.received_match_state.connect(self._on_match_state)
|
||||||
|
|
||||||
func _process(delta: float) -> void:
|
func _process(delta: float) -> void:
|
||||||
pass
|
delta_counter += delta
|
||||||
|
|
||||||
|
if delta_counter >= 0.05:
|
||||||
|
predicted_tick += 1
|
||||||
|
delta_counter = 0 # Reset counter
|
||||||
|
lerp_factor = delta_counter / 0.05 # Normalize factor between 0 and 1
|
||||||
|
|
||||||
|
for bullet in bullets:
|
||||||
|
var prev_pos = bullet.get_current_pos(predicted_tick)
|
||||||
|
var next_pos = bullet.get_current_pos(predicted_tick + 1)
|
||||||
|
var interpolated_pos = prev_pos.lerp(next_pos, lerp_factor)
|
||||||
|
|
||||||
|
bullet.position = world_to_screen(interpolated_pos)
|
||||||
|
|
||||||
|
#var screen_size = get_viewport().size
|
||||||
|
#bullets = bullets.filter(func(bullet):
|
||||||
|
# return bullet.position.x >= 0 and bullet.position.x <= screen_size.x and \
|
||||||
|
# bullet.position.y >= 0 and bullet.position.y <= screen_size.y
|
||||||
|
#)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_match_state(p_state : NakamaRTAPI.MatchData):
|
||||||
|
match p_state.op_code:
|
||||||
|
2: # Spawn bullet
|
||||||
|
var data = JSON.parse_string(p_state.data)
|
||||||
|
var bullet = DanmakuBullet.new()
|
||||||
|
bullet.setup_bullet(
|
||||||
|
int(data["class"]),
|
||||||
|
int(data["tick"]),
|
||||||
|
data["x"],
|
||||||
|
data["y"],
|
||||||
|
data["vel_x"],
|
||||||
|
data["vel_y"])
|
||||||
|
bullet.position = world_to_screen(bullet.get_current_pos(int(data["tick"])))
|
||||||
|
bullet.texture = load("res://test-bullet.png")
|
||||||
|
add_child(bullet)
|
||||||
|
bullets.append(bullet)
|
||||||
|
delta_counter = 0
|
||||||
|
predicted_tick = int(data["tick"])
|
||||||
|
|
||||||
func attempt_auth() -> void:
|
func attempt_auth() -> void:
|
||||||
nakama_client = Nakama.create_client("defaultkey", "127.0.0.1", 7350, "http")
|
nakama_client = Nakama.create_client("defaultkey", "127.0.0.1", 7350, "http")
|
||||||
|
|
@ -36,3 +83,13 @@ func create_and_join_debug_match() -> void:
|
||||||
if debug_br_match.is_exception():
|
if debug_br_match.is_exception():
|
||||||
print("An error occurred when joining debug BR match: %s" % response)
|
print("An error occurred when joining debug BR match: %s" % response)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
func world_to_screen(server_pos: Vector2) -> Vector2:
|
||||||
|
var screen_size = get_viewport().size
|
||||||
|
var scale_x = screen_size.x / SERVER_WIDTH
|
||||||
|
var scale_y = screen_size.y / SERVER_HEIGHT
|
||||||
|
|
||||||
|
var client_x = server_pos.x * scale_x
|
||||||
|
var client_y = server_pos.y * scale_y
|
||||||
|
|
||||||
|
return Vector2(client_x, client_y)
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ compatibility_minimum = 4.1
|
||||||
reloadable = true
|
reloadable = true
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
linux.debug.x86_64 = "res://../godot_wrapper/target/debug/libgodot_wrapper.so"
|
linux.debug.x86_64 = "res://../godot-extension/target/release/libgodot_extension.so"
|
||||||
linux.release.x86_64 = "res://../godot_wrapper/target/release/libgodot_wrapper.so"
|
linux.release.x86_64 = "res://../godot-extension/target/release/libgodot_extension.so"
|
||||||
windows.debug.x86_64 = "res://../godot_wrapper/target/debug/godot_wrapper.dll"
|
windows.debug.x86_64 = "res://../godot-extension/target/release/godot_extension.dll"
|
||||||
windows.release.x86_64 = "res://../godot_wrapper/target/release/godot_wrapper.dll"
|
windows.release.x86_64 = "res://../godot-extension/target/release/godot_extension.dll"
|
||||||
macos.debug = "res://../godot_wrapper/target/debug/libgodot_wrapper.dylib"
|
macos.debug = "res://../godot-extension/target/release/libgodot_extension.dylib"
|
||||||
macos.release = "res://../godot_wrapper/target/release/libgodot_wrapper.dylib"
|
macos.release = "res://../godot-extension/target/release/libgodot_extension.dylib"
|
||||||
macos.debug.arm64 = "res://../godot_wrapper/target/debug/libgodot_wrapper.dylib"
|
macos.debug.arm64 = "res://../godot-extension/target/release/libgodot_extension.dylib"
|
||||||
macos.release.arm64 = "res://../godot_wrapper/target/release/libgodot_wrapper.dylib"
|
macos.release.arm64 = "res://../godot-extension/target/release/libgodot_extension.dylib"
|
||||||
|
|
@ -18,3 +18,9 @@ config/icon="res://icon.svg"
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
Nakama="*res://addons/com.heroiclabs.nakama/Nakama.gd"
|
Nakama="*res://addons/com.heroiclabs.nakama/Nakama.gd"
|
||||||
|
|
||||||
|
[importer_defaults]
|
||||||
|
|
||||||
|
animation_library={
|
||||||
|
"animation/fps": 120.0
|
||||||
|
}
|
||||||
|
|
|
||||||
BIN
client/test-bullet.png
Normal file
BIN
client/test-bullet.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 743 B |
41
godot-extension/src/bullet.rs
Normal file
41
godot-extension/src/bullet.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
use godot::prelude::*;
|
||||||
|
use shared::bullet::Bullet;
|
||||||
|
use godot::classes::{ Sprite2D, ISprite2D };
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Sprite2D)]
|
||||||
|
struct DanmakuBullet {
|
||||||
|
bullet_state: Bullet,
|
||||||
|
|
||||||
|
base: Base<Sprite2D>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl ISprite2D for DanmakuBullet {
|
||||||
|
fn init(base: Base<Sprite2D>) -> Self {
|
||||||
|
Self {
|
||||||
|
bullet_state: Bullet::new(0, 0, 0.0, 0.0, [0.0, 0.0]),
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl DanmakuBullet {
|
||||||
|
#[func]
|
||||||
|
fn setup_bullet(&mut self, class: u8, spawn_time: i64, spawn_x: f64, spawn_y: f64, param_x: f64, param_y: f64) {
|
||||||
|
self.bullet_state = Bullet::new(class, spawn_time, spawn_x, spawn_y, [param_x, param_y]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
fn get_current_pos(&self, tick: i64) -> Vector2 {
|
||||||
|
let (x, y) = self.bullet_state.get_current_pos(tick);
|
||||||
|
Vector2::new(x as f32, y as f32)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
fn beyond_kill_boundary(&self, tick: i64) -> bool {
|
||||||
|
self.bullet_state.beyond_kill_boundary(tick)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
use godot::prelude::*;
|
|
||||||
|
|
||||||
use shared::bullet::Bullet;
|
|
||||||
|
|
||||||
#[derive(GodotClass)]
|
|
||||||
#[class(base=RefCounted)]
|
|
||||||
struct DanmakuBullet {
|
|
||||||
bullet_state: Bullet,
|
|
||||||
|
|
||||||
base: Base<RefCounted>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[godot_api]
|
|
||||||
impl BulletWrapper {
|
|
||||||
#[func]
|
|
||||||
fn new(class: u8, spawn_time: i64, spawn_x: f64, spawn_y: f64, parameters: [f64; 2]) -> Self {
|
|
||||||
Self {
|
|
||||||
bullet_state: Bullet::new(class, spawn_time, spawn_x, spawn_y, parameters),
|
|
||||||
base: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[func]
|
|
||||||
fn get_current_pos(&self, tick: i64) -> (f64, f64) {
|
|
||||||
self.bullet_state.get_current_pos(tick)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[func]
|
|
||||||
fn beyond_kill_boundary(&self, tick: i64) -> bool {
|
|
||||||
self.bullet_state.beyond_kill_boundary(tick)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BulletExtension;
|
|
||||||
|
|
||||||
#[gdextension]
|
|
||||||
unsafe impl ExtensionLibrary for BulletExtension {}
|
|
||||||
|
|
@ -1 +1,7 @@
|
||||||
mod godot;
|
mod bullet;
|
||||||
|
|
||||||
|
use godot::prelude::*;
|
||||||
|
struct Danmaku;
|
||||||
|
|
||||||
|
#[gdextension]
|
||||||
|
unsafe impl ExtensionLibrary for Danmaku {}
|
||||||
|
|
@ -154,17 +154,19 @@ func (m *BattleRoyaleMatch) MatchLoop(ctx context.Context, logger runtime.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test bullet spawning
|
// Test bullet spawning
|
||||||
if tick%20 == 0 {
|
if tick%1 == 0 {
|
||||||
for _, v := range lobbyState.presences {
|
for _, v := range lobbyState.presences {
|
||||||
vel := rand.Float64()*(STAGE_WIDTH/float64(lobbyState.tickRate)) + 1.0
|
vel := rand.Float64()*(STAGE_WIDTH/float64(lobbyState.tickRate)) + 1.0
|
||||||
|
vel_x_sign := 2*rand.Intn(2) - 1
|
||||||
|
vel_y_sign := 2*rand.Intn(2) - 1
|
||||||
|
|
||||||
bullet := C.new_bullet(
|
bullet := C.new_bullet(
|
||||||
C.uint8_t(BULLET_LINEAR),
|
C.uint8_t(BULLET_LINEAR),
|
||||||
C.int64_t(tick),
|
C.int64_t(tick),
|
||||||
C.double(STAGE_WIDTH*rand.Float64()),
|
C.double(STAGE_WIDTH*rand.Float64()),
|
||||||
C.double(STAGE_HEIGHT*rand.Float64()),
|
C.double(STAGE_HEIGHT*rand.Float64()),
|
||||||
C.double(vel),
|
C.double(float64(vel_x_sign)*vel),
|
||||||
C.double(vel),
|
C.double(float64(vel_y_sign)*vel),
|
||||||
)
|
)
|
||||||
|
|
||||||
var x, y C.double
|
var x, y C.double
|
||||||
|
|
@ -175,8 +177,8 @@ func (m *BattleRoyaleMatch) MatchLoop(ctx context.Context, logger runtime.Logger
|
||||||
"tick": tick,
|
"tick": tick,
|
||||||
"x": float64(x),
|
"x": float64(x),
|
||||||
"y": float64(y),
|
"y": float64(y),
|
||||||
"vel_x": vel,
|
"vel_x": float64(vel_x_sign) * vel,
|
||||||
"vel_y": vel,
|
"vel_y": float64(vel_y_sign) * vel,
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := json.Marshal(bulletData)
|
data, err := json.Marshal(bulletData)
|
||||||
|
|
|
||||||
Reference in a new issue