I am having an annoying bug with my character movement animations. That bug is, that whenever I run the code, the animation only works for the 'W' key. (The movement is WASD.) I don't get any compilation errors and I am using Love2D 0.10.1
Here is the movement handler function
function player.move(dt)
if love.keyboard.isDown("d") and
player.xvel < player.speed then
player.xvel = player.xvel + player.speed * dt
player.image = love.graphics.newImage("images/player/walk1.png")
else
player.image = love.graphics.newImage("images/player/static.png")
end
if love.keyboard.isDown("a") and
player.xvel > -player.speed then
player.xvel = player.xvel - player.speed * dt
player.image = love.graphics.newImage("images/player/walk1.png")
else
player.image = love.graphics.newImage("images/player/static.png")
end
if love.keyboard.isDown("s") and
player.yvel < player.speed then
player.yvel = player.yvel + player.speed * dt
player.image = love.graphics.newImage("images/player/walk1.png")
else
player.image = love.graphics.newImage("images/player/static.png")
end
if love.keyboard.isDown("w") and
player.yvel > -player.speed then
player.yvel = player.yvel - player.speed * dt
player.image = love.graphics.newImage("images/player/walk1.png")
else
player.image = love.graphics.newImage("images/player/static.png")
end
end
Anything helps! Oh, and also, if anyone knows how to make it to where it goes to a certain frame every x amount of seconds, that's be great! Thanks!
One solution I could propose for the problem with animation would be to use if only at the key d, and elseif on the other cases. The problem is caused by the fact that if any other key is pressed, but w isn't, then the
if love.keyboard.isDown("w") and
player.yvel > -player.speed then
player.yvel = player.yvel - player.speed * dt
player.image = love.graphics.newImage("images/player/walk1.png")
else
player.image = love.graphics.newImage("images/player/static.png")
end
switch enters the else part, because w is not down, and in the else part it sets the image to static.png.
Here you can read about the if-elseif-else-end control structure of Lua:
http://www.lua.org/pil/4.3.1.html
http://www.tutorialspoint.com/lua/if_else_statement_in_lua.htm
Be careful with the fact that some languages use it as else if, but in Lua there is no space between, so it is written like elseif.
Related
I can't get my character to move backward or forwards- but left and right work perfectly fine! The inputs in the project are fine, there's nothing crazy I did with the physics on the rigidbody, I just can't seem to figure out the issue.
Portion of code pertaining to movement:
if (Input.GetAxis("Horizontal") > 0 || Input.GetAxis("Horizontal") < 0) {
gameObject.transform.GetComponent<Rigidbody>().MovePosition(gameObject.transform.position + (gameObject.transform.right * Input.GetAxis("Horizontal") * 10 * hSpeedMult * Time.deltaTime));
posAt = gameObject.transform.position;
}
else {
gameObject.transform.position = new Vector3(posAt.x, gameObject.transform.position.y, posAt.z);
}
if (Input.GetAxis("Vertical") > 0 || Input.GetAxis("Vertical") < 0) {
gameObject.transform.GetComponent<Rigidbody>().MovePosition(gameObject.transform.position + (gameObject.transform.forward * Input.GetAxis("Vertical") * 10 * vSpeedMult * Time.deltaTime));
posAt = gameObject.transform.position;
}
else {
gameObject.transform.position = new Vector3(posAt.x, gameObject.transform.position.y, posAt.z);
}
The "posAt" is just used to make sure the player cannot move when no controls are pressed.
Once I removed the "position freezer", it did the trick. My "PosAt" lines were the problem.
I have recently been familiar with lua in LOVE 2D and watched some tutorials and now am trying to make a simple game. The game will feature a character who can run and when pressed 'space', attack(strike with his sword). When pressed 'space', it should go through all the frames/sprites of attacking animation. But the character is not going through all the frames and the interval between them seems really fast even though I kept it minimum.
This is the code I am using to account for the key pressing.
self.animations = {
['idle'] = Animation{
frames = {
self.frames[1]
},
interval = 1
},
['attack'] = Animation{
frames = {
self.frames[1], self.frames[2], self.frames[3], self.frames[4], self.frames[5], self.frames[6], self.frames[3]
},
interval = 0.25
}
}
self.animation = self.animations['idle']
self.currentFrame = self.animation:getCurrentFrame()
self.behaviors = {
['idle'] = function(dt)
if love.keyboard.wasPressed('space') then
self.dy = 0
self.state = 'attack'
self.animation = self.animations['attack']
elseif love.keyboard.wasPressed('up') then
self.dy = -MOVE_DIST
elseif love.keyboard.wasPressed('down') then
self.dy = MOVE_DIST
else
self.dy = 0
end
end,
['attack'] = function(dt)
self.animation = self.animations['attack']
if love.keyboard.wasPressed('up') then
self.dy = -MOVE_DIST
elseif love.keyboard.wasPressed('down') then
self.dy = MOVE_DIST
else
self.dy = 0
self.state = 'idle'
self.animation = self.animations['idle']
end
end
This is my animation class that's responsible for transition effects
Animation = Class{}
function Animation:init(params)
--self.texture = params.texture
self.frames = params.frames
self.interval = params.interval or 0.05
self.timer = 0
self.currentFrame = 1
end
function Animation:getCurrentFrame()
return self.frames[self.currentFrame]
end
function Animation:restart()
self.timer = 0
self.currentFrame = 1
end
function Animation:update(dt)
self.timer = self.timer + dt
if #self.frames == 1 then
return self.currentFrame
else
while self.timer > self.interval do
self.timer = self.timer - self.interval
self.currentFrame = (self.currentFrame + 1) % (#self.frames + 1)
if self.currentFrame == 0 then
self.currentFrame = 1
end
end
end
end
Please help. I hope I asked the question correctly. Thanks in advance.
Don't really know how you deal with the state in the key pressing code but this could be part of the issue too.
Anyway, your Animation:update looks very weird to me and I really think this is the center of the problem. There is a simple function that you could use instead and it should work perfectly (if you have any question about it feel free to ask).
If your not really comfortable with a debugger you could use love.graphics.print to print some value to the screen (like self.currentFrame or self.timer in that case) to see what's going on with those value in real time.
function Animation:update(dt)
self.timer = self.timer + dt/self.interval
if self.timer >= #self.frames then
self.timer = 0
end
self.currentFrame = Math.floor(self.timer)+1
end
Also note that "Math.floor(self.timer)+1" cannot be replaced by "Math.ceil(self.timer)" because it will return 0 if self.timer == 0 (and lua's array starts at one)
Edit:
It could probably come from here:
['attack'] = function(dt)
self.animation = self.animations['attack']
if love.keyboard.wasPressed('up') then
self.dy = -MOVE_DIST
elseif love.keyboard.wasPressed('down') then
self.dy = MOVE_DIST
else
self.dy = 0
self.state = 'idle'
self.animation = self.animations['idle']
end
end
I don't know how you deal with your inputs since 'love.keyboard.wasPressed' if not a love function but if 'up' and 'down' where not pressed the last frame, the state will go back to 'idle' and the animation to animations['idle']
Without more code I cannot do much more for you.
I need to calculate the total job experience as year value. Users add experiences with starting and ending dates to their resumes, just like Linkedin. But there is no any certain pattern. For instance;
A user may have a resume like that;
Experience 2
08.2012 - 01.2015
Experience 1
01.2011 - 01.2013
The user started their second experience while the first hasn't finished yet. So resumes may have many overlapping experiences. Overlapping also may occur between more than 2. So I need to consider many cases.
I tried to visualise the experience and year relationship for you.
I just need to develop an algorithm covering all the cases for this issue.
Sort by start date
start at the beginning and accumulate overlapping experiences (i.e. treat as one)
e.g. (Jan 2012, Jan 2015), (Jan 2014, Dec 2016) overlap, so we treat it as a single experience
This "super experience" begins at the start of the first, and ends at the end of the last; (Jan 2012, Dec 2016)
This is assuming that there can be gaps in experience, so we don't want to treat the entire history as one long "super experience"
I just did this
Sort the experiences by Begin Date.
Use 2 variables, that represent the begin of work and the end called Begin
and End.
If end and begin are empty it means that is the first date, we filled with the first experience, and we calculate the month count between the begin and end of this experience and and then this months count add to our months accumulator.
if the end and begin date of next experience is not between our begin and end variables, we calculate the months count from the experience and then add it to our accumulator.
If the begin date of next experience is between our begin and end variables, we calculate the months count between our end date as begin and the experience end date as end, and then that difference add to our months accumulator.
as you can see every time we set our new end if the experience end is greater than ours.
at the end we get the months, if you divide by 12 you get the years exactly you can round it if you want
NOTE: I Mapped the experiences, if not have End it means that is equivalent to NOW
you can see all the code below
function monthDiff(d1, d2) {
var m = (d1.getFullYear() - d2.getFullYear()) * 12 +
(d1.getMonth() - d2.getMonth());
if (d1.getDate() < d2.getDate()) --m;
return m;
}
function dateCheck(from, to, check) {
var fDate, lDate, cDate;
fDate = Date.parse(from);
lDate = Date.parse(to);
cDate = Date.parse(check);
if (cDate <= lDate && cDate >= fDate) {
return true;
}
return false;
}
function calculateYearsOfExperience(experiences) {
if (!experiences) return 0;
let months = 0;
let now = new Date();
let sorted = experiences
.sort((a, b) => {
return new Date(a.begin) - new Date(b.begin);
})
.map(experience => {
if (!experience.end) experience.end = now;
return { begin: experience.begin, end: experience.end };
});
let begin;
let end;
for (var i in sorted) {
let dif = 0;
if (!end && !begin) {
dif = monthDiff(sorted[i].begin, sorted[i].end);
begin = sorted[i].begin;
end = sorted[i].end;
} else if (
!dateCheck(begin, end, sorted[i].begin) &&
!dateCheck(begin, end, sorted[i].end)
) {
dif = monthDiff(sorted[i].begin, sorted[i].end);
end = sorted[i].end;
} else if (dateCheck(begin, end, sorted[i].begin)) {
dif = monthDiff(end, sorted[i].end);
end = sorted[i].end;
}
months += dif;
}
return months / 12;
}
experiences = [
# (start date, end date),
(date(2012, 8, 1), date(2015, 1, 30)),
(date(2011, 1, 1), date(2013, 1, 30))
]
print(sum((end_date - start_date).days/365 for start_date, end_date in experiences))
Create an array full of 0. Element range: Start would be the very first hire date, last would be current date / last working date. For every year you have 12 elements that can be 0/1. After filling in the array count the elements that have the value 1. If you need to take into account the overlapping then ignore the 0/1 part and give +1 for every month worked.
This is c# code, but you'll get the steps in algorithm. It returns total number of months which you can convert into year and month format.
var sortedList = expList
.OrderBy(a => a.start_year)
.ThenBy(a => a.start_month)
.ThenBy(a => a.end_year)
.ThenBy(a => a.end_month)
.ToList();
int totalMonths = 0;
int totalDays = 0;
DateTime? prevEndDate = null;
foreach (var exp in sortedList)
{
if(exp.start_month != null && exp.start_year != null)
{
var startDate = new DateTime((int)exp.start_year, (int)exp.start_month, 1);
var endDate = (bool)exp.is_present ?
DateTime.Now :
new DateTime((int)exp.end_year, (int)exp.end_month, 1);
if (prevEndDate != null && prevEndDate > startDate)
{
startDate = (DateTime)prevEndDate;
}
var timespan = endDate.Subtract(startDate);
var tempdate = DateTime.MinValue + timespan;
totalMonths = totalMonths + (tempdate.Year - 1) * 12 + tempdate.Month - 1;
totalDays = totalDays + tempdate.Day - 1;
prevEndDate = endDate;
}
}
if (totalDays > 0)
{
totalMonths = totalMonths + 1;
}
public static function YearCalculation($id=null) {
if($id=="")
$employee_id=#Auth::guard('web_employee')->user()->id;
else
$employee_id=$id;
$employee_exp = Experience::where('employee_id',$employee_id)->orderBy("experience_from","ASC")->get();
//print_r($employee_exp ); exit;
$years = 0;
$months = 0;
$days = 0;
$sum=0;
$lastfromdate=0;
$last_endDate=0;
if(#$employee_exp!=null){
foreach(#$employee_exp as $experience){
$fdate = #$experience->experience_from;
if($experience->is_current==0){
$tdate = #$experience->experience_to;
}else{
$tdate = date("Y-m-d");
}
if($last_endDate != date("Y-m-d") ){
if( $fdate < $last_endDate ){
$start_date1 = strtotime($last_endDate);
$end_date1 = strtotime($tdate);
$interval1 = ($end_date1 - $start_date1)/60/60/24;
$sum +=$interval1;
}
else{
$start_date2 = strtotime($fdate);
$end_date2 = strtotime($tdate);
$interval2 = ($end_date2 - $start_date2)/60/60/24;
$sum +=$interval2;
}
if($last_endDate < $tdate){
$last_endDate=$tdate;
}
}
}
$years = ($sum / 365) ;
$years = floor($years);
$month = ($sum % 365) / 30.4166;
$month = floor($month);
$days = ($sum % 365) % 30.4166;
//$total=date_diff(0,$tmstamp);
//$total_year=$years.' years, ' .$month.' months and '.$days.($days==1?' day':' days');
$total_year=($years==0?'':($years==1?$years.' year':$years.' years and ')) .($month==0?'':($month==1?$month.($days>1?'+':'').' month':$month.($days>1?'+':'').' months'));
return $total_year;
}
}
I've been using the YouMax plugin which enables you to embed your YouTube channel on your website. However, I am having problems as it displays the uploaded date in months and years. I'd like it to display days, weeks, months and years.
You can view the source code here http://jsfiddle.net/wCKKU/
I believe that its this that needs adjusting to make it calculate in day, weeks, months and years.
function getDateDiff(timestamp) {
if (null == timestamp || timestamp == "" || timestamp == "undefined") return "?";
var splitDate = ((timestamp.toString().split('T'))[0]).split('-');
var d1 = new Date();
var d1Y = d1.getFullYear();
var d2Y = parseInt(splitDate[0], 10);
var d1M = d1.getMonth();
var d2M = parseInt(splitDate[1], 10);
var diffInMonths = (d1M + 12 * d1Y) - (d2M + 12 * d2Y);
if (diffInMonths <= 1) return "1 month";
else if (diffInMonths < 12) return diffInMonths + " months";
var diffInYears = Math.floor(diffInMonths / 12);
if (diffInYears <= 1) return "1 year";
else if (diffInYears < 12) return diffInYears + " years"
}
You could modify the plugin by a small block of code in the middle of the function:
var d2M = parseInt(splitDate[1], 10); // this line is already there
var d1D = d1.getDate();
var d2D = parseInt(splitDate[2],10);
var diffInDays = (d1D + 30 *d1M + 12 * d1Y) - (d2D + 30 *d2M + 12 *d2Y);
if (diffInDays < 2) return "1 day";
else if (diffInDays < 7) return diffInDays+" days";
else if (diffInDays > 7 && diffInDays < 14) return "1 week";
else if (diffInDays > 14 && diffInDays < 30) return Math.floor(diffInDays / 7) + " weeks";
var diffInMonths = (d1M + 12 * d1Y) - (d2M + 12 * d2Y); // this line is already there
Note that this isn't a particularly elegant way to handle the issue, but it matches the coding style the plugin is already using, and at least won't break anything else.
Also, as a side comment, if you're modifying the plugin code you'll want to fix a bug in it at the same time. Getting the current month should look like this:
var d1M = d1.getMonth() + 1;
This is because in Javascript, the getMonth() function returns the month on a zero-based index, and your math won't be reliable unless you switch it to a one-based index.
I have a event listener assigned to an object. This then triggers the startDrag function. I'm moving my character in the game with dragging. But as soon as I scroll or move the display, my dragging function gets all messed up. It doesn't react as it should and the object(event.target) can't be controlled at all.
Did anyone else had this experience?
Is this a corona bug?
How can I solve this?
Can I temporarily disable the startDrag event listener for the time of scrolling? Or maybe restart it?
All help would be greatly appreciated.
Here is the code...
local physics = require( "physics" )
physics.start()
physics.setContinuous( false )
display.setStatusBar( display.HiddenStatusBar )
physics.setScale( 60 )
physics.setDrawMode( "hybrid" )
local height = display.contentHeight
local width = display.contentWidth
local allElements = display.newGroup()
local texsGroup = display.newGroup()
local backGround = display.newRect(0,0-height,width,2*height)
backGround:setFillColor(91,91,91)
backGround:toBack()
local wallBottom = display.newRect(texsGroup, 0,height-20,width,20)
physics.addBody(wallBottom, "static", { density=5, friction=0.5, bounce=0.3 } )
local tex = {}
local numberRips = 60
local texSize = {
-- w: texwidth, h: texheight, s: strength required
{w=30, h=20, s=1},
{w=20, h=10, s=1.5},
{w=10, h=10, s=2},
}
local r
local lim = display.newGroup()
local function createRips()
local originX = 0
local originY = height -75
for i=0,numberRips do
r = math.random(3)
local x = originX + math.random(width)
local y = originY - math.random(2*height)
tex[i] = display.newRect(lim, x, y, texSize[r].w, texSize[r].h)
tex[i].status = "active"
tex[i].size = texSize[r].s
if (r == 1) then
tex[i]:setFillColor(51,255,0)
elseif (r == 2) then
tex[i]:setFillColor(255,51,51)
elseif (r == 3) then
tex[i]:setFillColor(51,51,255)
end
end
end
createRips()
local w, h, r = width/2, height - 265, 12
local L = display.newCircle(w-115,h+29,r)
local buttonRadius = 35
local button3 = display.newCircle((L.x),(L.y),buttonRadius)
button3.myName = "L"
allElements:insert(button3)
allElements:insert(lim)
allElements:insert(L)
local d, f, b = 15, 1, 0.15
physics.addBody(L, "dynamic", { density=d, friction=f, bounce=b, radius=r } )
button3.isVisible = false
button3.isHitTestable = true
physics.addBody( button3, "static", { density=1, radius=buttonRadius } )
local function addFrictionJoint(a, b, posX, posY, lowerAngle, upperAngle, mT)
local j = physics.newJoint ( "pivot", a, b, posX, posY, rFrom, rTo)
j.isLimitEnabled = true
j:setRotationLimits (lowerAngle, upperAngle)
return j
end
-- JOINTS
addFrictionJoint( button3, L, L.x, L.y, 0, 0 )
local function startDrag( event, params )
local body = event.target
local phase = event.phase
local stage = display.getCurrentStage()
local direction = event.direction
if "began" == phase then
stage:setFocus( body, event.id )
body.isFocus = true
event.target.bodyType = "dynamic"
-- Create a temporary touch joint and store it in the object for later reference
if params and params.center then
-- drag the body from its center point
body.tempJoint = physics.newJoint( "touch", body, body.x, body.y )
else
-- drag the body from the point where it was touched
body.tempJoint = physics.newJoint( "touch", body, event.x, event.y )
end
--body.tempJoint.maxForce = 0.25*body.tempJoint.maxForce
-- Apply optional joint parameters
if params then
local maxForce, frequency, dampingRatio
if params.maxForce then
-- Internal default is (1000 * mass), so set this fairly high if setting manually
body.tempJoint.maxForce = params.maxForce
end
if params.frequency then
-- This is the response speed of the elastic joint: higher numbers = less lag/bounce
body.tempJoint.frequency = params.frequency
end
if params.dampingRatio then
-- Possible values: 0 (no damping) to 1.0 (critical damping)
body.tempJoint.dampingRatio = params.dampingRatio
end
end
elseif body.isFocus then
if "moved" == phase then
-- Update the joint to track the touch
body.tempJoint:setTarget( event.x, event.y )
elseif "ended" == phase or "cancelled" == phase then
stage:setFocus( body, nil )
body.isFocus = false
-- Remove the joint when the touch ends
body.tempJoint:removeSelf()
body.bodyType = "static"
end
end
-- Stop further propagation of touch event
return true
end
function moveCamera(e)
if button3.y < -lim.y + 300 then
allElements.y = -(button3.y - 300)
end
end
Runtime:addEventListener("enterFrame", moveCamera)
button3:addEventListener( "touch", startDrag )
When you scroll the screen the touch event and the physics object are in different coordinate systems. See localToContent/globalToContent