summaryrefslogtreecommitdiffhomepage
path: root/samples/99_genre_platformer/gorillas_basic/app/main.rb
diff options
context:
space:
mode:
authorAmir Rajan <[email protected]>2020-09-11 02:02:01 -0500
committerAmir Rajan <[email protected]>2020-09-11 02:02:57 -0500
commit33ec37b141e896b47ed642923fd33b0c658ae9fb (patch)
treea40d3e5d41beeb06508200078f6f26b0ee57d6a4 /samples/99_genre_platformer/gorillas_basic/app/main.rb
parent958cf43779d2bf528869e80511c4c4f2a433b2db (diff)
downloaddragonruby-game-toolkit-contrib-33ec37b141e896b47ed642923fd33b0c658ae9fb.tar.gz
dragonruby-game-toolkit-contrib-33ec37b141e896b47ed642923fd33b0c658ae9fb.zip
synced samples
Diffstat (limited to 'samples/99_genre_platformer/gorillas_basic/app/main.rb')
-rw-r--r--samples/99_genre_platformer/gorillas_basic/app/main.rb373
1 files changed, 373 insertions, 0 deletions
diff --git a/samples/99_genre_platformer/gorillas_basic/app/main.rb b/samples/99_genre_platformer/gorillas_basic/app/main.rb
new file mode 100644
index 0000000..53f9a4f
--- /dev/null
+++ b/samples/99_genre_platformer/gorillas_basic/app/main.rb
@@ -0,0 +1,373 @@
+class YouSoBasicGorillas
+ attr_accessor :outputs, :grid, :state, :inputs
+
+ def tick
+ defaults
+ render
+ calc
+ process_inputs
+ end
+
+ def defaults
+ outputs.background_color = [33, 32, 87]
+ state.building_spacing = 1
+ state.building_room_spacing = 15
+ state.building_room_width = 10
+ state.building_room_height = 15
+ state.building_heights = [4, 4, 6, 8, 15, 20, 18]
+ state.building_room_sizes = [5, 4, 6, 7]
+ state.gravity = 0.25
+ state.first_strike ||= :player_1
+ state.buildings ||= []
+ state.holes ||= []
+ state.player_1_score ||= 0
+ state.player_2_score ||= 0
+ state.wind ||= 0
+ end
+
+ def render
+ render_stage
+ render_value_insertion
+ render_gorillas
+ render_holes
+ render_banana
+ render_game_over
+ render_score
+ render_wind
+ end
+
+ def render_score
+ outputs.primitives << [0, 0, 1280, 31, fancy_white].solid
+ outputs.primitives << [1, 1, 1279, 29].solid
+ outputs.labels << [ 10, 25, "Score: #{state.player_1_score}", 0, 0, fancy_white]
+ outputs.labels << [1270, 25, "Score: #{state.player_2_score}", 0, 2, fancy_white]
+ end
+
+ def render_wind
+ outputs.primitives << [640, 12, state.wind * 500 + state.wind * 10 * rand, 4, 35, 136, 162].solid
+ outputs.lines << [640, 30, 640, 0, fancy_white]
+ end
+
+ def render_game_over
+ return unless state.over
+ outputs.primitives << [grid.rect, 0, 0, 0, 200].solid
+ outputs.primitives << [640, 370, "Game Over!!", 5, 1, fancy_white].label
+ if state.winner == :player_1
+ outputs.primitives << [640, 340, "Player 1 Wins!!", 5, 1, fancy_white].label
+ else
+ outputs.primitives << [640, 340, "Player 2 Wins!!", 5, 1, fancy_white].label
+ end
+ end
+
+ def render_stage
+ return unless state.stage_generated
+ return if state.stage_rendered
+
+ outputs.static_solids << [grid.rect, 33, 32, 87]
+ outputs.static_solids << state.buildings.map(&:solids)
+ state.stage_rendered = true
+ end
+
+ def render_gorilla gorilla, id
+ return unless gorilla
+ if state.banana && state.banana.owner == gorilla
+ animation_index = state.banana.created_at.frame_index(3, 5, false)
+ end
+ if !animation_index
+ outputs.sprites << [gorilla.solid, "sprites/#{id}-idle.png"]
+ else
+ outputs.sprites << [gorilla.solid, "sprites/#{id}-#{animation_index}.png"]
+ end
+ end
+
+ def render_gorillas
+ render_gorilla state.player_1, :left
+ render_gorilla state.player_2, :right
+ end
+
+ def render_value_insertion
+ return if state.banana
+ return if state.over
+
+ if state.current_turn == :player_1_angle
+ outputs.labels << [ 10, 710, "Angle: #{state.player_1_angle}_", fancy_white]
+ elsif state.current_turn == :player_1_velocity
+ outputs.labels << [ 10, 710, "Angle: #{state.player_1_angle}", fancy_white]
+ outputs.labels << [ 10, 690, "Velocity: #{state.player_1_velocity}_", fancy_white]
+ elsif state.current_turn == :player_2_angle
+ outputs.labels << [1120, 710, "Angle: #{state.player_2_angle}_", fancy_white]
+ elsif state.current_turn == :player_2_velocity
+ outputs.labels << [1120, 710, "Angle: #{state.player_2_angle}", fancy_white]
+ outputs.labels << [1120, 690, "Velocity: #{state.player_2_velocity}_", fancy_white]
+ end
+ end
+
+ def render_banana
+ return unless state.banana
+ rotation = state.tick_count.%(360) * 20
+ rotation *= -1 if state.banana.dx > 0
+ outputs.sprites << [state.banana.x, state.banana.y, 15, 15, 'sprites/banana.png', rotation]
+ end
+
+ def render_holes
+ outputs.sprites << state.holes.map do |s|
+ animation_index = s.created_at.frame_index(7, 3, false)
+ if animation_index
+ [s.sprite, [s.sprite.rect, "sprites/explosion#{animation_index}.png" ]]
+ else
+ s.sprite
+ end
+ end
+ end
+
+ def calc
+ calc_generate_stage
+ calc_current_turn
+ calc_banana
+ end
+
+ def calc_current_turn
+ return if state.current_turn
+
+ state.current_turn = :player_1_angle
+ state.current_turn = :player_2_angle if state.first_strike == :player_2
+ end
+
+ def calc_generate_stage
+ return if state.stage_generated
+
+ state.buildings << building_prefab(state.building_spacing + -20, *random_building_size)
+ 8.numbers.inject(state.buildings) do |buildings, i|
+ buildings <<
+ building_prefab(state.building_spacing +
+ state.buildings.last.right,
+ *random_building_size)
+ end
+
+ building_two = state.buildings[1]
+ state.player_1 = new_player(building_two.x + building_two.w.fdiv(2),
+ building_two.h)
+
+ building_nine = state.buildings[-3]
+ state.player_2 = new_player(building_nine.x + building_nine.w.fdiv(2),
+ building_nine.h)
+ state.stage_generated = true
+ state.wind = 1.randomize(:ratio, :sign)
+ end
+
+ def new_player x, y
+ state.new_entity(:gorilla) do |p|
+ p.x = x - 25
+ p.y = y
+ p.solid = [p.x, p.y, 50, 50]
+ end
+ end
+
+ def calc_banana
+ return unless state.banana
+
+ state.banana.x += state.banana.dx
+ state.banana.dx += state.wind.fdiv(50)
+ state.banana.y += state.banana.dy
+ state.banana.dy -= state.gravity
+ banana_collision = [state.banana.x, state.banana.y, 10, 10]
+
+ if state.player_1 && banana_collision.intersect_rect?(state.player_1.solid)
+ state.over = true
+ if state.banana.owner == state.player_2
+ state.winner = :player_2
+ else
+ state.winner = :player_1
+ end
+
+ state.player_2_score += 1
+ elsif state.player_2 && banana_collision.intersect_rect?(state.player_2.solid)
+ state.over = true
+ if state.banana.owner == state.player_2
+ state.winner = :player_1
+ else
+ state.winner = :player_2
+ end
+ state.player_1_score += 1
+ end
+
+ if state.over
+ place_hole
+ return
+ end
+
+ return if state.holes.any? do |h|
+ h.sprite.scale_rect(0.8, 0.5, 0.5).intersect_rect? [state.banana.x, state.banana.y, 10, 10]
+ end
+
+ return unless state.banana.y < 0 || state.buildings.any? do |b|
+ b.rect.intersect_rect? [state.banana.x, state.banana.y, 1, 1]
+ end
+
+ place_hole
+ end
+
+ def place_hole
+ return unless state.banana
+
+ state.holes << state.new_entity(:banana) do |b|
+ b.sprite = [state.banana.x - 20, state.banana.y - 20, 40, 40, 'sprites/hole.png']
+ end
+
+ state.banana = nil
+ end
+
+ def process_inputs_main
+ return if state.banana
+ return if state.over
+
+ if inputs.keyboard.key_down.enter
+ input_execute_turn
+ elsif inputs.keyboard.key_down.backspace
+ state.as_hash[state.current_turn] ||= ""
+ state.as_hash[state.current_turn] = state.as_hash[state.current_turn][0..-2]
+ elsif inputs.keyboard.key_down.char
+ state.as_hash[state.current_turn] ||= ""
+ state.as_hash[state.current_turn] += inputs.keyboard.key_down.char
+ end
+ end
+
+ def process_inputs_game_over
+ return unless state.over
+ return unless inputs.keyboard.key_down.truthy_keys.any?
+ state.over = false
+ outputs.static_solids.clear
+ state.buildings.clear
+ state.holes.clear
+ state.stage_generated = false
+ state.stage_rendered = false
+ if state.first_strike == :player_1
+ state.first_strike = :player_2
+ else
+ state.first_strike = :player_1
+ end
+ end
+
+ def process_inputs
+ process_inputs_main
+ process_inputs_game_over
+ end
+
+ def input_execute_turn
+ return if state.banana
+
+ if state.current_turn == :player_1_angle && parse_or_clear!(:player_1_angle)
+ state.current_turn = :player_1_velocity
+ elsif state.current_turn == :player_1_velocity && parse_or_clear!(:player_1_velocity)
+ state.current_turn = :player_2_angle
+ state.banana =
+ new_banana(state.player_1,
+ state.player_1.x + 25,
+ state.player_1.y + 60,
+ state.player_1_angle,
+ state.player_1_velocity)
+ elsif state.current_turn == :player_2_angle && parse_or_clear!(:player_2_angle)
+ state.current_turn = :player_2_velocity
+ elsif state.current_turn == :player_2_velocity && parse_or_clear!(:player_2_velocity)
+ state.current_turn = :player_1_angle
+ state.banana =
+ new_banana(state.player_2,
+ state.player_2.x + 25,
+ state.player_2.y + 60,
+ 180 - state.player_2_angle,
+ state.player_2_velocity)
+ end
+
+ if state.banana
+ state.player_1_angle = nil
+ state.player_1_velocity = nil
+ state.player_2_angle = nil
+ state.player_2_velocity = nil
+ end
+ end
+
+ def random_building_size
+ [state.building_heights.sample, state.building_room_sizes.sample]
+ end
+
+ def int? v
+ v.to_i.to_s == v.to_s
+ end
+
+ def random_building_color
+ [[ 99, 0, 107],
+ [ 35, 64, 124],
+ [ 35, 136, 162],
+ ].sample
+ end
+
+ def random_window_color
+ [[ 88, 62, 104],
+ [253, 224, 187]].sample
+ end
+
+ def windows_for_building starting_x, floors, rooms
+ floors.-(1).combinations(rooms - 1).map do |floor, room|
+ [starting_x +
+ state.building_room_width.*(room) +
+ state.building_room_spacing.*(room + 1),
+ state.building_room_height.*(floor) +
+ state.building_room_spacing.*(floor + 1),
+ state.building_room_width,
+ state.building_room_height,
+ random_window_color]
+ end
+ end
+
+ def building_prefab starting_x, floors, rooms
+ state.new_entity(:building) do |b|
+ b.x = starting_x
+ b.y = 0
+ b.w = state.building_room_width.*(rooms) +
+ state.building_room_spacing.*(rooms + 1)
+ b.h = state.building_room_height.*(floors) +
+ state.building_room_spacing.*(floors + 1)
+ b.right = b.x + b.w
+ b.rect = [b.x, b.y, b.w, b.h]
+ b.solids = [[b.x - 1, b.y, b.w + 2, b.h + 1, fancy_white],
+ [b.x, b.y, b.w, b.h, random_building_color],
+ windows_for_building(b.x, floors, rooms)]
+ end
+ end
+
+ def parse_or_clear! game_prop
+ if int? state.as_hash[game_prop]
+ state.as_hash[game_prop] = state.as_hash[game_prop].to_i
+ return true
+ end
+
+ state.as_hash[game_prop] = nil
+ return false
+ end
+
+ def new_banana owner, x, y, angle, velocity
+ state.new_entity(:banana) do |b|
+ b.owner = owner
+ b.x = x
+ b.y = y
+ b.angle = angle % 360
+ b.velocity = velocity / 5
+ b.dx = b.angle.vector_x(b.velocity)
+ b.dy = b.angle.vector_y(b.velocity)
+ end
+ end
+
+ def fancy_white
+ [253, 252, 253]
+ end
+end
+
+$you_so_basic_gorillas = YouSoBasicGorillas.new
+
+def tick args
+ $you_so_basic_gorillas.outputs = args.outputs
+ $you_so_basic_gorillas.grid = args.grid
+ $you_so_basic_gorillas.state = args.state
+ $you_so_basic_gorillas.inputs = args.inputs
+ $you_so_basic_gorillas.tick
+end