Skip to content

Instantly share code, notes, and snippets.

Created July 24, 2012 03:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/3167856 to your computer and use it in GitHub Desktop.
Save anonymous/3167856 to your computer and use it in GitHub Desktop.
require 'rubygems'
require 'gosu'
include Gosu
module Tiles
Grass = 0
Earth = 1
end
class CollectibleGem
attr_reader :x, :y
def initialize(image, x, y)
@image = image
@x, @y = x, y
end
def draw
# Draw, slowly rotating
@image.draw_rot(@x, @y, 0, 25 * Math.sin(milliseconds / 133.7))
end
end
# Player class.
class CptnRuby
attr_reader :x, :y
attr_accessor :gems_collected
def initialize(window, x, y)
@x, @y = x, y
@dir = :left
self.gems_collected = 0
@vy = 0 # Vertical velocity
@map = window.map
# Load all animation frames
@standing, @walk1, @walk2, @jump =
*Image.load_tiles(window, "media/CptnRuby.png", 50, 50, false)
# This always points to the frame that is currently drawn.
# This is set in update, and used in draw.
@cur_image = @standing
end
def draw
# Flip vertically when facing to the left.
if @dir == :left then
offs_x = -25
factor = 1.0
else
offs_x = 25
factor = -1.0
end
@cur_image.draw(@x + offs_x, @y - 49, 0, factor, 1.0)
end
# Could the object be placed at x + offs_x/y + offs_y without being stuck?
def would_fit(offs_x, offs_y)
# Check at the center/top and center/bottom for map collisions
not @map.solid?(@x + offs_x, @y + offs_y) and
not @map.solid?(@x + offs_x, @y + offs_y - 45)
end
def update(move_x)
# Select image depending on action
if (move_x == 0)
@cur_image = @standing
else
@cur_image = (milliseconds / 175 % 2 == 0) ? @walk1 : @walk2
end
if (@vy < 0)
@cur_image = @jump
end
# Directional walking, horizontal movement
if move_x > 0 then
@dir = :right
move_x.times { if would_fit(1, 0) then @x += 1 end }
end
if move_x < 0 then
@dir = :left
(-move_x).times { if would_fit(-1, 0) then @x -= 1 end }
end
# Acceleration/gravity
# By adding 1 each frame, and (ideally) adding vy to y, the player's
# jumping curve will be the parabole we want it to be.
@vy += 1
# Vertical movement
if @vy > 0 then
@vy.times { if would_fit(0, 1) then @y += 1 else @vy = 0 end }
end
if @vy < 0 then
(-@vy).times { if would_fit(0, -1) then @y -= 1 else @vy = 0 end }
end
end
def try_to_jump
if @map.solid?(@x, @y + 1) then
@vy = -20
end
end
def collect_gems(gems)
# Same as in the tutorial game.
gems.reject! do |c|
if (c.x - @x).abs < 50 and (c.y - @y).abs < 50
self.gems_collected += 1
true
end
end
end
end
# Map class holds and draws tiles and gems.
class Map
attr_reader :width, :height, :gems, :total_gems
def initialize(window, filename)
# Load 60x60 tiles, 5px overlap in all four directions.
@tileset = Image.load_tiles(window, "media/CptnRuby Tileset.png", 60, 60, true)
gem_img = Image.new(window, "media/CptnRuby Gem.png", false)
@gems = []
lines = File.readlines(filename).map { |line| line.chomp }
@height = lines.size
@width = lines[0].size
@tiles = Array.new(@width) do |x|
Array.new(@height) do |y|
case lines[y][x, 1]
when '"'
Tiles::Grass
when '#'
Tiles::Earth
when 'x'
@gems.push(CollectibleGem.new(gem_img, x * 50 + 25, y * 50 + 25))
nil
else
nil
end
end
end
@total_gems = @gems.length
end
def draw
# Very primitive drawing function:
# Draws all the tiles, some off-screen, some on-screen.
@height.times do |y|
@width.times do |x|
tile = @tiles[x][y]
if tile
# Draw the tile with an offset (tile images have some overlap)
# Scrolling is implemented here just as in the game objects.
@tileset[tile].draw(x * 50 - 5, y * 50 - 5, 0)
end
end
end
@gems.each { |c| c.draw }
end
# Solid at a given pixel position?
def solid?(x, y)
y < 0 || @tiles[x / 50][y / 50]
end
end
class Game < Window
attr_accessor :level, :map
def initialize
super(640, 480, false)
self.caption = "Cptn. Ruby"
self.level = 1
@sky = Image.new(self, "media/Space.png", true)
self.map = Map.new(self, "media/map_#{level}.txt")
@cptn = CptnRuby.new(self, 400, 100)
# The scrolling position is stored as top left corner of the screen.
@camera_x = @camera_y = 0
end
def update
move_x = 0
move_x -= 5 if button_down? KbLeft
move_x += 5 if button_down? KbRight
@cptn.update(move_x)
@cptn.collect_gems(@map.gems)
# Scrolling follows player
@camera_x = [[@cptn.x - 320, 0].max, @map.width * 50 - 640].min
@camera_y = [[@cptn.y - 240, 0].max, @map.height * 50 - 480].min
if @cptn.gems_collected >= @map.total_gems
load_new_level
end
end
def draw
@sky.draw 0, 0, 0
translate(-@camera_x, -@camera_y) do
@map.draw
@cptn.draw
end
end
def button_down(id)
if id == KbUp then @cptn.try_to_jump end
if id == KbEscape then close end
end
def load_new_level
self.level += 1
self.map = Map.new(self, "media/map_#{level}.txt")
@camera_x = @camera_y = 0
@cptn.gems_collected = 0
end
end
Game.new.show
#....................................................#
#....................................................#
#....................................................#
#............x.......................................#
#x....x...x..x.......#####...........................#
#.x.....................................##...........#
#...............""..........###...##..........##.....#
#..##..###..##..##...................................#
#..................................................###
#.............................###....................#
##....##.............................................#
#....................##....##......##....##....##....#
#....................................................#
#...x....##....##....................................#
#.....x..............................................#
#......x...##.....##.................................#
#.......x.........................................#..#
#...........##........#...#...#..#...................#
#...#................................................#
#....."""".........................#..#####...###....#
#x....#......................##......................#
#"""""#.....#........................#...............#
##xxxx......#........................................#
##xxxx...#####............."...""""".................#
######"""#############################################
#........................................................#
#........................................................#
#........................................................#
#.........................x....."".......................#
#............xxx.........x......###....................x.#
#""""""""""""""""....##""""""...###""...####""####""""####
#......................######..........................xx#
#..x...................................................xx#
#.............................#........."""""""""""""""""#
#x.................xx.##......#.........##################
####..#..#..#..#########......x......#...................#
#.............................###........................#
#....x...........................#......................x#
#...................................###..................#
#"""""".....................................x............#
#...........x........x.................#..""""...........#
#.........######...#####......................""...#...""#
#xx......................##..........................x...#
#................................x..x................#...#
######.......................###.##.##.##................#
#....##............................................#...""#
#........................................................#
#x.......##..................###.....................#...#
#".............."".......................................#
###.............####...............................#.....#
#"""""""""""""#######""""""""""""""""""""""""""""""""""""#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment