ruby_snake 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ruby_snake.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 zhouguangming
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # Ruby Snake
2
+
3
+ Ruby Snake is a simple greedy-snake like game, it is plable at command-line, sopported ruby 1.8+ .
4
+ The rules are the same of any snake game:
5
+
6
+ > You control a stupid snake and the objective is to eat as many money you can. Each money eaten increases it's size by one unit and movement speed will be more and more fast.
7
+
8
+ > The game ends when the snake collides with the walls or itself.
9
+
10
+ > To each money is given a bonus value, so the challenge is to earn the biggest score possible by eating as much money as you can.
11
+
12
+ Good Luck!
13
+
14
+ ![image](http://zgm.dn.qbox.me/ruby_snake.png)
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ gem 'ruby_snake'
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install ruby_snake
29
+
30
+ ## Usage
31
+
32
+ ```
33
+ ruby_snake
34
+ ```
35
+
36
+ ## Keyboard Mapping
37
+
38
+ Easy to play, very friendly operation of vim user.
39
+
40
+ > `k` -> up
41
+
42
+ > `j` -> down
43
+
44
+ > `l` -> right
45
+
46
+ > `h` -> left
47
+
48
+ > `space` -> pause && continue
49
+
50
+ > `q` -> quit
51
+
52
+
53
+ ## Contributing
54
+
55
+ 1. Fork it
56
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
57
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
58
+ 4. Push to the branch (`git push origin my-new-feature`)
59
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/bin/ruby_snake ADDED
@@ -0,0 +1,10 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path('../../lib/', __FILE__)
4
+
5
+ require 'ruby_snake'
6
+
7
+ RubySnake.play
8
+
9
+
10
+
@@ -0,0 +1,25 @@
1
+ module RubySnake
2
+ module Config
3
+ UP = 107 # k
4
+ DOWN = 106 # j
5
+ LEFT = 104 # h
6
+ RIGHT = 108 # l
7
+ PAUSE = 32 # space
8
+ QUIT = 113 # q
9
+ YES = 121 # y
10
+ NO = 110 # n
11
+
12
+ KEYBOARD_MAPPING = {
13
+ UP => 'up',
14
+ DOWN => 'down',
15
+ LEFT => 'left',
16
+ RIGHT => 'right',
17
+ PAUSE => 'pause',
18
+ QUIT => 'exit',
19
+ YES => 'yes',
20
+ NO => 'no'
21
+ }
22
+
23
+ OPERATIONS = [UP, DOWN, LEFT, RIGHT, PAUSE, QUIT, YES, NO]
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ module RubySnake
2
+ class Game
3
+ class << self
4
+ def start
5
+ UI.draw
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,94 @@
1
+ module RubySnake
2
+ class Snake
3
+ attr_accessor :direction, :head, :tail, :food, :width, :height
4
+
5
+ def initialize(width, height)
6
+ @width, @height = width - 3, height - 3
7
+ end
8
+
9
+ def body
10
+ @body ||= Proc.new do
11
+ body = []
12
+ body << [1, 0] << [0, 0]
13
+ end.call
14
+ end
15
+
16
+ def odd_columns
17
+ @odd_columns ||= (0..width).select { |c| c % 2 != 0 }
18
+ end
19
+
20
+ def food
21
+ @food ||= rand_food
22
+ end
23
+
24
+ def rand_food
25
+ while true
26
+ food_coordinate = [odd_columns.sample, rand(height)]
27
+ break unless body.include? food_coordinate
28
+ end
29
+ food_coordinate
30
+ end
31
+
32
+ def eat_food
33
+ self.food = nil
34
+ end
35
+
36
+ def can_eat_food?
37
+ self.head == food
38
+ end
39
+
40
+ def direction
41
+ @direction ||= 'right'
42
+ end
43
+
44
+ def head
45
+ body.first
46
+ end
47
+
48
+ def near_border?
49
+ return true if head.first == 1 or head.last == 0
50
+ return true if head.first == @width or head.first == @width - 1
51
+ return true if head.last == @height
52
+ end
53
+
54
+ def tail
55
+ body.last
56
+ end
57
+
58
+ def move_head(direction)
59
+ x = head.first
60
+ y = head.last
61
+ case direction
62
+ when 'down'
63
+ return false if y + 1 > @height
64
+ body.unshift [x, y + 1]
65
+ when 'up'
66
+ return false if y - 1 < 0
67
+ body.unshift [x, y - 1]
68
+ when 'left'
69
+ return false if x - 2 < 0
70
+ body.unshift [x - 2, y]
71
+ when 'right'
72
+ return false if x + 2 > @width
73
+ body.unshift [x + 2, y]
74
+ end
75
+ body.uniq == body
76
+ end
77
+
78
+ def move_tail
79
+ body.pop
80
+ end
81
+
82
+ def move(o=nil)
83
+ self.direction = o unless o.nil?
84
+ return false unless move_head(direction)
85
+ if can_eat_food?
86
+ eat_food
87
+ else
88
+ move_tail
89
+ end
90
+ true
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,222 @@
1
+ #encoding: utf-8
2
+ require 'ncurses'
3
+
4
+ module RubySnake
5
+ class UI
6
+ class << self
7
+ include Config
8
+ def init
9
+ Ncurses.initscr
10
+ Ncurses.cbreak
11
+ Ncurses.noecho
12
+ Ncurses.nonl
13
+ Ncurses.stdscr.intrflush(false)
14
+ Ncurses.stdscr.keypad(true)
15
+ Ncurses.curs_set 0
16
+
17
+ Ncurses.start_color
18
+ Ncurses.init_pair(1, Ncurses::COLOR_RED, Ncurses::COLOR_BLACK);
19
+ Ncurses.init_pair(2, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK);
20
+ Ncurses.init_pair(3, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK);
21
+ Ncurses.init_pair(4, Ncurses::COLOR_GREEN, Ncurses::COLOR_BLACK);
22
+
23
+ @window = Ncurses::WINDOW.new(30, 101, (Ncurses.stdscr.getmaxy - 30) / 2, (Ncurses.stdscr.getmaxx - 101) / 2)
24
+ unless @window
25
+ @window = Ncurses.stdscr
26
+ end
27
+ Ncurses.nodelay @window, true
28
+ @window.clear
29
+ @operation = KEYBOARD_MAPPING[RIGHT]
30
+ @snake = Snake.new(@window.getmaxx, @window.getmaxy)
31
+ @time_flag = Time.now.to_f
32
+ end
33
+
34
+ def direction_opposite?(o)
35
+ return true if @operation == 'up' && o == DOWN
36
+ return true if @operation == 'down' && o == UP
37
+ return true if @operation == 'left' && o == RIGHT
38
+ return true if @operation == 'right' && o == LEFT
39
+ end
40
+
41
+ def display stuff, symbol
42
+ x = stuff.last + 1
43
+ y = stuff.first + 1
44
+ @window.mvprintw(x, y, symbol)
45
+ end
46
+
47
+ def score
48
+ @snake.body.length - 2
49
+ end
50
+
51
+ def level
52
+ score/10 + 1
53
+ end
54
+
55
+ def speed
56
+ return 1 if @pause_flag
57
+
58
+ if score < 10
59
+ 0.2
60
+ elsif score >= 10 && score < 20
61
+ 0.1
62
+ elsif score >= 20 && score < 30
63
+ 0.05
64
+ elsif score >= 30
65
+ 0.03
66
+ end
67
+ end
68
+
69
+ def time
70
+ if @pause_flag
71
+ @used_time
72
+ else
73
+ ((Time.now.to_f - @time_flag + @used_time.to_f) * 10).round / 10.0
74
+ end
75
+ end
76
+
77
+ def pause
78
+ @used_time = time
79
+ @pause_flag ||= true
80
+ end
81
+
82
+ def continue
83
+ @time_flag = Time.now.to_f
84
+ @pause_flag = false
85
+ end
86
+
87
+ def clear
88
+ display @snake.tail, ' '
89
+ end
90
+
91
+ def draw_food
92
+ @window.color_set(1, nil)
93
+ display @snake.food, '$'
94
+ @window.refresh
95
+ end
96
+
97
+ def draw_snake
98
+ @window.color_set(2, nil)
99
+ @snake.body.each do |body|
100
+ if body == @snake.head
101
+ display body, '@'
102
+ else
103
+ display body, 'o'
104
+ end
105
+ end
106
+ end
107
+
108
+ def pause_or_continue
109
+ if @pause_flag
110
+ continue
111
+ else
112
+ pause
113
+ end
114
+ end
115
+
116
+ def draw_title
117
+ @window.color_set(4, nil)
118
+ y = @snake.width / 2 - 15
119
+ @window.mvprintw(0, y, "Score: #{score} Level: #{level} Time: #{time}s")
120
+ end
121
+
122
+ def draw_boder
123
+ if @snake.near_border?
124
+ @window.color_set(1, nil)
125
+ else
126
+ @window.color_set(4, nil)
127
+ end
128
+ @window.border(*([0] * 8))
129
+ end
130
+
131
+ def listen_operation
132
+ operation = @window.getch
133
+ if OPERATIONS.include?(operation) && !direction_opposite?(operation)
134
+ case operation
135
+ when PAUSE
136
+ pause_or_continue
137
+ when QUIT
138
+ Thread.current.kill
139
+ else
140
+ @operation = operation
141
+ @operation = KEYBOARD_MAPPING[@operation]
142
+ end
143
+ end
144
+ end
145
+
146
+ def game_over
147
+ x = @window.getmaxx / 2
148
+ y = @window.getmaxy / 2 - 10
149
+ Ncurses.nodelay @window, false
150
+ @window.clear
151
+
152
+ text = '
153
+
154
+ _________________________________
155
+ < Opps, I am died, restart? (y/n) >
156
+ ---------------------------------
157
+ .-.
158
+ / aa
159
+ \ -,_)
160
+ _..._| \ `-<
161
+ {} ." .__.\' |
162
+ {} ( /`\
163
+ {}(`\'------\' /
164
+ |\/;._______.\'\
165
+ ; \ /
166
+ \'-\'-.......-\'
167
+
168
+
169
+ '
170
+
171
+ @window.mvaddstr(y, x, text)
172
+ @window.refresh
173
+ while true
174
+ case @window.getch
175
+ when YES
176
+ return false
177
+ when NO
178
+ return true
179
+ end
180
+ end
181
+ end
182
+
183
+ def draw_map
184
+ draw_boder
185
+ draw_title
186
+ draw_snake
187
+ draw_food
188
+ clear
189
+ sleep speed
190
+ @window.refresh
191
+ end
192
+
193
+ def restart
194
+ @window.clear
195
+ @operation = nil
196
+ Ncurses.nodelay @window, true
197
+ @snake = Snake.new(@window.getmaxx, @window.getmaxy)
198
+ end
199
+
200
+ def draw
201
+ begin
202
+ init
203
+ while true
204
+ listen_operation
205
+ draw_map
206
+ if !@pause_flag && !@snake.move(@operation)
207
+ sleep 1
208
+ if game_over
209
+ break
210
+ else
211
+ restart
212
+ end
213
+ end
214
+ end
215
+ ensure
216
+ Ncurses.endwin()
217
+ end
218
+ end
219
+ end
220
+
221
+ end
222
+ end
@@ -0,0 +1,3 @@
1
+ module RubySnake
2
+ VERSION = "0.0.1"
3
+ end
data/lib/ruby_snake.rb ADDED
@@ -0,0 +1,14 @@
1
+ $:.unshift File.expand_path('../', __FILE__)
2
+
3
+ require "ruby_snake/version"
4
+
5
+ module RubySnake
6
+ autoload :UI, 'ruby_snake/ui'
7
+ autoload :Game, 'ruby_snake/game'
8
+ autoload :Snake, 'ruby_snake/snake'
9
+ autoload :Config, 'ruby_snake/config'
10
+
11
+ def self.play
12
+ Game.start
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/ruby_snake/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["zhouguangming"]
6
+ gem.email = ["zhouguangming1989@gmail.com"]
7
+ gem.description = %q{A simple greedy-snake like game}
8
+ gem.summary = %q{A simple greedy-snake like game}
9
+ gem.homepage = "https://github.com/zhouguangming/ruby_snake"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "ruby_snake"
15
+ gem.require_paths = ["lib"]
16
+ gem.add_dependency "ncurses-ruby"
17
+ gem.version = RubySnake::VERSION
18
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_snake
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - zhouguangming
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: ncurses-ruby
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: A simple greedy-snake like game
31
+ email:
32
+ - zhouguangming1989@gmail.com
33
+ executables:
34
+ - ruby_snake
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - .gitignore
39
+ - Gemfile
40
+ - LICENSE
41
+ - README.md
42
+ - Rakefile
43
+ - bin/ruby_snake
44
+ - lib/ruby_snake.rb
45
+ - lib/ruby_snake/config.rb
46
+ - lib/ruby_snake/game.rb
47
+ - lib/ruby_snake/snake.rb
48
+ - lib/ruby_snake/ui.rb
49
+ - lib/ruby_snake/version.rb
50
+ - ruby_snake.gemspec
51
+ homepage: https://github.com/zhouguangming/ruby_snake
52
+ licenses: []
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 1.8.24
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: A simple greedy-snake like game
75
+ test_files: []
76
+ has_rdoc: