Jump to content
  • Advertisement
Sign in to follow this  
Vogelius

2D Walls with perspective trough vertex array speed problem

This topic is 2301 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi! My first post here but I think I posted it in the right place.

Anyway I am the developer of rbSFML and while creating this I have a game as a side project for fun that I also use to verify that the binding is working as intended. Anyway I've reached a problem I would need an outside look on as my thought process has become stuck.

As I normally work with 3D and so on I thought it would be fun to see if I could make a game with fake 3D and build a game from that. That has already been solved and works just fine and efficiently. Problem I have to solve is that when the camera moves the order of the walls have to be rearranged so they draw over each other correctly(SFML doesn't allow the use of depth buffer). Since this is being done in Ruby it's pretty slow. As soon as the rebuild runs the update time spikes and this builds linearly with the amount of walls I have. Currently the spike isn't that big, just takes Ruby around 1000 microseconds to build the walls you see on the image.

rsspib.png
But that's only 28 walls. The plan is to have a big and vivid world filled with this. So let's say worst-case scenario is a big city with large buildings so at any given time we might have around 500 walls showing on the screen. That would result in around 17.8 milliseconds of thinking time and resulting on less than 60 FPS on my hardware which is all of the latest. Of course that's not acceptable as it won't work as the development progresses. What I want is solutions in how to make this work better, I am out of ideas.


class TileArea
def rebuild_wall_vertexes(camera_position)
for layer in @wall_vertex_arrays
layer.clear
end
for wall in @walls
rect = wall.display_rect

min_tex = wall.type.texture_offset
max_tex = SFML::Vector2.new(min_tex.x + WallType::Size.x, min_tex.y + WallType::Size.y)
layer = @wall_vertex_arrays[wall.position.z]

wall.sort_directions(camera_position)
for direction in wall.directions
case direction
when :south then
layer.append(SFML::Vertex.new([rect.left, rect.top + rect.height], [min_tex.x, min_tex.y]))
layer.append(SFML::Vertex.new([rect.left, rect.top + rect.height], [min_tex.x, max_tex.y]))
layer.append(SFML::Vertex.new([rect.left + rect.width, rect.top + rect.height], [max_tex.x, max_tex.y]))
layer.append(SFML::Vertex.new([rect.left + rect.width, rect.top + rect.height], [max_tex.x, min_tex.y]))
when :north then
layer.append(SFML::Vertex.new([rect.left, rect.top], [min_tex.x, min_tex.y]))
layer.append(SFML::Vertex.new([rect.left, rect.top], [min_tex.x, max_tex.y]))
layer.append(SFML::Vertex.new([rect.left + rect.width, rect.top], [max_tex.x, max_tex.y]))
layer.append(SFML::Vertex.new([rect.left + rect.width, rect.top], [max_tex.x, min_tex.y]))
when :west then
layer.append(SFML::Vertex.new([rect.left, rect.top + rect.height], [min_tex.x, min_tex.y]))
layer.append(SFML::Vertex.new([rect.left, rect.top + rect.height], [min_tex.x, max_tex.y]))
layer.append(SFML::Vertex.new([rect.left, rect.top], [max_tex.x, max_tex.y]))
layer.append(SFML::Vertex.new([rect.left, rect.top], [max_tex.x, min_tex.y]))
when :east then
layer.append(SFML::Vertex.new([rect.left + rect.width, rect.top], [min_tex.x, min_tex.y]))
layer.append(SFML::Vertex.new([rect.left + rect.width, rect.top], [min_tex.x, max_tex.y]))
layer.append(SFML::Vertex.new([rect.left + rect.width, rect.top + rect.height], [max_tex.x, max_tex.y]))
layer.append(SFML::Vertex.new([rect.left + rect.width, rect.top + rect.height], [max_tex.x, min_tex.y]))
end
end
end
end
end

class Wall
def sort_directions(camera_position)
position_x = @position.x * WallType::Size.x + WallType::Size.x / 2
position_y = @position.y * WallType::Size.y + WallType::Size.y / 2
if(camera_position.y > position_y && (@directions.first == :south || @directions.last == :north))
@directions.reverse!
elsif(camera_position.y < position_y && (@directions.last == :south || @directions.first == :north))
@directions.reverse!
end
end
end


The rebuild method is only called when needed and even only on specific intervals. The vertex code can be optimized with not clearing and reusing the already in place vertexes but it doesn't give much(I tried but there is a visual bug in rbSFML that will be fixed soon and then I'll apply it). As far as I can see I need an architectural change in order to make the better of this. Any crazy idea is accepted. Keep in mind I am only interested in a solution for the walls visible on screen.

I have backup solutions but I would like to try and not do them as they are more or less just brute-forcing by providing more power instead of actually solving the problem.

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!