Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

2D Walls with perspective trough vertex array speed problem


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
No replies to this topic

#1 Vogelius   Members   -  Reputation: 102

Like
0Likes
Like

Posted 21 August 2012 - 09:49 AM

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.

Posted Image
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.

Ad:



Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS