GodotФорумДемонстрируем наработки

Godot4 :: Царство и капитаны (2 стр)

Страницы: 1 2
#15
21:15, 23 мая 2024

Я пока буксую ...

Люди слухают музон..
https://www.youtube.com/watch?v=ORuMA7C0j3A

Люди что-то делают..

3D Action RPG Remastered Tutorial in Godot 4.2! 8 Hour Free Course!
https://www.youtube.com/watch?v=1m6UXCtw2Pg
Мистер "Coding Quests" учит - как сделать игру (видюшка на 8 часов).

Первые 20 минут - заряжаем набор три-мерных тайлов для GridMap.
Модельки взяты отсюда..
https://kaylousberg.itch.io/kaykit-adventurers
Под видео, есть подробный набор линков на ресурсы.

#16
23:25, 23 мая 2024

slatazan
А я ведь надо признаться, хоть мало что понимаю из твоих сообщений, но вдохновился твоей игрой.

И делаю походовую стратегию. Правда у меня сайфай.
Хотя тоже, на уровне мин прототипа подвис. Времени совсем нет.

#17
0:53, 24 мая 2024

Der FlugSimulator
// делаю походовую стратегию
Если есть тема - напечатай линк.
Если есть демо - могу поиграть-покритиковать.

Вот есть пошаговая игра..
Примерно с 10-й минуты идёт казуальная игра - вроде-бы, игроку понравилось.
https://www.youtube.com/watch?v=X2MYkCyQn7c
Как-минимум с 20-й по 30-ю минуту - можно посмотреть на трудный стартовый бой.

#18
11:55, 24 мая 2024

slatazan
> Если есть тема - напечатай линк.

Пока нет. Я вначале начал делать хексагонами, как у тебя, потом немного переделал.
Потом переделал еще и с очередностью ходов, создав тему.
В общем у меня пока всё в зачаточной стадии и даже не совсем собирается.

Но как только будет - сразу создам тему.

#19
23:38, 11 июня 2024

Кое-как собрал скрипт _игрока - некие базовые возможности.

ESC переключает курсор, и если курсор виден, то клик для указания _куда_бежать,
по полигонам нав-меша. Если не видно курсора - жмём кнопки, чтобы двигать
персонажа - ему мешаются ноды колизий, которые принимали участие в запеканиях
двух слоёв нав-меша (где пехота проходит, и где низкий полёт пролетает).

Надо напечатать код на форум, для сохранки :)

extends CharacterBody3D

# player
# ../Shape3D
# ../Knight[ ... AnimationPlayer]
# ../camera_base.h.v.Camera3D
# ../AnimationTree
# ../NavigationAgent3D

@onready var anim_tree = get_node( "AnimationTree")
@onready var playback = anim_tree.get( "parameters/playback")
@onready var pl_mesh = get_node( "Knight")
@onready var pl_mesh_cape = get_node( "Knight/Rig/Skeleton3D/Knight_Cape")
@onready var camera_h = get_node( "camera_base/h")
@onready var nav: NavigationAgent3D = get_node("NavigationAgent3D")


@export var gravity := 9.8
@export var jump_force: int = 9
@export var walk_speed: int = 8
@export var run_speed: int = 12


# state machine
var is_atk: bool = false # атакуем
var is_walk: bool = false
var is_run: bool = false # бежым
var is_death: bool = false # подыхаем

# anim Node Names
var nod_nam_idle : String = "Idle"
var nod_nam_walk : String = "Walk"
var nod_nam_run : String = "Run"
var nod_nam_jump : String = "Jump"
var nod_nam_atk1 : String = "Attack1"
var nod_nam_death : String = "Death_A"


# ---
const RAY_LENGTH = 1000
const JUMP_VELOCITY = 5.0


var movement_speed := 4.0 # сюда ставить скорость бега, или скорость шага.

var try_find_way := false
var test_is_fly := false
var klik_mouse_mode := 0

var ray_ignor_scn = null # test
var pillar_gltf = null




func _ready() -> void:
  nav.velocity_computed.connect( Callable( _on_velocity_computed))
  #ray_ignor_scn = get_node( "... /GridMap2")
  #pillar_gltf = get_node( "... /pillar/StaticBody3D")

  if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
    klik_mouse_mode = 1
#---------


func _on_velocity_computed( safe_velocity: Vector3):
  velocity = safe_velocity
  move_and_slide()
#---------



func _physics_process( delta):
  
  var on_floor = is_on_floor() # узнать - есть-ли контакт, с поверхностью.
  if not on_floor: # Если персонаж подвис, тогда..
    velocity.y -= gravity * delta # Add the gravity. // гравитация давит.

  #if not is_death -> pass

  if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
    if not klik_mouse_mode:
      klik_mouse_mode = 1
      # первый кадр, после переключения - сбросим старый путь..
      if not nav.is_navigation_finished():
        nav_target( self.position) # чтобы обнулить пре-поиск.
    #
    move_klik( delta) # тэстируем поинт-клик
  else:
    klik_mouse_mode = 0
    move_wasd( delta) # рулим движуху ... стрелочками


  if( nod_nam_atk1 in playback.get_current_node() ):
    is_atk = true
  else:
    is_atk = false
  attack1()

  anim_tree[ "parameters/conditions/IsOnFloor"] = on_floor
  anim_tree[ "parameters/conditions/IsInAir"] = ! on_floor
  anim_tree[ "parameters/conditions/IsWalk"] = is_walk
  anim_tree[ "parameters/conditions/IsNotWalk"] = ! is_walk
  anim_tree[ "parameters/conditions/IsRun"] = is_run
  anim_tree[ "parameters/conditions/IsNotRun"] = ! is_run
  anim_tree[ "parameters/conditions/IsDeath"] = is_death
#---------




func nav_target( movement_target: Vector3):
  nav.set_target_position( movement_target)
#---------


func nav_set_land( also_collision: int = 0):
  nav.set_navigation_layer_value( 1, true)
  nav.set_navigation_layer_value( 2, false)
  if also_collision:
    set_collision_mask_value( 1, true)
    set_collision_mask_value( 2, false)
#---------

func nav_set_fly( also_collision: int = 0):
  nav.set_navigation_layer_value( 1, false)
  nav.set_navigation_layer_value( 2, true)
  if also_collision:
    set_collision_mask_value( 1, false)
    set_collision_mask_value( 2, true)
#---------


func priv_may_toggle__alt_path() -> int:
  # Вызываем процу от сигнала - попытка сменить полёт-пехоту.
  # Сбрасываем нынешний путь - он сам сбросится.

  # Псевдо-клик, как будто под персонажа, и get_final_position(),
  # по хикс-зэд, должна быть совсем близко - тогда return 1;
  # Иначе - точка в другом слое плохо досягаема - сместись,
  # и снова переключай полёт-пехоту.

  if test_is_fly: # Сейчас - в полёте,
    nav_set_land() # и нужно проверить место посадки, в первом слое.
  else:
    nav_set_fly()
  nav_target( self.position)

  var v3 = nav.get_final_position()
  v3.y = self.position.y # выровним, чтобы в двумерке была дистанция..
  var a = v3.distance_to( self.position)
  #print( "alt_path dist: ", a)

  if test_is_fly: # Сейчас - в полёте, вернуть полётный слой..
    nav_set_fly()
  else:
    nav_set_land()
  nav_target( self.position) # чтобы обнулить пре-поиск.
  # Не знаю, как сбрасывать старый путь.

  #if a > 0.5:
  if a > 0.4: # слишком большой допуск,
    return 0 # и блокируем смену слоя.

  return 1 # разрешаем смену слоя - капсулу игрока авто-подвинут.
#---------




func attack1():

  if( nod_nam_idle in playback.get_current_node() ) or(
  nod_nam_walk in playback.get_current_node() ): # or(
  #nod_nam_run in playback.get_current_node() ): // нет атаки, при спринте.
    pass
    if Input.is_action_just_pressed( "attack1"):
      # Эту аниму можно назначить: кастинг сбора простой травы-руды.
      #print( "strike")
      if ! is_atk: # Если персонаж не занят атакой - пусть атакует.
        playback.travel( nod_nam_atk1) # включить аниму _атаки.

        # --- в целях тэста, добавка для переключения полёт-пехота..
        toggle_nav_land_fly()
#---------


func toggle_nav_land_fly():
  if priv_may_toggle__alt_path(): # Если можно переключать, тогда..
    if test_is_fly: # смотри старое // new --> пехота // первый слой.
      nav_set_land( 1)
      test_is_fly = false
      pl_mesh.position.y = 0.0
      pl_mesh_cape.hide()

    else: # // new --> полёт // ставим второй слой.
      nav_set_fly( 1)
      test_is_fly = true
      pl_mesh.position.y = 1.0
      pl_mesh_cape.show()
#---------
#20
23:39, 11 июня 2024
func move_wasd( delta):

  if Input.is_action_just_pressed( "ui_accept") and is_on_floor():
    velocity.y = JUMP_VELOCITY # прыгаем, если сигнал, и чувствуем опору.

  # Get the input direction and handle the movement/deceleration.
  # As good practice, you should replace UI actions with custom gameplay actions.
  var input_dir = Input.get_vector( "ui_left", "ui_right", "ui_up", "ui_down")
  var direction = (transform.basis * Vector3( input_dir.x, 0, input_dir.y)).normalized()
  if direction:
    #velocity.x = direction.x * SPEED
    #velocity.z = direction.z * SPEED
    # OR
    #var v1 = direction.rotated( Vector3( 0, 1.0, 0), deg_to_rad( camera_h.rotation.y))
    # оказалось, что не нужно конвертировать градусы в радианы ...
    # Почитал подсказку - действительно, градусная постановка - для удобства,
    # а свойство несёт радианы, когда работает.
    var v1 = direction.rotated( Vector3( 0, 1.0, 0), camera_h.rotation.y)
    velocity.x = v1.x * movement_speed
    velocity.z = v1.z * movement_speed
    var nt = get_node_or_null( "../CanvasLayer/Label")
    if nt:
      nt.text = "%1.1f  %1.1f  rot%1.1f" % [ v1.x, v1.z, camera_h.rotation.y]
    
    pl_mesh.rotation.y = camera_h.rotation.y + deg_to_rad( -180.0)

    walk_run( 1)
  else:
    walk_run( 0)
    velocity.x = move_toward( velocity.x, 0, movement_speed)
    velocity.z = move_toward( velocity.z, 0, movement_speed)

  move_and_slide()
#---------




var auto_shift := 0 # мало знаний про Анимашн, но хакнуть можно быстро.

func walk_run( move: int):
  var run_mode := false # выяснить (галочка или прижатый шыфт).
  #if Input.is_key_pressed( KEY_SHIFT): ...
  # Вероятно, персонаж всегда будет бегать. // но бег не анимируется _сразу,
  # и надо начинать с шага, чтобы анима бега подхватилась ...
  if auto_shift == 2:
    run_mode = true
  if move  and( auto_shift < 1): # 0
    auto_shift = 1
  else:
    auto_shift = 2
  #
  if Input.is_key_pressed( KEY_SHIFT): # чтобы шаг был доступен.
    run_mode = false


  is_walk = false
  is_run = false
  if run_mode:
    if move:
      is_run = true
    else:
      auto_shift = 0
    movement_speed = run_speed
  else:
    if move:
      is_walk = true
    else:
      auto_shift = 0
    movement_speed = walk_speed
  #
#---------




func _unhandled_input( event):
  if event is InputEventMouseButton and event.pressed and event.button_index == 1:
    try_find_way = true # оформить зацепку, которую перехватят в _physics_process
#---------




func move_klik( delta):

  if try_find_way:
    try_find_way = false
    var space_state = get_world_3d().direct_space_state
    var cam = get_node( "camera_base/h/v/Camera3D")
    var mousepos = get_viewport().get_mouse_position()

    var origin = cam.project_ray_origin( mousepos)
    var end = origin + cam.project_ray_normal( mousepos) * RAY_LENGTH
    var query = PhysicsRayQueryParameters3D.create( origin, end)
    query.collide_with_areas = true

    #query.exclude = self # [self, доп] # масив // игнорим свои колиз-шэйпы.
    #query.exclude = [ self, null] # так нельзя
    #query.exclude = [ self, ray_ignor_scn] # так не игнорят.
    # Попытки вытаскивать мешы в m_grid, и добавлять каждую вторую ячейку,
    # в масив ignor = игнор не работает по Мешам.
    # Зато стал работать по отдельному статик боди, который выташил
    # из отдельной заготовки. Значит, можно строить локацию хитрей,
    # чтобы столбы были отдельно (на снэпе - это повторит грид-мэп).
    # Можно делать почти плоские поляны-комнаты.
    # Есть кнопка PageDown для Node3D: ставит на пол - на первую опору.
    # Впрочем, кликать на стену, и думать о точке _за_стеной - это
    # не очевидно (для разных игроков). Класически - клик по стене - надо
    # бежать к основанию стены - так и происходит, если стену не игнорить.

    var ignor = []
    ignor.append( self) # игнорит, потому-что CharacterBody3D (тело).
    if pillar_gltf:
      ignor.append( pillar_gltf) # сработала указка на StaticBody3D (тело).
    query.exclude = ignor # передали масив игнорирований _тел.

    var result = space_state.intersect_ray( query) # узнали пересечение.

    nav_target( result.position) # приказали _навигатору найти путь.
    print( result.position) # Путь, примерно, к этой точке.

  elif nav.is_navigation_finished():
    walk_run( 0)
    return

  walk_run( 1)

  var next_p: Vector3 = nav.get_next_path_position()
  var new_v: Vector3 = global_position.direction_to( next_p) * movement_speed
  if nav.avoidance_enabled:
    nav.set_velocity( new_v)
    # Чуток потэстил - не хочу эту огибаловку использовать.
    # Пусть игроки и монстры пробегают сквозь друг-друга.
  else:
    _on_velocity_computed( new_v)

  var v1 = Vector3( 0, 0, 1) # позитивная единица, вместо негативной.
  var ug = v1.signed_angle_to( new_v, Vector3( 0, 1, 0))
  pl_mesh.rotation.y = ug
#---------

#.
#21
14:00, 12 июня 2024

slatazan
> Надо напечатать код на форум, для сохранки

Контроль версий не используешь что ли?
Я конечно не против, пиши, мог бы даже code review сделать, у тебя тут даже на поверхности совсем чудеса, но...

Всё таки это форум, тут бы лучше на человекопонятном языке писать ))

#22
23:58, 16 июня 2024

Der FlugSimulator
// Контроль версий
Угу, не использую. Считаю, что мне - повезёт :)

// совсем чудеса, в коде
Ну, не знаю. Геройчик бегает нормально.

Мини-скрипт, который для поворота камеры использую..

extends Node3D

var h_sens: float = 0.003 # 0.005 // карусель-поворот
var h_accel: float = 8.0 # малое значение - большая энэрция
var kh := 0.0
var kv := -35.0

func _ready():
  Input.set_mouse_mode( Input.MOUSE_MODE_CAPTURED)

func _input( e: InputEvent):

  if e is InputEventMouseMotion  and(
  Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED):
    kh += -e.relative.x * h_sens # карусель
    #kv += -e.relative.y * v_sens # кивок

  if e is InputEventKey:
    if e.is_action_pressed( "ui_cancel"):
      if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
        Input.set_mouse_mode( Input.MOUSE_MODE_CAPTURED)
      else:
        Input.set_mouse_mode( Input.MOUSE_MODE_VISIBLE)

func _physics_process( delta: float):
  var h = get_node( "h")
  h.rotation.y = lerpf( h.rotation.y, kh, h_accel * delta)
#23
22:34, 28 июня 2024

Добавка учитывания пустого поиска пересечения..

# player.gd :: move_klik
    var result = space_state.intersect_ray( query) # узнали пересечение.

    var r_pos = self.position # добавка кода.
    if result.is_empty():
      print( "ZERO intersect_ray")
    else:
      r_pos = result.position

    nav_target( r_pos) # приказали _навигатору найти путь.
    print( r_pos) # Путь, примерно, к этой точке.
#24
22:35, 28 июня 2024

// ---
Увлёкся гаражным декором. (изолента на руле ...)

Пытаюсь усвоить и адаптировать чужые заготовки полигонов.
У одного набора полигонов, зажатый цвет-материал.
Я не стал разбираться - сделал две добавочных папки,
где заменил все текстуры на тёмную, и на золотисто-блёклую.
В архиве, эти дубляжы полигонов - хорошо ужымаются - сойдёт подход.


Изображение

Обычная локация - маленькая, как зал-комната,
чтобы авто-оптимизация была.
Загружаем локацию - некоторые яшики бросают жребий,
чтобы сменить визуалку - некое разны-образие, и работа
заборчиками, и стенами. Накидать яшиков, везде ...
На скриншоте, перед серым рыцарем - большые яшики, как стена.

// Сумка и ярлыки - не работают.

Забавный шэйдэр мультяшного моря..
https://godotshaders.com/shader/wind-waker-water-no-textures-needed/

#25
22:36, 28 июня 2024
extends Node3D
# b_box_large_m_1 // сцена для создания стены.
# b_box_m_1 // сцена для заборчика.
#
# Внутри сцен, под этот скрипт, подразумеваю три пары яшиков - каждый
# из них, можно поворачивать по оси угрик.


@export var rot_deg_half := 0
# 0= не крутить карусель.
# 10= выбор градуса поворота, плюс-минус 10.
# Стараемся не ставить большых чисел.

@export var use_dekor := 0
# 0= random // умолчанка выставит разные визуальные кубики.
# 1= выставить пару первых яшиков.
# 2= вторая пара
# 3= третья пара
# else: невидимая колизия - не включаем визуалку яшиков.


var m1 = [ null, null, null]
var m2 = [ null, null, null]
var mr = [ 0, 90, 180, 270]

func _ready(): # при загрузке локаций

  if rot_deg_half < 0:
    rot_deg_half = 0
  if rot_deg_half > 30:
    rot_deg_half = 30

  m1[ 0] = get_node( "b1")
  m1[ 1] = get_node( "d1")
  m1[ 2] = get_node( "g1")

  m2[ 0] = get_node( "b2")
  m2[ 1] = get_node( "d2")
  m2[ 2] = get_node( "g2")

  var p1 = m1[ 0]
  var p2 = m2[ 0]
  p1.hide() # прячем изначальные яшики.
  p2.hide()

  if use_dekor == 0:
    p1 = m1[ g2.random( 0, 2)] # жребий от 0 до 2
    p2 = m2[ g2.random( 0, 2)]
  elif use_dekor == 2:
    p1 = m1[ 1]
    p2 = m2[ 1]
  elif use_dekor == 3:
    p1 = m1[ 2]
    p2 = m2[ 2]

  show_rot_box( p1, rot_deg_half)
  show_rot_box( p2, rot_deg_half)
#---------

func show_rot_box( a, do_r: int = 0):
  if do_r:
    var rot = mr[ g2.random( 0, 3)]
    if rot: # нуль оставляем без перемен, а остальное - шанс изменить.
      if g2.random( 0, 2):
        if g2.random( 0, 1):
          rot -= g2.random( 1, do_r)
        else:
          rot += g2.random( 1, do_r)
        #print( "box_rot: ", rot)
    a.rotation.y = deg_to_rad( rot)
  #
  if use_dekor < 4:
    a.show()
#---------
#26
15:33, 29 июня 2024

slatazan
> Забавный шэйдэр мультяшного моря..

Видел.
Мне он не очень. Я свой написал, сразу с плавучестью.

Страницы: 1 2
GodotФорумДемонстрируем наработки