Page 1 of 1

How to use same image more than once

Posted: Sat Jul 06, 2019 10:37 pm
by MarsOdin
I have the following problem:

I created a table for blueprints of objects I want to use in my game (sapceships, etc). Every blueprint has an image. Once I need a new object I create it by loading the data of one of the blueprints into the table for objects.
When I assign the same blueprint (thus the same image) to more than one object only 1 of those objects is rendered. If I assign a different blueprint to it it renders normally.
Where it says "test" is where I created object[2] and object[3]. object[2].img = blueprint[2].img and object[3].img = blueprint[2].img is where I call the same image: img = love.graphics.newImage("images/Human-Spacestation.png").

how can I use the same image more than once without having this problem?

Here is my code:

Code: Select all

    -- Blueprints
        blueprint = {
            [1] = {name = "Spaceship",
                img = love.graphics.newImage("images/Human-Battlecruiser.png"),
            },
            [2] = {name = "Spacestation",
                img = love.graphics.newImage("images/Human-Spacestation.png"),
            },
        }
    -- Objects
        object = {
            nextID = 1,
            selection = {n = 1, 
                crosshairImg = love.graphics.newImage("images/crosshair026.png"),
                print = true,
            },
        }
        object[1] = blueprint[1]
        object[1].img = blueprint[1].img
        object[1].id = object.nextID
        object[1].activePlayerChar = true
        object[1].isOnMap = true
        object[1].posX = map.centerPosX
        object[1].posY = map.centerPosY
        
        object.nextID = object.nextID + 1

        --test 
            object[2] = blueprint[2]
            object[2].img = blueprint[2].img
            object[2].id = object.nextID
            object[2].activePlayerChar = false
            object[2].isOnMap = true
            object[2].posX = map.gridStartPosX + 2*map.boxWidthAndHeight - map.centerBoxPosX
            object[2].posY = map.gridStartPosY + 2*map.boxWidthAndHeight - map.centerBoxPosY

            object.nextID = object.nextID + 1


            object[3] = blueprint[2]
            object[3].img = blueprint[2].img
            object[3].id = object.nextID
            object[3].activePlayerChar = false
            object[3].isOnMap = true
            object[3].posX = map.gridStartPosX + 1*map.boxWidthAndHeight - map.centerBoxPosX
            object[3].posY = map.gridStartPosY + 1*map.boxWidthAndHeight - map.centerBoxPosY

            object.nextID = object.nextID + 1
            --end of test
            
   	function printObjectOnMap(isOnMap, img, posX, posY)
            if isOnMap == true then   
                imgWidth = img:getWidth()
                love.graphics.draw(img, posX, posY, 0, 1, 1, imgWidth/2, imgWidth/2)
            end
        end
        
        for i = 1, #object do
            printObjectOnMap(object[i].isOnMap, object[i].img, object[i].posX, object[i].posY)
        end  

Re: How to use same image more than once

Posted: Sun Jul 07, 2019 1:07 am
by raidho36

Code: Select all

object[1] = blueprint[1]
Your object and your blueprint are now the same data entity, and you're editing your blueprint by proxy. You should copy data over from blueprints to your new objects.

Re: How to use same image more than once

Posted: Sun Jul 07, 2019 4:39 am
by MarsOdin
raidho36 wrote: Sun Jul 07, 2019 1:07 am Your object and your blueprint are now the same data entity, and you're editing your blueprint by proxy. You should copy data over from blueprints to your new objects.
Thank you for your answer. I learned something new.
I have been searching on how to copy tables but I can't find anything that works. Even the methods explained in http://lua-users.org/wiki/CopyTable I can't implement in löve.
Could you tell me a simple way on how to copy a table or table values? Thank you!

Re: How to use same image more than once

Posted: Sun Jul 07, 2019 5:51 am
by sphyrth
For now, change

Code: Select all

object[1] = blueprint[1]
to

Code: Select all

object[1].name = blueprint[1].name

Re: How to use same image more than once

Posted: Sun Jul 07, 2019 7:53 am
by raidho36
MarsOdin wrote: Sun Jul 07, 2019 4:39 am Could you tell me a simple way on how to copy a table or table values? Thank you!
Just go over every entry and copy them manually. Same thing as you do now, but properly.

There are many ways to copy data automatically, but your specific situation warrants using manual approach instead. Only do things automatically if that's how it must be done, make sure not to fall into the trap of doing so just because you're lazy - that'll result in a lot of hard to pin down problems, and you'll have to rewrite it to manual style anyway (or do even more metaprogramming just to shoehorn an automatic mechanism where it doesn't belong).

Re: How to use same image more than once

Posted: Sun Jul 07, 2019 10:02 am
by pgimeno
It's also possible that there's something else outside the part of the code shown, that is causing more problems. People can only advise based on what has been shown, not on what has not, and not having something runnable makes it harder to help.

Re: How to use same image more than once

Posted: Sun Jul 07, 2019 10:43 pm
by MarsOdin
sphyrth wrote: Sun Jul 07, 2019 5:51 am For now, change

Code: Select all

object[1] = blueprint[1]
to

Code: Select all

object[1].name = blueprint[1].name
Thanks! That solved my problem!
And thanks to the other replies for their input!

Re: How to use same image more than once

Posted: Mon Jul 08, 2019 3:55 pm
by SPlice
I recommend setting up an image library that will allow you to reference images with some kind of ID for example the image name.

You could do something along the lines of

Code: Select all

	function getImage(fileName)
		if not imageTable[fileName] then
			imageTable[fileName] = love.graphics.newImage(fileName)
		end
		return imageTable[name]
	end

in your draw function you could than do

Code: Select all

	love.graphics.draw(getImage(object[1].fileName),getImage(object[1].x,getImage(object[1].y)
This will insure that each image only gets loaded once and allow you to avoid having to load an image for each object instance.
I recommend implementing something like this because its going to eliminate any duplicate images in your objects if you use the same image twice and it also simplifies creating objects because you don't have to have any complicated data types(like image data) in your objects, making serialization for for networking and saving much easier.
It does add some overhead to drawing images, and you could make it a little faster by using numeric indexes but its not going to buy you enough to make a difference. You will run into frame rate issues from drawing too much stuff before the lookup slows things down enough to matter.