corona and appwarp moving hero in multiplayer - lua

I am trying to move my hero in a multiplayer setup to the left and right.
I have to squares to initiate move left and move right for a regular crircle on a ground.
I am using AppWarp to initate the multiplayer instance and that is working fine, however I am having trouble on how to communicate the moving of the circle.
Here is my lua:
-- When left arrow is touched, move character left
function left:touch()
motionx = -speed;
end
left:addEventListener("touch",left)
-- When right arrow is touched, move character right
function right:touch()
motionx = speed;
end
right:addEventListener("touch",right)
-- Move character
local function movePlayer (event)
appWarpClient.sendUpdatePeers(tostring(player.x))
end
Runtime:addEventListener("enterFrame", movePlayer)
-- Stop character movement when no arrow is pushed
local function stop (event)
if event.phase =="ended" then
motionx = 0;
end
The keyline here is
appWarpClient.sendUpdatePeers(tostring(player.x))
with this I send the current X position of my hero (the circle) and in my warplisteners I pick it up like so:
function onUpdatePeersReceived(update)
local func = string.gmatch(update, "%S+")
-- extract the sent values which are space delimited
--local id = tostring(func())
local x = func()
statusText.text = x
player.x = x + motionx
end
When I start the game on 2 clients I can start moving the ball but it is wobbeling back and forth between 62 units, wich i guess is my speed
speed = 6; -- Set Walking Speed
if I change this:
function onUpdatePeersReceived(update)
local func = string.gmatch(update, "%S+")
-- extract the sent values which are space delimited
--local id = tostring(func())
local x = func()
statusText.text = x
player.x = x + motionx
end
to this:
function onUpdatePeersReceived(update)
local func = string.gmatch(update, "%S+")
-- extract the sent values which are space delimited
--local id = tostring(func())
local x = func()
statusText.text = x
player.x = player.x + motionx
end
(last line before "end")
player.x = player.x + motionx
instead of
player.x = x + motionx
The coordinates gets updated but the hero only moves on one of the screens.
Any idea how to implement a better movement system that moves my hero on both clients at the same time?
Kind regards
edit:
Added if-else, it was pending between +-speed and 0 since the speed is 0 when hero is stopped.
if(motionx ~= "0") then
player.x = player.x + motionx
statusText.text = "motionx ~= 0"
elseif(motionx == "0") then
player.x = player.x
else
statusText.text ="Something went horribly wrong"
end

Related

How to make love2d game compatible

I am getting the message "This game indicates it was made for version '0.9.1' of LOVE.
It may not be compatible with the running version (0.10.2)." when I try and run my game. The game still works but the message is annoying me. How do I update it to the latest version? My code is here:
debug = true
Main.lua
-- Timers
-- We declare these here so we don't have to edit them multiple places
canShoot = true
canShootTimerMax = 0.2
canShootTimer = canShootTimerMax
createEnemyTimerMax = 0.4
createEnemyTimer = createEnemyTimerMax
-- Player Object
player = { x = 200, y = 710, speed = 150, img = nil }
isAlive = true
score = 0
-- Image Storage
bulletImg = nil
enemyImg = nil
-- Entity Storage
bullets = {} -- array of current bullets being drawn and updated
enemies = {} -- array of current enemies on screen
-- Collision detection taken function from http://love2d.org/wiki/BoundingBox.lua
-- Returns true if two boxes overlap, false if they don't
-- x1,y1 are the left-top coords of the first box, while w1,h1 are its width and height
-- x2,y2,w2 & h2 are the same, but for the second box
function CheckCollision(x1,y1,w1,h1, x2,y2,w2,h2)
return x1 < x2+w2 and
x2 < x1+w1 and
y1 < y2+h2 and
y2 < y1+h1
end
-- Loading
function love.load(arg)
player.img = love.graphics.newImage('assets/plane.png')
enemyImg = love.graphics.newImage('assets/enemy.png')
bulletImg = love.graphics.newImage('assets/bullet.png')
end
-- Updating
function love.update(dt)
-- I always start with an easy way to exit the game
if love.keyboard.isDown('escape') then
love.event.push('quit')
end
-- Time out how far apart our shots can be.
canShootTimer = canShootTimer - (1 * dt)
if canShootTimer < 0 then
canShoot = true
end
-- Time out enemy creation
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 = enemyImg }
table.insert(enemies, newEnemy)
end
-- update the positions of bullets
for i, bullet in ipairs(bullets) do
bullet.y = bullet.y - (250 * dt)
if bullet.y < 0 then -- remove bullets when they pass off the screen
table.remove(bullets, i)
end
end
-- update the positions of enemies
for i, enemy in ipairs(enemies) do
enemy.y = enemy.y + (200 * dt)
if enemy.y > 850 then -- remove enemies when they pass off the screen
table.remove(enemies, i)
end
end
-- run our collision detection
-- Since there will be fewer enemies on screen than bullets we'll loop them first
-- Also, we need to see if the enemies hit our player
for i, enemy in ipairs(enemies) do
for j, bullet in ipairs(bullets) do
if CheckCollision(enemy.x, enemy.y, enemy.img:getWidth(), enemy.img:getHeight(), bullet.x, bullet.y, bullet.img:getWidth(), bullet.img:getHeight()) then
table.remove(bullets, j)
table.remove(enemies, i)
score = score + 1
end
end
if CheckCollision(enemy.x, enemy.y, enemy.img:getWidth(), enemy.img:getHeight(), player.x, player.y, player.img:getWidth(), player.img:getHeight())
and isAlive then
table.remove(enemies, i)
isAlive = false
end
end
if love.keyboard.isDown('left','a') then
if player.x > 0 then -- binds us to the map
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
end
if love.keyboard.isDown(' ', 'rctrl', 'lctrl', 'ctrl') and canShoot then
-- Create some bullets
newBullet = { x = player.x + (player.img:getWidth()/2), y = player.y, img = bulletImg }
table.insert(bullets, newBullet)
canShoot = false
canShootTimer = canShootTimerMax
end
if not isAlive and love.keyboard.isDown('r') then
-- remove all our bullets and enemies from screen
bullets = {}
enemies = {}
-- reset timers
canShootTimer = canShootTimerMax
createEnemyTimer = createEnemyTimerMax
-- move player back to default position
player.x = 50
player.y = 710
-- reset our game state
score = 0
isAlive = true
end
end
-- Drawing
function love.draw(dt)
for i, bullet in ipairs(bullets) do
love.graphics.draw(bullet.img, bullet.x, bullet.y)
end
for i, enemy in ipairs(enemies) do
love.graphics.draw(enemy.img, enemy.x, enemy.y)
end
love.graphics.setColor(255, 255, 255)
love.graphics.print("SCORE: " .. tostring(score), 400, 10)
if isAlive then
love.graphics.draw(player.img, player.x, player.y)
else
love.graphics.print("Press 'R' to restart", love.graphics:getWidth()/2-50, love.graphics:getHeight()/2-10)
end
if debug then
fps = tostring(love.timer.getFPS())
love.graphics.print("Current FPS: "..fps, 9, 10)
end
end
conf.lua
-- Configuration
function love.conf(t)
t.title = "Scrolling Shooter Tutorial" -- The title of the window the game is in (string)
t.version = "0.9.1" -- The LÖVE version this game was made for (string)
t.window.width = 480 -- we want our game to be long and thin.
t.window.height = 800
-- For Windows debugging
t.console = true
end
As noted in the comments, the problem in your case was that, in conf.lua, the version was specified as "0.9.1". In some cases, changing this value to "0.10.2" is sufficient, but a significant amount of changes occurred between 0.9.0 and 0.10.0.
Be especially aware that mouse input is definitely going to be broken because, in versions before 0.10.0, LOVE used strings to represent mouse buttons, whereas in 0.10.0 and beyond, numbers are used. To fix this, look for mouse-related functions (love.mouse.isDown, love.mousepressed, etc.) and change "l" to 1, "r" to 2, and so on. See the full list of old values and love.mousepressed for more. Additionally, mousewheel movement changed as well, with the addition of the love.wheelmoved callback and removing the strings passed to love.mousepressed.
Additionally, read through the changelog for any changes that may have affected your program.

Shooting object until the end of the screen not just until cursor position

local function shoot( event )
local x, y = event.x, event.y
rotateShip(x, y)
local laser = display.newImage("Images/laser.png")
laser.x = player.x
laser.y = player.y
transition.to(laser, {time=300, x=x, y=y, onComplete=shotDone})
end
^ That is my code so far. It shoots the object until it reaches the click position. What I want it to do is continue on past the click until it reaches the edge of the screen. I already have the angle of the shot stored in a variable that for the sake of this we will call "shotAngle"
Any help would be greatly appreciated!
Liv :)
Okey, so first of all: you should not do this movement with transition.to(). As I assume you make a game where you can shoot laser projectiles. Way easier would be moving all of the projectiles you have currently in game by velocity*dt (in their current moving direction) where dt is amount of time passed since last frame. Then you can just check if they are out of playground and delete them if yes. But if you really want to do it this way...
Oh boy, here we go!
local function shoot(event)
local width, height -- Size of playground
local ex, ey = event.x, event.y -- Where player have clicked/tapped/etc
local px, py = player.x, player.y -- Current position of player
local speed -- Projectile speed in [pixels per milisecond]
-- Our laser projectile
local laser = display.newImage("Images/laser.png")
laser.x, laser.y = player.x, player.y
-- Borders: bx, by
local bx, by = width, height
if ex < px then
bx = 0
end
if ey < py then
by = 0
end
-- Let's get our target coordinates
local tx, ty = bx
ty = ((py-ey)/(px-ex))*bx+py-((py-ey)/(px-ex))*px
if ty > height or ty < 0 then
ty = by
tx = (by-py+((py-ey)/(px-ex))*px)/((py-ey)/(px-ex))
end
-- Let's get animation time now!
local distance = math.sqrt((tx-px)*(tx-px)+(ty-py)*(ty-py))
local time = distance/speed
-- Now, just shoot
transition.to(laser, {time=time, x=tx, y=ty, onComplete=shotDone})
end

How to stop an object from moving past a point

I was wondering if there was a way to stop an object from moving off the screen. In my code, I have a controllable character (player) and I want to prevent it from moving to the left when it's x coordinate is < 1
I have tried to do this in the code below, however, the player will not be stopped if you hold down the left arrow key.
Is there a way to fix this? If I had a guess, I would somehow need my program to continuously check for the case where player.x < 1
motionx = 0; -- Variable used to move character along x axis
speed = 10; -- Set Walking Speed
local function moveplayer (event)
player.x = player.x + motionx;
end
Runtime:addEventListener("enterFrame", moveplayer)
local function onKeyEvent( event )
if ( event.phase == "down" ) then
if ( event.keyName == "left" ) and player.x > 1 then
motionx = -speed
return true
elseif ( event.keyName == "right" ) then
motionx = speed
return true
end
end
end
Runtime:addEventListener( "key", onKeyEvent )
You need to check the boundaries and set the motionx to zero:
local player = display.newCircle(display.contentCenterX, display.contentCenterY, 10)
local motionx = 0; -- Variable used to move character along x axis
local speed = 10; -- Set Walking Speed
local function moveplayer( event )
player.x = player.x + motionx;
if player.x < 0 then
player.x = 0
motionx = 0
elseif player.x > display.contentWidth then
player.x = display.contentWidth
motionx = 0
end
end
Runtime:addEventListener( "enterFrame", moveplayer )
local function onKeyEvent( event )
if event.phase == "down" then
if event.keyName == "left" then
motionx = -speed
return true
elseif event.keyName == "right" then
motionx = speed
return true
end
end
end
Runtime:addEventListener( "key", onKeyEvent )
Simply implement a function that checks your objects position vs your screen boundaries. Whenever it reaches the border of your screen you stop it.
To check your objects position for every frame add your function as an event listener for the event "enterFrame".
Read this for details:
https://docs.coronalabs.com/guide/events/detectEvents/index.html
Of course you can also use the collision engine by placing invisible walls around your screen so your object will bounce back whenever it hits the border.
You were fairly close but may need your whole code to test it. I only changed this player.x < 1 and moved )
motionx = 0; -- Variable used to move character along x axis
speed = 10; -- Set Walking Speed
local function moveplayer (event)
player.x = player.x + motionx;
end
Runtime:addEventListener("enterFrame", moveplayer)
local function onKeyEvent( event )
if ( event.phase == "down" ) then
if ( event.keyName == "left" and player.x < 1) then
motionx = -speed
return true
elseif ( event.keyName == "right" ) then
motionx = speed
return true
end
end
end
Runtime:addEventListener( "key", onKeyEvent )

How to fire a bullet in the direction of finger swipe in corona sdk

I am working on a game in corona. I want to fire a bullet when a user swipes their finger on an object. The further he swipes, the further the the bullet should go. I worked on this and on tap event the bullet is fired, there are two functions start projectile and game loop, start projectile is used to fire projectile and game loop is used to translate the weapon, but I can't understand how to aim for the target using finger swipe. Please give me any suggestions, thanks...
Code for what has been achieved so far is below
local function startprojectile(event)
gameIsActive=true
local firetimer
local getobj=event.target
local getxloc=getobj.x
local getyloc=getobj.y
local function firenow()
if gameIsActive=false then
timer.cancel(firetimer)
firetimer=nil
else
local bullet=display.newImageRect("object.png",50,60);
bullet.x=getxloc-50; bullet.y=getyloc-50
bullet.type=bullet1
physics.addBody(bullet,{isSensor=true})
weaponGroup:insert(bullet)
end
gameIsActive=false
end
firetimer.timer.performWithDelay(650,firenow)
end
local function gameloop()
local i
for i=weaponGroup.numChildren,1,-1 do
local weapon=weaponGroup[i]
if weapon ~=nil and weapon.x ~=nil
then
weapon:translate(-20,0)
end
end
You can get the angle that the bullet should be fired by using the built in lua function
startX, startY = player.x, player.y
dir = math.atan2(( swipeY - player.y ), ( swipeX - player.x ))
bulletDx = bullet.speed * math.cos(dir)
bulletDy = bullet.speed * math.sin(dir)
table.insert( bullet, { x = startX, y = startY, dx = bulletDx, dy = bulletDy } )
You can change the variable from swipe Y to whatever Corona uses (I don't code with it).
I'm assuming you know how to move the bullet, but if not,
for i, v in ipairs( bullet ) do
bullet.x = bullet.x + bullet.dx * dt
bullet.y = bullet.y + bullet.dy * dt
end

Make an object rotate to angle of tilt with accelerometer in CoronaSDK?

with my first game I have a doodle I control with the accelerometer. In many games I've seen that when the device is titled the object (in my case a doodle fish) rotate towards the tilt so it gives an illusion the "fish" swim down and if the device is tilted up and down the "fish" swims up and down.
How do I write that in lua when working with Corona SDK?
Here is my code for moving the doodle so far;
display.setStatusBar(display.HiddenStatusBar)
system.setAccelerometerInterval( 50 )
_W = display.contentWidth
_H = display.contentHeight
local bg = display.newImageRect("images/bg.png", 480, 320)
bg:setReferencePoint(display.CenterReferencePoint)
bg.x = _W/2
bg.y = _H/2
local player = display.newImageRect("images/doodle.png", 128, 64)
player:setReferencePoint(display.CenterReferencePoint)
player.x = _W/2
player.y = _H/2
-- Set up the Accelerometer values in Landscape
local motionX = 0
local motionY = 0
local function onAccelerate( event )
motionX = 10 * event.yGravity;
motionY = 10 * event.xGravity;
end
Runtime:addEventListener ("accelerometer", onAccelerate);
-- Make the player move on tilt.
local function movePlayer (event)
player.x = player.x + motionX;
player.y = player.y + motionY;
end
Runtime:addEventListener("enterFrame", movePlayer)
local function screenBoundaries (event)
-- Left side boundaries
if player.x < 0 + player.width/2 then
player.x = 0 + player.width/2
end
-- Right side boundaries
if player.x > display.contentWidth - player.width/2 then
player.x = display.contentWidth - player.width/2
end
-- Upper boundaries
if player.y < 0 + player.height/2 then
player.y = 0 + player.height/2
end
-- Lower boundaries
if player.y > display.contentHeight - player.height/2 then
player.y = display.contentHeight - player.height/2
end
end
Runtime:addEventListener("enterFrame", screenBoundaries)
EDIT;
I've tried to make the player rotate to tilt but it's not working, it doesn't return any errors when I run it in the simulator, what am I doing wrong?
Basically what I want to do is when the accelerometer y value increase/decrease the player(fish) swim up and down but I only want it to tilt moderately (0 to +/- 45 degrees) or what ever seems realistic. Perhaps 25 -35 degrees is optimal?
My math is not up to date so I apologize for that, can someone please help me with this?
display.setStatusBar(display.HiddenStatusBar)
system.setAccelerometerInterval( 50 )
_W = display.contentWidth
_H = display.contentHeight
local ceil = math.ceil
local pi = math.pi
local atan2 = math.atan2
local playerRotation
-- Put the doodle fish in the center if the screen.
local player = display.newImageRect("images/doodle.png", 128, 64)
player:setReferencePoint(display.CenterReferencePoint)
player.x = _W/2
player.y = _H/2
-- My rotation function, not sure how to do it right.
local function getPlayerRotationAngle(xGravity, yGravity)
angle = math.atan2(xGravity, yGravity)
angle = angle*(180/pi)
playerRotate = ceil(360 - angle(xGravity, yGravity))
return playerRotate
end
-- Set up the Accelerometer values in Landscape
local motionX = 0
local motionY = 0
local function onAccelerate( event )
motionX = 5 * event.yGravity;
motionY = 5 * event.xGravity;
-- Should I put the rotation here or down in the movePlayer function?
player.rotation = playerRotate(event.yGravity, event.xGravity);
end
Runtime:addEventListener ("accelerometer", onAccelerate);
-- Make the player move on tilt.
function movePlayer (event)
player.x = player.x + motionX
player.y = player.y + motionY
end
Runtime:addEventListener("enterFrame", movePlayer)
Your overall code looks good.
Several games I did use something similar.
What jumps out is you mentioning
I've tried to make the player rotate to tilt but it's not working, it doesn't return any errors when I run it in the simulator, what am I doing wrong?
Are you actually running the code on a device?
The Corona SDK simulator does not support simulation for the accelerometer so the event will never fire.
If you are running on the device, include the Crawl Space Library.
This will allow you to print() any form of data including tables.
Then add
print(event)
to your onAccelerate() function, hook your device up to your development machine and watch the console for the data you actually receive. (Assuming you're developing for iOS using a Mac, use iPhone Configuration Utility to get the data). Then debug from there.
Include
io.output():setvbuf("no")
at the beginning of your main.lua to disable console output caching on the device first. Otherwise the console output of your device will be buffered and hard to debug.

Resources