Hello,
. @Brandn3wbian and the few that were expecting this a couple of days ago, sorry for the delay, i’ve been busy with work, but here it is.
Tile based games are very easy to work with (simple ai, collision detection, etc…) so I figured I would share some code to show how it works.
You can make quite a few types of games that fit the constraints of this engine style, such as zelda, bomberman, pacman, diablo, etc…
Note that the art used here is just cubes and builtin codea textures, so it’s ugly as hell
With nice assets though, it can very easily look gorgeous (think zelda in 3D) like Oceanhorn.
http://www.youtube.com/watch?v=W4pW3o5HVHU
Note that I updated my Blender to Codea exporter, and you can easily create better assets with it:
http://twolivesleft.com/Codea/Talk/discussion/962/blender-scene-exporter-for-codea
Also, the code here is made as simple as possible and can be easily optimised (1D array, etc…)
Anyways, here is the source (pastebin is here)
--# Main
-- Use this function to perform your initial setup
displayMode(FULLSCREEN)
function setup()
stick = Stick()
pylon = Wall("Cargo Bot:Crate Red 2")
wall = Wall("Cargo Bot:Crate Yellow 2")
floor = Floor("Cargo Bot:Crate Green 2")
world = World()
hero = Hero(3,3)
TO_DEG = 180/math.pi
end
-- This function gets called once every frame
function draw()
background(0)
local TO_DEG = TO_DEG
local hero = hero
perspective(60)
camera(hero.x, 3, 1 + hero.z, hero.x, 0, hero.z, 0, 1, 0)
-- Draw world
pushMatrix()
world:draw()
popMatrix()
-- Draw hero
translate(hero.x, hero.y, hero.z)
rotate(stick.direction*TO_DEG, 0, 1, 0)
-- roll animation
if stick.active then
rotate(-ElapsedTime*10*TO_DEG, 0, 0, 1)
end
scale(.25, .25, .25)
hero:draw()
-- Restore orthographic projection
ortho()
viewMatrix(matrix())
resetMatrix()
-- fade out overlay
sprite("Cargo Bot:Background Fade", WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)
if stick.active then
local ceil = math.ceil
stick:draw()
-- move hero based on stick direction
local mvtx = math.cos(stick.direction)/50*stick.dist
local mvtz = -math.sin(stick.direction)/50*stick.dist
hero.x = hero.x + mvtx
hero.z = hero.z + mvtz
-- convert to table coordinates
hero.px = ceil(hero.x - .5)
hero.py = ceil(hero.z - .5)
-- lazy collision check
if world.data[hero.py][hero.px] ~= 0 then
hero.x = hero.x - mvtx
hero.z = hero.z - mvtz
hero.px = ceil(hero.x - .5)
hero.py = ceil(hero.z - .5)
end
end
end
function touched(touch)
stick:touched(touch)
end
--# World
World = class()
function World:init()
-- define the world
self.data =
{
{1, 1, 1, 1, 1, 1, 1, 1},
{1, 2, 0, 0, 0, 0, 2, 1},
{1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 1, 2, 0, 0, 1},
{1, 0, 0, 2, 1, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 1},
{1, 2, 0, 0, 0, 0, 2, 1},
{1, 1, 1, 1, 1, 1, 1, 1}
}
end
function World:draw()
local floor, wall, pylon = floor, wall, pylon
local offSet = 3
local px, py = hero.px, hero.py
-- look around the hero to draw whatever is around him
translate(px - offSet, 0, py - offSet)
for y = py - offSet, py + offSet do
for x = px - offSet, px + offSet do
if self.data[y] then
local val = self.data[y][x]
if val == 0 then
floor:draw()
elseif val == 1 then
wall:draw()
elseif val == 2 then
pylon:draw()
end
end
translate(1,0,0)
end
translate(-(1 + 2 * offSet), 0, 1)
end
end
--# Hero
Hero = class()
function Hero:init(x, z)
self.x, self.y, self.z = x,0,z
self.px, self.py = math.ceil(.5+x), math.ceil(.5+z)
self.mdl = Wall("Cargo Bot:Crate Blue 2")
end
function Hero:draw()
self.mdl:draw()
end
--# Wall
Wall = class()
function Wall:init(tex)
-- all the unique vertices that make up a cube
local vertices =
{
vec3(-0.5, -0.5, 0.5), -- Left bottom front
vec3( 0.5, -0.5, 0.5), -- Right bottom front
vec3( 0.5, 0.5, 0.5), -- Right top front
vec3(-0.5, 0.5, 0.5), -- Left top front
vec3(-0.5, -0.5, -0.5), -- Left bottom back
vec3( 0.5, -0.5, -0.5), -- Right bottom back
vec3( 0.5, 0.5, -0.5), -- Right top back
vec3(-0.5, 0.5, -0.5), -- Left top back
}
-- now construct a cube out of the vertices above
local verts =
{
-- Front
vertices[1], vertices[2], vertices[3],
vertices[1], vertices[3], vertices[4],
-- Right
vertices[2], vertices[6], vertices[7],
vertices[2], vertices[7], vertices[3],
-- Back
vertices[6], vertices[5], vertices[8],
vertices[6], vertices[8], vertices[7],
-- Left
vertices[5], vertices[1], vertices[4],
vertices[5], vertices[4], vertices[8],
-- Top
vertices[4], vertices[3], vertices[7],
vertices[4], vertices[7], vertices[8],
-- Bottom
vertices[5], vertices[6], vertices[2],
vertices[5], vertices[2], vertices[1],
}
-- all the unique texture positions needed
local texvertices =
{
vec2(0,0),
vec2(1,0),
vec2(0,1),
vec2(1,1)
}
-- apply the texture coordinates to each triangle
local texCoords =
{
-- Front
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Right
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Back
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Left
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Top
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
-- Bottom
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
}
self.model = mesh()
self.model.vertices = verts
self.model.texture = tex
self.model.texCoords = texCoords
self.model:setColors(255,255,255,255)
end
function Wall:draw()
self.model:draw()
end
--# Floor
Floor = class()
function Floor:init(tex)
-- all the unique vertices that make up a cube
local vertices =
{
vec3( 0.5, -0.5, 0.5), -- Right top front
vec3(-0.5, -0.5, 0.5), -- Left top front
vec3( 0.5, -0.5, -0.5), -- Right top back
vec3(-0.5, -0.5, -0.5), -- Left top back
}
-- now construct a cube out of the vertices above
local verts =
{
-- Bottom
vertices[3], vertices[4], vertices[2],
vertices[3], vertices[2], vertices[1],
}
-- all the unique texture positions needed
local texvertices =
{
vec2(0,0),
vec2(1,0),
vec2(0,1),
vec2(1,1)
}
-- apply the texture coordinates to each triangle
local texCoords =
{
-- Bottom
texvertices[1], texvertices[2], texvertices[4],
texvertices[1], texvertices[4], texvertices[3],
}
self.model = mesh()
self.model.vertices = verts
self.model.texture = tex
self.model.texCoords = texCoords
self.model:setColors(255,255,255,255)
end
function Floor:draw()
self.model:draw()
end
--# Stick
Stick = class()
function Stick:init()
self.direction = 0
self.dist = 0
self.active = false
self.origin = vec2(150, 150)
self.center = self.origin
self.pos = self.origin
self.stick_bg = readImage("Space Art:Eclipse")
self.stick = readImage("Space Art:UFO")
end
function Stick:draw()
sprite(self.stick_bg, self.center.x, self.center.y)
sprite(self.stick, self.pos.x, self.pos.y)
end
function Stick:touched(touch)
if touch.state == BEGAN then
self.center = vec2(touch.x, touch.y)
self.active = true
end
self.pos = vec2(touch.x, touch.y)
self.direction = math.atan2(self.pos.y - self.center.y, self.pos.x - self.center.x)
self.dist = math.min(2, self.pos:dist(self.center)/32)
if touch.state == ENDED then
self.center = self.origin
self.pos = self.center
self.active = false
end
end
Cheers