add working checkpoint and finish with timer
This commit is contained in:
parent
d120c82ff6
commit
36296d9b39
7 changed files with 208 additions and 89 deletions
|
@ -39,7 +39,6 @@ target_position = Vector2(256, 128)
|
|||
collision_mask = 2
|
||||
|
||||
[node name="resetTimer" type="Timer" parent="CharacterBody_Car"]
|
||||
wait_time = 2.0
|
||||
one_shot = true
|
||||
|
||||
[node name="RayCast_Car" type="RayCast2D" parent="CharacterBody_Car"]
|
||||
|
|
|
@ -7,26 +7,48 @@ script = ExtResource("1_7syh4")
|
|||
|
||||
[node name="hud" type="CanvasLayer" parent="."]
|
||||
|
||||
[node name="speedlabel" type="Label" parent="hud"]
|
||||
[node name="debuglabel" type="Label" parent="hud"]
|
||||
z_index = 8
|
||||
offset_left = 38.0
|
||||
offset_top = 541.0
|
||||
offset_right = 454.0
|
||||
offset_bottom = 586.0
|
||||
theme_override_font_sizes/font_size = 32
|
||||
offset_left = 14.0
|
||||
offset_top = 535.0
|
||||
offset_right = 430.0
|
||||
offset_bottom = 580.0
|
||||
theme_override_font_sizes/font_size = 20
|
||||
text = "adsf"
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="speedlabel2" type="Label" parent="hud"]
|
||||
[node name="timer" type="Label" parent="hud"]
|
||||
z_index = 8
|
||||
offset_left = 40.0
|
||||
offset_top = 582.0
|
||||
offset_right = 456.0
|
||||
offset_bottom = 627.0
|
||||
theme_override_font_sizes/font_size = 32
|
||||
text = "adsf"
|
||||
offset_left = 17.0
|
||||
offset_top = 562.0
|
||||
offset_right = 433.0
|
||||
offset_bottom = 631.0
|
||||
theme_override_font_sizes/font_size = 50
|
||||
text = "0.000"
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="countdown_label" type="Label" parent="hud"]
|
||||
offset_left = 604.0
|
||||
offset_top = 312.0
|
||||
offset_right = 644.0
|
||||
offset_bottom = 342.0
|
||||
theme_override_font_sizes/font_size = 50
|
||||
text = "3"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="times_container" type="HFlowContainer" parent="hud"]
|
||||
offset_left = 29.0
|
||||
offset_top = 29.0
|
||||
offset_right = 69.0
|
||||
offset_bottom = 69.0
|
||||
|
||||
[node name="Camera2D" type="Camera2D" parent="."]
|
||||
|
||||
[node name="cars" type="Node" parent="."]
|
||||
|
||||
[node name="countdown" type="Timer" parent="."]
|
||||
wait_time = 3.0
|
||||
one_shot = true
|
||||
|
||||
[connection signal="timeout" from="countdown" to="." method="_on_countdown_timeout"]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=6 format=4 uid="uid://dghq8c8asg7h1"]
|
||||
[gd_scene load_steps=9 format=4 uid="uid://dghq8c8asg7h1"]
|
||||
|
||||
[ext_resource type="TileSet" uid="uid://beswbm12qkkxk" path="res://sprites/spritesheet_road/bg_road.tres" id="2_i1338"]
|
||||
[ext_resource type="TileSet" uid="uid://buu8w8n61kbxf" path="res://sprites/spritesheet_road/markings.tres" id="3_ktygs"]
|
||||
|
@ -8,7 +8,16 @@
|
|||
tile_size = Vector2i(128, 128)
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_daqun"]
|
||||
size = Vector2(23, 106.5)
|
||||
size = Vector2(23, 222)
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_dltky"]
|
||||
size = Vector2(19, 108)
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_uys5r"]
|
||||
size = Vector2(20, 126)
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_82iti"]
|
||||
size = Vector2(20, 231)
|
||||
|
||||
[node name="Map" type="Node"]
|
||||
|
||||
|
@ -45,22 +54,30 @@ tile_set = ExtResource("4_r58io")
|
|||
collision_layer = 4
|
||||
collision_mask = 4
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="area_finish"]
|
||||
position = Vector2(89.5, -0.5)
|
||||
[node name="CollisionShape2D_Fin" type="CollisionShape2D" parent="area_finish"]
|
||||
position = Vector2(89.5, -1)
|
||||
shape = SubResource("RectangleShape2D_daqun")
|
||||
|
||||
[node name="area_cp0" type="Area2D" parent="."]
|
||||
collision_layer = 4
|
||||
collision_mask = 4
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="area_cp0"]
|
||||
position = Vector2(278, 575)
|
||||
shape = SubResource("RectangleShape2D_dltky")
|
||||
|
||||
[node name="area_cp1" type="Area2D" parent="."]
|
||||
collision_layer = 4
|
||||
collision_mask = 4
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="area_cp1"]
|
||||
position = Vector2(267, 575.5)
|
||||
shape = SubResource("RectangleShape2D_daqun")
|
||||
position = Vector2(194, 840)
|
||||
shape = SubResource("RectangleShape2D_uys5r")
|
||||
|
||||
[node name="area_cp2" type="Area2D" parent="."]
|
||||
collision_layer = 4
|
||||
collision_mask = 4
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="area_cp2"]
|
||||
position = Vector2(235, 833.75)
|
||||
shape = SubResource("RectangleShape2D_daqun")
|
||||
position = Vector2(-384, 0)
|
||||
shape = SubResource("RectangleShape2D_82iti")
|
||||
|
|
|
@ -2,6 +2,7 @@ extends CharacterBody2D
|
|||
|
||||
#Tutorial: https://www.youtube.com/watch?v=mJ1ZfGDTMCY t=15s
|
||||
|
||||
signal car_finished(playerid,finalTime)
|
||||
|
||||
const COLLISIONMASK_FINISH=3 #set in road_overlay
|
||||
const COLLISIONMASK_CHECKPOINT=4 #set in road_overlay
|
||||
|
@ -12,16 +13,21 @@ var checkpointtimes :Array[float]=[]
|
|||
const ROAD_R_NAME="road_r"
|
||||
const ROAD_L_NAME="road_l"
|
||||
|
||||
|
||||
const COLLISION_SLOWDOWN_CAR=1.01
|
||||
const COLLISION_SLOWDOWN_WALL=1.2
|
||||
|
||||
|
||||
const STANDSTILLSPEED=0.5
|
||||
var wheel_base = 60*0.5
|
||||
|
||||
var engine_power = 350
|
||||
var engine_power = 500
|
||||
|
||||
var friction = -0.5
|
||||
var drag = -0.0005
|
||||
var braking = -200
|
||||
var max_speed_reverse = 100
|
||||
var slip_speed = 200
|
||||
var slip_speed = 100
|
||||
var traction_fast = 0.1 #traction when above slip_speed
|
||||
var traction_slow = 0.5
|
||||
|
||||
|
@ -46,6 +52,7 @@ var resetcar_steerangle=120
|
|||
|
||||
|
||||
#Variables
|
||||
var running=false
|
||||
var acceleration = Vector2.ZERO
|
||||
|
||||
var steer_direction=0
|
||||
|
@ -64,10 +71,11 @@ var autosteer_enabled=false
|
|||
@onready var collision_enable_timer: Timer = $collisionEnableTimer
|
||||
|
||||
var playerid=0
|
||||
var finalTime=-1
|
||||
|
||||
func _ready() -> void:
|
||||
collision_shape.disabled=true #disable collisions on start. also to avoid collision when initially setting position
|
||||
|
||||
finalTime=-1
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
|
@ -80,6 +88,14 @@ func _physics_process(delta: float) -> void:
|
|||
#velocity = transform.x * 200
|
||||
#vel = move_and_slide()
|
||||
move_and_slide()
|
||||
|
||||
for i in get_slide_collision_count():
|
||||
var collision = get_slide_collision(i)
|
||||
#if $".".name==collision.get_collider().name: #collided with another car
|
||||
# velocity-=COLLISION_SLOWDOWN_CAR
|
||||
if ROAD_R_NAME==collision.get_collider().name or ROAD_L_NAME==collision.get_collider().name: #collided with road
|
||||
velocity/=COLLISION_SLOWDOWN_WALL
|
||||
|
||||
if get_slide_collision_count()>0:
|
||||
velocity/=2
|
||||
#for i in get_slide_collision_count():
|
||||
|
@ -95,7 +111,6 @@ func _physics_process(delta: float) -> void:
|
|||
|
||||
|
||||
func _on_reset_timer_timeout() -> void:
|
||||
print("resetting car")
|
||||
autoreset=true
|
||||
|
||||
func apply_friction():
|
||||
|
@ -143,6 +158,7 @@ func get_input():
|
|||
steer_direction=0 #drive straight
|
||||
|
||||
# Manual steering here
|
||||
'''
|
||||
var turn = 0
|
||||
if Input.is_action_pressed("ui_right"):
|
||||
turn += 1
|
||||
|
@ -150,26 +166,26 @@ func get_input():
|
|||
turn -= 1
|
||||
if turn!=0:
|
||||
steer_direction = turn*deg_to_rad(steering_angle)
|
||||
|
||||
'''
|
||||
|
||||
|
||||
|
||||
if Input.is_action_pressed("ui_up") or Input.is_action_pressed(Gamestate.userinput_prefix+str(playerid)):
|
||||
#velocity = transform.x * 500
|
||||
acceleration = transform.x * engine_power
|
||||
|
||||
if not autosteer_enabled: #start autosteer when accelerate is pressed
|
||||
autosteer_enabled=true
|
||||
collision_enable_timer.start()
|
||||
|
||||
if autoreset:
|
||||
print("Cancel autoreset")
|
||||
autoreset=false
|
||||
if Input.is_action_pressed("ui_down"):
|
||||
acceleration = transform.x * braking
|
||||
if running:
|
||||
if Input.is_action_pressed(Gamestate.userinput_prefix+str(playerid)):
|
||||
#velocity = transform.x * 500
|
||||
acceleration = transform.x * engine_power
|
||||
|
||||
if not autosteer_enabled: #start autosteer when accelerate is pressed
|
||||
autosteer_enabled=true
|
||||
collision_enable_timer.start()
|
||||
|
||||
if autoreset:
|
||||
print("Cancel autoreset")
|
||||
autoreset=false
|
||||
#if Input.is_action_pressed("ui_down"):
|
||||
#acceleration = transform.x * braking
|
||||
|
||||
|
||||
if autoreset:
|
||||
if autoreset and running:
|
||||
acceleration = transform.x * braking #drive backwards
|
||||
|
||||
if distance_min>=resetcar_distance: #nothing in front of car
|
||||
|
@ -210,28 +226,38 @@ func check_markers():
|
|||
#if ray_cast_car.get_collision_mask_value(COLLISIONMASK_CHECKPOINT):
|
||||
var rcc_collidername=ray_cast_car.get_collider().name
|
||||
if rcc_collidername=="area_finish":
|
||||
|
||||
var num_cp_collected=0
|
||||
for cpt in checkpointtimes:
|
||||
if cpt>0:
|
||||
num_cp_collected+=1
|
||||
#print("Player "+str(playerid)+" drove through Finish")
|
||||
if num_cp_collected==checkpointtimes.size():
|
||||
if getNextCPindex()==-1 and finalTime==-1: #all checkpoints have times and did not finish
|
||||
print("Player "+str(playerid)+" Finished")
|
||||
#TODO: get final time
|
||||
checkpointtimes.fill(0)
|
||||
elif rcc_collidername.begins_with("area_cp"):
|
||||
print("Final Time: "+str(Gamestate.getTimeElapsed()))
|
||||
running=false
|
||||
finalTime=Gamestate.getTimeElapsed()
|
||||
car_finished.emit(playerid,finalTime)
|
||||
|
||||
elif rcc_collidername.begins_with("area_cp"):
|
||||
var nextcp_i=getNextCPindex()
|
||||
var checkpoint_i=checkpoints.find(rcc_collidername)
|
||||
if checkpoint_i>=0 and checkpointtimes[checkpoint_i]==0: #found and no time for this cp yet
|
||||
checkpointtimes[checkpoint_i]=10 # TODO: set actual time here
|
||||
print("Player "+str(playerid)+" Checkpoint "+str(ray_cast_car.get_collider().name))
|
||||
if checkpoint_i>=0 and nextcp_i>=0: #found and there is a next checkpoint time free
|
||||
if (nextcp_i%checkpoints.size())==checkpoint_i: #this cp is next cp
|
||||
checkpointtimes[nextcp_i]=Gamestate.getTimeElapsed()
|
||||
print("Player "+str(playerid)+" Checkpoint "+str(ray_cast_car.get_collider().name))
|
||||
print("New CP array "+str(checkpointtimes))
|
||||
|
||||
func constrain(val,a,b):
|
||||
var vmin=min(a,b)
|
||||
var vmax=max(a,b)
|
||||
return min(vmax,max(vmin,val))
|
||||
|
||||
|
||||
func getNextCPindex():
|
||||
#returns index of first 0 value in times array
|
||||
#-1 if all cps have times
|
||||
#[10.2,15.5,12.2,0,0,0,0] -> 3
|
||||
var i=0
|
||||
for cpt in checkpointtimes:
|
||||
if cpt==0:
|
||||
return i
|
||||
i+=1
|
||||
return -1
|
||||
|
||||
func _on_collision_enable_timer_timeout() -> void:
|
||||
collision_shape.disabled=false
|
||||
|
|
|
@ -16,9 +16,9 @@ func setPlayerinformation(playerid, playercolor):
|
|||
cbcar.playerid=playerid
|
||||
carbody.modulate = playercolor
|
||||
|
||||
func setCheckpoints(cps):
|
||||
func setCheckpoints(cps,rounds):
|
||||
cbcar.checkpoints=cps
|
||||
cbcar.checkpointtimes.resize(cps.size())
|
||||
cbcar.checkpointtimes.resize(cps.size()*rounds)
|
||||
cbcar.checkpointtimes.fill(0.0)
|
||||
|
||||
func move_and_slide():
|
||||
|
@ -28,3 +28,12 @@ func printDebug():
|
|||
for i in cbcar.get_slide_collision_count():
|
||||
var collision = cbcar.get_slide_collision(i)
|
||||
print(""+str(cbcar.playerid)+" Collided with: "+ str( collision.get_collider().name)+" pid="+str(collision.get_collider().playerid)+" pos="+str(collision.get_collider().position))
|
||||
|
||||
func setRunning(r:bool):
|
||||
cbcar.running=r
|
||||
|
||||
func getCharacterBody():
|
||||
return cbcar
|
||||
|
||||
func hasFinished():
|
||||
return cbcar.finalTime!=-1
|
||||
|
|
|
@ -1,22 +1,31 @@
|
|||
extends Node2D
|
||||
|
||||
@onready var camera: Camera2D = $Camera2D
|
||||
#@onready var car: Node2D = $car_0
|
||||
@onready var countdown: Timer = $countdown
|
||||
@onready var countdown_label: Label = $hud/countdown_label
|
||||
|
||||
@onready var cars: Node = $cars
|
||||
@onready var times_container: HFlowContainer = $hud/times_container
|
||||
|
||||
const caroffset= 32+4 #space cars on start line
|
||||
|
||||
var viewCarMargin=Vector2(0.05,0.05) #proportions of viewsize. 0,0 = adjust when cars are outside view, 1,1=infinite zoom out
|
||||
var viewCarMargin_zoomstart=viewCarMargin+Vector2(0.2,0.2)
|
||||
var zoomspeed=0.5
|
||||
var zoomspeed_backup=0.1
|
||||
var viewCarMargin=Vector2(0.1,0.1) #proportions of viewsize. 0,0 = adjust when cars are outside view, 1,1=infinite zoom out
|
||||
var viewCarMargin_zoomstart=viewCarMargin+Vector2(0.05,0.05)
|
||||
var zoomspeed=1.0
|
||||
var zoomspeed_backup=0.2
|
||||
var zoom_normal=2
|
||||
const CAMERA_POSITION_SPEED=0.98 #0.0 - 1.0, higher=faster
|
||||
|
||||
var running=false
|
||||
|
||||
var rounds=3
|
||||
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
|
||||
countdown.start()
|
||||
countdown_label.visible=true
|
||||
|
||||
#Load Map
|
||||
#var num_checkpoints=0
|
||||
|
@ -40,7 +49,8 @@ func _ready() -> void:
|
|||
newcarinstance.setPlayerinformation(i,player.color)
|
||||
|
||||
newcarinstance.setPosition(Vector2(0,ceil(i/2.0)*(fmod(i,2)-0.5)*2.0*caroffset))
|
||||
newcarinstance.setCheckpoints(checkpoints)
|
||||
newcarinstance.setCheckpoints(checkpoints,rounds)
|
||||
newcarinstance.getCharacterBody().car_finished.connect(_on_car_finished)
|
||||
|
||||
|
||||
#print("Position car "+str(i)+" = "+str(ceil(i/2.0)*(fmod(i,2)-0.5)*2.0*caroffset))
|
||||
|
@ -51,34 +61,46 @@ func _ready() -> void:
|
|||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
if running:
|
||||
Gamestate.addTimeElapsed(delta)
|
||||
if !countdown.is_stopped():
|
||||
countdown_label.text=str(round(countdown.time_left))
|
||||
|
||||
var cars=cars.get_children()
|
||||
var meanCarPosition=Vector2.ZERO
|
||||
var displayedCarCount=0
|
||||
var maxCarSpeed=0
|
||||
var minPos=Vector2.ZERO #min/max x and y position of all cars
|
||||
var maxPos=Vector2.ZERO
|
||||
|
||||
var oneDriving=false
|
||||
for c in cars: #check if any one car is still driving
|
||||
if !c.hasFinished():
|
||||
oneDriving=true
|
||||
|
||||
for c in cars:
|
||||
var carpos = c.getPosition()
|
||||
meanCarPosition+=carpos
|
||||
|
||||
maxCarSpeed=max(maxCarSpeed,c.getSpeed())
|
||||
if displayedCarCount==0:
|
||||
minPos.x=carpos.x
|
||||
minPos.y=carpos.y
|
||||
maxPos.x=carpos.x
|
||||
maxPos.y=carpos.y
|
||||
else:
|
||||
minPos.x=min(minPos.x,carpos.x)
|
||||
minPos.y=min(minPos.y,carpos.y)
|
||||
maxPos.x=max(maxPos.x,carpos.x)
|
||||
maxPos.y=max(maxPos.y,carpos.y)
|
||||
|
||||
displayedCarCount+=1
|
||||
if !c.hasFinished() or !oneDriving:
|
||||
var carpos = c.getPosition()
|
||||
meanCarPosition+=carpos
|
||||
|
||||
maxCarSpeed=max(maxCarSpeed,c.getSpeed())
|
||||
if displayedCarCount==0:
|
||||
minPos.x=carpos.x
|
||||
minPos.y=carpos.y
|
||||
maxPos.x=carpos.x
|
||||
maxPos.y=carpos.y
|
||||
else:
|
||||
minPos.x=min(minPos.x,carpos.x)
|
||||
minPos.y=min(minPos.y,carpos.y)
|
||||
maxPos.x=max(maxPos.x,carpos.x)
|
||||
maxPos.y=max(maxPos.y,carpos.y)
|
||||
|
||||
displayedCarCount+=1
|
||||
|
||||
meanCarPosition/=displayedCarCount
|
||||
|
||||
#camera.position=car.getPosition()
|
||||
camera.position=meanCarPosition
|
||||
camera.position=lerp(camera.position,meanCarPosition,CAMERA_POSITION_SPEED*delta)
|
||||
#rint("zoom = "+str(camera.zoom))
|
||||
#camera.zoom=Vector2(1.5,1.5)
|
||||
|
||||
|
@ -103,14 +125,8 @@ func _process(delta: float) -> void:
|
|||
if camera.zoom.x<zoom_normal:
|
||||
camera.zoom+=Vector2(zoomspeed_backup*delta,zoomspeed_backup*delta)
|
||||
|
||||
$hud/speedlabel.text=str(camera.zoom.x)
|
||||
$hud/speedlabel.text=str(calculatedViewCarMargin)
|
||||
#$hud/speedlabel2.text=str(viewsize.x)
|
||||
|
||||
|
||||
|
||||
#$Camera2D/speedlabel.text=str(round(maxCarSpeed))
|
||||
|
||||
$hud/debuglabel.text=""
|
||||
$hud/timer.text=str(round(Gamestate.getTimeElapsed()*1000)/1000.0)
|
||||
|
||||
|
||||
|
||||
|
@ -137,3 +153,22 @@ func constrain(val,a,b):
|
|||
var vmin=min(a,b)
|
||||
var vmax=max(a,b)
|
||||
return min(vmax,max(vmin,val))
|
||||
|
||||
|
||||
func _on_countdown_timeout() -> void:
|
||||
running=true
|
||||
var cars=cars.get_children()
|
||||
for c in cars:
|
||||
c.setRunning(true)
|
||||
countdown_label.visible=false
|
||||
|
||||
func _on_car_finished(playerid,finalTime) -> void:
|
||||
print("Finished "+str(playerid)+" final time="+str(finalTime))
|
||||
var place=times_container.get_child_count()+1
|
||||
print("New Label. Place "+str(place))
|
||||
var newlabel= Label.new()
|
||||
times_container.add_child(newlabel)
|
||||
newlabel.set("theme_override_font_sizes/font_size",40)
|
||||
newlabel.text=str(place)+": "+str(round(finalTime*1000)/1000.0)+"s"
|
||||
newlabel.set("theme_override_colors/font_color",Gamestate.getPlayers()[playerid].color)
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ var players: Array[Player] = []
|
|||
|
||||
var userinput_prefix="inputP"
|
||||
|
||||
var time_elapsed=0
|
||||
|
||||
func addPlayer(key:int):
|
||||
if not getPlayerkeys().has(key):
|
||||
#playerkeys.append(key)
|
||||
|
@ -43,3 +45,12 @@ class Player:
|
|||
print("i is "+str(i)+" h="+str(fmod(0.3*i,1.0))+" assigned color "+str(color))
|
||||
|
||||
|
||||
func startGame():
|
||||
for player in players:
|
||||
player.setRunning(true)
|
||||
|
||||
func addTimeElapsed(delta):
|
||||
time_elapsed+=delta
|
||||
|
||||
func getTimeElapsed():
|
||||
return time_elapsed
|
||||
|
|
Loading…
Reference in a new issue