Add in post-gamejam development

- Add SFX
- Add particle effects and Wall of Death
- Spice up the main menu
- Add difficulty scaling
- Rework wall and laser spawning and add variants
master
En Yi 2022-07-09 19:50:02 +08:00
parent 515def25be
commit 67f9ce9ae3
54 changed files with 1405 additions and 331 deletions

9
.gitignore vendored
View File

@ -1,4 +1,7 @@
build/
*.kra~
.import
.import/
*.kra*
*~
*.import
*.otf
*.ttf
build/

23
Effects.gd 100644
View File

@ -0,0 +1,23 @@
extends Node2D
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
var sweep = false
var sweep_speed = 1.5
var sweep_pos = 0
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
$WallOfDeath.position.x = 0
func _process(delta):
# Called every frame. Delta is time since last frame.
# Update game logic here.
if sweep:
$WallOfDeath.position.x = sweep_pos * 640
$blackout.material.set_shader_param("sweep_pos", sweep_pos)
sweep_pos+= sweep_speed*delta

20
Fade.gd 100644
View File

@ -0,0 +1,20 @@
extends Node2D
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
var alpha = 1
var fade_speed = 1
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
pass
func _process(delta):
# Called every frame. Delta is time since last frame.
# Update game logic here.
$fadeRect.material.set_shader_param("alpha",alpha)
alpha -= fade_speed * delta
if alpha < 0:
set_process(false)

BIN
Flat_white_icon.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,14 +1,26 @@
extends Node
const GRID_SIZE = 16
const LOWEST_GRID = 0
const HIGHEST_GRID = 30
const WALL_WIDTH = 64
const LASER_TIMER = 0.25 # This is the time for a frame of laser
const LASER_FRAMES = 4
# A laser has 4 frames, so a laser takes 1 second to fire.
var loading_game = false
var high_score = 0
var diff_level = 1
var start_level = 1
var level_duration = 15
var diff_level = start_level
var wall_difficulty = 1
var laser_difficulty = 1
var level_duration = 10
var return_to_menu = false
var playable = true

58
Ground.gd 100644
View File

@ -0,0 +1,58 @@
extends Node2D
var time = 0.0
export var n_lines = 5
export var x_offset_spd = 0.1
export var field_angle = 170.0
export var start_y = 0
export var growth = 0.1
export var alpha = 1.0
var end_y = ProjectSettings.get_setting("display/window/size/height")
var start_point
var start_x
var end_x
var draw_width
var x_increment
var y_dist
var x_offset = 0
func _ready():
start_point = Vector2(ProjectSettings.get_setting("display/window/size/width")/2, start_y)
y_dist = end_y - start_point.y
var half_width = y_dist/tan(deg2rad((180-field_angle)/2))
start_x = start_point.x - half_width
end_x = start_point.x + half_width
draw_width = 2*half_width
x_increment = draw_width / (n_lines + 1)
#set_physics_process(false)
func _physics_process(delta):
x_offset += x_offset_spd * delta
update()
func _draw():
var draw_x = start_x + x_offset
for i in range(n_lines+2):
draw_line(start_point, Vector2(draw_x,end_y), Color(1,1,1,alpha), 1.0, true)
draw_x += x_increment
if draw_x > end_x:
draw_x -= draw_width
if draw_x < start_x:
draw_x += draw_width
var i = 0
while true:
var draw_dist = prespective_transform(i)
if draw_dist > ProjectSettings.get_setting("display/window/size/height"):
break
draw_line(Vector2(0,draw_dist), Vector2(ProjectSettings.get_setting("display/window/size/width"),draw_dist),
Color(1,1,1,alpha), 1.0, true)
i+= 1
func prespective_transform(y):
#return A*y*y + B*y + start_point.y
return start_point.y + exp(y * growth)

16
Ground.tscn 100644
View File

@ -0,0 +1,16 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Ground.gd" type="Script" id=1]
[node name="Ground" type="Node2D" index="0"]
script = ExtResource( 1 )
_sections_unfolded = [ "Material", "Rect" ]
n_lines = 30
x_offset_spd = 250.0
field_angle = 178.0
start_y = 300
growth = 0.5
alpha = 0.2

View File

@ -2,13 +2,16 @@ extends AnimatedSprite
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
var n_lasers = 0
signal shoot(obj)
onready var spawn_sound = $spawn_sfx
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
pass
$Line2D.set_default_color(Color(1.0,1.0,0.0, 0))
$Timer.set_wait_time(Global.LASER_TIMER)
$Timer.start()
func place_obj(p1,p2,t):
$Tween.interpolate_property(self, "position:x",
@ -17,7 +20,12 @@ func place_obj(p1,p2,t):
func _on_Timer_timeout():
set_frame(frame +1)
var frac = float(frame)/4;
$Line2D.set_default_color(Color(frac,frac,frac*0.6))
$Line2D.set_width(frac * Global.GRID_SIZE)
$Line2D.update()
func _on_Laser_frame_changed():
if frame == 4:
emit_signal("shoot",self)
emit_signal("shoot",self,n_lasers)
get_tree().queue_delete(self)

View File

@ -1,10 +1,11 @@
[gd_scene load_steps=7 format=2]
[gd_scene load_steps=8 format=2]
[ext_resource path="res://art/laser_frames/laser_e1.png" type="Texture" id=1]
[ext_resource path="res://art/laser_frames/laser_e2.png" type="Texture" id=2]
[ext_resource path="res://art/laser_frames/laser_e3.png" type="Texture" id=3]
[ext_resource path="res://art/laser_frames/laser_e4.png" type="Texture" id=4]
[ext_resource path="res://Laser.gd" type="Script" id=5]
[ext_resource path="res://sfx/laser_charge.wav" type="AudioStream" id=6]
[sub_resource type="SpriteFrames" id=1]
@ -17,19 +18,22 @@ animations = [ {
[node name="Laser" type="AnimatedSprite"]
z_index = 1
frames = SubResource( 1 )
animation = "default"
script = ExtResource( 5 )
_sections_unfolded = [ "Z Index" ]
[node name="Timer" type="Timer" parent="." index="0"]
process_mode = 1
wait_time = 0.25
one_shot = false
autostart = true
autostart = false
[node name="Line2D" type="Line2D" parent="." index="1"]
modulate = Color( 1, 1, 1, 0.464078 )
position = Vector2( 15, 0 )
points = PoolVector2Array( -1000, 0, -32, 0 )
width = 2.0
@ -37,7 +41,7 @@ default_color = Color( 1, 1, 1, 1 )
texture_mode = -1082452802
sharp_limit = 2.0
round_precision = 8
_sections_unfolded = [ "Border", "Fill", "Transform" ]
_sections_unfolded = [ "Border", "Fill", "Transform", "Visibility" ]
[node name="Tween" type="Tween" parent="." index="2"]
@ -48,6 +52,15 @@ playback/active = false
playback/repeat = false
playback/speed = 1.0
[node name="spawn_sfx" type="AudioStreamPlayer" parent="." index="3"]
stream = ExtResource( 6 )
volume_db = -10.0
pitch_scale = 1.0
autoplay = true
mix_target = 0
bus = "Master"
[connection signal="frame_changed" from="." to="." method="_on_Laser_frame_changed"]
[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]

View File

@ -6,21 +6,26 @@ extends Area2D
onready var tween_node = $Tween
var active = true
var active_frames = 6;
var parts = null
signal kill_zone(body)
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
$activetimer.set_wait_time(active_frames/60)
$activetimer.set_wait_time(active_frames/60.0)
func _on_Tween_tween_completed(object, key):
if parts:
get_tree().queue_delete(parts)
get_tree().queue_delete(self)
func _on_Laser_obj_body_entered(body):
if active:
print(body)
emit_signal("kill_zone", body)
if body.is_in_group("players"):
if not body.invuln:
emit_signal("kill_zone", body)
func _on_activetimer_timeout():

View File

@ -10,6 +10,7 @@ extents = Vector2( 312, 6.43319 )
[node name="Laser_obj" type="Area2D"]
z_index = 1
input_pickable = true
gravity_vec = Vector2( 0, 1 )
gravity = 98.0
@ -18,6 +19,7 @@ angular_damp = 1.0
audio_bus_override = false
audio_bus_name = "Master"
script = ExtResource( 1 )
_sections_unfolded = [ "Z Index" ]
[node name="Sprite" type="Sprite" parent="." index="0"]

18
RunTimeInfo.gd 100644
View File

@ -0,0 +1,18 @@
extends VBoxContainer
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
pass
func _process(delta):
# Called every frame. Delta is time since last frame.
# Update game logic here.RENDER_VIDEO_MEM_USED
$FPSLabel.set_text("FPS: " + str(Performance.get_monitor(Performance.TIME_FPS)))
$NodeCount.set_text("Obj Node Count: " + str(Performance.get_monitor(Performance.OBJECT_NODE_COUNT)) + " ("+ str(Performance.OBJECT_COUNT) + ")")
$ResCount.set_text("Res Count: " + str(Performance.get_monitor(Performance.OBJECT_RESOURCE_COUNT)))
$VidMem.set_text("Video Memory: " + str(Performance.get_monitor(Performance.RENDER_VIDEO_MEM_USED)))

101
RunTimeInfo.tscn 100644
View File

@ -0,0 +1,101 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://RunTimeInfo.gd" type="Script" id=1]
[node name="RunTimeInfo" type="VBoxContainer"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 40.0
margin_bottom = 40.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 1
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
alignment = 0
script = ExtResource( 1 )
[node name="FPSLabel" type="Label" parent="." index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 40.0
margin_bottom = 14.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "FPS"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="NodeCount" type="Label" parent="." index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_top = 18.0
margin_right = 40.0
margin_bottom = 32.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "FPS"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="ResCount" type="Label" parent="." index="2"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_top = 36.0
margin_right = 40.0
margin_bottom = 50.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "FPS"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="VidMem" type="Label" parent="." index="3"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_top = 54.0
margin_right = 40.0
margin_bottom = 68.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "FPS"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1

19
Spiny.gd 100644
View File

@ -0,0 +1,19 @@
extends Sprite
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
export var lift = 10
export var sides = 10
var y_pos
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
y_pos = self.texture.get_height()/2-lift
update()
func _draw():
draw_line(Vector2(-self.texture.get_width()/2+sides, y_pos),
Vector2(self.texture.get_width()/2-sides, y_pos),
Color(0,0,0), 1.0, false)

View File

@ -1,6 +0,0 @@
extends Node2D
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
signal out_of_bound(wall);

View File

@ -1,61 +1,37 @@
[gd_scene load_steps=4 format=2]
[gd_scene load_steps=6 format=2]
[ext_resource path="res://wall.gd" type="Script" id=1]
[ext_resource path="res://art/wall.png" type="Texture" id=2]
[ext_resource path="res://sfx/wall_move.wav" type="AudioStream" id=3]
[ext_resource path="res://sfx/wall_stopped.wav" type="AudioStream" id=4]
[sub_resource type="RectangleShape2D" id=1]
custom_solver_bias = 0.0
extents = Vector2( 29.8667, 16 )
[node name="Wall" type="StaticBody2D"]
input_pickable = false
collision_layer = 1
collision_mask = 1
constant_linear_velocity = Vector2( 0, 0 )
constant_angular_velocity = 0.0
friction = 1.0
bounce = 0.0
script = ExtResource( 1 )
_sections_unfolded = [ "Transform", "Z Index" ]
[node name="Sprite" type="Sprite" parent="." index="0"]
[node name="Sprite" type="Sprite" parent="."]
visible = false
texture = ExtResource( 2 )
centered = false
_sections_unfolded = [ "Offset" ]
__meta__ = {
"_edit_lock_": true
}
[node name="CollisionShape2D" type="CollisionShape2D" parent="." index="1"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2( 32, 16 )
shape = SubResource( 1 )
_sections_unfolded = [ "Transform", "Z Index" ]
__meta__ = {
"_edit_lock_": true
}
[node name="Tween" type="Tween" parent="." index="2"]
[node name="Tween" type="Tween" parent="."]
repeat = false
playback_process_mode = 1
playback_speed = 1.0
playback/active = false
playback/repeat = false
playback/speed = 1.0
[node name="Timer" type="Timer" parent="." index="3"]
process_mode = 1
wait_time = 1.0
[node name="Timer" type="Timer" parent="."]
one_shot = true
autostart = false
[node name="move_sfx" type="AudioStreamPlayer" parent="."]
stream = ExtResource( 3 )
volume_db = -10.0
[node name="stop_sfx" type="AudioStreamPlayer" parent="."]
stream = ExtResource( 4 )
volume_db = -10.0
[connection signal="tween_completed" from="Tween" to="." method="_on_Tween_tween_completed"]
[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]

101
WallOfDeath.tscn 100644
View File

@ -0,0 +1,101 @@
[gd_scene load_steps=7 format=2]
[ext_resource path="res://art/white_circle.png" type="Texture" id=1]
[ext_resource path="res://sfx/WOD_sfx.ogg" type="AudioStream" id=2]
[sub_resource type="GradientTexture" id=1]
flags = 4
width = 2048
[sub_resource type="Curve" id=2]
min_value = 0.0
max_value = 1.0
bake_resolution = 100
_data = [ Vector2( 0, 0 ), 0.0, 2.09483, 0, 0, Vector2( 0.39982, 1 ), 0.295409, 0.295409, 0, 0, Vector2( 1, 0 ), -0.0609925, 0.0, 0, 0 ]
[sub_resource type="CurveTexture" id=3]
flags = 4
width = 2048
curve = SubResource( 2 )
[sub_resource type="ParticlesMaterial" id=4]
render_priority = 0
trail_divisor = 1
emission_shape = 2
emission_box_extents = Vector3( 20, 240, 1 )
flag_align_y = false
flag_rotate_y = false
flag_disable_z = true
spread = 45.0
flatness = 0.0
gravity = Vector3( 0, 0, 0 )
initial_velocity = 1.0
initial_velocity_random = 0.0
angular_velocity = 0.0
angular_velocity_random = 0.0
orbit_velocity = 0.0
orbit_velocity_random = 0.0
linear_accel = 0.0
linear_accel_random = 0.0
radial_accel = 0.0
radial_accel_random = 0.0
tangential_accel = 0.0
tangential_accel_random = 0.0
damping = 0.0
damping_random = 0.0
angle = 0.0
angle_random = 0.0
scale = 1.0
scale_random = 0.8
scale_curve = SubResource( 3 )
color_ramp = SubResource( 1 )
hue_variation = 0.0
hue_variation_random = 0.0
anim_speed = 0.0
anim_speed_random = 0.0
anim_offset = 0.0
anim_offset_random = 0.0
anim_loop = false
_sections_unfolded = [ "Color", "Emission Shape", "Resource", "Scale", "Trail" ]
[node name="WallOfDeath" type="Node2D" index="0"]
_sections_unfolded = [ "Material" ]
[node name="Particles2D" type="Particles2D" parent="." index="0"]
position = Vector2( -12.2346, 232.567 )
emitting = true
amount = 30
lifetime = 1.2
one_shot = false
preprocess = 0.0
speed_scale = 1.0
explosiveness = 0.0
randomness = 0.15
fixed_fps = 0
fract_delta = true
visibility_rect = Rect2( -100, -100, 200, 200 )
local_coords = true
draw_order = 0
process_material = SubResource( 4 )
texture = ExtResource( 1 )
normal_map = null
h_frames = 1
v_frames = 1
_sections_unfolded = [ "Drawing", "Material", "Process Material", "Textures", "Time", "Transform", "Z Index" ]
[node name="sfx" type="AudioStreamPlayer" parent="." index="1"]
stream = ExtResource( 2 )
volume_db = 0.0
pitch_scale = 1.0
autoplay = true
mix_target = 0
bus = "Master"

46
Wall_Obstacle.gd 100644
View File

@ -0,0 +1,46 @@
extends Node2D
# This is to encapsulate information about the gap obstacles and position
var shift_proximity
onready var topwall = $Top
onready var bottomwall = $Bottom
var gap_size
var gap_pos
var true_pos
var hspeed = Vector2(0,0)
var tracking_player
var shift_set = false
signal out_of_bound(wall)
signal moving(state)
func _ready():
self.position.x = gap_pos.x;
topwall.position = Vector2(0,(gap_pos.y - gap_size/2)*Global.GRID_SIZE)
topwall.set_scale(Vector2(1, -30))
bottomwall.position = Vector2(0, (gap_pos.y+gap_size/2)*Global.GRID_SIZE)
bottomwall.set_scale(Vector2(1, 30))
bottomwall.connect("moving", self, "_emit_moving")
shift_set = int(true_pos-gap_pos.y) != 0
shift_proximity = abs(hspeed.x) * 40
func _physics_process(delta):
# # Called every frame. Delta is time since last frame.
# # Update game logic here.
position += hspeed
if shift_set and abs(position.x -tracking_player.get_ref().position.x) < shift_proximity:
shift_set = false
topwall.shift_position((true_pos-gap_pos.y)*Global.GRID_SIZE)
bottomwall.shift_position((true_pos-gap_pos.y)*Global.GRID_SIZE)
if position.x< - topwall.w:
emit_signal("out_of_bound", self)
get_tree().queue_delete(self)
func _emit_moving(state):
emit_signal("moving", state)

14
Wall_Obstacle.tscn 100644
View File

@ -0,0 +1,14 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://Wall_Obstacle.gd" type="Script" id=1]
[ext_resource path="res://Wall.tscn" type="PackedScene" id=2]
[node name="Wall_Obstacle" type="Node2D"]
script = ExtResource( 1 )
[node name="Top" parent="." index="0" instance=ExtResource( 2 )]
[node name="Bottom" parent="." index="1" instance=ExtResource( 2 )]

View File

@ -1,27 +1,65 @@
extends Node2D
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
signal wall_spawned(gap_pos,gap_size,shift_pos);
signal laser_spawned(pos)
signal wall_spawned(gap_pos,gap_size,shift_pos)
signal laser_spawned(pos, n_lasers)
signal bomb_spawned(pos, n_spores)
signal query_player(callback)
signal wall_queue_empty
var prev_pos = 0
var prev_gap_size = 0
var active = true
# Wall spawning properties
var topgap_max_offset = deg2rad(20)
var bottomgap_max_offset = deg2rad(40)
var wall_min_offset = deg2rad(5)
var wall_spawntime = 1
var last_wall_speed = 0
var wall_close_range = Global.WALL_WIDTH * 1.25
export var wall_density = 1.0
export var wall_dens_variance = 0.2
export var shift_probability = 0.5
# Wall density determines the timer for spawning the walls
# Laser spawning properties
const gap_proximity = 1
export var laser_density = 1.0
export var laser_dens_variance = 0.2
var laser_spawntime = 1
export var ordered_lasers = true
# Laser density determines the timer for spawning a laser
# Or determines the number of lasers spawned at a time for ordered_lasers
var spawning_walls = false
var spawning_lasers = false
var wall_queue = Array()
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
$spawntimer.set_wait_time(1)
calc_wall_spawntime()
$spawntimer.connect("timeout",self, "spawn_wall")
$spawntimer.start()
$lasertimer.set_wait_time(1)
$lasertimer.connect("timeout",self, "spawn_laser")
$lasertimer.connect("timeout",self, "prepare_spawn_laser")
$lasertimer.start()
$bombtimer.set_wait_time(1)
$bombtimer.connect("timeout",self, "spawn_bomb")
$bombtimer.start()
func set_wall_spawntimer(timer=1):
$spawntimer.set_wait_time(timer)
wall_spawntime = timer
func toggle_spawner(wall,laser):
func set_laser_spawntimer(timer=1):
$lasertimer.set_wait_time(timer)
laser_spawntime = timer
func set_bomb_spawntimer(timer=1):
$bombtimer.set_wait_time(timer)
func set_ordered_laser(state):
ordered_lasers = state
func toggle_spawner(wall,laser,bomb):
if wall:
$spawntimer.start()
else:
@ -30,56 +68,199 @@ func toggle_spawner(wall,laser):
$lasertimer.start()
else:
$lasertimer.stop()
if bomb:
$bombtimer.start()
else:
$bombtimer.stop()
spawning_walls = wall
spawning_lasers = laser
func activate_spawner():
$spawntimer.start()
func set_wall_density(mean, variance):
wall_density = mean
wall_dens_variance = variance
calc_wall_spawntime()
func set_shift_prob(val):
shift_probability = val
func set_laser_density(mean, variance):
laser_density = mean
laser_dens_variance = variance
calc_laser_spawntime()
func calc_wall_spawntime():
var current_speed = math.calc_wall_speed(wall_density)
set_wall_spawntimer(max(Global.WALL_WIDTH/current_speed/60 * 0.75,
math.negexp(2, wall_density*0.8 - rand_range(-wall_dens_variance,wall_dens_variance)*0.5)))
func calc_laser_spawntime():
if ordered_lasers:
set_laser_spawntimer(Global.LASER_FRAMES * Global.LASER_TIMER)
else:
set_laser_spawntimer(math.negexp(1, laser_density*0.6+rand_range(-laser_dens_variance,laser_dens_variance)*0.3))
func spawn_wall():
var gap_size = math.randint(0,5)
var shifting = false
"""Procedure to spawn the walls is here"""
var min_shift
var max_shift
var top_max_shift
var bottom_max_shift
var gap_size
var wall_speed = math.calc_wall_speed(wall_density)
var dist_elapsed = wall_spawntime * last_wall_speed * 60
# Set the limits of the shift and define gap size
if dist_elapsed > wall_close_range:
dist_elapsed /= Global.GRID_SIZE
if $lasertimer.is_stopped():
min_shift = 2
top_max_shift = dist_elapsed * tan(topgap_max_offset) / max(1,wall_density)
bottom_max_shift = dist_elapsed * tan(bottomgap_max_offset) / max(1,wall_density)
gap_size = rand_range(1,max(5,15-Global.wall_difficulty))
else:
min_shift = 1
top_max_shift = dist_elapsed * tan(topgap_max_offset*0.8) / max(1,wall_density)
bottom_max_shift = top_max_shift
gap_size = rand_range(2,max(2,max(5,15-Global.wall_difficulty)))
else:
min_shift = 0
gap_size = rand_range(1,max(5,15-Global.wall_difficulty))
if wall_queue:
top_max_shift = max(0,abs(wall_queue.back().gap_size + gap_size)/2-1)
bottom_max_shift = top_max_shift
else:
top_max_shift = Global.HIGHEST_GRID
bottom_max_shift = top_max_shift
# Generate the gap position
var final_gap_pos
if not wall_queue:
final_gap_pos = Global.HIGHEST_GRID/2 + rand_range(-1,1) * Global.HIGHEST_GRID/4
else:
var last_pos = wall_queue.back().true_pos
if randf() > last_pos/Global.HIGHEST_GRID:
final_gap_pos = last_pos + rand_range(min_shift,top_max_shift)
else:
final_gap_pos = last_pos - rand_range(min_shift,bottom_max_shift)
final_gap_pos = max(min(final_gap_pos,Global.HIGHEST_GRID),Global.LOWEST_GRID)
# Generate the fake position
var fake_pos = final_gap_pos
if gap_size >1:
shifting = math.randint(1,gap_size)>1
if math.rng_check(shift_probability):
fake_pos = rand_range(0, 30)
var gap_grid_pos
if not prev_pos:
gap_grid_pos = math.randint(5,20)
else:
#gap_grid_pos = prev_pos + pow(-1,math.randint(0,1)) * math.randint(5,15)
if randf() > int(prev_pos/24):
gap_grid_pos = prev_pos + math.randint(7,12)
else:
gap_grid_pos = prev_pos - math.randint(7,15)
gap_grid_pos = math.bound_val(gap_grid_pos,3,24)
last_wall_speed = wall_speed
emit_signal("wall_spawned",Vector2(position.x, fake_pos),gap_size,final_gap_pos)
calc_wall_spawntime()
var shift_pos
if shifting:
#print('shift set')
func prepare_spawn_laser():
emit_signal("query_player", funcref(self, "spawn_laser"))
if randf() > int(gap_grid_pos/24):
shift_pos = gap_grid_pos + math.randint(5,8)
else:
shift_pos = gap_grid_pos - math.randint(5,8)
shift_pos = math.bound_val(shift_pos,5,24)
else:
shift_pos = gap_grid_pos
prev_pos = shift_pos
prev_gap_size = gap_size
emit_signal("wall_spawned",Vector2(position.x, gap_grid_pos),gap_size,shift_pos)
#emit_signal("wall_spawned",Vector2(position.x, gap_grid_pos),gap_size,shift_pos)
func spawn_laser():
func spawn_laser(player):
var n_lasers;
if $spawntimer.is_stopped():
n_lasers = min(math.randint(1,4) + Global.diff_level - 3,8)
if ordered_lasers:
n_lasers = math.inv_negexp(10, laser_density * 0.6 + (randf()*2 - 1) * laser_dens_variance)
else:
if Global.laser_difficulty > 5:
n_lasers = math.randint(1,2)
else:
n_lasers = math.randint(1,3)
for i in range(n_lasers):
var grid_pos = rand_range(Global.LOWEST_GRID,Global.HIGHEST_GRID)
emit_signal("laser_spawned",grid_pos,n_lasers)
else:
n_lasers = math.randint(1,3)
# Spawn only 3 lasers when walls are present
# And it is always ordered
n_lasers = math.randint(1,2)
for i in range(n_lasers):
# Given the laser timing t
if wall_queue:
var laser_time = Global.LASER_FRAMES * Global.LASER_TIMER
# First predict the player position after t time
# Assume player is perfect and crosses as many wall as possible
var frames = laser_time * 60; # Assume 60fps
var rpn = pow(1-player.POS_RECOVERY,frames)
var predicted_player_pos = ceil(player.position.x * rpn +\
player.default_pos * (1-rpn))
predicted_player_pos = max(predicted_player_pos, player.position.x)
# Using the predicted player position
# Find out which walls are of concern
var closest_wall_ind = search_woc(player.position.x)
var max_wall_ind = search_woc(predicted_player_pos, frames)
# Assuming all wall is of the same speed
# The wall relative distance to each other is constant
# Therefore, a binary search is possible on the queue
# Where-ever the search terminates, take the wall before it
var overlaps = Array()
for i in range(max_wall_ind-closest_wall_ind+1):
overlaps.append(0)
for i in range(n_lasers):
var grid_pos = rand_range(Global.LOWEST_GRID,Global.HIGHEST_GRID)
var discard = false
var ind = 0
for j in range(closest_wall_ind, max_wall_ind+1):
# When spawning a laser, check if the position is on the gap
var top = wall_queue[j].true_pos - wall_queue[j].gap_size/2
var bottom = wall_queue[j].true_pos + wall_queue[j].gap_size/2
# Keep track of how many lasers has spawned on the gap
if(grid_pos > top - gap_proximity&& grid_pos < bottom+gap_proximity):
# Number of laser on gap < gap_size//2
if overlaps[ind] > wall_queue[j].gap_size/2-1:
# Reroll position if above condition is violated
discard = true
break
overlaps[ind] += 1
ind += 1
if not discard:
emit_signal("laser_spawned",grid_pos,n_lasers)
calc_laser_spawntime()
func search_woc(pos, elapsed_time=0):
# Binary search the wall of concern, return index
# Need to account for the moving walls using elapsed time, 0 for static check
var lo = 0
var hi = wall_queue.size() - 1
while(lo <= hi):
var mid = (lo+hi)/2
var new_position = wall_queue[mid].position.x + wall_queue[mid].hspeed.x * elapsed_time
if (pos == new_position):
return mid
if(pos < new_position):
hi = mid - 1
if(pos > new_position):
lo = mid + 1
return math.bound_val(lo, 0, wall_queue.size() - 1)
func spawn_bomb():
var n_bombs = math.randint(1,3)
for i in range(n_bombs):
var grid_pos = math.randint(2,29)
if prev_gap_size<1 and grid_pos == prev_pos:
grid_pos += pow(-1,math.randint(0,1))
emit_signal("laser_spawned",grid_pos)
var n_spores = math.randint(3,8)
emit_signal("bomb_spawned",grid_pos,n_spores)
func dequeue_wall(dummy):
wall_queue.pop_front()
if wall_queue.size() == 1:
emit_signal("wall_queue_empty")
func queue_wall(wall_ent):
wall_queue.append(wall_ent)

View File

@ -6,9 +6,16 @@
[node name="Wall_Spawner" type="Node2D"]
script = ExtResource( 1 )
wall_density = 1.0
wall_dens_variance = 0.2
shift_probability = 0.5
laser_density = 1.0
laser_dens_variance = 0.2
ordered_lasers = true
[node name="Sprite" type="Sprite" parent="." index="0"]
visible = false
texture = ExtResource( 2 )
[node name="spawntimer" type="Timer" parent="." index="1"]
@ -20,6 +27,13 @@ autostart = false
[node name="lasertimer" type="Timer" parent="." index="2"]
process_mode = 1
wait_time = 0.1
one_shot = false
autostart = false
[node name="bombtimer" type="Timer" parent="." index="3"]
process_mode = 1
wait_time = 1.0
one_shot = false

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

13
blackout.gd 100644
View File

@ -0,0 +1,13 @@
extends TextureRect
export var sweep_speed = 50
var sweep_pos = 0
var sweep = false
func _process(delta):
# # Called every frame. Delta is time since last frame.
# # Update game logic here.
if sweep:
self.material.set_shader_param("x_line", sweep_pos)
sweep_pos += sweep_speed * delta

13
cam.gd
View File

@ -1,16 +1,5 @@
extends Camera2D
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
pass
func _physics_process(delta):
# # Called every frame. Delta is time since last frame.
# # Update game logic here.
# Go back to 0 offset
set_offset(get_offset()/2)
pass

View File

@ -1,87 +1,119 @@
extends Node2D
onready var wall_res = preload("res://Wall.tscn")
onready var wall_res = preload("res://Wall_Obstacle.tscn")
onready var laser_e_res = preload("res://Laser_enemy.tscn")
onready var laser_res = preload("res://Laser_obj.tscn")
onready var laser_p_res = preload("res://laser_particle.tscn")
onready var spore_res = preload("res://Spore.tscn")
onready var screenSize = get_viewport().get_visible_rect().size
onready var diffInfo = get_node("DifficultyInfo")
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
var wall_move = false
var shift_time = 0.5
var current_mode = 0
export var starting_wall_diff = 1
export var starting_laser_diff = 1
export var input_map_seed = -1
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
print(screenSize)
$Wall_Spawner.toggle_spawner(true,false)
#$Wall_Spawner.deactivate_spawner()
pass
Global.diff_level = Global.start_level
Global.wall_difficulty = starting_wall_diff
Global.laser_difficulty = starting_laser_diff
display_difficulty()
randomize()
if input_map_seed < 0:
var map_seed = randi()
seed(map_seed)
print("Seed: ", map_seed)
else:
seed(input_map_seed)
print("Seed: ", input_map_seed)
$Wall_Spawner.toggle_spawner(true,false, false)
func _process(delta):
# ScreenShake
if wall_move:
screenshake(16,0.2)
# Scrolling background
var bg_rect = $bg.get_region_rect()
bg_rect.position.x += 5 * delta
if bg_rect.position.x > 900:
bg_rect.position.x = -900
$bg.set_region_rect(bg_rect)
$Effects/WallOfDeath/sfx.set_volume_db(min(3.0,
10 * log(60/max(1,$Player.position.x - $Effects/WallOfDeath.position.x))))
func despawn_ent(ent):
# Dequeue a given entity/object
#get_node(".").remove_child(ent)
#get_tree().queue_delete(ent)
pass
func _on_Wall_Spawner_wall_spawned(gap_pos, gap_size, shift_pos):
var topwall = wall_res.instance()
get_node(".").add_child(topwall)
topwall.connect("out_of_bound", self, "despawn_wall")
var bottomwall = wall_res.instance()
get_node(".").add_child(bottomwall)
bottomwall.connect("moving", self, "toggle_screenshake")
bottomwall.connect("out_of_bound", self, "despawn_wall")
topwall.position = Vector2(gap_pos.x,(gap_pos.y -29-gap_size)*Global.GRID_SIZE)
topwall.set_scale(Vector2(1, 15))
bottomwall.position = Vector2(gap_pos.x, screenSize.y - (27-gap_pos.y-gap_size)*Global.GRID_SIZE)#
bottomwall.set_scale(Vector2(1, 15))
if shift_pos-gap_pos.y != 0:
topwall.set_shift(shift_time,(shift_pos-gap_pos.y)*Global.GRID_SIZE)
bottomwall.set_shift(shift_time,(shift_pos-gap_pos.y)*Global.GRID_SIZE)
#screenSize.y/Global.GRID_SIZE
func despawn_wall(wall):
get_node(".").remove_child(wall)
get_tree().queue_delete(wall)
func shoot_laser(laser_en):
func shoot_laser(laser_en, n_lasers):
# Spawn the laser itself
var l = laser_res.instance()
get_node(".").add_child(l)
l.position = Vector2(0,laser_en.position.y)
l.connect("kill_zone",self,"check_laser_target")
despawn_wall(laser_en)
#despawn_ent(laser_en)
screenshake(32,0.4)
#l.tween_node.connect("tween_completed",self, "despawn_wall",l)
func check_laser_target(body):
#for b in body:
if body == $Player:
OS.delay_msec(10)
$Player/AnimatedSprite.play()
$Player.dead = true
# Spawn the laser particles (which has the sound lol)
# Maybe consider grouping the lasers???????
var l_p = laser_p_res.instance()
get_node(".").add_child(l_p)
l_p.position = Vector2(550,laser_en.position.y)
l_p.laser_sound.set_volume_db(10*log(min(0.7,0.3 + 0.1*n_lasers)/n_lasers))
func check_laser_target(body):
# Kill player
OS.delay_msec(30)
$Player.on_dead()
func _on_Player_dead_player():
$Effects.sweep = true
func _on_Player_gameover():
Global.diff_level = 1
# Reset the game variable
if $Player.score>Global.high_score:
Global.high_score = $Player.score
Global.return_to_menu = true
Global.playable = false
# Return to Main Menu
get_tree().change_scene("res://mainmenu.tscn")
func _on_Wall_Spawner_wall_spawned(gap_pos, gap_size, true_pos):
# Spawn the wall obstacle
var wall_obs = wall_res.instance()
wall_obs.gap_pos = gap_pos
wall_obs.gap_size = gap_size
wall_obs.true_pos = true_pos
wall_obs.hspeed.x = -math.calc_wall_speed($Wall_Spawner.wall_density)
wall_obs.tracking_player = weakref($Player)
get_node(".").add_child(wall_obs)
#wall_obs.connect("out_of_bound", self, "despawn_ent")
wall_obs.connect("moving", self, "toggle_screenshake")
wall_obs.connect("out_of_bound", $Wall_Spawner, "dequeue_wall")
$Wall_Spawner.queue_wall(wall_obs)
func _on_Wall_Spawner_laser_spawned(pos):
func _on_Wall_Spawner_query_player(callback):
callback.call_func($Player)
func _on_Wall_Spawner_laser_spawned(pos,n_lasers):
# Spawn the laser enemy
var l_enemy = laser_e_res.instance()
get_node(".").add_child(l_enemy)
l_enemy.connect("shoot",self,"shoot_laser")
l_enemy.position = Vector2(screenSize.x-32, pos*Global.GRID_SIZE)
l_enemy.place_obj(screenSize.x,screenSize.x-32,0.2)
l_enemy.n_lasers = n_lasers
l_enemy.spawn_sound.set_volume_db(10*log(min(0.7,0.3 + 0.1*n_lasers)/n_lasers))
func toggle_screenshake(state):
wall_move = state
@ -92,16 +124,65 @@ func screenshake(off,mag):
rand_range(-off,off) * mag ))
func _on_leveltimer_timeout():
# If wall is spawning, let the wall finish moving then toggle difficulty via signal
# Otherwise immediately increase difficulty
if not $Wall_Spawner.spawning_walls:
increase_difficulty()
else:
$Wall_Spawner.toggle_spawner(false,false,false)
func increase_difficulty():
# Up the difficulty
# Three factor that can be amp up:
# Laser density, wall density, which one to toggle
# Laser can be ordered or contiguous
Global.diff_level = min(Global.diff_level+1,10)
if Global.diff_level == 2:
$Wall_Spawner.toggle_spawner(false,true)
$Wall_Spawner.set_ordered_laser(false)
$Wall_Spawner.toggle_spawner(false,true,false)
current_mode = 1
elif Global.diff_level == 3:
$Wall_Spawner.toggle_spawner(true,true)
$Wall_Spawner.wall_density /= 2
$Wall_Spawner.set_ordered_laser(true)
$Wall_Spawner.toggle_spawner(true,true,false)
current_mode = 2
else:
if math.randint(0,1):
$Wall_Spawner.toggle_spawner(true,math.randint(0,1))
else:
$Wall_Spawner.toggle_spawner(false,true)
$Wall_Spawner/spawntimer.set_wait_time(max(1.5-0.15*Global.diff_level,0.7))
shift_time = max(1-0.1*Global.diff_level,0.3)
$leveltimer.set_wait_time(math.randint(5,8))
var mode = (current_mode + math.randint(1,2))%3
var mean
if mode==0:
Global.wall_difficulty = min(Global.wall_difficulty+0.5,10)
Global.laser_difficulty = min(Global.wall_difficulty+0.5,10)
mean = 0.8 + Global.wall_difficulty *0.25 + rand_range(-1, 1)
$Wall_Spawner.shift_probability = 1 - exp(-Global.wall_difficulty/8)
if math.rng_check(0.1):
$Wall_Spawner.set_wall_density(mean*1.5,0.1)
else:
$Wall_Spawner.set_wall_density(mean*rand_range(0.7, 0.9),0.1)
$Wall_Spawner.set_ordered_laser(true)
$Wall_Spawner.toggle_spawner(true,true,false)
elif mode==1:
Global.wall_difficulty = min(Global.wall_difficulty+1,10)
mean = 1 + Global.wall_difficulty * 0.1
$Wall_Spawner.shift_probability = 1 - exp(-Global.wall_difficulty/5)
if math.rng_check(0.15):
$Wall_Spawner.set_wall_density(mean*2,0.1)
else:
$Wall_Spawner.set_wall_density(mean*rand_range(0.8, 0.9),rand_range(0.1,0.3))
$Wall_Spawner.toggle_spawner(true,false,false)
else:
Global.laser_difficulty = min(Global.laser_difficulty+0.5,10)
mean = 0.5 + Global.laser_difficulty *0.2 + rand_range(-0.5,0.5)
$Wall_Spawner.set_laser_density(mean, math.inv_negexp(1, randf()*0.2 + 0.1))
$Wall_Spawner.set_ordered_laser(math.flip_coin())
$Wall_Spawner.toggle_spawner(false,true,false)
current_mode = mode
display_difficulty()
$leveltimer.start()
func display_difficulty():
diffInfo.get_node("Wall_diff_label").set_text("Wall Difficulty: " + str(Global.wall_difficulty) + "\nDensity: " + str($Wall_Spawner.wall_density))
diffInfo.get_node("Laser_diff_label").set_text("Laser Difficulty: " + str(Global.laser_difficulty) + "\nDensity: " + str($Wall_Spawner.laser_density))

View File

@ -1,52 +1,81 @@
[gd_scene load_steps=8 format=2]
[gd_scene load_steps=15 format=2]
[ext_resource path="res://gamescene.gd" type="Script" id=1]
[ext_resource path="res://art/bg.png" type="Texture" id=2]
[ext_resource path="res://cam.gd" type="Script" id=3]
[ext_resource path="res://player.tscn" type="PackedScene" id=4]
[ext_resource path="res://Wall_Spawner.tscn" type="PackedScene" id=5]
[ext_resource path="res://art/wall.png" type="Texture" id=6]
[ext_resource path="res://art/wall.png" type="Texture" id=2]
[ext_resource path="res://art/bg.png" type="Texture" id=3]
[ext_resource path="res://Ground.tscn" type="PackedScene" id=4]
[ext_resource path="res://cam.gd" type="Script" id=5]
[ext_resource path="res://player.tscn" type="PackedScene" id=6]
[ext_resource path="res://Wall_Spawner.tscn" type="PackedScene" id=7]
[ext_resource path="res://Effects.gd" type="Script" id=8]
[ext_resource path="res://WallOfDeath.tscn" type="PackedScene" id=9]
[ext_resource path="res://art/player.png" type="Texture" id=10]
[ext_resource path="res://RunTimeInfo.tscn" type="PackedScene" id=11]
[sub_resource type="RectangleShape2D" id=1]
custom_solver_bias = 0.0
extents = Vector2( 32, 15.6897 )
[node name="Gamescene" type="Node2D"]
[sub_resource type="Shader" id=2]
code = "shader_type canvas_item;
uniform float sweep_pos;
void fragment(){
if(UV.x < sweep_pos)
COLOR = vec4(0,0,0,1);
else
discard;
}"
[sub_resource type="ShaderMaterial" id=3]
render_priority = 0
shader = SubResource( 2 )
shader_param/sweep_pos = null
[node name="Gamescene" type="Node2D" index="0"]
script = ExtResource( 1 )
_sections_unfolded = [ "Material" ]
starting_wall_diff = 1
starting_laser_diff = 1
input_map_seed = -1
[node name="bg" type="Sprite" parent="."]
position = Vector2( 320, 240 )
texture = ExtResource( 2 )
__meta__ = {
"_edit_lock_": true
}
[node name="leveltimer" type="Timer" parent="." index="0"]
[node name="cam" type="Camera2D" parent="."]
position = Vector2( 296, 240 )
current = true
drag_margin_h_enabled = true
drag_margin_v_enabled = true
script = ExtResource( 3 )
process_mode = 1
wait_time = 3.0
one_shot = true
autostart = true
[node name="Player" parent="." instance=ExtResource( 4 )]
position = Vector2( 199.446, 96.3989 )
[node name="fieldwall" type="StaticBody2D" parent="." index="1"]
[node name="Wall_Spawner" parent="." instance=ExtResource( 5 )]
position = Vector2( 671.423, 111.06 )
[node name="fieldwall" type="StaticBody2D" parent="."]
editor/display_folded = true
position = Vector2( 320, -16 )
scale = Vector2( 10.125, 1 )
input_pickable = false
collision_layer = 1
collision_mask = 1
constant_linear_velocity = Vector2( 0, 0 )
constant_angular_velocity = 0.0
friction = 1.0
bounce = 0.0
__meta__ = {
"_edit_lock_": true
}
[node name="Sprite" type="Sprite" parent="fieldwall"]
texture = ExtResource( 6 )
[node name="Sprite" type="Sprite" parent="fieldwall" index="0"]
texture = ExtResource( 2 )
_sections_unfolded = [ "Animation", "Transform" ]
__meta__ = {
"_edit_lock_": true
}
[node name="CollisionShape2D" type="CollisionShape2D" parent="fieldwall"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="fieldwall" index="1"]
position = Vector2( 0, -1.67308 )
scale = Vector2( 1, 0.945607 )
shape = SubResource( 1 )
@ -54,11 +83,184 @@ __meta__ = {
"_edit_lock_": true
}
[node name="leveltimer" type="Timer" parent="."]
wait_time = 15.0
autostart = true
[node name="bg" type="Sprite" parent="." index="2"]
position = Vector2( 320, 240 )
z_index = -1
texture = ExtResource( 3 )
region_enabled = true
region_rect = Rect2( 0, 0, 800, 480 )
_sections_unfolded = [ "Animation", "Offset", "Region", "Z Index" ]
__meta__ = {
"_edit_lock_": true
}
[node name="Ground" parent="." index="3" instance=ExtResource( 4 )]
n_lines = 15
x_offset_spd = -250.0
start_y = 322
alpha = 0.1
[node name="cam" type="Camera2D" parent="." index="4"]
position = Vector2( 296, 240 )
anchor_mode = 1
rotating = false
current = true
zoom = Vector2( 1, 1 )
limit_left = -10000000
limit_top = -10000000
limit_right = 10000000
limit_bottom = 10000000
limit_smoothed = false
drag_margin_h_enabled = true
drag_margin_v_enabled = true
smoothing_enabled = false
smoothing_speed = 5.0
offset_v = 0.0
offset_h = 0.0
drag_margin_left = 0.2
drag_margin_top = 0.2
drag_margin_right = 0.2
drag_margin_bottom = 0.2
editor_draw_screen = true
editor_draw_limits = false
editor_draw_drag_margin = false
script = ExtResource( 5 )
_sections_unfolded = [ "Material" ]
[node name="Player" parent="." index="5" instance=ExtResource( 6 )]
position = Vector2( 199.446, 96.3989 )
[node name="Wall_Spawner" parent="." index="6" instance=ExtResource( 7 )]
position = Vector2( 630, 80 )
wall_density = 0.5
wall_dens_variance = 0.0
shift_probability = 0.1
laser_density = 0.5
ordered_lasers = false
[node name="Effects" type="Node2D" parent="." index="7"]
editor/display_folded = true
z_index = 2
script = ExtResource( 8 )
_sections_unfolded = [ "Z Index" ]
[node name="WallOfDeath" parent="Effects" index="0" instance=ExtResource( 9 )]
position = Vector2( -11.0032, 0 )
z_index = 1
_sections_unfolded = [ "Material", "Z Index" ]
[node name="blackout" type="TextureRect" parent="Effects" index="1"]
material = SubResource( 3 )
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = -50.0
margin_top = -20.0
margin_right = 680.0
margin_bottom = 520.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 1
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
texture = ExtResource( 10 )
expand = true
stretch_mode = 0
_sections_unfolded = [ "Material" ]
[node name="RunTimeInfo" parent="." index="8" instance=ExtResource( 11 )]
visible = false
margin_left = 430.0
margin_top = 410.0
margin_right = 470.0
margin_bottom = 478.0
_sections_unfolded = [ "Material", "Pause", "Visibility" ]
[node name="DifficultyInfo" type="VBoxContainer" parent="." index="9"]
editor/display_folded = true
visible = false
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 450.0
margin_top = 10.0
margin_right = 490.0
margin_bottom = 60.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 1
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 1
alignment = 0
__meta__ = {
"_edit_group_": true
}
[node name="Wall_diff_label" type="Label" parent="DifficultyInfo" index="0"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_right = 40.0
margin_bottom = 14.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="Laser_diff_label" type="Label" parent="DifficultyInfo" index="1"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_top = 18.0
margin_right = 40.0
margin_bottom = 32.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[connection signal="timeout" from="leveltimer" to="." method="_on_leveltimer_timeout"]
[connection signal="dead_player" from="Player" to="." method="_on_Player_dead_player"]
[connection signal="gameover" from="Player" to="." method="_on_Player_gameover"]
[connection signal="bomb_spawned" from="Wall_Spawner" to="." method="_on_Wall_Spawner_bomb_spawned"]
[connection signal="laser_spawned" from="Wall_Spawner" to="." method="_on_Wall_Spawner_laser_spawned"]
[connection signal="query_player" from="Wall_Spawner" to="." method="_on_Wall_Spawner_query_player"]
[connection signal="wall_queue_empty" from="Wall_Spawner" to="." method="increase_difficulty"]
[connection signal="wall_spawned" from="Wall_Spawner" to="." method="_on_Wall_Spawner_wall_spawned"]
[connection signal="timeout" from="leveltimer" to="." method="_on_leveltimer_timeout"]

BIN
icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -20,7 +20,7 @@ compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
@ -31,5 +31,5 @@ process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
detect_3d=false
svg/scale=1.0

19
laser_particle.gd 100644
View File

@ -0,0 +1,19 @@
extends Particles2D
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
onready var laser_sound = $laser_sfx
func _ready():
emitting = true
one_shot = true
#func _process(delta):
# # Called every frame. Delta is time since last frame.
# # Update game logic here.
# pass
func _on_Timer_timeout():
get_tree().queue_delete(self)

View File

@ -0,0 +1,88 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://laser_particle.gd" type="Script" id=1]
[ext_resource path="res://sfx/laser.wav" type="AudioStream" id=2]
[sub_resource type="ParticlesMaterial" id=1]
render_priority = 0
trail_divisor = 1
emission_shape = 2
emission_box_extents = Vector3( 50, 16, 1 )
flag_align_y = false
flag_rotate_y = false
flag_disable_z = true
spread = 15.0
flatness = 0.0
gravity = Vector3( 0, 0, 0 )
initial_velocity = 80.0
initial_velocity_random = 0.5
angular_velocity = 0.0
angular_velocity_random = 0.0
orbit_velocity = 0.0
orbit_velocity_random = 0.0
linear_accel = 0.0
linear_accel_random = 0.0
radial_accel = 0.0
radial_accel_random = 0.0
tangential_accel = 0.0
tangential_accel_random = 0.0
damping = 10.0
damping_random = 0.0
angle = 0.0
angle_random = 0.2
scale = 10.0
scale_random = 0.7
color = Color( 1, 1, 1, 1 )
hue_variation = 0.0
hue_variation_random = 0.0
anim_speed = 0.0
anim_speed_random = 0.0
anim_offset = 0.0
anim_offset_random = 0.0
anim_loop = false
_sections_unfolded = [ "Animation", "Damping", "Emission Shape", "Flags", "Gravity", "Initial Velocity", "Linear Accel", "Orbit Velocity", "Scale", "Spread" ]
[node name="Particles2D" type="Particles2D"]
rotation = 3.14159
emitting = false
amount = 6
lifetime = 3.0
one_shot = true
preprocess = 0.0
speed_scale = 6.0
explosiveness = 1.0
randomness = 0.5
fixed_fps = 0
fract_delta = true
visibility_rect = Rect2( -4.03601, -165.736, 530.925, 448.789 )
local_coords = true
draw_order = 0
process_material = SubResource( 1 )
texture = null
normal_map = null
h_frames = 1
v_frames = 1
script = ExtResource( 1 )
_sections_unfolded = [ "Drawing", "Process Material", "Textures", "Time", "Transform", "Z Index" ]
[node name="Timer" type="Timer" parent="." index="0"]
process_mode = 1
wait_time = 1.0
one_shot = true
autostart = true
[node name="laser_sfx" type="AudioStreamPlayer" parent="." index="1"]
stream = ExtResource( 2 )
volume_db = 0.0
pitch_scale = 1.0
autoplay = true
mix_target = 0
bus = "Master"
[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]

View File

@ -3,13 +3,10 @@ extends Node2D
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
var rot = 0;
var rot = 0
func _ready():
randomize()
# Called when the node is added to the scene for the first time.
# Initialization here
Global.playable = true
$Spiny/highscore.set_text(str(Global.high_score))
pass
func _physics_process(delta):
# # Called every frame. Delta is time since last frame.
@ -23,6 +20,3 @@ func _physics_process(delta):
$Spiny.set_rotation(rot)
func _on_Tween_tween_completed(object, key):
Global.playable = true

View File

@ -1,19 +1,32 @@
[gd_scene load_steps=7 format=2]
[gd_scene load_steps=11 format=2]
[ext_resource path="res://mainmenu.gd" type="Script" id=1]
[ext_resource path="res://art/main_menu.png" type="Texture" id=2]
[ext_resource path="res://art/player.png" type="Texture" id=3]
[ext_resource path="res://Data-Control.ttf" type="DynamicFontData" id=4]
[ext_resource path="res://blank.gd" type="Script" id=5]
[ext_resource path="res://Spiny.gd" type="Script" id=4]
[ext_resource path="res://charybdis.regular.ttf" type="DynamicFontData" id=5]
[ext_resource path="res://Fade.gd" type="Script" id=6]
[ext_resource path="res://sfx/WOD_sfx.ogg" type="AudioStream" id=7]
[sub_resource type="DynamicFont" id=1]
size = 10
font_data = ExtResource( 4 )
font_data = ExtResource( 5 )
[sub_resource type="Shader" id=2]
code = "shader_type canvas_item;
uniform float alpha;
void fragment(){
COLOR = vec4(0,0,0,alpha);
}"
[sub_resource type="ShaderMaterial" id=3]
shader = SubResource( 2 )
shader_param/alpha = null
[node name="mainmenu" type="Node2D"]
script = ExtResource( 1 )
[node name="Sprite" type="Sprite" parent="."]
[node name="BG" type="Sprite" parent="."]
position = Vector2( 304, 240 )
texture = ExtResource( 2 )
__meta__ = {
@ -24,9 +37,12 @@ __meta__ = {
position = Vector2( 304, 208 )
scale = Vector2( 3.5, 3.5 )
texture = ExtResource( 3 )
script = ExtResource( 4 )
__meta__ = {
"_edit_lock_": true
}
lift = 3
sides = 3
[node name="highscore" type="Label" parent="Spiny"]
margin_left = -9.0
@ -39,11 +55,8 @@ custom_fonts/font = SubResource( 1 )
text = "0"
align = 1
valign = 1
__meta__ = {
"_edit_lock_": true
}
[node name="Label" type="Label" parent="."]
[node name="Instruction" type="Label" parent="."]
margin_left = 240.0
margin_top = 288.0
margin_right = 373.0
@ -53,25 +66,36 @@ __meta__ = {
"_edit_lock_": true
}
[node name="blank" type="Sprite" parent="."]
position = Vector2( -16, 0 )
scale = Vector2( 40, 30 )
[node name="Credits" type="Label" parent="."]
margin_left = 10.0
margin_top = 350.0
margin_right = 588.0
margin_bottom = 466.0
text = "Made by: ASadPumpkin
Inspired by: Flappy Bird, BadLand
Engine: Godot 3.0.6 (https://godotengine.org/)
Art: Krita (https://krita.org/en/)
Font: Charybdis by Tepid Monkey Fonts (https://www.1001fonts.com/)
Sound Effects: Bfxr (https://www.bfxr.net/), Audacity (https://www.audacityteam.org/)
Additional SFX: freesfx.co.uk"
[node name="Fade" type="Node2D" parent="."]
script = ExtResource( 6 )
__meta__ = {
"_edit_group_": true,
"_edit_lock_": true
}
[node name="fadeRect" type="TextureRect" parent="Fade"]
material = SubResource( 3 )
margin_left = -10.0
margin_right = 620.0
margin_bottom = 480.0
texture = ExtResource( 3 )
centered = false
flip_v = true
script = ExtResource( 5 )
expand = true
[node name="Tween" type="Tween" parent="blank"]
[node name="Label2" type="Label" parent="."]
margin_left = 32.0
margin_top = 416.0
margin_right = 370.0
margin_bottom = 498.0
text = "Inspired by: Flappy Bird
Created In: Godot 3 Engine (https://godotengine.org/)
Art: Done In Krita (https://krita.org/en/)
Produced by: En Yi (eyt21@cam.ac.uk)
"
[connection signal="tween_completed" from="blank/Tween" to="." method="_on_Tween_tween_completed"]
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
stream = ExtResource( 7 )
volume_db = -1.0
pitch_scale = 0.3
autoplay = true

40
math.gd
View File

@ -6,6 +6,7 @@ static func logistic_func(x, x0=0, k=1):
return 1/(1+pow(1.6,-k*(x - x0)))
static func randint(lower, upper):
# Inclusive random integer
return randi() % (upper - lower + 1) + lower
static func within_bounds(val, lower, upper, inclusive = true):
@ -14,31 +15,30 @@ static func within_bounds(val, lower, upper, inclusive = true):
else:
return val<upper and val>lower
static func rng_check(prob):
assert (prob <= 1)
return randf() < prob
static func flip_coin():
return randint(0,1) == 1
static func roll_die(n_times=1, n_sides=6):
assert(n_times > 0)
assert(n_sides >= 1)
assert (n_times > 0)
assert (n_sides >= 1)
var total = 0
for i in range(n_times):
total += randint(1, n_sides)
return total
static func random_choice_index(chances):
var sum_chances = 0
for val in chances:
sum_chances += val
var random_chance = randint(1, sum_chances)
static func inv_negexp(A, B):
return A * (1-exp(-B))
var running_sum = 0
var choice = 0
for w in chances:
running_sum += w
static func negexp(A, B):
return A * exp(-B)
if random_chance <= running_sum:
return choice
choice += 1
static func random_choice_from_dict(choice_dict):
var choices = choice_dict.keys()
var chances = choice_dict.values()
return choices[random_choice_index(chances)]
static func calc_wall_speed(wall_density):
# Returns positive value
var spd = 4 + min(Global.wall_difficulty*0.4,4)
if wall_density > 1:
spd /= bound_val(wall_density*0.45, 1, 5)
return spd

View File

@ -1,31 +1,46 @@
extends KinematicBody2D
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
var GRAV = Vector2(0,25);
var JUMP_SPEED = Vector2(0,425);
const GRAV = Vector2(0,25);
const JUMP_SPEED = Vector2(0,450);
const LEEWAY = 32
const KB_RECOVERY = 0.1
const POS_RECOVERY = 0.01
var vel = Vector2(0,0);
var max_drop = 10;
var dead = false
var leeway = 32
var score = 0
var short_hop = false
var short_hop_factor = 5
var knockback = 0
onready var default_pos = position.x
export var invuln = false
export var float_enable = false
signal gameover()
signal dead_player()
func _ready():
# Called when the node is added to the scene for the first time.
# Initialization here
#print(default_pos)
pass
vel = -JUMP_SPEED
short_hop = true
$Jumptimer.start()
$jump_sfx.play()
func _physics_process(delta):
# # Called every frame. Delta is time since last frame.
# # Update game logic here.
if not dead:
vel += GRAV
if not float_enable:
vel += GRAV
#move_and_collide(vel)
#var col = move_and_collide(vel)
if Input.is_action_just_pressed("ui_accept"):
@ -33,34 +48,44 @@ func _physics_process(delta):
vel = -JUMP_SPEED
short_hop = true
$Jumptimer.start()
$jump_sfx.play()
if Input.is_action_just_released("ui_accept"):
if short_hop:
vel /= 4
vel /= short_hop_factor
short_hop = false
$Jumptimer.stop()
#print(vel)
vel = move_and_slide(vel)
position.x = lerp(position.x,default_pos,0.005)
# Slowly move back to default position
position.x = ceil(lerp(position.x,default_pos,POS_RECOVERY) - knockback)
knockback = lerp(knockback,0,KB_RECOVERY)
#var col = move_and_collide(vel)
#print(col)
if position.x< -$Sprite.get_texture().get_size().x-leeway/4 or \
position.y> get_viewport().get_visible_rect().size.y + $Sprite.get_texture().get_size().y+ leeway:
emit_signal("gameover")
if not invuln:
if position.x< -$Sprite.get_texture().get_size().x-LEEWAY/4 or \
position.y> get_viewport().get_visible_rect().size.y + $Sprite.get_texture().get_size().y+ LEEWAY:
if not dead:
on_dead()
func _on_AnimatedSprite_animation_finished():
emit_signal("gameover")
pass
func _on_Timer_timeout():
if not dead:
score += 1
$scorelabel.set_text(str(score))
func _on_Jumptimer_timeout():
short_hop = false
func on_dead():
$AnimatedSprite.play()
$dead_sfx.play()
get_tree().queue_delete($scorelabel)
dead = true
emit_signal("dead_player")
func _on_dead_sfx_finished():
emit_signal("gameover")

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=14 format=2]
[gd_scene load_steps=16 format=2]
[ext_resource path="res://player.gd" type="Script" id=1]
[ext_resource path="res://art/player.png" type="Texture" id=2]
@ -9,7 +9,9 @@
[ext_resource path="res://art/beam_frames/laser5.png" type="Texture" id=7]
[ext_resource path="res://art/beam_frames/laser6.png" type="Texture" id=8]
[ext_resource path="res://art/beam_frames/laser7.png" type="Texture" id=9]
[ext_resource path="res://Data-Control.ttf" type="DynamicFontData" id=10]
[ext_resource path="res://charybdis.regular.ttf" type="DynamicFontData" id=10]
[ext_resource path="res://sfx/jump.wav" type="AudioStream" id=11]
[ext_resource path="res://sfx/dead.wav" type="AudioStream" id=12]
[sub_resource type="RectangleShape2D" id=1]
@ -27,19 +29,23 @@ animations = [ {
[sub_resource type="DynamicFont" id=3]
size = 14
size = 16
use_mipmaps = false
use_filter = false
font_data = ExtResource( 10 )
_sections_unfolded = [ "Settings" ]
_sections_unfolded = [ "Font", "Settings" ]
[node name="Player" type="KinematicBody2D"]
[node name="Player" type="KinematicBody2D" groups=[
"players",
]]
input_pickable = false
collision_layer = 1
collision_mask = 1
collision/safe_margin = 0.08
script = ExtResource( 1 )
invuln = false
float_enable = false
[node name="Sprite" type="Sprite" parent="." index="0"]
@ -59,7 +65,7 @@ animation = "dead"
[node name="Timer" type="Timer" parent="." index="3"]
process_mode = 1
wait_time = 0.7
wait_time = 1.0
one_shot = false
autostart = true
@ -96,10 +102,30 @@ lines_skipped = 0
max_lines_visible = -1
_sections_unfolded = [ "custom_colors", "custom_fonts" ]
[node name="jump_sfx" type="AudioStreamPlayer" parent="." index="6"]
stream = ExtResource( 11 )
volume_db = 0.0
pitch_scale = 1.0
autoplay = false
mix_target = 0
bus = "Master"
[node name="dead_sfx" type="AudioStreamPlayer" parent="." index="7"]
stream = ExtResource( 12 )
volume_db = -10.0
pitch_scale = 1.0
autoplay = false
mix_target = 0
bus = "Master"
[connection signal="animation_finished" from="AnimatedSprite" to="." method="_on_AnimatedSprite_animation_finished"]
[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]
[connection signal="timeout" from="Jumptimer" to="." method="_on_Jumptimer_timeout"]
[connection signal="finished" from="dead_sfx" to="." method="_on_dead_sfx_finished"]

View File

@ -10,9 +10,9 @@ config_version=4
[application]
config/name="synth"
config/name="Flat White"
run/main_scene="res://mainmenu.tscn"
config/icon="res://icon.png"
config/icon="res://Flat_white_icon.png"
[autoload]
@ -23,7 +23,9 @@ Global="*res://Global.gd"
window/size/width=600
window/size/height=480
window/size/resizable=false
window/stretch/mode="2d"
window/stretch/aspect="keep"
window/stretch/shrink="1"
[importer_defaults]

1
sfx/.gitignore vendored 100644
View File

@ -0,0 +1 @@
.proj/

BIN
sfx/WOD_sfx.ogg 100644

Binary file not shown.

BIN
sfx/dead.sfx 100644

Binary file not shown.

BIN
sfx/dead.wav 100644

Binary file not shown.

BIN
sfx/jump.wav 100644

Binary file not shown.

BIN
sfx/laser.wav 100644

Binary file not shown.

Binary file not shown.

BIN
sfx/wall_move.wav 100644

Binary file not shown.

Binary file not shown.

36
wall.gd
View File

@ -1,41 +1,27 @@
extends StaticBody2D
# class member variables go here, for example:
# var a = 2
# var b = "textvar"
var shift = 0
#var moving = false
var hspeed = Vector2(-4,0)
#var shift = 0
onready var tween_node = $Tween
onready var h = $Sprite.get_texture().get_size().y
signal out_of_bound(wall)
signal moving(state);
onready var w = $Sprite.get_texture().get_size().x
signal moving(state)
func _ready():
hspeed.x -= min(Global.diff_level*0.5,4)
update()
func _physics_process(delta):
# # Called every frame. Delta is time since last frame.
# # Update game logic here.
# pass
position += hspeed
#move_and_slide(hspeed)
if position.x< - $Sprite.get_texture().get_size().x:
emit_signal("out_of_bound",self)
func _draw():
draw_rect(Rect2(0,0,Global.WALL_WIDTH, Global.GRID_SIZE), Color(1,1,1), true)
func set_shift(duration, shift):
$Timer.set_wait_time(duration)
self.shift = shift
$Timer.start()
func _on_Timer_timeout():
#position.y += shift
func shift_position(shift):
emit_signal("moving",true)
$move_sfx.play()
tween_node.interpolate_property(self, "position:y",
position.y, position.y + shift, 0.2, Tween.TRANS_LINEAR, Tween.EASE_IN)
tween_node.start()
func _on_Tween_tween_completed(object, key):
$stop_sfx.play()
$move_sfx.stop()
emit_signal("moving",false)