glimmer_snake 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d1bec8cd2eac33a2b2546c9a852007b7fb58d26556ee207a9c2ba0966775311
4
- data.tar.gz: ebe57fdb0c8c69eace44d740d3972c3793932839807a3db87269833acb9d35d8
3
+ metadata.gz: b0d5030c25633669f6aa7430e9afb02b1b9a9a7850b73b3739e3f9c3e55298e1
4
+ data.tar.gz: d3f3096c49d1f504fb0abdd203c0e192288d601a1e0aec8fb5922eb065c13a69
5
5
  SHA512:
6
- metadata.gz: 4d0e241b9fdeba7328906c739364d06dc518f45c279340775e5f85b305652b8c6da3d32f7a990f3fedf6dceeaf04dc4b4f8ea1093a0a6d043046eda4e2c0e9fe
7
- data.tar.gz: 6c7775a38e281cfc373ee5b070803d9d65d75eb03316ea97a9ea2a84b1e617dfbe729d93c361d9f375c78aa390c815e818cd8f7fe6f9aaefad4c819d1e536441
6
+ metadata.gz: f955857df6a0162a03bb433193ca1c20d2cc055e644e4b79236421c7543105769d125c742b3143fc731d54f93c168868045a7ce9f7558a477ef98e7720c5478f
7
+ data.tar.gz: e30a1e398ca0761e87d3d4c0202cc574b08f0cda51d053b324d84b6a815e8e2b97388bdec1a36c65232fa44c3bf55fb8f26d15bab6b2bcbd62cdceb201de047a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Change Log
2
2
 
3
+ ## 1.0.1
4
+
5
+ - Change snake direction on key press instead of key release to be more responsive for players who are not used to releasing pressed keys quickly
6
+ - Fix issue with detecting collision too soon if a snake fills the entire space horizontally or vertically
7
+ - Add unit tests for the Model layer
8
+ - Refactor `GlimmerSnake::Model::Snake` to be more readable like high-level game domain rules (especially `move` method)
9
+
3
10
  ## 1.0.0
4
11
 
5
12
  - Initial Glimmer Snake implementation
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # <img alt="Glimmer Tetris Icon" src="https://raw.githubusercontent.com/AndyObtiva/glimmer_snake/master/icons/linux/Glimmer%20Snake.png" height=85 /> Glimmer Snake 1.0.0
1
+ # <img alt="Glimmer Tetris Icon" src="https://raw.githubusercontent.com/AndyObtiva/glimmer_snake/master/icons/linux/Glimmer%20Snake.png" height=85 /> Glimmer Snake 1.0.1
2
2
  ## [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=40 /> Glimmer DSL for LibUI Application](https://github.com/AndyObtiva/glimmer-dsl-libui)
3
3
  [![Gem Version](https://badge.fury.io/rb/glimmer_snake.svg)](http://badge.fury.io/rb/glimmer_snake)
4
4
 
@@ -28,7 +28,7 @@ Mac | Windows | Linux
28
28
  ----|---------|------
29
29
  ![glimmer-dsl-libui-mac-snake.png](/screenshots/glimmer-dsl-libui-mac-snake.png) ![glimmer-dsl-libui-mac-snake-game-over.png](/screenshots/glimmer-dsl-libui-mac-snake-game-over.png) | ![glimmer-dsl-libui-windows-snake.png](/screenshots/glimmer-dsl-libui-windows-snake.png) ![glimmer-dsl-libui-windows-snake-game-over.png](/screenshots/glimmer-dsl-libui-windows-snake-game-over.png) | ![glimmer-dsl-libui-linux-snake.png](/screenshots/glimmer-dsl-libui-linux-snake.png) ![glimmer-dsl-libui-linux-snake-game-over.png](/screenshots/glimmer-dsl-libui-linux-snake-game-over.png)
30
30
 
31
- The goal is for the green snake to eat the red apple and to survive for as long as possible. Every time it eats an apple, it grows by 1 block (the size of the apple). If the snake hits its own body (especially after enlargement), it dies.
31
+ The goal of the game is for the green snake to eat the red apple and to survive for as long as possible. The snake always moves forward at a fixed speed. You can change the direction of the snake using arrow keys (Up is North, Right is East, Down is South, Left is West). Every time the snake eats an apple, it grows by 1 block (the size of the apple), and the apple regenerates somewhere else. If the snake hits its own body (especially after enlargement), it dies. Pressing the spacebar pauses/unpauses the game.
32
32
 
33
33
  The game remembers the highest score by storing in `~/.glimmer-snake`. You can delete that file if you want to reset the highest score.
34
34
 
data/TODO.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # TODO
2
2
 
3
- N/A
3
+ - Increase the speed of the snake slightly every time it eats an apple
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0
1
+ 1.0.1
@@ -47,10 +47,33 @@ class GlimmerSnake
47
47
  self.joins.clear
48
48
  end
49
49
 
50
+ def turn_right
51
+ head.orientation = RIGHT_TURN_MAP[head.orientation]
52
+ end
53
+
54
+ def turn_left
55
+ head.orientation = LEFT_TURN_MAP[head.orientation]
56
+ end
57
+
50
58
  def move
51
- @old_tail = tail.dup
59
+ create_new_head
60
+ remove_old_tail
61
+ if detect_collision?
62
+ collide_and_die
63
+ else
64
+ append_new_head
65
+ eat_apple if detect_apple?
66
+ end
67
+ end
68
+
69
+ def remove_old_tail
70
+ @old_tail = tail.dup # save in case of growing and keeping old tail
71
+ @vertebrae.delete(tail)
72
+ end
73
+
74
+ def create_new_head
52
75
  @new_head = head.dup
53
- case @new_head.orientation
76
+ case head.orientation
54
77
  when :east
55
78
  @new_head.column = (@new_head.column + 1) % @game.width
56
79
  when :west
@@ -60,25 +83,28 @@ class GlimmerSnake
60
83
  when :north
61
84
  @new_head.row = (@new_head.row - 1) % @game.height
62
85
  end
63
- if @vertebrae.map {|v| [v.row, v.column]}.include?([@new_head.row, @new_head.column])
64
- self.collided = true
65
- @game.over = true
66
- else
67
- @vertebrae.append(@new_head)
68
- @vertebrae.delete(tail)
69
- if head.row == @game.apple.row && head.column == @game.apple.column
70
- grow
71
- @game.apple.generate
72
- end
73
- end
74
86
  end
75
87
 
76
- def turn_right
77
- head.orientation = RIGHT_TURN_MAP[head.orientation]
88
+ def append_new_head
89
+ @vertebrae.append(@new_head)
78
90
  end
79
91
 
80
- def turn_left
81
- head.orientation = LEFT_TURN_MAP[head.orientation]
92
+ def detect_collision?
93
+ @vertebrae.map {|v| [v.row, v.column]}.include?([@new_head.row, @new_head.column])
94
+ end
95
+
96
+ def collide_and_die
97
+ self.collided = true
98
+ @game.over = true
99
+ end
100
+
101
+ def detect_apple?
102
+ head.row == @game.apple.row && head.column == @game.apple.column
103
+ end
104
+
105
+ def eat_apple
106
+ grow
107
+ @game.apple.generate
82
108
  end
83
109
 
84
110
  def grow
@@ -5,7 +5,7 @@ require_relative 'cell'
5
5
  class GlimmerSnake
6
6
  module Presenter
7
7
  class Grid
8
- include Glimmer
8
+ include Glimmer # used only for observer support (`observe` method only, not GUI)
9
9
 
10
10
  attr_reader :game, :cells
11
11
 
@@ -1,4 +1,4 @@
1
- require 'glimmer_snake/model/grid'
1
+ require 'glimmer_snake/presenter/grid'
2
2
 
3
3
  class GlimmerSnake
4
4
  module View
@@ -38,13 +38,17 @@ class GlimmerSnake
38
38
  square(0, 0, CELL_SIZE) {
39
39
  fill <= [@grid.cells[row][column], :color] # data-bind square fill to grid cell color
40
40
  }
41
-
42
- on_key_up do |area_key_event|
41
+
42
+ on_key_down do |area_key_event|
43
+ handled = true # assume we will handle the event
43
44
  if area_key_event[:key] == ' '
44
45
  @game.toggle_pause
45
- else
46
+ elsif %i[up right down left].include?(area_key_event[:ext_key])
46
47
  @keypress_queue << area_key_event[:ext_key]
48
+ else
49
+ handled = false # we won't handle the event after all
47
50
  end
51
+ handled
48
52
  end
49
53
  }
50
54
  end
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer_snake
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-22 00:00:00.000000000 Z
11
+ date: 2023-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer-dsl-libui
@@ -66,8 +66,9 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description: Glimmer Snake game desktop application built with Glimmer DSL for LibUI.
70
- Gem ships with a glimmer_snake binary script for launching the game.
69
+ description: Glimmer Snake game cross-platform desktop GUI application built with
70
+ Glimmer DSL for LibUI to run on Mac, Windows, and Linux. Gem ships with glimmer_snake
71
+ script for launching game.
71
72
  email: andy.am@gmail.com
72
73
  executables:
73
74
  - glimmer_snake
@@ -85,13 +86,12 @@ files:
85
86
  - app/glimmer_snake.rb
86
87
  - app/glimmer_snake/launch.rb
87
88
  - app/glimmer_snake/model/apple.rb
88
- - app/glimmer_snake/model/cell.rb
89
89
  - app/glimmer_snake/model/game.rb
90
- - app/glimmer_snake/model/grid.rb
91
90
  - app/glimmer_snake/model/snake.rb
92
91
  - app/glimmer_snake/model/vertebra.rb
92
+ - app/glimmer_snake/presenter/cell.rb
93
+ - app/glimmer_snake/presenter/grid.rb
93
94
  - app/glimmer_snake/view/glimmer_snake.rb
94
- - app/glimmer_snake/view/snake.rb
95
95
  - bin/glimmer_snake
96
96
  - glimmer_snake.gemspec
97
97
  - icons/linux/Glimmer Snake.png
@@ -104,7 +104,8 @@ metadata: {}
104
104
  post_install_message:
105
105
  - |2+
106
106
 
107
- Glimmer Snake 1.0.0 was installed!
107
+ Glimmer Snake 1.0.1
108
+ was installed!
108
109
  Play by running:
109
110
 
110
111
  glimmer_snake
@@ -1,91 +0,0 @@
1
- require 'glimmer-dsl-libui'
2
-
3
- require_relative 'snake/presenter/grid'
4
-
5
- class Snake
6
- include Glimmer
7
-
8
- CELL_SIZE = 15
9
- SNAKE_MOVE_DELAY = 0.1
10
-
11
- def initialize
12
- @game = Model::Game.new
13
- @grid = Presenter::Grid.new(@game)
14
- @game.start
15
- @keypress_queue = []
16
- create_gui
17
- register_observers
18
- end
19
-
20
- def launch
21
- @main_window.show
22
- end
23
-
24
- def register_observers
25
- observe(@game, :over) do |game_over|
26
- Glimmer::LibUI.queue_main do
27
- if game_over
28
- msg_box('Game Over!', "Score: #{@game.score} | High Score: #{@game.high_score}")
29
- @game.start
30
- end
31
- end
32
- end
33
-
34
- Glimmer::LibUI.timer(SNAKE_MOVE_DELAY) do
35
- unless @game.paused? || @game.over?
36
- process_queued_keypress
37
- @game.snake.move
38
- end
39
- end
40
- end
41
-
42
- def process_queued_keypress
43
- # key press queue ensures one turn per snake move to avoid a double-turn resulting in instant death (due to snake illogically going back against itself)
44
- key = @keypress_queue.shift
45
- case [@game.snake.head.orientation, key]
46
- in [:north, :right] | [:east, :down] | [:south, :left] | [:west, :up]
47
- @game.snake.turn_right
48
- in [:north, :left] | [:west, :down] | [:south, :right] | [:east, :up]
49
- @game.snake.turn_left
50
- else
51
- # No Op
52
- end
53
- end
54
-
55
- def create_gui
56
- @main_window = window {
57
- # data-bind window title to game score, converting it to a title string on read from the model
58
- title <= [@game, :score, on_read: -> (score) {"Snake (Score: #{@game.score})"}]
59
- content_size @game.width * CELL_SIZE, @game.height * CELL_SIZE
60
- resizable false
61
-
62
- vertical_box {
63
- padded false
64
-
65
- @game.height.times do |row|
66
- horizontal_box {
67
- padded false
68
-
69
- @game.width.times do |column|
70
- area {
71
- square(0, 0, CELL_SIZE) {
72
- fill <= [@grid.cells[row][column], :color] # data-bind square fill to grid cell color
73
- }
74
-
75
- on_key_up do |area_key_event|
76
- if area_key_event[:key] == ' '
77
- @game.toggle_pause
78
- else
79
- @keypress_queue << area_key_event[:ext_key]
80
- end
81
- end
82
- }
83
- end
84
- }
85
- end
86
- }
87
- }
88
- end
89
- end
90
-
91
- Snake.new.launch
File without changes