project/build/default_html5/main/player.scriptc
2025-08-25 01:59:20 +01:00

451 lines
No EOL
13 KiB
Text
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

±g
™glocal 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",
}
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
self.jump_velocity = 800
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.current_lives = 3
self.current_score = 000
self.paused = false
self.current_movement = Movement.STILL_RIGHT
go.set_position(vmath.vector3(100,100,0.2))
msg.post("/banner#banner", "lives", {lives = self.current_lives})
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
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
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)
local platform_result = physics.raycast(centre, platform, { hash("platform") })
if platform_result then
local point = platform_result.position - pos
if not self.climbing then
self.jumped = false
self.grounded = true
self.velocity.y = 0
if point.y > -36 then
pos.y = pos.y + (point.y + 36)
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)
local score_vars = {
score = self.current_score,
}
msg.post("/banner#score", "set_scores", score_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 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
end
if message_id == hash("curse_dying_reply") then
if message.dying == false then
msg.post("/holding_amulet#holdingamulet", "disable_sprite")
self.current_lives = self.current_lives - 1
msg.post("/banner#banner", "lives", {lives = self.current_lives})
if self.current_lives == 0 then
local data = { score = self.current_score }
msg.post("main:/controller#main", "NoMoreLives", data)
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("add 100 points") then
self.current_score = self.current_score + 100
print(self.current_score)
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
print("Is this working?")
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
@main/player.script"