lua - screen limit for characters - lua

I have a problem where my character keeps going out of my screen.
How do I fix this problem? I know I need to put in a function to prevent the character from going out of the screen and managed to do it on the radius of the circle.
if love.keyboard.isDown("right") then
player.x = player.x + 4
elseif love.keyboard.isDown("left") then
player.x = player.x - 4
elseif love.keyboard.isDown("up") then
player.y = player.y - 4
elseif love.keyboard.isDown("down") then
player.y = player.y + 4
end
if AABB(player.x, player.y, player.w, player.h, target.x, target.y, target.raduis) then
score = score + 1
target.x = math.random(target.raduis, love.graphics.getWidth() - target.raduis)
target.y = math.random(target.raduis, love.graphics.getHeight()- 100)
end

im not sure what the "character" is, so im going to do both the player and the target
if you want the character to not go off screen, try:
if player.x < 0 then
player.x = 0
elseif player.x + player.w > love.graphics.getWidth() then
player.x = love.graphics.getWidth() - player.w
end
if player.y < 0 then
player.y = 0
elseif player.y + player.h > love.graphics.getHeight() then
player.y = love.graphics.getHeight() - player.h
end
if you want the target to stay on screen, try:
if AABB(player.x, player.y, player.w, player.h, target.x, target.y,
target.raduis) then
score = score + 1
target.x = math.random(0 + target.raduis, love.graphics.getWidth() - target.raduis)
target.y = math.random(0 + target.raduis, love.graphics.getHeight() - target.raduis)
end
hopefully this helps

Related

Error ball.lua:21: attempt to call global 'checkcollision' (a nil value)

Having this problem with my code and i don't get it
basically trying to make a small game as an excercise, but failing when trying the ecollision part
from my beginners knowledge, there is a problem in line 21 (if checkcollision()) inside the "Ball" file, but don't know what thee problem is
This is my "Ball" code
Ball = {}
function Ball:load()
self.x = love.graphics.getWidth() / 2
self.y = love.graphics.getHeight() / 2
self.width = 20
self.height = 20
self.speed = 200
self.xvel = -self.speed
self.yvel = 0
end
function Ball:update(dt)
self:move(dt)
self:collide()
end
function Ball:collide()
if checkcollision(self, Player) then
self.xvel = self.speed
local middleBall = self.y + self.height / 2
local middlePlayer = Player.y + Player.height / 2
local CollisionPosition = middleBall - middlePlayer
self.yvel = CollisionPosition * 5
end
end
function Ball:move(dt)
self.x = self.x + self.xvel * dt
self.y = self.y + self.yvel * dt
end
function Ball:draw()
love.graphics.rectangle("fill",self.x, self.y, self.width, self.height)
end
This is my "main" code
require("player")
require("ball")
function love.load()
Player:load()
Ball:load()
end
function love.update(dt)
Player:update(dt)
Ball:update(dt)
end
function love.draw()
Player:draw()
Ball:draw()
end
function checkcollision(a, b)
if a.x + a.width > b.x and a.x < b.x + b.width and a.y + a.height > b.y and a.y < b.height then
return true
else
return false
end
end
My "player" code
Player = {}
function Player:load()
self.x = 50
self.y = love.graphics.getHeight() / 2
self.width = 25
self.height = 100
self.speed = 500
end
function Player:update(dt)
self:move(dt)
self:checkbounderies()
end
function Player:move(dt)
if love.keyboard.isDown("w") then
self.y = self.y - self.speed * dt
elseif love.keyboard.isDown("s") then
self.y = self.y + self.speed * dt
end
end
function Player:checkbounderies()
if self.y < 0 then
self.y = 0
elseif self.y + self.height > love.graphics.getHeight() then
self.y = love.graphics.getHeight() - self.height
end
end
function Player:draw()
love.graphics.rectangle("fill", self.x, self.y, self.width, self.height)
end
can someone point me to the right direction
You require Ball code which uses checkcollision function as upvalue before defining checkcollision function.
Basically you need to define checkcollision before using it anywhere; just reorder your imports.
But to solve it the right way, it would be better to move the checkcollision function to a separate file:
-- checkcollision.lua
local function checkcollision(a, b) ....... end
return checkcollision
and then require it in any file you want:
-- Ball.lua
local checkcollision = require "checkcollision"
function Ball:collide()
if checkcollision(self, Player) then
.......

How to offset bullet object, based on player's direction

I'm running lua 5.1 and love2d 11.3.0
In my demo, I have a top down shooter game. For visual purposes the character looks like so...As you can see from this top down perspective, he is holding his weapon out.
My issue is that I am having a hard time figuring out how to have his bullets start from the tip of his gun no matter what direction he is facing, or where on the screen he is positioned. Currently, the bullets always shoot from the center of this body. I have tried adjusting the bullet.x and bullet.y properties below, but that is a static change that doesn't respect the players direction...
function spawnBullet()
local bullet = {}
bullet.x = player.x
bullet.y = player.y
bullet.speed = 500
bullet.direction = playerMouseAngle()
table.insert(bullets, bullet)
end
The full game logic :
-- top down shooter game demo 2021
function love.load()
-- create table to collect sprite assets
sprites = {}
sprites.bg = love.graphics.newImage('graphics/bg_grass.jpg')
sprites.hero = love.graphics.newImage('graphics/hero.png')
-- create table for our player hero
player = {}
player.x = love.graphics.getWidth() / 2
player.y = love.graphics.getHeight() / 2
player.speed = 360
player.injured = false
player.injuredSpeed = 270
-- create table for player bullets
bullets = {}
-- game state, timer and score globals
gameState = 1
maxTime = 2
timer = maxTime
score = 0
end
function love.update(dt)
if gameState == 2 then
-- player speed will be adjusted below
local moveSpeed = player.speed
-- adjust player speed if player was injured
if player.injured then moveSpeed = player.injuredSpeed end
-- player moves right
if love.keyboard.isDown("d") and player.x < love.graphics.getWidth() -
50 then player.x = player.x + moveSpeed * dt end
-- player moves left
if love.keyboard.isDown("a") and player.x > 50 then
player.x = player.x - moveSpeed * dt
end
-- player moves up
if love.keyboard.isDown("w") and player.y > 50 then
player.y = player.y - moveSpeed * dt
end
-- player moves down
if love.keyboard.isDown("s") and player.y < love.graphics.getHeight() -
50 then player.y = player.y + moveSpeed * dt end
end
-- make bullets move in desired direction
for i, b in ipairs(bullets) do
b.x = b.x + (math.cos(b.direction) * b.speed * dt)
b.y = b.y + (math.sin(b.direction) * b.speed * dt)
end
-- remove the bullets from the game once they go off-screen
for i = #bullets, 1, -1 do
local b = bullets[i]
if b.x < 0 or b.y < 0 or b.x > love.graphics.getWidth() or b.y >
love.graphics.getHeight() then table.remove(bullets, i) end
end
-- manage game state and timer
if gameState == 2 then
timer = timer - dt
if timer <= 0 then
maxTime = 0.95 * maxTime
timer = maxTime
end
end
end
function love.draw()
-- setup background
love.graphics.push()
love.graphics.scale(0.20, 0.20)
love.graphics.draw(sprites.bg, 0, 0)
love.graphics.pop()
-- click to begin
if gameState == 1 then
love.graphics.printf('Click anywhere to begin!', 0, 50, love.graphics.getWidth(), "center")
end
-- display score
love.graphics.printf('Score: ' .. score, 0, love.graphics.getHeight() - 100, love.graphics.getWidth(), "center")
-- adjust player color if player gets injured
if player.injured then love.graphics.setColor(1, 0, 0) end
-- draw player
love.graphics.draw(sprites.hero, player.x, player.y, playerMouseAngle(),
nil, nil, sprites.hero:getWidth() / 2,
sprites.hero:getHeight() / 2)
-- display player bullets
for i, b in ipairs(bullets) do
love.graphics.circle("fill", b.x, b.y, 10, 100)
end
end
-- enable player direction based on mouse movement
function playerMouseAngle()
return
math.atan2(player.y - love.mouse.getY(), player.x - love.mouse.getX()) +
math.pi
end
-- define bullet properties
function spawnBullet()
local bullet = {}
bullet.x = player.x
bullet.y = player.y
bullet.speed = 500
bullet.direction = playerMouseAngle()
table.insert(bullets, bullet)
end
-- game state determins shooting player bullets...
function love.mousepressed(x, y, button)
if button == 1 and gameState == 2 then
spawnBullet()
-- ..or starting the game
elseif button == 1 and gameState == 1 then
gameState = 2
maxTime = 2
timer = maxTime
score = 0
end
end
Thanks in advance for any tips
You already have the required math in there during their travel...
-- make bullets move in desired direction
for i, b in ipairs(bullets) do
b.x = b.x + (math.cos(b.direction) * b.speed * dt)
b.y = b.y + (math.sin(b.direction) * b.speed * dt)
end
Just need to tweak it a bit for bullet creation
local bullet = {}
bullet.speed = 500
bullet.direction = playerMouseAngle()
bullet.x = player.x +(math.cos(bullet.direction + 0.5) * (sprites.hero:getWidth() / 2))
bullet.y = player.y +(math.sin(bullet.direction + 0.5) * (sprites.hero:getWidth() / 2))
table.insert(bullets, bullet)
Guessing on the scale. You might have to change the /2 to something else, like *0.75.

Trying to add horizontal movement to my game in love2d

I have tried to add horizontal movement into my game in love, but I haven't found a way yet. This is my code.
PADDLE_SPEED = 200
player1 = Paddle(10, 30, 5, 20)
player1 = Paddle(10, 30, 5, 20)
player2 = Paddle(VIRTUAL_WIDTH - 15, VIRTUAL_HEIGHT - 30, 5, 20)
player3 = Paddle(30, 10, 20, 5)
player4 = Paddle(VIRTUAL_WIDTH - 30, VIRTUAL_HEIGHT - 15, 20, 5)
ball = Ball(VIRTUAL_WIDTH / 2 - 2, VIRTUAL_HEIGHT / 2 - 2, 4, 4)
if love.keyboard.isDown('w') then
player1.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('s') then
player1.dy = PADDLE_SPEED
else
player1.dy = 0
end
if love.keyboard.isDown('a') then
player1.dx = PADDLE_SPEED
elseif love.keyboard.isDown('d') then
player1.dx = -PADDLE_SPEED
else
player1.dx = 0
end
if love.keyboard.isDown('a') then
player1.dx = -PADDLE_SPEED
elseif love.keyboard.isDown('d') then
player1.dy = PADDLE_SPEED
else
player1.dx = 0
end
if love.keyboard.isDown('up') then
player2.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('down') then
player2.dy = PADDLE_SPEED
else
player2.dy = 0
end
if love.keyboard.isDown('i') then
player3.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('k') then
player3.dy = PADDLE_SPEED
else
player3.dy = 0
end
if love.keyboard.isDown('g') then
player4.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('b') then
player4.dy = PADDLE_SPEED
else
player4.dy = 0
end
This is my class that I call Paddle
Paddle = Class{}
function Paddle:init(x, y, width, height)
self.x = x
self.y = y
self.width = width
self.height = height
self.dy = 0
self.dx = 0
end
function Paddle:update(dt)
if self.dy < 0 then
self.y = math.max(0, self.y + self.dy * dt)
else
self.y = math.min(VIRTUAL_HEIGHT - self.height, self.y + self.dy * dt)
end
end
function Paddle:render()
love.graphics.rectangle('fill', self.x, self.y, self.width, self.height)
end
I would try drawing the rectangles individually, but I would have to remove all the code that includes player1-4. Is there any way that I can set a variable like PADDLE_SPEED to a number?
So your not quite instantiating your Paddle class correctly. Based on Lua's documentation, I changed some things in your paddle class.
Paddle.lua
Paddle={x=0,y=0,width=0,height=0}
function Paddle:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Paddle:update(dt)
if self.dy < 0 then
self.y = math.max(0, self.y + self.dy * dt)
else
self.y = math.min(VIRTUAL_HEIGHT - self.height, self.y + self.dy * dt)
end
end
function Paddle:render()
love.graphics.rectangle('fill', self.x, self.y, self.width, self.height)
end
Also I'm not sure what you just didn't include in you question, but I set up your core 3 functions (love.load(), love.update(dt), and love.draw()), set values for VIRTUAL_WIDTH AND VIRTUAL_HEIGHT, and instantiated your player classes according to how the Lua documentation specifies
The main thing that might be your problem is that your assigning the speeds to your player objects dy and dx values. These are made up values that you've created for your player object. They don't do anything unless you later access them and use them somehow. I think what you are trying to do is change the x and y position of your player objects. You can do this by taking the players current x or y position and adding or subtracting the PADDLE_SPEED * dt(the number of seconds that have passed since the last execution of love.update(dt)
main.lua
require('Paddle')
function love.load()
--initial graphics setup
love.graphics.setBackgroundColor(0.41, 0.53, 0.97)
love.window.setMode(1000, 600)
PADDLE_SPEED = 200
VIRTUAL_WIDTH = 30
VIRTUAL_HEIGHT = 30
player1 = Paddle:new{x=10, y=30, width=5, height=20}
player2 = Paddle:new{x=VIRTUAL_WIDTH-15, y=VIRTUAL_HEIGHT-30, width=5, height=20}
player3 = Paddle:new{x=30, y=10, width=20, height=5}
player4 = Paddle:new{x=VIRTUAL_WIDTH-30, y=VIRTUAL_HEIGHT-15, width=20, height=5}
-- ball = Ball(VIRTUAL_WIDTH / 2 - 2, VIRTUAL_HEIGHT / 2 - 2, 4, 4)
end
function love.update(dt)
if love.keyboard.isDown('w') then
player1.y = player1.y + PADDLE_SPEED * dt
elseif love.keyboard.isDown('s') then
player1.y = player1.y - PADDLE_SPEED * dt
end
if love.keyboard.isDown('a') then
player1.x = player1.x + PADDLE_SPEED * dt
elseif love.keyboard.isDown('d') then
player1.x = player1.x - PADDLE_SPEED * dt
end
if love.keyboard.isDown('a') then
player2.x = player2.x - PADDLE_SPEED * dt
elseif love.keyboard.isDown('d') then
player2.x = player2.x + PADDLE_SPEED * dt
end
if love.keyboard.isDown('up') then
player2.y = player2.y - PADDLE_SPEED * dt
elseif love.keyboard.isDown('down') then
player2.y = player2.y + PADDLE_SPEED * dt
end
if love.keyboard.isDown('i') then
player3.y = player3.y - PADDLE_SPEED * dt
elseif love.keyboard.isDown('k') then
player3.y = player3.y + PADDLE_SPEED * dt
end
if love.keyboard.isDown('g') then
player4.y = player4.y - PADDLE_SPEED * dt
elseif love.keyboard.isDown('b') then
player4.y = player4.y + PADDLE_SPEED * dt
end
end
function love.draw()
player1:render()
player2:render()
player3:render()
player4:render()
end
So your ball won't work, because I don't know exactly what you want with it, and your Paddle:update(dt) still won't work because I don't know exactly what you want. When you do get Paddle:update(dt) working make sure you include player1:update(dt), player2:update(dt) ... inside your love:update(dt) function or else none of your players will update.
You should get horizontal and vertical movement of your blocks though
P.S. If you post a question a again, you should make sure that you specify exactly what isn't working. Some of your details were missing, and I wasn't sure if that was the part you were asking about, or you had those details in your original code and were asking about something else.
It seems like you probably want to deal with collisions. Here's another answer where i kind of explain collisions, but I would probably recommend love.physics for this type of scenario

Lua getting (x,y) of player in game

I want to find the x and y coordinates of my player in real time so I know where to make the next level of my game. I'm currently using LÖVE 2D to run my code. When I try to print out player.x and player.y, the game runs fine but there is no text output of the coordinates. I've tried to change the position of where the text is located but that doesn't work. Any help is appreciated. Note: I just started Lua today so be blunt, please. :)
love.graphics.setDefaultFilter('nearest','nearest')
function love.load()
room1Image = love.graphics.newImage('room1.png')
room2Image = love.graphics.newImage('room2.png')
room3Image = love.graphics.newImage('room3.png')
room1 = true
room2 = false
room3 = false
player = {}
player.x = 0
player.y = 255
player.speed = 5
player.image = love.graphics.newImage('player.png')
end
function love.update(dt)
if love.keyboard.isDown("left") then
player.x = player.x - 5
end
if love.keyboard.isDown("right") then
player.x = player.x + 5
end
if love.keyboard.isDown("up") then
player.y = player.y - 5
end
if love.keyboard.isDown("down") then
player.y = player.y + 5
end
if player.y >= 600 and room1 then
room1 = false
room2 = true
player.y = 5
end
if player.y <= 0 and room2 then
room1 = true
room2 = false
player.y = 600
end
if player.y >= 600 and room2 then
room2 = false
room3 = true
player.y = 5
end
if player.y <= 0 and room3 then
room2 = true
room3 = false
player.y = 600
end
end
function love.draw()
--draw background
if room1 then
love.graphics.draw(room1Image, room1Image.x, room1Image.y)
elseif room2 then
love.graphics.draw(room2Image, room2Image.x, room2Image.y)
elseif room3 then
love.graphics.draw(room3Image, room3Image.x, room3Image.y)
end
--draw player
love.graphics.draw(player.image, player.x, player.y, 0, 5)
end
If you want to output something to the console use print(). This will NOT be visible in the game window.
If you want to show some text to the player (in game) call love.graphics.print inside love.draw():
local x,y = 0, 0 --coordinates at which the text is printed
function love.load()
end
function love.update(dt)
end
function love.draw()
love.graphics.print("This is something I want you to see.", x, y)
end

love2d: Image doesn`t get drawn

I am trying to draw my map(loadMap and drawMap) and a player(ghost.png), but only my Map gets drawn and i do not gat an error:
main.lua:
function love.load()
getFiles()
loadPlayer()
loadMap("/maps/chez-peter.lua")
end
function love.draw()
drawPlayer()
drawMap()
end
function love.update(dt)
getKeyboard(dt)
end
function getFiles()
require("player-functions")
require("map-functions")
end
player-functions.lua:
function getKeyboard(dt)
if love.keyboard.isDown("up") then
Player.y = Player.y - 20 * dt
end
if love.keyboard.isDown("down") then
Player.y = Player.y + 20 * dt
end
if love.keyboard.isDown("right") then
Player.x = Player.x + 20 * dt
end
if love.keyboard.isDown("left") then
Player.x = Player.x - 20 * dt
end
end
function loadPlayer()
Player = {}
Player.img = love.graphics.newImage("player/ghost.png")
Player.x = 0
Player.y = 0
end
function drawPlayer()
love.graphics.draw(Player.img , Player.x, Player.y)
end
map-functions.lua:
TileTable = {}
local width = #(tileString:match("[^\n]+"))
for x = 1,width,1 do TileTable[x] = {} end
local rowIndex,columnIndex = 1,1
for row in tileString:gmatch("[^\n]+") do
assert(#row == width, 'Map is not aligned: width of row ' ..tostring(rowIndex) .. ' should be ' .. tostring(width) .. ', but it is ' ..tostring(#row))
columnIndex = 1
for character in row:gmatch(".") do
TileTable[columnIndex][rowIndex] = character
columnIndex = columnIndex + 1
end
rowIndex=rowIndex+1
end
end
function drawMap()
for x,column in ipairs(TileTable) do
for y,char in ipairs(column) do
love.graphics.draw(Tileset, Quads[ char ] , (x-1)*TileW, (y-1)*TileH)
end
end
end
I am using sublime text with the built in love2d building.
If you need chez-peter.lua just ask and thankyou for helping. :)
Try switching the position of the drawPlayer/drawMap methods so that you first draw the map, then draw the player. It could be that they are both being drawn, but the map is being drawn over the player.

Resources