Adding initial prototype 2
This commit is contained in:
266
proto2/ai/ball_game_ai.gd
Normal file
266
proto2/ai/ball_game_ai.gd
Normal file
@@ -0,0 +1,266 @@
|
||||
extends Node
|
||||
class_name BallGameAI
|
||||
|
||||
var _ball: PackedScene
|
||||
var _cheers = {}
|
||||
var _game_area: Rect2
|
||||
var _teams = {}
|
||||
var _main
|
||||
var _state = STATE_INIT
|
||||
var _ball_instance
|
||||
var _cheer_locations = {}
|
||||
var _team_start = {}
|
||||
var _ball_carrier = null
|
||||
var _ball_team = -1
|
||||
var ch2team: Dictionary = {}
|
||||
var gate2team = {}
|
||||
var _gates = {}
|
||||
var _scores = {}
|
||||
|
||||
enum {STATE_INIT, STATE_START, STATE_RUNNING, STATE_FINISH}
|
||||
func _ready():
|
||||
_game_area = Rect2()
|
||||
func set_ball(ball: PackedScene):
|
||||
_ball = ball
|
||||
func add_player(team: int, pl: Dictionary):
|
||||
if !_teams.has(team):
|
||||
_teams[team] = [pl]
|
||||
else:
|
||||
_teams[team].push_back(pl)
|
||||
assert pl != null
|
||||
ch2team[pl.scene] = team
|
||||
func add_cheer(team: int, ch: Dictionary):
|
||||
if !_cheers.has(team):
|
||||
_cheers[team] = [ch]
|
||||
else:
|
||||
_cheers[team].push_back(ch)
|
||||
assert ch != null
|
||||
ch2team[ch.scene] = team
|
||||
func add_cheer_game_location(team: int, loc: Vector2):
|
||||
if !_cheer_locations.has(team):
|
||||
_cheer_locations[team] = [loc]
|
||||
else:
|
||||
_cheer_locations[team].push_back(loc)
|
||||
_game_area = _game_area.expand(loc)
|
||||
func set_team_start(team: int, v: Vector2):
|
||||
_team_start[team] = v
|
||||
_game_area = _game_area.expand(v)
|
||||
func set_team_gate(team: int, gate: Area2D):
|
||||
_gates[team] = gate
|
||||
gate2team[gate] = team
|
||||
gate.connect("body_entered", self, "check_goal", [gate])
|
||||
_game_area = _game_area.expand(gate.global_position)
|
||||
func set_main(n):
|
||||
_main = n
|
||||
func start_game():
|
||||
var ball = _ball.instance()
|
||||
_main.add_child(ball)
|
||||
ball.global_position = world.master_node.global_position + Vector2(randf() - 0.5, randf() - 0.5) * 20.0
|
||||
ball.add_to_group("ball")
|
||||
_state = STATE_START
|
||||
for t in _teams.keys():
|
||||
for ch in _teams[t]:
|
||||
ch.scene.walkto(_team_start[t])
|
||||
var loc = 0
|
||||
for t in _cheers.keys():
|
||||
for ch in _cheers[t]:
|
||||
ch.scene.walkto(_cheer_locations[t][loc % _cheer_locations[t].size()])
|
||||
loc += 1
|
||||
_ball_instance = ball
|
||||
for t in _teams.keys():
|
||||
_scores[t] = 0
|
||||
func stop_game():
|
||||
for k in get_tree().get_nodes_in_group("ball"):
|
||||
k.queue_free()
|
||||
_state = STATE_INIT
|
||||
var max_score = -1
|
||||
var winner_team = -1
|
||||
for k in _scores.keys():
|
||||
if _scores[k] > max_score:
|
||||
max_score = _scores[k]
|
||||
winner_team = k
|
||||
if winner_team >= 0:
|
||||
for e in _teams[winner_team]:
|
||||
world.increase_xp(e, min(e.xp * 2, min(100 * e.level, 1000)))
|
||||
for e in _cheers[winner_team]:
|
||||
world.increase_xp(e, min(e.xp * 2, min(200 * e.level, 2000)))
|
||||
|
||||
var base_speed = 300.0
|
||||
func striker(ch: Dictionary, delta: float) -> Vector2:
|
||||
var velocity: Vector2 = Vector2()
|
||||
var dir = Vector2()
|
||||
if _ball_carrier == null:
|
||||
dir = _ball_instance.global_position - ch.scene.global_position
|
||||
else:
|
||||
dir = _ball_carrier.scene.global_position - ch.scene.global_position
|
||||
velocity = dir.normalized() * base_speed * ch.speed
|
||||
return velocity
|
||||
func avoid(ch: Dictionary, delta: float) -> Vector2:
|
||||
var velocity: Vector2 = Vector2()
|
||||
var vel_plus = Vector2()
|
||||
var team = ch2team[ch.scene]
|
||||
var ch_pos = ch.scene.global_position
|
||||
for t in _teams.keys():
|
||||
if t == team:
|
||||
continue
|
||||
for other in _teams[t]:
|
||||
var opos = other.scene.global_position
|
||||
var lvec = ch_pos - opos
|
||||
vel_plus += lvec
|
||||
velocity = vel_plus.normalized() * base_speed * ch.speed * (1.0 + ch.agression)
|
||||
return velocity
|
||||
func attack_gate(ch: Dictionary, delta: float) -> Vector2:
|
||||
var velocity: Vector2 = Vector2()
|
||||
var team = ch2team[ch.scene]
|
||||
var dir = _gates[team ^ 1].global_position - ch.scene.global_position
|
||||
if dir.length() > 80:
|
||||
velocity = dir.normalized() * base_speed * ch.speed * (1.0 + ch.agression)
|
||||
elif dir.length() > 40:
|
||||
velocity = dir.normalized() * base_speed * ch.speed * 0.6 * (1.0 + ch.agression)
|
||||
elif dir.length() > 25:
|
||||
velocity = dir.normalized() * base_speed * ch.speed * 0.25 * (1.0 + ch.agression)
|
||||
return velocity
|
||||
|
||||
var catch_delay = 0.0
|
||||
func catch_ball(pl):
|
||||
_ball_instance.kinematic = true
|
||||
_ball_instance.new_parent = pl.scene
|
||||
_ball_instance.update = true
|
||||
_ball_instance.impulse = Vector2()
|
||||
_ball_carrier = pl
|
||||
var max_imp = 500.0
|
||||
func drop_ball(pl):
|
||||
assert _main != null
|
||||
_ball_instance.kinematic = false
|
||||
_ball_instance.new_parent = _main
|
||||
_ball_instance.update = true
|
||||
_ball_instance.impulse = _ball_carrier.scene.velocity * _ball_instance.mass * (1.5 + randf() * 10.0)
|
||||
if _ball_instance.impulse.length() > max_imp:
|
||||
_ball_instance.impulse = _ball_instance.impulse.normalized() * max_imp
|
||||
_ball_carrier = null
|
||||
func check_goal(body, gate):
|
||||
print("check")
|
||||
if _state == STATE_RUNNING:
|
||||
var team = gate2team[gate]
|
||||
if body is RigidBody2D:
|
||||
if body == _ball_instance:
|
||||
_scores[team] += 1
|
||||
elif body is KinematicBody2D && _ball_carrier != null:
|
||||
print("check2")
|
||||
if body == _ball_carrier.scene:
|
||||
world.increase_xp(_ball_carrier, 150)
|
||||
_scores[team] += 1
|
||||
catch_delay += 3.0
|
||||
drop_ball(_ball_carrier)
|
||||
print(_scores)
|
||||
func colliding(delta):
|
||||
var close_distance2 = 450.0
|
||||
var chars = {}
|
||||
for t in _teams.keys():
|
||||
for e in _teams[t]:
|
||||
chars[e.scene] = e
|
||||
for t in _cheers.keys():
|
||||
for e in _cheers[t]:
|
||||
chars[e.scene] = e
|
||||
for p in chars.keys():
|
||||
var pos1 = chars[p].scene.global_position
|
||||
var v1 = chars[p].scene.velocity
|
||||
var strength = chars[p].strength
|
||||
if chars[p] == _ball_carrier:
|
||||
strength *= 5.0
|
||||
for m in chars.keys():
|
||||
if p == m:
|
||||
continue
|
||||
var pos2 = chars[m].scene.global_position
|
||||
var dist = pos1.distance_squared_to(pos2)
|
||||
var v2 = chars[m].scene.velocity
|
||||
if dist < close_distance2:
|
||||
if v1.dot(v2) < 0:
|
||||
if strength > chars[m].strength:
|
||||
chars[p].scene.velocity = chars[p].scene.velocity.linear_interpolate((v1 + v2) * 0.5, delta)
|
||||
chars[m].scene.velocity = chars[p].scene.velocity.linear_interpolate((v1 + v2) * 0.5, delta)
|
||||
else:
|
||||
chars[p].scene.velocity = Vector2()
|
||||
elif v1.dot(v2) >= 0:
|
||||
if v1.length() > v2.length():
|
||||
if strength > chars[m].strength:
|
||||
chars[p].scene.velocity = chars[p].scene.velocity.linear_interpolate((v1 + v2) * 0.5, delta)
|
||||
chars[m].scene.velocity = chars[p].scene.velocity.linear_interpolate((v1 + v2) * 0.5, delta)
|
||||
|
||||
var start_delay = 15.0
|
||||
func _process(delta):
|
||||
match(_state):
|
||||
STATE_INIT:
|
||||
pass
|
||||
STATE_START:
|
||||
var ok_to_run = true
|
||||
for c in _teams.keys():
|
||||
for pl in _teams[c]:
|
||||
var ppos = pl.scene.global_position
|
||||
var bpos = _team_start[c]
|
||||
if ppos.distance_to(bpos) < 40:
|
||||
pl.scene.state = pl.scene.STATE_CONTROL
|
||||
elif ppos.distance_to(bpos) > 60 && pl.scene.state != pl.scene.STATE_CONTROL:
|
||||
ok_to_run = false
|
||||
if ok_to_run:
|
||||
_state = STATE_RUNNING
|
||||
for c in _teams.keys():
|
||||
for pl in _teams[c]:
|
||||
pl.scene.state = pl.scene.STATE_CONTROL
|
||||
else:
|
||||
if start_delay < 0.0:
|
||||
for c in _teams.keys():
|
||||
for pl in _teams[c]:
|
||||
var ppos = pl.scene.global_position
|
||||
var bpos = _team_start[c]
|
||||
if ppos.distance_to(bpos) > 60 && pl.scene.state != pl.scene.STATE_CONTROL:
|
||||
pl.scene.global_position = _team_start[c]
|
||||
for c in _cheers.keys():
|
||||
for pl in _cheers[c]:
|
||||
var ppos = pl.scene.global_position
|
||||
var bpos = pl.scene.destination
|
||||
if ppos.distance_to(bpos) > 60 && pl.scene.state != pl.scene.STATE_CONTROL:
|
||||
pl.scene.global_position = _team_start[c]
|
||||
else:
|
||||
start_delay -= delta
|
||||
STATE_RUNNING:
|
||||
for c in _teams.keys():
|
||||
for pl in _teams[c]:
|
||||
assert pl.scene != null
|
||||
if !_ball_carrier || (pl != _ball_carrier && _ball_team != c):
|
||||
var velocity = striker(pl, delta)
|
||||
velocity = pl.scene.velocity.linear_interpolate(velocity, 0.3 * delta)
|
||||
# velocity = pl.scene.move_and_slide(velocity)
|
||||
pl.scene.velocity = velocity
|
||||
elif _ball_carrier && _ball_carrier == pl:
|
||||
var velocity = avoid(pl, delta) * 0.3 + attack_gate(pl, delta) * 0.7
|
||||
velocity = pl.scene.velocity.linear_interpolate(velocity, 0.6 * delta)
|
||||
# velocity = pl.scene.move_and_slide(velocity)
|
||||
pl.scene.velocity = velocity
|
||||
if _ball_carrier == null && pl.scene.global_position.distance_squared_to(_ball_instance.global_position) < 350 * (1.0 + pl.agression):
|
||||
if catch_delay <= 0.0:
|
||||
catch_ball(pl)
|
||||
_ball_team = c
|
||||
world.increase_xp(pl, 50)
|
||||
elif _ball_carrier && pl != _ball_carrier && pl.scene.global_position.distance_squared_to(_ball_carrier.scene.global_position) < 350 * (1.0 + pl.agression):
|
||||
if pl.strength * (1.0 + pl.agression) > _ball_carrier.strength * 1.2 * (1.0 + _ball_carrier.agression):
|
||||
world.increase_xp(pl, 50)
|
||||
drop_ball(_ball_carrier)
|
||||
catch_delay += 5.0
|
||||
colliding(delta)
|
||||
for c in _teams.keys():
|
||||
for pl in _teams[c]:
|
||||
pl.scene.velocity = pl.scene.move_and_slide(pl.scene.velocity + Vector2(randf() - 0.5, randf() - 0.5) * 3.0)
|
||||
if !_game_area.has_point(_ball_instance.global_position):
|
||||
if !_ball_carrier:
|
||||
_ball_instance.queue_free()
|
||||
_ball_instance = _ball.instance()
|
||||
_main.add_child(_ball_instance)
|
||||
_ball_instance.global_position = world.master_node.global_position + Vector2(randf() - 0.5, randf() - 0.5) * 20.0
|
||||
_ball_instance.add_to_group("ball")
|
||||
catch_delay += 10.0
|
||||
else:
|
||||
drop_ball(_ball_carrier)
|
||||
catch_delay += 7.0
|
||||
if catch_delay > 0.0:
|
||||
catch_delay -= delta
|
||||
Reference in New Issue
Block a user