Help making a little "menu?"

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.
Post Reply
dementia_patient
Prole
Posts: 7
Joined: Sun Jan 06, 2013 2:50 am

Help making a little "menu?"

Post by dementia_patient »

Basically I'm trying to make a "menu" that will spawn a button when I hold down a button("q" for right now.) I could swear the code should work, but for some reason it isn't. I've attached a .zip file with all the current files I have for it. So far all it has is Link running around in 4 directions, without being able to leave the screen. There's a file called "runescreen.lua" that has code in that SHOULD allow me to spawn an image at the coordinates I specify. I'm really sorry if my code is unclear. I don't think it should be an issue for you, but if it is, I'll gladly tell you whatever you need to know. I'm obviously not going to be using any of these sprites or positions etc, but I'm really new to Love and just testing what I can do.

Any help is more than welcome. Thanks a ton in advance, guys.
Attachments
test.rar
(816.01 KiB) Downloaded 99 times
scutheotaku
Party member
Posts: 235
Joined: Sat Dec 15, 2012 6:54 am

Re: Help making a little "menu?"

Post by scutheotaku »

Hi there,

Your main problem is that you were going about this the wrong way. I'll show you what I mean by explaining my corrections.

Here is my version of your "runescreen.lua" file:

Code: Select all

runes = {}

runeImages = {}
runeImages["shadow"] = love.graphics.newImage("images/runes/shadow.png")

function runeCreate(x, y, id)
	runes[#runes + 1] = {x=x, y=y, id=id}
end

function runeDraw()
	for i,v in ipairs(runes) do
		love.graphics.draw(runeImages[v.id], v.x, v.y)
	end
end


function activaterune(key)
	if key == "q" then
		gamestate = "rune"
	end
end

function deactivaterune(key)
	if key == "q" then
		gamestate = "play"
	end
end
I also made a minor adjustment to your "love.load" callback in "main.lua":

Code: Select all

function love.load()
	gamestate = "play"
	
	--loading up teh runes
	runeCreate(100, 100, "shadow")
end
The problem with your original code was two-fold. First, you were using "love.graphics.newImage" once every frame for each rune in your "runes" table, creating an endless amount of Image objects. Second of all, you were never actually drawing the images.

You see, "love.graphics.newImage" does not draw an image, instead it defines an Image object. It is not meant to be called over and over again. The function is usually used like this:

Code: Select all

image = love.graphics.newImage( filename )
--image is the variable which will contain the Image object, this is so that you can reference the Image object later
--filename most be a string and should be the filepath to the image file
[there are a few other ways that you can use the function (see: https://love2d.org/wiki/love.graphics.newImage ), but they're not important right now.]

No matter how many times you draw an Image object, you only have to define it ONCE. So, you may have 20 "shadow runes" being drawn, but you only have to define the shadow rune image object once.

Now we need to draw the image object. We can do this a few different ways, but for now we will use "love.graphics.draw()". This function draws "drawable objects" onto the screen. A "drawable object" is usually an image object, but it can also be other things (see here if you're curious: https://love2d.org/wiki/Drawable ).

Here is the function and its various arguments:

Code: Select all

love.graphics.draw( drawable object, x position, y position, rotation/orientation in radians, x-axis scale factor, y-axis scale factor, x-axis origin offset, y-axis origin offset, x-axis shearing factor, y-axis shearing factor )
So, let's say we define the shadow rune image like so:

Code: Select all

shadowRuneImage = love.graphics.newImage("images/runes/shadow.png")
That creates a new image object using the shadow rune image file, and then it "stores" this image object in the shadowRuneImage variable.

Now, to draw the shadowRuneImage at (100,100), we might use this code:

Code: Select all

function love.draw()

	love.graphics.draw(shadowRuneImage, 100, 100)
end
Get it?

With all of that in mind, my correct code above should make a lot of sense. Let me explain a couple of things about it though...

First of all, I setup a table called "runeImages" to store all of your rune image objects. Each entry into this table should have a key referring to its type. For example:

Code: Select all

runeImages["shadow"] = love.graphics.newImage("images/runes/shadow.png")
If you wanted to add a fire rune image object to the table, you might write:

Code: Select all

runeImages["fire"] = love.graphics.newImage("images/runes/firerune.png")
This allows you to refer to these image objects later by referencing that entry in the table. So if you want to draw the shadow rune image at (100,100), you might write:

Code: Select all

function love.draw()

	love.graphics.draw(runeImages["shadow"], 100, 100)
end
These leads to my version of your runeDraw() function:

Code: Select all

function runeDraw()
	for i,v in ipairs(runes) do
		love.graphics.draw(runeImages[v.id], v.x, v.y)
	end
end
This now references the runeImages table to draw the appropriate rune image. This should be pretty self-explanatory, but you may notice another change I made - I got rid of the "img" key/column from your runes table, as well as removed any references to it in your functions. Why? Because, with the runeImages table in place, "id" now serves both its original purpose and the purpose of "img."

For example, take a look at my adjustment to your love.load callback (in main.lua) again:

Code: Select all

function love.load()
	gamestate = "play"
	
	--loading up teh runes
	runeCreate(100, 100, "shadow")
end
Instead of writing:

Code: Select all

runeCreate(100, 100, ""images/runes/shadow.png", "shadow")
You just write:

Code: Select all

runeCreate(100, 100, "shadow")
Because the image object is already created and stored in the runeImages table, and the id that you write when calling your runeCreate function (in this case, "shadow") references that entry in the runeImages table (since the string you put as the id is the same).

So, if you had added a fire rune image object to the runeImages table like so:

Code: Select all

runeImages["fire"] = love.graphics.newImage("images/runes/firerune.png")
You could create a new fire rune like this:

Code: Select all

runeCreate(100, 100, "fire")
Ok, and with that it should be working now.

Oh, I did make one other change in runescreen.lua: in the runeCreate() function, I changed...

Code: Select all

table.insert(runes, {x=x, y=y, id=id})
to:

Code: Select all

runes[#runes + 1] = {x=x, y=y, id=id}
This does almost the same thing (for your uses, it should have the exact same results), and is faster.

Ok, well hopefully that all made sense! Just in case you aren't able to get my changes above to work, I've attached my modified version of your project to this post.

Cheers!

-Ben

PS: If you want to add the "img" property back to the runes table (e.g. if there are cases where the id and the corresponding runeImages key are not the same), then feel free!
Attachments
test.zip
(819.09 KiB) Downloaded 108 times
dementia_patient
Prole
Posts: 7
Joined: Sun Jan 06, 2013 2:50 am

Re: Help making a little "menu?"

Post by dementia_patient »

Holy crap, man. You are awesome. Thank you so much. I definitely understand everything you changed and why it had to be changed. You're a freaking life savor.
scutheotaku
Party member
Posts: 235
Joined: Sat Dec 15, 2012 6:54 am

Re: Help making a little "menu?"

Post by scutheotaku »

dementia_patient wrote:Holy crap, man. You are awesome. Thank you so much. I definitely understand everything you changed and why it had to be changed. You're a freaking life savor.
Great! I'm glad I could help :)
dementia_patient
Prole
Posts: 7
Joined: Sun Jan 06, 2013 2:50 am

Re: Help making a little "menu?"

Post by dementia_patient »

scutheotaku wrote:
dementia_patient wrote:Holy crap, man. You are awesome. Thank you so much. I definitely understand everything you changed and why it had to be changed. You're a freaking life savor.
Great! I'm glad I could help :)
Any ideas on how I might be able to fix that blur that happens when he runs? Is it just because the sprite is small and 16 bit? Or is there something I'm missing that I could fix?
scutheotaku
Party member
Posts: 235
Joined: Sat Dec 15, 2012 6:54 am

Re: Help making a little "menu?"

Post by scutheotaku »

dementia_patient wrote:
scutheotaku wrote:
dementia_patient wrote:Holy crap, man. You are awesome. Thank you so much. I definitely understand everything you changed and why it had to be changed. You're a freaking life savor.
Great! I'm glad I could help :)
Any ideas on how I might be able to fix that blur that happens when he runs? Is it just because the sprite is small and 16 bit? Or is there something I'm missing that I could fix?
Hmm, strange, LOVE does seem to be sometimes blurring your image whether your player is moving or not. You see this by quickly tapping the same direction button several times in a row (e.g. tap "d" "d" "d" "d"). I may be missing something in your code, but I'm not sure why it's doing this. I suspect that this may have to do with changing images so often, but that's sort of strange...maybe a more experienced LOVE user (I almost said "LOVEr"...haha) could help here? I've yet to do much experimentation with animation myself :)

That being said, you may want to look into a few different ways of doing your animation. These may or may not fix your blurring issues...

I'll show you one way to do this based on your current setup, as well as two animation libraries. All three of these methods involve having your Link sprites in a spritesheet - just an image that holds all the different animation frames. Generally, each of the frames will be aligned to an invisible (or visible) grid. For more info on spritesheets, see: http://www.codeandweb.com/what-is-a-sprite-sheet & http://spritedatabase.net/tutorial_sheet.php . Also, while I haven't personally used it, here is a fairly popular program for generating spritesheets from sprites you've already drawn: http://www.codeandweb.com/sprite-sheet-maker

Your "Zelda3Sheet1.gif" file is a spritesheet, though I'm not sure if it's setup on a fixed-width/height grid.

So the first way to do this animation would be very similar to what you're doing now, except that you'll be using quads.

A quad is a "quadrilateral (a polygon with four sides and four corners) with texture coordinate information."

You create a quad similar to how you create an Image object:

Code: Select all

quad = love.graphics.newQuad( x, y, width, height, sw, sh )

--number x
--The top-left position along the x-axis.

--number y
--The top-left position along the y-axis.

--number width
--The width of the Quad. (Must be greater than 0.)

--number height
--The height of the Quad. (Must be greater than 0.)

--number sw
--The reference width, the width of the Image. (Must be greater than 0.)

--number sh
--The reference height, the height of the Image. (Must be greater than 0.)

--if your spritesheet is 128x256, then sw should be 128 and sh should be 256
(See: https://love2d.org/wiki/love.graphics.newQuad )

To draw a quad, you use love.graphics.drawq():

Code: Select all

https://love2d.org/wiki/love.graphics.drawq
(See: https://love2d.org/wiki/love.graphics.drawq )

The thing about quads is that you can use them to draw only a portion of an image, like so:

Code: Select all

img = love.graphics.newImage("mushroom-64x64.png")

-- Let's say we want to display only the top-left 
-- 32x32 quadrant of the Image:
top_left = love.graphics.newQuad(0, 0, 32, 32, 64, 64)

-- And here is bottom left:
bottom_left = love.graphics.newQuad(0, 32, 32, 32, 64, 64)

function love.draw()
    love.graphics.drawq(img, top_left, 50, 50)
    love.graphics.drawq(img, bottom_left, 50, 200)
end
(Taken from: https://love2d.org/wiki/love.graphics.drawq )

So, you may do your animation something like this... (just an example):

Code: Select all

playerSpriteSheet = love.graphics.newImage("images/link.png")

playerRight = {}
playerRight[1] = love.graphics.newQuad(0, 0, 32, 32, 128, 128)
playerRight[2] = love.graphics.newQuad(32, 0, 32, 32, 128, 128)
playerRight[3] = love.graphics.newQuad(64, 0, 32, 32, 128, 128)
playerRight[4] = love.graphics.newQuad(96, 0, 32, 32, 128, 128)
playerRight[5] = love.graphics.newQuad(0, 32, 32, 32, 128, 128)
playerRight[6] = love.graphics.newQuad(32, 32, 32, 32, 128, 128)
playerRight[7] = love.graphics.newQuad(64, 32, 32, 32, 128, 128)

player.quad = playerRight[1]
Then...

Code: Select all

function playerMove(dt)
	if love.keyboard.isDown("d") then
		player.x = player.x + player.speed * dt
		player.quad = playerRight[player.pnum]
		player.animtimer = player.animtimer + dt
		if player.animtimer > 0.08 then
			player.pnum = player.pnum + 1
			player.animtimer = 0
		end
		if player.pnum > 7 then
			player.pnum = 1
		end
	end
end
And in your player.draw() function:

Code: Select all

function player.draw()
	love.graphics.setColor(255, 255, 255)
	love.graphics.drawq(playerSpriteSheet, player.quad, player.x, player.y)
end
Get it?

Though that's just one way to do animations.

Instead of that, you could try a LOVE animation library. Here are two popular ones:
https://love2d.org/wiki/anim8
https://love2d.org/wiki/AnAL

There's probably other methods too - like I said, I'm new to animating in LOVE also!

As for if anything above will fix your blurring...maybe? Sorry I don't have a concrete answer :(
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 9 guests