Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Zombie doesn't rotate correctly
Started by ConveyedRex7592 Feb 26 2020 10:06 AM

12 replies to this topic
rotating

Best Answer Alan PlantPot , 27 February 2020 - 10:25 AM

And depending on the orientation of the zombie in the image file itself, you might need to offset the final result as mentioned before. E.g:  

zombie.rotation = 90 + math.deg(math.atan2(zombie.y - hero.y, zombie.x - hero.x))

[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

ConveyedRex7592

[GLOBAL: userInfoPane.html]
ConveyedRex7592
  • Enthusiast

  • 39 posts
  • Corona SDK

Zombie is following me(hero), but sometimes it just bugs and doesn't look towards me.

 

PS hero is always in the center

 

My code:

 

function enemy(event)

      if zombie.x < display.contentCenterX then
        zombie.x = zombie.x + 1
        zombie.rotation = 270
      end

      if zombie.y > display.contentCenterY then
        zombie.y = zombie.y - 1
        zombie.rotation = 180
      end

      if zombie.x > display.contentCenterX then
        zombie.x = zombie.x - 1
        zombie.rotation = 90
      end

      if zombie.y < display.contentCenterY then
        zombie.y = zombie.y + 1
        zombie.rotation = 0
      end
    end



[TOPIC: post.html]
#2

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,219 posts
  • Corona SDK

Surely this is obvious?  If zombie.x > contentCenterX and zombie.y > contentCenterY what direction should it face?



[TOPIC: post.html]
#3

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Corona Geek

  • 1,271 posts
  • Corona SDK

To further clarify on what SGS is saying.

 

You have four completely separate conditional statements. As your code is run, every condition that is met will be activated. In other words, the lower down a conditional statement is, the more important it will be in your function.

 

i.e. left < below < right < above.

 

In other words, if the zombie is to the left of the centre, then that conditional statement will be met, BUT since the zombie will also be either below or above the centre, these will overwrite the rotation given by the zombie being to the left, and so on.



[TOPIC: post.html]
#4

Alan PlantPot

[GLOBAL: userInfoPane.html]
Alan PlantPot
  • Contributor

  • 939 posts
  • Corona SDK

Even if you were to use if...else if...elseif rather than just if...if...if you may still notice weird behaviour.

 

If we take this example (I'll simplify so it's just rotation for now):

if zombie.x < display.contentCenterX then
        zombie.rotation = 270
elseif zombie.y > display.contentCenterY then
        zombie.rotation = 180
elseif zombie.x > display.contentCenterX then
        zombie.rotation = 90
elseif zombie.y < display.contentCenterY then
        zombie.rotation = 0
end

If the zombie was 100 pixels to the left but 500 pixels below, most people would say that the zombie was predominantly below the hero rather than to its left. But in this code it would initially trigger the "zombie is to the left" part if statement, so the zombie would be facing right instead of facing up which would be more appropriate given its position relative to the hero. 

 

Personally I would use some trigonometry to set the angle between the player and the enemy. I haven't tested this but I think it's ok:

zombie.rotation = math.deg(math.atan2(zombie.x - hero.x, zombie.y - hero.y))

If you need them to always be at a 90 degree angle then you could also implement some code to snap the angle to the nearest 90 degrees.


  • sporkfin likes this

[TOPIC: post.html]
#5

ConveyedRex7592

[GLOBAL: userInfoPane.html]
ConveyedRex7592
  • Enthusiast

  • 39 posts
  • Corona SDK

That works only for left and right.

I tried that for up and down, but that doesn't work:

zombie.rotation = math.deg(math.atan2(zombie.y - hero.y, zombie.x - hero.x))



[TOPIC: post.html]
#6

Alan PlantPot

[GLOBAL: userInfoPane.html]
Alan PlantPot
  • Contributor

  • 939 posts
  • Corona SDK

It should work in all cases, the zombie should be able to rotate in any 360 degree angle towards the target (though you might need to offset the whole thing by 90/180 degrees depending on how the image is laid out in the image file itself).  

 

Can you paste in a slightly larger piece of code where you tried using the trig example?



[TOPIC: post.html]
#7

ConveyedRex7592

[GLOBAL: userInfoPane.html]
ConveyedRex7592
  • Enthusiast

  • 39 posts
  • Corona SDK

 
local composer = require "composer"
local joystickPlugin = require "plugin.joystick"
local physics = require "physics"
local scene = composer.newScene();
function scene:create(event)
  physics.start()
  physics.setGravity(0,0)
  local sceneGroup = self.view;
  system.activate("multitouch")
  local function zombieCollision(self, event)
    if event.phase == "began" then
      print("zombie")
    end
  end
  local spaceBackground = display.newImageRect("Images/SpaceBackground.png",
  display.actualContentWidth, display.actualContentHeight)
  spaceBackground.x = display.contentCenterX
  spaceBackground.y = display.contentCenterY
  local loading = display.newText("Loading...", display.contentCenterX - 230, 330,
  "Lobster-Regular", 40)
  local map = display.newImage("Images/survivalModeMap.png")
  map.isVisible = false
  map.x = display.contentCenterX
  map.y = display.contentCenterY
  local hero = display.newImage("Images/mehaHat.png")
  hero.isVisible = false
  hero.x = display.contentCenterX
  hero.y = display.contentCenterY
  physics.addBody(hero,"static")
  hero.direction = "up"
  hero.hp = 100
  local zombie = display.newImage("Images/zombie.jpg")
  zombie.isVisible = false
  zombie.x = display.contentCenterX
  physics.addBody(zombie,"dynamic")
  zombie.collision = zombieCollision
  zombie:addEventListener("collision", zombie)
  zombie.y = -100
  zombie.hp = 10
  local AttackButton = display.newImage("Images/mehaAttackButton.png")
  AttackButton.isVisible = false
  AttackButton.x = 480
  AttackButton.y = 270
  local AttackAnimationSheetData = {
    width = 400,
    height = 400,
    numFrames = 10,
    sheetContentWidth = 800,
    sheetContentHeight = 2000
  }
  local AttackAnimationSheet = graphics.newImageSheet("Images/mehaAttackAnimation.png", AttackAnimationSheetData)
  local sequenceData = {
    { name = "Attack", start = 1, count = 10, time = 500, loopCount = 1}
  }
  local props = {
    x = 10,
    y = 270,
    backgroundRadius = 50,
    movedStickRadius = 25,
  }
  function loadingEnd()
    spaceBackground.isVisible = false
    loading.isVisible = false
    map.isVisible = true
    hero.isVisible = true
    zombie.isVisible = true
    AttackButton.isVisible = true
    function enemy(event)
      if zombie.x < display.contentCenterX then
        zombie.x = zombie.x + 1
        --zombie.rotation = 270
        zombie.rotation = math.deg(math.atan2(zombie.x - hero.x, zombie.y - hero.y))
      end
      if zombie.y > display.contentCenterY then
        zombie.y = zombie.y - 1
        --zombie.rotation = 180
        zombie.rotation = math.deg(math.atan2(zombie.y - hero.y, zombie.x - hero.x))
      end
      if zombie.x > display.contentCenterX then
        zombie.x = zombie.x - 1
        --zombie.rotation = 90
        zombie.rotation = math.deg(math.atan2(zombie.x - hero.x, zombie.y - hero.y))
      end
      if zombie.y < display.contentCenterY then
        zombie.y = zombie.y + 1
        --zombie.rotation = 0
        zombie.rotation = math.deg(math.atan2(zombie.y - hero.y, zombie.x - hero.x))
      end
    end
    local Joystick = joystickPlugin.newJoystick(props)
    Joystick.background:setFillColor(0.5)
    Joystick.movedStick:setFillColor(0.7)
    local function enterFrame(event)
      if Joystick.isActivated() then
        local vector = Joystick.getVector()
        if vector.x < -0.5 then
          map.x = map.x + 2
          zombie.x = zombie.x + 2
          hero.rotation = 270
          hero.direction = "left"
        elseif vector.x > 0.5 then
          map.x = map.x - 2
          zombie.x = zombie.x -2
          hero.rotation = 90
          hero.direction = "right"
        end
        if vector.y < -0.5 then
          map.y = map.y + 2
          zombie.y = zombie.y + 2
          hero.rotation = 0
          hero.direction = "up"
        elseif vector.y > 0.5 then
          map.y = map.y - 2
          zombie.y = zombie.y-2
          hero.rotation = 180
          hero.direction = "down"
        end
      end
    end
    local AttackCoolDown = 0
    local function Attack(event)
      if(event.phase == "began") then
        if AttackCoolDown == 0 then
          hero.isVisible = false
          local mehaAttackAnimation = display.newSprite( AttackAnimationSheet, sequenceData )
          mehaAttackAnimation.x = display.contentCenterX
          mehaAttackAnimation.y = display.contentCenterY
          if hero.direction == "up" then
            mehaAttackAnimation.rotation = 0
          elseif hero.direction == "right" then
            mehaAttackAnimation.rotation = 90
          elseif hero.direction == "down" then
            mehaAttackAnimation.rotation = 180
          elseif hero.direction == "left" then
            mehaAttackAnimation.rotation = 270
          end
          mehaAttackAnimation:play()
          AttackCoolDown = 1
          timer.performWithDelay( 500, function()
          hero.isVisible = true
            mehaAttackAnimation:removeSelf()
            AttackCoolDown = 0
          end)
        end
      end
    end
    Runtime:addEventListener("enterFrame", enemy)
    Runtime:addEventListener("enterFrame", enterFrame)
    AttackButton:addEventListener("touch", Attack)
  end
  timer.performWithDelay( 2000, loadingEnd )
end
scene:addEventListener("create", scene);
return scene;
 



[TOPIC: post.html]
#8

Alan PlantPot

[GLOBAL: userInfoPane.html]
Alan PlantPot
  • Contributor

  • 939 posts
  • Corona SDK

A bit more than I expected, but that's fine  :)

 

I wasn't clear enough in my first message. Take the trig rotation code out of the if statements, and put it by itself (but still in the enter frame function).

 

That way it always rotates exactly towards the player regardless of whether the zombie is "more to the left" than it is "more up above the player":

function enemy(event)
      if zombie.x < display.contentCenterX then
        zombie.x = zombie.x + 1
      end
      if zombie.y > display.contentCenterY then
        zombie.y = zombie.y - 1
      end
      if zombie.x > display.contentCenterX then
        zombie.x = zombie.x - 1
      end
      if zombie.y < display.contentCenterY then
        zombie.y = zombie.y + 1
      end

      zombie.rotation = math.deg(math.atan2(zombie.x - hero.x, zombie.y - hero.y))
end


[TOPIC: post.html]
#9

ConveyedRex7592

[GLOBAL: userInfoPane.html]
ConveyedRex7592
  • Enthusiast

  • 39 posts
  • Corona SDK

Zombie turns right and left, but when it need to turn up it turns down and when it need turn down it turns up.



[TOPIC: post.html]
#10

Alan PlantPot

[GLOBAL: userInfoPane.html]
Alan PlantPot
  • Contributor

  • 939 posts
  • Corona SDK

Oops, I had the x and y arguments the wrong way round. Try this instead:

zombie.rotation = math.deg(math.atan2(zombie.y - hero.y, zombie.x - hero.x))


[TOPIC: post.html]
#11

Alan PlantPot

[GLOBAL: userInfoPane.html]
Alan PlantPot
  • Contributor

  • 939 posts
  • Corona SDK

  Best Answer

And depending on the orientation of the zombie in the image file itself, you might need to offset the final result as mentioned before. E.g:  

zombie.rotation = 90 + math.deg(math.atan2(zombie.y - hero.y, zombie.x - hero.x))

  • sporkfin likes this

[TOPIC: post.html]
#12

ConveyedRex7592

[GLOBAL: userInfoPane.html]
ConveyedRex7592
  • Enthusiast

  • 39 posts
  • Corona SDK

zombie.rotation = 90 + math.deg(math.atan2(zombie.y - hero.y, zombie.x - hero.x))

works perfectly!

 

Thanks for help! :)



[TOPIC: post.html]
#13

Alan PlantPot

[GLOBAL: userInfoPane.html]
Alan PlantPot
  • Contributor

  • 939 posts
  • Corona SDK

I'm glad that worked.   

 

If I were you, I would consider spending some time getting a better understanding of why your original method of trying if...if...if...if... didn't work - XeduR's original reply explained it quite well.




[topic_controls]
[/topic_controls]

Also tagged with one or more of these keywords: rotating