All sorts of questions on how to better my game.

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_patient567
Prole
Posts: 12
Joined: Sun Jan 27, 2013 6:00 am

All sorts of questions on how to better my game.

Post by dementia_patient567 »

Colored Polygon Battles.love
(40.22 KiB) Downloaded 201 times
The game is called "Colored Polygon Battles" and it's quite obviously a Geometry Wars/Asteroids knock-off lol

The controls are wasd to move, mouse to aim, right click to shoot and the scroll wheel to change colors.

The premise of the game is that there will be many different types of enemies that will have 1/3 colors on them. Same colors as the player. You'll need to shoot the enemies with their color to kill them. Meaning red bullets don't work on a blue guy etc.

I've only been working on this for 2 days or so so there isn't really any real point in it yet.

Before I go any further with it though, I need some help with figuring out how some stuff works.

Some things I can't figure out:

1) The thruster rotates around the very center of the image. I'd like to to rotate around the very back of it, but I can't seem to figure that out...

2)The particles eat up memory if I'm not careful. It's pretty stable on my computer with the current setup, but is there a way to make it a bit more efficient? Or do I just have to sacrifice having a lot of particles?

3)The stars in the background. As you'll see in data.lua, they're dynamically drawn. All 500 of them. I had 1000 but that was eating resources fairly bad so I cut it. I'm asking if there's a simpler way of drawing the same type of stars with a bit more efficiency. If not, I don't think it'll kill a game as small as this is meant to be.

4)Does love.audio not let me play overlapping sounds? In geowars, the shooting sound happens for every bullet at the proper pitch. Is there a way to do this with love without pitching the sound up like I've done? If not it's no huge deal. It also applies to the scroll wheel sound too.

5) I know my functions, tables and variables could be more efficient but I don't know enough about this stuff to do it. Any suggestions are very welcome.

6) The particles should carry out their business and then fade, even if the color was changed. Notice, when you shoot a wall while red, then switch to blue, the explosion that already happened changes to blue. Idk how to get rid of that. I suspect it has something to do with tables or OOP or something...

7) The "walls." When the ship hits one of the designated "walls," it sort of gets "stuck" for a second. It's a bit annoying. I don't know much about OOP(I'm trying to figure out how it works...) but I suspect it'd be better to make some sort of "wall class" where everything to do with the walls of the game are in there. If player hits it, wall does this to player. If bullet hits it, wall does this to bullet. Any deep explanation of this sort of system would be awesome.

8) I have a really shitty box made out of 3 rectangles. There are 3 to increase the line size. You'll notice that if you move while near the right side or the bottom, the lines really mess up and it's a bit of a headache. I think this could be fixed with this "wall class" that I mentioned above. Idk how to implement that correctly.

9)I've left the files fairly commented on different things. If you've got a minute and see something in my code that could help me make this game better and my knowledge of Lua/Love expand, I'd be very appreciative.

I realize that this isn't a game at all yet. But I feel like getting there's no point in continuing with a half-assed game if I don't know concepts that I'll have to/should know. If I've done well on bits and pieces of code, let me know. I've done pretty much 98% of this code without using tutorials(besides HUMP) and I'm trying to get things to work right simply by using my own head lol.

Anyways, if you're reading this far down, awesome! I hope one of you has a minute or ten to help me out with some of these problems.
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: All sorts of questions on how to better my game.

Post by micha »

Hi,

a partial answer:
1) The center of rotation are the origin coordinates you pass over in the love.graphics.draw command. See here: https://love2d.org/wiki/love.graphics.draw. To rotate around the "back" of the image, finde the coordinates of the back (with a graphics programm) and enter them in the ship:draw routine

3) If you draw a lot of similar images on screen, you should use a sprite batch. This means you have to make an image file of the stars first.
Anyway, my experience is, that the rendering commands (line, arc, circle etc) in löve are slower than the image drawing commands.

5) I didn't read you code in detail, so here is just a rough idea: Somewhere you have a table, that contains the coordinates of all the bullets. Here you only need to add, for each bullet, the color information. So each entry in the table should have an x, y and color (and what ever else you need, like velocity and stuff)

8) Did you try love.graphics.setLineWidth ? See here: https://love2d.org/wiki/love.graphics.setLineWidth
User avatar
Kadoba
Party member
Posts: 399
Joined: Mon Jan 10, 2011 8:25 am
Location: Oklahoma

Re: All sorts of questions on how to better my game.

Post by Kadoba »

1) The thruster rotates around the very center of the image. I'd like to to rotate around the very back of it, but I can't seem to figure that out...
You can do this with some basic trig. Since you have the direction of the thrust, all you have to do turn it into a vector and then multiply that by the distance you want to offset the thrusters.

Code: Select all

local direction = particleSystem:getDirection() 
local x = math.cos( direction ) * distance
local y = math.sin( direction ) * distance
particleSystem:setPosition( player.x + x, player.y + y)
2) The particles eat up memory if I'm not careful. It's pretty stable on my computer with the current setup, but is there a way to make it a bit more efficient? Or do I just have to sacrifice having a lot of particles?
You do seem to be using a lot of particles for effects. It's ultimately up to you but I suggest decreasing the particles to a reasonable amount.
3)The stars in the background. As you'll see in data.lua, they're dynamically drawn. All 500 of them. I had 1000 but that was eating resources fairly bad so I cut it. I'm asking if there's a simpler way of drawing the same type of stars with a bit more efficiency. If not, I don't think it'll kill a game as small as this is meant to be.
I don't think that your star creation code is doing what you think it is. For the first 500 seconds of the game you will create one star every update (regardless of the amount of time that has actually passed). So if you're running at a constant 120 fps you'll end up making 60,000 stars over about 8 minutes, which is why you're probably getting the slow down. I'm guessing you only wanted to make 500 stars but tried to make one per second for performance. Making 500 tables is nearly instantaneous so you should just make them all at once.
4)Does love.audio not let me play overlapping sounds? In geowars, the shooting sound happens for every bullet at the proper pitch. Is there a way to do this with love without pitching the sound up like I've done? If not it's no huge deal. It also applies to the scroll wheel sound too.
I believe only one sound can be playing per source. The love.audio module is pretty low level and does not manage things automatically. There are libraries that do this for you such as TEsound.
5) I know my functions, tables and variables could be more efficient but I don't know enough about this stuff to do it. Any suggestions are very welcome.
You really only need to worry about efficiency when it becomes a problem. Make it work first and then worry about efficiency if you get slowdowns. When you do get a slowdown is most likely going to be inside of a loop. Use a profiler instead of guess work to determine where your bottlenecks are. I recommend ProFi. But don't stress too much about optimization. You're still a beginner and no matter what you do you're going to get better and trash your old code. Just use this time to learn and have fun.
6) The particles should carry out their business and then fade, even if the color was changed. Notice, when you shoot a wall while red, then switch to blue, the explosion that already happened changes to blue. Idk how to get rid of that. I suspect it has something to do with tables or OOP or something...
No, I believe that's just the way the particle systems were designed. When you switch the colors it affects all of the particles in the system immediately. One trick to get around it is to have a separate, identical particle system for each color you're going to use.
7) The "walls." When the ship hits one of the designated "walls," it sort of gets "stuck" for a second. It's a bit annoying. I don't know much about OOP(I'm trying to figure out how it works...) but I suspect it'd be better to make some sort of "wall class" where everything to do with the walls of the game are in there. If player hits it, wall does this to player. If bullet hits it, wall does this to bullet. Any deep explanation of this sort of system would be awesome.
I haven't looked at the code but that sounds like you're not setting your velocity to 0 when you hit the wall. The wall is pushing the player out but the velocity is still pushing the player toward the wall so it gets "stuck". Flexible collision systems can be pretty complicated. I suggest using HardonCollider.
8) I have a really shitty box made out of 3 rectangles. There are 3 to increase the line size. You'll notice that if you move while near the right side or the bottom, the lines really mess up and it's a bit of a headache. I think this could be fixed with this "wall class" that I mentioned above. Idk how to implement that correctly.
See love.graphics.setLineWidth
9)I've left the files fairly commented on different things. If you've got a minute and see something in my code that could help me make this game better and my knowledge of Lua/Love expand, I'd be very appreciative.
You're a beginner but you ask really great questions. You have the right mindset, just not the experience.

Use globals sparingly. Ideally, only have one global table that you store all of your global values into. The problem is that globals are hard to track down and keep up with. Restricting everything to local makes sure that everything happens in one place and is easy to find. You may wonder how you can get access to data in other files if you can't declare things globally and the answer is that files are actually ran as functions and can return values. So the common thing to do is simply define everything in a local table and then return that. This is a lot less confusing than it sounds and cleans up your code a lot.

A good example of this is your background stars. Instead of declaring them globally and putting them in a very generic file named "data.lua" put them in in a local table their own lua file called "stars.lua" and return that table.

Example:

Code: Select all

-- Inside stars.lua

-- Put all functions in this table
local stars = {}

-- Define the functions
function stars.create() ...end
function stars.spawn() ... end
function stars.draw() ... end

-- Return the functions in one table
return stars

------------------------------------------------------------------------------------------------
-- Inside main.lua:

-- Get the stars table returned in stars.lua
local stars = require("stars")

-- Loads the stars
function love.load()
     stars.create()
end

-- Draw the stars
function love.draw()
    stars.draw()
end
You seem a little confused about OOP. What you keep referencing is "instancing" which is one aspect of OOP. Instancing is where you have a table with shared functions but independent data. For example, you can have the same type of enemy in two different locations with two different levels of health because they have their own location and health variables. However they have the same functions so they behave exactly the same.

You can accomplish this easily in lua using the __index metamethod. Metamethods are special functions that can be used to define a metatable. A metatable can be used to change the behavior of another table. They're very powerful but can be a little confusing at first. This is how you set a metatable:

Code: Select all

 
local meta = {} 
local t = {}
setmetatable(t, meta)

After that code, "meta" is now the metatable of "t" but it doesn't do anything yet because we haven't defined any metamethods. So let's define __index. When the table can't find a stored value in a normal table it will attempt to look in it's metatable's __index for it.

Code: Select all

print( t.text)   -- Prints nil
meta.__index = { text = "hello" }
print( t.text )   -- Prints "hello"
On the third line of the above code snippet, t.text isn't found so it looks inside of the meta.__index table. There, a value of "hello" is found it's returned as if it had been contained inside of t. You can also set the metatable's __index to itself.

Code: Select all

print( t.text ) -- Prints "hello"
meta.__index = meta
meta.text = "there"
print( t.text ) -- Prints "there"
If you're confused at this point, that's ok. You'll figure it out eventually. Now let's make a full-fledged class using what we just learned:

Code: Select all

-- Create a metatable and set the __index to itself.
local Person = {}
Person.__index = Person

-- A function to create a new person with independent x and y values and "Person" as the metatable.
function newperson(x, y)
   local instance = setmetatable({}, Person) --Creates a new table, sets it's metatable to person then returns it
   instance.x = x
   instance.y = y
   return instance
end

-- This function is shared between "Persons"
function Person:move(x,y)
   self.x = self.x + x
   self.y = self.y + y
end

-- Note how there is a colon (:) instead of a period (.) in-between the table and the function in the above code.
-- This causes the value "self" to become whatever the first parameter is. It is equivalent to the following function:

function Person.move(self, x, y)
   self.x = self.x + x
   self.y = self.y + y
end

-- Similarly, if you call a function using a colon instead of a period the table will become the first parameter.
-- These two function calls are exactly the same:

Person.move( Person, x, y )
Person:move( x, y )

-- Now, create two new people, both at location 0,0

local p1 = newperson(0,0)
local p2 = newperson(0,0)

-- Move them. They both have "Person" as their metatable so they use Person.move() but their x and y values are different.

p1:move(5,5)
p1:move(10,10)

-- Now they are at two different locations
print(p1.x, p1.y)  -- Prints "5      5"
print(p2.x, p2.y)  -- Prints "10    10"
I know that was a huge TLDR, but I hope it cleared some things up. None of this code is tested so sorry if it doesn't work correctly.
User avatar
interstellarDAVE
Prole
Posts: 23
Joined: Mon Jan 14, 2013 8:22 pm

Re: All sorts of questions on how to better my game.

Post by interstellarDAVE »

I sort of came up with a similar idea and tried to make it, got distracted and never finished. It was a little disorganized, but I'll come back to it.

About the starfield, I made something that generates 500 stars randomly and its pretty instantaneous. I changed the size and the alpha to give it a sense of depth. I was pretty happy about the performance and appearance.

Here is the initialization code.

Code: Select all

function initalizestarfield(density)
	for i = 1,density,1 do
		starfield[i] = { }
		starfield[i].x = math.random(1, windowsize.x)
		starfield[i].y = math.random(1, windowsize.y)
		starfield[i].alpha = math.random(1,100) -- capped at 200 so it doesn't confuse the forground and background
		starfield[i].size = math.random(1,5)
	end
	--createstarfield()
end
and the draw code

Code: Select all

function drawstarfield()
	-- gets the current brush and saves it to a temp location so it can restore it after drawing the starfield
	oldbrush = { love.graphics.getColor() }
	oldpointstyle = love.graphics.getPointStyle()
	oldpointsize = love.graphics.getPointSize()

	--print(table.getn(starfield))
	for i = 1,table.getn(starfield),1 do
		-- goes through the starfield and draws the stars
		love.graphics.setPoint(starfield[i].size,'smooth')
		love.graphics.setColor(255,255,255,starfield[i].alpha)
		love.graphics.point(starfield[i].x, starfield[i].y)
		--print(starfield[i].size .. ' ' .. starfield[i].alpha .. '(' .. starfield[i].x .. ',' .. starfield[i].y)
	end

	-- restores the old brush
	love.graphics.setColor(oldbrush)
	love.graphics.setPointStyle(oldpointstyle)
	love.graphics.setPointSize(oldpointsize)	
end
I tried to make it draw to an imagebuffer and save that so it wouldn't have to keep drawing them each frame, but I couldn't get the starts to display right. For some reason it was blending them over the black background .. gave up for now so I just let it draw each :draw() call because there wasn't a performance hit.

6. Particle fire.

Haven't messed with the particle system, but what I did with my game was to make it a class (bullet) so each instance had its own properties, so they could be different colors. I made mine physics objects so they would move momentum to whatever they shot. This way there would be feedback from impacts.

My old code was messed up since I didn't really know how to handle the tables without indexing them, but I would now do the destruction like this.

Code: Select all

bullets = { }
bullets.counter = 0

function bullets:create()
   bullets.counter = bullets.counter + 1 -- so that you have a unique ID for this bullet.
   bullets[bullets.counter] = bullet -- // but all your properties here.
end

function bullets:draw()
    for i,v pairs(bullets) do
     -- // whatever code you need to draw the bullets. i is the index and v is the actual data. for bullet[1] i = 1 bullet["ham"], i = "ham" 
    end
end

function bullets:destroy(bulletid)
    bullets[bulletid] = nil
end
Here is my github project for my space shooter if you want to compare and maybe see different way things are done. Though mine is more asteroids based then geometry wars. Asteruga Git
Post Reply

Who is online

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