local Movement = { STILL_LEFT = "STILL_LEFT", STILL_RIGHT = "STILL_RIGHT", MOVING_LEFT = "MOVING_LEFT", MOVING_RIGHT = "MOVING_RIGHT", CLIMBING_UP = "CLIMBING_UP", CLIMBING_DOWN = "CLIMBING_DOWN", FALLING = "FALLING", JUMPING_LEFT = "JUMPING_LEFT", JUMPING_RIGHT = "JUMPING_RIGHT", JUMPING_STRAIGHT_UP = "JUMPING_STRAIGHT_UP", CLIMBING_STILL = "CLIMBING_STILL", } local Actions = { LEFT_ARROW_PRESS = "LEFT_ARROW_PRESS", LEFT_ARROW_RELEASE = "LEFT_ARROW_RELEASE", RIGHT_ARROW_PRESS = "RIGHT_ARROW_PRESS", RIGHT_ARROW_RELEASE = "RIGHT_ARROW_RELEASE", UP_ARROW_PRESS = "UP_ARROW_PRESS", UP_ARROW_RELEASE = "UP_ARROW_RELEASE", DOWN_ARROW_PRESS = "DOWN_ARROW_PRESS", DOWN_ARROW_RELEASE = "DOWN_ARROW_RELEASE", SPACE_BAR_PRESS = "SPACE_BAR_PRESS", SPACE_BAR_RELEASE = "SPACE_BAR_RELEASE", } -- Transition table: [current_state][input] = next_state local transitions = { [Movement.STILL_RIGHT] = { [Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT, [Actions.RIGHT_ARROW_RELEASE] = Movement.STILL_RIGHT, [Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT, [Actions.LEFT_ARROW_RELEASE] = Movement.STILL_LEFT, [Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP, [Actions.UP_ARROW_RELEASE] = Movement.CLIMBING_STILL, [Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN, [Actions.DOWN_ARROW_RELEASE] = Movement.CLIMBING_STILL, }, [Movement.STILL_LEFT] = { [Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT, [Actions.RIGHT_ARROW_RELEASE] = Movement.STILL_RIGHT, [Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT, [Actions.LEFT_ARROW_RELEASE] = Movement.STILL_LEFT, [Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP, [Actions.UP_ARROW_RELEASE] = Movement.CLIMBING_STILL, [Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN, [Actions.DOWN_ARROW_RELEASE] = Movement.CLIMBING_STILL, }, [Movement.MOVING_LEFT] = { [Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT, [Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT, [Actions.LEFT_ARROW_RELEASE] = Movement.STILL_LEFT, [Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP, [Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN, }, [Movement.MOVING_RIGHT] = { [Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT, [Actions.RIGHT_ARROW_RELEASE] = Movement.STILL_RIGHT, [Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT, [Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP, [Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN, }, [Movement.CLIMBING_STILL] = { [Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT, [Actions.RIGHT_ARROW_RELEASE] = Movement.STILL_RIGHT, [Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT, [Actions.LEFT_ARROW_RELEASE] = Movement.STILL_LEFT, [Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP, [Actions.UP_ARROW_RELEASE] = Movement.CLIMBING_STILL, [Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN, [Actions.DOWN_ARROW_RELEASE] = Movement.CLIMBING_STILL, }, [Movement.CLIMBING_UP] = { [Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT, [Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT, [Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT, [Actions.LEFT_ARROW_RELEASE] = Movement.STILL_LEFT, [Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP, [Actions.UP_ARROW_RELEASE] = Movement.CLIMBING_STILL, [Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN, [Actions.DOWN_ARROW_RELEASE] = Movement.CLIMBING_STILL, }, [Movement.CLIMBING_DOWN] = { [Actions.RIGHT_ARROW_PRESS] = Movement.MOVING_RIGHT, [Actions.LEFT_ARROW_PRESS] = Movement.MOVING_LEFT, [Actions.UP_ARROW_PRESS] = Movement.CLIMBING_UP, [Actions.UP_ARROW_RELEASE] = Movement.CLIMBING_STILL, [Actions.DOWN_ARROW_PRESS] = Movement.CLIMBING_DOWN, [Actions.DOWN_ARROW_RELEASE] = Movement.CLIMBING_STILL, }, } function init(self) msg.post(".", "acquire_input_focus") self.direction = vmath.vector3(0,0,0) self.speed = 250 self.gravity = -5000 -- gravity force self.jump_velocity = 800-- how strong the jump is self.velocity = vmath.vector3(0, 0, 0) self.grounded = false self.jumped = false self.near_up_ladder = false self.correction = vmath.vector3() self.climbing = false self.is_moving = 0 self.left_pressed = false self.right_pressed = false self.up_pressed = false self.down_pressed = false self.jump_pressed = false self.have_amulet = false self.amulet_timer = 0 self.regenerating = false self.regen_timer = 0 self.blink_on_timer = 0 self.blink_off_timer = 0 self.paused = false self.current_movement = Movement.STILL_RIGHT go.set_position(vmath.vector3(100,100,0.2)) end function final(self) -- Add finalization code here -- Learn more: https://defold.com/manuals/script/ -- Remove this function if not needed end local function handleInput(self, input) local Transitions = transitions[self.current_movement] local next_movement = Transitions and Transitions[input] if next_movement then --print("Transitioning from", self.current_movement, "to", next_movement, "on input", input) self.current_movement = next_movement if next_movement == Movement.MOVING_LEFT then sprite.play_flipbook("#sprite", hash("run_left")) msg.post("holding_amulet", "left") self.direction.x = -1 self.velocity.y = 0 end if next_movement == Movement.MOVING_RIGHT then sprite.play_flipbook("#sprite", hash("run_right")) msg.post("holding_amulet", "right") self.direction.x = 1 self.velocity.y = 0 end if next_movement == Movement.STILL_RIGHT then if not self.climbing then sprite.play_flipbook("#sprite", hash("still_right")) else next_movement = Movement.CLIMBING_STILL sprite.play_flipbook("#sprite", hash("still_climbing")) end self.direction.x = 0 end if next_movement == Movement.STILL_LEFT then if not self.climbing then sprite.play_flipbook("#sprite", hash("still_left")) else next_movement = Movement.CLIMBING_STILL sprite.play_flipbook("#sprite", hash("still_climbing")) end self.direction.x = 0 end if next_movement == Movement.CLIMBING_STILL then sprite.play_flipbook("#sprite", hash("still_climbing")) self.velocity.y = 0 self.climbing = true if self.right_pressed then handleInput(self, Actions.RIGHT_ARROW_PRESS) --print("Actions.LEFT_RIGHT_PRESS from climbing_still") elseif self.left_pressed then handleInput(self, Actions.LEFT_ARROW_PRESS) --print("Actions.LEFT_ARROW_PRESS from climbing_still") end end if next_movement == Movement.CLIMBING_UP then sprite.play_flipbook("#sprite", hash("climbing")) self.direction.x = 0 self.velocity.y = 150 self.climbing = true end if next_movement == Movement.CLIMBING_DOWN then sprite.play_flipbook("#sprite", hash("climbing")) self.direction.x = 0 self.velocity.y = -150 self.climbing = true end else --print("No transition defined for", input, "in state", self.current_movement) end end function update(self, dt) if not self.paused then if self.amulet_timer > 0 then self.amulet_timer = self.amulet_timer - dt -- print ("You have " .. self.amulet_timer .. " seconds left of amulet") if self.amulet_timer < 0 then self.amulet_timer = 0 self.have_amulet = false msg.post("holding_amulet", "disable_sprite") end end if self.regen_timer > 0 then self.regen_timer = self.regen_timer - dt -- print ("You have " .. self.regen_timer .. " seconds left of regeneration") if self.regen_timer < 0 then self.regen_timer = 0 self.regenerating = false msg.post("#sprite", "enable") end if self.regenerating then if self.blink_on_timer > 0 then self.blink_on_timer = self.blink_on_timer - dt msg.post("#sprite", "enable") elseif self.blink_off_timer > 0 then self.blink_off_timer = self.blink_off_timer - dt msg.post("#sprite", "disable") else self.blink_on_timer = 0.25 self.blink_off_timer = 0.25 end end end self.correction = vmath.vector3() self.velocity.x = self.direction.x * self.speed local pos = go.get_position() pos = pos + self.velocity * dt if pos.x < 24 then pos.x = 24 elseif pos.x > 1030 then pos.x = 1030 end if pos.y < 0 then pos.y = 100 end local centre = vmath.vector3(pos.x, pos.y - 10, 0) local platform = pos + vmath.vector3(0, -36, 0) local ladder_up_left = pos + vmath.vector3(-24, -32, 0) local ladder_up_right = pos + vmath.vector3(24, -32, 0) local ladder_down_left = pos + vmath.vector3(-24, -42, 0) local ladder_down_right = pos + vmath.vector3(24, -42, 0) --msg.post("@render:", "draw_line", { start_point = centre, end_point = platform, color = vmath.vector4(1,0,0,1) }) --msg.post("@render:", "draw_line", { start_point = ladder_up_left, end_point = ladder_up_right, color = vmath.vector4(1,0,0,1) }) --msg.post("@render:", "draw_line", { start_point = ladder_up_right, end_point = ladder_up_left, color = vmath.vector4(1,0,0,1) }) --msg.post("@render:", "draw_line", { start_point = ladder_down_left, end_point = ladder_down_right, color = vmath.vector4(1,0,0,1) }) --msg.post("@render:", "draw_line", { start_point = ladder_down_right, end_point = ladder_down_left, color = vmath.vector4(1,0,0,1) }) local platform_result = physics.raycast(centre, platform, { hash("platform") }) if platform_result then local point = platform_result.position - pos -- msg.post("@render:", "draw_debug_text", { text = "Platform", position = vmath.vector3(20, 400, 0), color = vmath.vector4(1, 0, 0, 1) } ) -- msg.post("@render:", "draw_debug_text", { text = "X : " .. tostring(point.x), position = vmath.vector3(20, 380, 0), color = vmath.vector4(1, 0, 0, 1) } ) -- msg.post("@render:", "draw_debug_text", { text = "Y : " .. tostring(point.y), position = vmath.vector3(20, 360, 0), color = vmath.vector4(1, 0, 0, 1) } ) if not self.climbing then self.jumped = false self.speed = 250 self.grounded = true self.velocity.y = 0 if point.y > -36 then pos.y = pos.y + (point.y + 36) end --if self.climbing then -- self.climbing = false -- sprite.play_flipbook("#sprite", hash("still_left")) --end end else self.grounded = false end local ladder_up_result1 = physics.raycast(ladder_up_right, ladder_up_left, { hash("ladder") }) local ladder_up_result2 = physics.raycast(ladder_up_left, ladder_up_right, { hash("ladder") }) if ladder_up_result1 then self.near_up_ladder = true elseif ladder_up_result2 then self.near_up_ladder = true else self.near_up_ladder = false end local ladder_down_result1 = physics.raycast(ladder_down_right, ladder_down_left, { hash("ladder") }) local ladder_down_result2 = physics.raycast(ladder_down_left, ladder_down_right, { hash("ladder") }) if ladder_down_result1 then self.near_down_ladder = true elseif ladder_down_result2 then self.near_down_ladder = true else self.near_down_ladder = false end if not (self.near_up_ladder or self.near_down_ladder)then if self.climbing then self.climbing = false if self.left_pressed then handleInput(self, Actions.LEFT_ARROW_PRESS) end if self.right_pressed then handleInput(self, Actions.RIGHT_ARROW_PRESS) end end end -- local debug_vars = { -- x = pos.x, -- y = pos.y, -- x_vel = self.velocity.x, -- y_vel = self.velocity.y, -- grounded = self.grounded, -- near_up_ladder = self.near_up_ladder, -- near_down_ladder = self.near_down_ladder, -- jumped = self.jumped, -- climbing = self.climbing, -- left_pressed = self.left_pressed, -- right_pressed = self.right_pressed, -- up_pressed = self.up_pressed, -- down_pressed = self.down_pressed, -- } -- msg.post("#debug", "set_vars", debug_vars) if not self.grounded and not ((self.near_up_ladder or self.near_down_ladder) and self.climbing) then self.velocity.y = self.velocity.y + self.gravity * dt end go.set_position(pos) end end function fixed_update(self, dt) end function on_message(self, message_id, message, sender) if message_id == hash("contact_point_response") then if message.group == hash("curse") then if not self.regenerating then --print("collision with curse") msg.post(message.other_id, "dying") end end if message.group == hash("amulet") then self.have_amulet = true self.amulet_timer = 5 msg.post("holding_amulet", "enable_sprite") --print("collision with amulet") end if message.group == hash("mummy") then msg.post("main:/controller#main", "LevelCompleted") --print("collision with mummy") end end if message_id == hash("curse_dying_reply") then if message.dying == false then msg.post("/holding_amulet#holdingamulet", "disable_sprite") msg.post("main:/controller#main", "LifeLost") --else self.current_movement = Movement.MOVING_RIGHT handleInput(self, Actions.RIGHT_ARROW_RELEASE) go.set_position(vmath.vector3(100,100,0.2)) self.regenerating = true self.regen_timer = 3 --end end end if message_id == hash("pause") then self.paused = true end if message_id == hash("unpause") then self.paused = false end end function on_input(self, action_id, action) if not self.paused then if action_id == hash("left") then if action.pressed then self.left_pressed = true handleInput(self, Actions.LEFT_ARROW_PRESS) elseif action.released then self.left_pressed = false handleInput(self, Actions.LEFT_ARROW_RELEASE) end end if action_id == hash("right") then if action.pressed then self.right_pressed = true handleInput(self, Actions.RIGHT_ARROW_PRESS) elseif action.released then self.right_pressed = false handleInput(self, Actions.RIGHT_ARROW_RELEASE) end end if action_id == hash("jump") and action.pressed and not self.jumped and not self.climbing then self.velocity.y = self.jump_velocity self.speed = 500 self.jumped = true end if action_id == hash("climb_up") then if action.pressed then self.up_pressed = true handleInput(self, Actions.UP_ARROW_PRESS) elseif action.released then self.up_pressed = false handleInput(self, Actions.UP_ARROW_RELEASE) end end if action_id == hash("climb_down") then if action.pressed then self.down_pressed = true handleInput(self, Actions.DOWN_ARROW_PRESS) elseif action.released then self.down_pressed = false handleInput(self, Actions.DOWN_ARROW_RELEASE) end end end end function on_reload(self) -- Add reload-handling code here -- Learn more: https://defold.com/manuals/hot-reload/ -- Remove this function if not needed end