conjuration 0.1.2 → 0.2.0

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: 1a2cd4153fd1fe67cf858245a3337a12f28e3bf0383a14c4ca5a98021eb446e6
4
- data.tar.gz: 0b1975cf3fb9baf67802f204faaef6a91e71a2d080064eb922d22cee2ffc78ec
3
+ metadata.gz: 9730a469c206b387fd96012ddb7a885a4a3d19e991aeb3c5cc2cf0afca81560a
4
+ data.tar.gz: 356d4cb07b20f5378d4c161c9212a20dc5eaf42e84b22e49f79cebf2d1a7520b
5
5
  SHA512:
6
- metadata.gz: f655cf37edfa05b1ab4b6256a19486b31c3a406ae68c8447f02683b1b946fc13a34266c88017f6c5c332b4603187b2346e58e5988ffde8f41f8009aef4064446
7
- data.tar.gz: cecba3e7696c57a11662dce317652bae03b6be7c0addd4d71ac0a2c11a1875de083709305eba38df6a22e3343f4a09fa4a44fa40841e3c0679e4668a2e823364
6
+ metadata.gz: 9f2ec5ffb69518a3b2461cbdb4a7c5158f058daa292c5416ebf1857482aad1ccdd65f196177fa3c0694974ccd2f4a0beef8a8d5f495ec330787eb5d74983c619
7
+ data.tar.gz: a0f10f06c9f2c1a8812efad61a6c214e48866554ad6255d6a38af4ff7d87324f6d9f134c600a4bac3903c6bae3917931c05dd88288dd804b4ba72245507047ed
data/README.md CHANGED
@@ -73,6 +73,10 @@ You should setup your project with the following file structure:
73
73
 
74
74
  This is where you store your game assets. This can include images, sounds, and other resources.
75
75
 
76
+ ## Examples
77
+
78
+ - [Tic Tac Toe](/examples/tic_tac_toe)
79
+
76
80
  ## Contributing
77
81
 
78
82
  Bug reports and pull requests are welcome on GitHub at https://github.com/Nitemaeric/conjuration.
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "conjuration", path: "../.."
@@ -0,0 +1,22 @@
1
+ PATH
2
+ remote: ../..
3
+ specs:
4
+ conjuration (0.1.3)
5
+ gosu (~> 1.4.6)
6
+ zeitwerk (~> 2.6.14)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ gosu (1.4.6)
12
+ zeitwerk (2.6.14)
13
+
14
+ PLATFORMS
15
+ arm64-darwin-23
16
+ ruby
17
+
18
+ DEPENDENCIES
19
+ conjuration!
20
+
21
+ BUNDLED WITH
22
+ 2.5.10
@@ -0,0 +1,3 @@
1
+ # Tic Tac Toe - Conjuration Example
2
+
3
+ This is a simple example of a Tic Tac Toe game built with Conjuration.
@@ -0,0 +1,5 @@
1
+ require "conjuration"
2
+
3
+ require "./src/game"
4
+
5
+ Game.new.show
@@ -0,0 +1,10 @@
1
+ require_relative "./scenes/main_scene"
2
+
3
+ class Game < Conjuration::Game
4
+ def initialize
5
+ super(title: "Tic Tac Toe")
6
+
7
+ scene_manager.add_scene(:main, MainScene)
8
+ scene_manager.set_scene(:main)
9
+ end
10
+ end
@@ -0,0 +1,43 @@
1
+ class Slot < Conjuration::GameObject
2
+ attribute :mark
3
+
4
+ PLAYER_X_COLOR = Gosu::Color::RED
5
+ PLAYER_O_COLOR = Gosu::Color::GREEN
6
+
7
+ def initialize(x:, y:)
8
+ super(x:, y:, width: 200, height: 200)
9
+ end
10
+
11
+ def draw(window, scene)
12
+ window.draw_rect(x, y, width, height, Gosu::Color::BLACK)
13
+ window.draw_rect(x+2, y+2, width-4, height-4, Gosu::Color::WHITE)
14
+
15
+ if mark == "X"
16
+ window.rotate(45, x+width/2, y+height/2) do
17
+ window.draw_rect(x, y + height / 2 - 5, width, 10, PLAYER_X_COLOR)
18
+ window.draw_rect(x + width / 2 - 5, y, 10, height, PLAYER_X_COLOR)
19
+ end
20
+ elsif mark == "O"
21
+ window.draw_circle(x+width/2, y+height/2, width/2 - 30, PLAYER_O_COLOR, 0, 10)
22
+ else
23
+ if hovering?
24
+ if scene.current_player == "X"
25
+ window.rotate(45, x+width/2, y+height/2) do
26
+ window.draw_rect(x, y + height / 2 - 5, width, 10, PLAYER_X_COLOR)
27
+ window.draw_rect(x + width / 2 - 5, y, 10, height, PLAYER_X_COLOR)
28
+ end
29
+ elsif scene.current_player == "O"
30
+ window.draw_circle(x+width/2, y+height/2, width/2 - 30, PLAYER_O_COLOR, 0, 10)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ def on_click(scene, key)
37
+ return if mark
38
+
39
+ self.mark = scene.current_player
40
+
41
+ scene.change_player
42
+ end
43
+ end
@@ -0,0 +1,52 @@
1
+ require_relative "../game_objects/slot"
2
+ require_relative "./winner_scene"
3
+
4
+ class MainScene < Conjuration::Scene
5
+ attribute :current_player, default: "X"
6
+
7
+ def initialize(window, options = {})
8
+ super(window, options)
9
+
10
+ starting_x = 600
11
+ starting_y = 400
12
+
13
+ @slots = []
14
+
15
+ (0..2).each do |grid_y|
16
+ @slots << []
17
+
18
+ (0..2).each do |grid_x|
19
+ @slots[grid_y] << Slot.create(x: starting_x + grid_x * 200, y: starting_y + grid_y * 200, scene: self)
20
+ end
21
+ end
22
+ end
23
+
24
+ def change_player
25
+ self.current_player = current_player == "X" ? "O" : "X"
26
+ end
27
+
28
+ def check_winner
29
+ # Check horizontal wins
30
+ return @slots[0][0].mark if @slots[0][0].mark == @slots[0][1].mark && @slots[0][1].mark == @slots[0][2].mark
31
+ return @slots[1][0].mark if @slots[1][0].mark == @slots[1][1].mark && @slots[1][1].mark == @slots[1][2].mark
32
+ return @slots[2][0].mark if @slots[2][0].mark == @slots[2][1].mark && @slots[2][1].mark == @slots[2][2].mark
33
+
34
+ # Check vertical wins
35
+ return @slots[0][0].mark if @slots[0][0].mark == @slots[1][0].mark && @slots[1][0].mark == @slots[2][0].mark
36
+ return @slots[0][1].mark if @slots[0][1].mark == @slots[1][1].mark && @slots[1][1].mark == @slots[2][1].mark
37
+ return @slots[0][2].mark if @slots[0][2].mark == @slots[1][2].mark && @slots[1][2].mark == @slots[2][2].mark
38
+
39
+ # Check diagonal wins
40
+ return @slots[0][0].mark if @slots[0][0].mark == @slots[1][1].mark && @slots[1][1].mark == @slots[2][2].mark
41
+ return @slots[0][2].mark if @slots[0][2].mark == @slots[1][1].mark && @slots[1][1].mark == @slots[2][0].mark
42
+ end
43
+
44
+ def button_up(window, id)
45
+ super
46
+
47
+ if @winner = check_winner
48
+ window.scene_manager.add_scene(:winner, WinnerScene)
49
+ window.scene_manager.set_scene(:winner, winner: @winner)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,11 @@
1
+ class WinnerScene < Conjuration::Scene
2
+ def initialize(window, winner:)
3
+ super
4
+
5
+ Conjuration::Text.create(x: 600, y: 400, text: "#{winner} wins!", color: Gosu::Color::WHITE, scene: self)
6
+
7
+ Conjuration::Button.create(x: 600, y: 600, text: "Close", scene: self) do |scene|
8
+ scene.window.close
9
+ end
10
+ end
11
+ end
@@ -22,37 +22,39 @@
22
22
  # person.age = 30
23
23
  # person.inspect # => "<Person name: \"Alice\", age: 30>"
24
24
  #
25
- module Attributes
26
- def self.included(base)
27
- base.extend(ClassMethods)
28
- end
25
+ module Conjuration
26
+ module Attributes
27
+ def self.included(base)
28
+ base.extend(ClassMethods)
29
+ end
29
30
 
30
- def initialize(...)
31
- super()
31
+ def initialize(...)
32
+ super()
32
33
 
33
- @attributes = {}
34
- end
34
+ @attributes = {}
35
+ end
35
36
 
36
- def inspect
37
- "<#{self.class} #{@attributes.map { |attribute_name, value| "#{attribute_name}: #{value.inspect}" }.join(", ")}>"
38
- end
37
+ def inspect
38
+ "<#{self.class} #{@attributes.map { |attribute_name, value| "#{attribute_name}: #{value.inspect}" }.join(", ")}>"
39
+ end
39
40
 
40
- module ClassMethods
41
- def attribute(attribute_name)
42
- define_method(attribute_name) do
43
- @attributes[attribute_name]
44
- end
41
+ module ClassMethods
42
+ def attribute(attribute_name, default: nil)
43
+ define_method(attribute_name) do
44
+ @attributes[attribute_name] ||= default
45
+ end
45
46
 
46
- define_method("#{attribute_name}=") do |value|
47
- @attributes[attribute_name] = value
47
+ define_method("#{attribute_name}=") do |value|
48
+ @attributes[attribute_name] = value
49
+ end
48
50
  end
49
- end
50
51
 
51
- def boolean_attribute(attribute_name)
52
- attribute(attribute_name)
52
+ def boolean_attribute(attribute_name)
53
+ attribute(attribute_name)
53
54
 
54
- define_method("#{attribute_name}?") do
55
- !!@attributes[attribute_name]
55
+ define_method("#{attribute_name}?") do
56
+ !!@attributes[attribute_name]
57
+ end
56
58
  end
57
59
  end
58
60
  end
@@ -33,5 +33,34 @@ module Conjuration
33
33
  def button_up(id)
34
34
  @scene_manager.button_up(self, @input_manager.map_button(id))
35
35
  end
36
+
37
+ def draw_circle(x, y, r, c, z = 0, thickness = 1, sides = nil, mode = :default)
38
+ # Unless specified, calculate a nice-looking "minimum" number of sides
39
+ # sides = (r + Math::sqrt(r * 0.1) * 4).floor if sides.nil?
40
+ sides = (2.0 * r * Math::PI).floor if sides.nil?
41
+
42
+ # Calculate the inner and outer offsets from the "true" circle
43
+ offs = thickness * 0.5
44
+ r_in = r - offs
45
+ r_out = r + offs
46
+
47
+ # Calculate the angular increment
48
+ ai = 360.0 / sides.to_f
49
+
50
+ translate(x, y) {
51
+ ang = 0
52
+ while ang <= 359.9 do
53
+ draw_quad(
54
+ Gosu.offset_x(ang, r_in), Gosu.offset_y(ang, r_in), c,
55
+ Gosu.offset_x(ang, r_out), Gosu.offset_y(ang, r_out), c,
56
+ Gosu.offset_x(ang + ai, r_in), Gosu.offset_y(ang + ai, r_in), c,
57
+ Gosu.offset_x(ang + ai, r_out), Gosu.offset_y(ang + ai, r_out), c,
58
+ z, mode
59
+ )
60
+ ang += ai
61
+ end
62
+ }
63
+
64
+ end
36
65
  end
37
66
  end
@@ -77,18 +77,18 @@ module Conjuration
77
77
  # Clicking
78
78
  # ==========
79
79
 
80
- def mouse_down(context, key)
81
- on_mouse_down(context, key)
80
+ def mouse_down(scene, key)
81
+ on_mouse_down(scene, key)
82
82
 
83
- return unless !clicking[key] && context.input_manager.button_down?(key) && in_bounds?(context)
83
+ return unless !clicking[key] && scene.window.input_manager.button_down?(key) && in_bounds?(scene.window)
84
84
 
85
85
  clicking[key] = true
86
86
  end
87
87
 
88
- def mouse_up(context, key)
89
- on_mouse_up(context, key)
88
+ def mouse_up(scene, key)
89
+ on_mouse_up(scene, key)
90
90
 
91
- on_click(context, key) if clicking[key] && !context.input_manager.button_down?(key) && in_bounds?(context)
91
+ on_click(scene, key) if clicking[key] && !scene.window.input_manager.button_down?(key) && in_bounds?(scene.window)
92
92
 
93
93
  clicking[key] = false
94
94
  end
@@ -15,7 +15,7 @@ module Conjuration
15
15
  end
16
16
 
17
17
  def button_down?(action)
18
- action_map[action].any? { |key_id| Gosu.button_down?(key_id) }
18
+ action_map[action]&.any? { |key_id| Gosu.button_down?(key_id) } || false
19
19
  end
20
20
 
21
21
  # Returns a hash of actions mapped to key bindings.
@@ -11,8 +11,8 @@ module Conjuration
11
11
  @scenes[key] = scene_class
12
12
  end
13
13
 
14
- def set_scene(_scene_class, options = {})
15
- @current_scene = @scenes[key].new(@window, options)
14
+ def set_scene(key, **options)
15
+ @current_scene = @scenes[key].new(@window, **options)
16
16
  end
17
17
 
18
18
  attr_reader :current_scene
@@ -34,15 +34,15 @@ module Conjuration
34
34
  def draw(context)
35
35
  @background_image&.draw(0, 0, 0, context.width.to_f / @background_image.width,
36
36
  context.height.to_f / @background_image.height)
37
- @game_objects.each { |game_object| game_object.draw(context) }
37
+ @game_objects.each { |game_object| game_object.draw(context, self) }
38
38
  end
39
39
 
40
40
  def button_down(context, key)
41
- @game_objects.each { |game_object| game_object.mouse_down(context, key) }
41
+ @game_objects.each { |game_object| game_object.mouse_down(self, key) }
42
42
  end
43
43
 
44
44
  def button_up(context, key)
45
- @game_objects.each { |game_object| game_object.mouse_up(context, key) }
45
+ @game_objects.each { |game_object| game_object.mouse_up(self, key) }
46
46
  end
47
47
  end
48
48
  end
@@ -0,0 +1,38 @@
1
+ module Conjuration
2
+ class Button < Conjuration::GameObject
3
+ def initialize(
4
+ x:,
5
+ y:,
6
+ width: 200,
7
+ height: 40,
8
+ text:,
9
+ font_size: 20,
10
+ color: Gosu::Color::BLACK,
11
+ background_color: Gosu::Color::WHITE,
12
+ hover: {
13
+ color: Gosu::Color::BLACK,
14
+ background_color: Gosu::Color::GRAY,
15
+ },
16
+ &action
17
+ )
18
+ super(x:, y:, width:, height:)
19
+
20
+ @text = text
21
+ @font = Gosu::Font.new(font_size)
22
+ @color = color
23
+ @background_color = background_color
24
+ @hover = hover
25
+ @action = action
26
+ end
27
+
28
+ def draw(window, scene)
29
+ window.draw_rect(x, y, width, height, hovering? ? @hover[:background_color] : @background_color)
30
+
31
+ @font.draw_text(@text, x + width/2 - @font.text_width(@text)/2, y + height/2 - @font.height/2, 1, 1, 1, hovering? ? @hover[:color] : @color)
32
+ end
33
+
34
+ def on_click(scene, key)
35
+ @action.call(scene) if key == InputManager::LEFT_CLICK
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ module Conjuration
2
+ class Text < Conjuration::GameObject
3
+ def initialize(x:, y:, text:, font_size: 20, color: Gosu::Color::BLACK)
4
+ @font = Gosu::Font.new(font_size)
5
+
6
+ super(x:, y:, width: @font.text_width(text), height: @font.height)
7
+
8
+ @text = text
9
+ @color = color
10
+ end
11
+
12
+ def draw(window, scene)
13
+ @font.draw_text(@text, x, y, 1, 1, 1, @color)
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Conjuration
4
- VERSION = "0.1.2"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/conjuration.rb CHANGED
@@ -4,6 +4,9 @@ require "gosu"
4
4
  require "zeitwerk"
5
5
 
6
6
  loader = Zeitwerk::Loader.for_gem
7
+ loader.collapse("#{__dir__}/conjuration/concerns")
8
+ loader.collapse("#{__dir__}/conjuration/managers")
9
+ loader.collapse("#{__dir__}/conjuration/ui")
7
10
  loader.setup
8
11
 
9
12
  module Conjuration
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conjuration
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Dye
@@ -52,6 +52,14 @@ files:
52
52
  - LICENSE.txt
53
53
  - README.md
54
54
  - Rakefile
55
+ - examples/tictactoe/Gemfile
56
+ - examples/tictactoe/Gemfile.lock
57
+ - examples/tictactoe/README.md
58
+ - examples/tictactoe/main.rb
59
+ - examples/tictactoe/src/game.rb
60
+ - examples/tictactoe/src/game_objects/slot.rb
61
+ - examples/tictactoe/src/scenes/main_scene.rb
62
+ - examples/tictactoe/src/scenes/winner_scene.rb
55
63
  - lib/conjuration.rb
56
64
  - lib/conjuration/concerns/attributes.rb
57
65
  - lib/conjuration/game.rb
@@ -61,6 +69,8 @@ files:
61
69
  - lib/conjuration/managers/input_manager.rb
62
70
  - lib/conjuration/managers/scene_manager.rb
63
71
  - lib/conjuration/scene.rb
72
+ - lib/conjuration/ui/button.rb
73
+ - lib/conjuration/ui/text.rb
64
74
  - lib/conjuration/version.rb
65
75
  homepage: https://github.com/nitemaeric/conjuration
66
76
  licenses: