The game
I'm working on a prototype where I have a player (white circle) that collects "trash" (a square with T) to protect "animals" that walks across the screen. A new piece of "trash" spawns on the screen when the Player collides with a "trash" object on the screen.
Here's a screenshot
What's happening right now?
How the spawning of the "Trash" works right now, is that they take random X/Y coordinates and spawn 10 of them across the screen.
But the problem with this is that sometimes they overlap each other when spawning on the screen or spawn in a cluster.
What I want to happen
What I want to happen is that when the trash is spawned on screen, the trash position themselves accordingly to the grid (see screenshot), making the spawn pattern (hopefully) more "even" (if that makes any sense).
What I have right now
As a foundation, I have a grid drawn out on the screen to better visualize how the grid will work. It's not aligned perfectly to the screen size (1680x1050) as the tiles themselves are 32x32.
I've used CS50's snake tutorial as a starting point and modify it to suit my needs.
What I want help with
What I want help with is how should I go about spawning the "Trash" accordingly to the tiles, the tutorial goes explains how stuff is spawned in the game by changing the tiles on the screen to something else (for example the snake's head). I think that I want something similar but that only affects the "trash".
If there's something that needs to be explained better, please let me know.
Thank you for your time!
main.lua
Code: Select all
require("mobdebug").start()
Player = require "player"
trash = require "trash"
animal = require "animal"
local tileGrid = {}
function love.load()
trashController.spawnTrash(10)
animalController.spawnAnimal(1)
spawnTimer = 1
Window = {}
Window.Width = love.graphics:getWidth()
Window.Height = love.graphics:getHeight()
TILE_SIZE = 32
MAX_TILES_X = (Window.Width / TILE_SIZE)
MAX_TILES_Y = (Window.Height / TILE_SIZE)
TILE_EMPTY = 0
TILE_TRASH = 1
--math.randomseed(os.time())
end
function love.update(dt)
Player:update(dt)
trash:update(dt)
animal:update(dt)
end
function love.draw()
Player:draw()
trash:draw()
animal:draw()
for y = 1, MAX_TILES_Y do
for x = 1, MAX_TILES_X do
love.graphics.setColor(0, 1, 1, 0.3)
love.graphics.rectangle('line',
(x - 1) * TILE_SIZE,
(y - 1) * TILE_SIZE,
TILE_SIZE,
TILE_SIZE)
love.graphics.setColor(1, 1, 1, 1)
end
end
end
function love.keypressed(key)
Player:keypressed(key)
-- Close Window
if key == 'escape' then
love.event.quit()
end
end
function love.keyreleased(key)
Player:keyreleased(key)
end
Code: Select all
Player = require "player"
trash = {}
trashController = {}
trashController.trashes = {}
--[[
attaching stuff to grid (starting to explain it)
https://youtu.be/ld_xcXdRez4?t=3505
]]
function trashController.spawnTrash(maxTrash)
local mRand = math.random
local width = love.graphics:getWidth()
local height = love.graphics:getHeight()
local minValue = 100
local minX = minValue
local maxX = width - minValue
local minY = minValue
local maxY = height - minValue
local halfWidth = love.graphics:getWidth() * 0.5
local halfHeight = love.graphics:getHeight() * 0.5
love.math.setRandomSeed(love.timer.getTime())
local randValueX = love.math.random(minX, maxX)
local randValueY = love.math.random(minY, maxY)
local minRandValueX = love.math.random(minX, halfWidth)
local maxRandValueX = love.math.random(halfWidth, maxX)
local minRandValueY = love.math.random(minY, halfHeight)
local maxRandValueY = love.math.random(halfHeight, maxY)
for i = 1, maxTrash do
x = mRand(minRandValueX, maxRandValueX)
y = mRand(minRandValueY, maxRandValueY)
Trash = {}
Trash.Sprite = love.graphics.newImage("trash.png")
Trash.posX = x
Trash.posY = y
Trash.Width = Trash.Sprite:getWidth()
Trash.Height = Trash.Sprite:getHeight()
table.insert(trashController.trashes, Trash)
end
end
function trashController.draw()
for i, trash in ipairs(trashController.trashes) do
love.graphics.draw(trash.Sprite, trash.posX, trash.posY)
end
end
function trash:trash_hit_player(trash, index)
local playerHalfWidth = Player.Width * 0.5
local playerHalfHeight = Player.Height * 0.5
local trashWidth = Trash.Sprite:getWidth()
local trashHeight = Trash.Sprite:getHeight()
if(trash.posX <= Player.posX + playerHalfWidth and
trash.posX + trashWidth >= Player.posX and
trash.posY < Player.posY + Player.Height and
trash.posY + trashHeight >= Player.posY) then
print("Trash hit Player")
table.remove(trashController.trashes, index)
end
end
function trash:update(dt)
for _, t in ipairs(trashController.trashes) do
trash:trash_hit_player(t, _)
end
if #trashController.trashes < 10 then
trashController.spawnTrash(1)
end
end
function trash:draw()
trashController.draw()
end
return trash
Code: Select all
trash = require "trash"
animal = {}
animalController = {}
animalController.animals = {}
function animalController.spawnAnimal(maxAnimal)
love.math.setRandomSeed(love.timer.getTime())
local mRand = math.random
local randSpawnValue = love.math.random(1, 4)
local randSpriteValue = love.math.random(1, 2)
-- Widths and Heights
local width = love.graphics:getWidth()
local height = love.graphics:getHeight()
local halfWidth = love.graphics:getWidth() * 0.5
local halfHeight = love.graphics:getHeight() * 0.5
-- sp = spawn point
local sp_LEFT = 50
local sp_RIGHT = 1600
local sp_TOP = 50
local sp_BOTTOM = 950
-- sr = spawn min/max range
local sr_minX = 100
local sr_maxX = width - 100
local sr_minY = 100
local sr_maxY = height - 100
-- Animal Sprite
local bigAnimal = love.graphics.newImage("Deer.png")
local bigAnimalWidth = bigAnimal:getWidth()
local bihgAnimalHeight = bigAnimal:getHeight()
local smallAnimal = love.graphics.newImage("smallAnimal.png")
local smallAnimalWidth = smallAnimal:getWidth()
local smallAnimalHeight = smallAnimal:getHeight()
-- local Scale = 1
-- local Direction = 1
Animal = {}
--Animal.randomSprite = love.math.random(smallAnimal, bigAnimal)
Animal.Sprite = bigAnimal
Animal.Life = 2
Animal.collidedLastFrame = false
Animal.color = {0,1,0,1}
-- local randSpawnValue = love.math.random(1, 4)
if randSpawnValue == 1 then
Animal.spawnLeft = true
Animal.spawnRight = false
Animal.spawnTop = false
Animal.spawnBottom = false
Animal.posX = sp_LEFT
Animal.posY = mRand(sr_minY, sr_maxY)
elseif randSpawnValue == 2 then
--[[
Create its own separate sprite that's in
the correct direction?
Would be ugly solution and it would be necessary
that it uses the same timer.
]]
Animal.spawnLeft = false
Animal.spawnRight = true
Animal.spawnTop = false
Animal.spawnBottom = false
Animal.posX = sp_RIGHT
Animal.posY = mRand(sr_minY, sr_maxY)
elseif randSpawnValue == 3 then
Animal.spawnLeft = false
Animal.spawnRight = false
Animal.spawnTop = true
Animal.spawnBottom = false
Animal.posX = mRand(sr_minX, sr_maxY)
Animal.posY = sp_TOP
elseif randSpawnValue == 4 then
Animal.spawnLeft = false
Animal.spawnRight = false
Animal.spawnTop = false
Animal.spawnBottom = true
Animal.posX = mRand(sr_minX, sr_maxX)
Animal.posY = sp_BOTTOM
end
table.insert(animalController.animals, Animal)
end
function animalController.draw()
for i, animal in ipairs(animalController.animals) do
love.graphics.print(animal.Life, animal.posX, animal.posY, 0, 2, 2)
love.graphics.setColor(animal.color)
love.graphics.draw(Animal.Sprite,
animal.posX,
animal.posY,
animal.Radians)
end
love.graphics.setColor(1, 1, 1, 1)
end
function animal_hit_trash(animal, index)
local trashWidth = Trash.Sprite:getWidth()
local trashHeight = Trash.Sprite:getHeight()
local trashHalfWidth = Trash.Sprite:getWidth() * 0.5
local trashHalfHeight = Trash.Sprite:getHeight() * 0.5
local animalWidth = animal.Sprite:getWidth()
local animalHeight = animal.Sprite:getHeight()
local animalHalfWidth = animal.Sprite:getWidth() * 0.5
local animalHalfHeight = animal.Sprite:getHeight() * 0.5
local Collided = false
for _, t in ipairs(trashController.trashes) do
if (animal.posX <= t.posX + trashHalfWidth and
animal.posX + animalWidth > t.posX and
animal.posY < t.posY + trashHeight and
animal.posY + animalHeight > t.posY) then
Collided = true
if animal.collidedLastFrame == false then
animal.Life = animal.Life - 1
animal.collidedLastFrame = true
print("Animal hit Trash")
if animal.Life == 0 then
table.remove(animalController.animals, index)
else
animal.color = {1,0,0,1}
end
end
end
end
if Collided == false then
animal.collidedLastFrame = false
end
end
function animal:update(dt)
local moveSpeed = 400
--print(spawnTimer)
spawnTimer = spawnTimer - dt
if spawnTimer <= 0 then
animalController.spawnAnimal()
spawnTimer = spawnTimer + 1
end
for _, animal in pairs(animalController.animals) do
if animal.spawnLeft == true then
animal.posX = animal.posX + moveSpeed * dt
elseif animal.spawnRight == true then
animal.posX = animal.posX - moveSpeed * dt
elseif animal.spawnTop == true then
animal.posY = animal.posY + moveSpeed * dt
elseif animal.spawnBottom == true then
animal.posY = animal.posY - moveSpeed * dt
end
end
-- Destroy animal when it collides with Trash
for i, animal in ipairs(animalController.animals) do
animal_hit_trash(animal, i)
end
-- Remove animals if they're outside of the screen
for i, animal in ipairs(animalController.animals) do
if animal.posX >= 1800 then
table.remove(animalController.animals, i)
print("removed animal RIGHT")
elseif animal.posX <= -250 then
table.remove(animalController.animals, i)
print("removed animal LEFT")
elseif animal.posY >= 1200 then
table.remove(animalController.animals, i)
print("removed animal BOTTOM")
elseif animal.posY <= -250 then
table.remove(animalController.animals, i)
print("removed animal TOP")
end
end
end
function animal:draw()
animalController.draw()
end
return animal
Code: Select all
local isLeftHeld
local isRightHeld
local isUpHeld
local isDownHeld
-- " p " is for "player"
local p_LEFT = {'left', 'a'}
local p_RIGHT = {'right', 'd'}
local p_UP = {'up', 'w'}
local p_DOWN = {'down', 's'}
Player = {}
-- Player Draw
Player.Sprite = love.graphics.newImage("player.png")
Player.posX = love.graphics.getWidth() * 0.5
Player.posY = love.graphics.getHeight() * 0.5
Player.Radians = 0
Player.scaleX = 1
Player.scaleY = 1
Player.originX = 0
Player.originY = 0
-- Player Movement
Player.Acceleration = 1
Player.Speed = 500
Player.Width = Player.Sprite:getWidth()
Player.Height = Player.Sprite:getHeight()
-- Player Clamping
Player.clampTop = Player.Sprite:getWidth() * 0
Player.clampBottom = love.graphics:getHeight() - 64
Player.clampLeft = Player.Sprite:getHeight() * 0
Player.clampRight = love.graphics:getWidth() - 64
function Player:update(dt)
-- Player Movement
if love.keyboard.isDown(p_LEFT) then
self.posX = self.posX - (self.Acceleration * self.Speed) * dt
elseif love.keyboard.isDown(p_RIGHT) then
self.posX = self.posX + (self.Acceleration * self.Speed) * dt
end
if love.keyboard.isDown(p_UP) then
self.posY = self.posY - (self.Acceleration * self.Speed) * dt
elseif love.keyboard.isDown(p_DOWN) then
self.posY = self.posY + (self.Acceleration * self.Speed) * dt
end
-- Player Clamping
if self.posY <= self.clampTop then
self.posY = self.clampTop
end
if self.posY >= self.clampBottom then
self.posY = self.clampBottom
end
if self.posX <= self.clampLeft then
self.posX = self.clampLeft
end
if self.posX >= self.clampRight then
self.posX = self.clampRight
end
end
function Player:draw()
love.graphics.draw(self.Sprite,
self.posX,
self.posY,
self.Radians,
self.scaleX,
self.scaleY,
self.originX,
self.originY)
end
function Player:keypressed(key)
end
function Player:keyreleased(key)
end
return Player