dl-tetris 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,41 @@
1
+ Dave and Luke's Tetris clone
2
+ ----------------------------
3
+
4
+ A quick little tetris clone written in Ruby. It uses the [rubygame](http://rubygame.org/) library and was originally based from [this great template](http://rubygame.org/wiki/Generic_Game_Template).
5
+
6
+ It was started by Dave to practice Ruby and Luke has since seperated it out and turned it into a 'proper' project.
7
+
8
+ Arrow keys move, up arrow rotates and space drops your piece.
9
+
10
+ ![Tetris Screenshot 1](http://kzar.co.uk/images/tetris.png)
11
+
12
+ Notes
13
+ -----
14
+
15
+ - If you're using a Mac you will need to run this with [RSDL](https://github.com/knu/rsdl) instead of the normal Ruby command.
16
+ - If you're not using a Mac you will need to change the font path.
17
+ - You will need to install libsdl, sdl_gfx, sdl_ttf, rubygame, rsdl (see above) and Ruby 1.9 for this to work properly.
18
+
19
+ Todo
20
+ ----
21
+
22
+ - Music!
23
+ - End game logic
24
+ - Special effects?!
25
+ - [XKCD setting?!](http://xkcd.com/724/)
26
+
27
+ Licence
28
+ -------
29
+
30
+ Copyright Dave Barker and Luke Antins 2010
31
+
32
+ This program is free software: you can redistribute it and/or modify
33
+ it under the terms of the GNU General Public License as published by
34
+ the Free Software Foundation, either version 3 of the License, or
35
+ (at your option) any later version.
36
+ This program is distributed in the hope that it will be useful,
37
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
38
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39
+ GNU General Public License for more details.
40
+ You should have received a copy of the GNU General Public License
41
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -0,0 +1,22 @@
1
+ require 'rake/testtask'
2
+ require 'fileutils'
3
+ require 'yard'
4
+ require 'yard/rake/yardoc_task'
5
+
6
+ task :default => :'test'
7
+
8
+ # Testing
9
+ desc 'Run tests'
10
+ Rake::TestTask.new(:test) do |task|
11
+ task.test_files = FileList['test/**/*_test.rb']
12
+ task.verbose = true
13
+ end
14
+
15
+ ##
16
+ # docs task.
17
+ desc 'Build documentation.'
18
+ YARD::Rake::YardocTask.new :yardoc do |t|
19
+ t.files = ['lib/**/*.rb']
20
+ t.options = ['--output-dir', "doc/",
21
+ '--title', 'Dave and Luke\'s Tetris Clone - API Documentation']
22
+ end
@@ -0,0 +1,10 @@
1
+ # hack the path.
2
+ $CURRENT_DIR = File.dirname(File.expand_path(__FILE__))
3
+ $LOAD_PATH.unshift $CURRENT_DIR + '/../lib'
4
+
5
+ # lets roll.
6
+ require 'tetris'
7
+
8
+ # init the game, and run the main game loop.
9
+ game = Game.new(10, 20, 1000, "/Library/Fonts/Chalkduster.ttf")
10
+ game.run
@@ -0,0 +1,10 @@
1
+ # hack the path.
2
+ $CURRENT_DIR = File.dirname(File.expand_path(__FILE__))
3
+ $LOAD_PATH.unshift $CURRENT_DIR + '/../lib'
4
+
5
+ # lets roll.
6
+ require 'tetris'
7
+
8
+ # init the game, and run the main game loop.
9
+ game = Game.new(10, 20, 1000, "/Library/Fonts/Chalkduster.ttf")
10
+ game.run
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rsdl
2
+ load "boot.rb"
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rsdl
2
+ load boot.rb
@@ -0,0 +1,42 @@
1
+ # Dave's Tetris clone, Dave Barker 2010
2
+ #
3
+ # (Requires rubygame, rsdl, sdl, sdl_graphics, sdl_ttf and ruby >= 1.9)
4
+ # (Make sure you put Chalkduster.ttf if working directory)
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ #
17
+ # Code was started from this great rubygame template:
18
+ # http://rubygame.org/wiki/Generic_Game_Template
19
+
20
+ require 'rubygame'
21
+
22
+ require 'tetris/core_ruby_ext'
23
+ require 'tetris/game'
24
+ require 'tetris/map'
25
+ require 'tetris/piece'
26
+
27
+ $TileSize = 20
28
+ $Colours = [:blue, :red, :pink, :green, :cyan, :purple, :yellow]
29
+
30
+ $Pieces = [[" , # , # , ## ",
31
+ " , , # , ###",
32
+ " , ## , # , # ",
33
+ " , , ###, #"],
34
+ [" , ## , ## , "],
35
+ [" , ,####, ",
36
+ " # , # , # , # "],
37
+ [" , ##, ## , ",
38
+ " , # , ## , # "],
39
+ [" , # , ###, ",
40
+ " , # , ##, # ",
41
+ " , , ###, # ",
42
+ " , # , ## , # "]]
@@ -0,0 +1,5 @@
1
+ class Array
2
+ def rand_item
3
+ self[rand(self.length)]
4
+ end
5
+ end
@@ -0,0 +1,79 @@
1
+ class Game
2
+ def initialize(w, h, speed, font_file)
3
+ # Setup rubygame stuff
4
+ @screen = Rubygame::Screen.new([w * $TileSize, h * $TileSize], 0,
5
+ [Rubygame::HWSURFACE, Rubygame::DOUBLEBUF])
6
+ @queue = Rubygame::EventQueue.new
7
+ @clock = Rubygame::Clock.new
8
+ @clock.target_framerate = 30
9
+ Rubygame::TTF.setup
10
+ @ttf = Rubygame::TTF.new(font_file, 20)
11
+
12
+ # Setup the game of tetris
13
+ @screen.title = "Tetris"
14
+ @map = Map.new(w, h)
15
+ @piece = Piece.new
16
+ @background = :white
17
+ @speed = speed
18
+ @step = 0
19
+ @score = 0
20
+ end
21
+
22
+ def run
23
+ loop do
24
+ update(@clock.tick)
25
+ draw
26
+ end
27
+ end
28
+
29
+ def update(time_delta)
30
+ # Process the event queue
31
+ @queue.each do |ev|
32
+ case ev
33
+ when Rubygame::KeyDownEvent
34
+ case(ev.key)
35
+ when Rubygame::K_LEFT
36
+ @piece.move(-1, 0, @map)
37
+ when Rubygame::K_RIGHT
38
+ @piece.move(1, 0, @map)
39
+ when Rubygame::K_DOWN
40
+ @piece.move(0, 1, @map)
41
+ when Rubygame::K_UP
42
+ @piece.rotate(@map)
43
+ when Rubygame::K_SPACE
44
+ @piece.drop(@map)
45
+ end
46
+ when Rubygame::QuitEvent
47
+ Rubygame.quit
48
+ exit
49
+ end
50
+ end
51
+ # Update the game state
52
+ @step += time_delta
53
+ if @step > @speed
54
+ @step -= @speed
55
+ @piece.move(0, 1, @map)
56
+ end
57
+ @piece.update(@map) {|x, y, colour| @map.set(x, y, colour)}
58
+ @score += @map.update
59
+ end
60
+
61
+ def draw_square(x, y, colour, border=true)
62
+ # Setup the points for SDL
63
+ x_pos = x * $TileSize
64
+ y_pos = y * $TileSize
65
+ pt1 = [x_pos, y_pos]
66
+ pt2 = [x_pos + $TileSize, y_pos + $TileSize]
67
+ # Draw the square and then the border
68
+ @screen.draw_box_s(pt1, pt2, colour)
69
+ @screen.draw_box(pt1, pt2, :black) if border
70
+ end
71
+
72
+ def draw
73
+ @screen.fill(@background)
74
+ @piece.squares {|x, y, colour| draw_square(x, y, colour)}
75
+ @map.draw {|coords, colour| draw_square(coords[0], coords[1], colour)}
76
+ @ttf.render("Score: " + @score.to_s, true, :black).blit(@screen, [0,0])
77
+ @screen.flip
78
+ end
79
+ end
@@ -0,0 +1,68 @@
1
+ class Map
2
+ def initialize(w, h)
3
+ @w = w
4
+ @h = h
5
+ @tiles = Array.new(w, nil)
6
+ end
7
+
8
+ def clear(x, y, w, h)
9
+ (x..(x + w)).each do |x|
10
+ (y..(y + h)).each do |y|
11
+ set(x, y, nil)
12
+ end
13
+ end
14
+ end
15
+
16
+ def set(x, y, colour)
17
+ @tiles[pos(x,y)] = colour
18
+ end
19
+
20
+ def draw
21
+ @tiles.each_with_index do |colour, p|
22
+ yield(coords(p), colour) if colour
23
+ end
24
+ end
25
+
26
+ def free?(x, y)
27
+ x >= 0 and x < @w and y >= 0 and y < @h and not @tiles[pos(x,y)]
28
+ end
29
+
30
+ def update
31
+ points = 0
32
+ shift_lines! do |line|
33
+ # Enumerable should have an every? method
34
+ if not line.each.any? {|tile| not tile} then
35
+ points += 1
36
+ true
37
+ end
38
+ end
39
+ points
40
+ end
41
+
42
+ private
43
+
44
+ def coords(p)
45
+ [p % @w, p / @w]
46
+ end
47
+
48
+ def pos(x, y)
49
+ x + y * @w
50
+ end
51
+
52
+ def shift_lines!
53
+ (0..@h).each do |y|
54
+ row = (0..@w-1).collect {|x| @tiles[pos(x,y-1)] }
55
+ shift_line(y-1, 1) if yield row
56
+ end
57
+ end
58
+
59
+ def shift_line(y, distance)
60
+ if y < 1 then
61
+ @tiles[pos(0,y + distance)..pos(@w-1,y + distance)] = [nil] * @w
62
+ else
63
+ @tiles[pos(0,y)..pos(@w-1,y)] =
64
+ @tiles[pos(0,y-distance)..pos(@w-1,y-distance)]
65
+ shift_line(y-1, distance)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,82 @@
1
+ class Piece
2
+ @@type_width = 4
3
+
4
+ def initialize
5
+ @@types ||= load_pieces($Pieces)
6
+
7
+ @type = @@types.rand_item
8
+ @rotation = 0
9
+ @x = 0
10
+ @y = 0
11
+ @colour = $Colours.rand_item
12
+ end
13
+
14
+ def parse_piece_string(s)
15
+ s.chars.each_with_object([]) do |c, result|
16
+ case c
17
+ when " " then result << false
18
+ when "," then next
19
+ else result << true
20
+ end
21
+ end
22
+ end
23
+
24
+ def load_pieces(pieces)
25
+ pieces.collect do |piece|
26
+ piece.collect {|rotation| parse_piece_string rotation}
27
+ end
28
+ end
29
+
30
+ def squares(piece=current)
31
+ result = []
32
+ piece.each_with_index do |tile, i|
33
+ x, y = coords(i)
34
+ result << yield(@x+x, @y+y, @colour) if tile
35
+ end
36
+ return result
37
+ end
38
+
39
+ def move(x, y, map)
40
+ unless collision?(map, x, y)
41
+ @x += x
42
+ @y += y
43
+ end
44
+ end
45
+
46
+ def drop(map)
47
+ @y += 1 while not collision?(map, 0, 1)
48
+ end
49
+
50
+ def rotate(map)
51
+ @rotation = next_rotation unless collision?(map, 0, 0, @type[next_rotation])
52
+ end
53
+
54
+ def update(map)
55
+ if collision?(map, 0, 1)
56
+ squares {|x, y, colour| map.set(x, y, colour)}
57
+ initialize
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def current
64
+ @type[@rotation]
65
+ end
66
+
67
+ def next_rotation
68
+ if @rotation > @type.count - 2
69
+ return 0
70
+ else
71
+ return @rotation + 1
72
+ end
73
+ end
74
+
75
+ def coords(p)
76
+ [p % @@type_width, p / @@type_width]
77
+ end
78
+
79
+ def collision?(map, x_offset, y_offset, piece=current)
80
+ squares(piece) {|x, y, c| not map.free?(x + x_offset, y + y_offset)}.any?
81
+ end
82
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ class GameTest < Test::Unit::TestCase
4
+ def test_code_me
5
+ flunk 'bad developer'
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ require 'simplecov'
2
+
3
+ # code coverage, this must be first!
4
+ SimpleCov.start do
5
+ add_filter '/test/'
6
+ end
7
+
8
+ $TEST_DIR = File.dirname(File.expand_path(__FILE__))
9
+ $LOAD_PATH.unshift $TEST_DIR + '/../lib'
10
+ $TESTING = true
11
+
12
+ require 'test/unit'
13
+ require 'rake'
14
+ require 'turn'
15
+ require 'rr'
16
+
17
+ require 'tetris'
18
+
19
+ class Test::Unit::TestCase
20
+ include RR::Adapters::TestUnit
21
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dl-tetris
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Dave Barker
13
+ - Luke Antins
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-21 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rsdl
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 0
31
+ - 1
32
+ - 4
33
+ version: 0.1.4
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: rubygame
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ segments:
45
+ - 2
46
+ - 6
47
+ - 4
48
+ version: 2.6.4
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ description: Simple tetris clone written using the rubygame library. Arrow keys to move, up arrow to rotate. Space drops your piece to the ground.
52
+ email:
53
+ - kzar@kzar.co.uk
54
+ executables:
55
+ - tetris
56
+ extensions: []
57
+
58
+ extra_rdoc_files: []
59
+
60
+ files:
61
+ - bin/boot.rb
62
+ - bin/boot.rb~
63
+ - bin/tetris
64
+ - bin/tetris~
65
+ - lib/tetris/core_ruby_ext.rb
66
+ - lib/tetris/game.rb
67
+ - lib/tetris/map.rb
68
+ - lib/tetris/piece.rb
69
+ - lib/tetris.rb
70
+ - test/game_test.rb
71
+ - test/test_helper.rb
72
+ - README.markdown
73
+ - Rakefile
74
+ has_rdoc: true
75
+ homepage: https://github.com/lantins/tetris
76
+ licenses: []
77
+
78
+ post_install_message:
79
+ rdoc_options: []
80
+
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ segments:
97
+ - 1
98
+ - 3
99
+ - 7
100
+ version: 1.3.7
101
+ requirements: []
102
+
103
+ rubyforge_project:
104
+ rubygems_version: 1.3.7
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Simple tetris clone written using the rubygame library
108
+ test_files: []
109
+