184 lines
6.3 KiB
Lua
184 lines
6.3 KiB
Lua
-- Urho2D tile map example.
|
|
-- This sample demonstrates:
|
|
-- - Creating an isometric 2D scene with tile map
|
|
-- - Displaying the scene using the Renderer subsystem
|
|
-- - Handling keyboard to move a character and zoom 2D camera
|
|
-- - Generating physics shapes from the tmx file's objects
|
|
-- - Displaying debug geometry for physics and tile map
|
|
-- Note that this sample uses some functions from Sample2D utility class.
|
|
|
|
require "LuaScripts/Utilities/Sample"
|
|
require "LuaScripts/Utilities/2D/Sample2D"
|
|
|
|
|
|
function Start()
|
|
-- Set filename for load/save functions
|
|
demoFilename = "Isometric2D"
|
|
|
|
-- Execute the common startup for samples
|
|
SampleStart()
|
|
|
|
-- Create the scene content
|
|
CreateScene()
|
|
|
|
-- Create the UI content
|
|
CreateUIContent("ISOMETRIC 2.5D DEMO")
|
|
|
|
-- Hook up to the frame update events
|
|
SubscribeToEvents()
|
|
end
|
|
|
|
function CreateScene()
|
|
scene_ = Scene()
|
|
|
|
-- Create the Octree, DebugRenderer and PhysicsWorld2D components to the scene
|
|
scene_:CreateComponent("Octree")
|
|
scene_:CreateComponent("DebugRenderer")
|
|
local physicsWorld = scene_:CreateComponent("PhysicsWorld2D")
|
|
physicsWorld.gravity = Vector2.ZERO -- Neutralize gravity as the character will always be grounded
|
|
|
|
-- Create camera
|
|
cameraNode = Node()
|
|
local camera = cameraNode:CreateComponent("Camera")
|
|
camera.orthographic = true
|
|
camera.orthoSize = graphics.height * PIXEL_SIZE
|
|
zoom = 2 * Min(graphics.width / 1280, graphics.height / 800) -- Set zoom according to user's resolution to ensure full visibility (initial zoom (2) is set for full visibility at 1280x800 resolution)
|
|
camera.zoom = zoom
|
|
|
|
-- Setup the viewport for displaying the scene
|
|
renderer:SetViewport(0, Viewport:new(scene_, camera))
|
|
renderer.defaultZone.fogColor = Color(0.2, 0.2, 0.2) -- Set background color for the scene
|
|
|
|
-- Create tile map from tmx file
|
|
local tmxFile = cache:GetResource("TmxFile2D", "Urho2D/Tilesets/atrium.tmx")
|
|
local tileMapNode = scene_:CreateChild("TileMap")
|
|
local tileMap = tileMapNode:CreateComponent("TileMap2D")
|
|
tileMap.tmxFile = tmxFile
|
|
local info = tileMap.info
|
|
|
|
-- Create Spriter Imp character (from sample 33_SpriterAnimation)
|
|
CreateCharacter(info, true, 0, Vector3(-5, 11, 0), 0.15)
|
|
|
|
-- Generate physics collision shapes from the tmx file's objects located in "Physics" (top) layer
|
|
local tileMapLayer = tileMap:GetLayer(tileMap.numLayers - 1)
|
|
CreateCollisionShapesFromTMXObjects(tileMapNode, tileMapLayer, info)
|
|
|
|
-- Instantiate enemies and moving platforms at each placeholder of "MovingEntities" layer (placeholders are Poly Line objects defining a path from points)
|
|
PopulateMovingEntities(tileMap:GetLayer(tileMap.numLayers - 2))
|
|
|
|
-- Instantiate coins to pick at each placeholder of "Coins" layer (placeholders for coins are Rectangle objects)
|
|
PopulateCoins(tileMap:GetLayer(tileMap.numLayers - 3))
|
|
|
|
-- Check when scene is rendered
|
|
SubscribeToEvent("EndRendering", HandleSceneRendered)
|
|
end
|
|
|
|
function HandleSceneRendered()
|
|
UnsubscribeFromEvent("EndRendering")
|
|
SaveScene(true) -- Save the scene so we can reload it later
|
|
scene_.updateEnabled = false -- Pause the scene as long as the UI is hiding it
|
|
end
|
|
|
|
function SubscribeToEvents()
|
|
-- Subscribe HandleUpdate() function for processing update events
|
|
SubscribeToEvent("Update", "HandleUpdate")
|
|
|
|
-- Subscribe HandlePostUpdate() function for processing post update events
|
|
SubscribeToEvent("PostUpdate", "HandlePostUpdate")
|
|
|
|
-- Subscribe to PostRenderUpdate to draw physics shapes
|
|
SubscribeToEvent("PostRenderUpdate", "HandlePostRenderUpdate")
|
|
|
|
-- Unsubscribe the SceneUpdate event from base class to prevent camera pitch and yaw in 2D sample
|
|
UnsubscribeFromEvent("SceneUpdate")
|
|
end
|
|
|
|
function HandleUpdate(eventType, eventData)
|
|
-- Zoom in/out
|
|
Zoom(cameraNode:GetComponent("Camera"))
|
|
|
|
-- Toggle debug geometry with spacebar
|
|
if input:GetKeyPress(KEY_Z) then drawDebug = not drawDebug end
|
|
|
|
-- Check for loading / saving the scene
|
|
if input:GetKeyPress(KEY_F5) then
|
|
SaveScene()
|
|
end
|
|
if input:GetKeyPress(KEY_F7) then
|
|
ReloadScene(false)
|
|
end
|
|
end
|
|
|
|
function HandlePostUpdate(eventType, eventData)
|
|
if character2DNode == nil or cameraNode == nil then
|
|
return
|
|
end
|
|
cameraNode.position = Vector3(character2DNode.position.x, character2DNode.position.y, -10) -- Camera tracks character
|
|
end
|
|
|
|
function HandlePostRenderUpdate(eventType, eventData)
|
|
if drawDebug then
|
|
scene_:GetComponent("PhysicsWorld2D"):DrawDebugGeometry(true)
|
|
end
|
|
end
|
|
|
|
-- Character2D script object class
|
|
Character2D = ScriptObject()
|
|
|
|
function Character2D:Start()
|
|
self.wounded = false
|
|
self.killed = false
|
|
self.timer = 0
|
|
self.maxCoins = 0
|
|
self.remainingCoins = 0
|
|
self.remainingLifes = 3
|
|
end
|
|
|
|
function Character2D:Update(timeStep)
|
|
local node = self.node
|
|
local animatedSprite = node:GetComponent("AnimatedSprite2D")
|
|
|
|
-- Set direction
|
|
local moveDir = Vector3.ZERO -- Reset
|
|
local speedX = Clamp(MOVE_SPEED_X / zoom, 0.4, 1)
|
|
local speedY = speedX
|
|
|
|
if input:GetKeyDown(KEY_LEFT) or input:GetKeyDown(KEY_A) then
|
|
moveDir = moveDir + Vector3.LEFT * speedX
|
|
animatedSprite.flipX = false -- Flip sprite (reset to default play on the X axis)
|
|
end
|
|
if input:GetKeyDown(KEY_RIGHT) or input:GetKeyDown(KEY_D) then
|
|
moveDir = moveDir + Vector3.RIGHT * speedX
|
|
animatedSprite.flipX = true -- Flip sprite (flip animation on the X axis)
|
|
end
|
|
|
|
if not moveDir:Equals(Vector3.ZERO) then
|
|
speedY = speedX * MOVE_SPEED_SCALE
|
|
end
|
|
|
|
if input:GetKeyDown(KEY_UP) or input:GetKeyDown(KEY_W) then
|
|
moveDir = moveDir + Vector3.UP * speedY
|
|
end
|
|
if input:GetKeyDown(KEY_DOWN) or input:GetKeyDown(KEY_S) then
|
|
moveDir = moveDir + Vector3.DOWN * speedY
|
|
end
|
|
|
|
-- Move
|
|
if not moveDir:Equals(Vector3.ZERO) then
|
|
node:Translate(moveDir * timeStep)
|
|
end
|
|
|
|
-- Animate
|
|
if input:GetKeyDown(KEY_SPACE) then
|
|
if animatedSprite.animation ~= "attack" then
|
|
animatedSprite:SetAnimation("attack", LM_FORCE_LOOPED)
|
|
end
|
|
elseif not moveDir:Equals(Vector3.ZERO) then
|
|
if animatedSprite.animation ~= "run" then
|
|
animatedSprite:SetAnimation("run")
|
|
end
|
|
elseif animatedSprite.animation ~= "idle" then
|
|
animatedSprite:SetAnimation("idle")
|
|
end
|
|
end
|