[SOLVED] with making an OLD project work again

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
User avatar
nice
Party member
Posts: 191
Joined: Sun Sep 15, 2013 12:17 am
Location: Sweden

[SOLVED] with making an OLD project work again

Post by nice »

Hello everyone, I hope everyone is doing OK!
So I want to add at start that I haven't used Löve2D/Lua in some time. I haven't kept up with the new changes to Löve2D, so I'm a bit rusty & I'm not fully aware if there are any changes to the forums rules.

So to the question:

I have an OLD project which is my first game that I've made, I first posted about it to this forum in 2013 & I managed to find the old code again (see below).


I wanted to make it playable again to both reminisce but also maybe use it in my portfolio (undecided). So far, I've managed to get it to work, kinda. What I've managed so far is to make the game "draw" as it should & changed the old way of inputting RGB color values from 255's to 1's. I also had some audio files that I added "static" as the 2nd argument (as it's required in the newer version of Löve2D) but this game is missing a key mechanic.

This game is based on the arcade classic "Asteroids" & in this game, instead of shooting lasers, you created a "ship" trail behind you by pressing the space-bar. This is where my problem is, because I've been away from Lua/Löve2D for some time, I don't really now where the issue is & I was hoping to get a fresh pair of eyes on my old project who can point out any issues that this project has.


If there's anything I need to do to make it easier for you to help me, let me know ASAP & i'll see what I can do.
Take care!

P.S. Keywords to look for in this project is: trailPos, isSpacebarPressed, maxTrailSize.

The code which is over 500 lines long

Code: Select all

local isSpacebarPressed
local frameNum
local colorList
local numLives
local maxTrailSize
local isPpressed
local isMpressed
local isRpressed
local SHOW_COLLISION_BOX
local ship
local shiplives
local smallAsteroid
local mediumAsteroid
local largeAsteroid
local menuImage
local gameoverImage
local numAsteroids
local asteroids
local isUpHeld
local isLeftHeld
local isRightHeld
local score
local sfx
local sfx2
local sfx3
local expSound
local trailPos
local state
local maxVelocity
local trailSprite
local highScore = 0

function resetGame()
	print("in function resetGame")
	isSpacebarPressed = false
	frameNum = 1
	colorList = {}
	numLives = 5
	maxTrailSize = 20
	isPpressed = false
	isMpressed = false
	isRpressed = false

	-- debug
	SHOW_COLLISION_BOX = false

	--Ship--
	ship = {}
	ship.xPos = 400
	ship.yPos = 300
	ship.theta = 4.71
	ship.xVelocity = 0
	ship.xAccel = 0.15
	ship.w = 32
	ship.h = 32
	ship.sprite = love.graphics.newImage("ship2.png")
	trailSprite = love.graphics.newImage("ship.png")
	shipIcon = love.graphics.newImage("shiplives.png")
	maxVelocity = 5.25

	--Asteroid images--
	smallAsteroidImage = love.graphics.newImage("asteroid16.png")
	mediumAsteroidImage = love.graphics.newImage("asteroid32.png")
	largeAsteroidImage = love.graphics.newImage("asteroid64.png")
	menuImage = love.graphics.newImage("menu.png")
	gameoverImage = love.graphics.newImage("gameoverMenu.png")
	-- asteroid sfx
	smallAsteroidSound = love.audio.newSource("pickup.wav", "static")
	mediumAsteroidSound = love.audio.newSource("pickup2.wav", "static")
	largeAsteroidSound = love.audio.newSource("pickup3.wav", "static")
	expSound = love.audio.newSource("deathSfx.wav", "static")
	--Asteroids--
	numAsteroids = 20
	asteroids = {}

	--Asteroid spawner--
	for i = 1, numAsteroids do

		local rand = math.random(1,3)

		asteroids[i] = {}

		if rand == 1 then
			asteroids[i].W = 16
			asteroids[i].H = 16
			asteroids[i].sprite = smallAsteroidImage
			asteroids[i].v = 2.5
			asteroids[i].pointValue = 10
			asteroids[i].sfx = smallAsteroidSound
		elseif rand == 2 then
			asteroids[i].W = 32
			asteroids[i].H = 32
			asteroids[i].sprite = mediumAsteroidImage
			asteroids[i].v = 1.3
			asteroids[i].pointValue = 50
			asteroids[i].sfx = mediumAsteroidSound
		else
			asteroids[i].W = 64
			asteroids[i].H = 64
			asteroids[i].sprite = largeAsteroidImage
			asteroids[i].v = 1
			asteroids[i].pointValue = 100
			asteroids[i].sfx = largeAsteroidSound
		end

		rand = math.random(1,4)

		if rand == 1 then
			asteroids[i].X = math.random(-400, -64)
			asteroids[i].Y = math.random(0, 600)
			asteroids[i].theta = -0.785 + (math.random() * 1.57 )
		elseif rand == 2 then
			asteroids[i].X = math.random(864, 2000)
			asteroids[i].Y = math.random(0, 600)
			asteroids[i].theta = 2.35 + (math.random() * 1.57 )
		elseif rand == 3 then
			asteroids[i].X = math.random(0, 800)
			asteroids[i].Y = math.random(-400, -64)
			asteroids[i].theta = 0.398 + (math.random() * 1.57 )
		else
			asteroids[i].X = math.random(0, 800)
			asteroids[i].Y = math.random(700, 2000)
			asteroids[i].theta = 4.71 + (math.random() * 1.57 )
		end

	end

	-- controls
	isUpHeld = false
	isLeftHeld = false
	isRightHeld = false

	--other
	score = 0

	-- pick some random colors
	trailPos = {}
	for i = 1, maxTrailSize do
		local c = {}
		c.r = math.random(1)
		c.g = math.random(1)
		c.b = math.random(1)
		colorList[i] = c
	end
	--Check state
	state = "menuState"
end

function love.load()
	print( "in function love.load" )
	resetGame()
end

function love.draw()

	if state == "menuState" then
		drawMenu()
	elseif state == "gameState" then
		drawGame()
	elseif state == "gameoverState" then
		drawGameover()
	end

end

function love.update()
	mainFont = love.graphics.newFont("Mojang-Regular.ttf", 20)
	love.graphics.setFont(mainFont)

	if state == "menuState" then
		updateMenu()
	elseif state == "gameState" then
		updateGame()
	elseif state == "gameoverState" then
		updateGameover()
	end
end

function updateMenu()
	if isPpressed then
		state = "gameState"
	end
end

function updateGameover()
	if isRpressed then
		resetGame()
		state = "gameState"
	elseif isMpressed then
		resetGame()
		state = "menuState"
	end
end


function updateGame()

	-- stick the pos structure into the *front* of our trail list
	if frameNum % 5 == 0 then

		-- create a pos structure that represents where the ship is right now
		local pos = {}
		pos.x = ship.xPos
		pos.y = ship.yPos
		pos.theta = ship.theta

		table.insert(trailPos, 1, pos)
		if #trailPos > maxTrailSize then
			table.remove(trailPos)
		end

		if not isSpacebarPressed then
			table.remove(trailPos)
		end

	end

	for i = 1, numAsteroids do
		-- update position
		asteroids[i].X = asteroids[i].X + math.cos(asteroids[i].theta) * asteroids[i].v
		asteroids[i].Y = asteroids[i].Y + math.sin(asteroids[i].theta) * asteroids[i].v
		-- check for asteroid going offscreen, if so then respawn
		if asteroids[i].X > 900 or asteroids[i].Y > 700 or asteroids[i].X < -100 or asteroids[i].Y < -100 then

			rand = math.random(1,4)

			if rand == 1 then
				asteroids[i].X = math.random(-100, -64)
				asteroids[i].Y = math.random(0, 600)
				asteroids[i].theta = -0.785 + (math.random() * 1.57 )
			elseif rand == 2 then
				asteroids[i].X = math.random(864, 900)
				asteroids[i].Y = math.random(0, 600)
				asteroids[i].theta = 2.35 + (math.random() * 1.57 )
			elseif rand == 3 then
				asteroids[i].X = math.random(0, 800)
				asteroids[i].Y = math.random(-100, -64)
				asteroids[i].theta = 0.398 + (math.random() * 1.57 )
			else
				asteroids[i].X = math.random(0, 800)
				asteroids[i].Y = math.random(700, 900)
				asteroids[i].theta = 4.71 + (math.random() * 1.57 )
			end

		end
	end


	for i = 1, numAsteroids do
	---VVV SHIP TO ASTEROID COLLISION VVV
		-- test each asteroid against our main ship...
		if ship.xPos > asteroids[i].X and ship.xPos < asteroids[i].X + asteroids[i].W and ship.yPos > asteroids[i].Y and ship.yPos < asteroids[i].Y + asteroids[i].H then
		 	asteroids[i].X = math.random(-100, -64)
		 	asteroids[i].Y = math.random(0, 600)
		 	asteroids[i].theta = -0.785 + (math.random() * 1.57 )
		 	numLives = numLives - 1
		 	ship.xPos = 400
		 	ship.yPos = 300
		 	trailPos = {}
		 	love.audio.stop(expSound)
		 	love.audio.play(expSound)
		 	if numLives == 0 then
		 		love.audio.stop(expSound)
		 		love.audio.play(expSound)
		 		if score > highScore then
		 			highScore = score
		 		end
		 		state = 'gameoverState'
		 	end


		 end
		 -- test each asteroid against every ship in the trail...
		for j = 1, #trailPos do
			if trailPos[j].x > asteroids[i].X and trailPos[j].x < asteroids[i].X + asteroids[i].W and trailPos[j].y > asteroids[i].Y and trailPos[j].y < asteroids[i].Y + asteroids[i].H then
			 	asteroids[i].X = math.random(-100, -64)
			 	asteroids[i].Y = math.random(0, 600)
			 	asteroids[i].theta = -0.785 + (math.random() * 1.57 )
			 	score = score + asteroids[i].pointValue
				love.audio.stop(asteroids[i].sfx)
				love.audio.play(asteroids[i].sfx)
			end
		end
	end


	-- Asteroid to asteroid collision
	-- dont flip things twice!
	local hasAlreadyFlipped = {}
	for k = 1, numAsteroids do
		hasAlreadyFlipped[k] = false
	end
	for i = 1, numAsteroids do
		local curAsteroid = asteroids[i]
		for j = 1, numAsteroids do
			local isUpperLeftColliding = false
			local isUpperRightColliding = false
			local isLowerLeftColliding = false
			local isLowerRightColliding = false

			isUpperLeftColliding = curAsteroid.X > asteroids[j].X and
			  					   curAsteroid.X < asteroids[j].X + asteroids[j].W and
			  					   curAsteroid.Y > asteroids[j].Y and
			   					   curAsteroid.Y < asteroids[j].Y + asteroids[j].H

			isUpperRightColliding = curAsteroid.X + curAsteroid.W > asteroids[j].X and
									curAsteroid.X + curAsteroid.W < asteroids[j].X + asteroids[j].W and
									curAsteroid.Y > asteroids[j].Y and
									curAsteroid.Y < asteroids[j].Y + asteroids[j].H

			isLowerLeftColliding = curAsteroid.X > asteroids[j].X and
								   curAsteroid.X < asteroids[j].X + asteroids[j].W and
								   curAsteroid.Y + curAsteroid.H > asteroids[j].Y and
								   curAsteroid.Y + curAsteroid.H < asteroids[j].Y + asteroids[j].H

			isLowerRightColliding = curAsteroid.X + curAsteroid.W > asteroids[j].X and
									curAsteroid.X + curAsteroid.W < asteroids[j].X + asteroids[j].W and
									curAsteroid.Y + curAsteroid.H > asteroids[j].Y and
									curAsteroid.Y + curAsteroid.H < asteroids[j].Y + asteroids[j].H

			local isCurOnscreen = curAsteroid.X > 0 and curAsteroid.X < 800 and curAsteroid.Y > 0 and curAsteroid.Y < 600
			local isOtherOnscreen = asteroids[j].X > 0 and asteroids[j].X < 800 and asteroids[j].Y > 0 and asteroids[j].Y < 600

			if isCurOnscreen and isOtherOnscreen then
				if isUpperLeftColliding or isUpperRightColliding or isLowerLeftColliding or isLowerRightColliding then
					if hasAlreadyFlipped[i] == false then
						curAsteroid.theta = curAsteroid.theta + math.pi
						hasAlreadyFlipped[i] = true
					end
					if hasAlreadyFlipped[j] == false then
						asteroids[j].theta = asteroids[j].theta + math.pi
						hasAlreadyFlipped[j] = true
					end
				end
			end
		end
	end

	if isUpHeld == true then
		ship.xVelocity = ship.xVelocity + 0.5
	else
		ship.xVelocity = ship.xVelocity - 0.075
	end

	if isLeftHeld == true then
		ship.theta = ship.theta - 0.1
	end

	if isRightHeld == true then
		ship.theta = ship.theta + 0.1
	end

	if ship.xVelocity < 0 then
		ship.xVelocity = 0
	end

	if ship.xVelocity > maxVelocity then
		ship.xVelocity = maxVelocity
	end

	ship.xPos = ship.xPos + math.cos(ship.theta) * ship.xVelocity
	ship.yPos = ship.yPos + math.sin(ship.theta) * ship.xVelocity

	if ship.xPos > 800 then
  		ship.xPos = 0
	end

	if ship.xPos < 0 then
	  ship.xPos = 800
	end

	if ship.yPos > 600 then
		ship.yPos = 0
	end

	if ship.yPos < 0 then
		ship.yPos = 600
	end

	frameNum = frameNum + 1

end


function drawMenu()
	love.graphics.setColor(255, 255, 255)
	love.graphics.draw(menuImage, 0, 0)
end

function drawGameover()
	love.graphics.setColor(1, 1, 1)
	love.graphics.draw(gameoverImage, 0, 0)
	love.graphics.setColor((52/255), (89/255), (35/255))
	love.graphics.print(score, 150, 240)
	--love.graphics.print("best:"..highScore, 100, 340)
end

function drawGame()

	love.graphics.setBackgroundColor(115/255, 138/255, 40/255)

	for i = 1, numLives do
		love.graphics.setColor((52/255), (89/255), (35/255))
		love.graphics.draw( shipIcon, 32*i, 64, -math.pi/2 )
	end

	for i = #trailPos, 1, -1 do
		local alpha = 1
		love.graphics.setColor( colorList[i].r, colorList[i].g, colorList[i].b, alpha )
		love.graphics.draw(trailSprite, trailPos[i].x, trailPos[i].y, trailPos[i].theta, 1, 1, 16, 16 )
	end

	love.graphics.setColor(1, 1, 1)
	for i = 1, numAsteroids do
		love.graphics.draw(asteroids[i].sprite, asteroids[i].X, asteroids[i].Y)
		if SHOW_COLLISION_BOX then
			love.graphics.setColor( math.random(1), math.random(1), math.random(1) )
			love.graphics.rectangle( "line", asteroids[i].X, asteroids[i].Y, asteroids[i].W, asteroids[i].H )
			love.graphics.setPointSize( 10 )
			love.graphics.point( asteroids[i].X + asteroids[i].H, asteroids[i].Y + asteroids[i].H )
			love.graphics.print( i, asteroids[i].X, asteroids[i].Y )
			love.graphics.setColor( 1, 1, 1 )
		end
	end

	love.graphics.setColor((52/255), (89/255), (35/255))
	love.graphics.draw(ship.sprite, ship.xPos, ship.yPos, ship.theta, 1, 1, 16, 16)

	if SHOW_COLLISION_BOX then
		love.graphics.setColor( math.random(1), math.random(1), math.random(1) )
		love.graphics.setPointSize( 3 )
		love.graphics.point( ship.xPos, ship.yPos )
		love.graphics.setColor( 1, 1, 1 )
	end

	love.graphics.setColor((52/255), (89/255), (35/255))
	love.graphics.print(score, 45, 10, 0, 1, 1)

end

function love.keypressed(key)

	if key == 'right' then
		ship.theta = ship.theta + 0.1
	end

	if key == 'left' then
		ship.theta = ship.theta - 0.1
	end

	if key == 'up' then
		isUpHeld = true
	end

	if key == 'left' then
		isLeftHeld = true
	end

	if key == 'right' then
		isRightHeld = true
	end

	if key == 'escape' then
		love.event.push( 'quit' )
	end

	if key == 'c' then
		SHOW_COLLISION_BOX = not SHOW_COLLISION_BOX
	end

	if key == ' ' then
		isSpacebarPressed = true
	end

	if key == 'p' then
		isPpressed = true
	end

	if key == 'm' then
		isMpressed = true
	end

	if key == 'r' then
		isRpressed = true
	end
end


function love.keyreleased(key)

	if key == 'up' then
		isUpHeld = false
	end

	if key == 'left' then
		isLeftHeld = false
	end

	if key == 'right' then
		isRightHeld = false
	end

	if key == ' ' then
		isSpacebarPressed = false
	end

	if key == 'p' then
		isPpressed = false
	end

	if key == 'm' then
		isMpressed = false
	end

	if key == 'r' then
		isRpressed = false
	end
end
Last edited by nice on Mon Apr 26, 2021 4:09 pm, edited 1 time in total.
:awesome: Have a good day! :ultraglee:
User avatar
zorg
Party member
Posts: 3435
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: [HELP] with making an OLD project work again

Post by zorg »

- the keycode for spacebar is now 'space' instead of ' '.
- use love.math.random instead of math.random, the latter is not actually seeded at game startup so it'll always give you the same sequence of numbers.
- (love.)math.random(1) does not do what you think it does; just because the colors needed to be scaled from 0-255 to 0-1, the random function given an argument will always give an integer back... between 1 and 1 in that case, so... always 1; just use 255 there and then divide by 256 outside of the random call (otherwise the trail will be white / untinted)
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
nice
Party member
Posts: 191
Joined: Sun Sep 15, 2013 12:17 am
Location: Sweden

Re: [HELP] with making an OLD project work again

Post by nice »

zorg wrote: Mon Apr 26, 2021 1:07 pm - use love.math.random instead of math.random, the latter is not actually seeded at game startup so it'll always give you the same sequence of numbers.
You're an angel!
So just to clarify, I need to exchange every math.random to love.math.random, am I correct?
- (love.)math.random(1) does not do what you think it does; just because the colors needed to be scaled from 0-255 to 0-1, the random function given an argument will always give an integer back... between 1 and 1 in that case, so... always 1; just use 255 there and then divide by 256 outside of the random call (otherwise the trail will be white / untinted)
So I think I just did what you explained here:

Code: Select all

  --getColorValue = (255/256)
	-- pick some random colors
	trailPos = {}
	for i = 1, maxTrailSize do
		local c = {}
		c.r = love.math.random(getColorValue)
		c.g = love.math.random(getColorValue)
		c.b = love.math.random(getColorValue)
		colorList[i] = c
	end
At the start, having "getColorValue" uncommented turns my trail white but when I commented it again (or outright remove it) it works, what's going on?
:awesome: Have a good day! :ultraglee:
User avatar
darkfrei
Party member
Posts: 1168
Joined: Sat Feb 08, 2020 11:09 pm

Re: [HELP] with making an OLD project work again

Post by darkfrei »

What is love.math.random and different with math.random?
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
togFox
Party member
Posts: 764
Joined: Sat Jan 30, 2021 9:46 am
Location: Brisbane, Oztralia

Re: [HELP] with making an OLD project work again

Post by togFox »

love.math.random is automatically seeded.

Plus it starts with 'love'. :)
Current project:
https://togfox.itch.io/backyard-gridiron-manager
American football manager/sim game - build and manage a roster and win season after season
User avatar
pgimeno
Party member
Posts: 3541
Joined: Sun Oct 18, 2015 2:58 pm

Re: [SOLVED] with making an OLD project work again

Post by pgimeno »

math.random() without args returns a number between 0 and 1 and could be used to port the program to Löve 11; math.random(1) will always return 1. Same with love.math.random() vs love.math.random(1).

With LuaJIT, there isn't any advantage of the Löve version other than that it's initialized by default. Both are designed to be fast and cross-platform. The additional advantages of Löve's random number generator come with RandomGenerator objects created with love.math.newRandomGenerator(), not with love.math.random(), unless you consider an advantage that the seed is a 64 bit number instead of 32 bit.

With PUC Lua, you're not guaranteed to get the same random numbers from Lua interpreters compiled with different C libraries. Fortunately Löve uses LuaJIT, not PUC Lua.
User avatar
zorg
Party member
Posts: 3435
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: [HELP] with making an OLD project work again

Post by zorg »

nice wrote: Mon Apr 26, 2021 1:36 pm
- (love.)math.random(1) does not do what you think it does; just because the colors needed to be scaled from 0-255 to 0-1, the random function given an argument will always give an integer back... between 1 and 1 in that case, so... always 1; just use 255 there and then divide by 256 outside of the random call (otherwise the trail will be white / untinted)
So I think I just did what you explained here:

Code: Select all

  --getColorValue = (255/256)
	-- pick some random colors
	trailPos = {}
	for i = 1, maxTrailSize do
		local c = {}
		c.r = love.math.random(getColorValue)
		c.g = love.math.random(getColorValue)
		c.b = love.math.random(getColorValue)
		colorList[i] = c
	end
At the start, having "getColorValue" uncommented turns my trail white but when I commented it again (or outright remove it) it works, what's going on?
The way you did it still means that a fraction is the parameter you give to love.math.random; I meant moreso like this:

Code: Select all

-- pick some random colors
	trailPos = {}
	for i = 1, maxTrailSize do
		local c = {}
		c.r = love.math.random(255)/256
		c.g = love.math.random(255)/256
		c.b = love.math.random(255)/256
		colorList[i] = c
	end
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
nice
Party member
Posts: 191
Joined: Sun Sep 15, 2013 12:17 am
Location: Sweden

Re: [HELP] with making an OLD project work again

Post by nice »

The way you did it still means that a fraction is the parameter you give to love.math.random; I meant moreso like this:

Code: Select all

-- pick some random colors
	trailPos = {}
	for i = 1, maxTrailSize do
		local c = {}
		c.r = love.math.random(255)/256
		c.g = love.math.random(255)/256
		c.b = love.math.random(255)/256
		colorList[i] = c
	end
[/quote]

Ah, I think I understand, thank you for your help!
:awesome: Have a good day! :ultraglee:
User avatar
darkfrei
Party member
Posts: 1168
Joined: Sat Feb 08, 2020 11:09 pm

Re: [SOLVED] with making an OLD project work again

Post by darkfrei »

Note that love.math.random(255)/256 never gives 0 or 1.

Maybe you are need love.math.random(0, 255)/255 instead.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 21 guests