Roguelike engine - How to?

Showcase your libraries, tools and other projects that help your fellow love users.
Post Reply
User avatar
arquivista
No longer with us
Posts: 266
Joined: Tue Jul 06, 2010 8:39 am
Location: Insert Geolocation tag here
Contact:

Roguelike engine - How to?

Post by arquivista »

Hi folks, Based in Wiki Tutorials i was doing a small engine test for a roguelike (ie a kind of rpg), however i still dont yet understand how to deal with some map graphic issues.
My problem: i have an tiled map and a "independent" char (i want to try to do a kind of another layer) that i want to put over the map. However i don't understand how to update the char directly in the map and not quite in the window area. I mean what's the code way of merge my "tileHero" over the "tile" one? There is a way or should i rearrange code in order to change the Hero position all times map is scrolled? Thx in advance for help/sugestions.

Full package in attachment

Code: Select all

-- Roguelike Engine Test v0.1

-- Roadmap
-- 0.1 Split tile image file loading + Mouse Scroll Map
-- 0.2 Add Hero + Key Movement
-- 0.3 Parse unique tile image file + text array for data tiles  
-- 0.4 Map loading file
-- 0.5 Map algorithm


function love.load()
	setupMap()
	setupHero()
	initWindow()  
end

function initWindow ()

	window_size_x = tile_w * map_display_w + ( 2 * tile_w )
	window_size_y = tile_h * map_display_h + ( 2 * tile_h )
	windowfeatures = love.graphics.setMode( window_size_x, window_size_y, no, no, no )
	love.graphics.setCaption( "Roguelike Engine Test v0.1" )
	love.mouse.setPosition( window_size_x/2, window_size_x/2 )
	love.graphics.setFont(12)

end 

function setupMap()

	tile = {}
	for i=0,3 do -- Grass = 0, Tree = 1, Lava = 2, Water = 3
	   tile[i] = love.graphics.newImage( "tile"..i..".png" )
	end

	map_w = 20			-- Map Size X
	map_h = 20			-- Map Size Y
	map_x = 0			-- Reset X Map Position
	map_y = 0			-- Reset Y Map Position
	map_offset_x = 0	-- Window/Camera Offset X 
	map_offset_y = 0	-- Window/Camera Offset Y
	map_display_w = 9	-- Window/Camera Size X
	map_display_h = 9	-- Window/Camera Size Y
	tile_w = 32			-- Tile Size X
	tile_h = 32			-- Tile Size Y

map={
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
   { 0, 1, 0, 0, 2, 2, 2, 0, 3, 0, 3, 0, 1, 1, 1, 0, 0, 0, 0, 0},
   { 0, 1, 0, 0, 2, 0, 2, 0, 3, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0},
   { 0, 1, 1, 0, 2, 2, 2, 0, 0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
   { 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0},
   { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 2, 2, 2, 0, 3, 3, 3, 0, 1, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0},
   { 0, 2, 0, 0, 0, 3, 0, 3, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
   { 0, 2, 0, 0, 0, 3, 0, 3, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
   { 0, 2, 2, 2, 0, 3, 3, 3, 0, 1, 1, 1, 0, 2, 2, 2, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
}
  
end

function setupHero ()

	tileHero = love.graphics.newImage( "rogue.png" )
	hero_x = 5
	hero_y = 5		
end

function draw_map()
   for y=1, map_display_h do
      for x=1, map_display_w do                                                         
         love.graphics.draw( 
            tile[map[y+map_y][x+map_x]], 
            (x*tile_w)+map_offset_x, 
            (y*tile_h)+map_offset_y )
      end
   end
end

function draw_hero()
	love.graphics.draw( tileHero, hero_x * tile_w + map_offset_x , hero_y * tile_h + map_offset_y)
end


function love.update()

	mx = love.mouse.getX( )
	my = love.mouse.getY( )
	
	if my < tile_h then
	   map_y = map_y-1
	   if map_y < 0 then map_y = 0; end
	end
	
	bound_y = tile_h + map_display_h * tile_h
	
	if my > bound_y then
	   map_y = map_y+1
	   if map_y > map_h-map_display_h then map_y = map_h-map_display_h; end
	end
	
	if mx < tile_w then
	   map_x = math.max(map_x-1, 0)
	end
	
	bound_x = tile_w + map_display_w * tile_w	
	
	if mx > bound_x then
	   map_x = math.min(map_x+1, map_w-map_display_w)
	end
	   
	   
	function love.keypressed(key, unicode)
		if key == 'up' then
		   hero_y = hero_y-1
		   if map_y < 0 then map_y = 0; end
		end
		
		if key == 'down' then
		   hero_y = hero_y+1
		   if map_y > map_h-map_display_h then map_y = map_h-map_display_h; end
		end
		
		if key == 'left' then
		   hero_x = math.max(hero_x-1, 0)
		end
		
		if key == 'right' then
		   hero_x = math.min(hero_x+1, map_w-map_display_w)
		end 
	end
end

function love.draw()
    draw_map()
    draw_hero()
	love.graphics.print("FPS: "..love.timer.getFPS(), 10, 20)    
end

Attachments
roguelike.zip
(11.41 KiB) Downloaded 148 times
--------------------------------------------------------
To Do: Insert Signature Here
--------------------------------------------------------
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Roguelike engine - How to?

Post by Robin »

I'm not sure what your question is. Could you put it in another way?
Help us help you: attach a .love.
User avatar
arquivista
No longer with us
Posts: 266
Joined: Tue Jul 06, 2010 8:39 am
Location: Insert Geolocation tag here
Contact:

Re: Roguelike engine - How to?

Post by arquivista »

Robin wrote:I'm not sure what your question is. Could you put it in another way?
Hmm, sorry, i have the character guy and i wanted to draw it in directly in the map in draw_hero() function. However i don't know how to draw the "heroTile" directly in "map" tile but only in general window with

Code: Select all

love.graphics.draw( tileHero, hero_x * tile_w + map_offset_x , hero_y * tile_h + map_offset_y)
Unfortunly for me in this way it draws in window and not in map so map and char unsyncs a lot since i pretend to use mouse to scroll map (scroll it to the borders -+1 px) and keys to move char (-+32px).

Do i have a command way to write Char tile in Map tile and don't worry (since Love dont have a Map engine with multiple layers) or i need to rethink the way to sync the char to map?
--------------------------------------------------------
To Do: Insert Signature Here
--------------------------------------------------------
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Roguelike engine - How to?

Post by kikito »

I'm afraid you will have to use some math.

I suspect it will not be very complicated - likely similar to "if the player is on tile (tx, ty), his position must be (x,y), where x = tx*width and y = ty*height", where width and height are the dimensions of a map tile.

EDIT: I see that this is what you are doing now.

My advise is that you start without scroll. Scroll is somewhat difficult to handle, on the math side.

If you absolutely must handle scroll, the easiest way to do so is by moving everything before drawing - use love.graphics.translate in order to translate both the map and the player before actually drawing them.

This approach is simpler, but has one drawback: that you will have to invert mouse coordinates if you want to point-and-click with the mouse. Unless you do zooms or rotations, this shouldn't be quite complicated, but it is important to know beforehand.
Last edited by kikito on Tue Jul 06, 2010 9:20 pm, edited 1 time in total.
When I write def I mean function.
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Roguelike engine - How to?

Post by bartbes »

How about:

Code: Select all

-- Roguelike Engine Test v0.1

-- Roadmap
-- 0.1 Split tile image file loading + Mouse Scroll Map
-- 0.2 Add Hero + Key Movement
-- 0.3 Parse unique tile image file + text array for data tiles  
-- 0.4 Map loading file
-- 0.5 Map algorithm


function love.load()
	setupMap()
	setupHero()
	initWindow()  
end

function initWindow ()

	window_size_x = tile_w * map_display_w + ( 2 * tile_w )
	window_size_y = tile_h * map_display_h + ( 2 * tile_h )
	windowfeatures = love.graphics.setMode( window_size_x, window_size_y, no, no, no )
	love.graphics.setCaption( "Roguelike Engine Test v0.1" )
	love.mouse.setPosition( window_size_x/2, window_size_x/2 )
	love.graphics.setFont(12)

end 

function setupMap()

	tile = {}
	for i=0,3 do -- Grass = 0, Tree = 1, Lava = 2, Water = 3
	   tile[i] = love.graphics.newImage( "tile"..i..".png" )
	end

	map_w = 20			-- Map Size X
	map_h = 20			-- Map Size Y
	map_x = 0			-- Reset X Map Position
	map_y = 0			-- Reset Y Map Position
	map_offset_x = 0	-- Window/Camera Offset X 
	map_offset_y = 0	-- Window/Camera Offset Y
	map_display_w = 9	-- Window/Camera Size X
	map_display_h = 9	-- Window/Camera Size Y
	tile_w = 32			-- Tile Size X
	tile_h = 32			-- Tile Size Y

map={
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
   { 0, 1, 0, 0, 2, 2, 2, 0, 3, 0, 3, 0, 1, 1, 1, 0, 0, 0, 0, 0},
   { 0, 1, 0, 0, 2, 0, 2, 0, 3, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0},
   { 0, 1, 1, 0, 2, 2, 2, 0, 0, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
   { 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0},
   { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 2, 2, 2, 0, 3, 3, 3, 0, 1, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0},
   { 0, 2, 0, 0, 0, 3, 0, 3, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
   { 0, 2, 0, 0, 0, 3, 0, 3, 0, 1, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
   { 0, 2, 2, 2, 0, 3, 3, 3, 0, 1, 1, 1, 0, 2, 2, 2, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
}
  
end

function setupHero ()

	tileHero = love.graphics.newImage( "rogue.png" )
	hero_x = 5
	hero_y = 5		
end

function draw_map()
   for y=1, map_display_h do
      for x=1, map_display_w do                                                         
         love.graphics.draw( 
            (x == hero_x and y == hero_y) and tileHero or tile[map[y+map_y][x+map_x]], 
            (x*tile_w)+map_offset_x, 
            (y*tile_h)+map_offset_y )
      end
   end
end

--[[function draw_hero()
	love.graphics.draw( tileHero, hero_x * tile_w + map_offset_x , hero_y * tile_h + map_offset_y)
end]]


function love.update()

	mx = love.mouse.getX( )
	my = love.mouse.getY( )
	
	if my < tile_h then
	   map_y = map_y-1
	   if map_y < 0 then map_y = 0; end
	end
	
	bound_y = tile_h + map_display_h * tile_h
	
	if my > bound_y then
	   map_y = map_y+1
	   if map_y > map_h-map_display_h then map_y = map_h-map_display_h; end
	end
	
	if mx < tile_w then
	   map_x = math.max(map_x-1, 0)
	end
	
	bound_x = tile_w + map_display_w * tile_w	
	
	if mx > bound_x then
	   map_x = math.min(map_x+1, map_w-map_display_w)
	end
	   
	   
	function love.keypressed(key, unicode)
		if key == 'up' then
		   hero_y = hero_y-1
		   if map_y < 0 then map_y = 0; end
		end
		
		if key == 'down' then
		   hero_y = hero_y+1
		   if map_y > map_h-map_display_h then map_y = map_h-map_display_h; end
		end
		
		if key == 'left' then
		   hero_x = math.max(hero_x-1, 0)
		end
		
		if key == 'right' then
		   hero_x = math.min(hero_x+1, map_w-map_display_w)
		end 
	end
end

function love.draw()
    draw_map()
    --draw_hero()
	love.graphics.print("FPS: "..love.timer.getFPS(), 10, 20)    
end

It basically use lua's version of a ternary operator to check if the hero is on that tile, if so it draws the hero tile, if not it draws the tile as seen on the map.
User avatar
arquivista
No longer with us
Posts: 266
Joined: Tue Jul 06, 2010 8:39 am
Location: Insert Geolocation tag here
Contact:

Re: Roguelike engine - How to?

Post by arquivista »

bartbes wrote:How about:
[code
It basically use lua's version of a ternary operator to check if the hero is on that tile, if so it draws the hero tile, if not it draws the tile as seen on the map.
Wow, interesting, thanx a lot bartbes! :)
So, there's is after all way of put multiple tiles. But did the char lost his alpha? I really need to study lua graph more then!

it does the job for now with only one char but i'm afraid i will have a big problem later of a very complex draw_map function to check all the objects and monters too. I think that later i will create another layer for objects and chars and as kikito said to do some math instead to sync both layers.

Anyway thx to both, i will learn some more and do some kind of code that avoids future problems.
--------------------------------------------------------
To Do: Insert Signature Here
--------------------------------------------------------
Post Reply

Who is online

Users browsing this forum: No registered users and 53 guests