Thanks!
Well, this code is a mess. I wouldn't use any of this in any project. It is just to test the validity of the equation.
require 'gosu'
White=Gosu::Color::WHITE
class GameWindow < Gosu::Window
def initialize
super(600, 400, true)
$window=self
@img1=Gosu::Image.new(self, "tile1.png", true) #gray tile 40x40
@img3=Gosu::Image.new(self, "tile3.png", true) #yellow tile 80X80
@wall=[]
@f1=[]
for i in 0..18
#[tile img, x position]
@wall<<[@img1,i*40] #wall tiles
@f1<<[@img3,i*40] #floor tiles
end
@cx=350 #sort of camera_x
@cy=180.1 #horizon_y
@box=[]
for i in 0..2
@box<<Box.new(10+i*200, @cx, @cy)
end
@ms=2
end
def update
self.caption = "Editor: #{Gosu::fps} fps"
@wall.each do |pie|
pie[1]-=@ms
end
@f1.each do |pie|
pie[1]-=@ms
end
@box.each do |box|
box.move(-@ms)
end
#end
@box.each do |box|
box.update
end
end
#this could be much simpler, probably
#I just made a drawing and used basic math
#x1,y1 are coordinates of a point (1) in the screen
#y2 is the y coordinate on the screen of another point (2)
#points 1 and 2 are conected by a line, perpendicular to the wall
def getp(x1,y1,y2)
a=(x1*(@cy-y2)+@cx*(y2-y1))/(@cy-y1)
a
end
def draw
@wall.each do |brick|
if brick[1].between?(-40,740) #if we want to draw it
#fill the screen vertically
brick[0].draw(brick[1], 0, 0, 1, 1, White, :default)
brick[0].draw(brick[1], 40, 0, 1, 1, White, :default)
brick[0].draw(brick[1], 80, 0, 1, 1, White, :default)
brick[0].draw(brick[1], 120, 0, 1, 1, White, :default)
brick[0].draw(brick[1], 160, 0, 1, 1, White, :default)
brick[0].draw(brick[1], 200, 0, 1, 1, White, :default)
else
#when scrolling, we move the tile to right end if it moves left off the screen
if brick[1]<-40
brick[1]=@wall.max_by{|a|a[1]}[1]+40
end
end
end
#we should have a class for the floor tiles and we should calculate the coordinates in the update step, but I was just checking if the calculations are correct
@f1.each do |b|
if b[1].between?(-40,740)
#drawing the floor tiles
#the floor "top"
b[0].draw_as_quad(b[1],240,White,b[1]+40,240,White,getp(b[1],240,300),300,White,getp(b[1]+40,240,300),300,White,1,:default)
#the "front" face of the floor "blocks"
b[0].draw_as_quad(getp(b[1],240,300),300,White,getp(b[1]+40,240,300),300,White,getp(b[1],240,300),350,White,getp(b[1]+40,240,300),350,White,1,:default)
else
#when scrolling, we move the tile to right end if it moves left off the screen
if b[1]<-40
b[1]=@f1.max_by{|a|a[1]}[1]+40
end
end
end
@box.each do |box|
box.draw
end
end
def button_down(id)
if id == Gosu::KbEscape
puts @cy
$window.close
end
#move the horizon line up/down
if id==Gosu::KbUp
@cy-=5
@box.each do |box|
box.move_horizon(-5)
end
end
if id==Gosu::KbDown
if @cy<235
@cy+=5
@box.each do |box|
box.move_horizon(5)
end
end
end
end
end
class Box
def initialize (x, cx, cy)
@cx=cx
@cy=cy
@x=x
@img2=Gosu::Image.new($window, "tile2.png", true) #red tile 40x40
end
def getp(x1,y1,y2)
a=(x1*(@cy-y2)+@cx*(y2-y1))/(@cy-y1)
a
end
def move(x)
@x+=x
end
def move_horizon(y)
@cy+=y
end
def update
#when scrolling, we move the block to right end if it moves left off the screen
if @x<-40
@x=740
end
end
def draw
if @x.between?(-42,702)
#drawing the faces of the boxes
#we assume the block top being below the horizon
#we can easily make this more generic by adding the calcs for it being above the horizon
#again, we should add variables for the box shape and make calculations in the update step
#front face
@img2.draw_as_quad(getp(@x,240,250),230,White,getp(@x+40,240,250),230,White,getp(@x,240,250),250,White,getp(@x+40,240,250),250,White,1,:default)
#top face
@img2.draw_as_quad(@x,225,White,@x+40,225,White,getp(@x,240,250),230,White,getp(@x+40,240,250),230,White,1,:default)
#left face, only displayed if the block left face is to the right of @cx
if @x>@cx
@img2.draw_as_quad(@x,225,White,getp(@x,240,250),230,White,@x,240,White,getp(@x,240,250),250,White,1,:default)
end
#right face, only displayed if the block right face is to the left of @cx
if (@x+40)<@cx
@img2.draw_as_quad(getp(@x+40,240,250),230,White,@x+40,225,White,getp(@x+40,240,250),250,White,@x+40,240,White,1,:default)
end
end
end
end
window = GameWindow.new
window.show