dl-tetris 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+