slickr 0.0.1 → 0.0.2

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.
Files changed (57) hide show
  1. checksums.yaml +6 -14
  2. data/.rspec +0 -1
  3. data/.travis.yml +4 -0
  4. data/Gemfile +0 -2
  5. data/README.md +58 -52
  6. data/Rakefile +4 -0
  7. data/lib/slickr.rb +18 -1
  8. data/lib/slickr/actions/generate.rb +51 -0
  9. data/lib/slickr/behavior.rb +68 -0
  10. data/lib/slickr/cli.rb +12 -3
  11. data/lib/slickr/entity.rb +64 -0
  12. data/lib/slickr/entity_manager.rb +105 -0
  13. data/lib/slickr/generators/base.rb +95 -0
  14. data/lib/slickr/generators/behavior.rb +9 -0
  15. data/lib/slickr/generators/entity.rb +10 -0
  16. data/{files → lib/slickr/generators/files}/Rakefile +0 -0
  17. data/{files → lib/slickr/generators/files}/jinput.jar +0 -0
  18. data/{files → lib/slickr/generators/files}/libjinput-osx.jnilib +0 -0
  19. data/{files → lib/slickr/generators/files}/liblwjgl.jnilib +0 -0
  20. data/{files → lib/slickr/generators/files}/lwjgl.jar +0 -0
  21. data/{files → lib/slickr/generators/files}/openal.dylib +0 -0
  22. data/{files → lib/slickr/generators/files}/slick.jar +0 -0
  23. data/lib/slickr/generators/project.rb +36 -0
  24. data/lib/slickr/generators/reactor.rb +9 -0
  25. data/lib/slickr/generators/renderer.rb +9 -0
  26. data/lib/slickr/generators/templates/behavior.erb +3 -0
  27. data/lib/slickr/generators/templates/behaviors.erb +1 -0
  28. data/{templates → lib/slickr/generators/templates}/engine.erb +13 -9
  29. data/lib/slickr/generators/templates/entities.erb +1 -0
  30. data/lib/slickr/generators/templates/entity.erb +2 -0
  31. data/lib/slickr/generators/templates/reactor.erb +4 -0
  32. data/lib/slickr/generators/templates/reactors.erb +1 -0
  33. data/lib/slickr/generators/templates/renderer.erb +4 -0
  34. data/lib/slickr/generators/templates/renderers.erb +1 -0
  35. data/lib/slickr/reactor.rb +86 -0
  36. data/lib/slickr/renderer.rb +37 -0
  37. data/lib/slickr/tasks.rb +1 -3
  38. data/lib/slickr/version.rb +1 -1
  39. data/slickr.gemspec +0 -2
  40. data/spec/build/.gitkeep +0 -0
  41. data/spec/slickr/actions/generate_spec.rb +38 -0
  42. data/spec/slickr/entity_manager_spec.rb +31 -0
  43. data/spec/slickr/entity_spec.rb +21 -0
  44. data/spec/slickr/generators/behavior_spec.rb +17 -0
  45. data/spec/slickr/generators/entity_spec.rb +21 -0
  46. data/spec/slickr/generators/project_spec.rb +120 -0
  47. data/spec/slickr/generators/reactor_spec.rb +17 -0
  48. data/spec/slickr/generators/renderer_spec.rb +17 -0
  49. data/spec/slickr/reactor_spec.rb +25 -0
  50. data/spec/spec_helper.rb +17 -4
  51. metadata +64 -57
  52. data/lib/slickr/actions/create.rb +0 -79
  53. data/spec/slickj/actions/create_spec.rb +0 -174
  54. data/templates/components.erb +0 -5
  55. data/templates/entities.erb +0 -5
  56. data/templates/renderers.erb +0 -5
  57. data/templates/systems.erb +0 -5
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ODRmY2E3NWEwZjg0YTc1Y2QwZDlkYTExZGNmMWZlMmQxMDEyMjJkNg==
5
- data.tar.gz: !binary |-
6
- ZjVmZWI5MTU5ZWNhOGRmZTNmM2NlYjNlNWE4MjViNjkyMDNiZTZhYQ==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- ZGRkMzg4NGE3MTE1OTkyNzk1MDkxMDk5MjViNTdiYzU5ODliMDUyYTZhMDk4
10
- YTVmMWNkNTgxZjlhOWQ3NDAyYzIwYWJkMjJmYWI0ODlmMzM2ZmU4NmJiYTI5
11
- YjZjYjQ5NWNjM2RmZWM4ZTZiMjY0ZjY1MTllNGFiZTI1MjRlNTI=
12
- data.tar.gz: !binary |-
13
- YzQ4MWI3YTE3YzZkZmJjMzMwOTY4NzFkMzUyMzk5Zjg4NmVkNDQ1MDRlNzg2
14
- OTc2OWE4NWVjODg1MWZkOTJmMmE2MDg0NmFhMzRhMWYwZTkzZDdkNzM2MWNk
15
- NWFmMGY0YzFiYmY5Y2ZhYjU4M2UxZmViY2YzMDY4OTIzZTUyODM=
2
+ SHA1:
3
+ metadata.gz: 7593e388d74d18775d44ce56aac159b23a9e93ad
4
+ data.tar.gz: 05a5b28e4c555ec670421a490e6dda4c54413eb5
5
+ SHA512:
6
+ metadata.gz: 870175e5c09cea5de268086d2cc3e643f64193b947c26dd2d5c378e7660ecd20ffc42dc4fb0ea7493ca60c4a211ad88a4cf3b81cce853288502ce903e342ff1a
7
+ data.tar.gz: e0e2781159242322ad0be3ce13a439f8e32df97a6739a5aa7ee7d4f5a655a92386603013a5b933cf4e16782b261365a024a8b9c33a11c757d024eafffb51a472
data/.rspec CHANGED
@@ -1,3 +1,2 @@
1
1
  --color
2
2
  --format progress
3
- -d
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - "1.9.2"
3
+ - "1.9.3"
4
+ - jruby-19mode
data/Gemfile CHANGED
@@ -1,4 +1,2 @@
1
1
  source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in slickj.gemspec
4
2
  gemspec
data/README.md CHANGED
@@ -1,18 +1,49 @@
1
- # slickr
1
+ # Welcome to Slickr
2
+ [![Build Status](https://travis-ci.org/mnoble/slickr.png?branch=master)](https://travis-ci.org/mnoble/slickr)
3
+ [![Code Climate](https://codeclimate.com/github/mnoble/slickr.png)](https://codeclimate.com/github/mnoble/slickr)
2
4
 
3
- JRuby Slick2D project generators.
5
+ Slickr is a JRuby, Slick2D, project framework.
4
6
 
5
- ## Overview
7
+ Slickr tries to merge concepts from Entity-Component and good old
8
+ fashion Object Oriented Design. Ruby gives you a lot of power to
9
+ write great code and Slickr tries to help you do that, while developing
10
+ games.
6
11
 
7
- The project Slickr sets up is an attempt to merge concepts from
8
- Entity-Component and just plain old OOP best practices. Ruby gives you
9
- a lot of power to write great code and Slickr tries to set you up to do
10
- that well.
12
+ "Slick2D is an easy to use set of tools and utilities wrapped around
13
+ LWJGL OpenGL bindings to make 2D Java game development easier." —
14
+ [http://www.slick2d.org/wiki/index.php/Main_Page](http://www.slick2d.org/wiki/index.php/Main_Page)
11
15
 
12
- Keep things simple. Components should have no knowledge of the Entities
13
- that will implement them; Systems should not care about what type of
14
- Entity they're acting on. Basically, watch or read anything Sandi Metz
15
- says and follow it.
16
+ ## Getting Started
17
+
18
+ 1\. Install Slickr
19
+
20
+ ```
21
+ $ gem install slickr
22
+ ```
23
+
24
+ 2\. Create a new Slickr game
25
+
26
+ ```
27
+ $ slickr new my_game
28
+ ```
29
+
30
+ where "my_game" is the name of the game.
31
+
32
+ 3\. Change directory to `my_game` and play it
33
+
34
+ ```
35
+ $ cd my_game
36
+ $ rake play
37
+ ```
38
+
39
+ You should see a Window with nothing but a white background and some FPS
40
+ information.
41
+
42
+ ## Generating New Code
43
+
44
+ ```
45
+ $ slickr generate [component|entity|renderer|system] NAME
46
+ ```
16
47
 
17
48
  ## Project Structure
18
49
 
@@ -22,62 +53,37 @@ says and follow it.
22
53
  │   ├── jinput.jar
23
54
  │   ├── lwjgl.jar
24
55
  │   └── slick.jar
25
- ├── lib
26
- │   ├── components
27
- │   ├── components.rb
56
+ ├── lib/
57
+ │   ├── behaviors/
58
+ │   ├── behaviors.rb
28
59
  │   ├── engine.rb
29
- │   ├── entities
60
+ │   ├── entities/
30
61
  │   ├── entities.rb
31
- │   ├── renderers
62
+ │   ├── renderers/
32
63
  │   ├── renderers.rb
33
- │   ├── systems
34
- │   └── systems.rb
64
+ │   ├── reactors/
65
+ │   └── reactors.rb
35
66
  ├── libjinput-osx.jnilib
36
67
  ├── liblwjgl.jnilib
37
68
  └── openal.dylib
38
69
 
39
- ### assets
40
-
70
+ **assets/**<br/>
41
71
  Images, sounds, videos, etc.
42
72
 
43
- ### java
44
-
73
+ **java/**<br/>
45
74
  Slick2D framework jars.
46
75
 
47
- ### lib
48
-
49
- Your game code.
50
-
51
- ### lib/components
52
-
53
- Behaviors that entities will include. These are modules that implement
54
- whatever behavior the entity should have. A common example will be a
55
- `Spatial` component that implements `x` and `y` position and movement.
56
-
57
- ### lib/entities
58
-
59
- The actual objects that live your game's world. Entities will implement
60
- Components and Systems conduct Entities. These will be your Heros,
61
- Enemies, Bosses, etc.
76
+ **lib/behaviors/**<br/>
77
+ Behaviors that entities will include.
62
78
 
63
- ### lib/renderers
79
+ **lib/entities/**<br/>
80
+ The actual objects that live your game's world.
64
81
 
82
+ **lib/renderers/**<br/>
65
83
  Draws the current state of entities to the screen.
66
84
 
67
- ### lib/systems
68
-
69
- Systems react to changes in the world and update entitites accordingly.
70
- View these as controllers of sorts. A good example of this is an `Input`
71
- system. It would react to keyboard events and tell the appropriate
72
- entities where to move.
73
-
74
- ## Installation
75
-
76
- $ gem install slickr
77
-
78
- ## Usage
79
-
80
- $ slickr new PROJECT_NAME
85
+ **lib/reactors/**<br/>
86
+ Reactors take changes in the world and updates entitites accordingly.
81
87
 
82
88
  ## Contributing
83
89
 
data/Rakefile CHANGED
@@ -1 +1,5 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task :default => :spec
data/lib/slickr.rb CHANGED
@@ -2,6 +2,23 @@ require "fileutils"
2
2
  require "pathname"
3
3
  require "thor"
4
4
  require "active_support/all"
5
+
5
6
  require "slickr/version"
7
+ require "slickr/actions/generate"
8
+ require "slickr/generators/base"
9
+ require "slickr/generators/project"
10
+ require "slickr/generators/behavior"
11
+ require "slickr/generators/entity"
12
+ require "slickr/generators/renderer"
13
+ require "slickr/generators/reactor"
14
+ require "slickr/entity_manager"
15
+ require "slickr/entity"
16
+ require "slickr/behavior"
17
+ require "slickr/reactor"
18
+ require "slickr/renderer"
6
19
  require "slickr/cli"
7
- require "slickr/actions/create"
20
+
21
+ module Slickr
22
+ class SlickrError < StandardError; end
23
+ class NotImplementedError < SlickrError; end
24
+ end
@@ -0,0 +1,51 @@
1
+ module Slickr
2
+ module Actions
3
+ # Adapter for calling the different types of Generators.
4
+ #
5
+ # This class takes the name of the generator, in any form, and
6
+ # the name the user wants to give to the new piece of code. It
7
+ # will normalize both to follow Slickr conventions.
8
+ #
9
+ # == Naming Conventions
10
+ #
11
+ # Slickr follows the same sort of conventions as Rails. Classes
12
+ # are appended with their type. Eg. a "spatiality" behavior will
13
+ # become +SpatialityBehavior+, a "hero" renderer will become
14
+ # +HeroRenderer+, etc.
15
+ #
16
+ # @example Generating a new behavior
17
+ # Slickr::Actions::Generate.new("behavior", "spatiality").start
18
+ # # => lib/behaviors/spatiality_behavior.rb
19
+ #
20
+ # @example Generating a new behavior by specifying the full name
21
+ # Slickr::Actions::Generate.new("behavior", "spatiality_behavior").start
22
+ # # => lib/behaviors/spatiality_behavior.rb
23
+ #
24
+ # @example Generating a new behavior by specifying the name in class form
25
+ # Slickr::Actions::Generate.new("behavior", "SpatialityBehavior").start
26
+ # # => lib/behaviors/spatiality_behavior.rb
27
+ #
28
+ class Generate
29
+ def initialize(type, name)
30
+ @type = type
31
+ @name = name
32
+ end
33
+
34
+ def start
35
+ generator_class.new(name).start
36
+ end
37
+
38
+ def generator_class
39
+ Slickr::Generators.const_get(:"#{@type.capitalize}")
40
+ end
41
+
42
+ def name
43
+ "#{basename}_#{@type}".squeeze("_")
44
+ end
45
+
46
+ def basename
47
+ @name.gsub(/#{@type}/i, "").downcase
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,68 @@
1
+ module Slickr
2
+ # Behaviors give entities the ability to do things. They should
3
+ # implement the logic to move around the world, detect collision,
4
+ # etc.
5
+ #
6
+ # A behavior should not care about what entities use it. It should
7
+ # specify all the attribute and methods relevant to what it does.
8
+ #
9
+ # module Spatiality
10
+ # include Slickr::Behavior
11
+ #
12
+ # attr_access :x, :y, :speed
13
+ #
14
+ # def prepare(options={})
15
+ # @x = options.fetch(:x, 0)
16
+ # @y = options.fetch(:y, 0)
17
+ # @speed = options.fetch(:speed, 0)
18
+ # end
19
+ #
20
+ # def up(delta)
21
+ # self.y -= speed * delta
22
+ # end
23
+ #
24
+ # def down(delta)
25
+ # self.y += speed * delta
26
+ # end
27
+ #
28
+ # def left(delta)
29
+ # self.x -= speed * delta
30
+ # end
31
+ #
32
+ # def right(delta)
33
+ # self.x += speed * delta
34
+ # end
35
+ # end
36
+ #
37
+ # == Preparing
38
+ #
39
+ # since behaviors are modules that get mixed into entities, we can't
40
+ # use the normal +initialize+ to set defaults. Instead, Slickr uses
41
+ # a convention of the +prepare+ method.
42
+ #
43
+ # When you specify an entity should implement some behavior, it's
44
+ # pushed into the entity's behavior stack. When that entity is
45
+ # instantiated, it will run through all of its behaviors and
46
+ # +prepare+ each one with the options specified in the entity.
47
+ #
48
+ # class Hero < Slickr::Entity
49
+ # use Spatiality, x: 10, y: 10, speed: 0.2
50
+ # end
51
+ #
52
+ # hero = Hero.new
53
+ # hero.x #=> 10
54
+ # hero.y #=> 10
55
+ # hero.speed #=> 0.2
56
+ #
57
+ # == Don't Clobber Behavior Attributes
58
+ #
59
+ # Use good OO common-sense here. Don't create multiple behaviors that
60
+ # all depend on attributes of the same name. Behaviors should be
61
+ # independent of one another.
62
+ #
63
+ module Behavior
64
+ def prepare(*args)
65
+ raise NotImplementedError
66
+ end
67
+ end
68
+ end
data/lib/slickr/cli.rb CHANGED
@@ -1,9 +1,18 @@
1
1
  module Slickr
2
2
  class CLI < Thor
3
- desc "new NAME", "Create a new jruby slick2d project"
4
- method_options :name => :string
3
+ desc "generate GENERATOR NAME", "Generate new code"
4
+ def generate(generator, name)
5
+ Actions::Generate.new(generator, name).start
6
+ end
7
+
8
+ desc "g GENERATOR NAME", "Shortcut for generate", hide: true
9
+ def g(*args)
10
+ generate(*args)
11
+ end
12
+
13
+ desc "new NAME [options]", "Create a new jruby slick2d project"
5
14
  def new(name)
6
- Actions::Create.new(name).start
15
+ Generators::Project.new(name).start
7
16
  end
8
17
  end
9
18
  end
@@ -0,0 +1,64 @@
1
+ module Slickr
2
+ class Entity
3
+ class << self
4
+ attr_writer :behaviors
5
+ end
6
+
7
+ # Specify that an Entity should behave a certain way.
8
+ #
9
+ # @param behavior [Slickr::Behavior] The behavior to use.
10
+ # @param options [Hash] Default behavior values.
11
+ #
12
+ # @example A Hero can move about the world.
13
+ #
14
+ # class Hero < Slickr::Entity
15
+ # use Spatiality
16
+ # end
17
+ #
18
+ # Different Behaviors will allow you to specify different
19
+ # default values. For example, a Spatiality behavior that
20
+ # allows an Entity to move about the world, may take a
21
+ # default +x+ and +y+ value. The Entity will be placed at
22
+ # that location when the scene is first loaded.
23
+ #
24
+ # @example A Hero starting at a specific location.
25
+ #
26
+ # class Hero < Slickr::Entity
27
+ # use Spatiality, x: 100, y: 100
28
+ # end
29
+ #
30
+ def self.use(behavior, options={})
31
+ behaviors << [behavior, options]
32
+ end
33
+
34
+ def self.behaviors
35
+ @behaviors ||= []
36
+ end
37
+
38
+ def self.reset
39
+ @behaviors = []
40
+ end
41
+
42
+ def initialize
43
+ behaviors.each { |behavior, options| behave_like(behavior, options) }
44
+ end
45
+
46
+ def behaviors
47
+ self.class.behaviors
48
+ end
49
+
50
+ private
51
+
52
+ # Mixin a behavior and configure it with the appropriate options.
53
+ #
54
+ # Each behavior must implement a +prepare+ method that initializes
55
+ # the Entity with any default values. The +prepare+ method will
56
+ # always be that of the last Behavior mixed in.
57
+ #
58
+ def behave_like(behavior, options={})
59
+ extend behavior
60
+ prepare(options)
61
+ EntityManager.register(self, behavior)
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,105 @@
1
+ module Slickr
2
+ # Provides a central repository for storing and querying for Entities
3
+ # that exhibit some behavior.
4
+ #
5
+ # Each scene of your game will probably have many entities. When you
6
+ # instantiate one of those Entities, it's automatically registered
7
+ # to the +EntityManager+, with the behaviors it implements.
8
+ #
9
+ # @example
10
+ #
11
+ # class Boss < Slickr::Entity
12
+ # use Spatial, x: 0, y: 0
13
+ # end
14
+ #
15
+ # boss = Boss.new
16
+ # # => #<Boss components=[:spatial]>
17
+ #
18
+ # EntityManager.entities
19
+ # # => [#<Boss components=[:spatial]>]
20
+ #
21
+ # Systems and Renderers are the two things that will likely need to
22
+ # alter or manipulate entities. Systems change the data associated
23
+ # with an entity and Renderers draw that to the screen. These objects
24
+ # can ask the +EntityManager+ for any entities that care about the
25
+ # behaviors they affect.
26
+ #
27
+ # @example
28
+ #
29
+ # class Systems::Input
30
+ # def call(delta)
31
+ # entities.each { |e| e.up(delta) } if up_key?
32
+ # end
33
+ #
34
+ # def entities
35
+ # EntityManager.entities_with(:controllable, :spatial)
36
+ # end
37
+ # end
38
+ #
39
+ # The +Input+ system cares about entities that can be moved by keyboard
40
+ # or mouse input and have spatial awareness; that is, things that can
41
+ # move. The above +System+ tells an entity to move up if the up key is
42
+ # pressed. What "moving up" means is determined by the component. The
43
+ # System doesn't care; it just reacts to events in the world and tells
44
+ # entities to do stuff based on that.
45
+ #
46
+ # It's important to view +:controllable+ and +:spatial+ as behaviors.
47
+ # Systems and Renderers expect these objects to conform to some standard
48
+ # API. We don't care where the object came from, what type it is or
49
+ # what it does outside of what we expect. We're going for good object
50
+ # oriented design through duck typing here.
51
+ #
52
+ module EntityManager
53
+ extend self
54
+
55
+ # @!attribute entities
56
+ # Hash of entities and their registered components
57
+ #
58
+ def entities
59
+ @entities ||= reset!
60
+ end
61
+
62
+ # Register an +Entity+ as conforming to a specific +Component+
63
+ # behavior.
64
+ #
65
+ # @param entity [Entity] The +Entity+ that includes the behavior
66
+ # @param type [Module] A +Component+ module.
67
+ #
68
+ def register(entity, type)
69
+ entities[entity] << symbolize(type)
70
+ end
71
+
72
+ # Retrieve all registered entities that include all of the
73
+ # components passed.
74
+ #
75
+ # @param components [Array<Component>] List of components
76
+ #
77
+ # @example
78
+ # EntityManager.entities
79
+ # => { #<Entity components=[:spatial, :size]>, #<Entity components=[:spatial]> }
80
+ #
81
+ # EntityManager.entities_with(:spatial, :size)
82
+ # => #<Entity components=[:spatial, :size]>
83
+ #
84
+ def entities_with(*components)
85
+ entities.select { |entity, types| includes_all?(types, Set[*components]) }.keys
86
+ end
87
+
88
+ # Remove all entities.
89
+ #
90
+ def reset!
91
+ @entities = Hash.new { |h,k| h[k] = Set.new }
92
+ end
93
+
94
+ private
95
+
96
+ def includes_all?(types, items)
97
+ items.subset?(types)
98
+ end
99
+
100
+ def symbolize(type)
101
+ type.name.demodulize.underscore.gsub("_behavior", "").to_sym
102
+ end
103
+ end
104
+ end
105
+