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.
Related
I'm currently making a 2D side-scrolled, and I have a pixel-artists help with this. I did my first animation with a random asset and it worked fine, but now that I'm doing it with the actual asset it stopped showing the asset(No errors). I have changed the resolution and frame size inside code.
function love.load()
anim8 = require 'libraries/anim8-master/anim8'
love.graphics.setDefaultFilter("nearest", "nearest")
player = {};
player.x = 100; --Players position on x axis
player.y = 200; --Players position on y axis
player.speed = 2; --Players speed
player.spriteSheet = love.graphics.newImage('sprites/Man_Spite_Sheet_L.png'); --Players sprite-sheet imported
player.grid = anim8.newGrid(32, 32, player.spriteSheet:getWidth(), player.spriteSheet:getHeight()); --Player spritesheet split into a grid
player.animations = {}; --Table of players animations
player.animations.left = anim8.newAnimation(player.grid('1-4', 3), 0.2); --Right animation
player.animations.right = anim8.newAnimation(player.grid('1-4', 1), 0.2); --Left animation
player.anim = player.animations.left
end
function love.update(dt)
local isMoving = false;
if love.keyboard.isDown("d") then --Move on keypress "d"
player.x = player.x + player.speed;
player.anim = player.animations.right;
isMoving = true;
end
if love.keyboard.isDown("a") then --Move on keypress "a"
player.x = player.x - player.speed;
player.anim = player.animations.left;
isMoving = true;
end
if isMoving == false then
player.anim:gotoFrame(2)
end
player.anim:update(dt);
--[[
if love.keypressed("space") then
player.y = player.y - 20;
love.timer.sleep(1)
player.y = player.y + 20;
end
--]]
end
function love.draw()
player.anim:draw(player.spriteSheet, player.x, player.y, nil, 10);
end
Image of the output bellow:
Since we dont know your Version of LÖVE and...
"Since anim8 uses LÖVE's graphical functions, and they change from version to version, you must choose the version of anim8 which is compatible with your LÖVE."
(https://love2d.org/wiki/anim8)
...i like to suggest that you download one of the Examples depending on your LÖVE Version...
https://love2d.org/forums/viewtopic.php?f=5&t=8281
...try it,...
...rename it to *.zip and unpack it to read/use the main.lua/anim8.lua.
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.
I'm building a simple shooting game on Love2d, everything seems smooth at first, but then after I add the check collision function, I tried to open the game but I got 'not responding' message. So I'm not sure what's the problem here.
I use the collision function taken from love2d forums. It keep giving message that "compare number with nil" and after I put on some game state conditions, it give me 'not responding' massage. Below is my code.
Main.lua
WIDTH = 480
HEIGHT = 800
Class = require 'Class'
require 'Player'
require 'Enemies'
PLAYER_SPEED = 150
BULLET_SPEED = 250
createEnemyTimerMax = 0.4
createEnemyTimer = createEnemyTimerMax
isAlive = true
score = 0
-- called when game starts
-- load images, sounds of the game here
function love.load(arg)
gamestate = 'play'
background = love.graphics.newImage('gfx/milkyway.png')
-- initialize player
player = Player(200, 710)
-- initialize bullet
-- render image to map
bulletimage = love.graphics.newImage('gfx/bullet.png')
-- Entity storage
bullets = {} -- array of current bullets being drawn and updated
enemy = Enemies(math.random(10, 200), math.random(10, 200))
end
function love.update(dt)
-- keypress for shooting
love.keyboard.keysPressed = {}
love.keyboard.keysReleased = {}
-- move the player
if love.keyboard.isDown('left', 'a') then
if player.x > 0 then
player.x = player.x - (PLAYER_SPEED * dt)
end
elseif love.keyboard.isDown('right', 'd') then
if player.x < (love.graphics.getWidth() - player.img:getWidth()) then
player.x = player.x + (PLAYER_SPEED * dt)
end
elseif love.keyboard.isDown('up', 'w') then
if player.y > 0 then
player.y = player.y - (PLAYER_SPEED * dt)
end
elseif love.keyboard.isDown('down', 's') then
if player.y < (love.graphics.getHeight() - player.img:getHeight()) then
player.y = player.y + (PLAYER_SPEED * dt)
end
end
-- reset the game
if gamestate == 'done' and love.keyboard.isDown('r') then
gamestate = 'play'
-- remove all the bullets and enemies from the screen
bullets = {}
enemies = {}
-- reset timers
createEnemyTimer = createEnemyTimerMax
-- move player to default position
player.x = 200
player.y = 710
-- reset gamestate
score = 0
isAlive = true
end
-- keep updating the positions of bullets when shooting
for i, bullet in ipairs(bullets) do
bullet.y = bullet.y - (BULLET_SPEED * dt)
-- remove bullets when they pass off the screen
if bullet.y < 0 then
table.remove(bullets, i)
end
end
Player:update()
Enemies:update(dt)
end
-- global key pressed function
function love.keyboard.wasPressed(key)
if (love.keyboard.keysPressed[key]) then
return true
else
return false
end
end
-- global key released function
function love.keyboard.wasReleased(key)
if (love.keyboard.keysReleased[key]) then
return true
else
return false
end
end
-- called whenever a key is released
function love.keyreleased(key)
love.keyboard.keysReleased[key] = true
end
-- called whenever a key is pressed
function love.keypressed(key)
dt = love.timer.getDelta()
-- to exit the game
if love.keyboard.isDown('escape') then
love.event.quit()
end
-- create bullets when shooting
if love.keyboard.isDown('space') then
newBullet = {x = player.x + (player.img:getWidth() / 2),
y = player.y, img = bulletimage}
table.insert(bullets, newBullet)
end
love.keyboard.keysPressed[key] = true
end
function love.draw(dt)
-- set background image
love.graphics.clear(51/255, 43/255, 68/255, 1)
drawBackground()
-- draw player
if gamestate == 'play' then
player:render()
elseif gamestate == 'done' then
love.graphics.print("Press 'R' to restart", WIDTH / 2 - 50, HEIGHT / 2 - 10)
end
love.graphics.setDefaultFilter('nearest', 'nearest')
-- draw bullets
for i, bullet in ipairs(bullets) do
love.graphics.draw(bulletimage, bullet.x, bullet.y, 3)
end
-- draw enemies
enemy:render()
end
-- background is distributed for free on pixelstalk.net
function drawBackground()
for i = 0, love.graphics.getWidth() / background:getWidth() do
for j = 0, love.graphics.getHeight() / background:getHeight() do
love.graphics.draw(background, i * background:getWidth(), j * background:getHeight())
end
end
end
Enemies.lua
Enemies = Class{}
function Enemies:init(x, y)
self.x = x
self.y = y
enemies = {} -- array of current enemies on the screen
-- render image to map
self.enemyimg = love.graphics.newImage('gfx/enemy.png')
self.width = self.enemyimg:getWidth()
self.height = self.enemyimg:getHeight()
end
function Enemies:update(dt)
createEnemyTimer = createEnemyTimer - (1 * dt)
if createEnemyTimer < 0 then
createEnemyTimer = createEnemyTimerMax
-- create an enemy
randomNumber = math.random(10, love.graphics.getWidth() - 10)
newEnemy = { x = randomNumber, y = -10, img = self.enemyimg}
table.insert(enemies, newEnemy)
end
-- keep updating the positions of enemies
for i, enemy in ipairs(enemies) do
enemy.y = enemy.y + (200 * dt)
-- remove enemies when they pass off the screen
if enemy.y > 850 then
table.remove(enemies, i)
end
end
-- run our collision detection
-- also we need to see if enemies hit our player
while gamestate == 'play' do
for i, enemy in ipairs(enemies) do
for j, bullet in ipairs(bullets) do
if CheckCollision(self.x, self.y, self.width, self.height,
bullet.x, bullet.y, bullet.bulletimage:getWidth(), bullet.bulletimage:getHeight()) then
table.remove(bullets, j)
table.remove(enemies, i)
score = score + 1
end
end
if CheckCollision(self.x, self.y, self.width, self.height,
player.x, player.y, player.width, player.height)
and isAlive == true then
table.remove(enemies, i)
isAlive = false
gamestate = 'done'
end
end
end
end
function Enemies:render()
-- pixel aircrafts created by chabull and
-- distributed for free on OpenGameArt.org
for i, enemy in ipairs(enemies) do
love.graphics.draw(self.enemyimg, self.x, self.y)
end
end
-- function to check collision
-- returns true if 2 objects overlap, false if they don't
-- x1, y1 are left-top coords of the first object, while w1, h1 are its width and height
-- x2, y2, w2, h2 are the same, but for the second object
function CheckCollision(x1, y1, w1, h1, x2, y2, w2, h2)
if x1 < x2 + w2 and x2 < x1 + w1 and y1 < y2 + h2 and y2 < y1 + h1 then
return true
else
return false
end
end
I'm not a Love2d expert but Enemies.update is probably called every frame. Running a while loop with a condition gamestate == 'play' that most likely is true all the time in that function looks problematic to me.
You're basically trapped in an infinite loop instead of updating your game state.
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
I'm totally new to Lua and Love2D and probably do not understand the concepts at all.
Well this is a Love2D tutorial, and I want to change it so when I press "a", for example, on the keyboard, the object will exchange (from hamster to car) and so on.
Can you help me out?
-- Tutorial 1: Hamster Ball
-- Add an image to the game and move it around using
-- the arrow keys.
-- compatible with löve 0.6.0 and up
function love.load()
hamster = love.graphics.newImage("hamster.png")
auto = love.graphics.newImage("auto.png")
x = 50
y = 50
speed = 300
end
function love.update(dt)
if love.keyboard.isDown("right") then
x = x + (speed * dt)
end
if love.keyboard.isDown("left") then
x = x - (speed * dt)
end
if love.keyboard.isDown("down") then
y = y + (speed * dt)
end
if love.keyboard.isDown("up") then
y = y - (speed * dt)
end
if love.keyboard.isDown("escape") then
love.event.quit()
end
if love.keyboard.isDown("a") then
love.draw(auto,x,y)
end
end
function love.draw()
love.graphics.draw(hamster, x, y)
end
Well thanks Corbin, i figured it out without "state" local variable. Your solution was inspiring to me. Now it's working.
-- Tutorial 1: Hamster Ball
-- Add an image to the game and move it around using
-- the arrow keys.
-- compatible with löve 0.6.0 and up
function love.load()
hamster = love.graphics.newImage("hamster.png")
auto = love.graphics.newImage("auto.png")
activeImage = hamster
activeImageName = "hamster"
x = 50
y = 50
speed = 300
end
function love.update(dt)
if love.keyboard.isDown("right") then
x = x + (speed * dt)
end
if love.keyboard.isDown("left") then
x = x - (speed * dt)
end
if love.keyboard.isDown("down") then
y = y + (speed * dt)
end
if love.keyboard.isDown("up") then
y = y - (speed * dt)
end
if love.keyboard.isDown("escape") then
love.event.quit()
end
if love.keyboard.isDown("a") then
activeImage = auto
activeImageName = "auto"
end
if love.keyboard.isDown("h") then
activeImage = hamster
activeImageName = "hamster"
end
end
function love.draw()
love.graphics.draw(activeImage, x, y)
end
I'd suggest using love.update to only update state. Don't draw in it. Then do all of your drawing in love.draw. A solution might be:
local state = {}
function love.load()
hamster = love.graphics.newImage("hamster.png")
auto = love.graphics.newImage("auto.png")
state.activeImage = hamster
state.activeImageName = "hamster"
-- <snip> ...
end
function love.update(dt)
-- <snip> ...
if love.keyboard.isDown("a") then
if state.activeImageName == "hamster" then
state.activeImage = auto
state.activeImageName = "auto"
else
state.activeImage = hamster
state.activeImageName = "hamster"
end
end
end
function love.draw()
love.graphics.draw(state.activeImage, x, y)
end
This is probably not the best way to solve this, but it works - create an object which has an X value, a Y value, a speed value, and an IMG value. Set the X and Y to 50 and 50, the speed to 300, and set the IMG to nil. In the load function, set the IMG value to whichever image you would prefer it to start as. In the update function, check for a key press and when the key is pressed change the IMG value to the new image.
An example script for clarification:
player = {X = 50, Y = 50, speed = 300, IMG = nil}
function love.load()
hamster = love.graphics.newImage('hamster.png')
auto = love.graphics.newImage('auto.png')
player.IMG = hamster
end
function love.update(dt)
if love.keyboard.isDown('d') then
player.x = player.x + player.speed
elseif love.keyboard.isDown('a') then
player.x = player.x - player.speed
end
if love.keyboard.isDown('w') then
player.y = player.y + player.speed
elseif love.keyboard.isDown('s') then
player.y = player.y = player.speed
end
if love.keyboard.isDown('space') then
if player.IMG == hamster then
player.IMG = auto
else
player.IMG = hamster
end
end
function love.draw()
love.graphics.draw(player.IMG, player.X, player.Y)
end
Hopefully this helps!