Created
January 10, 2014 00:05
-
-
Save runnerpack/8344513 to your computer and use it in GitHub Desktop.
My basic implementation of "platformer" physics, based on information from http://freespace.virgin.net/hugo.elias/models/m_main.htm You'll need to supply your own "dude.png" to act as a character.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Fix require path issues in 1.9.* | |
$: << "." | |
begin; require 'rubygems'; rescue; end | |
require 'gosu' | |
include Gosu | |
#require 'texplay' | |
# Screen size | |
W = 1024 | |
H = 576 | |
# Full-screen mode | |
FS = false | |
# Update interval (Hz) | |
FPS = 60 | |
# Acceleration due to gravity (not sure what the units are; it doesn't have to be based on the update interval) | |
GRAVITY = FPS.div(20) | |
class Point | |
attr_accessor :x, :y | |
def initialize(x = 0, y = 0) | |
@x = x | |
@y = y | |
end | |
end # Point class | |
class Jumpman | |
attr_accessor :pos, :speed, :f_ground, :f_air, :tv, :jumps, :maxjumps, :color, :face | |
attr_reader :grav | |
def initialize (win, x, y, speed = 2, grav = 1.0, f_ground = 0.85, f_air = 0.85, tv = 64) | |
@win = win | |
@pos = Point.new(x, y) | |
@vel = Point.new(0, 0) | |
@acc = Point.new(0, 0) | |
# @acc = Point.new(0, @grav * GRAVITY) | |
@speed = speed | |
self.grav = grav | |
@f_ground = f_ground | |
@f_air = f_air | |
@tv = tv | |
@color = 0xFFFFFFFF | |
@jumps = 0 | |
@maxjumps = 1 | |
@face = 1.0 | |
# TODO: Replace with load_from_tiles for animation | |
@player = Gosu::Image.new(@win, "dude.png", true) | |
@vel = Point.new(@player.width * -0.5, -@player.height + 5) | |
end # Jumpman.new | |
def grav=(g) | |
@grav = g | |
@acc.y = @grav * GRAVITY if @acc | |
end | |
def draw | |
@win.translate(@pos.x, @pos.y) { | |
@player.draw_rot(0, 0, 0, 0.0, 0.5, 1.0, @face, @grav < 0 ? -1.0 : 1.0, @color) | |
} | |
end # Jumpman#draw | |
def update | |
@pos.x += @vel.x | |
@pos.y += @vel.y | |
@vel.x += @acc.x | |
@vel.y += @acc.y | |
# I haven't implemented Hugo's "wind resistance" formula, yet, hence this cludge. | |
if @jumps > 0 | |
@vel.x *= @f_air | |
else | |
@vel.x *= @f_ground | |
end | |
if @vel.y.abs > @tv | |
@vel.y = @tv * @grav | |
end | |
# Simple collision to keep player from falling off the screen | |
if (@pos.y > H * 0.95) | |
@pos.y = H * 0.95 | |
@vel.y = 0 | |
@jumps = 0 | |
elsif (@pos.y < H * 0.05) | |
@pos.y = H * 0.05 | |
@vel.y = 0 | |
@jumps = 0 | |
end | |
end # Jumpman#update | |
def button_down(id) | |
case id | |
when GpLeft, KbLeft | |
@face = -1.0 | |
@acc.x = -@speed | |
when GpRight, KbRight | |
@face = 1.0 | |
@acc.x = @speed | |
when GpButton2, KbLeftControl | |
# Jump | |
if @jumps < @maxjumps | |
@jumps += 1 | |
@vel.y = -@grav * GRAVITY * 12.0 | |
end | |
end | |
end # Jumpman#button_down | |
def button_up(id) | |
case id | |
when GpLeft, GpRight, KbLeft, KbRight | |
@acc.x = 0.0 | |
when GpButton2 | |
# Reserved for fireballs, etc. ;) | |
when GpButton0, KbSpace | |
# Gravity flip! | |
self.grav = -@grav | |
@jumps = @maxjumps | |
end | |
end # Jumpman#button_up | |
end # class Jumpman | |
class GfxWindow < Gosu::Window | |
def initialize | |
# Call the base class' initialize | |
super W, H, FS, 1.0 / FPS * 1000 | |
self.caption = "Jumping Physics!" | |
# Sprites | |
@actors = [] | |
# Player | |
@actors << Jumpman.new(self, W * 0.5, H * 0.25) | |
# Collectables | |
@statics = [] | |
# @statics << Item.new(self, W * 0.85, H * 0.75) | |
# @background = Image.new(self, 'blank_room.jpg', false) | |
@info = Gosu::Font.new(self, Gosu::default_font_name, 14) | |
@last_time = Gosu::milliseconds() | |
end | |
def button_down(id) | |
@actors.each do |a| | |
a.button_down(id) | |
end | |
if id == Gosu::Button::KbEscape then | |
close | |
end | |
end | |
def button_up(id) | |
@actors.each do |a| | |
a.button_up(id) | |
end | |
end | |
def draw | |
# @background.draw(0, 0, -1000, W.to_f / @background.width, H.to_f / @background.height) | |
@actors.each do |a| | |
a.draw | |
end | |
# @statics.each do |s| | |
# s.draw | |
# end | |
# @info.draw("x: #{@actors[0].x.floor} y: #{@actors[0].y.floor} ms: #{Gosu::milliseconds() - @last_time}", 10, 10, 0) | |
@last_time = Gosu::milliseconds() | |
end | |
def update | |
@actors.each do |a| | |
a.update | |
end | |
# @statics.each do |s| | |
# s.update | |
# end | |
end | |
def needs_cursor?() | |
true | |
end | |
end # class GfxWindow | |
begin | |
$window = GfxWindow.new | |
$window.show | |
rescue Exception => e | |
puts e.message, e.backtrace | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment