Posted 09 March 2013 - 10:02 AM
Yasuda Game Engine!
Latest update: camera locking & bug fixes
Yasuda is a game engine I have been working on for about a week now. It is designed to be easy to use, and open but have add-ons that specialize it to make it better for certain tasks. The main engine has collision detection but the map addon uses auto collision and will eventually have things like following and attacking in built ( so you can set entities to attack/follow other entities automatically )
Well, how good is it really? Here's an example:
What is so good about it?
-Easy to make add-ons for/overwrite current ones to suit your needs
-Per pixel and rectangle collision detection
-Entity storage and management
-Addons:
–Map - auto collision
–RPG - extra variables & functions related to role playing games such as money and health & collision attacking
Still to come:
entity actions such as following, attacking, eating and mining
terrain add-on that lets you make a 2d minecraft style terrain
animation support ( either .nfa or one I will make or both )
What do I need to know?
to load all addons use game.loadAddons( ) or game.loadAddon( path ) to load individually.
to create an entity use game.add( x, y, w, h, image, name ( used for map collision ) )
to make an addon create a file and make a table called game.addon ( these will be inserted into the game table.
to check collision do rec, pix = [entity]:isColliding( [entity], [per pixel collision?] )
to move and entity use [entity]:move( x, y ) or [entity]:teleport( x, y )
How can I get it?
pastebin: PiA7Sw5T <– latest version
map addon:
RPG addon: coming soon
Latest update: camera locking & bug fixes
Yasuda is a game engine I have been working on for about a week now. It is designed to be easy to use, and open but have add-ons that specialize it to make it better for certain tasks. The main engine has collision detection but the map addon uses auto collision and will eventually have things like following and attacking in built ( so you can set entities to attack/follow other entities automatically )
Well, how good is it really? Here's an example:
Spoiler
game.loadAddon( "map.gma" ) -- loads the map addon
m = game.add( 1, 1, 6, 9, "player", "player" ) -- creates the player entity
map = game.add( 1, 1, 51, 18, "a", "map" ) --creates the map entity
t = game.loadMap( true, true ) -- creates a map with pixel perfect collision and checks before it moves the player
m:insertToMap( t ) -- inserts the player into the map
map:insertToMap( t ) -- inserts the map entity into the map
while true do
term.setBackgroundColour( colours.lime )
term.clear( ) -- clears the screen with a lime background
map:draw( ) -- draws the map
m:draw( ) -- draws the player
ev = { os.pullEvent( ) } -- gets the event
if ev[1] == "key" then
if ev[2] == keys.left then
m:move( -1, 0, t ) -- moves the player to the left ( checks collision while doing so automatically with the map addon )
elseif ev[2] == keys.right then
m:move( 1, 0, t ) -- moves to the right
elseif ev[2] == keys.up then
m:move( 0, -1, t ) -- moves up
elseif ev[2] == keys.down then
m:move( 0, 1, t ) -- moves down
elseif ev[2] == keys.backspace then
break -- exits the program
elseif ev[2] == keys.tab then
if m:isLockedEntity( ) then -- checks if the camera is locked to the player
map:lock( ) -- locks the camera to the map
else
m:lock( ) -- locks the camera to the player
end
end
end
end
This would create a lime screen with a map drawn on that will not let the player move through bits of the map that aren't invisible. You can press tab to switch view to the player or a side view of the whole mapWhat is so good about it?
-Easy to make add-ons for/overwrite current ones to suit your needs
-Per pixel and rectangle collision detection
-Entity storage and management
-Addons:
–Map - auto collision
–RPG - extra variables & functions related to role playing games such as money and health & collision attacking
Still to come:
entity actions such as following, attacking, eating and mining
terrain add-on that lets you make a 2d minecraft style terrain
animation support ( either .nfa or one I will make or both )
What do I need to know?
to load all addons use game.loadAddons( ) or game.loadAddon( path ) to load individually.
to create an entity use game.add( x, y, w, h, image, name ( used for map collision ) )
to make an addon create a file and make a table called game.addon ( these will be inserted into the game table.
to check collision do rec, pix = [entity]:isColliding( [entity], [per pixel collision?] )
to move and entity use [entity]:move( x, y ) or [entity]:teleport( x, y )
How can I get it?
pastebin: PiA7Sw5T <– latest version
Spoiler
game = {
add = function( x, y, w, h, image, name, actions, desc )
local actions = actions or { }
local desc = desc or { }
local t = { oldX = x, oldY = y, dimension = "default", x = x, y = y, w = w, h = h, image = ( type( image ) == "string" and game.loadImage( image ) or image ), actions = actions, desc = desc, name = name }
return setmetatable( t, { __index = game } )
end;
loadImage = function( path )
--loads the image in a specific format
local t = { }
local tImage = paintutils.loadImage( path )
for y=1,#tImage do
local tLine = tImage[y]
for x=1,#tLine do
if tLine[x] > 0 then
table.insert( t, { x = x, y = y, bc = tLine[x], text = " ", tc = 1 } )
end
end
end
local maxX = 0
local maxY = 0
for i = 1,#t do
if t[i].x > maxX then
maxX = t[i].x
end
if t[i].y > maxY then
maxY = t[i].y
end
end
local r = { }
for i = 1,maxY do
r[i] = { }
for k = 1,maxX do
r[i][k] = { text = false, bc = 2, tc = 2 }
end
end
for i = 1,#t do
r[t[i].y][t[i].x] = { text = t[i].text, bc = t[i].bc, tc = t[i].tc }
end
return r
end;
setDimension = function( self, dim )
--changes the entities dimension ( for collision )
self.dimension = dim
return self.dimension
end;
camera = { entity = { x = 1, y = 1, w = 51, h = 19 } };
lock = function( self )
game.camera.entity = self
end;
draw = function( self )
--draws the entity at the entities x and y
for y = 1,#self.image do
for x = 1,#self.image[y] do
im = self.image[y][x]
if im.text ~= false then
local xdiff = ( self.x - game.camera.entity.x ) + ( 26 - ( game.camera.entity.w / 2 ) )
local ydiff = ( self.y - game.camera.entity.y ) + ( 10 - ( game.camera.entity.h / 2 ) )
term.native.setCursorPos( x + xdiff, y + ydiff )
term.native.setBackgroundColour( im.bc )
term.native.setTextColour( im.tc )
term.native.write( im.text )
end
end
end
end;
isLockedEntity = function( self )
if game.camera.entity == self then
return true
end
return false
end;
loadAddons = function( path )
path = path or ""
local f = fs.list( path )
for i = 1,#f do
if fs.isDir( f[i] ) then
game.loadAddons( f[i] )
elseif string.sub( f[i], string.len( f[i] )-3, string.len( f[i] ) ) == ".gma" then
game.loadAddon( f[i] )
end
end
end;
move = function( self, x, y )
--changes the entities x and y to x+x and y+y
self.oldX, self.oldY = self.x, self.y
self.x = self.x + math.floor( x )
self.y = self.y + math.floor( y )
end;
teleport = function( self, x, y )
--sets the entities x and y to x and y
self.oldX, self.oldY = self.x, self.y
self.x, self.y = x, y
end;
pixel = function( self, x, y, text, bc, tc )
if not self.image[y][x] then return end
bc = bc or self.image[y][x].bc-- or colours.black
tc = tc or self.image[y][x].tc-- or colours.white
text = text or self.image[y][x].item-- or " "
self.image[y][x] = { text = text, bc = bc, tc = tc }
self:draw( )
end;
remove = function( self, x, y )
if not self.image[y][x] then return end
self.image[y][x] =
{ text = false, bc = colours.white, tc = colours.white }
end;
getOppositeEdge = function( self, y )
if y then
return self.y+( self.h-1 )
end
return self.x+( self.w-1 )
end;
loadAddon = function( path )
--will load addons
local loaded = true
parallel.waitForAny( function( ) shell.run( path, "game_API_is_adding_you" ) end, function( ) sleep( 1 ) loaded = false end )
if loaded and game.addon then
for k, v in pairs( game.addon ) do
game[k] = v
end
end
game.addon = nil
return loaded
end;
back = function( self )
self:teleport( self.oldX, self.oldY )
end;
collide = function( r1, r2 )
end;
isColliding = function( r1, r2, detail )
if r2 == "screen" then
if r1.x < 1 or
r1.y < 1 or
r1:getOppositeEdge( ) > 51 or
r1:getOppositeEdge( true ) > 19 then
return true
end
return false
end
if r1.dimension ~= r2.dimension then
return false, false
end
local left = false
local top = false
local l, r, t, b = nil, nil, nil, nil
if r1.x < r2.x then
l, r = r2.x, r1:getOppositeEdge( )
left = true
elseif r1.x >= r2.x then
l, r = r1.x, r2:getOppositeEdge( )
end
if r1.y < r2.y then
t, b = r2.y, r1:getOppositeEdge( true )
top = true
elseif r1.y >= r2.y then
t, b = r1.y, r2:getOppositeEdge( true )
end
if l > r or t > b then
return false, false
end
if not detail then game.collide( r1, r2 ) return true, false end
for x = l, r do
for y = t, b do
local r1x, r2x, r1y, r2y = nil, nil, nil, nil
r1x, r2x = x-r1.x+1, x-r2.x+1
r1y, r2y = y-r1.y+1, y-r2.y+1
if r1.image[r1y] and r1.image[r1y][r1x] and r1.image[r1y][r1x].text ~= false and
r2.image[r2y] and r2.image[r2y][r2x] and r2.image[r2y][r2x].text ~= false then
game.collide( r1, r2 )
return true, true
end
end
end
game.collide( r1, r2 )
return true, false
end;
}
map addon:
Spoiler
local args = { ... }
if args[1] ~= "game_API_is_adding_you" then
return
end
game.addon = {
loadMap = function( col, mov )
game.map = { }
game.map.col = col
game.map.mov = mov
local t = { }
return t
end;
setCollision = function( col )
game.map.col = col
end;
setMoveCollision = function( tf )
game.map.mov = tf
end;
insertToMap = function( self, t )
table.insert( t, self )
end;
move = function( self, x, y, map )
--changes the entities x and y to x+x and y+y
self.oldX, self.oldY = self.x, self.y
self.x = self.x+x
if game.map.mov then
for i = 1,#map do
if map[i].name ~= self.name and map[i].name then
rec, pix = self:isColliding( map[i], true )
if game.map.col and pix then
self.x = self.x-x
break
elseif rec and not game.map.col then
self.x = self.x-x
break
end
end
end
end
self.y = self.y+y
if game.map.mov then
for i = 1,#map do
if map[i].name ~= self.name then
rec, pix = self:isColliding( map[i], true )
if game.map.col and pix then
self.y = self.y-y
break
elseif rec and not game.map.col then
self.y = self.y-y
break
end
end
end
end
end;
}
RPG addon: coming soon