Last active
September 17, 2019 20:46
-
-
Save amirrajan/942ba515527e85c69700ffeb0c0bdb34 to your computer and use it in GitHub Desktop.
Vertical space shooter in DragonRuby Game Toolkit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def new_enemy args | |
{ x: 1280.randomize(:ratio), | |
starting_y: 800, | |
final_distance: 900, | |
duration: 60.randomize(:ratio) + 180, | |
created_at: args.state.tick_count, | |
size: 32, | |
fire_rate: (30.randomize(:ratio) + (60 - args.state.score)).to_i } | |
end | |
def new_bullet args, starting_x, starting_y, enemy_speed | |
b = { x: starting_x, | |
starting_y: starting_y, | |
final_distance: 900 + (800 - starting_y), | |
created_at: args.state.tick_count, | |
size: 5 } | |
b[:duration] = b[:final_distance] / (enemy_speed + 2.0 + (5.0 * args.state.score.fdiv(100))) | |
b | |
end | |
def new_player_bullet args, starting_x, starting_y, player_speed | |
b = { x: starting_x, | |
starting_y: starting_y, | |
final_distance: starting_y - 900, | |
created_at: args.state.tick_count, | |
size: 5 } | |
b[:duration] = (b[:final_distance] / (player_speed + 2.0)).abs | |
b | |
end | |
def defaults args | |
args.state.tick_count ||= Kernel.tick_count | |
args.state.score ||= 0 | |
args.state.enemies ||= [] | |
args.state.bullets ||= [] | |
args.state.player_bullets ||= [] | |
args.state.max_enemies = 10 | |
args.state.player.x ||= 640 | |
args.state.player.y ||= 100 | |
args.state.player.size ||= 32 | |
if args.state.enemies.length == 0 | |
args.state.max_enemies.times do | |
s = new_enemy args | |
s[:created_at] += s[:duration].randomize(:ratio) | |
args.state.enemies << s | |
end | |
end | |
end | |
def input args | |
if args.inputs.keyboard.left | |
args.state.player.x -= 5 | |
elsif args.inputs.keyboard.right | |
args.state.player.x += 5 | |
end | |
if args.inputs.keyboard.up | |
args.state.player.y += 5 | |
elsif args.inputs.keyboard.down | |
args.state.player.y -= 5 | |
end | |
if args.inputs.keyboard.key_down.space | |
args.state.player_bullets << new_player_bullet(args, | |
args.state.player.x + args.state.player.size.half, | |
args.state.player.y + args.state.player.size, 5) | |
end | |
args.state.player.y = args.state.player.y.greater(0).lesser(720 - args.state.player.size) | |
args.state.player.x = args.state.player.x.greater(0).lesser(1280 - args.state.player.size) | |
end | |
def completed? entity | |
(entity[:created_at] + entity[:duration]).elapsed_time > 0 | |
end | |
def move_enemies args | |
if (enemies_to_add = args.state.max_enemies - args.state.enemies.length) > 0 | |
enemies_to_add.times { args.state.enemies << new_enemy(args) } | |
end | |
args.state.enemies = args.state.enemies.reject { |s| completed? s } | |
end | |
def move_bullets args | |
args.state.enemies.each do |e| | |
if args.state.tick_count.mod_zero?(e[:fire_rate]) | |
args.state.bullets << new_bullet(args, e[:x] + e[:size].half, current_y(e), e[:final_distance] / e[:duration]) | |
end | |
end | |
args.state.bullets = args.state.bullets.reject { |s| completed? s } | |
args.state.player_bullets = args.state.player_bullets.reject { |s| completed? s } | |
end | |
def intersect? entity_one, entity_two | |
return false if entity_one[:x] + entity_one[:size] < entity_two[:x] | |
return false if entity_one[:x] > entity_two[:x] + entity_two[:size] | |
return false if current_y(entity_one) + entity_one[:size] < current_y(entity_two) | |
return false if current_y(entity_one) > current_y(entity_two) + entity_two[:size] | |
return true | |
end | |
def kill args | |
bullets_hitting_enemies = [] | |
args.state.player_bullets.each do |b| | |
args.state.enemies.each do |e| | |
bullets_hitting_enemies << [b, e] if intersect? b, e | |
end | |
end | |
args.state.score += bullets_hitting_enemies.length | |
bullets_hitting_enemies.flatten! | |
args.state.player_bullets.reject! { |b| bullets_hitting_enemies.flatten.include? b } | |
args.state.enemies.reject! { |e| bullets_hitting_enemies.flatten.include? e } | |
dead = args.state.bullets.any? { |b| [b[:x], current_y(b), b[:size], b[:size]].intersects_rect?([args.state.player.x, args.state.player.y, args.state.player.size, args.state.player.size]) } | |
return unless dead | |
args.state.hash.clear | |
defaults args | |
end | |
def calc args | |
move_enemies args | |
move_bullets args | |
kill args | |
end | |
def current_y entity | |
entity[:starting_y] - (entity[:final_distance] * entity[:created_at].ease(entity[:duration], :identity)) | |
end | |
def render args | |
args.outputs.solids << args.state.enemies.map do |s| | |
[s[:x], | |
current_y(s), | |
s[:size], s[:size], 255, 0, 0] | |
end | |
args.outputs.solids << args.state.bullets.map do |b| | |
[b[:x], | |
current_y(b), | |
b[:size], b[:size], 255, 0, 0] | |
end | |
args.outputs.solids << args.state.player_bullets.map do |b| | |
[b[:x], | |
current_y(b), | |
b[:size], b[:size], 0, 0, 0] | |
end | |
args.solids << [args.state.player.x, | |
args.state.player.y, | |
args.state.player.size, | |
args.state.player.size, 0, 0, 0] | |
end | |
def tick args | |
defaults args | |
input args | |
calc args | |
render args | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment