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_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:
|
||||
print("Attempting auth.")
|
||||
await attempt_auth()
|
||||
print("Attempting to create debug match.")
|
||||
await create_and_join_debug_match()
|
||||
nakama_socket.received_match_state.connect(self._on_match_state)
|
||||
|
||||
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:
|
||||
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():
|
||||
print("An error occurred when joining debug BR match: %s" % response)
|
||||
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
|
||||
|
||||
[libraries]
|
||||
linux.debug.x86_64 = "res://../godot_wrapper/target/debug/libgodot_wrapper.so"
|
||||
linux.release.x86_64 = "res://../godot_wrapper/target/release/libgodot_wrapper.so"
|
||||
windows.debug.x86_64 = "res://../godot_wrapper/target/debug/godot_wrapper.dll"
|
||||
windows.release.x86_64 = "res://../godot_wrapper/target/release/godot_wrapper.dll"
|
||||
macos.debug = "res://../godot_wrapper/target/debug/libgodot_wrapper.dylib"
|
||||
macos.release = "res://../godot_wrapper/target/release/libgodot_wrapper.dylib"
|
||||
macos.debug.arm64 = "res://../godot_wrapper/target/debug/libgodot_wrapper.dylib"
|
||||
macos.release.arm64 = "res://../godot_wrapper/target/release/libgodot_wrapper.dylib"
|
||||
linux.debug.x86_64 = "res://../godot-extension/target/release/libgodot_extension.so"
|
||||
linux.release.x86_64 = "res://../godot-extension/target/release/libgodot_extension.so"
|
||||
windows.debug.x86_64 = "res://../godot-extension/target/release/godot_extension.dll"
|
||||
windows.release.x86_64 = "res://../godot-extension/target/release/godot_extension.dll"
|
||||
macos.debug = "res://../godot-extension/target/release/libgodot_extension.dylib"
|
||||
macos.release = "res://../godot-extension/target/release/libgodot_extension.dylib"
|
||||
macos.debug.arm64 = "res://../godot-extension/target/release/libgodot_extension.dylib"
|
||||
macos.release.arm64 = "res://../godot-extension/target/release/libgodot_extension.dylib"
|
||||
|
|
@ -18,3 +18,9 @@ config/icon="res://icon.svg"
|
|||
[autoload]
|
||||
|
||||
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
|
||||
if tick%20 == 0 {
|
||||
if tick%1 == 0 {
|
||||
for _, v := range lobbyState.presences {
|
||||
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(
|
||||
C.uint8_t(BULLET_LINEAR),
|
||||
C.int64_t(tick),
|
||||
C.double(STAGE_WIDTH*rand.Float64()),
|
||||
C.double(STAGE_HEIGHT*rand.Float64()),
|
||||
C.double(vel),
|
||||
C.double(vel),
|
||||
C.double(float64(vel_x_sign)*vel),
|
||||
C.double(float64(vel_y_sign)*vel),
|
||||
)
|
||||
|
||||
var x, y C.double
|
||||
|
|
@ -175,8 +177,8 @@ func (m *BattleRoyaleMatch) MatchLoop(ctx context.Context, logger runtime.Logger
|
|||
"tick": tick,
|
||||
"x": float64(x),
|
||||
"y": float64(y),
|
||||
"vel_x": vel,
|
||||
"vel_y": vel,
|
||||
"vel_x": float64(vel_x_sign) * vel,
|
||||
"vel_y": float64(vel_y_sign) * vel,
|
||||
}
|
||||
|
||||
data, err := json.Marshal(bulletData)
|
||||
|
|
|
|||
Reference in a new issue