diff --git a/app/main.rb b/app/main.rb index b513062..5f27c1b 100644 --- a/app/main.rb +++ b/app/main.rb @@ -14,6 +14,8 @@ require "app/scenes/main_menu.rb" require "app/scenes/paused.rb" require "app/scenes/settings.rb" +require "app/scenes/cube_tube.rb" + # NOTE: add all requires above this require "app/tick.rb" diff --git a/app/scenes/cube_tube.rb b/app/scenes/cube_tube.rb new file mode 100644 index 0000000..67fef63 --- /dev/null +++ b/app/scenes/cube_tube.rb @@ -0,0 +1,393 @@ +module Scene + class << self + def tick_cube_tube(args) + tick_gameplay(args) + args.state.game ||= BlockTubeGame.new args + args.state.game.tick + end + end +end + + +class BlockTubeGame + def initialize args + @args = args + + @blocksize = 30 + @grid_w = 10 + @grid_h = 20 + @grid_x = (720 - (@grid_w * @blocksize)) / 2 + @grid_y = ((1280 - (@grid_h * @blocksize)) / 2) + 150 + + @next_piece_box = [-1, -9, 7, 7] + + @color_index = [ + [000, 000, 000], + [255, 000, 000], + [000, 255, 000], + [000, 000, 255], + [255, 255, 000], + [000, 255, 255], + [255, 000, 255], + [255, 127, 000], + [127, 127, 127], + ] + + @sprite_index = [ + "sprites/square/black.png", + "sprites/square/red.png", + "sprites/square/green.png", + "sprites/square/blue.png", + "sprites/square/yellow.png", + "sprites/square/indigo.png", + "sprites/square/violet.png", + "sprites/square/orange.png", + "sprites/square/gray.png", + ] + + @grid = [] + + @lines = 0 + @level = 0 + @current_speed = 0 + @next_move = 0 + @gameover = false + @showgameover = false + + @current_piece_x = 0 + @current_piece_y = 0 + @current_piece = nil + @next_piece = nil + @lines_to_clear = [] + @line_clear_timer = 0 + + reset_game + end + + def reset_game + @lines = 0 + @level = 9 + @current_speed = get_speed + @next_move = @current_speed + @gameover = false + @showgameover = false + + @current_piece_x = 4 + @current_piece_y = -1 + @current_piece = nil + @next_piece = nil + select_next_piece + @lines_to_clear = [] + @line_clear_timer = 0 + + for x in 0..@grid_w-1 do + @grid[x] = [] + for y in 0..@grid_h-1 do + @grid[x][y] = 0 + end + end + end + + def render_grid_border x, y, w, h, color + + for i in x..(x+w)-1 do + render_block i, y, color + render_block i, (y + h - 1), color + end + + for i in y..(y+h)-1 do + render_block x, i, color + render_block (x + w - 1), i, color + end + end + + def render_background + # draw a solid black background + @args.outputs.solids << [ + 0, + 0, + 1280, + 1280, + *@color_index[0] + ] + end + + # x and y are positions in the grid, not pixels + def render_block x, y, color + @args.outputs.sprites << [ + (1280 - @grid_y) - (y * @blocksize), + @grid_x + (x * @blocksize), + @blocksize, @blocksize, + @sprite_index[color] + ] + end + + def render_grid + + render_grid_border -1, -1, @grid_w + 2, @grid_h + 2, 8 + + for x in 0..@grid_w-1 do + for y in 0..@grid_h-1 do + render_block x, y, @grid[x][y] if @grid[x][y] != 0 && (!@lines_to_clear.include?(y) || (@line_clear_timer % 14) < 7) + end + end + + end + + def render_piece piece, piece_x, piece_y + + for x in 0..piece.length-1 do + for y in 0..piece[x].length-1 do + render_block piece_x + x, piece_y + y, piece[x][y] if piece[x][y] != 0 + end + end + end + + def render_current_piece + render_piece @current_piece, @current_piece_x, @current_piece_y if @line_clear_timer <= 0 + end + + def render_next_piece + next_piece = @line_clear_timer <= 0 ? @next_piece : @current_piece + render_grid_border *@next_piece_box, 8 + centerx = (@next_piece_box[2] - next_piece.length) / 2 + centery = (@next_piece_box[3] - next_piece[0].length) / 2 + + render_piece next_piece, @next_piece_box[0] + centerx, @next_piece_box[1] + centery + + @args.outputs.labels << [ 892, 431, "Next piece", 10, 255, 255, 255, 255 ] + end + + def render_score + @args.outputs.labels << [ 200, 600, "Lines: #{@lines}", 10, 255, 255, 255, 255 ] + @args.outputs.labels << [ 400, 600, "Level: #{@level}", 10, 255, 255, 255, 255 ] + @args.outputs.labels << [ 400, 563, "(Speed: #{(1/(@current_speed/60)).round 2} L/s)", 0.1, 255, 255, 255, 255 ] + end + + def render_gameover + @args.outputs.solids << [ 0, 245, 1280, 200, 0, 0, 0, 255] + @args.outputs.labels << [ 200, 450, "GAME OVER", 100, 255, 255, 255, 255 ] + end + + def render + render_background + render_next_piece + render_current_piece + render_grid + render_score + render_gameover if @showgameover + end + + def current_piece_colliding + for x in 0..@current_piece.length-1 do + for y in 0..@current_piece[x].length-1 do + if (@current_piece[x][y] != 0) && ((@current_piece_y + y >= @grid_h) || ((@current_piece_y + y) >= 0 && @grid[@current_piece_x + x][@current_piece_y + y] != 0 )) + return true + end + end + end + return false + end + + def get_speed + return case @level + when 0 then 53 + when 1 then 49 + when 2 then 45 + when 3 then 41 + when 4 then 37 + when 5 then 33 + when 6 then 28 + when 7 then 22 + when 8 then 17 + when 9 then 11 + when 10 then 10 + when 11 then 9 + when 12 then 8 + when 13 then 7 + when 14 then 6 + when 15 then 6 + when 16 then 5 + when 17 then 5 + when 18 then 4 + when 19 then 4 + when 20 then 3 + else 3 + end + end + + def plant_current_piece + rows_to_check = [] + + for x in 0..@current_piece.length-1 do + for y in 0..@current_piece[x].length-1 do + if @current_piece[x][y] != 0 + col = @current_piece_x + x + row = @current_piece_y + y + @grid[col][row] = @current_piece[x][y] + rows_to_check << row if !rows_to_check.include? row + end + end + end + + @lines_to_clear = [] + + # see if any rows need to be cleared out + for y in 0..@grid_h-1 + full = true + for x in 0..@grid_w-1 + if @grid[x][y] == 0 + full = false + break + end + end + + if full # no empty space in the row + @lines_to_clear.push y + @lines += 1 + @level += 1 if (@lines%10).floor == 0 + @line_clear_timer = 70 + end + end + + select_next_piece + if @lines_to_clear.empty? + if current_piece_colliding + @gameover = true + end + else + @current_speed = get_speed + end + + @next_move = @current_speed + 2 + end + + def select_next_piece + + @current_piece = @next_piece + + @current_piece_x = 4 + @current_piece_y = -1 + + r = (rand 7) + 1 + @next_piece = case r + when 1 then [ [r, 0], [r, r], [0, r]] + when 2 then [ [0, r], [r, r], [r, 0]] + when 3 then [ [r, r, r], [r, 0, 0]] + when 4 then [ [r, r], [r, r] ] + when 5 then [ [r], [r], [r], [r]] + when 6 then [ [r, 0], [r, r], [r, 0]] + when 7 then [ [r, 0, 0], [r, r, r]] + end + select_next_piece if @current_piece == nil + end + + def rotate_current_piece_left + @current_piece = @current_piece.transpose.map(&:reverse) + if(@current_piece_x + @current_piece.length) >= @grid_w + @current_piece_x = @grid_w - @current_piece.length + end + end + + def rotate_current_piece_right + @current_piece = @current_piece.transpose.map(&:reverse) + @current_piece = @current_piece.transpose.map(&:reverse) + @current_piece = @current_piece.transpose.map(&:reverse) + end + + def fill_grid + b = false + for y in 0..@grid_h-1 do + for x in 0..@grid_w-1 do + if @grid[x][y] == 0 + @grid[x][y] = (rand 7) + 1 + b = true + end + end + return if b + end + @showgameover = true + end + + def restart_game + reset_game + end + + def iterate + + # check input first + k = @args.inputs.keyboard + c = @args.inputs.controller_one + + if @gameover + if @showgameover + if k.key_down.space || k.key_down.enter || c.key_down.start + restart_game + end + else + fill_grid + end + return + end + + if @line_clear_timer > 0 + @line_clear_timer -= 1 + if @line_clear_timer == 0 + for y in @lines_to_clear + for i in y.downto(1) do + for j in 0..@grid_w-1 + @grid[j][i] = @grid[j][i-1] + end + end + for i in 0..@grid_w-1 + @grid[i][0] = 0 + end + end + @lines_to_clear = [] + end + return + end + + if k.key_down.down || k.key_down.s || c.key_down.down + if @current_piece_x > 0 + @current_piece_x -= 1 + if current_piece_colliding + @current_piece_x += 1 + end + end + end + if k.key_down.up || k.key_down.w || c.key_down.up + if (@current_piece_x + @current_piece.length) < @grid_w + @current_piece_x += 1 + if current_piece_colliding + @current_piece_x -= 1 + end + end + end + if k.key_down.left || k.key_held.left || k.key_down.a || k.key_held.a || c.key_down.left || c.key_held.left + @next_move -= @current_speed / 3 + end + + if k.key_down.q || c.key_down.a + rotate_current_piece_left + end + if k.key_down.e || c.key_down.b + rotate_current_piece_right + end + + @next_move -= 1 + if @next_move <= 0 + @next_move = @current_speed + @current_piece_y += 1 + if current_piece_colliding + @current_piece_y -= 1 + plant_current_piece + end + end + end + + def tick + iterate + render + end +end \ No newline at end of file diff --git a/app/scenes/gameplay.rb b/app/scenes/gameplay.rb index 56c89b4..8dec146 100644 --- a/app/scenes/gameplay.rb +++ b/app/scenes/gameplay.rb @@ -21,7 +21,7 @@ module Scene draw_bg(args, BLACK) - labels << label("GAMEPLAY", x: 40, y: args.grid.top - 40, size: SIZE_LG, font: FONT_BOLD) + # labels << label("GAMEPLAY", x: 40, y: args.grid.top - 40, size: SIZE_LG, font: FONT_BOLD) args.outputs.labels << labels args.outputs.sprites << sprites end diff --git a/app/scenes/main_menu.rb b/app/scenes/main_menu.rb index a20201f..929581f 100644 --- a/app/scenes/main_menu.rb +++ b/app/scenes/main_menu.rb @@ -6,7 +6,7 @@ module Scene options = [ { key: :start, - on_select: -> (args) { Scene.switch(args, :gameplay, reset: true) } + on_select: -> (args) { Scene.switch(args, :cube_tube, reset: true) } }, { key: :settings, diff --git a/metadata/game_metadata.txt b/metadata/game_metadata.txt index 4f614fe..300de3e 100644 --- a/metadata/game_metadata.txt +++ b/metadata/game_metadata.txt @@ -1,7 +1,7 @@ -devid=myitchusername -devtitle=My Name -gameid=my-game-title -gametitle=My Game Title +devid=death.au +devtitle=death.au +gameid=cube-tube +gametitle=Cube Tube version=0.1-dev icon=metadata/icon.png diff --git a/sprites/square/black.png b/sprites/square/black.png new file mode 100644 index 0000000..1a80bda Binary files /dev/null and b/sprites/square/black.png differ diff --git a/sprites/square/blue.png b/sprites/square/blue.png new file mode 100644 index 0000000..3194ff5 Binary files /dev/null and b/sprites/square/blue.png differ diff --git a/sprites/square/gray.png b/sprites/square/gray.png new file mode 100644 index 0000000..b94f1dd Binary files /dev/null and b/sprites/square/gray.png differ diff --git a/sprites/square/green.png b/sprites/square/green.png new file mode 100644 index 0000000..d14a892 Binary files /dev/null and b/sprites/square/green.png differ diff --git a/sprites/square/indigo.png b/sprites/square/indigo.png new file mode 100644 index 0000000..f66aa46 Binary files /dev/null and b/sprites/square/indigo.png differ diff --git a/sprites/square/orange.png b/sprites/square/orange.png new file mode 100644 index 0000000..bf023bc Binary files /dev/null and b/sprites/square/orange.png differ diff --git a/sprites/square/red.png b/sprites/square/red.png new file mode 100644 index 0000000..a59443e Binary files /dev/null and b/sprites/square/red.png differ diff --git a/sprites/square/violet.png b/sprites/square/violet.png new file mode 100644 index 0000000..c8f3db8 Binary files /dev/null and b/sprites/square/violet.png differ diff --git a/sprites/square/white.png b/sprites/square/white.png new file mode 100644 index 0000000..7a233ea Binary files /dev/null and b/sprites/square/white.png differ diff --git a/sprites/square/yellow.png b/sprites/square/yellow.png new file mode 100644 index 0000000..3b586c4 Binary files /dev/null and b/sprites/square/yellow.png differ