Skip to content

Commit

Permalink
alot of small fixes and cleanups. Paralaxx-class can now repeat textu…
Browse files Browse the repository at this point in the history
…res when scrolling both left and right. big README update regarding Chingus trait-system.
  • Loading branch information
ippa committed Oct 3, 2009
1 parent 85846bf commit 4055869
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 81 deletions.
66 changes: 63 additions & 3 deletions README.rdoc
Expand Up @@ -89,9 +89,10 @@ Both $window and game states gets some new graphical helpers, currently only 3,
fill_gradient() # Fills window or a given rect with a gradient between two colors.

If you base your models on GameObject (or BasicGameObject) you get:
Enemy.all # Returns all object based on this class
Enemy.each # Iterates through all objects of class Enemt.
Enemy.destroy_if(&block) # destroy all objects for which &block returns true
Enemy.all # Returns an Array of all Enemy-instances
Enemy.size # Returns the amount of Enemy-instances
Enemy.destroy_all # Destroys all Enemy-instances
Enemy.destroy_if(&block) # Destroy all objects for which &block returns true


== BASICS / EXAMPLES
Expand Down Expand Up @@ -417,6 +418,65 @@ Or Chingus shortcut:

Chingus inputhandler will detect that Menu is a gamestate-class, create a new instance, cache it and activate it with push_game_state().

=== Traits
Traits (often called behaivors) is a way of adding logic to any class inheriting from BasicGameObject / GameObject.
Chingus trait-implementation is just ordinary ruby modules with 3 special methods:
- setup_trait
- update_trait
- draw_trait
Each of those 3 methods must call "super" to continue the trait-chain.

The flow for a game object then becomes:

-- creating the object
1) GameObject#initialize(options)
2) GameObject#setup_trait(options)
-- each game iteration
3) GameObject#draw_trait
4) GameObject#draw
5) GameObject#update_trait
6) GameObject#update


There's a couple of traits included as default in Chingu:

==== Trait "timer"
Adds timer functionallity to your game object
during(300) { @color = Color.new(0xFFFFFFFF) } # forces @color to white ever update for 300 ms
after(400) { self.destroy } # destroy object after 400 ms
between(1000,2000) { self.rotate(10) } # starting after 1 second, call rotate(10) every update during 1 second

==== Trait "velocity"
Adds variables velocity_x, velocity_y, acceleration_x, acceleration_y, max_velocity to game object.
They modify x, y as you would expect. *speed / angle will come*


== (IN DEVELOPMENT) Trait "effect"
Adds ability to automaticly fade, rotate and scale game objects.
* API isn't stabilized yet! *

== (IN DEVELOPMENT) Trait "collision_detection"
Adds class and instance methods for basic collision detection.

# Class method example
# This will collide all Enemy-instances with all Bullet-instances using the attribute #radius from each object.
Enemy.each_radius_collision(Bullet) do |enemy, bullet|
end

# You can also use the instance methods. This will use the Rect bounding_box from @player and each EnemyRocket-object.
@player.each_bounding_box_collision(EnemyRocket) do |player, enemyrocket|
player.die!
end

* API isn't stabilized yet! *

== (IN DEVELOPMENT) Trait "retrofy"
Providing easier handling of the "retrofy" effect (non-blurry zoom)
Aims to help out when using zoom-factor to create a retrofeeling with big pixels.
Provides screen_x and screen_y which takes the zoom into account
Also provides new code for draw() which uses screen_x / screen_y instead of x / y


=== Assets / Paths

You might wonder why this is necessary in the straight Gosu example:
Expand Down
82 changes: 41 additions & 41 deletions examples/example11.rb
@@ -1,51 +1,51 @@
require 'rubygems'
require 'opengl'
require 'gosu'
#include Gosu
require File.join(File.dirname($0), "..", "lib", "chingu")
include Gosu

class Game < Gosu::Window
#
# Parallax-example
# Images from http://en.wikipedia.org/wiki/Parallax_scrolling
#
class Game < Chingu::Window
def initialize
super(400,400,false)
super
self.input = { :holding_left => :scroll_left,
:holding_right => :scroll_right,
:holding_up => :scroll_up,
:holding_down => :scroll_down,
:escape => :exit }

self.caption = "Chingu::Parallax example. Scroll with left/right arrows."

@parallax = Chingu::Parallax.create(:x => 0, :y => 0, :center_x => 0, :center_y => 0)

#
# If no :zorder is given to @parallax.add_background it defaults to first added -> lowest zorder
# Everywhere the :image argument is used, theese 2 values are the Same:
# 1) Image["foo.png"] 2) "foo.png"
#
# TODO: scrolling to left borks outm, fix. + get rid of center_x / center_y args in a clean way.
@parallax << {:image => "paralaxx2", :damping => 100, :center => 0)
@parallax << {:image => "parallax-scroll-example-layer-1.png", :damping => 10, :center => 0)
@parallax << {:image => "paralaxx2.png", :damping => 5, :center => 0)
end

def update
def scroll_left
@parallax.x -= 2
end

def draw
gl do
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

# Reset the view
glLoadIdentity

# Move to the left 1.5 units and into the screen 6.0 units
glTranslate(-1.5, 0.0, -6.0)

# -- Draw a triangle --
glColor(1.0,1.0,1.0)

# Begin drawing a polygon
glBegin(GL_POLYGON)
glVertex3f( 0.0, 1.0, 0.0) # Top vertex
glVertex3f( 1.0, -1.0, 0.0) # Bottom right vertex
glVertex3f(-1.0, -1.0, 0.0) # Bottom left vertex
# Done with the polygon
glEnd

# Move 3 units to the right
glTranslate(3.0, 0.0, 0.0)

# -- Draw a square (quadrilateral) --
# Begin drawing a polygon (4 sided)
glBegin(GL_QUADS)
glVertex3f(-1.0, 1.0, 0.0) # Top Left vertex
glVertex3f( 1.0, 1.0, 0.0) # Top Right vertex
glVertex3f( 1.0, -1.0, 0.0) # Bottom Right vertex
glVertex3f(-1.0, -1.0, 0.0) # Bottom Left
glEnd
glFlush
end
def scroll_right
@parallax.x += 2
end

def scroll_up
@parallax.y -= 2
end

def scroll_down
@parallax.y += 2
end

end

Game.new.show
Game.new.show
13 changes: 8 additions & 5 deletions examples/example3.rb
Expand Up @@ -9,7 +9,9 @@
class Game < Chingu::Window
def initialize
super
self.input = {:holding_left => :scroll_left, :holding_right => :scroll_right, :escape => :exit}
self.input = { :holding_left => :scroll_left, :holding_right => :scroll_right, :escape => :exit }

self.caption = "Chingu::Parallax example. Scroll with left/right arrows."

@parallax = Chingu::Parallax.create(:x => 0, :y => 0, :center_x => 0, :center_y => 0)

Expand All @@ -19,10 +21,10 @@ def initialize
# 1) Image["foo.png"] 2) "foo.png"
#
# TODO: scrolling to left borks outm, fix. + get rid of center_x / center_y args in a clean way.
@parallax.add_background(:image => "Parallax-scroll-example-layer-0.png", :damping => 100, :center_x => 0, :center_y => 0)
@parallax.add_background(:image => "Parallax-scroll-example-layer-1.png", :damping => 10, :center_x => 0, :center_y => 0)
@parallax.add_background(:image => "Parallax-scroll-example-layer-2.png", :damping => 5, :center_x => 0, :center_y => 0)
@parallax.add_background(:image => "Parallax-scroll-example-layer-3.png", :damping => 1, :center_x => 0, :center_y => 0)
@parallax.add_background(:image => "Parallax-scroll-example-layer-0.png", :damping => 100, :center => 0)
@parallax.add_background(:image => "Parallax-scroll-example-layer-1.png", :damping => 10, :center => 0)
@parallax.add_background(:image => "Parallax-scroll-example-layer-2.png", :damping => 5, :center => 0)
@parallax << {:image => "Parallax-scroll-example-layer-3.png", :damping => 1, :center => 0} # you can also add like this
end

def scroll_left
Expand All @@ -32,6 +34,7 @@ def scroll_left
def scroll_right
@parallax.x += 2
end

end

Game.new.show
4 changes: 2 additions & 2 deletions examples/example9.rb
Expand Up @@ -38,7 +38,7 @@ def initialize(options)
@velocity_y = options[:velocity_y] || 1 + rand(2)

@bounding_box = Rect.new([@x, @y, 10, 10])
@radius = 12
@radius = 6

@blue = Color.new(255,100,255,255)
@red = Color.new(255,255,10,10)
Expand Down Expand Up @@ -98,7 +98,7 @@ def update
end

def draw
$window.caption = "Radius based collision Detection between all particles. Particles#: #{game_objects.size} - FPS: #{$window.fps}"
$window.caption = "radius based iterative collision detection. Particles#: #{game_objects.size}, Collisionchecks each gameloop: ~#{game_objects.size**2} - FPS: #{$window.fps}"
super
end
end
Expand Down
2 changes: 2 additions & 0 deletions lib/chingu/actor.rb
Expand Up @@ -2,6 +2,8 @@ module Chingu
#
# A game object class with most components included, nice for quick prototypes
#
# TODO: we probably wanna expand this concept or remove Actor as a whole.
#
class Actor < Chingu::GameObject
has_traits :effect, :velocity, :input

Expand Down
7 changes: 4 additions & 3 deletions lib/chingu/basic_game_object.rb
Expand Up @@ -107,7 +107,7 @@ def self.size
#
def self.destroy_if(&block)
all.each do |object|
object.destroy! if yield(object)
object.destroy if yield(object)
end
end

Expand All @@ -123,9 +123,10 @@ def self.destroy_all
# Removes object from the update cycle and freezes the object to prevent further modifications.
# If the object isn't being managed by Chingu (ie. you're doing manual update/draw calls) the object is only frozen, not removed from any updae cycle (because you are controlling that).
#
def destroy!
def destroy
@parent.remove_game_object(self) if @parent
self.freeze
end
end
alias :destroy! :destroy
end
end
24 changes: 8 additions & 16 deletions lib/chingu/game_object.rb
Expand Up @@ -45,26 +45,18 @@ def initialize(options = {})
@y = options[:y] || 0
@angle = options[:angle] || 0

@center_x = options[:center_x] || options[:center] || 0.5
@center_y = options[:center_y] || options[:center] || 0.5
@factor_x = options[:factor_x] || options[:factor] || 1.0
@factor_y = options[:factor_y] || options[:factor] || 1.0

# faster?
#self.center = options[:center] || 0.5
#self.factor = options[:factor] || 1.0
#@center_x = options[:center_x] || 0.5
#@center_y = options[:center_y] || 0.5
#@factor_x = options[:factor_x] || 1.0
#@factor_y = options[:factor_y] || 1.0
self.center = options[:center] || 0.5
self.factor = options[:factor] || 1.0
@center_x = options[:center_x] if options[:center_x]
@center_y = options[:center_y] if options[:center_y]
@factor_x = options[:factor_x] if options[:factor_x]
@factor_y = options[:factor_y] if options[:factor_y]

if options[:color].is_a?(Gosu::Color)
@color = options[:color]
elsif options[:color].is_a? Bignum
@color = Gosu::Color.new(options[:color])
else
@color = Gosu::Color.new(0xFFFFFFFF)
end
@color = Gosu::Color.new(options[:color] || 0xFFFFFFFF)
end

@mode = options[:mode] || :default # :additive is also available.
@zorder = options[:zorder] || 100
Expand Down
22 changes: 11 additions & 11 deletions lib/chingu/parallax.rb
Expand Up @@ -6,6 +6,8 @@ module Chingu
class Parallax < Chingu::GameObject
attr_reader :backgrounds

#
# Options (in hash-format):
#
# repeat: [true|false] When one background ends within the screen, repeat/loop it
#
Expand All @@ -17,17 +19,13 @@ def initialize(options)

#
# Add one background, either an ParallaxBackground-object or a Hash of options to create one
# You can also add new backgrounds with the shortcut "<<":
# @parallax << {:image => "landscape.png", :damping => 1}
#
def add_background(arg)
@backgrounds << (arg.is_a?(ParallaxBackground) ? arg : ParallaxBackground.new(arg))
end

#
# Shortcut for #add_background
#
def <<(arg)
self.add_background(arg)
end
alias << add_background

#
# TODO: make use of $window.milliseconds_since_last_update here!
Expand All @@ -36,6 +34,9 @@ def update
@backgrounds.each do |background|
background.x = -@x / background.damping
background.y = @y / background.damping

# This is the magic that repeats the background to the left and right
background.x -= background.image.width while background.x > 0
end
end

Expand All @@ -44,17 +45,16 @@ def update
#
def draw
@backgrounds.each do |background|
#background.image.draw(real_x, real_y, background.zorder)
background.draw

save_x = background.x

## If background lands inside our screen, repeat it
while (background.x + background.image.width) < $window.width
background.x += background.image.width
background.x += background.image.width
background.draw
#background.x -= background.image.width
#background.image.draw(real_x+background.image.width, real_y, background.zorder)
end

background.x = save_x
end
self
Expand Down

0 comments on commit 4055869

Please sign in to comment.