How can i divide up a map?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
legendman3
Citizen
Posts: 68
Joined: Sun Jan 22, 2012 8:29 pm

How can i divide up a map?

Post by legendman3 »

Say i want to take this map: http://upload.wikimedia.org/wikipedia/c ... States.PNG and divide it up so that each state is its own *clickable* object. How would i go about doing that? (code would be nice to look at...)
Last edited by legendman3 on Wed Feb 08, 2012 1:55 am, edited 1 time in total.
User avatar
MarekkPie
Inner party member
Posts: 587
Joined: Wed Dec 28, 2011 4:48 pm
Contact:

Re: How can i divide up a map?

Post by MarekkPie »

A (relatively) simple way would be to color the map, using a specific color for a specific state, and then when you click on the map, get the pixel data and compare it to a color.

I'm eating right now, so you'll get no code, but I'll come back and add some later.
User avatar
legendman3
Citizen
Posts: 68
Joined: Sun Jan 22, 2012 8:29 pm

Re: How can i divide up a map?

Post by legendman3 »

MarekkPie wrote:A (relatively) simple way would be to color the map, using a specific color for a specific state, and then when you click on the map, get the pixel data and compare it to a color.

I'm eating right now, so you'll get no code, but I'll come back and add some later.
I will try to code that while you eat. :P

Using this map because its png so it has no artifacts. http://upload.wikimedia.org/wikipedia/c ... States.PNG
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: How can i divide up a map?

Post by Jasoco »

To expand on what MerekkPie said:

You could make a second version of the image where every state is colored a unique solid color. Simple easy colors that you know the RGB values for.

Then when you click on the visible map (Which would be the normal map, not the colored one) you would check the color of the pixel at the coordinates, but on the colored map's imageData instead by taking the X and Y and I believe use r, g, b, a = ImageData:getPixel( x, y )? I never used it myself. So I'm not sure how to put the color map inside imageData.

Then you check the R, G, B against your state table to figure out what color was clicked and what state the color associates with.
User avatar
legendman3
Citizen
Posts: 68
Joined: Sun Jan 22, 2012 8:29 pm

Re: How can i divide up a map?

Post by legendman3 »

Jasoco wrote:To expand on what MerekkPie said:

You could make a second version of the image where every state is colored a unique solid color. Simple easy colors that you know the RGB values for.

Then when you click on the visible map (Which would be the normal map, not the colored one) you would check the color of the pixel at the coordinates, but on the colored map's imageData instead by taking the X and Y and I believe use r, g, b, a = ImageData:getPixel( x, y )? I never used it myself. So I'm not sure how to put the color map inside imageData.

Then you check the R, G, B against your state table to figure out what color was clicked and what state the color associates with.
This is my code:

Code: Select all

function love.load()
	map = love.graphics.newImage("map.png")
	love.graphics.setMode(800, 519)
end

function love.draw()
	love.graphics.draw(map, 0, 0)
end

function love.mousepressed()
	x, y = love.mouse.getPosition()
	r, g, b, a = love.graphics.getColor(x,y)
	if a == 136 and g == 0 and b == 21 then
		love.graphics.print("Why hello there.",0,0)
	end
end
I used love.graphics.getColor(x,y) but i will try the ImageData:getPixel( x, y ).

EDIT: and nothing changed. It still didn't print the words.
User avatar
MarekkPie
Inner party member
Posts: 587
Joined: Wed Dec 28, 2011 4:48 pm
Contact:

Re: How can i divide up a map?

Post by MarekkPie »

EDIT: ninja'ed.

https://love2d.org/wiki/love.image.newImageData

Though I was just going to say used the colored map as your viewed map, but Jasoco's method works if you want to keep the monocolored map. You might need to do some world-relative to map-relative conversions, since you aren't actually drawing the colored map, but it would be as simple as:

Code: Select all

function love.load()
    colormap = love.graphics.newImageData("PATH/TO/COLOREDMAP")
    colors = {...} -- the colors you used to color the colormap
    regmap = love.graphics.newImage("PATH/TO/REGULARMAP")
    offX = 100 -- the x-coord of your regmap
    offY = 100 -- the y-coord of your regmap
end

function love.draw()
    love.graphics.draw(regmap, offX, offY)
end

function love.mousepressed(x,y,b)
    local r,g,b,a = colormap:getPixel(x - offX, y - offY)
    for _,v in pairs(colors) do
        if r == v.r and g == v.g and b == v.b and a == v.a then
            -- selection code
        end
    end
end
You may even be able to loop through your imageData and not even need to keep track of your colors (though you might run into a bleed-over affect at the edges (I'm not too familiar with how image compression and whatnot works)):

Code: Select all

local function findColors(id)
    local colors = {}
    local w = id:getWidth() - 1
    local h = id:getHeight() - 1
    for x = 0, w do
        for y = 0, h do
            local r,g,b,a = id:getPixel()
            if #colors > 0 then
                local same = false
                for _,v in pairs(colors) do
                    if r == v.r and g == v.g and b == v.b and a == v.a then
                        found = true
                        break
                    end
                end
                if not same then
                    colors[#colors + 1] = {r = r, g = g, b = b, a = a}
                end
            else
                colors[1] = {r = r, g = g, b = b, a = a}
            end
        end
    end
end
Keep in mind, the above will be VERY, VERY, VERY SLOW. Like, worst case (O(n^4)), if you have every single pixel a different color, and the size of your image is 16x16, then it will take 16^4 = 65536 iterations. Even the best case (Theta(n^2)), where the whole image is one color, will take 16^2 = 256 iterations. Only use that if you are extraordinarily lazy.
User avatar
legendman3
Citizen
Posts: 68
Joined: Sun Jan 22, 2012 8:29 pm

Re: How can i divide up a map?

Post by legendman3 »

MarekkPie wrote:https://love2d.org/wiki/love.image.newImageData

Though I was just going to say used the colored map as your viewed map, but Jasoco's method works if you want to keep the monocolored map. You might need to do some world-relative to map-relative conversions, since you aren't actually drawing the colored map, but it would be as simple as:

Code: Select all

function love.load()
    colormap = love.graphics.newImageData("PATH/TO/COLOREDMAP")
    colors = {...} -- the colors you used to color the colormap
    regmap = love.graphics.newImage("PATH/TO/REGULARMAP")
    offX = 100 -- the x-coord of your regmap
    offY = 100 -- the y-coord of your regmap
end
I got some questions:
1. What do you mean by a coloredmap and a non-coloredmap?
2. I add all the different colors one by one into the colors{} array? Like colors[1] = {128,128,128}?

The rest makes sense.
MarekkPie wrote:-snip- Only use that if you are extraordinarily lazy.
Yeah that has too many disadvantages... and im not that lazy...
User avatar
legendman3
Citizen
Posts: 68
Joined: Sun Jan 22, 2012 8:29 pm

Re: How can i divide up a map?

Post by legendman3 »

By the way what am i doing wrong?
HjREi.png
HjREi.png (6.33 KiB) Viewed 324 times

Code: Select all

colormap = love.graphics.newImageData("images/coloredmap.png")
User avatar
MarekkPie
Inner party member
Posts: 587
Joined: Wed Dec 28, 2011 4:48 pm
Contact:

Re: How can i divide up a map?

Post by MarekkPie »

First question: I was going off Jasoco's explanation. If you do not want to give away what you are doing - on the fact that it might look really ugly - you could load a second map (into imageData) and find the appropriate pixel on that map relative to your cursor position. The map that is visible is the mono-chromatic map, but you compare the pixel data of the hidden colored map.

Second question: Yeah, though I would go make a separate file called "mapcolors.lua" (or something), and write it as:

Code: Select all

return {
    black = {r =   0, g =   0, b =   0, a =   0},
    white = {r = 255, g = 255, b = 255, a = 255},
    ...
}

Code: Select all

-- in main.lua
colors = require "PATH/TO/colors.lua"
You would have to loop through that table using pairs(), instead of ipairs() or a normal for loop, but pairs() is faster than either of those, so whatever.

Third question: It's love.image.newImageData().
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: How can i divide up a map?

Post by vrld »

legendman3 wrote:

Code: Select all

colormap = love.graphics.newImageData("images/coloredmap.png")
love.image.newImageData
legendman3 wrote:

Code: Select all

function love.mousepressed()
   x, y = love.mouse.getPosition()
   r, g, b, a = love.graphics.getColor(x,y)
   if a == 136 and g == 0 and b == 21 then
      love.graphics.print("Why hello there.",0,0)
   end
end
EDIT: and nothing changed. It still didn't print the words.
You're calling love.graphics.print() only in the frame where the user pressed the mouse. That cannot work. Even worse, you're calling it outside of love.draw(), which makes two reasons why it does not print anything. A third reason why this doesn't work is that you use an Image instead of ImageData. Do this instead:

Code: Select all

local mouse = {x=0,y=0}
local map
function love.load()
    map = love.image.newImageData("map.png")
end

function love.mousepressed(x,y)
    mouse.x = x
    mouse.y = y
end

function love.draw()
    r, g, b = map:getPixel(mouse.x, mouse.y)
    if a == 136 and g == 0 and b == 21 then
        love.graphics.print("Why hello there.",0,0)
    end
end
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
Post Reply

Who is online

Users browsing this forum: No registered users and 23 guests